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 {...@@ -1060,6 +1060,7 @@ pub const LibExeObjStep = struct {
1060 /// Add command line arguments with `addArg`.1060 /// Add command line arguments with `addArg`.
1061 pub fn run(exe: *LibExeObjStep) *RunStep {1061 pub fn run(exe: *LibExeObjStep) *RunStep {
1062 assert(exe.kind == Kind.Exe);1062 assert(exe.kind == Kind.Exe);
1063 assert(exe.target == Target.Native);
1063 const run_step = RunStep.create(exe.builder, exe.builder.fmt("run {}", exe.step.name));1064 const run_step = RunStep.create(exe.builder, exe.builder.fmt("run {}", exe.step.name));
1064 run_step.addArtifactArg(exe);1065 run_step.addArtifactArg(exe);
1065 return run_step;1066 return run_step;
...@@ -1276,7 +1277,7 @@ pub const LibExeObjStep = struct {...@@ -1276,7 +1277,7 @@ pub const LibExeObjStep = struct {
1276 LibExeObjStep.Kind.Lib => {1277 LibExeObjStep.Kind.Lib => {
1277 if (other.static or self.target.isWindows()) {1278 if (other.static or self.target.isWindows()) {
1278 try zig_args.append("--object");1279 try zig_args.append("--object");
1279 try zig_args.append(other.getOutputPath());1280 try zig_args.append(other.getOutputLibPath());
1280 } else {1281 } else {
1281 const full_path_lib = other.getOutputPath();1282 const full_path_lib = other.getOutputPath();
1282 try zig_args.append("--library");1283 try zig_args.append("--library");
...@@ -1495,7 +1496,7 @@ pub const RunStep = struct {...@@ -1495,7 +1496,7 @@ pub const RunStep = struct {
1495 cwd: ?[]const u8,1496 cwd: ?[]const u8,
14961497
1497 /// Override this field to modify the environment, or use setEnvironmentVariable1498 /// Override this field to modify the environment, or use setEnvironmentVariable
1498 env_map: ?*const BufMap,1499 env_map: ?*BufMap,
14991500
1500 pub const Arg = union(enum) {1501 pub const Arg = union(enum) {
1501 Artifact: *LibExeObjStep,1502 Artifact: *LibExeObjStep,
...@@ -1529,12 +1530,28 @@ pub const RunStep = struct {...@@ -1529,12 +1530,28 @@ pub const RunStep = struct {
1529 }1530 }
1530 }1531 }
15311532
1532 pub fn setEnvironmentVariable(self: *RunStep, key: []const u8, value: []const u8) void {1533 pub fn addPathDir(self: *RunStep, search_path: []const u8) void {
1533 const env_map = self.env_map orelse blk: {1534 const PATH = if (builtin.os == builtin.Os.windows) "Path" else "PATH";
1534 const env_map = os.getEnvMap(allocator) catch unreachable;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;
1535 self.env_map = env_map;1548 self.env_map = env_map;
1536 break :blk env_map;1549 return env_map;
1537 };1550 };
1551 }
1552
1553 pub fn setEnvironmentVariable(self: *RunStep, key: []const u8, value: []const u8) void {
1554 const env_map = self.getEnvMap();
1538 env_map.set(key, value) catch unreachable;1555 env_map.set(key, value) catch unreachable;
1539 }1556 }
15401557
...@@ -1547,12 +1564,32 @@ pub const RunStep = struct {...@@ -1547,12 +1564,32 @@ pub const RunStep = struct {
1547 for (self.argv.toSlice()) |arg| {1564 for (self.argv.toSlice()) |arg| {
1548 switch (arg) {1565 switch (arg) {
1549 Arg.Bytes => |bytes| try argv.append(bytes),1566 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 },
1551 }1574 }
1552 }1575 }
15531576
1554 return self.builder.spawnChildEnvMap(cwd, self.env_map orelse self.builder.env_map, argv.toSliceConst());1577 return self.builder.spawnChildEnvMap(cwd, self.env_map orelse self.builder.env_map, argv.toSliceConst());
1555 }1578 }
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 }
1556};1593};
15571594
1558const InstallArtifactStep = struct {1595const InstallArtifactStep = struct {
std/os/windows/util.zig+7-1
...@@ -167,7 +167,7 @@ pub fn windowsOpen(...@@ -167,7 +167,7 @@ pub fn windowsOpen(
167pub fn createWindowsEnvBlock(allocator: *mem.Allocator, env_map: *const BufMap) ![]u16 {167pub fn createWindowsEnvBlock(allocator: *mem.Allocator, env_map: *const BufMap) ![]u16 {
168 // count bytes needed168 // count bytes needed
169 const max_chars_needed = x: {169 const max_chars_needed = x: {
170 var max_chars_needed: usize = 1; // 1 for the final null byte170 var max_chars_needed: usize = 4; // 4 for the final 4 null bytes
171 var it = env_map.iterator();171 var it = env_map.iterator();
172 while (it.next()) |pair| {172 while (it.next()) |pair| {
173 // +1 for '='173 // +1 for '='
...@@ -191,6 +191,12 @@ pub fn createWindowsEnvBlock(allocator: *mem.Allocator, env_map: *const BufMap)...@@ -191,6 +191,12 @@ pub fn createWindowsEnvBlock(allocator: *mem.Allocator, env_map: *const BufMap)
191 }191 }
192 result[i] = 0;192 result[i] = 0;
193 i += 1;193 i += 1;
194 result[i] = 0;
195 i += 1;
196 result[i] = 0;
197 i += 1;
198 result[i] = 0;
199 i += 1;
194 return allocator.shrink(u16, result, i);200 return allocator.shrink(u16, result, i);
195}201}
196202