| ... | @@ -18,10 +18,8 @@ const File = std.fs.File; | ... | @@ -18,10 +18,8 @@ const File = std.fs.File; |
| 18 | pub const FmtStep = @import("build/fmt.zig").FmtStep; | 18 | pub const FmtStep = @import("build/fmt.zig").FmtStep; |
| 19 | | 19 | |
| 20 | pub const Builder = struct { | 20 | pub const Builder = struct { |
| 21 | uninstall_tls: TopLevelStep, | | |
| 22 | install_tls: TopLevelStep, | 21 | install_tls: TopLevelStep, |
| 23 | have_uninstall_step: bool, | 22 | uninstall_tls: TopLevelStep, |
| 24 | have_install_step: bool, | | |
| 25 | allocator: *Allocator, | 23 | allocator: *Allocator, |
| 26 | native_system_lib_paths: ArrayList([]const u8), | 24 | native_system_lib_paths: ArrayList([]const u8), |
| 27 | native_system_include_dirs: ArrayList([]const u8), | 25 | native_system_include_dirs: ArrayList([]const u8), |
| ... | @@ -42,14 +40,15 @@ pub const Builder = struct { | ... | @@ -42,14 +40,15 @@ pub const Builder = struct { |
| 42 | default_step: *Step, | 40 | default_step: *Step, |
| 43 | env_map: *BufMap, | 41 | env_map: *BufMap, |
| 44 | top_level_steps: ArrayList(*TopLevelStep), | 42 | top_level_steps: ArrayList(*TopLevelStep), |
| 45 | prefix: []const u8, | 43 | install_prefix: ?[]const u8, |
| 46 | search_prefixes: ArrayList([]const u8), | 44 | search_prefixes: ArrayList([]const u8), |
| 47 | lib_dir: []const u8, | 45 | lib_dir: ?[]const u8, |
| 48 | exe_dir: []const u8, | 46 | exe_dir: ?[]const u8, |
| 49 | installed_files: ArrayList([]const u8), | 47 | installed_files: ArrayList(InstalledFile), |
| 50 | build_root: []const u8, | 48 | build_root: []const u8, |
| 51 | cache_root: []const u8, | 49 | cache_root: []const u8, |
| 52 | release_mode: ?builtin.Mode, | 50 | release_mode: ?builtin.Mode, |
| | 51 | is_release: bool, |
| 53 | override_std_dir: ?[]const u8, | 52 | override_std_dir: ?[]const u8, |
| 54 | override_lib_dir: ?[]const u8, | 53 | override_lib_dir: ?[]const u8, |
| 55 | | 54 | |
| ... | @@ -93,13 +92,20 @@ pub const Builder = struct { | ... | @@ -93,13 +92,20 @@ pub const Builder = struct { |
| 93 | description: []const u8, | 92 | description: []const u8, |
| 94 | }; | 93 | }; |
| 95 | | 94 | |
| 96 | pub fn init(allocator: *Allocator, zig_exe: []const u8, build_root: []const u8, cache_root: []const u8) Builder { | 95 | pub fn create( |
| 97 | const env_map = allocator.create(BufMap) catch unreachable; | 96 | allocator: *Allocator, |
| 98 | env_map.* = process.getEnvMap(allocator) catch unreachable; | 97 | zig_exe: []const u8, |
| 99 | var self = Builder{ | 98 | build_root: []const u8, |
| | 99 | cache_root: []const u8, |
| | 100 | ) !*Builder { |
| | 101 | const env_map = try allocator.create(BufMap); |
| | 102 | env_map.* = try process.getEnvMap(allocator); |
| | 103 | |
| | 104 | const self = try allocator.create(Builder); |
| | 105 | self.* = Builder{ |
| 100 | .zig_exe = zig_exe, | 106 | .zig_exe = zig_exe, |
| 101 | .build_root = build_root, | 107 | .build_root = build_root, |
| 102 | .cache_root = fs.path.relative(allocator, build_root, cache_root) catch unreachable, | 108 | .cache_root = try fs.path.relative(allocator, build_root, cache_root), |
| 103 | .verbose = false, | 109 | .verbose = false, |
| 104 | .verbose_tokenize = false, | 110 | .verbose_tokenize = false, |
| 105 | .verbose_ast = false, | 111 | .verbose_ast = false, |
| ... | @@ -119,42 +125,53 @@ pub const Builder = struct { | ... | @@ -119,42 +125,53 @@ pub const Builder = struct { |
| 119 | .top_level_steps = ArrayList(*TopLevelStep).init(allocator), | 125 | .top_level_steps = ArrayList(*TopLevelStep).init(allocator), |
| 120 | .default_step = undefined, | 126 | .default_step = undefined, |
| 121 | .env_map = env_map, | 127 | .env_map = env_map, |
| 122 | .prefix = undefined, | 128 | .install_prefix = null, |
| 123 | .search_prefixes = ArrayList([]const u8).init(allocator), | 129 | .search_prefixes = ArrayList([]const u8).init(allocator), |
| 124 | .lib_dir = undefined, | 130 | .lib_dir = null, |
| 125 | .exe_dir = undefined, | 131 | .exe_dir = null, |
| 126 | .installed_files = ArrayList([]const u8).init(allocator), | 132 | .installed_files = ArrayList(InstalledFile).init(allocator), |
| 127 | .uninstall_tls = TopLevelStep{ | | |
| 128 | .step = Step.init("uninstall", allocator, makeUninstall), | | |
| 129 | .description = "Remove build artifacts from prefix path", | | |
| 130 | }, | | |
| 131 | .have_uninstall_step = false, | | |
| 132 | .install_tls = TopLevelStep{ | 133 | .install_tls = TopLevelStep{ |
| 133 | .step = Step.initNoOp("install", allocator), | 134 | .step = Step.initNoOp("install", allocator), |
| 134 | .description = "Copy build artifacts to prefix path", | 135 | .description = "Copy build artifacts to prefix path", |
| 135 | }, | 136 | }, |
| 136 | .have_install_step = false, | 137 | .uninstall_tls = TopLevelStep{ |
| | 138 | .step = Step.init("uninstall", allocator, makeUninstall), |
| | 139 | .description = "Remove build artifacts from prefix path", |
| | 140 | }, |
| 137 | .release_mode = null, | 141 | .release_mode = null, |
| | 142 | .is_release = false, |
| 138 | .override_std_dir = null, | 143 | .override_std_dir = null, |
| 139 | .override_lib_dir = null, | 144 | .override_lib_dir = null, |
| 140 | }; | 145 | }; |
| | 146 | try self.top_level_steps.append(&self.install_tls); |
| | 147 | try self.top_level_steps.append(&self.uninstall_tls); |
| 141 | self.detectNativeSystemPaths(); | 148 | self.detectNativeSystemPaths(); |
| 142 | self.default_step = self.step("default", "Build the project"); | 149 | self.default_step = &self.install_tls.step; |
| 143 | return self; | 150 | return self; |
| 144 | } | 151 | } |
| 145 | | 152 | |
| 146 | pub fn deinit(self: *Builder) void { | 153 | pub fn destroy(self: *Builder) void { |
| 147 | self.native_system_lib_paths.deinit(); | 154 | self.native_system_lib_paths.deinit(); |
| 148 | self.native_system_include_dirs.deinit(); | 155 | self.native_system_include_dirs.deinit(); |
| 149 | self.native_system_rpaths.deinit(); | 156 | self.native_system_rpaths.deinit(); |
| 150 | self.env_map.deinit(); | 157 | self.env_map.deinit(); |
| 151 | self.top_level_steps.deinit(); | 158 | self.top_level_steps.deinit(); |
| | 159 | self.allocator.destroy(self); |
| 152 | } | 160 | } |
| 153 | | 161 | |
| 154 | pub fn setInstallPrefix(self: *Builder, maybe_prefix: ?[]const u8) void { | 162 | pub fn setInstallPrefix(self: *Builder, optional_prefix: ?[]const u8) void { |
| 155 | self.prefix = maybe_prefix orelse "/usr/local"; // TODO better default | 163 | self.install_prefix = optional_prefix; |
| 156 | self.lib_dir = fs.path.join(self.allocator, [_][]const u8{ self.prefix, "lib" }) catch unreachable; | 164 | } |
| 157 | self.exe_dir = fs.path.join(self.allocator, [_][]const u8{ self.prefix, "bin" }) catch unreachable; | 165 | |
| | 166 | fn resolveInstallPrefix(self: *Builder) void { |
| | 167 | const prefix = if (self.install_prefix) |prefix| prefix else blk: { |
| | 168 | const prefix = self.cache_root; |
| | 169 | self.install_prefix = prefix; |
| | 170 | break :blk prefix; |
| | 171 | }; |
| | 172 | |
| | 173 | self.lib_dir = fs.path.join(self.allocator, [_][]const u8{ prefix, "lib" }) catch unreachable; |
| | 174 | self.exe_dir = fs.path.join(self.allocator, [_][]const u8{ prefix, "bin" }) catch unreachable; |
| 158 | } | 175 | } |
| 159 | | 176 | |
| 160 | pub fn addExecutable(self: *Builder, name: []const u8, root_src: ?[]const u8) *LibExeObjStep { | 177 | pub fn addExecutable(self: *Builder, name: []const u8, root_src: ?[]const u8) *LibExeObjStep { |
| ... | @@ -263,18 +280,10 @@ pub const Builder = struct { | ... | @@ -263,18 +280,10 @@ pub const Builder = struct { |
| 263 | } | 280 | } |
| 264 | | 281 | |
| 265 | pub fn getInstallStep(self: *Builder) *Step { | 282 | pub fn getInstallStep(self: *Builder) *Step { |
| 266 | if (self.have_install_step) return &self.install_tls.step; | | |
| 267 | | | |
| 268 | self.top_level_steps.append(&self.install_tls) catch unreachable; | | |
| 269 | self.have_install_step = true; | | |
| 270 | return &self.install_tls.step; | 283 | return &self.install_tls.step; |
| 271 | } | 284 | } |
| 272 | | 285 | |
| 273 | pub fn getUninstallStep(self: *Builder) *Step { | 286 | pub fn getUninstallStep(self: *Builder) *Step { |
| 274 | if (self.have_uninstall_step) return &self.uninstall_tls.step; | | |
| 275 | | | |
| 276 | self.top_level_steps.append(&self.uninstall_tls) catch unreachable; | | |
| 277 | self.have_uninstall_step = true; | | |
| 278 | return &self.uninstall_tls.step; | 287 | return &self.uninstall_tls.step; |
| 279 | } | 288 | } |
| 280 | | 289 | |
| ... | @@ -283,10 +292,11 @@ pub const Builder = struct { | ... | @@ -283,10 +292,11 @@ pub const Builder = struct { |
| 283 | const self = @fieldParentPtr(Builder, "uninstall_tls", uninstall_tls); | 292 | const self = @fieldParentPtr(Builder, "uninstall_tls", uninstall_tls); |
| 284 | | 293 | |
| 285 | for (self.installed_files.toSliceConst()) |installed_file| { | 294 | for (self.installed_files.toSliceConst()) |installed_file| { |
| | 295 | const full_path = self.getInstallPath(installed_file.dir, installed_file.path); |
| 286 | if (self.verbose) { | 296 | if (self.verbose) { |
| 287 | warn("rm {}\n", installed_file); | 297 | warn("rm {}\n", full_path); |
| 288 | } | 298 | } |
| 289 | fs.deleteFile(installed_file) catch {}; | 299 | fs.deleteFile(full_path) catch {}; |
| 290 | } | 300 | } |
| 291 | | 301 | |
| 292 | // TODO remove empty directories | 302 | // TODO remove empty directories |
| ... | @@ -460,6 +470,18 @@ pub const Builder = struct { | ... | @@ -460,6 +470,18 @@ pub const Builder = struct { |
| 460 | return &step_info.step; | 470 | return &step_info.step; |
| 461 | } | 471 | } |
| 462 | | 472 | |
| | 473 | /// This provides the -Drelease option to the build user and does not give them the choice. |
| | 474 | pub fn setPreferredReleaseMode(self: *Builder, mode: builtin.Mode) void { |
| | 475 | if (self.release_mode != null) { |
| | 476 | @panic("setPreferredReleaseMode must be called before standardReleaseOptions and may not be called twice"); |
| | 477 | } |
| | 478 | const description = self.fmt("create a release build ({})", @tagName(mode)); |
| | 479 | self.is_release = self.option(bool, "release", description) orelse false; |
| | 480 | self.release_mode = if (is_release) mode else builtin.Mode.Debug; |
| | 481 | } |
| | 482 | |
| | 483 | /// If you call this without first calling `setPreferredReleaseMode` then it gives the build user |
| | 484 | /// the choice of what kind of release. |
| 463 | pub fn standardReleaseOptions(self: *Builder) builtin.Mode { | 485 | pub fn standardReleaseOptions(self: *Builder) builtin.Mode { |
| 464 | if (self.release_mode) |mode| return mode; | 486 | if (self.release_mode) |mode| return mode; |
| 465 | | 487 | |
| ... | @@ -467,11 +489,20 @@ pub const Builder = struct { | ... | @@ -467,11 +489,20 @@ pub const Builder = struct { |
| 467 | const release_fast = self.option(bool, "release-fast", "optimizations on and safety off") orelse false; | 489 | const release_fast = self.option(bool, "release-fast", "optimizations on and safety off") orelse false; |
| 468 | const release_small = self.option(bool, "release-small", "size optimizations on and safety off") orelse false; | 490 | const release_small = self.option(bool, "release-small", "size optimizations on and safety off") orelse false; |
| 469 | | 491 | |
| 470 | const mode = if (release_safe and !release_fast and !release_small) builtin.Mode.ReleaseSafe else if (release_fast and !release_safe and !release_small) builtin.Mode.ReleaseFast else if (release_small and !release_fast and !release_safe) builtin.Mode.ReleaseSmall else if (!release_fast and !release_safe and !release_small) builtin.Mode.Debug else x: { | 492 | const mode = if (release_safe and !release_fast and !release_small) |
| | 493 | builtin.Mode.ReleaseSafe |
| | 494 | else if (release_fast and !release_safe and !release_small) |
| | 495 | builtin.Mode.ReleaseFast |
| | 496 | else if (release_small and !release_fast and !release_safe) |
| | 497 | builtin.Mode.ReleaseSmall |
| | 498 | else if (!release_fast and !release_safe and !release_small) |
| | 499 | builtin.Mode.Debug |
| | 500 | else x: { |
| 471 | warn("Multiple release modes (of -Drelease-safe, -Drelease-fast and -Drelease-small)"); | 501 | warn("Multiple release modes (of -Drelease-safe, -Drelease-fast and -Drelease-small)"); |
| 472 | self.markInvalidUserInput(); | 502 | self.markInvalidUserInput(); |
| 473 | break :x builtin.Mode.Debug; | 503 | break :x builtin.Mode.Debug; |
| 474 | }; | 504 | }; |
| | 505 | self.is_release = mode != .Debug; |
| 475 | self.release_mode = mode; | 506 | self.release_mode = mode; |
| 476 | return mode; | 507 | return mode; |
| 477 | } | 508 | } |
| ... | @@ -571,6 +602,8 @@ pub const Builder = struct { | ... | @@ -571,6 +602,8 @@ pub const Builder = struct { |
| 571 | } | 602 | } |
| 572 | | 603 | |
| 573 | pub fn validateUserInputDidItFail(self: *Builder) bool { | 604 | pub fn validateUserInputDidItFail(self: *Builder) bool { |
| | 605 | self.resolveInstallPrefix(); |
| | 606 | |
| 574 | // make sure all args are used | 607 | // make sure all args are used |
| 575 | var it = self.user_input_options.iterator(); | 608 | var it = self.user_input_options.iterator(); |
| 576 | while (true) { | 609 | while (true) { |
| ... | @@ -644,27 +677,52 @@ pub const Builder = struct { | ... | @@ -644,27 +677,52 @@ pub const Builder = struct { |
| 644 | return InstallArtifactStep.create(self, artifact); | 677 | return InstallArtifactStep.create(self, artifact); |
| 645 | } | 678 | } |
| 646 | | 679 | |
| 647 | ///::dest_rel_path is relative to prefix path or it can be an absolute path | 680 | ///`dest_rel_path` is relative to prefix path |
| 648 | pub fn installFile(self: *Builder, src_path: []const u8, dest_rel_path: []const u8) void { | 681 | pub fn installFile(self: *Builder, src_path: []const u8, dest_rel_path: []const u8) void { |
| 649 | self.getInstallStep().dependOn(&self.addInstallFile(src_path, dest_rel_path).step); | 682 | self.getInstallStep().dependOn(&self.addInstallFileWithDir(src_path, .Prefix, dest_rel_path).step); |
| | 683 | } |
| | 684 | |
| | 685 | ///`dest_rel_path` is relative to bin path |
| | 686 | pub fn installBinFile(self: *Builder, src_path: []const u8, dest_rel_path: []const u8) void { |
| | 687 | self.getInstallStep().dependOn(&self.addInstallFileWithDir(src_path, .Bin, dest_rel_path).step); |
| 650 | } | 688 | } |
| 651 | | 689 | |
| 652 | ///::dest_rel_path is relative to prefix path or it can be an absolute path | 690 | ///`dest_rel_path` is relative to lib path |
| | 691 | pub fn installLibFile(self: *Builder, src_path: []const u8, dest_rel_path: []const u8) void { |
| | 692 | self.getInstallStep().dependOn(&self.addInstallFileWithDir(src_path, .Lib, dest_rel_path).step); |
| | 693 | } |
| | 694 | |
| | 695 | ///`dest_rel_path` is relative to install prefix path |
| 653 | pub fn addInstallFile(self: *Builder, src_path: []const u8, dest_rel_path: []const u8) *InstallFileStep { | 696 | pub fn addInstallFile(self: *Builder, src_path: []const u8, dest_rel_path: []const u8) *InstallFileStep { |
| 654 | const full_dest_path = fs.path.resolve( | 697 | return self.addInstallFileWithDir(src_path, .Prefix, dest_rel_path); |
| 655 | self.allocator, | 698 | } |
| 656 | [_][]const u8{ self.prefix, dest_rel_path }, | 699 | |
| 657 | ) catch unreachable; | 700 | ///`dest_rel_path` is relative to bin path |
| 658 | self.pushInstalledFile(full_dest_path); | 701 | pub fn addInstallBinFile(self: *Builder, src_path: []const u8, dest_rel_path: []const u8) *InstallFileStep { |
| | 702 | return self.addInstallFileWithDir(src_path, .Bin, dest_rel_path); |
| | 703 | } |
| 659 | | 704 | |
| | 705 | ///`dest_rel_path` is relative to lib path |
| | 706 | pub fn addInstallLibFile(self: *Builder, src_path: []const u8, dest_rel_path: []const u8) *InstallFileStep { |
| | 707 | return self.addInstallFileWithDir(src_path, .Lib, dest_rel_path); |
| | 708 | } |
| | 709 | |
| | 710 | pub fn addInstallFileWithDir( |
| | 711 | self: *Builder, |
| | 712 | src_path: []const u8, |
| | 713 | install_dir: InstallDir, |
| | 714 | dest_rel_path: []const u8, |
| | 715 | ) *InstallFileStep { |
| 660 | const install_step = self.allocator.create(InstallFileStep) catch unreachable; | 716 | const install_step = self.allocator.create(InstallFileStep) catch unreachable; |
| 661 | install_step.* = InstallFileStep.init(self, src_path, full_dest_path); | 717 | install_step.* = InstallFileStep.init(self, src_path, install_dir, dest_rel_path); |
| 662 | return install_step; | 718 | return install_step; |
| 663 | } | 719 | } |
| 664 | | 720 | |
| 665 | pub fn pushInstalledFile(self: *Builder, full_path: []const u8) void { | 721 | pub fn pushInstalledFile(self: *Builder, dir: InstallDir, dest_rel_path: []const u8) void { |
| 666 | _ = self.getUninstallStep(); | 722 | self.installed_files.append(InstalledFile{ |
| 667 | self.installed_files.append(full_path) catch unreachable; | 723 | .dir = dir, |
| | 724 | .path = dest_rel_path, |
| | 725 | }) catch unreachable; |
| 668 | } | 726 | } |
| 669 | | 727 | |
| 670 | fn copyFile(self: *Builder, source_path: []const u8, dest_path: []const u8) !void { | 728 | fn copyFile(self: *Builder, source_path: []const u8, dest_path: []const u8) !void { |
| ... | @@ -786,6 +844,18 @@ pub const Builder = struct { | ... | @@ -786,6 +844,18 @@ pub const Builder = struct { |
| 786 | pub fn addSearchPrefix(self: *Builder, search_prefix: []const u8) void { | 844 | pub fn addSearchPrefix(self: *Builder, search_prefix: []const u8) void { |
| 787 | self.search_prefixes.append(search_prefix) catch unreachable; | 845 | self.search_prefixes.append(search_prefix) catch unreachable; |
| 788 | } | 846 | } |
| | 847 | |
| | 848 | fn getInstallPath(self: *Builder, dir: InstallDir, dest_rel_path: []const u8) []const u8 { |
| | 849 | const base_dir = switch (dir) { |
| | 850 | .Prefix => self.install_prefix.?, |
| | 851 | .Bin => self.exe_dir.?, |
| | 852 | .Lib => self.lib_dir.?, |
| | 853 | }; |
| | 854 | return fs.path.resolve( |
| | 855 | self.allocator, |
| | 856 | [_][]const u8{ base_dir, dest_rel_path }, |
| | 857 | ) catch unreachable; |
| | 858 | } |
| 789 | }; | 859 | }; |
| 790 | | 860 | |
| 791 | const Version = struct { | 861 | const Version = struct { |
| ... | @@ -980,6 +1050,9 @@ pub const LibExeObjStep = struct { | ... | @@ -980,6 +1050,9 @@ pub const LibExeObjStep = struct { |
| 980 | output_dir: ?[]const u8, | 1050 | output_dir: ?[]const u8, |
| 981 | need_system_paths: bool, | 1051 | need_system_paths: bool, |
| 982 | | 1052 | |
| | 1053 | installed_path: ?[]const u8, |
| | 1054 | install_step: ?*InstallArtifactStep, |
| | 1055 | |
| 983 | const LinkObject = union(enum) { | 1056 | const LinkObject = union(enum) { |
| 984 | StaticPath: []const u8, | 1057 | StaticPath: []const u8, |
| 985 | OtherStep: *LibExeObjStep, | 1058 | OtherStep: *LibExeObjStep, |
| ... | @@ -1071,6 +1144,8 @@ pub const LibExeObjStep = struct { | ... | @@ -1071,6 +1144,8 @@ pub const LibExeObjStep = struct { |
| 1071 | .output_dir = null, | 1144 | .output_dir = null, |
| 1072 | .need_system_paths = false, | 1145 | .need_system_paths = false, |
| 1073 | .single_threaded = false, | 1146 | .single_threaded = false, |
| | 1147 | .installed_path = null, |
| | 1148 | .install_step = null, |
| 1074 | }; | 1149 | }; |
| 1075 | self.computeOutFileNames(); | 1150 | self.computeOutFileNames(); |
| 1076 | return self; | 1151 | return self; |
| ... | @@ -1146,10 +1221,15 @@ pub const LibExeObjStep = struct { | ... | @@ -1146,10 +1221,15 @@ pub const LibExeObjStep = struct { |
| 1146 | self.output_dir = self.builder.dupe(dir); | 1221 | self.output_dir = self.builder.dupe(dir); |
| 1147 | } | 1222 | } |
| 1148 | | 1223 | |
| | 1224 | pub fn install(self: *LibExeObjStep) void { |
| | 1225 | self.builder.installArtifact(self); |
| | 1226 | } |
| | 1227 | |
| 1149 | /// Creates a `RunStep` with an executable built with `addExecutable`. | 1228 | /// Creates a `RunStep` with an executable built with `addExecutable`. |
| 1150 | /// Add command line arguments with `addArg`. | 1229 | /// Add command line arguments with `addArg`. |
| 1151 | pub fn run(exe: *LibExeObjStep) *RunStep { | 1230 | pub fn run(exe: *LibExeObjStep) *RunStep { |
| 1152 | assert(exe.kind == Kind.Exe); | 1231 | assert(exe.kind == Kind.Exe); |
| | 1232 | |
| 1153 | // It doesn't have to be native. We catch that if you actually try to run it. | 1233 | // It doesn't have to be native. We catch that if you actually try to run it. |
| 1154 | // Consider that this is declarative; the run step may not be run unless a user | 1234 | // Consider that this is declarative; the run step may not be run unless a user |
| 1155 | // option is supplied. | 1235 | // option is supplied. |
| ... | @@ -1692,7 +1772,8 @@ pub const RunStep = struct { | ... | @@ -1692,7 +1772,8 @@ pub const RunStep = struct { |
| 1692 | // On Windows we don't have rpaths so we have to add .dll search paths to PATH | 1772 | // On Windows we don't have rpaths so we have to add .dll search paths to PATH |
| 1693 | self.addPathForDynLibs(artifact); | 1773 | self.addPathForDynLibs(artifact); |
| 1694 | } | 1774 | } |
| 1695 | try argv.append(artifact.getOutputPath()); | 1775 | const executable_path = artifact.installed_path orelse artifact.getOutputPath(); |
| | 1776 | try argv.append(executable_path); |
| 1696 | }, | 1777 | }, |
| 1697 | } | 1778 | } |
| 1698 | } | 1779 | } |
| ... | @@ -1719,38 +1800,32 @@ const InstallArtifactStep = struct { | ... | @@ -1719,38 +1800,32 @@ const InstallArtifactStep = struct { |
| 1719 | step: Step, | 1800 | step: Step, |
| 1720 | builder: *Builder, | 1801 | builder: *Builder, |
| 1721 | artifact: *LibExeObjStep, | 1802 | artifact: *LibExeObjStep, |
| 1722 | dest_file: []const u8, | 1803 | dest_dir: InstallDir, |
| 1723 | | 1804 | |
| 1724 | const Self = @This(); | 1805 | const Self = @This(); |
| 1725 | | 1806 | |
| 1726 | pub fn create(builder: *Builder, artifact: *LibExeObjStep) *Self { | 1807 | pub fn create(builder: *Builder, artifact: *LibExeObjStep) *Self { |
| 1727 | const dest_dir = switch (artifact.kind) { | 1808 | if (artifact.install_step) |s| return s; |
| 1728 | LibExeObjStep.Kind.Obj => unreachable, | 1809 | |
| 1729 | LibExeObjStep.Kind.Test => unreachable, | | |
| 1730 | LibExeObjStep.Kind.Exe => builder.exe_dir, | | |
| 1731 | LibExeObjStep.Kind.Lib => builder.lib_dir, | | |
| 1732 | }; | | |
| 1733 | const self = builder.allocator.create(Self) catch unreachable; | 1810 | const self = builder.allocator.create(Self) catch unreachable; |
| 1734 | self.* = Self{ | 1811 | self.* = Self{ |
| 1735 | .builder = builder, | 1812 | .builder = builder, |
| 1736 | .step = Step.init(builder.fmt("install {}", artifact.step.name), builder.allocator, make), | 1813 | .step = Step.init(builder.fmt("install {}", artifact.step.name), builder.allocator, make), |
| 1737 | .artifact = artifact, | 1814 | .artifact = artifact, |
| 1738 | .dest_file = fs.path.join( | 1815 | .dest_dir = switch (artifact.kind) { |
| 1739 | builder.allocator, | 1816 | .Obj => unreachable, |
| 1740 | [_][]const u8{ dest_dir, artifact.out_filename }, | 1817 | .Test => unreachable, |
| 1741 | ) catch unreachable, | 1818 | .Exe => InstallDir.Bin, |
| | 1819 | .Lib => InstallDir.Lib, |
| | 1820 | }, |
| 1742 | }; | 1821 | }; |
| 1743 | self.step.dependOn(&artifact.step); | 1822 | self.step.dependOn(&artifact.step); |
| 1744 | builder.pushInstalledFile(self.dest_file); | 1823 | artifact.install_step = self; |
| 1745 | if (self.artifact.kind == LibExeObjStep.Kind.Lib and self.artifact.is_dynamic) { | 1824 | |
| 1746 | builder.pushInstalledFile(fs.path.join( | 1825 | builder.pushInstalledFile(self.dest_dir, artifact.out_filename); |
| 1747 | builder.allocator, | 1826 | if (self.artifact.isDynamicLibrary()) { |
| 1748 | [_][]const u8{ builder.lib_dir, artifact.major_only_filename }, | 1827 | builder.pushInstalledFile(.Lib, artifact.major_only_filename); |
| 1749 | ) catch unreachable); | 1828 | builder.pushInstalledFile(.Lib, artifact.name_only_filename); |
| 1750 | builder.pushInstalledFile(fs.path.join( | | |
| 1751 | builder.allocator, | | |
| 1752 | [_][]const u8{ builder.lib_dir, artifact.name_only_filename }, | | |
| 1753 | ) catch unreachable); | | |
| 1754 | } | 1829 | } |
| 1755 | return self; | 1830 | return self; |
| 1756 | } | 1831 | } |
| ... | @@ -1768,10 +1843,12 @@ const InstallArtifactStep = struct { | ... | @@ -1768,10 +1843,12 @@ const InstallArtifactStep = struct { |
| 1768 | .Lib => if (!self.artifact.is_dynamic) u32(0o666) else u32(0o755), | 1843 | .Lib => if (!self.artifact.is_dynamic) u32(0o666) else u32(0o755), |
| 1769 | }, | 1844 | }, |
| 1770 | }; | 1845 | }; |
| 1771 | try builder.copyFileMode(self.artifact.getOutputPath(), self.dest_file, mode); | 1846 | const full_dest_path = builder.getInstallPath(self.dest_dir, self.artifact.out_filename); |
| | 1847 | try builder.copyFileMode(self.artifact.getOutputPath(), full_dest_path, mode); |
| 1772 | if (self.artifact.isDynamicLibrary()) { | 1848 | if (self.artifact.isDynamicLibrary()) { |
| 1773 | try doAtomicSymLinks(builder.allocator, self.dest_file, self.artifact.major_only_filename, self.artifact.name_only_filename); | 1849 | try doAtomicSymLinks(builder.allocator, full_dest_path, self.artifact.major_only_filename, self.artifact.name_only_filename); |
| 1774 | } | 1850 | } |
| | 1851 | self.artifact.installed_path = full_dest_path; |
| 1775 | } | 1852 | } |
| 1776 | }; | 1853 | }; |
| 1777 | | 1854 | |
| ... | @@ -1779,20 +1856,29 @@ pub const InstallFileStep = struct { | ... | @@ -1779,20 +1856,29 @@ pub const InstallFileStep = struct { |
| 1779 | step: Step, | 1856 | step: Step, |
| 1780 | builder: *Builder, | 1857 | builder: *Builder, |
| 1781 | src_path: []const u8, | 1858 | src_path: []const u8, |
| 1782 | dest_path: []const u8, | 1859 | dir: InstallDir, |
| 1783 | | 1860 | dest_rel_path: []const u8, |
| 1784 | pub fn init(builder: *Builder, src_path: []const u8, dest_path: []const u8) InstallFileStep { | 1861 | |
| | 1862 | pub fn init( |
| | 1863 | builder: *Builder, |
| | 1864 | src_path: []const u8, |
| | 1865 | dir: InstallDir, |
| | 1866 | dest_rel_path: []const u8, |
| | 1867 | ) InstallFileStep { |
| | 1868 | builder.pushInstalledFile(dir, dest_rel_path); |
| 1785 | return InstallFileStep{ | 1869 | return InstallFileStep{ |
| 1786 | .builder = builder, | 1870 | .builder = builder, |
| 1787 | .step = Step.init(builder.fmt("install {}", src_path), builder.allocator, make), | 1871 | .step = Step.init(builder.fmt("install {}", src_path), builder.allocator, make), |
| 1788 | .src_path = src_path, | 1872 | .src_path = src_path, |
| 1789 | .dest_path = dest_path, | 1873 | .dir = dir, |
| | 1874 | .dest_rel_path = dest_rel_path, |
| 1790 | }; | 1875 | }; |
| 1791 | } | 1876 | } |
| 1792 | | 1877 | |
| 1793 | fn make(step: *Step) !void { | 1878 | fn make(step: *Step) !void { |
| 1794 | const self = @fieldParentPtr(InstallFileStep, "step", step); | 1879 | const self = @fieldParentPtr(InstallFileStep, "step", step); |
| 1795 | try self.builder.copyFile(self.src_path, self.dest_path); | 1880 | const full_dest_path = self.builder.getInstallPath(self.dir, self.dest_rel_path); |
| | 1881 | try self.builder.copyFile(self.src_path, full_dest_path); |
| 1796 | } | 1882 | } |
| 1797 | }; | 1883 | }; |
| 1798 | | 1884 | |
| ... | @@ -1925,3 +2011,14 @@ fn doAtomicSymLinks(allocator: *Allocator, output_path: []const u8, filename_maj | ... | @@ -1925,3 +2011,14 @@ fn doAtomicSymLinks(allocator: *Allocator, output_path: []const u8, filename_maj |
| 1925 | return err; | 2011 | return err; |
| 1926 | }; | 2012 | }; |
| 1927 | } | 2013 | } |
| | 2014 | |
| | 2015 | pub const InstallDir = enum { |
| | 2016 | Prefix, |
| | 2017 | Lib, |
| | 2018 | Bin, |
| | 2019 | }; |
| | 2020 | |
| | 2021 | pub const InstalledFile = struct { |
| | 2022 | dir: InstallDir, |
| | 2023 | path: []const u8, |
| | 2024 | }; |