Skip to content

Commit ac05328

Browse files
committed
std.Build: add an option to addCSourceFiles() to include a precompiled header
1 parent bf04bae commit ac05328

File tree

8 files changed

+166
-2
lines changed

8 files changed

+166
-2
lines changed

lib/std/Build/Module.zig

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,18 +126,21 @@ pub const CSourceFiles = struct {
126126
files: []const []const u8,
127127
lang: ?CSourceLang = null,
128128
flags: []const []const u8,
129+
precompiled_header: ?LazyPath = null,
129130
};
130131

131132
pub const CSourceFile = struct {
132133
file: LazyPath,
133134
lang: ?CSourceLang = null,
134135
flags: []const []const u8 = &.{},
136+
precompiled_header: ?LazyPath = null,
135137

136138
pub fn dupe(self: CSourceFile, b: *std.Build) CSourceFile {
137139
return .{
138140
.file = self.file.dupe(b),
139141
.lang = self.lang,
140142
.flags = b.dupeStrings(self.flags),
143+
.precompiled_header = self.precompiled_header,
141144
};
142145
}
143146
};
@@ -500,6 +503,7 @@ pub const AddCSourceFilesOptions = struct {
500503
files: []const []const u8,
501504
lang: ?CSourceLang = null,
502505
flags: []const []const u8 = &.{},
506+
precompiled_header: ?LazyPath = null,
503507
};
504508

505509
/// Handy when you have many C/C++ source files and want them all to have the same flags.
@@ -522,8 +526,13 @@ pub fn addCSourceFiles(m: *Module, options: AddCSourceFilesOptions) void {
522526
.files = b.dupeStrings(options.files),
523527
.lang = options.lang,
524528
.flags = b.dupeStrings(options.flags),
529+
.precompiled_header = options.precompiled_header,
525530
};
526531
m.link_objects.append(allocator, .{ .c_source_files = c_source_files }) catch @panic("OOM");
532+
533+
if (options.precompiled_header) |pch| {
534+
addLazyPathDependenciesOnly(m, pch);
535+
}
527536
}
528537

