Skip to content

Commit d35a562

Browse files
committed
std.Build: add precompiled C header creation
1 parent 650a335 commit d35a562

File tree

3 files changed

+59
-12
lines changed

3 files changed

+59
-12
lines changed

lib/std/Build.zig

+25
Original file line numberDiff line numberDiff line change
@@ -741,6 +741,31 @@ pub fn addObject(b: *Build, options: ObjectOptions) *Step.Compile {
741741
});
742742
}
743743

744+
pub const PchOptions = struct {
745+
name: []const u8,
746+
target: ResolvedTarget,
747+
optimize: std.builtin.OptimizeMode,
748+
max_rss: usize = 0,
749+
link_libc: ?bool = null,
750+
link_libcpp: ?bool = null,
751+
};
752+
753+
pub fn addPrecompiledCHeader(b: *Build, options: PchOptions, source: Module.CSourceFile) *Step.Compile {
754+
const pch = Step.Compile.create(b, .{
755+
.name = options.name,
756+
.root_module = .{
757+
.target = options.target,
758+
.optimize = options.optimize,
759+
.link_libc = options.link_libc,
760+
.link_libcpp = options.link_libcpp,
761+
},
762+
.kind = .pch,
763+
.max_rss = options.max_rss,
764+
});
765+
pch.addCSourceFile(source);
766+
return pch;
767+
}
768+
744769
pub const SharedLibraryOptions = struct {
745770
name: []const u8,
746771
/// To choose the same computer as the one building the package, pass the

lib/std/Build/Step/Compile.zig

+33-11
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,7 @@ pub const Kind = enum {
254254
exe,
255255
lib,
256256
obj,
257+
pch,
257258
@"test",
258259
};
259260

@@ -337,24 +338,29 @@ pub fn create(owner: *std.Build, options: Options) *Compile {
337338
.exe => "zig build-exe",
338339
.lib => "zig build-lib",
339340
.obj => "zig build-obj",
341+
.pch => "zig build-pch",
340342
.@"test" => "zig test",
341343
},
342344
name_adjusted,
343345
@tagName(options.root_module.optimize orelse .Debug),
344346
resolved_target.query.zigTriple(owner.allocator) catch @panic("OOM"),
345347
});
346348

347-
const out_filename = std.zig.binNameAlloc(owner.allocator, .{
348-
.root_name = name,
349-
.target = target,
350-
.output_mode = switch (options.kind) {
351-
.lib => .Lib,
352-
.obj => .Obj,
353-
.exe, .@"test" => .Exe,
354-
},
355-
.link_mode = options.linkage,
356-
.version = options.version,
357-
}) catch @panic("OOM");
349+
const out_filename = if (options.kind == .pch)
350+
std.fmt.allocPrint(owner.allocator, "{s}.pch", .{name}) catch @panic("OOM")
351+
else
352+
std.zig.binNameAlloc(owner.allocator, .{
353+
.root_name = name,
354+
.target = target,
355+
.output_mode = switch (options.kind) {
356+
.lib => .Lib,
357+
.obj => .Obj,
358+
.exe, .@"test" => .Exe,
359+
.pch => unreachable,
360+
},
361+
.link_mode = options.linkage,
362+
.version = options.version,
363+
}) catch @panic("OOM");
358364

359365
const compile = owner.allocator.create(Compile) catch @panic("OOM");
360366
compile.* = .{
@@ -780,17 +786,20 @@ pub fn linkFrameworkWeak(c: *Compile, name: []const u8) void {
780786

781787
/// Handy when you have many C/C++ source files and want them all to have the same flags.
782788
pub fn addCSourceFiles(compile: *Compile, options: Module.AddCSourceFilesOptions) void {
789+
assert(compile.kind != .pch); // pch can only be generated from a single C header file
783790
compile.root_module.addCSourceFiles(options);
784791
}
785792

786793
pub fn addCSourceFile(compile: *Compile, source: Module.CSourceFile) void {
794+
assert(compile.kind != .pch or compile.root_module.link_objects.items.len == 0); // pch can only be generated from a single C header file
787795
compile.root_module.addCSourceFile(source);
788796
}
789797

790798
/// Resource files must have the extension `.rc`.
791799
/// Can be called regardless of target. The .rc file will be ignored
792800
/// if the target object format does not support embedded resources.
793801
pub fn addWin32ResourceFile(compile: *Compile, source: Module.RcSourceFile) void {
802+
assert(compile.kind != .pch); // pch can only be generated from a single C header file
794803
compile.root_module.addWin32ResourceFile(source);
795804
}
796805

@@ -871,14 +880,17 @@ pub fn getEmittedLlvmBc(compile: *Compile) LazyPath {
871880
}
872881

873882
pub fn addAssemblyFile(compile: *Compile, source: LazyPath) void {
883+
assert(compile.kind != .pch); // pch can only be generated from a single C header file
874884
compile.root_module.addAssemblyFile(source);
875885
}
876886

877887
pub fn addObjectFile(compile: *Compile, source: LazyPath) void {
888+
assert(compile.kind != .pch); // pch can only be generated from a single C header file
878889
compile.root_module.addObjectFile(source);
879890
}
880891

881892
pub fn addObject(compile: *Compile, object: *Compile) void {
893+
assert(compile.kind != .pch); // pch can only be generated from a single C header file
882894
compile.root_module.addObject(object);
883895
}
884896

@@ -1003,6 +1015,7 @@ fn getZigArgs(compile: *Compile) ![][]const u8 {
10031015
.lib => "build-lib",
10041016
.exe => "build-exe",
10051017
.obj => "build-obj",
1018+
.pch => "build-pch",
10061019
.@"test" => "test",
10071020
};
10081021
try zig_args.append(cmd);
@@ -1065,6 +1078,14 @@ fn getZigArgs(compile: *Compile) ![][]const u8 {
10651078
}
10661079
}
10671080

1081+
if (compile.kind == .pch) {
1082+
// precompiled headers must have a single input header file.
1083+
var it = compile.root_module.iterateDependencies(compile, false);
1084+
const link_objects = it.next().?.module.link_objects;
1085+
assert(link_objects.items.len == 1 and link_objects.items[0] == .c_source_file);
1086+
assert(it.next() == null);
1087+
}
1088+
10681089
var cli_named_modules = try CliNamedModules.init(arena, &compile.root_module);
10691090

10701091
// For this loop, don't chase dynamic libraries because their link
@@ -1170,6 +1191,7 @@ fn getZigArgs(compile: *Compile) ![][]const u8 {
11701191
switch (other.kind) {
11711192
.exe => return step.fail("cannot link with an executable build artifact", .{}),
11721193
.@"test" => return step.fail("cannot link with a test", .{}),
1194+
.pch => @panic("Cannot link with a precompiled header file"),
11731195
.obj => {
11741196
const included_in_lib_or_obj = !my_responsibility and
11751197
(dep.compile.?.kind == .lib or dep.compile.?.kind == .obj);

lib/std/Build/Step/InstallArtifact.zig

+1-1
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ pub fn create(owner: *std.Build, artifact: *Step.Compile, options: Options) *Ins
5656
const dest_dir: ?InstallDir = switch (options.dest_dir) {
5757
.disabled => null,
5858
.default => switch (artifact.kind) {
59-
.obj => @panic("object files have no standard installation procedure"),
59+
.obj, .pch => @panic("object files have no standard installation procedure"),
6060
.exe, .@"test" => .bin,
6161
.lib => if (artifact.isDll()) .bin else .lib,
6262
},

0 commit comments

Comments
 (0)