Skip to content

Commit

Permalink
std.Build: add an option to addCSourceFiles() to include a precompi…
Browse files Browse the repository at this point in the history
…led header
  • Loading branch information
xxxbxxx committed Jan 31, 2024
1 parent a4a3163 commit b83acd6
Show file tree
Hide file tree
Showing 9 changed files with 174 additions and 2 deletions.
13 changes: 13 additions & 0 deletions lib/std/Build/Module.zig
Original file line number Diff line number Diff line change
Expand Up @@ -127,18 +127,21 @@ pub const CSourceFiles = struct {
files: []const []const u8,
lang: ?CSourceLang = null,
flags: []const []const u8,
precompiled_header: ?LazyPath = null,
};

pub const CSourceFile = struct {
file: LazyPath,
lang: ?CSourceLang = null,
flags: []const []const u8 = &.{},
precompiled_header: ?LazyPath = null,

pub fn dupe(self: CSourceFile, b: *std.Build) CSourceFile {
return .{
.file = self.file.dupe(b),
.lang = self.lang,
.flags = b.dupeStrings(self.flags),
.precompiled_header = self.precompiled_header,
};
}
};
Expand Down Expand Up @@ -504,6 +507,7 @@ pub const AddCSourceFilesOptions = struct {
files: []const []const u8,
lang: ?CSourceLang = null,
flags: []const []const u8 = &.{},
precompiled_header: ?LazyPath = null,
};

/// Handy when you have many C/C++ source files and want them all to have the same flags.
Expand All @@ -516,8 +520,13 @@ pub fn addCSourceFiles(m: *Module, options: AddCSourceFilesOptions) void {
.files = b.dupeStrings(options.files),
.lang = options.lang,
.flags = b.dupeStrings(options.flags),
.precompiled_header = options.precompiled_header,
};
m.link_objects.append(allocator, .{ .c_source_files = c_source_files }) catch @panic("OOM");

if (options.precompiled_header) |pch| {
addLazyPathDependenciesOnly(m, pch);
}
}

