authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-03-09 00:42:14-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-03-09 00:42:14-05:00
log5046aa9403e98fec7a744f35faa9d17925c9079d
treeb508f9157b9da09069255563fe8ed6337953568c
parent85d23e68eecc8b2af89a3836296ac0689ec7a5b9

fix running things with zig build on Windows

Windows doesn't have rpaths for DLLs so we instead add search paths to Path environment variable when running an executable that depends on DLLs built with zig build.

2 files changed, 51 insertions(+), 8 deletions(-)

std/build.zig+44-7
......@@ -1060,6 +1060,7 @@ pub const LibExeObjStep = struct {
10601060 /// Add command line arguments with `addArg`.
10611061 pub fn run(exe: *LibExeObjStep) *RunStep {
10621062 assert(exe.kind == Kind.Exe);
1063 assert(exe.target == Target.Native);
10631064 const run_step = RunStep.create(exe.builder, exe.builder.fmt("run {}", exe.step.name));
10641065 run_step.addArtifactArg(exe);
10651066 return run_step;
......@@ -1276,7 +1277,7 @@ pub const LibExeObjStep = struct {
12761277 LibExeObjStep.Kind.Lib => {
12771278 if (other.static or self.target.isWindows()) {
12781279 try zig_args.append("--object");
1279 try zig_args.append(other.getOutputPath());
1280 try zig_args.append(other.getOutputLibPath());
12801281 } else {
12811282 const full_path_lib = other.getOutputPath();
12821283 try zig_args.append("--library");
......@@ -1495,7 +1496,7 @@ pub const RunStep = struct {
14951496 cwd: ?[]const u8,
14961497
14971498 /// Override this field to modify the environment, or use setEnvironmentVariable
1498 env_map: ?*const BufMap,
1499 env_map: ?*BufMap,
14991500
15001501 pub const Arg = union(enum) {
15011502 Artifact: *LibExeObjStep,
......@@ -1529,12 +1530,28 @@ pub const RunStep = struct {
15291530 }
15301531 }
15311532
1532 pub fn setEnvironmentVariable(self: *RunStep, key: []const u8, value: []const u8) void {
1533 const env_map = self.env_map orelse blk: {
1534 const env_map = os.getEnvMap(allocator) catch unreachable;
1533 pub fn addPathDir(self: *RunStep, search_path: []const u8) void {
1534 const PATH = if (builtin.os == builtin.Os.windows) "Path" else "PATH";
1535 const env_map = self.getEnvMap();
1536 const prev_path = env_map.get(PATH) orelse {
1537 env_map.set(PATH, search_path) catch unreachable;
1538 return;
1539 };
1540 const new_path = self.builder.fmt("{}" ++ [1]u8{os.path.delimiter} ++ "{}", prev_path, search_path);
1541 env_map.set(PATH, new_path) catch unreachable;
1542 }
1543
1544 pub fn getEnvMap(self: *RunStep) *BufMap {
1545 return self.env_map orelse {
1546 const env_map = self.builder.allocator.create(BufMap) catch unreachable;
1547 env_map.* = os.getEnvMap(self.builder.allocator) catch unreachable;
15351548 self.env_map = env_map;
1536 break :blk env_map;
1549 return env_map;
15371550 };
1551 }
1552
1553 pub fn setEnvironmentVariable(self: *RunStep, key: []const u8, value: []const u8) void {
1554 const env_map = self.getEnvMap();
15381555 env_map.set(key, value) catch unreachable;
15391556 }
15401557
......@@ -1547,12 +1564,32 @@ pub const RunStep = struct {
15471564 for (self.argv.toSlice()) |arg| {
15481565 switch (arg) {
15491566 Arg.Bytes => |bytes| try argv.append(bytes),
1550 Arg.Artifact => |artifact| try argv.append(artifact.getOutputPath()),
1567 Arg.Artifact => |artifact| {
1568 if (artifact.target.isWindows()) {
1569 // On Windows we don't have rpaths so we have to add .dll search paths to PATH
1570 self.addPathForDynLibs(artifact);
1571 }
1572 try argv.append(artifact.getOutputPath());
1573 },
15511574 }
15521575 }
15531576
15541577 return self.builder.spawnChildEnvMap(cwd, self.env_map orelse self.builder.env_map, argv.toSliceConst());
15551578 }
1579
1580 fn addPathForDynLibs(self: *RunStep, artifact: *LibExeObjStep) void {
1581 for (artifact.link_objects.toSliceConst()) |link_object| {
1582 switch (link_object) {
1583 LibExeObjStep.LinkObject.OtherStep => |other| {
1584 if (other.target.isWindows() and other.isDynamicLibrary()) {
1585 self.addPathDir(os.path.dirname(other.getOutputPath()).?);
1586 self.addPathForDynLibs(other);
1587 }
1588 },
1589 else => {},
1590 }
1591 }
1592 }
15561593};
15571594
15581595const InstallArtifactStep = struct {
std/os/windows/util.zig+7-1
......@@ -167,7 +167,7 @@ pub fn windowsOpen(
167167pub fn createWindowsEnvBlock(allocator: *mem.Allocator, env_map: *const BufMap) ![]u16 {
168168 // count bytes needed
169169 const max_chars_needed = x: {
170 var max_chars_needed: usize = 1; // 1 for the final null byte
170 var max_chars_needed: usize = 4; // 4 for the final 4 null bytes
171171 var it = env_map.iterator();
172172 while (it.next()) |pair| {
173173 // +1 for '='
......@@ -191,6 +191,12 @@ pub fn createWindowsEnvBlock(allocator: *mem.Allocator, env_map: *const BufMap)
191191 }
192192 result[i] = 0;
193193 i += 1;
194 result[i] = 0;
195 i += 1;
196 result[i] = 0;
197 i += 1;
198 result[i] = 0;
199 i += 1;
194200 return allocator.shrink(u16, result, i);
195201}
196202