I'm using a pattern to have paths in build files that are relative to the build file instead of the build root folder.
This pattern looked like this:
/// DEPRECATED, DO NOT USE
fn sdkRoot() []const u8 {
return std.fs.path.dirname(@src().file) orelse ".";
}
...
{
var path = sdkRoot() ++ "/src/main.zig"; // get a nice path
}
...
The problem with this is that with the new stage2 compiler, the ++
operator now has new semantics that make the operation above a runtime operation, and thus path
a pointer-to-temporary, not a pointer-to-comptime-memory.
But there's a nice alternative one can use:
fn sdkPath(comptime suffix: []const u8) []const u8 {
if (suffix[0] != '/') @compileError("relToPath requires an absolute path!");
return comptime blk: {
const root_dir = std.fs.path.dirname(@src().file) orelse ".";
break :blk root_dir ++ suffix;
};
}
...
{
var path = sdkPath("/src/main.zig"); // get a nice path
}
...
This way, it can trivially be a comptime
return value, removing the need for a lot of comptime sdkRoot()
calls.
Discussion (2)
Very useful! Since you're using ++ in both examples, can you explain how they differ? Does the stage2 compiler require ++ use within an explicit comptime block for the result to be comptime?
++
in the first example returns a pointer-to-temporary, whereas the second example returns acomptime
known value that is guaranteed to put into the.rodata
section and has a lifetime of the whole program life time