Skip to content

Commit 9c51931

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

File tree

9 files changed

+174
-2
lines changed

9 files changed

+174
-2
lines changed

lib/std/Build/Module.zig

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

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

137139
pub fn dupe(self: CSourceFile, b: *std.Build) CSourceFile {
138140
return .{
139141
.file = self.file.dupe(b),
140142
.lang = self.lang,
141143
.flags = b.dupeStrings(self.flags),
144+
.precompiled_header = self.precompiled_header,
142145
};
143146
}
144147
};
@@ -504,6 +507,7 @@ pub const AddCSourceFilesOptions = struct {
504507
files: []const []const u8,
505508
lang: ?CSourceLang = null,
506509
flags: []const []const u8 = &.{},
510+
precompiled_header: ?LazyPath = null,
507511
};
508512

509513
/// Handy when you have many C/C++ source files and want them all to have the same flags.
@@ -516,8 +520,13 @@ pub fn addCSourceFiles(m: *Module, options: AddCSourceFilesOptions) void {
516520
.files = b.dupeStrings(options.files),
517521
.lang = options.lang,
518522
.flags = b.dupeStrings(options.flags),
523+
.precompiled_header = options.precompiled_header,
519524
};
520525
m.link_objects.append(allocator, .{ .c_source_files = c_source_files }) catch @panic("OOM");
526+
527+
if (options.precompiled_header) |pch| {
528+
addLazyPathDependenciesOnly(m, pch);
529+
}
521530
}
522531

523532
pub fn addCSourceFile(m: *Module, source: CSourceFile) void {
@@ -527,6 +536,10 @@ pub fn addCSourceFile(m: *Module, source: CSourceFile) void {
527536
c_source_file.* = source.dupe(b);
528537
m.link_objects.append(allocator, .{ .c_source_file = c_source_file }) catch @panic("OOM");
529538
addLazyPathDependenciesOnly(m, source.file);
539+
540+
if (source.precompiled_header) |pch| {
541+
addLazyPathDependenciesOnly(m, pch);
542+
}
530543
}
531544

532545
/// 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
@@ -1151,7 +1151,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
11511151
.c_source_file => |c_source_file| l: {
11521152
if (!my_responsibility) break :l;
11531153

1154-
if (c_source_file.flags.len == 0) {
1154+
if (c_source_file.flags.len == 0 and c_source_file.precompiled_header == null) {
11551155
if (prev_has_cflags) {
11561156
try zig_args.append("-cflags");
11571157
try zig_args.append("--");
@@ -1162,6 +1162,11 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
11621162
for (c_source_file.flags) |arg| {
11631163
try zig_args.append(arg);
11641164
}
1165+
if (c_source_file.precompiled_header) |pch| {
1166+
try zig_args.append("-include-pch");
1167+
try zig_args.append(pch.getPath(b));
1168+
try zig_args.append("-fpch-validate-input-files-content");
1169+
}
11651170
try zig_args.append("--");
11661171
prev_has_cflags = true;
11671172
}
@@ -1178,7 +1183,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
11781183
.c_source_files => |c_source_files| l: {
11791184
if (!my_responsibility) break :l;
11801185

1181-
if (c_source_files.flags.len == 0) {
1186+
if (c_source_files.flags.len == 0 and c_source_files.precompiled_header == null) {
11821187
if (prev_has_cflags) {
11831188
try zig_args.append("-cflags");
11841189
try zig_args.append("--");
@@ -1189,6 +1194,13 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
11891194
for (c_source_files.flags) |flag| {
11901195
try zig_args.append(flag);
11911196
}
1197+
1198+
if (c_source_files.precompiled_header) |pch| {
1199+
try zig_args.append("-include-pch");
1200+
try zig_args.append(pch.getPath(b));
1201+
try zig_args.append("-fpch-validate-input-files-content");
1202+
}
1203+
11921204
try zig_args.append("--");
11931205
prev_has_cflags = true;
11941206
}

test/standalone.zig

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,10 @@ pub const build_cases = [_]BuildCase{
265265
.build_root = "test/standalone/depend_on_main_mod",
266266
.import = @import("standalone/depend_on_main_mod/build.zig"),
267267
},
268+
.{
269+
.build_root = "test/standalone/pch",
270+
.import = @import("standalone/pch/build.zig"),
271+
},
268272
};
269273

270274
const std = @import("std");

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/include_c.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 <string.h>
4+
5+
#define C_INCLUDED 1
6+
7+
int one = 3;

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)