mirror of
https://github.com/ziglang/zig.git
synced 2026-02-13 04:48:20 +00:00
zig cc: expose clang precompiled C header support
see https://releases.llvm.org/17.0.1/tools/clang/docs/UsersManual.html#generating-a-pch-file syntax examples: `zig cc -x c-header test.h -o test.pch` `zig cc -include-pch test.pch main.c` `zig c++ -x c++-header test.h -o test.pch` `zig c++ -include-pch test.pch main.cpp`
This commit is contained in:
parent
314533c28b
commit
1a98fcd00a
@ -270,11 +270,11 @@ pub const LangToExt = std.ComptimeStringMap(FileExt, .{
|
||||
.{ "c", .c },
|
||||
.{ "c-header", .h },
|
||||
.{ "c++", .cpp },
|
||||
.{ "c++-header", .h },
|
||||
.{ "c++-header", .hpp },
|
||||
.{ "objective-c", .m },
|
||||
.{ "objective-c-header", .h },
|
||||
.{ "objective-c-header", .hm },
|
||||
.{ "objective-c++", .mm },
|
||||
.{ "objective-c++-header", .h },
|
||||
.{ "objective-c++-header", .hmm },
|
||||
.{ "assembler", .assembly },
|
||||
.{ "assembler-with-cpp", .assembly_with_cpp },
|
||||
.{ "cuda", .cu },
|
||||
@ -887,6 +887,8 @@ pub const ClangPreprocessorMode = enum {
|
||||
yes,
|
||||
/// This means we are doing `zig cc -E`.
|
||||
stdout,
|
||||
/// precompiled C header
|
||||
pch,
|
||||
};
|
||||
|
||||
pub const Framework = link.File.MachO.Framework;
|
||||
@ -4393,6 +4395,10 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: *std.P
|
||||
.assembly_with_cpp => "assembler-with-cpp",
|
||||
.c => "c",
|
||||
.cpp => "c++",
|
||||
.h => "c-header",
|
||||
.hpp => "c++-header",
|
||||
.hm => "objective-c-header",
|
||||
.hmm => "objective-c++-header",
|
||||
.cu => "cuda",
|
||||
.m => "objective-c",
|
||||
.mm => "objective-c++",
|
||||
@ -4418,10 +4424,11 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: *std.P
|
||||
else
|
||||
"/dev/null";
|
||||
|
||||
try argv.ensureUnusedCapacity(5);
|
||||
try argv.ensureUnusedCapacity(6);
|
||||
switch (comp.clang_preprocessor_mode) {
|
||||
.no => argv.appendSliceAssumeCapacity(&[_][]const u8{ "-c", "-o", out_obj_path }),
|
||||
.yes => argv.appendSliceAssumeCapacity(&[_][]const u8{ "-E", "-o", out_obj_path }),
|
||||
.no => argv.appendSliceAssumeCapacity(&.{ "-c", "-o", out_obj_path }),
|
||||
.yes => argv.appendSliceAssumeCapacity(&.{ "-E", "-o", out_obj_path }),
|
||||
.pch => argv.appendSliceAssumeCapacity(&.{ "-Xclang", "-emit-pch", "-o", out_obj_path }),
|
||||
.stdout => argv.appendAssumeCapacity("-E"),
|
||||
}
|
||||
|
||||
@ -4456,10 +4463,11 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: *std.P
|
||||
try argv.appendSlice(c_object.src.extra_flags);
|
||||
try argv.appendSlice(c_object.src.cache_exempt_flags);
|
||||
|
||||
try argv.ensureUnusedCapacity(5);
|
||||
try argv.ensureUnusedCapacity(6);
|
||||
switch (comp.clang_preprocessor_mode) {
|
||||
.no => argv.appendSliceAssumeCapacity(&.{ "-c", "-o", out_obj_path }),
|
||||
.yes => argv.appendSliceAssumeCapacity(&.{ "-E", "-o", out_obj_path }),
|
||||
.pch => argv.appendSliceAssumeCapacity(&.{ "-Xclang", "-emit-pch", "-o", out_obj_path }),
|
||||
.stdout => argv.appendAssumeCapacity("-E"),
|
||||
}
|
||||
if (comp.clang_passthrough_mode) {
|
||||
@ -5101,7 +5109,7 @@ pub fn addCCArgs(
|
||||
try argv.appendSlice(&[_][]const u8{ "-target", llvm_triple });
|
||||
|
||||
if (target.os.tag == .windows) switch (ext) {
|
||||
.c, .cpp, .m, .mm, .h, .cu, .rc, .assembly, .assembly_with_cpp => {
|
||||
.c, .cpp, .m, .mm, .h, .hpp, .hm, .hmm, .cu, .rc, .assembly, .assembly_with_cpp => {
|
||||
const minver: u16 = @truncate(@intFromEnum(target.os.getVersionRange().windows.min) >> 16);
|
||||
try argv.append(
|
||||
try std.fmt.allocPrint(arena, "-D_WIN32_WINNT=0x{x:0>4}", .{minver}),
|
||||
@ -5111,7 +5119,7 @@ pub fn addCCArgs(
|
||||
};
|
||||
|
||||
switch (ext) {
|
||||
.c, .cpp, .m, .mm, .h, .cu, .rc => {
|
||||
.c, .cpp, .m, .mm, .h, .hpp, .hm, .hmm, .cu, .rc => {
|
||||
try argv.appendSlice(&[_][]const u8{
|
||||
"-nostdinc",
|
||||
"-fno-spell-checking",
|
||||
@ -5679,6 +5687,9 @@ pub const FileExt = enum {
|
||||
cpp,
|
||||
cu,
|
||||
h,
|
||||
hpp,
|
||||
hm,
|
||||
hmm,
|
||||
m,
|
||||
mm,
|
||||
ll,
|
||||
@ -5697,7 +5708,7 @@ pub const FileExt = enum {
|
||||
|
||||
pub fn clangSupportsDepFile(ext: FileExt) bool {
|
||||
return switch (ext) {
|
||||
.c, .cpp, .h, .m, .mm, .cu => true,
|
||||
.c, .cpp, .h, .hpp, .hm, .hmm, .m, .mm, .cu => true,
|
||||
|
||||
.ll,
|
||||
.bc,
|
||||
@ -5722,6 +5733,9 @@ pub const FileExt = enum {
|
||||
.cpp => ".cpp",
|
||||
.cu => ".cu",
|
||||
.h => ".h",
|
||||
.hpp => ".h",
|
||||
.hm => ".h",
|
||||
.hmm => ".h",
|
||||
.m => ".m",
|
||||
.mm => ".mm",
|
||||
.ll => ".ll",
|
||||
|
||||
@ -554,7 +554,7 @@ pub const File = struct {
|
||||
return @fieldParentPtr(C, "base", base).flush(arena, prog_node);
|
||||
}
|
||||
const comp = base.comp;
|
||||
if (comp.clang_preprocessor_mode == .yes) {
|
||||
if (comp.clang_preprocessor_mode == .yes or comp.clang_preprocessor_mode == .pch) {
|
||||
const gpa = comp.gpa;
|
||||
const emit = base.emit;
|
||||
// TODO: avoid extra link step when it's just 1 object file (the `zig cc -c` case)
|
||||
|
||||
43
src/main.zig
43
src/main.zig
@ -1694,7 +1694,7 @@ fn buildOutputType(
|
||||
fatal("only one manifest file can be specified, found '{s}' after '{s}'", .{ arg, other });
|
||||
} else manifest_file = arg;
|
||||
},
|
||||
.assembly, .assembly_with_cpp, .c, .cpp, .h, .ll, .bc, .m, .mm, .cu => {
|
||||
.assembly, .assembly_with_cpp, .c, .cpp, .h, .hpp, .hm, .hmm, .ll, .bc, .m, .mm, .cu => {
|
||||
try create_module.c_source_files.append(arena, .{
|
||||
// Populated after module creation.
|
||||
.owner = undefined,
|
||||
@ -1746,7 +1746,7 @@ fn buildOutputType(
|
||||
assembly,
|
||||
preprocessor,
|
||||
};
|
||||
var c_out_mode: COutMode = .link;
|
||||
var c_out_mode: ?COutMode = null;
|
||||
var out_path: ?[]const u8 = null;
|
||||
var is_shared_lib = false;
|
||||
var linker_args = std.ArrayList([]const u8).init(arena);
|
||||
@ -1789,7 +1789,7 @@ fn buildOutputType(
|
||||
try cc_argv.appendSlice(arena, it.other_args);
|
||||
},
|
||||
.positional => switch (file_ext orelse Compilation.classifyFileExt(mem.sliceTo(it.only_arg, 0))) {
|
||||
.assembly, .assembly_with_cpp, .c, .cpp, .ll, .bc, .h, .m, .mm, .cu => {
|
||||
.assembly, .assembly_with_cpp, .c, .cpp, .ll, .bc, .h, .hpp, .hm, .hmm, .m, .mm, .cu => {
|
||||
try create_module.c_source_files.append(arena, .{
|
||||
// Populated after module creation.
|
||||
.owner = undefined,
|
||||
@ -2462,7 +2462,12 @@ fn buildOutputType(
|
||||
}
|
||||
}
|
||||
|
||||
switch (c_out_mode) {
|
||||
// precompiled header syntax: "zig cc -x c-header test.h -o test.pch"
|
||||
const emit_pch = ((file_ext == .h or file_ext == .hpp or file_ext == .hm or file_ext == .hmm) and c_out_mode == null);
|
||||
if (emit_pch)
|
||||
c_out_mode = .preprocessor;
|
||||
|
||||
switch (c_out_mode orelse .link) {
|
||||
.link => {
|
||||
create_module.opts.output_mode = if (is_shared_lib) .Lib else .Exe;
|
||||
emit_bin = if (out_path) |p| .{ .yes = p } else EmitBin.yes_a_out;
|
||||
@ -2511,11 +2516,16 @@ fn buildOutputType(
|
||||
// For example `zig cc` and no args should print the "no input files" message.
|
||||
return process.exit(try clangMain(arena, all_args));
|
||||
}
|
||||
if (out_path) |p| {
|
||||
emit_bin = .{ .yes = p };
|
||||
clang_preprocessor_mode = .yes;
|
||||
if (emit_pch) {
|
||||
emit_bin = if (out_path) |p| .{ .yes = p } else .yes_default_path;
|
||||
clang_preprocessor_mode = .pch;
|
||||
} else {
|
||||
clang_preprocessor_mode = .stdout;
|
||||
if (out_path) |p| {
|
||||
emit_bin = .{ .yes = p };
|
||||
clang_preprocessor_mode = .yes;
|
||||
} else {
|
||||
clang_preprocessor_mode = .stdout;
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
@ -2882,13 +2892,16 @@ fn buildOutputType(
|
||||
},
|
||||
}
|
||||
},
|
||||
.basename = try std.zig.binNameAlloc(arena, .{
|
||||
.root_name = root_name,
|
||||
.target = target,
|
||||
.output_mode = create_module.resolved_options.output_mode,
|
||||
.link_mode = create_module.resolved_options.link_mode,
|
||||
.version = optional_version,
|
||||
}),
|
||||
.basename = if (clang_preprocessor_mode == .pch)
|
||||
try std.fmt.allocPrint(arena, "{s}.pch", .{root_name})
|
||||
else
|
||||
try std.zig.binNameAlloc(arena, .{
|
||||
.root_name = root_name,
|
||||
.target = target,
|
||||
.output_mode = create_module.resolved_options.output_mode,
|
||||
.link_mode = create_module.resolved_options.link_mode,
|
||||
.version = optional_version,
|
||||
}),
|
||||
},
|
||||
.yes => |full_path| b: {
|
||||
const basename = fs.path.basename(full_path);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user