Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: ziglang/zig
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: caa6433b5636
Choose a base ref
...
head repository: ziglang/zig
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 2b9302107fdd
Choose a head ref
  • 2 commits
  • 4 files changed
  • 1 contributor

Commits on Dec 12, 2017

  1. Copy the full SHA
    cd5fd65 View commit details
  2. Copy the full SHA
    2b93021 View commit details
Showing with 119 additions and 115 deletions.
  1. +14 −112 build.zig
  2. +5 −0 std/buf_map.zig
  3. +57 −0 std/build.zig
  4. +43 −3 std/os/child_process.zig
126 changes: 14 additions & 112 deletions build.zig
Original file line number Diff line number Diff line change
@@ -92,81 +92,21 @@ const LibraryDep = struct {
};

fn findLLVM(b: &Builder) -> LibraryDep {
const libs_output = {
const args1 = [][]const u8{"llvm-config-5.0", "--libs", "--system-libs"};
const args2 = [][]const u8{"llvm-config", "--libs", "--system-libs"};
const max_output_size = 10 * 1024;
const good_result = exec(b.allocator, args1, null, null, max_output_size) %% |err| {
if (err == error.FileNotFound) {
exec(b.allocator, args2, null, null, max_output_size) %% |err2| {
std.debug.panic("unable to spawn {}: {}\n", args2[0], err2);
}
} else {
std.debug.panic("unable to spawn {}: {}\n", args1[0], err);
}
};
switch (good_result.term) {
os.ChildProcess.Term.Exited => |code| {
if (code != 0) {
std.debug.panic("llvm-config exited with {}:\n{}\n", code, good_result.stderr);
}
},
else => {
std.debug.panic("llvm-config failed:\n{}\n", good_result.stderr);
},
}
good_result.stdout
};
const includes_output = {
const args1 = [][]const u8{"llvm-config-5.0", "--includedir"};
const args2 = [][]const u8{"llvm-config", "--includedir"};
const max_output_size = 10 * 1024;
const good_result = exec(b.allocator, args1, null, null, max_output_size) %% |err| {
if (err == error.FileNotFound) {
exec(b.allocator, args2, null, null, max_output_size) %% |err2| {
std.debug.panic("unable to spawn {}: {}\n", args2[0], err2);
}
} else {
std.debug.panic("unable to spawn {}: {}\n", args1[0], err);
}
};
switch (good_result.term) {
os.ChildProcess.Term.Exited => |code| {
if (code != 0) {
std.debug.panic("llvm-config --includedir exited with {}:\n{}\n", code, good_result.stderr);
}
},
else => {
std.debug.panic("llvm-config failed:\n{}\n", good_result.stderr);
},
}
good_result.stdout
};
const libdir_output = {
const args1 = [][]const u8{"llvm-config-5.0", "--libdir"};
const args2 = [][]const u8{"llvm-config", "--libdir"};
const max_output_size = 10 * 1024;
const good_result = exec(b.allocator, args1, null, null, max_output_size) %% |err| {
if (err == error.FileNotFound) {
exec(b.allocator, args2, null, null, max_output_size) %% |err2| {
std.debug.panic("unable to spawn {}: {}\n", args2[0], err2);
}
} else {
std.debug.panic("unable to spawn {}: {}\n", args1[0], err);
}
};
switch (good_result.term) {
os.ChildProcess.Term.Exited => |code| {
if (code != 0) {
std.debug.panic("llvm-config --libdir exited with {}:\n{}\n", code, good_result.stderr);
}
},
else => {
std.debug.panic("llvm-config failed:\n{}\n", good_result.stderr);
},
}
good_result.stdout
const llvm_config_exe = b.findProgram(
[][]const u8{"llvm-config-5.0", "llvm-config"},
[][]const u8{
"/usr/local/opt/llvm@5/",
"/mingw64/bin",
"/c/msys64/mingw64/bin",
"c:/msys64/mingw64/bin",
"C:/Libraries/llvm-5.0.0/bin",
}) %% |err|
{
std.debug.panic("unable to find llvm-config: {}\n", err);
};
const libs_output = b.exec([][]const u8{llvm_config_exe, "--libs", "--system-libs"});
const includes_output = b.exec([][]const u8{llvm_config_exe, "--includedir"});
const libdir_output = b.exec([][]const u8{llvm_config_exe, "--libdir"});

var result = LibraryDep {
.libs = ArrayList([]const u8).init(b.allocator),
@@ -203,41 +143,3 @@ fn findLLVM(b: &Builder) -> LibraryDep {
}
return result;
}


// TODO move to std lib
const ExecResult = struct {
term: os.ChildProcess.Term,
stdout: []u8,
stderr: []u8,
};

fn exec(allocator: &std.mem.Allocator, argv: []const []const u8, cwd: ?[]const u8, env_map: ?&const BufMap, max_output_size: usize) -> %ExecResult {
const child = %%os.ChildProcess.init(argv, allocator);
defer child.deinit();

child.stdin_behavior = os.ChildProcess.StdIo.Ignore;
child.stdout_behavior = os.ChildProcess.StdIo.Pipe;
child.stderr_behavior = os.ChildProcess.StdIo.Pipe;
child.cwd = cwd;
child.env_map = env_map;

%return child.spawn();

var stdout = Buffer.initNull(allocator);
var stderr = Buffer.initNull(allocator);
defer Buffer.deinit(&stdout);
defer Buffer.deinit(&stderr);

var stdout_file_in_stream = io.FileInStream.init(&??child.stdout);
var stderr_file_in_stream = io.FileInStream.init(&??child.stderr);

%return stdout_file_in_stream.stream.readAllBuffer(&stdout, max_output_size);
%return stderr_file_in_stream.stream.readAllBuffer(&stderr, max_output_size);

return ExecResult {
.term = %return child.wait(),
.stdout = stdout.toOwnedSlice(),
.stderr = stderr.toOwnedSlice(),
};
}
5 changes: 5 additions & 0 deletions std/buf_map.zig
Original file line number Diff line number Diff line change
@@ -42,6 +42,11 @@ pub const BufMap = struct {
}
}

pub fn get(self: &BufMap, key: []const u8) -> ?[]const u8 {
const entry = self.hash_map.get(key) ?? return null;
return entry.value;
}

pub fn delete(self: &BufMap, key: []const u8) {
const entry = self.hash_map.remove(key) ?? return;
self.free(entry.key);
57 changes: 57 additions & 0 deletions std/build.zig
Original file line number Diff line number Diff line change
@@ -671,6 +671,63 @@ pub const Builder = struct {
};
}
}

