diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2023-02-27 14:11:29 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2023-02-27 16:10:48 -0700 |
| commit | d399f8a489dd2ae62fae9b805778bfdc697a969b (patch) | |
| tree | 60df6836102786a1e665dfc92d815a27d6f8c352 /lib/std/Build/CompileStep.zig | |
| parent | b5b634e4e8a2a1fe32fba50ccd175257b4213936 (diff) | |
| parent | f6c934677315665c140151b8dd28a56f948205e2 (diff) | |
| download | zig-d399f8a489dd2ae62fae9b805778bfdc697a969b.tar.gz zig-d399f8a489dd2ae62fae9b805778bfdc697a969b.zip | |
Merge remote-tracking branch 'origin/master' into llvm16
Diffstat (limited to 'lib/std/Build/CompileStep.zig')
| -rw-r--r-- | lib/std/Build/CompileStep.zig | 146 |
1 files changed, 121 insertions, 25 deletions
diff --git a/lib/std/Build/CompileStep.zig b/lib/std/Build/CompileStep.zig index a916de0fc6..ea2320cc89 100644 --- a/lib/std/Build/CompileStep.zig +++ b/lib/std/Build/CompileStep.zig @@ -21,7 +21,7 @@ const VcpkgRoot = std.Build.VcpkgRoot; const InstallDir = std.Build.InstallDir; const InstallArtifactStep = std.Build.InstallArtifactStep; const GeneratedFile = std.Build.GeneratedFile; -const InstallRawStep = std.Build.InstallRawStep; +const ObjCopyStep = std.Build.ObjCopyStep; const EmulatableRunStep = std.Build.EmulatableRunStep; const CheckObjectStep = std.Build.CheckObjectStep; const RunStep = std.Build.RunStep; @@ -432,10 +432,6 @@ pub fn install(self: *CompileStep) void { self.builder.installArtifact(self); } -pub fn installRaw(self: *CompileStep, dest_filename: []const u8, options: InstallRawStep.CreateOptions) *InstallRawStep { - return self.builder.installRaw(self, dest_filename, options); -} - pub fn installHeader(a: *CompileStep, src_path: []const u8, dest_rel_path: []const u8) void { const install_file = a.builder.addInstallHeaderFile(src_path, dest_rel_path); a.builder.getInstallStep().dependOn(&install_file.step); @@ -458,6 +454,7 @@ pub fn installConfigHeader( options.install_dir, dest_rel_path, ); + install_file.step.dependOn(&config_header.step); cs.builder.getInstallStep().dependOn(&install_file.step); cs.installed_headers.append(&install_file.step) catch @panic("OOM"); } @@ -506,6 +503,18 @@ pub fn installLibraryHeaders(a: *CompileStep, l: *CompileStep) void { a.installed_headers.appendSlice(l.installed_headers.items) catch @panic("OOM"); } +pub fn addObjCopy(cs: *CompileStep, options: ObjCopyStep.Options) *ObjCopyStep { + var copy = options; + if (copy.basename == null) { + if (options.format) |f| { + copy.basename = cs.builder.fmt("{s}.{s}", .{ cs.name, @tagName(f) }); + } else { + copy.basename = cs.name; + } + } + return cs.builder.addObjCopy(cs.getOutputSource(), copy); +} + /// Deprecated: use `std.Build.addRunArtifact` /// This function will run in the context of the package that created the executable, /// which is undesirable when running an executable provided by a dependency package. @@ -955,7 +964,10 @@ pub fn addFrameworkPath(self: *CompileStep, dir_path: []const u8) void { /// package's module table using `name`. pub fn addModule(cs: *CompileStep, name: []const u8, module: *Module) void { cs.modules.put(cs.builder.dupe(name), module) catch @panic("OOM"); - cs.addRecursiveBuildDeps(module); + + var done = std.AutoHashMap(*Module, void).init(cs.builder.allocator); + defer done.deinit(); + cs.addRecursiveBuildDeps(module, &done) catch @panic("OOM"); } /// Adds a module to be used with `@import` without exposing it in the current @@ -969,10 +981,12 @@ pub fn addOptions(cs: *CompileStep, module_name: []const u8, options: *OptionsSt addModule(cs, module_name, options.createModule()); } -fn addRecursiveBuildDeps(cs: *CompileStep, module: *Module) void { +fn addRecursiveBuildDeps(cs: *CompileStep, module: *Module, done: *std.AutoHashMap(*Module, void)) !void { + if (done.contains(module)) return; + try done.put(module, {}); module.source_file.addStepDependencies(&cs.step); for (module.dependencies.values()) |dep| { - cs.addRecursiveBuildDeps(dep); + try cs.addRecursiveBuildDeps(dep, done); } } @@ -1031,22 +1045,110 @@ fn linkLibraryOrObject(self: *CompileStep, other: *CompileStep) void { fn appendModuleArgs( cs: *CompileStep, zig_args: *ArrayList([]const u8), - name: []const u8, - module: *Module, ) error{OutOfMemory}!void { - try zig_args.append("--pkg-begin"); - try zig_args.append(name); - try zig_args.append(module.builder.pathFromRoot(module.source_file.getPath(module.builder))); + // First, traverse the whole dependency graph and give every module a unique name, ideally one + // named after what it's called somewhere in the graph. It will help here to have both a mapping + // from module to name and a set of all the currently-used names. + var mod_names = std.AutoHashMap(*Module, []const u8).init(cs.builder.allocator); + var names = std.StringHashMap(void).init(cs.builder.allocator); + + var to_name = std.ArrayList(struct { + name: []const u8, + mod: *Module, + }).init(cs.builder.allocator); + { + var it = cs.modules.iterator(); + while (it.next()) |kv| { + // While we're traversing the root dependencies, let's make sure that no module names + // have colons in them, since the CLI forbids it. We handle this for transitive + // dependencies further down. + if (std.mem.indexOfScalar(u8, kv.key_ptr.*, ':') != null) { + @panic("Module names cannot contain colons"); + } + try to_name.append(.{ + .name = kv.key_ptr.*, + .mod = kv.value_ptr.*, + }); + } + } + + while (to_name.popOrNull()) |dep| { + if (mod_names.contains(dep.mod)) continue; + + // We'll use this buffer to store the name we decide on + var buf = try cs.builder.allocator.alloc(u8, dep.name.len + 32); + // First, try just the exposed dependency name + std.mem.copy(u8, buf, dep.name); + var name = buf[0..dep.name.len]; + var n: usize = 0; + while (names.contains(name)) { + // If that failed, append an incrementing number to the end + name = std.fmt.bufPrint(buf, "{s}{}", .{ dep.name, n }) catch unreachable; + n += 1; + } + + try mod_names.put(dep.mod, name); + try names.put(name, {}); + var it = dep.mod.dependencies.iterator(); + while (it.next()) |kv| { + // Same colon-in-name check as above, but for transitive dependencies. + if (std.mem.indexOfScalar(u8, kv.key_ptr.*, ':') != null) { + @panic("Module names cannot contain colons"); + } + try to_name.append(.{ + .name = kv.key_ptr.*, + .mod = kv.value_ptr.*, + }); + } + } + + // Since the module names given to the CLI are based off of the exposed names, we already know + // that none of the CLI names have colons in them, so there's no need to check that explicitly. + + // Every module in the graph is now named; output their definitions { - const keys = module.dependencies.keys(); - for (module.dependencies.values(), 0..) |sub_module, i| { - const sub_name = keys[i]; - try cs.appendModuleArgs(zig_args, sub_name, sub_module); + var it = mod_names.iterator(); + while (it.next()) |kv| { + const mod = kv.key_ptr.*; + const name = kv.value_ptr.*; + + const deps_str = try constructDepString(cs.builder.allocator, mod_names, mod.dependencies); + const src = mod.builder.pathFromRoot(mod.source_file.getPath(mod.builder)); + try zig_args.append("--mod"); + try zig_args.append(try std.fmt.allocPrint(cs.builder.allocator, "{s}:{s}:{s}", .{ name, deps_str, src })); } } - try zig_args.append("--pkg-end"); + // Lastly, output the root dependencies + const deps_str = try constructDepString(cs.builder.allocator, mod_names, cs.modules); + if (deps_str.len > 0) { + try zig_args.append("--deps"); + try zig_args.append(deps_str); + } +} + +fn constructDepString( + allocator: std.mem.Allocator, + mod_names: std.AutoHashMap(*Module, []const u8), + deps: std.StringArrayHashMap(*Module), +) ![]const u8 { + var deps_str = std.ArrayList(u8).init(allocator); + var it = deps.iterator(); + while (it.next()) |kv| { + const expose = kv.key_ptr.*; + const name = mod_names.get(kv.value_ptr.*).?; + if (std.mem.eql(u8, expose, name)) { + try deps_str.writer().print("{s},", .{name}); + } else { + try deps_str.writer().print("{s}={s},", .{ expose, name }); + } + } + if (deps_str.items.len > 0) { + return deps_str.items[0 .. deps_str.items.len - 1]; // omit trailing comma + } else { + return ""; + } } fn make(step: *Step) !void { @@ -1573,13 +1675,7 @@ fn make(step: *Step) !void { try zig_args.append("--test-no-exec"); } - { - const keys = self.modules.keys(); - for (self.modules.values(), 0..) |module, i| { - const name = keys[i]; - try self.appendModuleArgs(&zig_args, name, module); - } - } + try self.appendModuleArgs(&zig_args); for (self.include_dirs.items) |include_dir| { switch (include_dir) { |
