Skip to content

Commit d91d6ed

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

File tree

7 files changed

+154
-3
lines changed

7 files changed

+154
-3
lines changed

lib/std/Build/Module.zig

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,18 +153,21 @@ pub const CSourceFiles = struct {
153153
files: []const []const u8,
154154
lang: ?CSourceLang = null,
155155
flags: []const []const u8,
156+
precompiled_header: ?LazyPath = null,
156157
};
157158

158159
pub const CSourceFile = struct {
159160
file: LazyPath,
160161
lang: ?CSourceLang = null,
161162
flags: []const []const u8 = &.{},
163+
precompiled_header: ?LazyPath = null,
162164

163165
pub fn dupe(file: CSourceFile, b: *std.Build) CSourceFile {
164166
return .{
165167
.file = file.file.dupe(b),
166168
.lang = file.lang,
167169
.flags = b.dupeStrings(file.flags),
170+
.precompiled_header = file.precompiled_header,
168171
};
169172
}
170173
};
@@ -557,6 +560,7 @@ pub const AddCSourceFilesOptions = struct {
557560
files: []const []const u8,
558561
lang: ?CSourceLang = null,
559562
flags: []const []const u8 = &.{},
563+
precompiled_header: ?LazyPath = null,
560564
};
561565

562566
/// Handy when you have many C/C++ source files and want them all to have the same flags.
@@ -579,9 +583,14 @@ pub fn addCSourceFiles(m: *Module, options: AddCSourceFilesOptions) void {
579583
.files = b.dupeStrings(options.files),
580584
.lang = options.lang,
581585
.flags = b.dupeStrings(options.flags),
586+
.precompiled_header = options.precompiled_header,
582587
};
583588
m.link_objects.append(allocator, .{ .c_source_files = c_source_files }) catch @panic("OOM");
584589
addLazyPathDependenciesOnly(m, c_source_files.root);
590+
591+
if (options.precompiled_header) |pch| {
592+
addLazyPathDependenciesOnly(m, pch);
593+
}
585594
}
586595

587596
pub fn addCSourceFile(m: *Module, source: CSourceFile) void {
@@ -591,6 +600,10 @@ pub fn addCSourceFile(m: *Module, source: CSourceFile) void {
591600
c_source_file.* = source.dupe(b);
592601
m.link_objects.append(allocator, .{ .c_source_file = c_source_file }) catch @panic("OOM");
593602
addLazyPathDependenciesOnly(m, source.file);
603+
604+
if (source.precompiled_header) |pch| {
605+
addLazyPathDependenciesOnly(m, pch);
606+
}
594607
}
595608

596609
/// 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
@@ -1290,7 +1290,7 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 {
12901290
.c_source_file => |c_source_file| l: {
12911291
if (!my_responsibility) break :l;
12921292

1293-
if (c_source_file.flags.len == 0) {
1293+
if (c_source_file.flags.len == 0 and c_source_file.precompiled_header == null) {
12941294
if (prev_has_cflags) {
12951295
try zig_args.append("-cflags");
12961296
try zig_args.append("--");
@@ -1301,6 +1301,11 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 {
13011301
for (c_source_file.flags) |arg| {
13021302
try zig_args.append(arg);
13031303
}
1304+
if (c_source_file.precompiled_header) |pch| {
1305+
try zig_args.append("-include-pch");
1306+
try zig_args.append(pch.getPath(b));
1307+
try zig_args.append("-fpch-validate-input-files-content");
1308+
}
13041309
try zig_args.append("--");
13051310
prev_has_cflags = true;
13061311
}
@@ -1322,7 +1327,7 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 {
13221327
.c_source_files => |c_source_files| l: {
13231328
if (!my_responsibility) break :l;
13241329

1325-
if (c_source_files.flags.len == 0) {
1330+
if (c_source_files.flags.len == 0 and c_source_files.precompiled_header == null) {
13261331
if (prev_has_cflags) {
13271332
try zig_args.append("-cflags");
13281333
try zig_args.append("--");
@@ -1333,6 +1338,13 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 {
13331338
for (c_source_files.flags) |flag| {
13341339
try zig_args.append(flag);
13351340
}
1341+
1342+
if (c_source_files.precompiled_header) |pch| {
1343+
try zig_args.append("-include-pch");
1344+
try zig_args.append(pch.getPath(b));
1345+
try zig_args.append("-fpch-validate-input-files-content");
1346+
}
1347+
13361348
try zig_args.append("--");
13371349
prev_has_cflags = true;
13381350
}

test/standalone/c_header/build.zig

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ pub fn build(b: *std.Build) void {
77
const target = b.standardTargetOptions(.{});
88
const optimize = b.standardOptimizeOption(.{});
99

10-
// single-file c-header library
10+
// testcase 1: single-file c-header library
1111
{
1212
const exe = b.addExecutable(.{
1313
.name = "single-file-library",
@@ -26,4 +26,63 @@ pub fn build(b: *std.Build) void {
2626

2727
test_step.dependOn(&b.addRunArtifact(exe).step);
2828
}
29+
30+
// testcase 2: precompiled c-header
31+
{
32+
const exe = b.addExecutable(.{
33+
.name = "pchtest",
34+
.target = target,
35+
.optimize = optimize,
36+
.link_libc = true,
37+
});
38+
39+
const pch = b.addPrecompiledCHeader(.{
40+
.name = "pch_c",
41+
.target = target,
42+
.optimize = optimize,
43+
.link_libc = true,
44+
}, .{
45+
.file = b.path("include_a.h"),
46+
.flags = &[_][]const u8{},
47+
.lang = .h,
48+
});
49+
50+
exe.addCSourceFiles(.{
51+
.files = &.{"test.c"},
52+
.flags = &[_][]const u8{},
53+
.lang = .c,
54+
.precompiled_header = pch.getEmittedBin(),
55+
});
56+
57+
test_step.dependOn(&b.addRunArtifact(exe).step);
58+
}
59+
60+
// testcase 3: precompiled c++-header
61+
{
62+
const exe = b.addExecutable(.{
63+
.name = "pchtest++",
64+
.target = target,
65+
.optimize = optimize,
66+
});
67+
exe.linkLibCpp();
68+
69+
const pch = b.addPrecompiledCHeader(.{
70+
.name = "pch_c++",
71+
.target = target,
72+
.optimize = optimize,
73+
.link_libcpp = true,
74+
}, .{
75+
.file = b.path("include_a.h"),
76+
.flags = &[_][]const u8{},
77+
.lang = .hpp,
78+
});
79+
80+
exe.addCSourceFile(.{
81+
.file = b.path("test.cpp"),
82+
.flags = &[_][]const u8{},
83+
.precompiled_header = pch.getEmittedBin(),
84+
});
85+
86+
test_step.dependOn(&b.addRunArtifact(exe).step);
87+
}
2988
}

test/standalone/c_header/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/c_header/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/c_header/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/c_header/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)