mlugg f3c0555975
std.Build: introduce ConfigHeader.getOutputDir, small refactor
`std.Build.Step.ConfigHeader` emits a *directory* containing a config
header under a given sub path, but there's no good way to actually
access that directory as a `LazyPath` in the configure phase. This is
silly; it's perfectly valid to refer to that directory, perhaps to
explicitly pass as a "-I" flag to a different toolchain invoked via a
`Step.Run`. So now, instead of the `GeneratedFile` being the actual
*file*, it should be that *directory*, i.e. `cache/o/<digest>`. We can
then easily get the *file* if needed just by using `LazyPath.path` to go
"deeper", which there is a helper function for.

The legacy `getOutput` function is now a deprecated alias for
`getOutputFile`, and `getOutputDir` is introduced.

`std.Build.Module.IncludeDir.appendZigProcessFlags` needed a fix after
this change, so I took the opportunity to refactor it a little. I was
looking at this function while working on ziglang/translate-c yesterday
and realised it could be expressed much more simply -- particularly
after the `ConfigHeader` change here.

I had to update the test `standalone/cmakedefine/` -- it turns out this
test was well and truly reaching into build system internals, and doing
horrible not-really-allowed stuff like overriding the `makeFn` of a
`TopLevelStep`. To top it all off, the test forgot to set
`b.default_step` to its "test" step, so the test never even ran. I've
refactored it to follow accepted practices and to actually, like, work.
2025-06-17 11:55:36 +01:00

106 lines
2.9 KiB
Zig

const std = @import("std");
const ConfigHeader = std.Build.Step.ConfigHeader;
pub fn build(b: *std.Build) void {
const config_header = b.addConfigHeader(
.{
.style = .{ .cmake = b.path("config.h.in") },
.include_path = "config.h",
},
.{
.noval = null,
.trueval = true,
.falseval = false,
.zeroval = 0,
.oneval = 1,
.tenval = 10,
.stringval = "test",
.boolnoval = void{},
.booltrueval = true,
.boolfalseval = false,
.boolzeroval = 0,
.booloneval = 1,
.booltenval = 10,
.boolstringval = "test",
},
);
const pwd_sh = b.addConfigHeader(
.{
.style = .{ .cmake = b.path("pwd.sh.in") },
.include_path = "pwd.sh",
},
.{ .DIR = "${PWD}" },
);
const sigil_header = b.addConfigHeader(
.{
.style = .{ .cmake = b.path("sigil.h.in") },
.include_path = "sigil.h",
},
.{},
);
const stack_header = b.addConfigHeader(
.{
.style = .{ .cmake = b.path("stack.h.in") },
.include_path = "stack.h",
},
.{
.AT = "@",
.UNDERSCORE = "_",
.NEST_UNDERSCORE_PROXY = "UNDERSCORE",
.NEST_PROXY = "NEST_UNDERSCORE_PROXY",
},
);
const wrapper_header = b.addConfigHeader(
.{
.style = .{ .cmake = b.path("wrapper.h.in") },
.include_path = "wrapper.h",
},
.{
.DOLLAR = "$",
.TEXT = "TRAP",
.STRING = "TEXT",
.STRING_AT = "@STRING@",
.STRING_CURLY = "{STRING}",
.STRING_VAR = "${STRING}",
},
);
const check_exe = b.addExecutable(.{
.name = "check",
.root_module = b.createModule(.{
.target = b.graph.host,
.root_source_file = b.path("check.zig"),
}),
});
const test_step = b.step("test", "Test it");
b.default_step = test_step;
test_step.dependOn(addCheck(b, check_exe, config_header));
test_step.dependOn(addCheck(b, check_exe, pwd_sh));
test_step.dependOn(addCheck(b, check_exe, sigil_header));
test_step.dependOn(addCheck(b, check_exe, stack_header));
test_step.dependOn(addCheck(b, check_exe, wrapper_header));
}
fn addCheck(
b: *std.Build,
check_exe: *std.Build.Step.Compile,
ch: *ConfigHeader,
) *std.Build.Step {
// We expect `ch.include_path` to only be a basename to infer where the expected output is.
std.debug.assert(std.fs.path.dirname(ch.include_path) == null);
const expected_path = b.fmt("expected_{s}", .{ch.include_path});
const run_check = b.addRunArtifact(check_exe);
run_check.addFileArg(ch.getOutputFile());
run_check.addFileArg(b.path(expected_path));
return &run_check.step;
}