Getting a LazyPath to an installed file

Hi everyone, I’ve been messing with Zig for a while now but this is the first time I had an issue that I couldn’t find addressed somewhere. The actual question is more narrow than everything below, but just in case I’m doing this in a super roundabout way I thought I would just give the full context.

In my build script, I depend on the PipeWire repository in order to access enums/constants defined in its headers. This felt more correct and flexible than directly committing translated header files.

It seemed like the best way to do this was with addTranslateC:

const pipewire = b.dependency("pipewire", .{});
const translate_pipewire = b.addTranslateC(.{
    .root_source_file = pipewire.path("src/pipewire/pipewire.h"),
    .target = target,
    .optimize = optimize,
});
const config_pipewire_version = b.addConfigHeader(.{
    .style = .{ .autoconf_at = pipewire.path("src/pipewire/version.h.in") },
}, .{
    .PIPEWIRE_VERSION_MAJOR = "1",
    .PIPEWIRE_VERSION_MINOR = "0",
    .PIPEWIRE_VERSION_MICRO = "0",
    .PIPEWIRE_API_VERSION = "0.3",
});
const pipewire_version_header_out = b.addInstallHeaderFile(
    config_pipewire_version.getOutput(),
    "pipewire/version.h",
);
translate_pipewire.step.dependOn(&pipewire_version_header_out.step);
translate_pipewire.addConfigHeader(config_pipewire_version);

b.getInstallPath(pipewire_version_header_out.dir, "pipewire"); // returns an absolute path string
translate_pipewire.addIncludePath(...); // takes a LazyPath

translate_pipewire.addIncludePath(pipewire.path("src"));
translate_pipewire.addIncludePath(pipewire.path("spa/include"));

It failed to compile because of src/pipewire/version.h.in, so I found that Build has addConfigHeader to handle generated header files. That part seems to be working, but my problem is I can’t figure out how to actually point the translate-c step, which is working with the cached repository outside of the build root, towards the generated version.h, which is installed under zig-out. I’m assuming I should use TranslateC.addIncludePath, but it takes a LazyPath. The best thing I see for getting paths from the InstallFile object is passing the .dir field to getInstallPath, but this returns a string path from the system root which I understand is not intended to be used in the build system. Am I supposed to use b.path("zig-out/include")? Am I not intended to get LazyPaths from InstallDirs?

What you are looking for is the source value on the std.Build.Step.InstallFile. This will be the LazyPath to the version.h file after templating it.

    translate_pipewire.addIncludePath(pipewire_version_header_out.source);

That will give the include path the version header as an input path.

However, I think the underlying issue (if I can guess), is that you don’t have the install path set on the b.addConfigHeader(...) options.

You probably need something like this:

const config_pipewire_version = b.addConfigHeader(.{
    .style = .{ .autoconf_at = pipewire.path("src/pipewire/version.h.in") },
    // ADD THIS LINE
    .include_path = "pipewire/version.h",
}, .{
    .PIPEWIRE_VERSION_MAJOR = "1",
    .PIPEWIRE_VERSION_MINOR = "0",
    .PIPEWIRE_VERSION_MICRO = "0",
    .PIPEWIRE_API_VERSION = "0.3",
});

With that, you don’t need the addInstallHeaderFile things unless you are trying to get that header file as part of your build output for consumers to use.

Thank you! It works with this added.