authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-07-04 04:25:40+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-07-04 04:25:40+02:00
logeb2a1bb0d04532c84c042eaad1c3ee092c8c8a23
treed62e2409bb44cc00ed54f1ba708c4910748bafb4
parentbd4e82b460f3a2173ff546e59ae3a903fb1c1c50
parent59451cce931230af873a6f789d9178cea70d73ea

Merge pull request 'zig build: avoid resolving absolute path to build root directory if possible' (#36028) from Techatrix/zig:relative-build-root into master

Reviewed-on: https://codeberg.org/ziglang/zig/pulls/36028 Reviewed-by: Andrew Kelley <andrew@ziglang.org>

4 files changed, 30 insertions(+), 26 deletions(-)

lib/compiler/Maker.zig+24-18
......@@ -164,12 +164,12 @@ pub fn main(init: process.Init.Minimal) !void {
164164
165165 const cwd: Dir = .cwd();
166166
167 const zig_lib_directory: Cache.Directory = .{
167 const zig_lib_directory: Cache.Directory = if (std.mem.eql(u8, zig_lib_arg, ".")) .cwd() else .{
168168 .path = zig_lib_arg,
169169 .handle = try cwd.openDir(io, zig_lib_arg, .{}),
170170 };
171171
172 const global_cache_directory: Cache.Directory = .{
172 const global_cache_directory: Cache.Directory = if (std.mem.eql(u8, global_cache_arg, ".")) .cwd() else .{
173173 .path = global_cache_arg,
174174 .handle = try cwd.createDirPathOpen(io, global_cache_arg, .{}),
175175 };
......@@ -560,10 +560,11 @@ pub fn main(init: process.Init.Minimal) !void {
560560 const cwd_path = std.zig.getResolvedCwd(io, arena) catch |err|
561561 fatal("resolving current directory path failed: {t}", .{err});
562562
563 const build_root = try findBuildRoot(arena, io, .{
563 var build_root = try findBuildRoot(arena, io, .{
564564 .cwd_path = cwd_path,
565565 .build_file = build_file,
566566 });
567 defer build_root.deinit(io);
567568
568569 graph.build_root_directory = build_root.directory;
569570 graph.local_cache_root = if (override_local_cache_dir) |unresolved_path| std.zig.Directories.openUnresolved(
......@@ -573,7 +574,7 @@ pub fn main(init: process.Init.Minimal) !void {
573574 unresolved_path,
574575 .@"local cache",
575576 ) else .{
576 .path = try Dir.path.join(arena, &.{ build_root.directory.path orelse ".", default_local_zig_cache_basename }),
577 .path = try build_root.directory.join(arena, &.{default_local_zig_cache_basename}),
577578 .handle = try build_root.directory.handle.createDirPathOpen(io, default_local_zig_cache_basename, .{}),
578579 };
579580 graph.cache = .{
......@@ -3335,22 +3336,21 @@ inline fn debugMakerLeaks() bool {
33353336
33363337const BuildRoot = struct {
33373338 directory: Cache.Directory,
3339 close_directory: bool,
33383340 build_zig_basename: []const u8,
3339 cleanup_build_dir: ?Io.Dir,
33403341
33413342 fn deinit(br: *BuildRoot, io: Io) void {
3342 if (br.cleanup_build_dir) |*dir| dir.close(io);
3343 if (br.close_directory) br.directory.handle.close(io);
33433344 br.* = undefined;
33443345 }
33453346};
33463347
33473348const FindBuildRootOptions = struct {
33483349 build_file: ?[]const u8 = null,
3349 cwd_path: ?[]const u8 = null,
3350 cwd_path: []const u8,
33503351};
33513352
33523353fn findBuildRoot(arena: Allocator, io: Io, options: FindBuildRootOptions) !BuildRoot {
3353 const cwd_path = options.cwd_path orelse try std.zig.getResolvedCwd(io, arena);
33543354 const build_zig_basename = if (options.build_file) |bf|
33553355 Dir.path.basename(bf)
33563356 else
......@@ -3364,35 +3364,41 @@ fn findBuildRoot(arena: Allocator, io: Io, options: FindBuildRootOptions) !Build
33643364 return .{
33653365 .build_zig_basename = build_zig_basename,
33663366 .directory = .{ .path = dirname, .handle = dir },
3367 .cleanup_build_dir = dir,
3367 .close_directory = true,
33683368 };
33693369 }
33703370
33713371 return .{
33723372 .build_zig_basename = build_zig_basename,
3373 .directory = .{ .path = null, .handle = Io.Dir.cwd() },
3374 .cleanup_build_dir = null,
3373 .directory = .cwd(),
3374 .close_directory = false,
33753375 };
33763376 }
33773377 // Search up parent directories until we find build.zig.
3378 var dirname: []const u8 = cwd_path;
3378 var dirname: ?[]const u8 = null;
33793379 while (true) {
3380 const joined_path = try Dir.path.join(arena, &[_][]const u8{ dirname, build_zig_basename });
3380 const joined_path = if (dirname) |d|
3381 try Dir.path.join(arena, &.{ d, build_zig_basename })
3382 else
3383 build_zig_basename;
33813384 if (Io.Dir.cwd().access(io, joined_path, .{})) |_| {
3382 const dir = Io.Dir.cwd().openDir(io, dirname, .{}) catch |err| {
3383 fatal("unable to open directory while searching for build.zig file, {q}: {t}", .{ dirname, err });
3384 };
3385 const dir = if (dirname) |d|
3386 Io.Dir.cwd().openDir(io, d, .{}) catch |err| {
3387 fatal("unable to open directory while searching for build.zig file, {q}: {t}", .{ d, err });
3388 }
3389 else
3390 Io.Dir.cwd();
33853391 return .{
33863392 .build_zig_basename = build_zig_basename,
33873393 .directory = .{
33883394 .path = dirname,
33893395 .handle = dir,
33903396 },
3391 .cleanup_build_dir = dir,
3397 .close_directory = dirname != null,
33923398 };
33933399 } else |err| switch (err) {
33943400 error.FileNotFound => {
3395 dirname = Dir.path.dirname(dirname) orelse {
3401 dirname = Dir.path.dirname(dirname orelse options.cwd_path) orelse {
33963402 log.info("initialize {s} template file with \"zig init\"", .{std.zig.build_zig_basename});
33973403 log.info("see \"zig --help\" for more options", .{});
33983404 fatal("no build.zig file found, in the current directory or any parent directories", .{});
lib/compiler/configurer.zig+1-1
......@@ -68,7 +68,7 @@ pub fn main(init: process.Init.Minimal) !void {
6868
6969 const cwd: Io.Dir = .cwd();
7070
71 const build_root: std.Build.Cache.Path = .{
71 const build_root: std.Build.Cache.Path = if (std.mem.eql(u8, build_root_sub_path, ".")) .cwd() else .{
7272 .root_dir = .{
7373 .handle = try cwd.openDir(io, build_root_sub_path, .{}),
7474 .path = build_root_sub_path,
lib/std/Build/Cache.zig+3-5
......@@ -90,10 +90,8 @@ fn findPrefix(cache: *const Cache, file_path: []const u8) !PrefixedPath {
9090fn findPrefixResolved(cache: *const Cache, resolved_path: []u8) !PrefixedPath {
9191 const gpa = cache.gpa;
9292 const cwd = cache.cwd;
93 const prefixes_slice = cache.prefixes();
94 var i: u8 = 1; // Start at 1 to skip over checking the null prefix.
95 while (i < prefixes_slice.len) : (i += 1) {
96 const p = prefixes_slice[i].path.?;
93 for (cache.prefixes(), 0..) |prefix, i| {
94 const p = prefix.path orelse continue;
9795 const sub_path = getPrefixSubpath(gpa, cwd, p, resolved_path) catch |err| switch (err) {
9896 error.NotASubPath => continue,
9997 else => |e| return e,
......@@ -101,7 +99,7 @@ fn findPrefixResolved(cache: *const Cache, resolved_path: []u8) !PrefixedPath {
10199 // Free the resolved path since we're not going to return it
102100 gpa.free(resolved_path);
103101 return .{
104 .prefix = i,
102 .prefix = @intCast(i),
105103 .sub_path = sub_path,
106104 };
107105 }
src/main.zig+2-2
......@@ -5065,11 +5065,11 @@ fn jitCmdInner(
50655065 if (options.prepend_cmd) |cmd|
50665066 child_argv.appendAssumeCapacity(cmd);
50675067 if (options.prepend_zig_lib_dir_path)
5068 child_argv.appendAssumeCapacity(try arena.print("--zig-lib={s}", .{dirs.zig_lib.path.?}));
5068 child_argv.appendAssumeCapacity(try arena.print("--zig-lib={s}", .{dirs.zig_lib.path orelse "."}));
50695069 if (options.prepend_zig_exe_path)
50705070 child_argv.appendAssumeCapacity(try arena.print("--zig={s}", .{self_exe_path}));
50715071 if (options.prepend_global_cache_path)
5072 child_argv.appendAssumeCapacity(try arena.print("--global-cache={s}", .{dirs.global_cache.path.?}));
5072 child_argv.appendAssumeCapacity(try arena.print("--global-cache={s}", .{dirs.global_cache.path orelse "."}));
50735073 if (options.prepend_seed)
50745074 child_argv.appendAssumeCapacity(try arena.print("--seed=0x{x}", .{randInt(io, u32)}));
50755075