pub fn addCSourceFile(m: *Module, source: CSourceFile) void {
Expand All @@ -527,6 +536,10 @@ pub fn addCSourceFile(m: *Module, source: CSourceFile) void {
c_source_file.* = source.dupe(b);
m.link_objects.append(allocator, .{ .c_source_file = c_source_file }) catch @panic("OOM");
addLazyPathDependenciesOnly(m, source.file);

if (source.precompiled_header) |pch| {
addLazyPathDependenciesOnly(m, pch);
}
}

/// Resource files must have the extension `.rc`.
Expand Down
16 changes: 14 additions & 2 deletions lib/std/Build/Step/Compile.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1171,7 +1171,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
.c_source_file => |c_source_file| l: {
if (!my_responsibility) break :l;

if (c_source_file.flags.len == 0) {
if (c_source_file.flags.len == 0 and c_source_file.precompiled_header == null) {
if (prev_has_cflags) {
try zig_args.append("-cflags");
try zig_args.append("--");
Expand All @@ -1182,6 +1182,11 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
for (c_source_file.flags) |arg| {
try zig_args.append(arg);
}
if (c_source_file.precompiled_header) |pch| {
try zig_args.append("-include-pch");
try zig_args.append(pch.getPath(b));
try zig_args.append("-fpch-validate-input-files-content");
}
try zig_args.append("--");
prev_has_cflags = true;
}
Expand All @@ -1198,7 +1203,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
.c_source_files => |c_source_files| l: {
if (!my_responsibility) break :l;

if (c_source_files.flags.len == 0) {
if (c_source_files.flags.len == 0 and c_source_files.precompiled_header == null) {
if (prev_has_cflags) {
try zig_args.append("-cflags");
try zig_args.append("--");
Expand All @@ -1209,6 +1214,13 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
for (c_source_files.flags) |flag| {
try zig_args.append(flag);
}

if (c_source_files.precompiled_header) |pch| {
try zig_args.append("-include-pch");
try zig_args.append(pch.getPath(b));
try zig_args.append("-fpch-validate-input-files-content");
}

try zig_args.append("--");
prev_has_cflags = true;
}
Expand Down
4 changes: 4 additions & 0 deletions test/standalone.zig
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,10 @@ pub const build_cases = [_]BuildCase{
.build_root = "test/standalone/depend_on_main_mod",
.import = @import("standalone/depend_on_main_mod/build.zig"),
},
.{
.build_root = "test/standalone/pch",
.import = @import("standalone/pch/build.zig"),
},
};

const std = @import("std");
69 changes: 69 additions & 0 deletions test/standalone/pch/build.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
const std = @import("std");

pub fn build(b: *std.Build) void {
const test_step = b.step("test", "Test it");
b.default_step = test_step;

const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});

// c-header
{
const exe = b.addExecutable(.{
.name = "pchtest",
.target = target,
.optimize = optimize,
.link_libc = true,
});

const pch = b.addPrecompiledCHeader(.{
.name = "pch_c",
.target = target,
.optimize = optimize,
.link_libc = true,
}, .{
.file = .{ .path = "include_a.h" },
.flags = &[_][]const u8{},
.lang = .h,
});

exe.addCSourceFiles(.{
.files = &.{"test.c"},
.flags = &[_][]const u8{},
.lang = .c,
.precompiled_header = pch.getEmittedBin(),
});

test_step.dependOn(&b.addRunArtifact(exe).step);
}

// c++-header
{
const exe = b.addExecutable(.{
.name = "pchtest++",
.target = target,
.optimize = optimize,
.link_libc = true,
});
exe.linkLibCpp();

const pch = b.addPrecompiledCHeader(.{
.name = "pch_c++",
.target = target,
.optimize = optimize,
.link_libcpp = true,
}, .{
.file = .{ .path = "include_a.h" },
.flags = &[_][]const u8{},
.lang = .hpp,
});

exe.addCSourceFile(.{
.file = .{ .path = "test.cpp" },
.flags = &[_][]const u8{},
.precompiled_header = pch.getEmittedBin(),
});

test_step.dependOn(&b.addRunArtifact(exe).step);
}
}
15 changes: 15 additions & 0 deletions test/standalone/pch/include_a.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#pragma once

#include "include_b.h"

#include <string.h>
#include <stdlib.h>

#if defined(__cplusplus)
#include <iostream>
#else
#include <stdio.h>
#endif

#define A_INCLUDED 1

7 changes: 7 additions & 0 deletions test/standalone/pch/include_b.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#pragma once

#include <math.h>

typedef double real;

#define B_INCLUDED 1
7 changes: 7 additions & 0 deletions test/standalone/pch/include_c.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#pragma once

#include <string.h>

#define C_INCLUDED 1

int one = 3;
22 changes: 22 additions & 0 deletions test/standalone/pch/test.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@

// includes commented out to make sure the symbols come from the precompiled header.
//#include "include_a.h"
//#include "include_b.h"

#ifndef A_INCLUDED
#error "pch not included"
#endif
#ifndef B_INCLUDED
#error "pch not included"
#endif

int main(int argc, char *argv[])
{
real a = 0.123;

if (argc > 1) {
fprintf(stdout, "abs(%g)=%g\n", a, fabs(a));
}

return EXIT_SUCCESS;
}
23 changes: 23 additions & 0 deletions test/standalone/pch/test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@

// includes commented out to make sure the symbols come from the precompiled header.
//#include "includeA.h"
//#include "includeB.h"

#ifndef A_INCLUDED
#error "pch not included"
#endif
#ifndef B_INCLUDED
#error "pch not included"
#endif

int main(int argc, char *argv[])
{
real a = -0.123;

if (argc > 1) {
std::cout << "abs(" << a << ")=" << fabs(a) << "\n";
}

return EXIT_SUCCESS;
}

0 comments on commit b83acd6

Please sign in to comment.