pub fn findProgram(self: &Builder, names: []const []const u8, paths: []const []const u8) -> %[]const u8 {
if (self.env_map.get("PATH")) |PATH| {
for (names) |name| {
if (os.path.isAbsolute(name)) {
return name;
}
var it = mem.split(PATH, []u8{os.path.delimiter});
while (it.next()) |path| {
const full_path = %return os.path.join(self.allocator, path, name);
if (os.path.real(self.allocator, full_path)) |real_path| {
return real_path;
} else |_| {
continue;
}
}
}
}
for (names) |name| {
if (os.path.isAbsolute(name)) {
return name;
}
for (paths) |path| {
const full_path = %return os.path.join(self.allocator, path, name);
if (os.path.real(self.allocator, full_path)) |real_path| {
return real_path;
} else |_| {
continue;
}
}
}
return error.FileNotFound;
}

pub fn exec(self: &Builder, argv: []const []const u8) -> []u8 {
const max_output_size = 100 * 1024;
const result = os.ChildProcess.exec(self.allocator, argv, null, null, max_output_size) %% |err| {
std.debug.panic("Unable to spawn {}: {}", argv[0], @errorName(err));
};
switch (result.term) {
os.ChildProcess.Term.Exited => |code| {
if (code != 0) {
warn("The following command exited with error code {}:\n", code);
printCmd(null, argv);
warn("stderr:{}\n", result.stderr);
std.debug.panic("command failed");
}
return result.stdout;
},
else => {
warn("The following command terminated unexpectedly:\n");
printCmd(null, argv);
warn("stderr:{}\n", result.stderr);
std.debug.panic("command failed");
},
}
}
};

const Version = struct {
46 changes: 43 additions & 3 deletions std/os/child_process.zig
Original file line number Diff line number Diff line change
@@ -5,7 +5,6 @@ const os = std.os;
const posix = os.posix;
const windows = os.windows;
const mem = std.mem;
const Allocator = mem.Allocator;
const debug = std.debug;
const assert = debug.assert;
const BufMap = std.BufMap;
@@ -74,7 +73,7 @@ pub const ChildProcess = struct {

/// First argument in argv is the executable.
/// On success must call deinit.
pub fn init(argv: []const []const u8, allocator: &Allocator) -> %&ChildProcess {
pub fn init(argv: []const []const u8, allocator: &mem.Allocator) -> %&ChildProcess {
const child = %return allocator.create(ChildProcess);
%defer allocator.destroy(child);

@@ -180,6 +179,46 @@ pub const ChildProcess = struct {
}
}

pub const ExecResult = struct {
term: os.ChildProcess.Term,
stdout: []u8,
stderr: []u8,
};

/// Spawns a child process, waits for it, collecting stdout and stderr, and then returns.
/// If it succeeds, the caller owns result.stdout and result.stderr memory.
pub fn exec(allocator: &mem.Allocator, argv: []const []const u8, cwd: ?[]const u8,
env_map: ?&const BufMap, max_output_size: usize) -> %ExecResult
{
const child = %%ChildProcess.init(argv, allocator);
defer child.deinit();

child.stdin_behavior = ChildProcess.StdIo.Ignore;
child.stdout_behavior = ChildProcess.StdIo.Pipe;
child.stderr_behavior = ChildProcess.StdIo.Pipe;
child.cwd = cwd;
child.env_map = env_map;

%return child.spawn();

var stdout = Buffer.initNull(allocator);
var stderr = Buffer.initNull(allocator);
defer Buffer.deinit(&stdout);
defer Buffer.deinit(&stderr);

var stdout_file_in_stream = io.FileInStream.init(&??child.stdout);
var stderr_file_in_stream = io.FileInStream.init(&??child.stderr);

%return stdout_file_in_stream.stream.readAllBuffer(&stdout, max_output_size);
%return stderr_file_in_stream.stream.readAllBuffer(&stderr, max_output_size);

return ExecResult {
.term = %return child.wait(),
.stdout = stdout.toOwnedSlice(),
.stderr = stderr.toOwnedSlice(),
};
}

fn waitWindows(self: &ChildProcess) -> %Term {
if (self.term) |term| {
self.cleanupStreams();
@@ -589,6 +628,7 @@ pub const ChildProcess = struct {
StdIo.Ignore => %return os.posixDup2(dev_null_fd, std_fileno),
}
}

};

fn 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: ?

/// Caller must dealloc.
/// Guarantees a null byte at result[result.len].
fn windowsCreateCommandLine(allocator: &Allocator, argv: []const []const u8) -> %[]u8 {
fn windowsCreateCommandLine(allocator: &mem.Allocator, argv: []const []const u8) -> %[]u8 {
var buf = %return Buffer.initSize(allocator, 0);
defer buf.deinit();