529538
pub fn addCSourceFile(m: *Module, source: CSourceFile) void {
@@ -533,6 +542,10 @@ pub fn addCSourceFile(m: *Module, source: CSourceFile) void {
533542
c_source_file.* = source.dupe(b);
534543
m.link_objects.append(allocator, .{ .c_source_file = c_source_file }) catch @panic("OOM");
535544
addLazyPathDependenciesOnly(m, source.file);
545+
546+
if (source.precompiled_header) |pch| {
547+
addLazyPathDependenciesOnly(m, pch);
548+
}
536549
}
537550

538551
/// Resource files must have the extension `.rc`.

lib/std/Build/Step/Compile.zig

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1281,7 +1281,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
12811281
.c_source_file => |c_source_file| l: {
12821282
if (!my_responsibility) break :l;
12831283

1284-
if (c_source_file.flags.len == 0) {
1284+
if (c_source_file.flags.len == 0 and c_source_file.precompiled_header == null) {
12851285
if (prev_has_cflags) {
12861286
try zig_args.append("-cflags");
12871287
try zig_args.append("--");
@@ -1292,6 +1292,11 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
12921292
for (c_source_file.flags) |arg| {
12931293
try zig_args.append(arg);
12941294
}
1295+
if (c_source_file.precompiled_header) |pch| {
1296+
try zig_args.append("-include-pch");
1297+
try zig_args.append(pch.getPath(b));
1298+
try zig_args.append("-fpch-validate-input-files-content");
1299+
}
12951300
try zig_args.append("--");
12961301
prev_has_cflags = true;
12971302
}
@@ -1308,7 +1313,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
13081313
.c_source_files => |c_source_files| l: {
13091314
if (!my_responsibility) break :l;
13101315

1311-
if (c_source_files.flags.len == 0) {
1316+
if (c_source_files.flags.len == 0 and c_source_files.precompiled_header == null) {
13121317
if (prev_has_cflags) {
13131318
try zig_args.append("-cflags");
13141319
try zig_args.append("--");
@@ -1319,6 +1324,13 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
13191324
for (c_source_files.flags) |flag| {
13201325
try zig_args.append(flag);
13211326
}
1327+
1328+
if (c_source_files.precompiled_header) |pch| {
1329+
try zig_args.append("-include-pch");
1330+
try zig_args.append(pch.getPath(b));
1331+
try zig_args.append("-fpch-validate-input-files-content");
1332+
}
1333+
13221334
try zig_args.append("--");
13231335
prev_has_cflags = true;
13241336
}

test/standalone/build.zig.zon

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,9 @@
155155
.install_headers = .{
156156
.path = "install_headers",
157157
},
158+
.precompiled_c_headers = .{
159+
.path = "pch",
160+
},
158161
},
159162
.paths = .{
160163
"build.zig",

test/standalone/pch/build.zig

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
const std = @import("std");
2+
3+
pub fn build(b: *std.Build) void {
4+
const test_step = b.step("test", "Test it");
5+
b.default_step = test_step;
6+
7+
const target = b.standardTargetOptions(.{});
8+
const optimize = b.standardOptimizeOption(.{});
9+
10+
// c-header
11+
{
12+
const exe = b.addExecutable(.{
13+
.name = "pchtest",
14+
.target = target,
15+
.optimize = optimize,
16+
.link_libc = true,
17+
});
18+
19+
const pch = b.addPrecompiledCHeader(.{
20+
.name = "pch_c",
21+
.target = target,
22+
.optimize = optimize,
23+
.link_libc = true,
24+
}, .{
25+
.file = .{ .path = "include_a.h" },
26+
.flags = &[_][]const u8{},
27+
.lang = .h,
28+
});
29+
30+
exe.addCSourceFiles(.{
31+
.files = &.{"test.c"},
32+
.flags = &[_][]const u8{},
33+
.lang = .c,
34+
.precompiled_header = pch.getEmittedBin(),
35+
});
36+
37+
test_step.dependOn(&b.addRunArtifact(exe).step);
38+
}
39+
40+
// c++-header
41+
{
42+
const exe = b.addExecutable(.{
43+
.name = "pchtest++",
44+
.target = target,
45+
.optimize = optimize,
46+
.link_libc = true,
47+
});
48+
exe.linkLibCpp();
49+
50+
const pch = b.addPrecompiledCHeader(.{
51+
.name = "pch_c++",
52+
.target = target,
53+
.optimize = optimize,
54+
.link_libcpp = true,
55+
}, .{
56+
.file = .{ .path = "include_a.h" },
57+
.flags = &[_][]const u8{},
58+
.lang = .hpp,
59+
});
60+
61+
exe.addCSourceFile(.{
62+
.file = .{ .path = "test.cpp" },
63+
.flags = &[_][]const u8{},
64+
.precompiled_header = pch.getEmittedBin(),
65+
});
66+
67+
test_step.dependOn(&b.addRunArtifact(exe).step);
68+
}
69+
}

test/standalone/pch/include_a.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#pragma once
2+
3+
#include "include_b.h"
4+
5+
#include <string.h>
6+
#include <stdlib.h>
7+
8+
#if defined(__cplusplus)
9+
#include <iostream>
10+
#else
11+
#include <stdio.h>
12+
#endif
13+
14+
#define A_INCLUDED 1
15+

test/standalone/pch/include_b.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#pragma once
2+
3+
#include <math.h>
4+
5+
typedef double real;
6+
7+
#define B_INCLUDED 1

test/standalone/pch/test.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
2+
// includes commented out to make sure the symbols come from the precompiled header.
3+
//#include "include_a.h"
4+
//#include "include_b.h"
5+
6+
#ifndef A_INCLUDED
7+
#error "pch not included"
8+
#endif
9+
#ifndef B_INCLUDED
10+
#error "pch not included"
11+
#endif
12+
13+
int main(int argc, char *argv[])
14+
{
15+
real a = 0.123;
16+
17+
if (argc > 1) {
18+
fprintf(stdout, "abs(%g)=%g\n", a, fabs(a));
19+
}
20+
21+
return EXIT_SUCCESS;
22+
}

test/standalone/pch/test.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
2+
// includes commented out to make sure the symbols come from the precompiled header.
3+
//#include "includeA.h"
4+
//#include "includeB.h"
5+
6+
#ifndef A_INCLUDED
7+
#error "pch not included"
8+
#endif
9+
#ifndef B_INCLUDED
10+
#error "pch not included"
11+
#endif
12+
13+
int main(int argc, char *argv[])
14+
{
15+
real a = -0.123;
16+
17+
if (argc > 1) {
18+
std::cout << "abs(" << a << ")=" << fabs(a) << "\n";
19+
}
20+
21+
return EXIT_SUCCESS;
22+
}
23+

0 commit comments

Comments
 (0)