authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-03-25 18:29:19-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-03-25 18:29:19-07:00
logabd131e3367bb10a67bc4c240b87b05d1de4e42f
treec83463cce17cba484a746dac069869a770996370
parent54b3484256695381c034aa30f322b1499a4b27c8

zig cc: make --version use the full clang CLI lowering code path

because clang wants to parse the -target argument with clang -target syntax. closes #30178

5 files changed, 47 insertions(+), 15 deletions(-)

lib/std/zig.zig+1
......@@ -1121,6 +1121,7 @@ pub const ClangCliParam = struct {
11211121 rtlib,
11221122 static,
11231123 dynamic,
1124 version,
11241125 };
11251126
11261127 pub fn matchEql(self: @This(), arg: []const u8) u2 {
src/Compilation.zig+16-11
......@@ -1471,6 +1471,8 @@ pub const ClangPreprocessorMode = enum {
14711471 stdout,
14721472 /// precompiled C header
14731473 pch,
1474 /// `--version`
1475 version,
14741476};
14751477
14761478pub const Framework = link.File.MachO.Framework;
......@@ -2936,16 +2938,16 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateE
29362938 .none => unreachable,
29372939 .manifest_create, .manifest_read, .manifest_lock => |e| return comp.setMiscFailure(
29382940 .check_whole_cache,
2939 "failed to check cache: {s} {s}",
2940 .{ @tagName(man.diagnostic), @errorName(e) },
2941 "failed to check cache: {t} {t}",
2942 .{ man.diagnostic, e },
29412943 ),
29422944 .file_open, .file_stat, .file_read, .file_hash => |op| {
29432945 const pp = man.files.keys()[op.file_index].prefixed_path;
29442946 const prefix = man.cache.prefixes()[pp.prefix];
29452947 return comp.setMiscFailure(
29462948 .check_whole_cache,
2947 "failed to check cache: '{f}{s}' {s} {s}",
2948 .{ prefix, pp.sub_path, @tagName(man.diagnostic), @errorName(op.err) },
2949 "failed to check cache: '{f}{s}' {t} {t}",
2950 .{ prefix, pp.sub_path, man.diagnostic, op.err },
29492951 );
29502952 },
29512953 },
......@@ -5739,6 +5741,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr
57395741 .yes => argv.appendSliceAssumeCapacity(&.{ "-E", "-o", out_obj_path }),
57405742 .pch => argv.appendSliceAssumeCapacity(&.{ "-Xclang", "-emit-pch", "-o", out_obj_path }),
57415743 .stdout => argv.appendAssumeCapacity("-E"),
5744 .version => argv.appendAssumeCapacity("--version"),
57425745 }
57435746
57445747 if (comp.emit_asm != null) {
......@@ -5782,6 +5785,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr
57825785 .yes => argv.appendSliceAssumeCapacity(&.{ "-E", "-o", out_obj_path }),
57835786 .pch => argv.appendSliceAssumeCapacity(&.{ "-Xclang", "-emit-pch", "-o", out_obj_path }),
57845787 .stdout => argv.appendAssumeCapacity("-E"),
5788 .version => argv.appendAssumeCapacity("--version"),
57855789 }
57865790 if (out_diag_path) |diag_file_path| {
57875791 argv.appendSliceAssumeCapacity(&.{ "--serialize-diagnostics", diag_file_path });
......@@ -5830,8 +5834,10 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr
58305834 if (code != 0) {
58315835 std.process.exit(code);
58325836 }
5833 if (comp.clang_preprocessor_mode == .stdout)
5834 std.process.exit(0);
5837 switch (comp.clang_preprocessor_mode) {
5838 .stdout, .version => std.process.exit(0),
5839 else => {},
5840 }
58355841 },
58365842 else => std.process.abort(),
58375843 }
......@@ -5879,11 +5885,10 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr
58795885 return comp.failCObj(c_object, "clang exited with code {d}", .{exit_code});
58805886 }
58815887 }
5882 if (comp.clang_passthrough_mode and
5883 comp.clang_preprocessor_mode == .stdout)
5884 {
5885 std.process.exit(0);
5886 }
5888 if (comp.clang_passthrough_mode) switch (comp.clang_preprocessor_mode) {
5889 .stdout, .version => std.process.exit(0),
5890 else => {},
5891 };
58875892 }
58885893
58895894 if (out_dep_path) |dep_file_path| {
src/clang_options.zon+2-1
......@@ -637,6 +637,7 @@
637637},
638638.{
639639 .name = "version",
640 .ze = .version,
640641 .pd1 = false,
641642 .pd2 = true,
642643},
......@@ -3378,7 +3379,7 @@
33783379},
33793380.{ .name = "verify-ignore-unexpected" },
33803381.{ .name = "verify-pch" },
3381.{ .name = "version" },
3382.{ .name = "version", .ze = .version },
33823383.{ .name = "via-file-asm", .pd2 = true },
33833384.{ .name = "w" },
33843385.{
src/main.zig+24-3
......@@ -1889,6 +1889,7 @@ fn buildOutputType(
18891889 object,
18901890 assembly,
18911891 preprocessor,
1892 version,
18921893 };
18931894 var c_out_mode: ?COutMode = null;
18941895 var out_path: ?[]const u8 = null;
......@@ -1917,6 +1918,10 @@ fn buildOutputType(
19171918 .c, .r => c_out_mode = .object, // -c or -r
19181919 .asm_only => c_out_mode = .assembly, // -S
19191920 .preprocess_only => c_out_mode = .preprocessor, // -E
1921 .version => {
1922 c_out_mode = .version; // --version
1923 disable_c_depfile = true;
1924 },
19201925 .emit_llvm => emit_llvm = true,
19211926 .x => {
19221927 const lang = mem.sliceTo(it.only_arg, 0);
......@@ -2939,9 +2944,11 @@ fn buildOutputType(
29392944 }
29402945
29412946 // precompiled header syntax: "zig cc -x c-header test.h -o test.pch"
2942 const emit_pch = ((file_ext == .h or file_ext == .hpp or file_ext == .hm or file_ext == .hmm) and c_out_mode == null);
2943 if (emit_pch)
2944 c_out_mode = .preprocessor;
2947 const emit_pch = if (file_ext) |fe| switch (fe) {
2948 .h, .hpp, .hm, .hmm => c_out_mode == null,
2949 else => false,
2950 } else false;
2951 if (emit_pch) c_out_mode = .preprocessor;
29452952
29462953 switch (c_out_mode orelse .link) {
29472954 .link => {
......@@ -3009,6 +3016,20 @@ fn buildOutputType(
30093016 }
30103017 }
30113018 },
3019 .version => {
3020 // We can't allow control flow to reach the simpler logic
3021 // below because the -target argument has to be lowered to
3022 // clang syntax in Compilation.
3023 create_module.opts.output_mode = .Obj;
3024 clang_preprocessor_mode = .version;
3025 if (create_module.c_source_files.items.len == 0) {
3026 try create_module.c_source_files.append(arena, .{
3027 .owner = undefined,
3028 .src_path = "a.c", // dummy name
3029 .ext = .c,
3030 });
3031 }
3032 },
30123033 }
30133034 if (create_module.c_source_files.items.len == 0 and
30143035 !anyObjectLinkInputs(create_module.cli_link_inputs.items) and
tools/update_clang_options.zig+4
......@@ -590,6 +590,10 @@ const known_options = [_]KnownOpt{
590590 .name = "dynamic",
591591 .ident = "dynamic",
592592 },
593 .{
594 .name = "version",
595 .ident = "version",
596 },
593597};
594598
595599const blacklisted_options = [_][]const u8{};