authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-03-08 22:42:41-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-05-25 18:54:34-07:00
logeaffd5551349be6132ab33827e307f28ca8ac051
tree51cbb7ed774b3c949f00b07b0d732b492c9f35ed
parent8f36a83b45eedef92b3fcda605e0ccb3828ddbd3

maker: progress towards lowering Compile Step CLI args

next thing to do is figure out how LazyPath is supposed to work now. something like this: * each Step that provides LazyPath objects has a setLazyPath and getLazyPath function which takes a tagged union identifying which one to access * steps that fulfill LazyPath objects can freely call setLazyPath without obtaining a lock because the dependency graph prevents simultaneous access. * similarly, steps that access LazyPath results can freely call getLazyPath without obtaining a lock, because after modification, there may be simultaneous reads from dependencies but they will all be read-only * a fulfilled LazyPath object is a read-only std.Build.Cache.Path.

6 files changed, 431 insertions(+), 304 deletions(-)

lib/compiler/Maker/ScannedConfig.zig+1-1
...@@ -135,7 +135,7 @@ fn printValue(sc: *const ScannedConfig, s: *Serializer, comptime Field: type, fi...@@ -135,7 +135,7 @@ fn printValue(sc: *const ScannedConfig, s: *Serializer, comptime Field: type, fi
135 .extended => @compileError("TODO"),135 .extended => @compileError("TODO"),
136 .union_list => {136 .union_list => {
137 var slice_field = try s.beginTuple(.{});137 var slice_field = try s.beginTuple(.{});
138 for (field_value.get(c.extra), 0..) |elem, i| switch (field_value.tag(c.extra, i)) {138 for (field_value.slice(c.extra), 0..) |elem, i| switch (field_value.tag(c.extra, i)) {
139 inline else => |tag| {139 inline else => |tag| {
140 var sub_struct = try s.beginStruct(.{});140 var sub_struct = try s.beginStruct(.{});
141 try sub_struct.fieldPrefix(@tagName(tag));141 try sub_struct.fieldPrefix(@tagName(tag));
lib/compiler/Maker/Step.zig+5-4
...@@ -316,13 +316,14 @@ pub fn captureChildProcess(...@@ -316,13 +316,14 @@ pub fn captureChildProcess(
316 return result;316 return result;
317}317}
318318
319pub fn fail(step: *Step, comptime fmt: []const u8, args: anytype) error{ OutOfMemory, MakeFailed } {319pub fn fail(step: *Step, maker: *const Maker, comptime fmt: []const u8, args: anytype) error{ OutOfMemory, MakeFailed } {
320 try step.addError(fmt, args);320 try step.addError(maker, fmt, args);
321 return error.MakeFailed;321 return error.MakeFailed;
322}322}
323323
324pub fn addError(step: *Step, comptime fmt: []const u8, args: anytype) error{OutOfMemory}!void {324pub fn addError(step: *Step, maker: *const Maker, comptime fmt: []const u8, args: anytype) error{OutOfMemory}!void {
325 const arena = step.owner.allocator;325 const graph = maker.graph;
326 const arena = graph.arena; // TODO don't leak into the process_arena
326 const msg = try std.fmt.allocPrint(arena, fmt, args);327 const msg = try std.fmt.allocPrint(arena, fmt, args);
327 try step.result_error_msgs.append(arena, msg);328 try step.result_error_msgs.append(arena, msg);
328}329}
lib/compiler/Maker/Step/Compile.zig+394-290
...@@ -23,14 +23,17 @@ zig_args: std.ArrayList([]const u8) = .empty,...@@ -23,14 +23,17 @@ zig_args: std.ArrayList([]const u8) = .empty,
2323
24pub fn make(24pub fn make(
25 compile: *Compile,25 compile: *Compile,
26 step_index: Configuration.Step.Index,26 compile_index: Configuration.Step.Index,
27 maker: *Maker,27 maker: *Maker,
28 progress_node: std.Progress.Node,28 progress_node: std.Progress.Node,
29) Step.ExtendedMakeError!void {29) Step.ExtendedMakeError!void {
30 const graph = maker.graph;30 const graph = maker.graph;
31 const step = maker.stepByIndex(step_index);31 const step = maker.stepByIndex(compile_index);
32
33 // Reset / repopulate persistent state.
32 compile.zig_args.clearRetainingCapacity();34 compile.zig_args.clearRetainingCapacity();
33 try lowerZigArgs(compile, step_index, maker, &compile.zig_args, false);35
36 try lowerZigArgs(compile, compile_index, maker, &compile.zig_args, false);
34 if (true) @panic("TODO implement compile.make()");37 if (true) @panic("TODO implement compile.make()");
35 const process_arena = graph.arena; // TODO don't leak into the process_arena38 const process_arena = graph.arena; // TODO don't leak into the process_arena
3639
...@@ -42,7 +45,7 @@ pub fn make(...@@ -42,7 +45,7 @@ pub fn make(
42 ) catch |err| switch (err) {45 ) catch |err| switch (err) {
43 error.NeedCompileErrorCheck => {46 error.NeedCompileErrorCheck => {
44 assert(compile.expect_errors != null);47 assert(compile.expect_errors != null);
45 try checkCompileErrors(compile);48 try checkCompileErrors(compile, maker);
46 return;49 return;
47 },50 },
48 else => |e| return e,51 else => |e| return e,
...@@ -81,19 +84,50 @@ pub fn make(...@@ -81,19 +84,50 @@ pub fn make(
81 }84 }
82}85}
8386
87/// List of importable modules in a compilation's module graph, including
88/// the root module. The root module is guaranteed to be first.
89const ModuleList = std.AutoArrayHashMapUnmanaged(Configuration.Module.Index, Configuration.String);
90/// Keyed on the first key in the module list.
91const ModuleGraph = std.ArrayHashMapUnmanaged(ModuleList, void, ModuleListContext, false);
92
93const ModuleListContext = struct {
94 pub fn eql(ctx: @This(), a: ModuleList, b: ModuleList) bool {
95 _ = ctx;
96 return a.keys()[0] == b.keys()[0];
97 }
98
99 pub fn hash(ctx: @This(), key: ModuleList) u32 {
100 _ = ctx;
101 return std.hash.int(@intFromEnum(key.keys()[0]));
102 }
103
104 const Adapter = struct {
105 pub fn eql(ctx: @This(), a: Configuration.Module.Index, b: ModuleList, b_index: usize) bool {
106 _ = ctx;
107 _ = b_index;
108 return a == b.keys()[0];
109 }
110
111 pub fn hash(ctx: @This(), key: Configuration.Module.Index) u32 {
112 _ = ctx;
113 return std.hash.int(@intFromEnum(key));
114 }
115 };
116};
117
84fn lowerZigArgs(118fn lowerZigArgs(
85 compile: *Compile,119 compile: *const Compile,
86 step_index: Configuration.Step.Index,120 compile_index: Configuration.Step.Index,
87 maker: *Maker,121 maker: *const Maker,
88 zig_args: *std.ArrayList([]const u8),122 zig_args: *std.ArrayList([]const u8),
89 fuzz: bool,123 fuzz: bool,
90) Allocator.Error!void {124) error{ OutOfMemory, MakeFailed }!void {
91 const step = maker.stepByIndex(step_index);125 const step = maker.stepByIndex(compile_index);
92 const graph = maker.graph;126 const graph = maker.graph;
93 const arena = graph.arena; // TODO don't leak into the process arena127 const arena = graph.arena; // TODO don't leak into the process arena
94 const gpa = maker.gpa;128 const gpa = maker.gpa;
95 const conf = &maker.scanned_config.configuration;129 const conf = &maker.scanned_config.configuration;
96 const conf_step = step_index.ptr(conf);130 const conf_step = compile_index.ptr(conf);
97 const conf_comp = conf_step.extended.get(conf.extra).compile;131 const conf_comp = conf_step.extended.get(conf.extra).compile;
98132
99 try zig_args.append(gpa, graph.zig_exe);133 try zig_args.append(gpa, graph.zig_exe);
...@@ -144,21 +178,21 @@ fn lowerZigArgs(...@@ -144,21 +178,21 @@ fn lowerZigArgs(
144178
145 try addBool(gpa, zig_args, "-ffuzz", fuzz);179 try addBool(gpa, zig_args, "-ffuzz", fuzz);
146180
147 if (true) @panic("TODO");
148
149 var is_linking_libc = conf_comp.flags3.is_linking_libc;
150 var is_linking_libcpp = conf_comp.flags3.is_linking_libcpp;
151
152 {181 {
182 var is_linking_libc = conf_comp.flags3.is_linking_libc;
183 var is_linking_libcpp = conf_comp.flags3.is_linking_libcpp;
184
153 // Stores system libraries that have already been seen for at least one185 // Stores system libraries that have already been seen for at least one
154 // module, along with any arguments that need to be passed to the186 // module, along with any C compiler arguments that need to be passed
155 // compiler for each module individually.187 // to the compiler for each module individually as reported by
156 var seen_system_libs: std.StringHashMapUnmanaged([]const []const u8) = .empty;188 // pkg-config.
157 var frameworks: std.StringArrayHashMapUnmanaged(Module.FrameworkFlags) = .empty;189 var seen_system_libs: std.AutoArrayHashMapUnmanaged(Configuration.String, []const []const u8) = .empty;
190 var frameworks: std.AutoArrayHashMapUnmanaged(Configuration.String, Configuration.Module.Framework.Flags) = .empty;
191 var module_graph: ModuleGraph = .empty;
158192
159 var prev_has_cflags = false;193 var prev_has_cflags = false;
160 var prev_has_rcflags = false;194 var prev_has_rcflags = false;
161 var prev_search_strategy: Module.SystemLib.SearchStrategy = .paths_first;195 var prev_search_strategy: Configuration.SystemLib.SearchStrategy = .paths_first;
162 var prev_preferred_link_mode: std.builtin.LinkMode = .dynamic;196 var prev_preferred_link_mode: std.builtin.LinkMode = .dynamic;
163 // Track the number of positional arguments so that a nice error can be197 // Track the number of positional arguments so that a nice error can be
164 // emitted if there is nothing to link.198 // emitted if there is nothing to link.
...@@ -166,250 +200,256 @@ fn lowerZigArgs(...@@ -166,250 +200,256 @@ fn lowerZigArgs(
166200
167 // Fully recursive iteration including dynamic libraries to detect201 // Fully recursive iteration including dynamic libraries to detect
168 // libc and libc++ linkage.202 // libc and libc++ linkage.
169 for (getCompileDependencies(true)) |some_compile| {203 for (try getCompileDependencies(arena, &module_graph, conf, compile_index, true)) |some_compile_index| {
170 for (some_compile.root_module.getGraph().modules) |mod| {204 const some_compile = some_compile_index.ptr(conf).extended.get(conf.extra).compile;
171 if (mod.link_libc == true) is_linking_libc = true;205 const modules = try getModuleList(arena, &module_graph, some_compile.root_module, conf);
172 if (mod.link_libcpp == true) is_linking_libcpp = true;206 for (modules.keys()) |mod_index| {
207 const mod = mod_index.get(conf);
208 is_linking_libc = is_linking_libc or mod.flags2.link_libc == .true;
209 is_linking_libcpp = is_linking_libcpp or mod.flags2.link_libcpp == .true;
173 }210 }
174 }211 }
175212
176 var cli_named_modules = try CliNamedModules.init(arena, compile.root_module);213 var cli_named_modules = try CliNamedModules.init(arena, &module_graph, compile_index, maker);
177214
178 // For this loop, don't chase dynamic libraries because their link215 // For this loop, don't chase dynamic libraries because their link
179 // objects are already linked.216 // objects are already linked.
180 for (getCompileDependencies(false)) |dep_compile| {217 for (try getCompileDependencies(arena, &module_graph, conf, compile_index, false)) |dep_compile_index| {
181 for (dep_compile.root_module.getGraph().modules) |mod| {218 const dep_compile = dep_compile_index.ptr(conf).extended.get(conf.extra).compile;
219 const modules = try getModuleList(arena, &module_graph, dep_compile.root_module, conf);
220 for (modules.keys()) |mod_index| {
221 const mod = mod_index.get(conf);
182 // While walking transitive dependencies, if a given link object is222 // While walking transitive dependencies, if a given link object is
183 // already included in a library, it should not redundantly be223 // already included in a library, it should not redundantly be
184 // placed on the linker line of the dependee.224 // placed on the linker line of the dependee.
185 const my_responsibility = dep_compile == compile;225 const my_responsibility = dep_compile_index == compile_index;
186 const already_linked = !my_responsibility and dep_compile.isDynamicLibrary();226 const already_linked = !my_responsibility and dep_compile.isDynamicLibrary();
187227
188 // Inherit dependencies on darwin frameworks.228 // Inherit dependencies on darwin frameworks.
189 if (!already_linked) {229 if (!already_linked) {
190 for (mod.frameworks.keys(), mod.frameworks.values()) |name, info| {230 for (mod.frameworks.slice) |framework| {
191 try frameworks.put(arena, name, info);231 try frameworks.put(arena, framework.name, framework.flags);
192 }232 }
193 }233 }
194234
235 if (true) @panic("TODO");
236
195 // Inherit dependencies on system libraries and static libraries.237 // Inherit dependencies on system libraries and static libraries.
196 for (mod.link_objects.items) |link_object| {238 for (0..mod.link_objects.len) |lo_i| switch (mod.link_objects.get(conf.extra, lo_i)) {
197 switch (link_object) {239 .static_path => |static_path| {
198 .static_path => |static_path| {240 if (my_responsibility) {
199 if (my_responsibility) {241 try zig_args.append(gpa, static_path.getPath2(step));
200 try zig_args.append(gpa, static_path.getPath2(step));242 total_linker_objects += 1;
201 total_linker_objects += 1;243 }
202 }244 },
203 },245 .system_lib => |system_lib| {
204 .system_lib => |system_lib| {246 const system_lib_gop = try seen_system_libs.getOrPut(arena, system_lib.name);
205 const system_lib_gop = try seen_system_libs.getOrPut(arena, system_lib.name);247 if (system_lib_gop.found_existing) {
206 if (system_lib_gop.found_existing) {248 try zig_args.appendSlice(gpa, system_lib_gop.value_ptr.*);
207 try zig_args.appendSlice(gpa, system_lib_gop.value_ptr.*);249 continue;
208 continue;250 } else {
209 } else {251 system_lib_gop.value_ptr.* = &.{};
210 system_lib_gop.value_ptr.* = &.{};252 }
211 }
212253
213 if (already_linked)254 if (already_linked)
214 continue;255 continue;
215256
216 if ((system_lib.search_strategy != prev_search_strategy or257 if ((system_lib.search_strategy != prev_search_strategy or
217 system_lib.preferred_link_mode != prev_preferred_link_mode) and258 system_lib.preferred_link_mode != prev_preferred_link_mode) and
218 compile.linkage != .static)259 compile.linkage != .static)
219 {260 {
220 switch (system_lib.search_strategy) {261 switch (system_lib.search_strategy) {
221 .no_fallback => switch (system_lib.preferred_link_mode) {262 .no_fallback => switch (system_lib.preferred_link_mode) {
222 .dynamic => try zig_args.append(gpa, "-search_dylibs_only"),263 .dynamic => try zig_args.append(gpa, "-search_dylibs_only"),
223 .static => try zig_args.append(gpa, "-search_static_only"),264 .static => try zig_args.append(gpa, "-search_static_only"),
224 },265 },
225 .paths_first => switch (system_lib.preferred_link_mode) {266 .paths_first => switch (system_lib.preferred_link_mode) {
226 .dynamic => try zig_args.append(gpa, "-search_paths_first"),267 .dynamic => try zig_args.append(gpa, "-search_paths_first"),
227 .static => try zig_args.append(gpa, "-search_paths_first_static"),268 .static => try zig_args.append(gpa, "-search_paths_first_static"),
228 },269 },
229 .mode_first => switch (system_lib.preferred_link_mode) {270 .mode_first => switch (system_lib.preferred_link_mode) {
230 .dynamic => try zig_args.append(gpa, "-search_dylibs_first"),271 .dynamic => try zig_args.append(gpa, "-search_dylibs_first"),
231 .static => try zig_args.append(gpa, "-search_static_first"),272 .static => try zig_args.append(gpa, "-search_static_first"),
232 },273 },
233 }
234 prev_search_strategy = system_lib.search_strategy;
235 prev_preferred_link_mode = system_lib.preferred_link_mode;
236 }274 }
275 prev_search_strategy = system_lib.search_strategy;
276 prev_preferred_link_mode = system_lib.preferred_link_mode;
277 }
237278
238 const prefix: []const u8 = prefix: {279 const prefix: []const u8 = prefix: {
239 if (system_lib.needed) break :prefix "-needed-l";280 if (system_lib.needed) break :prefix "-needed-l";
240 if (system_lib.weak) break :prefix "-weak-l";281 if (system_lib.weak) break :prefix "-weak-l";
241 break :prefix "-l";282 break :prefix "-l";
242 };283 };
243 switch (system_lib.use_pkg_config) {284 switch (system_lib.use_pkg_config) {
244 .no => try zig_args.append(gpa, try allocPrint(arena, "{s}{s}", .{ prefix, system_lib.name })),285 .no => try zig_args.append(gpa, try allocPrint(arena, "{s}{s}", .{ prefix, system_lib.name })),
245 .yes, .force => {286 .yes, .force => {
246 if (compile.runPkgConfig(maker, system_lib.name)) |result| {287 if (compile.runPkgConfig(maker, system_lib.name)) |result| {
247 try zig_args.appendSlice(gpa, result.cflags);288 try zig_args.appendSlice(gpa, result.cflags);
248 try zig_args.appendSlice(gpa, result.libs);289 try zig_args.appendSlice(gpa, result.libs);
249 try seen_system_libs.put(arena, system_lib.name, result.cflags);290 try seen_system_libs.put(arena, system_lib.name, result.cflags);
250 } else |err| switch (err) {291 } else |err| switch (err) {
251 error.PkgConfigInvalidOutput,292 error.PkgConfigInvalidOutput,
252 error.PkgConfigCrashed,293 error.PkgConfigCrashed,
253 error.PkgConfigFailed,294 error.PkgConfigFailed,
254 error.PkgConfigNotInstalled,295 error.PkgConfigNotInstalled,
255 error.PackageNotFound,296 error.PackageNotFound,
256 => switch (system_lib.use_pkg_config) {297 => switch (system_lib.use_pkg_config) {
257 .yes => {298 .yes => {
258 // pkg-config failed, so fall back to linking the library299 // pkg-config failed, so fall back to linking the library
259 // by name directly.300 // by name directly.
260 try zig_args.append(gpa, try allocPrint(arena, "{s}{s}", .{301 try zig_args.append(gpa, try allocPrint(arena, "{s}{s}", .{
261 prefix,302 prefix,
262 system_lib.name,303 system_lib.name,
263 }));304 }));
264 },
265 .force => {
266 return step.fail("pkg-config failed for library {s}", .{system_lib.name});
267 },
268 .no => unreachable,
269 },305 },
306 .force => {
307 return step.fail(maker, "pkg-config failed for library {s}", .{system_lib.name});
308 },
309 .no => unreachable,
310 },
270311
271 else => |e| return e,312 else => |e| return e,
272 }313 }
273 },314 },
274 }315 }
275 },316 },
276 .other_step => |other| {317 .other_step => |other| {
277 switch (other.kind) {318 switch (other.kind) {
278 .exe => return step.fail("cannot link with an executable build artifact", .{}),319 .exe => return step.fail(maker, "cannot link with an executable build artifact", .{}),
279 .@"test" => return step.fail("cannot link with a test", .{}),320 .@"test" => return step.fail(maker, "cannot link with a test", .{}),
280 .obj, .test_obj => {321 .obj, .test_obj => {
281 const included_in_lib_or_obj = !my_responsibility and322 const included_in_lib_or_obj = !my_responsibility and
282 (dep_compile.kind == .lib or dep_compile.kind == .obj or dep_compile.kind == .test_obj);323 (dep_compile.kind == .lib or dep_compile.kind == .obj or dep_compile.kind == .test_obj);
283 if (!already_linked and !included_in_lib_or_obj) {324 if (!already_linked and !included_in_lib_or_obj) {
284 try zig_args.append(gpa, other.getEmittedBin().getPath2(step));325 try zig_args.append(gpa, other.getEmittedBin().getPath2(step));
285 total_linker_objects += 1;326 total_linker_objects += 1;
286 }327 }
287 },328 },
288 .lib => l: {329 .lib => l: {
289 const other_produces_implib = other.producesImplib();330 const other_produces_implib = other.producesImplib();
290 const other_is_static = other_produces_implib or other.isStaticLibrary();331 const other_is_static = other_produces_implib or other.isStaticLibrary();
291332
292 if (compile.isStaticLibrary() and other_is_static) {333 if (compile.isStaticLibrary() and other_is_static) {
293 // Avoid putting a static library inside a static library.334 // Avoid putting a static library inside a static library.
294 break :l;335 break :l;
295 }336 }
296337
297 // For DLLs, we must link against the implib.338 // For DLLs, we must link against the implib.
298 // For everything else, we directly link339 // For everything else, we directly link
299 // against the library file.340 // against the library file.
300 const full_path_lib = if (other_produces_implib)341 const full_path_lib = if (other_produces_implib)
301 try other.getGeneratedFilePath("generated_implib", &compile.step)342 try other.getGeneratedFilePath("generated_implib", &compile.step)
302 else343 else
303 try other.getGeneratedFilePath("generated_bin", &compile.step);344 try other.getGeneratedFilePath("generated_bin", &compile.step);
304345
305 try zig_args.append(gpa, full_path_lib);346 try zig_args.append(gpa, full_path_lib);
306 total_linker_objects += 1;347 total_linker_objects += 1;
307348
308 if (other.linkage == .dynamic and349 if (other.linkage == .dynamic and
309 compile.rootModuleTarget().os.tag != .windows)350 compile.rootModuleTarget().os.tag != .windows)
310 {351 {
311 if (Dir.path.dirname(full_path_lib)) |dirname| {352 if (Dir.path.dirname(full_path_lib)) |dirname| {
312 try zig_args.append(gpa, "-rpath");353 try zig_args.append(gpa, "-rpath");
313 try zig_args.append(gpa, dirname);354 try zig_args.append(gpa, dirname);
314 }
315 }355 }
316 },356 }
317 }357 },
318 },358 }
319 .assembly_file => |asm_file| l: {359 },
320 if (!my_responsibility) break :l;360 .assembly_file => |asm_file| l: {
361 if (!my_responsibility) break :l;
321362
322 if (prev_has_cflags) {363 if (prev_has_cflags) {
323 try zig_args.append(gpa, "-cflags");364 try zig_args.append(gpa, "-cflags");
324 try zig_args.append(gpa, "--");365 try zig_args.append(gpa, "--");
325 prev_has_cflags = false;366 prev_has_cflags = false;
326 }367 }
327 try zig_args.append(gpa, asm_file.getPath2(mod.owner, step));368 try zig_args.append(gpa, asm_file.getPath2(mod.owner, step));
328 total_linker_objects += 1;369 total_linker_objects += 1;
329 },370 },
330371
331 .c_source_file => |c_source_file| l: {372 .c_source_file => |c_source_file| l: {
332 if (!my_responsibility) break :l;373 if (!my_responsibility) break :l;
333374
334 if (prev_has_cflags or c_source_file.flags.len != 0) {375 if (prev_has_cflags or c_source_file.flags.len != 0) {
335 try zig_args.append(gpa, "-cflags");376 try zig_args.append(gpa, "-cflags");
336 for (c_source_file.flags) |arg| {377 for (c_source_file.flags) |arg| {
337 try zig_args.append(gpa, arg);378 try zig_args.append(gpa, arg);
338 }
339 try zig_args.append(gpa, "--");
340 }379 }
341 prev_has_cflags = (c_source_file.flags.len != 0);380 try zig_args.append(gpa, "--");
381 }
382 prev_has_cflags = (c_source_file.flags.len != 0);
342383
343 if (c_source_file.language) |lang| {384 if (c_source_file.language) |lang| {
344 try zig_args.append(gpa, "-x");385 try zig_args.append(gpa, "-x");
345 try zig_args.append(gpa, lang.internalIdentifier());386 try zig_args.append(gpa, lang.internalIdentifier());
346 }387 }
347388
348 try zig_args.append(gpa, c_source_file.file.getPath2(mod.owner, step));389 try zig_args.append(gpa, c_source_file.file.getPath2(mod.owner, step));
349390
350 if (c_source_file.language != null) {391 if (c_source_file.language != null) {
351 try zig_args.append(gpa, "-x");392 try zig_args.append(gpa, "-x");
352 try zig_args.append(gpa, "none");393 try zig_args.append(gpa, "none");
353 }394 }
354 total_linker_objects += 1;395 total_linker_objects += 1;
355 },396 },
356397
357 .c_source_files => |c_source_files| l: {398 .c_source_files => |c_source_files| l: {
358 if (!my_responsibility) break :l;399 if (!my_responsibility) break :l;
359400
360 if (prev_has_cflags or c_source_files.flags.len != 0) {401 if (prev_has_cflags or c_source_files.flags.len != 0) {
361 try zig_args.append(gpa, "-cflags");402 try zig_args.append(gpa, "-cflags");
362 for (c_source_files.flags) |arg| {403 for (c_source_files.flags) |arg| {
363 try zig_args.append(gpa, arg);404 try zig_args.append(gpa, arg);
364 }
365 try zig_args.append(gpa, "--");
366 }405 }
367 prev_has_cflags = (c_source_files.flags.len != 0);406 try zig_args.append(gpa, "--");
407 }
408 prev_has_cflags = (c_source_files.flags.len != 0);
368409
369 if (c_source_files.language) |lang| {410 if (c_source_files.language) |lang| {
370 try zig_args.append(gpa, "-x");411 try zig_args.append(gpa, "-x");
371 try zig_args.append(gpa, lang.internalIdentifier());412 try zig_args.append(gpa, lang.internalIdentifier());
372 }413 }
373414
374 const root_path = c_source_files.root.getPath2(mod.owner, step);415 const root_path = c_source_files.root.getPath2(mod.owner, step);
375 for (c_source_files.files) |file| {416 for (c_source_files.files) |file| {
376 try zig_args.append(gpa, try Dir.path.join(arena, &.{ root_path, file }));417 try zig_args.append(gpa, try Dir.path.join(arena, &.{ root_path, file }));
377 }418 }
378419
379 if (c_source_files.language != null) {420 if (c_source_files.language != null) {
380 try zig_args.append(gpa, "-x");421 try zig_args.append(gpa, "-x");
381 try zig_args.append(gpa, "none");422 try zig_args.append(gpa, "none");
382 }423 }
383424
384 total_linker_objects += c_source_files.files.len;425 total_linker_objects += c_source_files.files.len;
385 },426 },
386427
387 .win32_resource_file => |rc_source_file| l: {428 .win32_resource_file => |rc_source_file| l: {
388 if (!my_responsibility) break :l;429 if (!my_responsibility) break :l;
389430
390 if (rc_source_file.flags.len == 0 and rc_source_file.include_paths.len == 0) {431 if (rc_source_file.flags.len == 0 and rc_source_file.include_paths.len == 0) {
391 if (prev_has_rcflags) {432 if (prev_has_rcflags) {
392 try zig_args.append(gpa, "-rcflags");
393 try zig_args.append(gpa, "--");
394 prev_has_rcflags = false;
395 }
396 } else {
397 try zig_args.append(gpa, "-rcflags");433 try zig_args.append(gpa, "-rcflags");
398 for (rc_source_file.flags) |arg| {
399 try zig_args.append(gpa, arg);
400 }
401 for (rc_source_file.include_paths) |include_path| {
402 try zig_args.append(gpa, "/I");
403 try zig_args.append(gpa, include_path.getPath2(mod.owner, step));
404 }
405 try zig_args.append(gpa, "--");434 try zig_args.append(gpa, "--");
406 prev_has_rcflags = true;435 prev_has_rcflags = false;
407 }436 }
408 try zig_args.append(gpa, rc_source_file.file.getPath2(mod.owner, step));437 } else {
409 total_linker_objects += 1;438 try zig_args.append(gpa, "-rcflags");
410 },439 for (rc_source_file.flags) |arg| {
411 }440 try zig_args.append(gpa, arg);
412 }441 }
442 for (rc_source_file.include_paths) |include_path| {
443 try zig_args.append(gpa, "/I");
444 try zig_args.append(gpa, include_path.getPath2(mod.owner, step));
445 }
446 try zig_args.append(gpa, "--");
447 prev_has_rcflags = true;
448 }
449 try zig_args.append(gpa, rc_source_file.file.getPath2(mod.owner, step));
450 total_linker_objects += 1;
451 },
452 };
413453
414 // We need to emit the --mod argument here so that the above link objects454 // We need to emit the --mod argument here so that the above link objects
415 // have the correct parent module, but only if the module is part of455 // have the correct parent module, but only if the module is part of
...@@ -450,48 +490,47 @@ fn lowerZigArgs(...@@ -450,48 +490,47 @@ fn lowerZigArgs(
450 }490 }
451491
452 if (total_linker_objects == 0) {492 if (total_linker_objects == 0) {
453 return step.fail("the linker needs one or more objects to link", .{});493 return step.fail(maker, "the linker needs one or more objects to link", .{});
454 }494 }
455495
456 for (frameworks.keys(), frameworks.values()) |name, info| {496 for (frameworks.keys(), frameworks.values()) |name, info| {
497 try zig_args.ensureUnusedCapacity(gpa, 2);
457 if (info.needed) {498 if (info.needed) {
458 try zig_args.append(gpa, "-needed_framework");499 zig_args.appendAssumeCapacity("-needed_framework");
459 } else if (info.weak) {500 } else if (info.weak) {
460 try zig_args.append(gpa, "-weak_framework");501 zig_args.appendAssumeCapacity("-weak_framework");
461 } else {502 } else {
462 try zig_args.append(gpa, "-framework");503 zig_args.appendAssumeCapacity("-framework");
463 }504 }
464 try zig_args.append(gpa, name);505 zig_args.appendAssumeCapacity(name.slice(conf));
465 }506 }
466507
467 if (is_linking_libcpp) {508 try zig_args.ensureUnusedCapacity(gpa, 2);
468 try zig_args.append(gpa, "-lc++");509 if (is_linking_libcpp) zig_args.appendAssumeCapacity("-lc++");
469 }510 if (is_linking_libc) zig_args.appendAssumeCapacity("-lc");
470
471 if (is_linking_libc) {
472 try zig_args.append(gpa, "-lc");
473 }
474 }511 }
475512
476 if (compile.win32_manifest) |manifest_file| {513 if (true) @panic("TODO");
514
515 if (conf_comp.win32_manifest) |manifest_file| {
477 try zig_args.append(gpa, manifest_file.getPath2(step));516 try zig_args.append(gpa, manifest_file.getPath2(step));
478 }517 }
479518
480 if (compile.win32_module_definition) |module_file| {519 if (conf_comp.win32_module_definition) |module_file| {
481 try zig_args.append(gpa, module_file.getPath2(step));520 try zig_args.append(gpa, module_file.getPath2(step));
482 }521 }
483522
484 if (compile.image_base) |image_base| {523 if (conf_comp.image_base) |image_base| {
485 try zig_args.appendSlice(gpa, &.{524 try zig_args.appendSlice(gpa, &.{
486 "--image-base", try allocPrint(arena, "0x{x}", .{image_base}),525 "--image-base", try allocPrint(arena, "0x{x}", .{image_base}),
487 });526 });
488 }527 }
489528
490 for (compile.filters) |filter| {529 for (conf_comp.filters) |filter| {
491 try zig_args.appendSlice(gpa, &.{ "--test-filter", filter });530 try zig_args.appendSlice(gpa, &.{ "--test-filter", filter });
492 }531 }
493532
494 if (compile.test_runner) |test_runner| {533 if (conf_comp.test_runner) |test_runner| {
495 try zig_args.appendSlice(gpa, &.{ "--test-runner", test_runner.path.getPath2(step) });534 try zig_args.appendSlice(gpa, &.{ "--test-runner", test_runner.path.getPath2(step) });
496 }535 }
497536
...@@ -503,8 +542,8 @@ fn lowerZigArgs(...@@ -503,8 +542,8 @@ fn lowerZigArgs(
503 try addBool(gpa, zig_args, "--debug-incremental", graph.debug_incremental);542 try addBool(gpa, zig_args, "--debug-incremental", graph.debug_incremental);
504 try addBool(gpa, zig_args, "--verbose-air", graph.verbose_air);543 try addBool(gpa, zig_args, "--verbose-air", graph.verbose_air);
505 try addBool(gpa, zig_args, "--verbose-llvm-ir", graph.verbose_llvm_ir);544 try addBool(gpa, zig_args, "--verbose-llvm-ir", graph.verbose_llvm_ir);
506 try addBool(gpa, zig_args, "--verbose-link", graph.verbose_link or compile.verbose_link);545 try addBool(gpa, zig_args, "--verbose-link", graph.verbose_link or conf_comp.flags.verbose_link);
507 try addBool(gpa, zig_args, "--verbose-cc", graph.verbose_cc or compile.verbose_cc);546 try addBool(gpa, zig_args, "--verbose-cc", graph.verbose_cc or conf_comp.flags.verbose_cc);
508 try addBool(gpa, zig_args, "--verbose-llvm-cpu-features", graph.verbose_llvm_cpu_features);547 try addBool(gpa, zig_args, "--verbose-llvm-cpu-features", graph.verbose_llvm_cpu_features);
509 try addBool(gpa, zig_args, "--time-report", graph.time_report);548 try addBool(gpa, zig_args, "--time-report", graph.time_report);
510549
...@@ -516,49 +555,49 @@ fn lowerZigArgs(...@@ -516,49 +555,49 @@ fn lowerZigArgs(
516 if (compile.generated_llvm_ir != null) try zig_args.append(gpa, "-femit-llvm-ir");555 if (compile.generated_llvm_ir != null) try zig_args.append(gpa, "-femit-llvm-ir");
517 if (compile.generated_h != null) try zig_args.append(gpa, "-femit-h");556 if (compile.generated_h != null) try zig_args.append(gpa, "-femit-h");
518557
519 try addFlag(gpa, zig_args, "formatted-panics", compile.formatted_panics);558 try addFlag(gpa, zig_args, "formatted-panics", conf_comp.flags.formatted_panics);
520559
521 switch (compile.compress_debug_sections) {560 switch (conf_comp.compress_debug_sections) {
522 .none => {},561 .none => {},
523 .zlib => try zig_args.append(gpa, "--compress-debug-sections=zlib"),562 .zlib => try zig_args.append(gpa, "--compress-debug-sections=zlib"),
524 .zstd => try zig_args.append(gpa, "--compress-debug-sections=zstd"),563 .zstd => try zig_args.append(gpa, "--compress-debug-sections=zstd"),
525 }564 }
526565
527 if (compile.link_eh_frame_hdr) {566 if (conf_comp.flags.link_eh_frame_hdr) {
528 try zig_args.append(gpa, "--eh-frame-hdr");567 try zig_args.append(gpa, "--eh-frame-hdr");
529 }568 }
530 if (compile.link_emit_relocs) {569 if (conf_comp.flags.link_emit_relocs) {
531 try zig_args.append(gpa, "--emit-relocs");570 try zig_args.append(gpa, "--emit-relocs");
532 }571 }
533 if (compile.link_function_sections) {572 if (conf_comp.flags.link_function_sections) {
534 try zig_args.append(gpa, "-ffunction-sections");573 try zig_args.append(gpa, "-ffunction-sections");
535 }574 }
536 if (compile.link_data_sections) {575 if (conf_comp.flags.link_data_sections) {
537 try zig_args.append(gpa, "-fdata-sections");576 try zig_args.append(gpa, "-fdata-sections");
538 }577 }
539 if (compile.link_gc_sections) |x| {578 if (conf_comp.flags.link_gc_sections) |x| {
540 try zig_args.append(gpa, if (x) "--gc-sections" else "--no-gc-sections");579 try zig_args.append(gpa, if (x) "--gc-sections" else "--no-gc-sections");
541 }580 }
542 if (!compile.linker_dynamicbase) {581 if (!conf_comp.flags.linker_dynamicbase) {
543 try zig_args.append(gpa, "--no-dynamicbase");582 try zig_args.append(gpa, "--no-dynamicbase");
544 }583 }
545 if (compile.linker_allow_shlib_undefined) |x| {584 if (conf_comp.flags.linker_allow_shlib_undefined) |x| {
546 try zig_args.append(gpa, if (x) "-fallow-shlib-undefined" else "-fno-allow-shlib-undefined");585 try zig_args.append(gpa, if (x) "-fallow-shlib-undefined" else "-fno-allow-shlib-undefined");
547 }586 }
548 if (compile.link_z_notext) try zig_args.appendSlice(gpa, &.{ "-z", "notext" });587 if (conf_comp.flags.link_z_notext) try zig_args.appendSlice(gpa, &.{ "-z", "notext" });
549 if (!compile.link_z_relro) try zig_args.appendSlice(gpa, &.{ "-z", "norelro" });588 if (!conf_comp.flags.link_z_relro) try zig_args.appendSlice(gpa, &.{ "-z", "norelro" });
550 if (compile.link_z_lazy) try zig_args.appendSlice(gpa, &.{ "-z", "lazy" });589 if (conf_comp.flags.link_z_lazy) try zig_args.appendSlice(gpa, &.{ "-z", "lazy" });
551 if (compile.link_z_common_page_size) |size| try zig_args.appendSlice(gpa, &.{590 if (conf_comp.flags.link_z_common_page_size) |size| try zig_args.appendSlice(gpa, &.{
552 "-z",591 "-z",
553 try allocPrint(arena, "common-page-size={d}", .{size}),592 try allocPrint(arena, "common-page-size={d}", .{size}),
554 });593 });
555 if (compile.link_z_max_page_size) |size| try zig_args.appendSlice(gpa, &.{594 if (conf_comp.flags.link_z_max_page_size) |size| try zig_args.appendSlice(gpa, &.{
556 "-z",595 "-z",
557 try allocPrint(arena, "max-page-size={d}", .{size}),596 try allocPrint(arena, "max-page-size={d}", .{size}),
558 });597 });
559 if (compile.link_z_defs) try zig_args.appendSlice(gpa, &.{ "-z", "defs" });598 if (conf_comp.flags.link_z_defs) try zig_args.appendSlice(gpa, &.{ "-z", "defs" });
560599
561 if (compile.libc_file) |libc_file| {600 if (conf_comp.flags.libc_file) |libc_file| {
562 try zig_args.appendSlice(gpa, &.{ "--libc", libc_file.getPath2(step) });601 try zig_args.appendSlice(gpa, &.{ "--libc", libc_file.getPath2(step) });
563 } else if (graph.libc_file) |libc_file| {602 } else if (graph.libc_file) |libc_file| {
564 try zig_args.appendSlice(gpa, &.{ "--libc", libc_file });603 try zig_args.appendSlice(gpa, &.{ "--libc", libc_file });
...@@ -573,18 +612,16 @@ fn lowerZigArgs(...@@ -573,18 +612,16 @@ fn lowerZigArgs(
573 if (graph.debug_compiler_runtime_libs) |mode|612 if (graph.debug_compiler_runtime_libs) |mode|
574 try zig_args.append(gpa, try allocPrint(arena, "--debug-rt={t}", .{mode}));613 try zig_args.append(gpa, try allocPrint(arena, "--debug-rt={t}", .{mode}));
575614
576 try zig_args.append(gpa, "--name");615 try zig_args.appendSlice(gpa, &.{ "--name", conf_comp.root_name.slice(conf) });
577 try zig_args.append(gpa, compile.name);
578616
579 if (compile.linkage) |some| switch (some) {617 if (compile.linkage) |some| switch (some) {
580 .dynamic => try zig_args.append(gpa, "-dynamic"),618 .dynamic => try zig_args.append(gpa, "-dynamic"),
581 .static => try zig_args.append(gpa, "-static"),619 .static => try zig_args.append(gpa, "-static"),
582 };620 };
583 if (compile.kind == .lib and compile.linkage != null and compile.linkage.? == .dynamic) {621 if (compile.kind == .lib and compile.linkage != null and compile.linkage.? == .dynamic) {
584 if (compile.version) |version| {622 if (compile.version) |version| try zig_args.appendSlice(gpa, &.{
585 try zig_args.append(gpa, "--version");623 "--version", try allocPrint(arena, "{f}", .{version}),
586 try zig_args.append(gpa, try allocPrint(arena, "{f}", .{version}));624 });
587 }
588625
589 if (compile.rootModuleTarget().os.tag.isDarwin()) {626 if (compile.rootModuleTarget().os.tag.isDarwin()) {
590 const install_name = compile.install_name orelse try allocPrint(arena, "@rpath/{s}{s}{s}", .{627 const install_name = compile.install_name orelse try allocPrint(arena, "@rpath/{s}{s}{s}", .{
...@@ -696,7 +733,7 @@ fn lowerZigArgs(...@@ -696,7 +733,7 @@ fn lowerZigArgs(
696733
697 for (graph.search_prefixes.items) |search_prefix| {734 for (graph.search_prefixes.items) |search_prefix| {
698 var prefix_dir = cwd.openDir(io, search_prefix, .{}) catch |err| {735 var prefix_dir = cwd.openDir(io, search_prefix, .{}) catch |err| {
699 return step.fail("unable to open prefix directory '{s}': {t}", .{ search_prefix, err });736 return step.fail(maker, "unable to open prefix directory '{s}': {t}", .{ search_prefix, err });
700 };737 };
701 defer prefix_dir.close(io);738 defer prefix_dir.close(io);
702739
...@@ -710,7 +747,7 @@ fn lowerZigArgs(...@@ -710,7 +747,7 @@ fn lowerZigArgs(
710 });747 });
711 } else |err| switch (err) {748 } else |err| switch (err) {
712 error.FileNotFound => {},749 error.FileNotFound => {},
713 else => |e| return step.fail("unable to access '{s}/lib' directory: {t}", .{ search_prefix, e }),750 else => |e| return step.fail(maker, "unable to access '{s}/lib' directory: {t}", .{ search_prefix, e }),
714 }751 }
715752
716 if (prefix_dir.access(io, "include", .{})) |_| {753 if (prefix_dir.access(io, "include", .{})) |_| {
...@@ -719,7 +756,7 @@ fn lowerZigArgs(...@@ -719,7 +756,7 @@ fn lowerZigArgs(
719 });756 });
720 } else |err| switch (err) {757 } else |err| switch (err) {
721 error.FileNotFound => {},758 error.FileNotFound => {},
722 else => |e| return step.fail("unable to access '{s}/include' directory: {t}", .{ search_prefix, e }),759 else => |e| return step.fail(maker, "unable to access '{s}/include' directory: {t}", .{ search_prefix, e }),
723 }760 }
724 }761 }
725762
...@@ -825,13 +862,13 @@ fn lowerZigArgs(...@@ -825,13 +862,13 @@ fn lowerZigArgs(
825 var af = graph.cache_root.handle.createFileAtomic(io, args_file, .{862 var af = graph.cache_root.handle.createFileAtomic(io, args_file, .{
826 .replace = false,863 .replace = false,
827 .make_path = true,864 .make_path = true,
828 }) catch |e| return step.fail("failed creating tmp args file {f}{s}: {t}", .{865 }) catch |e| return step.fail(maker, "failed creating tmp args file {f}{s}: {t}", .{
829 graph.cache_root, args_file, e,866 graph.cache_root, args_file, e,
830 });867 });
831 defer af.deinit(io);868 defer af.deinit(io);
832869
833 af.file.writeStreamingAll(io, args) catch |e| {870 af.file.writeStreamingAll(io, args) catch |e| {
834 return step.fail("failed writing args data to tmp file {f}{s}: {t}", .{871 return step.fail(maker, "failed writing args data to tmp file {f}{s}: {t}", .{
835 graph.cache_root, args_file, e,872 graph.cache_root, args_file, e,
836 });873 });
837 };874 };
...@@ -842,7 +879,7 @@ fn lowerZigArgs(...@@ -842,7 +879,7 @@ fn lowerZigArgs(
842 error.PathAlreadyExists => {879 error.PathAlreadyExists => {
843 // The args file was created by another concurrent build process.880 // The args file was created by another concurrent build process.
844 },881 },
845 else => |other_err| return step.fail("failed linking tmp file {f}{s}: {t}", .{882 else => |other_err| return step.fail(maker, "failed linking tmp file {f}{s}: {t}", .{
846 graph.cache_root, args_file, other_err,883 graph.cache_root, args_file, other_err,
847 }),884 }),
848 };885 };
...@@ -899,14 +936,14 @@ pub fn doAtomicSymLinks(...@@ -899,14 +936,14 @@ pub fn doAtomicSymLinks(
899 const major_only_path = try Dir.path.join(arena, &.{ out_dir, filename_major_only });936 const major_only_path = try Dir.path.join(arena, &.{ out_dir, filename_major_only });
900 const cwd: Io.Dir = .cwd();937 const cwd: Io.Dir = .cwd();
901 cwd.symLinkAtomic(io, out_basename, major_only_path, .{}) catch |err| {938 cwd.symLinkAtomic(io, out_basename, major_only_path, .{}) catch |err| {
902 return step.fail("unable to symlink {s} -> {s}: {t}", .{939 return step.fail(maker, "unable to symlink {s} -> {s}: {t}", .{
903 major_only_path, out_basename, err,940 major_only_path, out_basename, err,
904 });941 });
905 };942 };
906 // sym link for libfoo.so to libfoo.so.1943 // sym link for libfoo.so to libfoo.so.1
907 const name_only_path = try Dir.path.join(arena, &.{ out_dir, filename_name_only });944 const name_only_path = try Dir.path.join(arena, &.{ out_dir, filename_name_only });
908 cwd.symLinkAtomic(io, filename_major_only, name_only_path, .{}) catch |err| {945 cwd.symLinkAtomic(io, filename_major_only, name_only_path, .{}) catch |err| {
909 return step.fail("unable to symlink {s} -> {s}: {t}", .{946 return step.fail(maker, "unable to symlink {s} -> {s}: {t}", .{
910 name_only_path, filename_major_only, err,947 name_only_path, filename_major_only, err,
911 });948 });
912 };949 };
...@@ -1080,7 +1117,7 @@ fn runPkgConfig(compile: *Compile, maker: *Maker, lib_name: []const u8) !PkgConf...@@ -1080,7 +1117,7 @@ fn runPkgConfig(compile: *Compile, maker: *Maker, lib_name: []const u8) !PkgConf
1080 } else if (mem.startsWith(u8, arg, wl_rpath_prefix)) {1117 } else if (mem.startsWith(u8, arg, wl_rpath_prefix)) {
1081 try zig_cflags.appendSlice(arena, &.{ "-rpath", arg[wl_rpath_prefix.len..] });1118 try zig_cflags.appendSlice(arena, &.{ "-rpath", arg[wl_rpath_prefix.len..] });
1082 } else if (b.debug_pkg_config) {1119 } else if (b.debug_pkg_config) {
1083 return compile.step.fail("unknown pkg-config flag '{s}'", .{arg});1120 return compile.step.fail(maker, "unknown pkg-config flag '{s}'", .{arg});
1084 }1121 }
1085 }1122 }
10861123
...@@ -1093,7 +1130,7 @@ fn runPkgConfig(compile: *Compile, maker: *Maker, lib_name: []const u8) !PkgConf...@@ -1093,7 +1130,7 @@ fn runPkgConfig(compile: *Compile, maker: *Maker, lib_name: []const u8) !PkgConf
1093 };1130 };
1094}1131}
10951132
1096fn checkCompileErrors(compile: *Compile) !void {1133fn checkCompileErrors(compile: *Compile, maker: *Maker) !void {
1097 // Clear this field so that it does not get printed by the build runner.1134 // Clear this field so that it does not get printed by the build runner.
1098 const actual_eb = compile.step.result_error_bundle;1135 const actual_eb = compile.step.result_error_bundle;
1099 compile.step.result_error_bundle = .empty;1136 compile.step.result_error_bundle = .empty;
...@@ -1120,7 +1157,7 @@ fn checkCompileErrors(compile: *Compile) !void {...@@ -1120,7 +1157,7 @@ fn checkCompileErrors(compile: *Compile) !void {
1120 switch (expect_errors) {1157 switch (expect_errors) {
1121 .starts_with => |expect_starts_with| {1158 .starts_with => |expect_starts_with| {
1122 if (std.mem.startsWith(u8, actual_errors, expect_starts_with)) return;1159 if (std.mem.startsWith(u8, actual_errors, expect_starts_with)) return;
1123 return compile.step.fail(1160 return compile.step.fail(maker,
1124 \\1161 \\
1125 \\========= should start with: ============1162 \\========= should start with: ============
1126 \\{s}1163 \\{s}
...@@ -1135,7 +1172,7 @@ fn checkCompileErrors(compile: *Compile) !void {...@@ -1135,7 +1172,7 @@ fn checkCompileErrors(compile: *Compile) !void {
1135 return;1172 return;
1136 }1173 }
11371174
1138 return compile.step.fail(1175 return compile.step.fail(maker,
1139 \\1176 \\
1140 \\========= should contain: ===============1177 \\========= should contain: ===============
1141 \\{s}1178 \\{s}
...@@ -1158,7 +1195,7 @@ fn checkCompileErrors(compile: *Compile) !void {...@@ -1158,7 +1195,7 @@ fn checkCompileErrors(compile: *Compile) !void {
1158 return;1195 return;
1159 }1196 }
11601197
1161 return compile.step.fail(1198 return compile.step.fail(maker,
1162 \\1199 \\
1163 \\========= should contain: ===============1200 \\========= should contain: ===============
1164 \\{s}1201 \\{s}
...@@ -1185,7 +1222,7 @@ fn checkCompileErrors(compile: *Compile) !void {...@@ -1185,7 +1222,7 @@ fn checkCompileErrors(compile: *Compile) !void {
11851222
1186 if (mem.eql(u8, expected_generated.items, actual_errors)) return;1223 if (mem.eql(u8, expected_generated.items, actual_errors)) return;
11871224
1188 return compile.step.fail(1225 return compile.step.fail(maker,
1189 \\1226 \\
1190 \\========= expected: =====================1227 \\========= expected: =====================
1191 \\{s}1228 \\{s}
...@@ -1222,42 +1259,109 @@ fn moduleNeedsCliArg(mod: *const Module) bool {...@@ -1222,42 +1259,109 @@ fn moduleNeedsCliArg(mod: *const Module) bool {
1222}1259}
12231260
1224const CliNamedModules = struct {1261const CliNamedModules = struct {
1225 modules: std.AutoArrayHashMapUnmanaged(*Module, void),1262 modules: std.AutoArrayHashMapUnmanaged(Configuration.Module.Index, void),
1226 names: std.StringArrayHashMapUnmanaged(void),1263 names: std.StringArrayHashMapUnmanaged(void),
12271264
1228 /// Traverse the whole dependency graph and give every module a unique1265 /// Traverse the whole dependency graph and give every module a unique
1229 /// name, ideally one named after what it's called somewhere in the graph.1266 /// name, ideally one named after what it's called somewhere in the graph.
1230 /// It will help here to have both a mapping from module to name and a set1267 /// It will help here to have both a mapping from module to name and a set
1231 /// of all the currently-used names.1268 /// of all the currently-used names.
1232 fn init(arena: Allocator, root_module: *Module) Allocator.Error!CliNamedModules {1269 fn init(
1233 var compile: CliNamedModules = .{1270 arena: Allocator,
1271 module_graph: *ModuleGraph,
1272 compile_index: Configuration.Step.Index,
1273 maker: *const Maker,
1274 ) Allocator.Error!CliNamedModules {
1275 const conf = &maker.scanned_config.configuration;
1276 const conf_compile = compile_index.ptr(conf).extended.get(conf.extra).compile;
1277
1278 var result: CliNamedModules = .{
1234 .modules = .{},1279 .modules = .{},
1235 .names = .{},1280 .names = .{},
1236 };1281 };
1237 const graph = root_module.getGraph();1282 const modules = try getModuleList(arena, module_graph, conf_compile.root_module, conf);
1238 {1283 {
1239 assert(graph.modules[0] == root_module);1284 assert(conf_compile.root_module == modules.keys()[0]);
1240 try compile.modules.put(arena, root_module, {});1285 try result.modules.put(arena, conf_compile.root_module, {});
1241 try compile.names.put(arena, "root", {});1286 try result.names.put(arena, "root", {});
1242 }1287 }
1243 for (graph.modules[1..], graph.names[1..]) |mod, orig_name| {1288 for (modules.keys()[1..], modules.values()[1..]) |mod, orig_name| {
1244 var name = orig_name;1289 const orig_name_slice = orig_name.slice(conf);
1290 var name: []const u8 = orig_name_slice;
1245 var n: usize = 0;1291 var n: usize = 0;
1246 while (true) {1292 while (true) {
1247 const gop = try compile.names.getOrPut(arena, name);1293 const gop = try result.names.getOrPut(arena, name);
1248 if (!gop.found_existing) {1294 if (!gop.found_existing) {
1249 try compile.modules.putNoClobber(arena, mod, {});1295 try result.modules.putNoClobber(arena, mod, {});
1250 break;1296 break;
1251 }1297 }
1252 name = try allocPrint(arena, "{s}{d}", .{ orig_name, n });1298 name = try allocPrint(arena, "{s}{d}", .{ orig_name_slice, n });
1253 n += 1;1299 n += 1;
1254 }1300 }
1255 }1301 }
1256 return compile;1302 return result;
1257 }1303 }
1258};1304};
12591305
1260fn getCompileDependencies(chase_dynamic: bool) void {1306fn getCompileDependencies(
1261 _ = chase_dynamic;1307 arena: Allocator,
1262 @panic("TODO");1308 module_graph: *ModuleGraph,
1309 conf: *const Configuration,
1310 start: Configuration.Step.Index,
1311 chase_dynamic: bool,
1312) ![]const Configuration.Step.Index {
1313 var compiles: std.AutoArrayHashMapUnmanaged(Configuration.Step.Index, void) = .empty;
1314 var compiles_i: usize = 0;
1315
1316 try compiles.putNoClobber(arena, start, {});
1317
1318 while (compiles_i < compiles.count()) : (compiles_i += 1) {
1319 const step = compiles.keys()[compiles_i].ptr(conf);
1320 const compile = step.extended.get(conf.extra).compile;
1321 const modules = try getModuleList(arena, module_graph, compile.root_module, conf);
1322
1323 for (modules.keys()) |mod_index| {
1324 const mod = mod_index.get(conf);
1325 for (0..mod.link_objects.len) |i| {
1326 switch (mod.link_objects.get(conf.extra, i)) {
1327 .other_step => |other_compile_index| {
1328 const other_compile = other_compile_index.ptr(conf).extended.get(conf.extra).compile;
1329 if (!chase_dynamic and other_compile.isDynamicLibrary()) continue;
1330 try compiles.put(arena, other_compile_index, {});
1331 },
1332 else => {},
1333 }
1334 }
1335 }
1336 }
1337
1338 return compiles.keys();
1339}
1340
1341/// Returned pointer expires upon next call to `getModuleList`.
1342fn getModuleList(
1343 arena: Allocator,
1344 module_graph: *ModuleGraph,
1345 root_module: Configuration.Module.Index,
1346 conf: *const Configuration,
1347) !*ModuleList {
1348 const gop = try module_graph.getOrPutAdapted(arena, root_module, @as(ModuleListContext.Adapter, .{}));
1349 const modules = gop.key_ptr;
1350
1351 if (gop.found_existing) return modules;
1352 modules.* = .empty;
1353 try modules.putNoClobber(arena, root_module, .root);
1354
1355 var i: usize = 0;
1356
1357 while (i < modules.entries.len) : (i += 1) {
1358 const dep_index = modules.keys()[i];
1359 const dep = dep_index.get(conf);
1360 const imports = dep.import_table.get(conf).imports;
1361 try modules.ensureUnusedCapacity(arena, imports.mal.len);
1362 for (imports.mal.items(.name), imports.mal.items(.module)) |import_name, other_mod|
1363 modules.putAssumeCapacity(other_mod, import_name);
1364 }
1365
1366 return modules;
1263}1367}
lib/compiler/configurer.zig+1
...@@ -202,6 +202,7 @@ pub fn main(init: process.Init.Minimal) !void {...@@ -202,6 +202,7 @@ pub fn main(init: process.Init.Minimal) !void {
202 var wc: Configuration.Wip = .init(gpa);202 var wc: Configuration.Wip = .init(gpa);
203 defer wc.deinit();203 defer wc.deinit();
204 assert(try wc.addString("") == .empty);204 assert(try wc.addString("") == .empty);
205 assert(try wc.addString("root") == .root);
205206
206 try serializeSystemIntegrationOptions(&graph, &wc);207 try serializeSystemIntegrationOptions(&graph, &wc);
207208
lib/std/Build/Module.zig+3-5
...@@ -668,11 +668,9 @@ pub const Graph = struct {...@@ -668,11 +668,9 @@ pub const Graph = struct {
668 names: []const []const u8,668 names: []const []const u8,
669};669};
670670
671/// Intended to be used during the make phase only.671/// Given that `root` is the root `Module` of a compilation, return all
672///672/// `Module` in the module graph, including `root` itself. `root` is guaranteed
673/// Given that `root` is the root `Module` of a compilation, return all `Module`s673/// to be the first module in the returned slice.
674/// in the module graph, including `root` itself. `root` is guaranteed to be the
675/// first module in the returned slice.
676pub fn getGraph(root: *Module) Graph {674pub fn getGraph(root: *Module) Graph {
677 if (root.cached_graph.modules.len != 0) {675 if (root.cached_graph.modules.len != 0) {
678 return root.cached_graph;676 return root.cached_graph;
lib/std/zig/Configuration.zig+27-4
...@@ -859,6 +859,10 @@ pub const Step = extern struct {...@@ -859,6 +859,10 @@ pub const Step = extern struct {
859 version_script: bool,859 version_script: bool,
860 _: u18 = 0,860 _: u18 = 0,
861 };861 };
862
863 pub fn isDynamicLibrary(compile: *const Compile) bool {
864 return compile.flags3.kind == .lib and compile.flags2.linkage == .dynamic;
865 }
862 };866 };
863867
864 pub const CheckFile = struct {868 pub const CheckFile = struct {
...@@ -1243,6 +1247,13 @@ pub const ImportTable = struct {...@@ -1243,6 +1247,13 @@ pub const ImportTable = struct {
1243 pub const Index = enum(u32) {1247 pub const Index = enum(u32) {
1244 invalid = maxInt(u32),1248 invalid = maxInt(u32),
1245 _,1249 _,
1250
1251 pub fn get(this: @This(), c: *const Configuration) ImportTable {
1252 return switch (this) {
1253 .invalid => unreachable,
1254 _ => extraData(c, ImportTable, @intFromEnum(this)),
1255 };
1256 }
1246 };1257 };
1247};1258};
12481259
...@@ -1313,6 +1324,8 @@ pub const InstallDestDir = enum(u32) {...@@ -1313,6 +1324,8 @@ pub const InstallDestDir = enum(u32) {
1313/// Points into `string_bytes`, null-terminated.1324/// Points into `string_bytes`, null-terminated.
1314pub const OptionalString = enum(u32) {1325pub const OptionalString = enum(u32) {
1315 empty = 0,1326 empty = 0,
1327 /// The string "root".
1328 root = 1,
1316 none = maxInt(u32),1329 none = maxInt(u32),
1317 _,1330 _,
13181331
...@@ -1326,6 +1339,8 @@ pub const OptionalString = enum(u32) {...@@ -1326,6 +1339,8 @@ pub const OptionalString = enum(u32) {
1326/// Points into `string_bytes`, null-terminated.1339/// Points into `string_bytes`, null-terminated.
1327pub const String = enum(u32) {1340pub const String = enum(u32) {
1328 empty = 0,1341 empty = 0,
1342 /// The string "root".
1343 root = 1,
1329 _,1344 _,
13301345
1331 pub fn slice(index: String, c: *const Configuration) [:0]const u8 {1346 pub fn slice(index: String, c: *const Configuration) [:0]const u8 {
...@@ -1954,15 +1969,23 @@ pub const Storage = enum {...@@ -1954,15 +1969,23 @@ pub const Storage = enum {
1954 };1969 };
19551970
1956 /// Valid to call only when serializing.1971 /// Valid to call only when serializing.
1957 pub fn init(slice: []const Union) @This() {1972 pub fn init(s: []const Union) @This() {
1958 return .{ .data = slice.ptr, .len = slice.len };1973 return .{ .data = s.ptr, .len = s.len };
1959 }1974 }
19601975
1961 /// Valid to call only when deserializing.1976 /// Valid to call only when deserializing.
1962 pub fn get(this: *const @This(), extra: []const u32) []const u32 {1977 pub fn slice(this: *const @This(), extra: []const u32) []const u32 {
1963 return extra[@intFromPtr(this.data)..][0..this.len];1978 return extra[@intFromPtr(this.data)..][0..this.len];
1964 }1979 }
19651980
1981 /// Valid to call only when deserializing.
1982 pub fn get(this: *const @This(), extra: []const u32, i: usize) Union {
1983 const elem = slice(this, extra)[i];
1984 return switch (this.tag(extra, i)) {
1985 inline else => |comptime_tag| @unionInit(Union, @tagName(comptime_tag), @enumFromInt(elem)),
1986 };
1987 }
1988
1966 /// Valid to call only when deserializing.1989 /// Valid to call only when deserializing.
1967 pub fn tag(this: *const @This(), extra: []const u32, i: usize) Tag {1990 pub fn tag(this: *const @This(), extra: []const u32, i: usize) Tag {
1968 _ = this;1991 _ = this;
...@@ -2093,7 +2116,7 @@ pub const Storage = enum {...@@ -2093,7 +2116,7 @@ pub const Storage = enum {
2093 const len = buffer[data_start - 1];2116 const len = buffer[data_start - 1];
2094 defer i.* = data_start + len * @typeInfo(Field.Elem).@"struct".fields.len;2117 defer i.* = data_start + len * @typeInfo(Field.Elem).@"struct".fields.len;
2095 return .{ .mal = .{2118 return .{ .mal = .{
2096 .bytes = @ptrCast(buffer[data_start..][0..len]),2119 .bytes = @ptrCast(@constCast(buffer[data_start..][0..len])),
2097 .len = len,2120 .len = len,
2098 .capacity = len,2121 .capacity = len,
2099 } };2122 } };