union LazyPath [src]
A reference to an existing or future path.
Fields
src_path: struct {
owner: *std.Build,
sub_path: []const u8,
}A source file path relative to build root.
generated: struct {
file: *const GeneratedFile,
/// The number of parent directories to go up.
/// 0 means the generated file itself.
/// 1 means the directory of the generated file.
/// 2 means the parent of that directory, and so on.
up: usize = 0,
/// Applied after `up`.
sub_path: []const u8 = "",
}
cwd_relative: []const u8An absolute path or a path relative to the current working directory of
the build runner process.
This is uncommon but used for system environment paths such as --zig-lib-dir which
ignore the file system path of build.zig and instead are relative to the directory from
which zig build was invoked.
Use of this tag indicates a dependency on the host system.
dependency: struct {
dependency: *Dependency,
sub_path: []const u8,
}
Members
- addStepDependencies (Function)
- dirname (Function)
- dupe (Function)
- getDisplayName (Function)
- getPath (Function)
- getPath2 (Function)
- getPath3 (Function)
- join (Function)
- path (Function)
Source
pub const LazyPath = union(enum) {
/// A source file path relative to build root.
src_path: struct {
owner: *std.Build,
sub_path: []const u8,
},
generated: struct {
file: *const GeneratedFile,
/// The number of parent directories to go up.
/// 0 means the generated file itself.
/// 1 means the directory of the generated file.
/// 2 means the parent of that directory, and so on.
up: usize = 0,
/// Applied after `up`.
sub_path: []const u8 = "",
},
/// An absolute path or a path relative to the current working directory of
/// the build runner process.
/// This is uncommon but used for system environment paths such as `--zig-lib-dir` which
/// ignore the file system path of build.zig and instead are relative to the directory from
/// which `zig build` was invoked.
/// Use of this tag indicates a dependency on the host system.
cwd_relative: []const u8,
dependency: struct {
dependency: *Dependency,
sub_path: []const u8,
},
/// Returns a lazy path referring to the directory containing this path.
///
/// The dirname is not allowed to escape the logical root for underlying path.
/// For example, if the path is relative to the build root,
/// the dirname is not allowed to traverse outside of the build root.
/// Similarly, if the path is a generated file inside zig-cache,
/// the dirname is not allowed to traverse outside of zig-cache.
pub fn dirname(lazy_path: LazyPath) LazyPath {
return switch (lazy_path) {
.src_path => |sp| .{ .src_path = .{
.owner = sp.owner,
.sub_path = dirnameAllowEmpty(sp.sub_path) orelse {
dumpBadDirnameHelp(null, null, "dirname() attempted to traverse outside the build root\n", .{}) catch {};
@panic("misconfigured build script");
},
} },
.generated => |generated| .{ .generated = if (dirnameAllowEmpty(generated.sub_path)) |sub_dirname| .{
.file = generated.file,
.up = generated.up,
.sub_path = sub_dirname,
} else .{
.file = generated.file,
.up = generated.up + 1,
.sub_path = "",
} },
.cwd_relative => |rel_path| .{
.cwd_relative = dirnameAllowEmpty(rel_path) orelse {
// If we get null, it means one of two things:
// - rel_path was absolute, and is now root
// - rel_path was relative, and is now ""
// In either case, the build script tried to go too far
// and we should panic.
if (fs.path.isAbsolute(rel_path)) {
dumpBadDirnameHelp(null, null,
\\dirname() attempted to traverse outside the root.
\\No more directories left to go up.
\\
, .{}) catch {};
@panic("misconfigured build script");
} else {
dumpBadDirnameHelp(null, null,
\\dirname() attempted to traverse outside the current working directory.
\\
, .{}) catch {};
@panic("misconfigured build script");
}
},
},
.dependency => |dep| .{ .dependency = .{
.dependency = dep.dependency,
.sub_path = dirnameAllowEmpty(dep.sub_path) orelse {
dumpBadDirnameHelp(null, null,
\\dirname() attempted to traverse outside the dependency root.
\\
, .{}) catch {};
@panic("misconfigured build script");
},
} },
};
}
pub fn path(lazy_path: LazyPath, b: *Build, sub_path: []const u8) LazyPath {
return lazy_path.join(b.allocator, sub_path) catch @panic("OOM");
}
pub fn join(lazy_path: LazyPath, arena: Allocator, sub_path: []const u8) Allocator.Error!LazyPath {
return switch (lazy_path) {
.src_path => |src| .{ .src_path = .{
.owner = src.owner,
.sub_path = try fs.path.resolve(arena, &.{ src.sub_path, sub_path }),
} },
.generated => |gen| .{ .generated = .{
.file = gen.file,
.up = gen.up,
.sub_path = try fs.path.resolve(arena, &.{ gen.sub_path, sub_path }),
} },
.cwd_relative => |cwd_relative| .{
.cwd_relative = try fs.path.resolve(arena, &.{ cwd_relative, sub_path }),
},
.dependency => |dep| .{ .dependency = .{
.dependency = dep.dependency,
.sub_path = try fs.path.resolve(arena, &.{ dep.sub_path, sub_path }),
} },
};
}
/// Returns a string that can be shown to represent the file source.
/// Either returns the path, `"generated"`, or `"dependency"`.
pub fn getDisplayName(lazy_path: LazyPath) []const u8 {
return switch (lazy_path) {
.src_path => |sp| sp.sub_path,
.cwd_relative => |p| p,
.generated => "generated",
.dependency => "dependency",
};
}
/// Adds dependencies this file source implies to the given step.
pub fn addStepDependencies(lazy_path: LazyPath, other_step: *Step) void {
switch (lazy_path) {
.src_path, .cwd_relative, .dependency => {},
.generated => |gen| other_step.dependOn(gen.file.step),
}
}
/// Deprecated, see `getPath3`.
pub fn getPath(lazy_path: LazyPath, src_builder: *Build) []const u8 {
return getPath2(lazy_path, src_builder, null);
}
/// Deprecated, see `getPath3`.
pub fn getPath2(lazy_path: LazyPath, src_builder: *Build, asking_step: ?*Step) []const u8 {
const p = getPath3(lazy_path, src_builder, asking_step);
return src_builder.pathResolve(&.{ p.root_dir.path orelse ".", p.sub_path });
}
/// Intended to be used during the make phase only.
///
/// `asking_step` is only used for debugging purposes; it's the step being
/// run that is asking for the path.
pub fn getPath3(lazy_path: LazyPath, src_builder: *Build, asking_step: ?*Step) Cache.Path {
switch (lazy_path) {
.src_path => |sp| return .{
.root_dir = sp.owner.build_root,
.sub_path = sp.sub_path,
},
.cwd_relative => |sub_path| return .{
.root_dir = Cache.Directory.cwd(),
.sub_path = sub_path,
},
.generated => |gen| {
// TODO make gen.file.path not be absolute and use that as the
// basis for not traversing up too many directories.
var file_path: Cache.Path = .{
.root_dir = Cache.Directory.cwd(),
.sub_path = gen.file.path orelse {
std.debug.lockStdErr();
const stderr = std.io.getStdErr();
dumpBadGetPathHelp(gen.file.step, stderr, src_builder, asking_step) catch {};
std.debug.unlockStdErr();
@panic("misconfigured build script");
},
};
if (gen.up > 0) {
const cache_root_path = src_builder.cache_root.path orelse
(src_builder.cache_root.join(src_builder.allocator, &.{"."}) catch @panic("OOM"));
for (0..gen.up) |_| {
if (mem.eql(u8, file_path.sub_path, cache_root_path)) {
// If we hit the cache root and there's still more to go,
// the script attempted to go too far.
dumpBadDirnameHelp(gen.file.step, asking_step,
\\dirname() attempted to traverse outside the cache root.
\\This is not allowed.
\\
, .{}) catch {};
@panic("misconfigured build script");
}
// path is absolute.
// dirname will return null only if we're at root.
// Typically, we'll stop well before that at the cache root.
file_path.sub_path = fs.path.dirname(file_path.sub_path) orelse {
dumpBadDirnameHelp(gen.file.step, asking_step,
\\dirname() reached root.
\\No more directories left to go up.
\\
, .{}) catch {};
@panic("misconfigured build script");
};
}
}
return file_path.join(src_builder.allocator, gen.sub_path) catch @panic("OOM");
},
.dependency => |dep| return .{
.root_dir = dep.dependency.builder.build_root,
.sub_path = dep.sub_path,
},
}
}
/// Copies the internal strings.
///
/// The `b` parameter is only used for its allocator. All *Build instances
/// share the same allocator.
pub fn dupe(lazy_path: LazyPath, b: *Build) LazyPath {
return lazy_path.dupeInner(b.allocator);
}
fn dupeInner(lazy_path: LazyPath, allocator: std.mem.Allocator) LazyPath {
return switch (lazy_path) {
.src_path => |sp| .{ .src_path = .{
.owner = sp.owner,
.sub_path = sp.owner.dupePath(sp.sub_path),
} },
.cwd_relative => |p| .{ .cwd_relative = dupePathInner(allocator, p) },
.generated => |gen| .{ .generated = .{
.file = gen.file,
.up = gen.up,
.sub_path = dupePathInner(allocator, gen.sub_path),
} },
.dependency => |dep| .{ .dependency = dep },
};
}
}