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 {...@@ -1121,6 +1121,7 @@ pub const ClangCliParam = struct {
1121 rtlib,1121 rtlib,
1122 static,1122 static,
1123 dynamic,1123 dynamic,
1124 version,
1124 };1125 };
11251126
1126 pub fn matchEql(self: @This(), arg: []const u8) u2 {1127 pub fn matchEql(self: @This(), arg: []const u8) u2 {
src/Compilation.zig+16-11
...@@ -1471,6 +1471,8 @@ pub const ClangPreprocessorMode = enum {...@@ -1471,6 +1471,8 @@ pub const ClangPreprocessorMode = enum {
1471 stdout,1471 stdout,
1472 /// precompiled C header1472 /// precompiled C header
1473 pch,1473 pch,
1474 /// `--version`
1475 version,
1474};1476};
14751477
1476pub const Framework = link.File.MachO.Framework;1478pub const Framework = link.File.MachO.Framework;
...@@ -2936,16 +2938,16 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateE...@@ -2936,16 +2938,16 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateE
2936 .none => unreachable,2938 .none => unreachable,
2937 .manifest_create, .manifest_read, .manifest_lock => |e| return comp.setMiscFailure(2939 .manifest_create, .manifest_read, .manifest_lock => |e| return comp.setMiscFailure(
2938 .check_whole_cache,2940 .check_whole_cache,
2939 "failed to check cache: {s} {s}",2941 "failed to check cache: {t} {t}",
2940 .{ @tagName(man.diagnostic), @errorName(e) },2942 .{ man.diagnostic, e },
2941 ),2943 ),
2942 .file_open, .file_stat, .file_read, .file_hash => |op| {2944 .file_open, .file_stat, .file_read, .file_hash => |op| {
2943 const pp = man.files.keys()[op.file_index].prefixed_path;2945 const pp = man.files.keys()[op.file_index].prefixed_path;
2944 const prefix = man.cache.prefixes()[pp.prefix];2946 const prefix = man.cache.prefixes()[pp.prefix];
2945 return comp.setMiscFailure(2947 return comp.setMiscFailure(
2946 .check_whole_cache,2948 .check_whole_cache,
2947 "failed to check cache: '{f}{s}' {s} {s}",2949 "failed to check cache: '{f}{s}' {t} {t}",
2948 .{ prefix, pp.sub_path, @tagName(man.diagnostic), @errorName(op.err) },2950 .{ prefix, pp.sub_path, man.diagnostic, op.err },
2949 );2951 );
2950 },2952 },
2951 },2953 },
...@@ -5739,6 +5741,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr...@@ -5739,6 +5741,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr
5739 .yes => argv.appendSliceAssumeCapacity(&.{ "-E", "-o", out_obj_path }),5741 .yes => argv.appendSliceAssumeCapacity(&.{ "-E", "-o", out_obj_path }),
5740 .pch => argv.appendSliceAssumeCapacity(&.{ "-Xclang", "-emit-pch", "-o", out_obj_path }),5742 .pch => argv.appendSliceAssumeCapacity(&.{ "-Xclang", "-emit-pch", "-o", out_obj_path }),
5741 .stdout => argv.appendAssumeCapacity("-E"),5743 .stdout => argv.appendAssumeCapacity("-E"),
5744 .version => argv.appendAssumeCapacity("--version"),
5742 }5745 }
57435746
5744 if (comp.emit_asm != null) {5747 if (comp.emit_asm != null) {
...@@ -5782,6 +5785,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr...@@ -5782,6 +5785,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr
5782 .yes => argv.appendSliceAssumeCapacity(&.{ "-E", "-o", out_obj_path }),5785 .yes => argv.appendSliceAssumeCapacity(&.{ "-E", "-o", out_obj_path }),
5783 .pch => argv.appendSliceAssumeCapacity(&.{ "-Xclang", "-emit-pch", "-o", out_obj_path }),5786 .pch => argv.appendSliceAssumeCapacity(&.{ "-Xclang", "-emit-pch", "-o", out_obj_path }),
5784 .stdout => argv.appendAssumeCapacity("-E"),5787 .stdout => argv.appendAssumeCapacity("-E"),
5788 .version => argv.appendAssumeCapacity("--version"),
5785 }5789 }
5786 if (out_diag_path) |diag_file_path| {5790 if (out_diag_path) |diag_file_path| {
5787 argv.appendSliceAssumeCapacity(&.{ "--serialize-diagnostics", diag_file_path });5791 argv.appendSliceAssumeCapacity(&.{ "--serialize-diagnostics", diag_file_path });
...@@ -5830,8 +5834,10 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr...@@ -5830,8 +5834,10 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr
5830 if (code != 0) {5834 if (code != 0) {
5831 std.process.exit(code);5835 std.process.exit(code);
5832 }5836 }
5833 if (comp.clang_preprocessor_mode == .stdout)5837 switch (comp.clang_preprocessor_mode) {
5834 std.process.exit(0);5838 .stdout, .version => std.process.exit(0),
5839 else => {},
5840 }
5835 },5841 },
5836 else => std.process.abort(),5842 else => std.process.abort(),
5837 }5843 }
...@@ -5879,11 +5885,10 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr...@@ -5879,11 +5885,10 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr
5879 return comp.failCObj(c_object, "clang exited with code {d}", .{exit_code});5885 return comp.failCObj(c_object, "clang exited with code {d}", .{exit_code});
5880 }5886 }
5881 }5887 }
5882 if (comp.clang_passthrough_mode and5888 if (comp.clang_passthrough_mode) switch (comp.clang_preprocessor_mode) {
5883 comp.clang_preprocessor_mode == .stdout)5889 .stdout, .version => std.process.exit(0),
5884 {5890 else => {},
5885 std.process.exit(0);5891 };
5886 }
5887 }5892 }
58885893
5889 if (out_dep_path) |dep_file_path| {5894 if (out_dep_path) |dep_file_path| {
src/clang_options.zon+2-1
...@@ -637,6 +637,7 @@...@@ -637,6 +637,7 @@
637},637},
638.{638.{
639 .name = "version",639 .name = "version",
640 .ze = .version,
640 .pd1 = false,641 .pd1 = false,
641 .pd2 = true,642 .pd2 = true,
642},643},
...@@ -3378,7 +3379,7 @@...@@ -3378,7 +3379,7 @@
3378},3379},
3379.{ .name = "verify-ignore-unexpected" },3380.{ .name = "verify-ignore-unexpected" },
3380.{ .name = "verify-pch" },3381.{ .name = "verify-pch" },
3381.{ .name = "version" },3382.{ .name = "version", .ze = .version },
3382.{ .name = "via-file-asm", .pd2 = true },3383.{ .name = "via-file-asm", .pd2 = true },
3383.{ .name = "w" },3384.{ .name = "w" },
3384.{3385.{
src/main.zig+24-3
...@@ -1889,6 +1889,7 @@ fn buildOutputType(...@@ -1889,6 +1889,7 @@ fn buildOutputType(
1889 object,1889 object,
1890 assembly,1890 assembly,
1891 preprocessor,1891 preprocessor,
1892 version,
1892 };1893 };
1893 var c_out_mode: ?COutMode = null;1894 var c_out_mode: ?COutMode = null;
1894 var out_path: ?[]const u8 = null;1895 var out_path: ?[]const u8 = null;
...@@ -1917,6 +1918,10 @@ fn buildOutputType(...@@ -1917,6 +1918,10 @@ fn buildOutputType(
1917 .c, .r => c_out_mode = .object, // -c or -r1918 .c, .r => c_out_mode = .object, // -c or -r
1918 .asm_only => c_out_mode = .assembly, // -S1919 .asm_only => c_out_mode = .assembly, // -S
1919 .preprocess_only => c_out_mode = .preprocessor, // -E1920 .preprocess_only => c_out_mode = .preprocessor, // -E
1921 .version => {
1922 c_out_mode = .version; // --version
1923 disable_c_depfile = true;
1924 },
1920 .emit_llvm => emit_llvm = true,1925 .emit_llvm => emit_llvm = true,
1921 .x => {1926 .x => {
1922 const lang = mem.sliceTo(it.only_arg, 0);1927 const lang = mem.sliceTo(it.only_arg, 0);
...@@ -2939,9 +2944,11 @@ fn buildOutputType(...@@ -2939,9 +2944,11 @@ fn buildOutputType(
2939 }2944 }
29402945
2941 // precompiled header syntax: "zig cc -x c-header test.h -o test.pch"2946 // 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);2947 const emit_pch = if (file_ext) |fe| switch (fe) {
2943 if (emit_pch)2948 .h, .hpp, .hm, .hmm => c_out_mode == null,
2944 c_out_mode = .preprocessor;2949 else => false,
2950 } else false;
2951 if (emit_pch) c_out_mode = .preprocessor;
29452952
2946 switch (c_out_mode orelse .link) {2953 switch (c_out_mode orelse .link) {
2947 .link => {2954 .link => {
...@@ -3009,6 +3016,20 @@ fn buildOutputType(...@@ -3009,6 +3016,20 @@ fn buildOutputType(
3009 }3016 }
3010 }3017 }
3011 },3018 },
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 },
3012 }3033 }
3013 if (create_module.c_source_files.items.len == 0 and3034 if (create_module.c_source_files.items.len == 0 and
3014 !anyObjectLinkInputs(create_module.cli_link_inputs.items) and3035 !anyObjectLinkInputs(create_module.cli_link_inputs.items) and
tools/update_clang_options.zig+4
...@@ -590,6 +590,10 @@ const known_options = [_]KnownOpt{...@@ -590,6 +590,10 @@ const known_options = [_]KnownOpt{
590 .name = "dynamic",590 .name = "dynamic",
591 .ident = "dynamic",591 .ident = "dynamic",
592 },592 },
593 .{
594 .name = "version",
595 .ident = "version",
596 },
593};597};
594598
595const blacklisted_options = [_][]const u8{};599const blacklisted_options = [_][]const u8{};