authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-02-01 22:43:41-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-02-02 20:43:01-07:00
loged4ccea7bae99c1baa634716941f308d9f922985
treef2bbf9997f911b68cca67bc0c297e8324ced4180
parent22537873f4e80fa1caca6b7b8a4b14c8d7284de2

build system: implement --system [dir]

This prevents package fetching and enables system_package_mode in the build system which flips the defaults for system integrations.

4 files changed, 70 insertions(+), 17 deletions(-)

lib/build_runner.zig+17-11
...@@ -202,6 +202,11 @@ pub fn main() !void {...@@ -202,6 +202,11 @@ pub fn main() !void {
202 builder.debug_pkg_config = true;202 builder.debug_pkg_config = true;
203 } else if (mem.eql(u8, arg, "--debug-compile-errors")) {203 } else if (mem.eql(u8, arg, "--debug-compile-errors")) {
204 builder.debug_compile_errors = true;204 builder.debug_compile_errors = true;
205 } else if (mem.eql(u8, arg, "--system")) {
206 // The usage text shows another argument after this parameter
207 // but it is handled by the parent process. The build runner
208 // only sees this flag.
209 graph.system_package_mode = true;
205 } else if (mem.eql(u8, arg, "--glibc-runtimes")) {210 } else if (mem.eql(u8, arg, "--glibc-runtimes")) {
206 builder.glibc_runtimes_dir = nextArgOrFatal(args, &arg_idx);211 builder.glibc_runtimes_dir = nextArgOrFatal(args, &arg_idx);
207 } else if (mem.eql(u8, arg, "--verbose-link")) {212 } else if (mem.eql(u8, arg, "--verbose-link")) {
...@@ -1053,18 +1058,14 @@ fn usage(b: *std.Build, out_stream: anytype) !void {...@@ -1053,18 +1058,14 @@ fn usage(b: *std.Build, out_stream: anytype) !void {
1053 try out_stream.writeAll(1058 try out_stream.writeAll(
1054 \\1059 \\
1055 \\General Options:1060 \\General Options:
1056 \\ -p, --prefix [path] Where to put installed files (default: zig-out)1061 \\ -p, --prefix [path] Where to install files (default: zig-out)
1057 \\ --prefix-lib-dir [path] Where to put installed libraries1062 \\ --prefix-lib-dir [path] Where to install libraries
1058 \\ --prefix-exe-dir [path] Where to put installed executables1063 \\ --prefix-exe-dir [path] Where to install executables
1059 \\ --prefix-include-dir [path] Where to put installed C header files1064 \\ --prefix-include-dir [path] Where to install C header files
1060 \\1065 \\
1061 \\ --release[=mode] Request release mode, optionally specifying a1066 \\ --release[=mode] Request release mode, optionally specifying a
1062 \\ preferred optimization mode: fast, safe, small1067 \\ preferred optimization mode: fast, safe, small
1063 \\1068 \\
1064 \\ --sysroot [path] Set the system root directory (usually /)
1065 \\ --search-prefix [path] Add a path to look for binaries, libraries, headers
1066 \\ --libc [file] Provide a file which specifies libc paths
1067 \\
1068 \\ -fdarling, -fno-darling Integration with system-installed Darling to1069 \\ -fdarling, -fno-darling Integration with system-installed Darling to
1069 \\ execute macOS programs on Linux hosts1070 \\ execute macOS programs on Linux hosts
1070 \\ (default: no)1071 \\ (default: no)
...@@ -1122,13 +1123,18 @@ fn usage(b: *std.Build, out_stream: anytype) !void {...@@ -1122,13 +1123,18 @@ fn usage(b: *std.Build, out_stream: anytype) !void {
1122 try out_stream.writeAll(1123 try out_stream.writeAll(
1123 \\1124 \\
1124 \\System Integration Options:1125 \\System Integration Options:
1125 \\ --system [dir] System Package Mode. Disable fetching; prefer system libs1126 \\ --search-prefix [path] Add a path to look for binaries, libraries, headers
1126 \\ -fsys=[name] Enable a system integration1127 \\ --sysroot [path] Set the system root directory (usually /)
1127 \\ -fno-sys=[name] Disable a system integration1128 \\ --libc [file] Provide a file which specifies libc paths
1129 \\
1128 \\ --host-target [triple] Use the provided target as the host1130 \\ --host-target [triple] Use the provided target as the host
1129 \\ --host-cpu [cpu] Use the provided CPU as the host1131 \\ --host-cpu [cpu] Use the provided CPU as the host
1130 \\ --host-dynamic-linker [path] Use the provided dynamic linker as the host1132 \\ --host-dynamic-linker [path] Use the provided dynamic linker as the host
1131 \\1133 \\
1134 \\ --system [pkgdir] Disable package fetching; enable all integrations
1135 \\ -fsys=[name] Enable a system integration
1136 \\ -fno-sys=[name] Disable a system integration
1137 \\
1132 \\ Available System Integrations: Enabled:1138 \\ Available System Integrations: Enabled:
1133 \\1139 \\
1134 );1140 );
lib/std/Build.zig+1-1
...@@ -1254,7 +1254,7 @@ pub fn standardOptimizeOption(b: *Build, options: StandardOptimizeOptionOptions)...@@ -1254,7 +1254,7 @@ pub fn standardOptimizeOption(b: *Build, options: StandardOptimizeOptionOptions)
1254 if (b.option(1254 if (b.option(
1255 std.builtin.OptimizeMode,1255 std.builtin.OptimizeMode,
1256 "optimize",1256 "optimize",
1257 "Prioritize performance, safety, or binary size (-O flag)",1257 "Prioritize performance, safety, or binary size",
1258 )) |mode| {1258 )) |mode| {
1259 return mode;1259 return mode;
1260 }1260 }
src/Package/Fetch.zig+28-3
...@@ -80,6 +80,15 @@ pub const JobQueue = struct {...@@ -80,6 +80,15 @@ pub const JobQueue = struct {
80 thread_pool: *ThreadPool,80 thread_pool: *ThreadPool,
81 wait_group: WaitGroup = .{},81 wait_group: WaitGroup = .{},
82 global_cache: Cache.Directory,82 global_cache: Cache.Directory,
83 /// If true then, no fetching occurs, and:
84 /// * The `global_cache` directory is assumed to be the direct parent
85 /// directory of on-disk packages rather than having the "p/" directory
86 /// prefix inside of it.
87 /// * An error occurs if any non-lazy packages are not already present in
88 /// the package cache directory.
89 /// * Missing hash field causes an error, and no fetching occurs so it does
90 /// not print the correct hash like usual.
91 read_only: bool,
83 recursive: bool,92 recursive: bool,
84 /// Dumps hash information to stdout which can be used to troubleshoot why93 /// Dumps hash information to stdout which can be used to troubleshoot why
85 /// two hashes of the same package do not match.94 /// two hashes of the same package do not match.
...@@ -270,7 +279,8 @@ pub fn run(f: *Fetch) RunError!void {...@@ -270,7 +279,8 @@ pub fn run(f: *Fetch) RunError!void {
270 // We want to fail unless the resolved relative path has a279 // We want to fail unless the resolved relative path has a
271 // prefix of "p/$hash/".280 // prefix of "p/$hash/".
272 const digest_len = @typeInfo(Manifest.MultiHashHexDigest).Array.len;281 const digest_len = @typeInfo(Manifest.MultiHashHexDigest).Array.len;
273 const expected_prefix = f.parent_package_root.sub_path[0 .. "p/".len + digest_len];282 const prefix_len: usize = if (f.job_queue.read_only) 0 else "p/".len;
283 const expected_prefix = f.parent_package_root.sub_path[0 .. prefix_len + digest_len];
274 if (!std.mem.startsWith(u8, pkg_root.sub_path, expected_prefix)) {284 if (!std.mem.startsWith(u8, pkg_root.sub_path, expected_prefix)) {
275 return f.fail(285 return f.fail(
276 f.location_tok,286 f.location_tok,
...@@ -311,7 +321,9 @@ pub fn run(f: *Fetch) RunError!void {...@@ -311,7 +321,9 @@ pub fn run(f: *Fetch) RunError!void {
311321
312 const s = fs.path.sep_str;322 const s = fs.path.sep_str;
313 if (remote.hash) |expected_hash| {323 if (remote.hash) |expected_hash| {
314 const pkg_sub_path = "p" ++ s ++ expected_hash;324 const prefixed_pkg_sub_path = "p" ++ s ++ expected_hash;
325 const prefix_len: usize = if (f.job_queue.read_only) "p/".len else 0;
326 const pkg_sub_path = prefixed_pkg_sub_path[prefix_len..];
315 if (cache_root.handle.access(pkg_sub_path, .{})) |_| {327 if (cache_root.handle.access(pkg_sub_path, .{})) |_| {
316 f.package_root = .{328 f.package_root = .{
317 .root_dir = cache_root,329 .root_dir = cache_root,
...@@ -322,7 +334,14 @@ pub fn run(f: *Fetch) RunError!void {...@@ -322,7 +334,14 @@ pub fn run(f: *Fetch) RunError!void {
322 if (!f.job_queue.recursive) return;334 if (!f.job_queue.recursive) return;
323 return queueJobsForDeps(f);335 return queueJobsForDeps(f);
324 } else |err| switch (err) {336 } else |err| switch (err) {
325 error.FileNotFound => {},337 error.FileNotFound => {
338 if (f.job_queue.read_only) return f.fail(
339 f.location_tok,
340 try eb.printString("package not found at '{}{s}'", .{
341 cache_root, pkg_sub_path,
342 }),
343 );
344 },
326 else => |e| {345 else => |e| {
327 try eb.addRootErrorMessage(.{346 try eb.addRootErrorMessage(.{
328 .msg = try eb.printString("unable to open global package cache directory '{}{s}': {s}", .{347 .msg = try eb.printString("unable to open global package cache directory '{}{s}': {s}", .{
...@@ -332,6 +351,12 @@ pub fn run(f: *Fetch) RunError!void {...@@ -332,6 +351,12 @@ pub fn run(f: *Fetch) RunError!void {
332 return error.FetchFailed;351 return error.FetchFailed;
333 },352 },
334 }353 }
354 } else {
355 try eb.addRootErrorMessage(.{
356 .msg = try eb.addString("dependency is missing hash field"),
357 .src_loc = try f.srcLoc(f.location_tok),
358 });
359 return error.FetchFailed;
335 }360 }
336361
337 // Fetch and unpack the remote into a temporary directory.362 // Fetch and unpack the remote into a temporary directory.
src/main.zig+24-2
...@@ -5179,6 +5179,7 @@ pub fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi...@@ -5179,6 +5179,7 @@ pub fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi
5179 var verbose_cimport = false;5179 var verbose_cimport = false;
5180 var verbose_llvm_cpu_features = false;5180 var verbose_llvm_cpu_features = false;
5181 var fetch_only = false;5181 var fetch_only = false;
5182 var system_pkg_dir_path: ?[]const u8 = null;
51825183
5183 const argv_index_exe = child_argv.items.len;5184 const argv_index_exe = child_argv.items.len;
5184 _ = try child_argv.addOne();5185 _ = try child_argv.addOne();
...@@ -5235,6 +5236,12 @@ pub fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi...@@ -5235,6 +5236,12 @@ pub fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi
5235 reference_trace = 256;5236 reference_trace = 256;
5236 } else if (mem.eql(u8, arg, "--fetch")) {5237 } else if (mem.eql(u8, arg, "--fetch")) {
5237 fetch_only = true;5238 fetch_only = true;
5239 } else if (mem.eql(u8, arg, "--system")) {
5240 if (i + 1 >= args.len) fatal("expected argument after '{s}'", .{arg});
5241 i += 1;
5242 system_pkg_dir_path = args[i];
5243 try child_argv.append("--system");
5244 continue;
5238 } else if (mem.startsWith(u8, arg, "-freference-trace=")) {5245 } else if (mem.startsWith(u8, arg, "-freference-trace=")) {
5239 const num = arg["-freference-trace=".len..];5246 const num = arg["-freference-trace=".len..];
5240 reference_trace = std.fmt.parseUnsigned(u32, num, 10) catch |err| {5247 reference_trace = std.fmt.parseUnsigned(u32, num, 10) catch |err| {
...@@ -5419,8 +5426,6 @@ pub fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi...@@ -5419,8 +5426,6 @@ pub fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi
5419 var http_client: std.http.Client = .{ .allocator = gpa };5426 var http_client: std.http.Client = .{ .allocator = gpa };
5420 defer http_client.deinit();5427 defer http_client.deinit();
54215428
5422 try http_client.loadDefaultProxies();
5423
5424 var progress: std.Progress = .{ .dont_print_on_dumb = true };5429 var progress: std.Progress = .{ .dont_print_on_dumb = true };
5425 const root_prog_node = progress.start("Fetch Packages", 0);5430 const root_prog_node = progress.start("Fetch Packages", 0);
5426 defer root_prog_node.end();5431 defer root_prog_node.end();
...@@ -5429,12 +5434,28 @@ pub fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi...@@ -5429,12 +5434,28 @@ pub fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi
5429 .http_client = &http_client,5434 .http_client = &http_client,
5430 .thread_pool = &thread_pool,5435 .thread_pool = &thread_pool,
5431 .global_cache = global_cache_directory,5436 .global_cache = global_cache_directory,
5437 .read_only = false,
5432 .recursive = true,5438 .recursive = true,
5433 .debug_hash = false,5439 .debug_hash = false,
5434 .work_around_btrfs_bug = work_around_btrfs_bug,5440 .work_around_btrfs_bug = work_around_btrfs_bug,
5435 };5441 };
5436 defer job_queue.deinit();5442 defer job_queue.deinit();
54375443
5444 if (system_pkg_dir_path) |p| {
5445 job_queue.global_cache = .{
5446 .path = p,
5447 .handle = fs.cwd().openDir(p, .{}) catch |err| {
5448 fatal("unable to open system package directory '{s}': {s}", .{
5449 p, @errorName(err),
5450 });
5451 },
5452 };
5453 job_queue.read_only = true;
5454 cleanup_build_dir = job_queue.global_cache.handle;
5455 } else {
5456 try http_client.loadDefaultProxies();
5457 }
5458
5438 try job_queue.all_fetches.ensureUnusedCapacity(gpa, 1);5459 try job_queue.all_fetches.ensureUnusedCapacity(gpa, 1);
5439 try job_queue.table.ensureUnusedCapacity(gpa, 1);5460 try job_queue.table.ensureUnusedCapacity(gpa, 1);
54405461
...@@ -7363,6 +7384,7 @@ fn cmdFetch(...@@ -7363,6 +7384,7 @@ fn cmdFetch(
7363 .thread_pool = &thread_pool,7384 .thread_pool = &thread_pool,
7364 .global_cache = global_cache_directory,7385 .global_cache = global_cache_directory,
7365 .recursive = false,7386 .recursive = false,
7387 .read_only = false,
7366 .debug_hash = debug_hash,7388 .debug_hash = debug_hash,
7367 .work_around_btrfs_bug = work_around_btrfs_bug,7389 .work_around_btrfs_bug = work_around_btrfs_bug,
7368 };7390 };