From ab2ab6b52686f9d1d95b1b304828aa09a92a050e Mon Sep 17 00:00:00 2001 From: dweiller <4678790+dweiller@users.noreplay.github.com> Date: Thu, 16 Sep 2021 02:12:34 +1000 Subject: [PATCH 1/2] Add exact_install_filename to LibExeObjStep This allows setting the exact installed filename for a LibExeObjStep. Versioned symlinks will not be made for a shared dynamic library that has exact_install_filename set. --- lib/std/build.zig | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/lib/std/build.zig b/lib/std/build.zig index 7b976405dc04..6e5c686e8406 100644 --- a/lib/std/build.zig +++ b/lib/std/build.zig @@ -1418,6 +1418,7 @@ pub const LibExeObjStep = struct { kind: Kind, major_only_filename: ?[]const u8, name_only_filename: ?[]const u8, + exact_install_filename: ?[]const u8 = null, strip: bool, lib_paths: ArrayList([]const u8), rpaths: ArrayList([]const u8), @@ -2754,7 +2755,9 @@ pub const LibExeObjStep = struct { } } - if (self.kind == .lib and self.linkage != null and self.linkage.? == .dynamic and self.version != null and self.target.wantSharedLibSymLinks()) { + if (self.exact_install_filename == null and self.kind == .lib and self.linkage != null and + self.linkage.? == .dynamic and self.version != null and self.target.wantSharedLibSymLinks()) + { try doAtomicSymLinks(builder.allocator, self.getOutputSource().getPath(builder), self.major_only_filename.?, self.name_only_filename.?); } } @@ -2798,8 +2801,13 @@ pub const InstallArtifactStep = struct { self.step.dependOn(&artifact.step); artifact.install_step = self; - builder.pushInstalledFile(self.dest_dir, artifact.out_filename); - if (self.artifact.isDynamicLibrary()) { + const install_name = if (self.artifact.exact_install_filename) |name| + name + else + self.artifact.out_filename; + + builder.pushInstalledFile(self.dest_dir, install_name); + if (self.artifact.exact_install_filename == null and self.artifact.isDynamicLibrary()) { if (artifact.major_only_filename) |name| { builder.pushInstalledFile(.lib, name); } @@ -2823,9 +2831,16 @@ pub const InstallArtifactStep = struct { const self = @fieldParentPtr(Self, "step", step); const builder = self.builder; - const full_dest_path = builder.getInstallPath(self.dest_dir, self.artifact.out_filename); + const install_name = if (self.artifact.exact_install_filename) |name| + name + else + self.artifact.out_filename; + + const full_dest_path = builder.getInstallPath(self.dest_dir, install_name); try builder.updateFile(self.artifact.getOutputSource().getPath(builder), full_dest_path); - if (self.artifact.isDynamicLibrary() and self.artifact.version != null and self.artifact.target.wantSharedLibSymLinks()) { + if (self.artifact.exact_install_filename == null and self.artifact.isDynamicLibrary() and + self.artifact.version != null and self.artifact.target.wantSharedLibSymLinks()) + { try doAtomicSymLinks(builder.allocator, full_dest_path, self.artifact.major_only_filename.?, self.artifact.name_only_filename.?); } if (self.pdb_dir) |pdb_dir| { From 6cb5d1a0b3695f48b430ee3bc6fb425c4b593757 Mon Sep 17 00:00:00 2001 From: dweiller <4678790+dweiller@users.noreplay.github.com> Date: Sat, 18 Sep 2021 17:31:31 +1000 Subject: [PATCH 2/2] Fix order dependence of LibExeObjStep.install() Instead of configuring the paths of a ArtifactInstallStep when it is created, defer this until the make() call of the associated LibExeObjStep. This means that any steps that depend on the paths of the installed files (even if they do not need the files to be installed) should depend on the LibExeObjStep and do any processing with the installation paths after the LibExeObjStep has been made. --- lib/std/build.zig | 81 +++++++++++++++++++++++++++++++---------------- 1 file changed, 53 insertions(+), 28 deletions(-) diff --git a/lib/std/build.zig b/lib/std/build.zig index 6e5c686e8406..27cbdd7559b5 100644 --- a/lib/std/build.zig +++ b/lib/std/build.zig @@ -59,6 +59,7 @@ pub const Builder = struct { search_prefixes: ArrayList([]const u8), libc_file: ?[]const u8 = null, installed_files: ArrayList(InstalledFile), + configure_installed_files: ArrayList(*InstallArtifactStep), build_root: []const u8, cache_root: []const u8, global_cache_root: []const u8, @@ -173,6 +174,7 @@ pub const Builder = struct { .h_dir = undefined, .dest_dir = env_map.get("DESTDIR"), .installed_files = ArrayList(InstalledFile).init(allocator), + .configure_installed_files = ArrayList(*InstallArtifactStep).init(allocator), .install_tls = TopLevelStep{ .step = Step.initNoOp(.top_level, "install", allocator), .description = "Copy build artifacts to prefix path", @@ -438,6 +440,10 @@ pub const Builder = struct { const uninstall_tls = @fieldParentPtr(TopLevelStep, "step", uninstall_step); const self = @fieldParentPtr(Builder, "uninstall_tls", uninstall_tls); + for (self.configure_installed_files.items) |install_step| { + install_step.configure(); + } + for (self.installed_files.items) |installed_file| { const full_path = self.getInstallPath(installed_file.dir, installed_file.path); if (self.verbose) { @@ -1049,6 +1055,10 @@ pub const Builder = struct { self.installed_files.append(file.dupe(self)) catch unreachable; } + pub fn pushInstallConfigure(self: *Builder, install_step: *InstallArtifactStep) void { + self.configure_installed_files.append(install_step) catch unreachable; + } + pub fn updateFile(self: *Builder, source_path: []const u8, dest_path: []const u8) !void { if (self.verbose) { warn("cp {s} {s} ", .{ source_path, dest_path }); @@ -2729,6 +2739,7 @@ pub const LibExeObjStep = struct { // This will ensure all output filenames will now have the output_dir available! self.computeOutFileNames(); + if (self.install_step) |install_step| install_step.configure(); // Update generated files if (self.output_dir != null) { @@ -2769,20 +2780,25 @@ pub const InstallArtifactStep = struct { step: Step, builder: *Builder, artifact: *LibExeObjStep, - dest_dir: InstallDir, - pdb_dir: ?InstallDir, - h_dir: ?InstallDir, + state: ?ConfiguredState = null, const Self = @This(); - pub fn create(builder: *Builder, artifact: *LibExeObjStep) *Self { - if (artifact.install_step) |s| return s; + const ConfiguredState = struct { + basename: []const u8, + dest_dir: InstallDir, + pdb_dir: ?InstallDir, + h_dir: ?InstallDir, + }; - const self = builder.allocator.create(Self) catch unreachable; - self.* = Self{ - .builder = builder, - .step = Step.init(.install_artifact, builder.fmt("install {s}", .{artifact.step.name}), builder.allocator, make), - .artifact = artifact, + /// must be called after all declarative setup of the artifact (i.e. by artifact.make() or makeUninstall()) + fn configure(self: *InstallArtifactStep) void { + if (self.state != null) return; + + const artifact = self.artifact; + + const state = ConfiguredState{ + .basename = artifact.exact_install_filename orelse artifact.out_filename, .dest_dir = artifact.override_dest_dir orelse switch (artifact.kind) { .obj => unreachable, .@"test" => unreachable, @@ -2798,32 +2814,44 @@ pub const InstallArtifactStep = struct { } else null, .h_dir = if (artifact.kind == .lib and artifact.emit_h) .header else null, }; - self.step.dependOn(&artifact.step); - artifact.install_step = self; - const install_name = if (self.artifact.exact_install_filename) |name| - name - else - self.artifact.out_filename; + self.state = state; - builder.pushInstalledFile(self.dest_dir, install_name); - if (self.artifact.exact_install_filename == null and self.artifact.isDynamicLibrary()) { + const builder = artifact.builder; + builder.pushInstalledFile(state.dest_dir, state.basename); + if (artifact.exact_install_filename == null and artifact.isDynamicLibrary()) { if (artifact.major_only_filename) |name| { builder.pushInstalledFile(.lib, name); } if (artifact.name_only_filename) |name| { builder.pushInstalledFile(.lib, name); } - if (self.artifact.target.isWindows()) { + if (artifact.target.isWindows()) { builder.pushInstalledFile(.lib, artifact.out_lib_filename); } } - if (self.pdb_dir) |pdb_dir| { + if (state.pdb_dir) |pdb_dir| { builder.pushInstalledFile(pdb_dir, artifact.out_pdb_filename); } - if (self.h_dir) |h_dir| { + if (state.h_dir) |h_dir| { builder.pushInstalledFile(h_dir, artifact.out_h_filename); } + } + + pub fn create(builder: *Builder, artifact: *LibExeObjStep) *Self { + if (artifact.install_step) |s| return s; + + const self = builder.allocator.create(Self) catch unreachable; + self.* = Self{ + .builder = builder, + .step = Step.init(.install_artifact, builder.fmt("install {s}", .{artifact.step.name}), builder.allocator, make), + .artifact = artifact, + }; + + self.step.dependOn(&artifact.step); + artifact.install_step = self; + + builder.pushInstallConfigure(self); return self; } @@ -2831,23 +2859,20 @@ pub const InstallArtifactStep = struct { const self = @fieldParentPtr(Self, "step", step); const builder = self.builder; - const install_name = if (self.artifact.exact_install_filename) |name| - name - else - self.artifact.out_filename; + const state = self.state orelse panic("Install state for {s} not configured.", .{self.artifact.name}); - const full_dest_path = builder.getInstallPath(self.dest_dir, install_name); + const full_dest_path = builder.getInstallPath(state.dest_dir, state.basename); try builder.updateFile(self.artifact.getOutputSource().getPath(builder), full_dest_path); if (self.artifact.exact_install_filename == null and self.artifact.isDynamicLibrary() and self.artifact.version != null and self.artifact.target.wantSharedLibSymLinks()) { try doAtomicSymLinks(builder.allocator, full_dest_path, self.artifact.major_only_filename.?, self.artifact.name_only_filename.?); } - if (self.pdb_dir) |pdb_dir| { + if (state.pdb_dir) |pdb_dir| { const full_pdb_path = builder.getInstallPath(pdb_dir, self.artifact.out_pdb_filename); try builder.updateFile(self.artifact.getOutputPdbSource().getPath(builder), full_pdb_path); } - if (self.h_dir) |h_dir| { + if (state.h_dir) |h_dir| { const full_pdb_path = builder.getInstallPath(h_dir, self.artifact.out_h_filename); try builder.updateFile(self.artifact.getOutputHSource().getPath(builder), full_pdb_path); }