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 {...@@ -164,12 +164,12 @@ pub fn main(init: process.Init.Minimal) !void {
164164
165 const cwd: Dir = .cwd();165 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 .{
168 .path = zig_lib_arg,168 .path = zig_lib_arg,
169 .handle = try cwd.openDir(io, zig_lib_arg, .{}),169 .handle = try cwd.openDir(io, zig_lib_arg, .{}),
170 };170 };
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 .{
173 .path = global_cache_arg,173 .path = global_cache_arg,
174 .handle = try cwd.createDirPathOpen(io, global_cache_arg, .{}),174 .handle = try cwd.createDirPathOpen(io, global_cache_arg, .{}),
175 };175 };
...@@ -560,10 +560,11 @@ pub fn main(init: process.Init.Minimal) !void {...@@ -560,10 +560,11 @@ pub fn main(init: process.Init.Minimal) !void {
560 const cwd_path = std.zig.getResolvedCwd(io, arena) catch |err|560 const cwd_path = std.zig.getResolvedCwd(io, arena) catch |err|
561 fatal("resolving current directory path failed: {t}", .{err});561 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, .{
564 .cwd_path = cwd_path,564 .cwd_path = cwd_path,
565 .build_file = build_file,565 .build_file = build_file,
566 });566 });
567 defer build_root.deinit(io);
567568
568 graph.build_root_directory = build_root.directory;569 graph.build_root_directory = build_root.directory;
569 graph.local_cache_root = if (override_local_cache_dir) |unresolved_path| std.zig.Directories.openUnresolved(570 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 {...@@ -573,7 +574,7 @@ pub fn main(init: process.Init.Minimal) !void {
573 unresolved_path,574 unresolved_path,
574 .@"local cache",575 .@"local cache",
575 ) else .{576 ) 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}),
577 .handle = try build_root.directory.handle.createDirPathOpen(io, default_local_zig_cache_basename, .{}),578 .handle = try build_root.directory.handle.createDirPathOpen(io, default_local_zig_cache_basename, .{}),
578 };579 };
579 graph.cache = .{580 graph.cache = .{
...@@ -3335,22 +3336,21 @@ inline fn debugMakerLeaks() bool {...@@ -3335,22 +3336,21 @@ inline fn debugMakerLeaks() bool {
33353336
3336const BuildRoot = struct {3337const BuildRoot = struct {
3337 directory: Cache.Directory,3338 directory: Cache.Directory,
3339 close_directory: bool,
3338 build_zig_basename: []const u8,3340 build_zig_basename: []const u8,
3339 cleanup_build_dir: ?Io.Dir,
33403341
3341 fn deinit(br: *BuildRoot, io: Io) void {3342 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);
3343 br.* = undefined;3344 br.* = undefined;
3344 }3345 }
3345};3346};
33463347
3347const FindBuildRootOptions = struct {3348const FindBuildRootOptions = struct {
3348 build_file: ?[]const u8 = null,3349 build_file: ?[]const u8 = null,
3349 cwd_path: ?[]const u8 = null,3350 cwd_path: []const u8,
3350};3351};
33513352
3352fn findBuildRoot(arena: Allocator, io: Io, options: FindBuildRootOptions) !BuildRoot {3353fn findBuildRoot(arena: Allocator, io: Io, options: FindBuildRootOptions) !BuildRoot {
3353 const cwd_path = options.cwd_path orelse try std.zig.getResolvedCwd(io, arena);
3354 const build_zig_basename = if (options.build_file) |bf|3354 const build_zig_basename = if (options.build_file) |bf|
3355 Dir.path.basename(bf)3355 Dir.path.basename(bf)
3356 else3356 else
...@@ -3364,35 +3364,41 @@ fn findBuildRoot(arena: Allocator, io: Io, options: FindBuildRootOptions) !Build...@@ -3364,35 +3364,41 @@ fn findBuildRoot(arena: Allocator, io: Io, options: FindBuildRootOptions) !Build
3364 return .{3364 return .{
3365 .build_zig_basename = build_zig_basename,3365 .build_zig_basename = build_zig_basename,
3366 .directory = .{ .path = dirname, .handle = dir },3366 .directory = .{ .path = dirname, .handle = dir },
3367 .cleanup_build_dir = dir,3367 .close_directory = true,
3368 };3368 };
3369 }3369 }
33703370
3371 return .{3371 return .{
3372 .build_zig_basename = build_zig_basename,3372 .build_zig_basename = build_zig_basename,
3373 .directory = .{ .path = null, .handle = Io.Dir.cwd() },3373 .directory = .cwd(),
3374 .cleanup_build_dir = null,3374 .close_directory = false,
3375 };3375 };
3376 }3376 }
3377 // Search up parent directories until we find build.zig.3377 // Search up parent directories until we find build.zig.
3378 var dirname: []const u8 = cwd_path;3378 var dirname: ?[]const u8 = null;
3379 while (true) {3379 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;
3381 if (Io.Dir.cwd().access(io, joined_path, .{})) |_| {3384 if (Io.Dir.cwd().access(io, joined_path, .{})) |_| {
3382 const dir = Io.Dir.cwd().openDir(io, dirname, .{}) catch |err| {3385 const dir = if (dirname) |d|
3383 fatal("unable to open directory while searching for build.zig file, {q}: {t}", .{ dirname, err });3386 Io.Dir.cwd().openDir(io, d, .{}) catch |err| {
3384 };3387 fatal("unable to open directory while searching for build.zig file, {q}: {t}", .{ d, err });
3388 }
3389 else
3390 Io.Dir.cwd();
3385 return .{3391 return .{
3386 .build_zig_basename = build_zig_basename,3392 .build_zig_basename = build_zig_basename,
3387 .directory = .{3393 .directory = .{
3388 .path = dirname,3394 .path = dirname,
3389 .handle = dir,3395 .handle = dir,
3390 },3396 },
3391 .cleanup_build_dir = dir,3397 .close_directory = dirname != null,
3392 };3398 };
3393 } else |err| switch (err) {3399 } else |err| switch (err) {
3394 error.FileNotFound => {3400 error.FileNotFound => {
3395 dirname = Dir.path.dirname(dirname) orelse {3401 dirname = Dir.path.dirname(dirname orelse options.cwd_path) orelse {
3396 log.info("initialize {s} template file with \"zig init\"", .{std.zig.build_zig_basename});3402 log.info("initialize {s} template file with \"zig init\"", .{std.zig.build_zig_basename});
3397 log.info("see \"zig --help\" for more options", .{});3403 log.info("see \"zig --help\" for more options", .{});
3398 fatal("no build.zig file found, in the current directory or any parent directories", .{});3404 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 {...@@ -68,7 +68,7 @@ pub fn main(init: process.Init.Minimal) !void {
6868
69 const cwd: Io.Dir = .cwd();69 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 .{
72 .root_dir = .{72 .root_dir = .{
73 .handle = try cwd.openDir(io, build_root_sub_path, .{}),73 .handle = try cwd.openDir(io, build_root_sub_path, .{}),
74 .path = build_root_sub_path,74 .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 {...@@ -90,10 +90,8 @@ fn findPrefix(cache: *const Cache, file_path: []const u8) !PrefixedPath {
90fn findPrefixResolved(cache: *const Cache, resolved_path: []u8) !PrefixedPath {90fn findPrefixResolved(cache: *const Cache, resolved_path: []u8) !PrefixedPath {
91 const gpa = cache.gpa;91 const gpa = cache.gpa;
92 const cwd = cache.cwd;92 const cwd = cache.cwd;
93 const prefixes_slice = cache.prefixes();93 for (cache.prefixes(), 0..) |prefix, i| {
94 var i: u8 = 1; // Start at 1 to skip over checking the null prefix.94 const p = prefix.path orelse continue;
95 while (i < prefixes_slice.len) : (i += 1) {
96 const p = prefixes_slice[i].path.?;
97 const sub_path = getPrefixSubpath(gpa, cwd, p, resolved_path) catch |err| switch (err) {95 const sub_path = getPrefixSubpath(gpa, cwd, p, resolved_path) catch |err| switch (err) {
98 error.NotASubPath => continue,96 error.NotASubPath => continue,
99 else => |e| return e,97 else => |e| return e,
...@@ -101,7 +99,7 @@ fn findPrefixResolved(cache: *const Cache, resolved_path: []u8) !PrefixedPath {...@@ -101,7 +99,7 @@ fn findPrefixResolved(cache: *const Cache, resolved_path: []u8) !PrefixedPath {
101 // Free the resolved path since we're not going to return it99 // Free the resolved path since we're not going to return it
102 gpa.free(resolved_path);100 gpa.free(resolved_path);
103 return .{101 return .{
104 .prefix = i,102 .prefix = @intCast(i),
105 .sub_path = sub_path,103 .sub_path = sub_path,
106 };104 };
107 }105 }
src/main.zig+2-2
...@@ -5065,11 +5065,11 @@ fn jitCmdInner(...@@ -5065,11 +5065,11 @@ fn jitCmdInner(
5065 if (options.prepend_cmd) |cmd|5065 if (options.prepend_cmd) |cmd|
5066 child_argv.appendAssumeCapacity(cmd);5066 child_argv.appendAssumeCapacity(cmd);
5067 if (options.prepend_zig_lib_dir_path)5067 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 "."}));
5069 if (options.prepend_zig_exe_path)5069 if (options.prepend_zig_exe_path)
5070 child_argv.appendAssumeCapacity(try arena.print("--zig={s}", .{self_exe_path}));5070 child_argv.appendAssumeCapacity(try arena.print("--zig={s}", .{self_exe_path}));
5071 if (options.prepend_global_cache_path)5071 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 "."}));
5073 if (options.prepend_seed)5073 if (options.prepend_seed)
5074 child_argv.appendAssumeCapacity(try arena.print("--seed=0x{x}", .{randInt(io, u32)}));5074 child_argv.appendAssumeCapacity(try arena.print("--seed=0x{x}", .{randInt(io, u32)}));
50755075