authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2026-06-16 01:43:20-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2026-06-20 21:08:23-04:00
log4f921814c0a6555a61d9e0a92fcc6f30bc20e994
tree1991b1341621c3b1ec4297a7e93e18a12d3a2693
parente949341b705c16b46544f26f5aab0a16670f42b4

main: handle more cli args for `zig test -ofmt=c`


8 files changed, 184 insertions(+), 120 deletions(-)

lib/zig.h+17-9
......@@ -4557,9 +4557,12 @@ static inline void zig_msvc_atomic_store_i128(zig_i128 volatile* obj, zig_i128 a
45574557#include <intrin.h>
45584558#endif
45594559
4560static inline void* zig_e_zig_windows_teb(void) zig_mangled(zig_e_zig_windows_teb, "zig_windows_teb");
4561static inline void* zig_e_zig_windows_peb(void) zig_mangled(zig_e_zig_windows_peb, "zig_windows_peb");
4562
45604563#if defined(zig_thumb)
45614564
4562static inline void* zig_windows_teb(void) {
4565static inline void* zig_e_zig_windows_teb(void) {
45634566 void* teb = 0;
45644567#if defined(zig_msvc)
45654568 teb = (void*)_MoveFromCoprocessor(15, 0, 13, 0, 2);
......@@ -4571,7 +4574,7 @@ static inline void* zig_windows_teb(void) {
45714574
45724575#elif defined(zig_aarch64)
45734576
4574static inline void* zig_windows_teb(void) {
4577static inline void* zig_e_zig_windows_teb(void) {
45754578 void* teb = 0;
45764579#if defined(zig_msvc)
45774580 teb = (void*)__readx18qword(0x0);
......@@ -4583,7 +4586,7 @@ static inline void* zig_windows_teb(void) {
45834586
45844587#elif defined(zig_x86_32)
45854588
4586static inline void* zig_windows_teb(void) {
4589static inline void* zig_e_zig_windows_teb(void) {
45874590 void* teb = 0;
45884591#if defined(zig_msvc)
45894592 teb = (void*)__readfsdword(0x18);
......@@ -4593,7 +4596,7 @@ static inline void* zig_windows_teb(void) {
45934596 return teb;
45944597}
45954598
4596static inline void* zig_windows_peb(void) {
4599static inline void* zig_e_zig_windows_peb(void) {
45974600 void* peb = 0;
45984601#if defined(zig_msvc)
45994602 peb = (void*)__readfsdword(0x30);
......@@ -4605,7 +4608,7 @@ static inline void* zig_windows_peb(void) {
46054608
46064609#elif defined(zig_x86_64)
46074610
4608static inline void* zig_windows_teb(void) {
4611static inline void* zig_e_zig_windows_teb(void) {
46094612 void* teb = 0;
46104613#if defined(zig_msvc)
46114614 teb = (void*)__readgsqword(0x30);
......@@ -4615,7 +4618,7 @@ static inline void* zig_windows_teb(void) {
46154618 return teb;
46164619}
46174620
4618static inline void* zig_windows_peb(void) {
4621static inline void* zig_e_zig_windows_peb(void) {
46194622 void* peb = 0;
46204623#if defined(zig_msvc)
46214624 peb = (void*)__readgsqword(0x60);
......@@ -4629,7 +4632,9 @@ static inline void* zig_windows_peb(void) {
46294632
46304633#if defined(zig_loongarch)
46314634
4632static inline void zig_loongarch_cpucfg(uint32_t word, uint32_t* result) {
4635static inline void zig_e_zig_loongarch_cpucfg(uint32_t word, uint32_t* result) zig_mangled(zig_e_zig_loongarch_cpucfg, "zig_loongarch_cpucfg");
4636
4637static inline void zig_e_zig_loongarch_cpucfg(uint32_t word, uint32_t* result) {
46334638#if defined(zig_gnuc_asm)
46344639 __asm__("cpucfg %[result], %[word]" : [result] "=r" (result) : [word] "r" (word));
46354640#else
......@@ -4639,7 +4644,10 @@ static inline void zig_loongarch_cpucfg(uint32_t word, uint32_t* result) {
46394644
46404645#elif defined(zig_x86) && !defined(zig_x86_16)
46414646
4642static inline void zig_x86_cpuid(uint32_t leaf_id, uint32_t subid, uint32_t* eax, uint32_t* ebx, uint32_t* ecx, uint32_t* edx) {
4647static inline void zig_e_zig_x86_cpuid(uint32_t leaf_id, uint32_t subid, uint32_t* eax, uint32_t* ebx, uint32_t* ecx, uint32_t* edx) zig_mangled(zig_e_zig_x86_cpuid, "zig_x86_cpuid");
4648static inline uint32_t zig_e_zig_x86_get_xcr0(void) zig_mangled(zig_e_zig_x86_get_xcr0, "zig_x86_get_xcr0");
4649
4650static inline void zig_e_zig_x86_cpuid(uint32_t leaf_id, uint32_t subid, uint32_t* eax, uint32_t* ebx, uint32_t* ecx, uint32_t* edx) {
46434651#if defined(zig_msvc)
46444652 int cpu_info[4];
46454653 __cpuidex(cpu_info, leaf_id, subid);
......@@ -4657,7 +4665,7 @@ static inline void zig_x86_cpuid(uint32_t leaf_id, uint32_t subid, uint32_t* eax
46574665#endif
46584666}
46594667
4660static inline uint32_t zig_x86_get_xcr0(void) {
4668static inline uint32_t zig_e_zig_x86_get_xcr0(void) {
46614669#if defined(zig_msvc)
46624670 return (uint32_t)_xgetbv(0);
46634671#elif defined(zig_gnuc_asm)
src/Compilation.zig+60-49
......@@ -103,16 +103,12 @@ native_system_include_paths: []const []const u8,
103103/// Corresponds to `-u <symbol>` for ELF/MachO and `/include:<symbol>` for COFF/PE.
104104force_undefined_symbols: std.array_hash_map.String(void),
105105
106c_object_table: std.array_hash_map.Auto(*CObject, void) = .empty,
107win32_resource_table: if (dev.env.supports(.win32_resource)) std.array_hash_map.Auto(*Win32Resource, void) else struct {
108 pub fn keys(_: @This()) [0]void {
109 return .{};
110 }
111 pub fn count(_: @This()) u0 {
112 return 0;
113 }
106c_objects: std.ArrayList(*CObject) = .empty,
107win32_resources: if (dev.env.supports(.win32_resource)) std.ArrayList(*Win32Resource) else struct {
108 items: [0]*struct {},
109 pub const empty: @This() = .{ .items = .{} };
114110 pub fn deinit(_: @This(), _: Allocator) void {}
115} = .{},
111} = .empty,
116112
117113link_diags: link.Diags,
118114link_queue: link.Queue = .empty,
......@@ -915,21 +911,6 @@ pub const CrtFile = struct {
915911 }
916912};
917913
918/// Supported languages for "zig clang -x <lang>".
919/// Loosely based on llvm-project/clang/include/clang/Driver/Types.def
920pub const LangToExt = std.StaticStringMap(FileExt).initComptime(.{
921 .{ "c", .c },
922 .{ "c-header", .h },
923 .{ "c++", .cpp },
924 .{ "c++-header", .hpp },
925 .{ "objective-c", .m },
926 .{ "objective-c-header", .hm },
927 .{ "objective-c++", .mm },
928 .{ "objective-c++-header", .hmm },
929 .{ "assembler", .assembly },
930 .{ "assembler-with-cpp", .assembly_with_cpp },
931});
932
933914/// For passing to a C compiler.
934915pub const CSourceFile = struct {
935916 /// Many C compiler flags are determined by settings contained in the owning Module.
......@@ -2486,8 +2467,10 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic,
24862467 };
24872468 errdefer comp.destroy();
24882469
2470 if (target.ofmt == .c) return comp;
2471
24892472 // Add a `CObject` for each `c_source_files`.
2490 try comp.c_object_table.ensureTotalCapacity(gpa, options.c_source_files.len);
2473 try comp.c_objects.ensureTotalCapacity(gpa, options.c_source_files.len);
24912474 for (options.c_source_files) |c_source_file| {
24922475 const c_object = try gpa.create(CObject);
24932476 errdefer gpa.destroy(c_object);
......@@ -2496,7 +2479,7 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic,
24962479 .status = .{ .new = {} },
24972480 .src = c_source_file,
24982481 };
2499 comp.c_object_table.putAssumeCapacityNoClobber(c_object, {});
2482 comp.c_objects.appendAssumeCapacity(c_object);
25002483 }
25012484
25022485 // Add a `Win32Resource` for each `rc_source_files` and one for `manifest_file`.
......@@ -2504,7 +2487,7 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic,
25042487 options.rc_source_files.len + @intFromBool(options.manifest_file != null);
25052488 if (win32_resource_count > 0) {
25062489 dev.check(.win32_resource);
2507 try comp.win32_resource_table.ensureTotalCapacity(gpa, win32_resource_count);
2490 try comp.win32_resources.ensureTotalCapacity(gpa, win32_resource_count);
25082491 for (options.rc_source_files) |rc_source_file| {
25092492 const win32_resource = try gpa.create(Win32Resource);
25102493 errdefer gpa.destroy(win32_resource);
......@@ -2513,7 +2496,7 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic,
25132496 .status = .{ .new = {} },
25142497 .src = .{ .rc = rc_source_file },
25152498 };
2516 comp.win32_resource_table.putAssumeCapacityNoClobber(win32_resource, {});
2499 comp.win32_resources.appendAssumeCapacity(win32_resource);
25172500 }
25182501
25192502 if (options.manifest_file) |manifest_path| {
......@@ -2524,11 +2507,11 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic,
25242507 .status = .{ .new = {} },
25252508 .src = .{ .manifest = manifest_path },
25262509 };
2527 comp.win32_resource_table.putAssumeCapacityNoClobber(win32_resource, {});
2510 comp.win32_resources.appendAssumeCapacity(win32_resource);
25282511 }
25292512 }
25302513
2531 if (comp.emit_bin != null and target.ofmt != .c) {
2514 if (comp.emit_bin != null) {
25322515 if (!comp.skip_linker_dependencies) {
25332516 // If we need to build libc for the target, add work items for it.
25342517 // We go through the work queue so that building can be done in parallel.
......@@ -2749,20 +2732,20 @@ pub fn destroy(comp: *Compilation) void {
27492732 openbsd_file.deinit(gpa, io);
27502733 }
27512734
2752 for (comp.c_object_table.keys()) |key| {
2753 key.destroy(gpa, io);
2735 for (comp.c_objects.items) |c_object| {
2736 c_object.destroy(gpa, io);
27542737 }
2755 comp.c_object_table.deinit(gpa);
2738 comp.c_objects.deinit(gpa);
27562739
27572740 for (comp.failed_c_objects.values()) |bundle| {
27582741 bundle.destroy(gpa);
27592742 }
27602743 comp.failed_c_objects.deinit(gpa);
27612744
2762 for (comp.win32_resource_table.keys()) |key| {
2763 key.destroy(gpa, io);
2745 for (comp.win32_resources.items) |win32_resource| {
2746 win32_resource.destroy(gpa, io);
27642747 }
2765 comp.win32_resource_table.deinit(gpa);
2748 comp.win32_resources.deinit(gpa);
27662749
27672750 for (comp.failed_win32_resources.values()) |*value| {
27682751 value.deinit(gpa);
......@@ -3016,8 +2999,8 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateE
30162999 // changes. For now, to avoid crashing the linker in this case, don't kick off C object
30173000 // updates if we've done prelink already. https://codeberg.org/ziglang/zig/issues/32081
30183001 } else {
3019 try comp.c_object_work_queue.ensureUnusedCapacity(gpa, comp.c_object_table.count());
3020 for (comp.c_object_table.keys()) |c_object| {
3002 try comp.c_object_work_queue.ensureUnusedCapacity(gpa, comp.c_objects.items.len);
3003 for (comp.c_objects.items) |c_object| {
30213004 comp.c_object_work_queue.pushBackAssumeCapacity(c_object);
30223005 try comp.appendFileSystemInput(try .fromUnresolved(arena, comp.dirs, &.{c_object.src.src_path}));
30233006 }
......@@ -3032,8 +3015,8 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateE
30323015
30333016 // For compiling Win32 resources, we rely on the cache hash system to avoid duplicating work.
30343017 // Add a Job for each Win32 resource file.
3035 try comp.win32_resource_work_queue.ensureUnusedCapacity(gpa, comp.win32_resource_table.count());
3036 for (comp.win32_resource_table.keys()) |win32_resource| {
3018 try comp.win32_resource_work_queue.ensureUnusedCapacity(gpa, comp.win32_resources.items.len);
3019 for (comp.win32_resources.items) |win32_resource| {
30373020 comp.win32_resource_work_queue.pushBackAssumeCapacity(win32_resource);
30383021 switch (win32_resource.src) {
30393022 .rc => |f| {
......@@ -3140,9 +3123,9 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateE
31403123 return;
31413124 }
31423125
3143 if (comp.zcu == null and comp.config.output_mode == .Obj and comp.c_object_table.count() == 1) {
3126 if (comp.zcu == null and comp.config.output_mode == .Obj and comp.c_objects.items.len == 1) {
31443127 // This is `zig build-obj foo.c`. We can emit asm and LLVM IR/bitcode.
3145 const c_obj_path = comp.c_object_table.keys()[0].status.success.object_path;
3128 const c_obj_path = comp.c_objects.items[0].status.success.object_path;
31463129 if (comp.emit_asm) |path| try comp.emitFromCObject(arena, c_obj_path, ".s", path);
31473130 if (comp.emit_llvm_ir) |path| try comp.emitFromCObject(arena, c_obj_path, ".ll", path);
31483131 if (comp.emit_llvm_bc) |path| try comp.emitFromCObject(arena, c_obj_path, ".bc", path);
......@@ -3482,14 +3465,14 @@ fn addNonIncrementalStuffToCacheManifest(
34823465
34833466 try link.hashInputs(man, comp.link_inputs);
34843467
3485 for (comp.c_object_table.keys()) |key| {
3486 _ = try man.addFile(key.src.src_path, null);
3487 man.hash.addOptional(key.src.ext);
3488 man.hash.addListOfBytes(key.src.extra_flags);
3468 for (comp.c_objects.items) |c_object| {
3469 _ = try man.addFile(c_object.src.src_path, null);
3470 man.hash.addOptional(c_object.src.ext);
3471 man.hash.addListOfBytes(c_object.src.extra_flags);
34893472 }
34903473
3491 for (comp.win32_resource_table.keys()) |key| {
3492 switch (key.src) {
3474 for (comp.win32_resources.items) |win32_resource| {
3475 switch (win32_resource.src) {
34933476 .rc => |rc_src| {
34943477 _ = try man.addFile(rc_src.src_path, null);
34953478 man.hash.addListOfBytes(rc_src.extra_flags);
......@@ -5592,9 +5575,10 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr
55925575 c_source_basename[0 .. c_source_basename.len - fs.path.extension(c_source_basename).len];
55935576
55945577 const target = comp.getTarget();
5578 assert(target.ofmt != .c);
55955579 const o_ext = target.ofmt.fileExt(target.cpu.arch);
55965580 const digest = if (!comp.disable_c_depfile and try man.hit()) man.final() else blk: {
5597 var argv = std.array_list.Managed([]const u8).init(gpa);
5581 var argv: std.array_list.Managed([]const u8) = .init(gpa);
55985582 defer argv.deinit();
55995583
56005584 // In case we are doing passthrough mode, we need to detect -S and -emit-llvm.
......@@ -7057,6 +7041,33 @@ pub const FileExt = enum {
70577041 .unknown => "",
70587042 };
70597043 }
7044
7045 /// The value accepted by "zig clang -x <lang>" and passed to "clang -x <lang>".
7046 pub fn toLang(ext: FileExt) ?[]const u8 {
7047 return switch (ext) {
7048 else => null,
7049 .c => "c",
7050 .h => "c-header",
7051 .cpp => "c++",
7052 .hpp => "c++-header",
7053 .m => "objective-c",
7054 .hm => "objective-c-header",
7055 .mm => "objective-c++",
7056 .hmm => "objective-c++-header",
7057 .assembly => "assembler",
7058 .assembly_with_cpp => "assembler-with-cpp",
7059 };
7060 }
7061
7062 /// Supported languages for "zig clang -x <lang>".
7063 /// Loosely based on llvm-project/clang/include/clang/Driver/Types.def
7064 pub const from_lang = std.StaticStringMap(FileExt).initComptime(init: {
7065 var init: []const struct { []const u8, FileExt } = &.{};
7066 for (std.enums.values(FileExt)) |file_ext| if (file_ext.toLang()) |lang| {
7067 init = init ++ .{.{ lang, file_ext }};
7068 };
7069 break :init init;
7070 });
70607071};
70617072
70627073pub fn hasObjectExt(filename: []const u8) bool {
src/codegen/c.zig+4-1
......@@ -328,6 +328,9 @@ fn isReservedIdent(ident: []const u8) bool {
328328 return true;
329329 }
330330
331 // zig.h
332 if (mem.startsWith(u8, ident, "zig_")) return true;
333
331334 return reserved_idents.has(ident);
332335}
333336
......@@ -3755,7 +3758,7 @@ fn airCmpLteErrorsLen(f: *Function, inst: Air.Inst.Index) !CValue {
37553758 try f.writeCValue(w, local, .other);
37563759 try w.writeAll(" = ");
37573760 try f.writeCValue(w, operand, .other);
3758 try w.print(" < sizeof({f}) / sizeof(*{0f});", .{fmtIdentSolo("zig_errorName")});
3761 try w.writeAll(" < sizeof(zig_errorName) / sizeof(*zig_errorName);");
37593762 try f.newline();
37603763 return local;
37613764}
src/link.zig+2-2
......@@ -933,8 +933,8 @@ pub const File = struct {
933933 // Until then, we do `lld -r -o output.o input.o` even though the output is the same
934934 // as the input. For the preprocessing case (`zig cc -E -o foo`) we copy the file
935935 // to the final location. See also the corresponding TODO in Coff linking.
936 assert(comp.c_object_table.count() == 1);
937 const the_key = comp.c_object_table.keys()[0];
936 assert(comp.c_objects.items.len == 1);
937 const the_key = comp.c_objects.items[0];
938938 const cached_pp_file_path = the_key.status.success.object_path;
939939 Io.Dir.copyFile(
940940 cached_pp_file_path.root_dir.handle,
src/link/Lld.zig+20-20
......@@ -313,14 +313,14 @@ fn linkAsArchive(lld: *Lld, arena: Allocator) !void {
313313 object_files.appendAssumeCapacity(try input.path().?.toStringZ(arena));
314314 }
315315
316 try object_files.ensureUnusedCapacity(arena, comp.c_object_table.count() +
317 comp.win32_resource_table.count() + 2);
316 try object_files.ensureUnusedCapacity(arena, comp.c_objects.items.len +
317 comp.win32_resources.items.len + 2);
318318
319 for (comp.c_object_table.keys()) |key| {
320 object_files.appendAssumeCapacity(try key.status.success.object_path.toStringZ(arena));
319 for (comp.c_objects.items) |c_object| {
320 object_files.appendAssumeCapacity(try c_object.status.success.object_path.toStringZ(arena));
321321 }
322 for (comp.win32_resource_table.keys()) |key| {
323 object_files.appendAssumeCapacity(try arena.dupeSentinel(u8, key.status.success.res_path, 0));
322 for (comp.win32_resources.items) |win32_resource| {
323 object_files.appendAssumeCapacity(try arena.dupeSentinel(u8, win32_resource.status.success.res_path, 0));
324324 }
325325 if (zcu_obj_path) |p| object_files.appendAssumeCapacity(try p.toStringZ(arena));
326326 if (compiler_rt_path) |p| object_files.appendAssumeCapacity(try p.toStringZ(arena));
......@@ -395,8 +395,8 @@ fn coffLink(lld: *Lld, arena: Allocator) !void {
395395 const the_object_path = blk: {
396396 if (link.firstObjectInput(comp.link_inputs)) |obj| break :blk obj.path;
397397
398 if (comp.c_object_table.count() != 0)
399 break :blk comp.c_object_table.keys()[0].status.success.object_path;
398 if (comp.c_objects.items.len != 0)
399 break :blk comp.c_objects.items[0].status.success.object_path;
400400
401401 if (zcu_obj_path) |p|
402402 break :blk p;
......@@ -546,12 +546,12 @@ fn coffLink(lld: *Lld, arena: Allocator) !void {
546546 },
547547 };
548548
549 for (comp.c_object_table.keys()) |key| {
550 try argv.append(try key.status.success.object_path.toString(arena));
549 for (comp.c_objects.items) |c_object| {
550 try argv.append(try c_object.status.success.object_path.toString(arena));
551551 }
552552
553 for (comp.win32_resource_table.keys()) |key| {
554 try argv.append(key.status.success.res_path);
553 for (comp.win32_resources.items) |win32_resource| {
554 try argv.append(win32_resource.status.success.res_path);
555555 }
556556
557557 if (zcu_obj_path) |p| {
......@@ -805,8 +805,8 @@ fn elfLink(lld: *Lld, arena: Allocator) !void {
805805 const the_object_path = blk: {
806806 if (link.firstObjectInput(comp.link_inputs)) |obj| break :blk obj.path;
807807
808 if (comp.c_object_table.count() != 0)
809 break :blk comp.c_object_table.keys()[0].status.success.object_path;
808 if (comp.c_objects.items.len != 0)
809 break :blk comp.c_objects.items[0].status.success.object_path;
810810
811811 if (zcu_obj_path) |p|
812812 break :blk p;
......@@ -1099,8 +1099,8 @@ fn elfLink(lld: *Lld, arena: Allocator) !void {
10991099 whole_archive = false;
11001100 }
11011101
1102 for (comp.c_object_table.keys()) |key| {
1103 try argv.append(try key.status.success.object_path.toString(arena));
1102 for (comp.c_objects.items) |c_object| {
1103 try argv.append(try c_object.status.success.object_path.toString(arena));
11041104 }
11051105
11061106 if (zcu_obj_path) |p| {
......@@ -1381,8 +1381,8 @@ fn wasmLink(lld: *Lld, arena: Allocator) !void {
13811381 const the_object_path = blk: {
13821382 if (link.firstObjectInput(comp.link_inputs)) |obj| break :blk obj.path;
13831383
1384 if (comp.c_object_table.count() != 0)
1385 break :blk comp.c_object_table.keys()[0].status.success.object_path;
1384 if (comp.c_objects.items.len != 0)
1385 break :blk comp.c_objects.items[0].status.success.object_path;
13861386
13871387 if (zcu_obj_path) |p|
13881388 break :blk p;
......@@ -1566,8 +1566,8 @@ fn wasmLink(lld: *Lld, arena: Allocator) !void {
15661566 whole_archive = false;
15671567 }
15681568
1569 for (comp.c_object_table.keys()) |key| {
1570 try argv.append(try key.status.success.object_path.toString(arena));
1569 for (comp.c_objects.items) |c_object| {
1570 try argv.append(try c_object.status.success.object_path.toString(arena));
15711571 }
15721572 if (zcu_obj_path) |p| {
15731573 try argv.append(try p.toString(arena));
src/link/MachO.zig+7-7
......@@ -377,9 +377,9 @@ pub fn flush(
377377 // This is a set of object files emitted by clang in a single `build-exe` invocation.
378378 // For instance, the implicit `a.o` as compiled by `zig build-exe a.c` will end up
379379 // in this set.
380 try positionals.ensureUnusedCapacity(comp.c_object_table.keys().len);
381 for (comp.c_object_table.keys()) |key| {
382 positionals.appendAssumeCapacity(try link.openObjectInput(io, diags, key.status.success.object_path));
380 try positionals.ensureUnusedCapacity(comp.c_objects.items.len);
381 for (comp.c_objects.items) |c_object| {
382 positionals.appendAssumeCapacity(try link.openObjectInput(io, diags, c_object.status.success.object_path));
383383 }
384384
385385 if (zcu_obj_path) |path| try positionals.append(try link.openObjectInput(io, diags, path));
......@@ -657,8 +657,8 @@ fn dumpArgv(self: *MachO, comp: *Compilation) !void {
657657 .dso_exact => |dso_exact| try argv.appendSlice(&.{ "-l", dso_exact.name }),
658658 };
659659
660 for (comp.c_object_table.keys()) |key| {
661 try argv.append(try key.status.success.object_path.toString(arena));
660 for (comp.c_objects.items) |c_object| {
661 try argv.append(try c_object.status.success.object_path.toString(arena));
662662 }
663663
664664 if (zcu_obj_path) |p| {
......@@ -749,8 +749,8 @@ fn dumpArgv(self: *MachO, comp: *Compilation) !void {
749749 .dso_exact => |dso_exact| try argv.appendSlice(&.{ "-l", dso_exact.name }),
750750 };
751751
752 for (comp.c_object_table.keys()) |key| {
753 try argv.append(try key.status.success.object_path.toString(arena));
752 for (comp.c_objects.items) |c_object| {
753 try argv.append(try c_object.status.success.object_path.toString(arena));
754754 }
755755
756756 if (zcu_obj_path) |p| {
src/link/MachO/relocatable.zig+4-4
......@@ -9,8 +9,8 @@ pub fn flushObject(macho_file: *MachO, comp: *Compilation, module_obj_path: ?Pat
99 try positionals.ensureUnusedCapacity(comp.link_inputs.len);
1010 positionals.appendSliceAssumeCapacity(comp.link_inputs);
1111
12 for (comp.c_object_table.keys()) |key| {
13 try positionals.append(try link.openObjectInput(io, diags, key.status.success.object_path));
12 for (comp.c_objects.items) |c_object| {
13 try positionals.append(try link.openObjectInput(io, diags, c_object.status.success.object_path));
1414 }
1515
1616 if (module_obj_path) |path| try positionals.append(try link.openObjectInput(io, diags, path));
......@@ -86,8 +86,8 @@ pub fn flushStaticLib(macho_file: *MachO, comp: *Compilation, module_obj_path: ?
8686 try positionals.ensureUnusedCapacity(comp.link_inputs.len);
8787 positionals.appendSliceAssumeCapacity(comp.link_inputs);
8888
89 for (comp.c_object_table.keys()) |key| {
90 try positionals.append(try link.openObjectInput(io, diags, key.status.success.object_path));
89 for (comp.c_objects.items) |c_object| {
90 try positionals.append(try link.openObjectInput(io, diags, c_object.status.success.object_path));
9191 }
9292
9393 if (module_obj_path) |path| try positionals.append(try link.openObjectInput(io, diags, path));
src/main.zig+70-28
......@@ -887,6 +887,7 @@ const CliModule = struct {
887887 inherited: Package.Module.CreateOptions.Inherited,
888888 target_arch_os_abi: ?[]const u8,
889889 target_mcpu: ?[]const u8,
890 dynamic_linker: ?[]const u8,
890891
891892 deps: []const Dep,
892893 resolved: ?*Package.Module,
......@@ -943,6 +944,7 @@ fn buildOutputType(
943944 var emit_implib_arg_provided = false;
944945 var target_arch_os_abi: ?[]const u8 = null;
945946 var target_mcpu: ?[]const u8 = null;
947 var dynamic_linker: ?[]const u8 = null;
946948 var emit_h: Emit = .no;
947949 var soname: SOName = undefined;
948950 var want_compiler_rt: ?bool = null;
......@@ -1059,7 +1061,6 @@ fn buildOutputType(
10591061 // Populated just before the call to `createModule`.
10601062 .dirs = undefined,
10611063 .object_format = null,
1062 .dynamic_linker = null,
10631064 .modules = .empty,
10641065 .opts = .{
10651066 .is_test = switch (arg_mode) {
......@@ -1179,6 +1180,7 @@ fn buildOutputType(
11791180 &cc_argv,
11801181 &target_arch_os_abi,
11811182 &target_mcpu,
1183 &dynamic_linker,
11821184 &deps,
11831185 &c_source_files_owner_index,
11841186 &rc_source_files_owner_index,
......@@ -1397,9 +1399,9 @@ fn buildOutputType(
13971399 } else if (mem.cutPrefix(u8, arg, "-O")) |rest| {
13981400 mod_opts.optimize_mode = parseOptimizeMode(rest);
13991401 } else if (mem.eql(u8, arg, "--dynamic-linker")) {
1400 create_module.dynamic_linker = args_iter.nextOrFatal();
1402 dynamic_linker = args_iter.nextOrFatal();
14011403 } else if (mem.eql(u8, arg, "--no-dynamic-linker")) {
1402 create_module.dynamic_linker = "";
1404 dynamic_linker = "";
14031405 } else if (mem.eql(u8, arg, "--sysroot")) {
14041406 const next_arg = args_iter.nextOrFatal();
14051407 create_module.sysroot = next_arg;
......@@ -1846,7 +1848,7 @@ fn buildOutputType(
18461848 const lang = if (rest.len == 0) args_iter.nextOrFatal() else rest;
18471849 if (mem.eql(u8, lang, "none")) {
18481850 file_ext = null;
1849 } else if (Compilation.LangToExt.get(lang)) |got_ext| {
1851 } else if (Compilation.FileExt.from_lang.get(lang)) |got_ext| {
18501852 file_ext = got_ext;
18511853 } else {
18521854 fatal("language not recognized: {s}", .{lang});
......@@ -1983,7 +1985,7 @@ fn buildOutputType(
19831985 const lang = mem.sliceTo(it.only_arg, 0);
19841986 if (mem.eql(u8, lang, "none")) {
19851987 file_ext = null;
1986 } else if (Compilation.LangToExt.get(lang)) |got_ext| {
1988 } else if (Compilation.FileExt.from_lang.get(lang)) |got_ext| {
19871989 file_ext = got_ext;
19881990 } else {
19891991 fatal("language not recognized: {q}", .{lang});
......@@ -2610,12 +2612,11 @@ fn buildOutputType(
26102612 mem.eql(u8, arg, "--dynamic-linker") or
26112613 mem.eql(u8, arg, "-dynamic-linker"))
26122614 {
2613 create_module.dynamic_linker = linker_args_it.nextOrFatal();
2614 } else if (mem.eql(u8, arg, "-I") or
2615 mem.eql(u8, arg, "--no-dynamic-linker") or
2615 dynamic_linker = linker_args_it.nextOrFatal();
2616 } else if (mem.eql(u8, arg, "--no-dynamic-linker") or
26162617 mem.eql(u8, arg, "-no-dynamic-linker"))
26172618 {
2618 create_module.dynamic_linker = "";
2619 dynamic_linker = "";
26192620 } else if (mem.eql(u8, arg, "-E") or
26202621 mem.eql(u8, arg, "--export-dynamic") or
26212622 mem.eql(u8, arg, "-export-dynamic"))
......@@ -3184,6 +3185,7 @@ fn buildOutputType(
31843185 .inherited = mod_opts,
31853186 .target_arch_os_abi = target_arch_os_abi,
31863187 .target_mcpu = target_mcpu,
3188 .dynamic_linker = dynamic_linker,
31873189 .deps = try deps.toOwnedSlice(arena),
31883190 .resolved = null,
31893191 .c_source_files_start = c_source_files_owner_index,
......@@ -3842,10 +3844,59 @@ fn buildOutputType(
38423844 if (test_exec_args.items.len == 0 and target.ofmt == .c and emit_bin_resolved != .no) {
38433845 // Default to using `zig run` to execute the produced .c code from `zig test`.
38443846 try test_exec_args.appendSlice(arena, &.{ self_exe_path, "run" });
3845 if (dirs.zig_lib.path) |p| {
3846 try test_exec_args.appendSlice(arena, &.{ "-I", p });
3847 // Skip passing `-ofmt`, we want the default for the target, not `.c` anymore.
3848
3849 var prev_has_cflags = false;
3850 var prev_has_rcflags = false;
3851 if (dirs.zig_lib.path) |zig_lib_path| {
3852 try test_exec_args.appendSlice(arena, &.{ "-cflags", "-I", zig_lib_path, "--" });
3853 prev_has_cflags = true;
3854 }
3855 try test_exec_args.append(arena, null);
3856 for (create_module.modules.keys(), create_module.modules.values()) |mod_name, mod| {
3857 for (create_module.c_source_files.items[mod.c_source_files_start..mod.c_source_files_end]) |c_source_file| {
3858 const cflags_len = c_source_file.extra_flags.len + c_source_file.cache_exempt_flags.len;
3859 if (prev_has_cflags or cflags_len > 0) {
3860 try test_exec_args.ensureUnusedCapacity(arena, 1 + cflags_len + 1);
3861 test_exec_args.appendAssumeCapacity("-cflags");
3862 for (c_source_file.extra_flags) |extra_flag| test_exec_args.appendAssumeCapacity(extra_flag);
3863 for (c_source_file.cache_exempt_flags) |cache_exempt_flag| test_exec_args.appendAssumeCapacity(cache_exempt_flag);
3864 test_exec_args.appendAssumeCapacity("--");
3865 }
3866 prev_has_cflags = cflags_len > 0;
3867 if (c_source_file.ext) |ext| try test_exec_args.appendSlice(arena, &.{ "-x", ext.toLang() });
3868 try test_exec_args.append(arena, c_source_file.src_path);
3869 if (c_source_file.ext) |_| try test_exec_args.appendSlice(arena, &.{ "-x", "none" });
3870 }
3871 for (create_module.rc_source_files.items[mod.rc_source_files_start..mod.rc_source_files_end]) |rc_source_file| {
3872 const rcflags_len = rc_source_file.extra_flags.len;
3873 if (prev_has_rcflags or rcflags_len > 0) {
3874 try test_exec_args.ensureUnusedCapacity(arena, 1 + rcflags_len + 1);
3875 test_exec_args.appendAssumeCapacity("-rcflags");
3876 for (rc_source_file.extra_flags) |extra_flag| test_exec_args.appendAssumeCapacity(extra_flag);
3877 test_exec_args.appendAssumeCapacity("--");
3878 }
3879 prev_has_rcflags = rcflags_len > 0;
3880 try test_exec_args.append(arena, rc_source_file.src_path);
3881 }
3882 if (mod.target_arch_os_abi) |triple| try test_exec_args.appendSlice(arena, &.{ "-target", triple });
3883 if (mod.target_mcpu) |mcpu| try test_exec_args.appendSlice(arena, &.{ "-mcpu", mcpu });
3884 if (mod.dynamic_linker) |dl| if (dl.len > 0)
3885 try test_exec_args.appendSlice(arena, &.{ "--dynamic-linker", dl })
3886 else
3887 try test_exec_args.append(arena, "--no-dynamic-linker");
3888 try test_exec_args.ensureUnusedCapacity(arena, mod.cc_argv.len);
3889 for (mod.cc_argv) |cc_arg| test_exec_args.appendAssumeCapacity(cc_arg);
3890 for (mod.deps) |dep| try test_exec_args.appendSlice(arena, &.{
3891 "--dep",
3892 if (std.mem.eql(u8, dep.key, dep.value)) dep.value else try std.fmt.allocPrint(arena, "{s}={s}", .{ dep.key, dep.value }),
3893 });
3894 try test_exec_args.append(arena, try std.fmt.allocPrint(arena, "-M{s}", .{mod_name}));
38473895 }
38483896
3897 try test_exec_args.ensureUnusedCapacity(arena, comp.global_cc_argv.len);
3898 for (comp.global_cc_argv) |global_cc_arg| test_exec_args.appendAssumeCapacity(global_cc_arg);
3899 if (create_module.resolved_options.link_libcpp) try test_exec_args.append(arena, "-lc++");
38493900 if (create_module.resolved_options.link_libc) {
38503901 try test_exec_args.append(arena, "-lc");
38513902 } else if (target.os.tag == .windows) {
......@@ -3855,21 +3906,10 @@ fn buildOutputType(
38553906 });
38563907 }
38573908
3858 const first_cli_mod = create_module.modules.values()[0];
3859 if (first_cli_mod.target_arch_os_abi) |triple| {
3860 try test_exec_args.appendSlice(arena, &.{ "-target", triple });
3861 }
3862 if (first_cli_mod.target_mcpu) |mcpu| {
3863 try test_exec_args.append(arena, try std.fmt.allocPrint(arena, "-mcpu={s}", .{mcpu}));
3864 }
3865 if (create_module.dynamic_linker) |dl| {
3866 if (dl.len > 0) {
3867 try test_exec_args.appendSlice(arena, &.{ "--dynamic-linker", dl });
3868 } else {
3869 try test_exec_args.append(arena, "--no-dynamic-linker");
3870 }
3871 }
3872 try test_exec_args.append(arena, null); // placeholder for the path of the emitted C source file
3909 try test_exec_args.ensureUnusedCapacity(arena, 2 * log_scopes.items.len + @intFromBool(verbose_link) + @intFromBool(verbose_cc));
3910 for (log_scopes.items) |log_scope| test_exec_args.appendSliceAssumeCapacity(&.{ "--debug-log", log_scope });
3911 if (verbose_link) test_exec_args.appendAssumeCapacity("--verbose-link");
3912 if (verbose_cc) test_exec_args.appendAssumeCapacity("--verbose-cc");
38733913 }
38743914
38753915 try runOrTest(
......@@ -3898,7 +3938,6 @@ const CreateModule = struct {
38983938 dirs: Compilation.Directories,
38993939 modules: std.array_hash_map.String(CliModule),
39003940 opts: Compilation.Config.Options,
3901 dynamic_linker: ?[]const u8,
39023941 object_format: ?[]const u8,
39033942 /// undefined until createModule() for the root module is called.
39043943 resolved_options: Compilation.Config,
......@@ -3960,7 +3999,7 @@ fn createModule(
39603999 var target_parse_options: std.Target.Query.ParseOptions = .{
39614000 .arch_os_abi = cli_mod.target_arch_os_abi orelse "native",
39624001 .cpu_features = cli_mod.target_mcpu,
3963 .dynamic_linker = create_module.dynamic_linker,
4002 .dynamic_linker = cli_mod.dynamic_linker,
39644003 .object_format = create_module.object_format,
39654004 };
39664005
......@@ -7844,6 +7883,7 @@ fn handleModArg(
78447883 cc_argv: *std.ArrayList([]const u8),
78457884 target_arch_os_abi: *?[]const u8,
78467885 target_mcpu: *?[]const u8,
7886 dynamic_linker: *?[]const u8,
78477887 deps: *std.ArrayList(CliModule.Dep),
78487888 c_source_files_owner_index: *usize,
78497889 rc_source_files_owner_index: *usize,
......@@ -7892,6 +7932,7 @@ fn handleModArg(
78927932 .inherited = mod_opts.*,
78937933 .target_arch_os_abi = target_arch_os_abi.*,
78947934 .target_mcpu = target_mcpu.*,
7935 .dynamic_linker = dynamic_linker.*,
78957936 .deps = try deps.toOwnedSlice(arena),
78967937 .resolved = null,
78977938 .c_source_files_start = c_source_files_owner_index.*,
......@@ -7903,6 +7944,7 @@ fn handleModArg(
79037944 mod_opts.* = .{};
79047945 target_arch_os_abi.* = null;
79057946 target_mcpu.* = null;
7947 dynamic_linker.* = null;
79067948 c_source_files_owner_index.* = create_module.c_source_files.items.len;
79077949 rc_source_files_owner_index.* = create_module.rc_source_files.items.len;
79087950}