authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-12-12 14:35:53-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-12-12 14:35:53-05:00
logcd5fd653d7dd738d4c67b304e9cb17fb211f0163
treedc0ae70eb9cde19118df13359a1fdca7ae68d20c
parentcaa6433b5636af968aa7018a3bea8e658bca05a3

self-hosted: move code to std.os.ChildProcess.exec


2 files changed, 49 insertions(+), 47 deletions(-)

build.zig+6-44
...@@ -96,9 +96,9 @@ fn findLLVM(b: &Builder) -> LibraryDep {...@@ -96,9 +96,9 @@ fn findLLVM(b: &Builder) -> LibraryDep {
96 const args1 = [][]const u8{"llvm-config-5.0", "--libs", "--system-libs"};96 const args1 = [][]const u8{"llvm-config-5.0", "--libs", "--system-libs"};
97 const args2 = [][]const u8{"llvm-config", "--libs", "--system-libs"};97 const args2 = [][]const u8{"llvm-config", "--libs", "--system-libs"};
98 const max_output_size = 10 * 1024;98 const max_output_size = 10 * 1024;
99 const good_result = exec(b.allocator, args1, null, null, max_output_size) %% |err| {99 const good_result = os.ChildProcess.exec(b.allocator, args1, null, null, max_output_size) %% |err| {
100 if (err == error.FileNotFound) {100 if (err == error.FileNotFound) {
101 exec(b.allocator, args2, null, null, max_output_size) %% |err2| {101 os.ChildProcess.exec(b.allocator, args2, null, null, max_output_size) %% |err2| {
102 std.debug.panic("unable to spawn {}: {}\n", args2[0], err2);102 std.debug.panic("unable to spawn {}: {}\n", args2[0], err2);
103 }103 }
104 } else {104 } else {
...@@ -121,9 +121,9 @@ fn findLLVM(b: &Builder) -> LibraryDep {...@@ -121,9 +121,9 @@ fn findLLVM(b: &Builder) -> LibraryDep {
121 const args1 = [][]const u8{"llvm-config-5.0", "--includedir"};121 const args1 = [][]const u8{"llvm-config-5.0", "--includedir"};
122 const args2 = [][]const u8{"llvm-config", "--includedir"};122 const args2 = [][]const u8{"llvm-config", "--includedir"};
123 const max_output_size = 10 * 1024;123 const max_output_size = 10 * 1024;
124 const good_result = exec(b.allocator, args1, null, null, max_output_size) %% |err| {124 const good_result = os.ChildProcess.exec(b.allocator, args1, null, null, max_output_size) %% |err| {
125 if (err == error.FileNotFound) {125 if (err == error.FileNotFound) {
126 exec(b.allocator, args2, null, null, max_output_size) %% |err2| {126 os.ChildProcess.exec(b.allocator, args2, null, null, max_output_size) %% |err2| {
127 std.debug.panic("unable to spawn {}: {}\n", args2[0], err2);127 std.debug.panic("unable to spawn {}: {}\n", args2[0], err2);
128 }128 }
129 } else {129 } else {
...@@ -146,9 +146,9 @@ fn findLLVM(b: &Builder) -> LibraryDep {...@@ -146,9 +146,9 @@ fn findLLVM(b: &Builder) -> LibraryDep {
146 const args1 = [][]const u8{"llvm-config-5.0", "--libdir"};146 const args1 = [][]const u8{"llvm-config-5.0", "--libdir"};
147 const args2 = [][]const u8{"llvm-config", "--libdir"};147 const args2 = [][]const u8{"llvm-config", "--libdir"};
148 const max_output_size = 10 * 1024;148 const max_output_size = 10 * 1024;
149 const good_result = exec(b.allocator, args1, null, null, max_output_size) %% |err| {149 const good_result = os.ChildProcess.exec(b.allocator, args1, null, null, max_output_size) %% |err| {
150 if (err == error.FileNotFound) {150 if (err == error.FileNotFound) {
151 exec(b.allocator, args2, null, null, max_output_size) %% |err2| {151 os.ChildProcess.exec(b.allocator, args2, null, null, max_output_size) %% |err2| {
152 std.debug.panic("unable to spawn {}: {}\n", args2[0], err2);152 std.debug.panic("unable to spawn {}: {}\n", args2[0], err2);
153 }153 }
154 } else {154 } else {
...@@ -203,41 +203,3 @@ fn findLLVM(b: &Builder) -> LibraryDep {...@@ -203,41 +203,3 @@ fn findLLVM(b: &Builder) -> LibraryDep {
203 }203 }
204 return result;204 return result;
205}205}
206
207
208// TODO move to std lib
209const ExecResult = struct {
210 term: os.ChildProcess.Term,
211 stdout: []u8,
212 stderr: []u8,
213};
214
215fn exec(allocator: &std.mem.Allocator, argv: []const []const u8, cwd: ?[]const u8, env_map: ?&const BufMap, max_output_size: usize) -> %ExecResult {
216 const child = %%os.ChildProcess.init(argv, allocator);
217 defer child.deinit();
218
219 child.stdin_behavior = os.ChildProcess.StdIo.Ignore;
220 child.stdout_behavior = os.ChildProcess.StdIo.Pipe;
221 child.stderr_behavior = os.ChildProcess.StdIo.Pipe;
222 child.cwd = cwd;
223 child.env_map = env_map;
224
225 %return child.spawn();
226
227 var stdout = Buffer.initNull(allocator);
228 var stderr = Buffer.initNull(allocator);
229 defer Buffer.deinit(&stdout);
230 defer Buffer.deinit(&stderr);
231
232 var stdout_file_in_stream = io.FileInStream.init(&??child.stdout);
233 var stderr_file_in_stream = io.FileInStream.init(&??child.stderr);
234
235 %return stdout_file_in_stream.stream.readAllBuffer(&stdout, max_output_size);
236 %return stderr_file_in_stream.stream.readAllBuffer(&stderr, max_output_size);
237
238 return ExecResult {
239 .term = %return child.wait(),
240 .stdout = stdout.toOwnedSlice(),
241 .stderr = stderr.toOwnedSlice(),
242 };
243}
std/os/child_process.zig+43-3
...@@ -5,7 +5,6 @@ const os = std.os;...@@ -5,7 +5,6 @@ const os = std.os;
5const posix = os.posix;5const posix = os.posix;
6const windows = os.windows;6const windows = os.windows;
7const mem = std.mem;7const mem = std.mem;
8const Allocator = mem.Allocator;
9const debug = std.debug;8const debug = std.debug;
10const assert = debug.assert;9const assert = debug.assert;
11const BufMap = std.BufMap;10const BufMap = std.BufMap;
...@@ -74,7 +73,7 @@ pub const ChildProcess = struct {...@@ -74,7 +73,7 @@ pub const ChildProcess = struct {
7473
75 /// First argument in argv is the executable.74 /// First argument in argv is the executable.
76 /// On success must call deinit.75 /// On success must call deinit.
77 pub fn init(argv: []const []const u8, allocator: &Allocator) -> %&ChildProcess {76 pub fn init(argv: []const []const u8, allocator: &mem.Allocator) -> %&ChildProcess {
78 const child = %return allocator.create(ChildProcess);77 const child = %return allocator.create(ChildProcess);
79 %defer allocator.destroy(child);78 %defer allocator.destroy(child);
8079
...@@ -180,6 +179,46 @@ pub const ChildProcess = struct {...@@ -180,6 +179,46 @@ pub const ChildProcess = struct {
180 }179 }
181 }180 }
182181
182 pub const ExecResult = struct {
183 term: os.ChildProcess.Term,
184 stdout: []u8,
185 stderr: []u8,
186 };
187
188 /// Spawns a child process, waits for it, collecting stdout and stderr, and then returns.
189 /// If it succeeds, the caller owns result.stdout and result.stderr memory.
190 pub fn exec(allocator: &mem.Allocator, argv: []const []const u8, cwd: ?[]const u8,
191 env_map: ?&const BufMap, max_output_size: usize) -> %ExecResult
192 {
193 const child = %%ChildProcess.init(argv, allocator);
194 defer child.deinit();
195
196 child.stdin_behavior = ChildProcess.StdIo.Ignore;
197 child.stdout_behavior = ChildProcess.StdIo.Pipe;
198 child.stderr_behavior = ChildProcess.StdIo.Pipe;
199 child.cwd = cwd;
200 child.env_map = env_map;
201
202 %return child.spawn();
203
204 var stdout = Buffer.initNull(allocator);
205 var stderr = Buffer.initNull(allocator);
206 defer Buffer.deinit(&stdout);
207 defer Buffer.deinit(&stderr);
208
209 var stdout_file_in_stream = io.FileInStream.init(&??child.stdout);
210 var stderr_file_in_stream = io.FileInStream.init(&??child.stderr);
211
212 %return stdout_file_in_stream.stream.readAllBuffer(&stdout, max_output_size);
213 %return stderr_file_in_stream.stream.readAllBuffer(&stderr, max_output_size);
214
215 return ExecResult {
216 .term = %return child.wait(),
217 .stdout = stdout.toOwnedSlice(),
218 .stderr = stderr.toOwnedSlice(),
219 };
220 }
221
183 fn waitWindows(self: &ChildProcess) -> %Term {222 fn waitWindows(self: &ChildProcess) -> %Term {
184 if (self.term) |term| {223 if (self.term) |term| {
185 self.cleanupStreams();224 self.cleanupStreams();
...@@ -589,6 +628,7 @@ pub const ChildProcess = struct {...@@ -589,6 +628,7 @@ pub const ChildProcess = struct {
589 StdIo.Ignore => %return os.posixDup2(dev_null_fd, std_fileno),628 StdIo.Ignore => %return os.posixDup2(dev_null_fd, std_fileno),
590 }629 }
591 }630 }
631
592};632};
593633
594fn windowsCreateProcess(app_name: &u8, cmd_line: &u8, envp_ptr: ?&u8, cwd_ptr: ?&u8,634fn windowsCreateProcess(app_name: &u8, cmd_line: &u8, envp_ptr: ?&u8, cwd_ptr: ?&u8,
...@@ -611,7 +651,7 @@ fn windowsCreateProcess(app_name: &u8, cmd_line: &u8, envp_ptr: ?&u8, cwd_ptr: ?...@@ -611,7 +651,7 @@ fn windowsCreateProcess(app_name: &u8, cmd_line: &u8, envp_ptr: ?&u8, cwd_ptr: ?
611651
612/// Caller must dealloc.652/// Caller must dealloc.
613/// Guarantees a null byte at result[result.len].653/// Guarantees a null byte at result[result.len].
614fn windowsCreateCommandLine(allocator: &Allocator, argv: []const []const u8) -> %[]u8 {654fn windowsCreateCommandLine(allocator: &mem.Allocator, argv: []const []const u8) -> %[]u8 {
615 var buf = %return Buffer.initSize(allocator, 0);655 var buf = %return Buffer.initSize(allocator, 0);
616 defer buf.deinit();656 defer buf.deinit();
617657