| author | |
| committer | |
| log | d3fc2648cc94f0e98ab1299711c02bb5b3f2864c |
| tree | 0b85fdd16ee2d07b7a0fb87a0ff51724f9f4b40c |
| parent | 9bf97b8494524074b1d3cfe71cd08aae335ba576 |
| parent | 3dad7312b2c0f84c557b1cf01cfbbbaa04ffc79c |
| signature |
Implement system package mode and lazy dependencies21 files changed, 1169 insertions(+), 719 deletions(-)
build.zig+2-2| ... | ... | @@ -45,7 +45,7 @@ pub fn build(b: *std.Build) !void { |
| 45 | 45 | }); |
| 46 | 46 | |
| 47 | 47 | const docgen_cmd = b.addRunArtifact(docgen_exe); |
| 48 | docgen_cmd.addArgs(&.{ "--zig", b.zig_exe }); | |
| 48 | docgen_cmd.addArgs(&.{ "--zig", b.graph.zig_exe }); | |
| 49 | 49 | if (b.zig_lib_dir) |p| { |
| 50 | 50 | docgen_cmd.addArg("--zig-lib-dir"); |
| 51 | 51 | docgen_cmd.addDirectoryArg(p); |
| ... | ... | @@ -884,7 +884,7 @@ fn findConfigH(b: *std.Build, config_h_path_option: ?[]const u8) ?[]const u8 { |
| 884 | 884 | } |
| 885 | 885 | } |
| 886 | 886 | |
| 887 | var check_dir = fs.path.dirname(b.zig_exe).?; | |
| 887 | var check_dir = fs.path.dirname(b.graph.zig_exe).?; | |
| 888 | 888 | while (true) { |
| 889 | 889 | var dir = fs.cwd().openDir(check_dir, .{}) catch unreachable; |
| 890 | 890 | defer dir.close(); |
deps/aro/build/GenerateDef.zig+1-1| ... | ... | @@ -53,7 +53,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { |
| 53 | 53 | const self = @fieldParentPtr(GenerateDef, "step", step); |
| 54 | 54 | const arena = b.allocator; |
| 55 | 55 | |
| 56 | var man = b.cache.obtain(); | |
| 56 | var man = b.graph.cache.obtain(); | |
| 57 | 57 | defer man.deinit(); |
| 58 | 58 | |
| 59 | 59 | // Random bytes to make GenerateDef unique. Refresh this with new |
lib/build_runner.zig+205-136| ... | ... | @@ -46,11 +46,6 @@ pub fn main() !void { |
| 46 | 46 | return error.InvalidArgs; |
| 47 | 47 | }; |
| 48 | 48 | |
| 49 | const host: std.Build.ResolvedTarget = .{ | |
| 50 | .query = .{}, | |
| 51 | .result = try std.zig.system.resolveTargetQuery(.{}), | |
| 52 | }; | |
| 53 | ||
| 54 | 49 | const build_root_directory: std.Build.Cache.Directory = .{ |
| 55 | 50 | .path = build_root, |
| 56 | 51 | .handle = try std.fs.cwd().openDir(build_root, .{}), |
| ... | ... | @@ -66,27 +61,29 @@ pub fn main() !void { |
| 66 | 61 | .handle = try std.fs.cwd().makeOpenPath(global_cache_root, .{}), |
| 67 | 62 | }; |
| 68 | 63 | |
| 69 | var cache: std.Build.Cache = .{ | |
| 70 | .gpa = arena, | |
| 71 | .manifest_dir = try local_cache_directory.handle.makeOpenPath("h", .{}), | |
| 64 | var graph: std.Build.Graph = .{ | |
| 65 | .arena = arena, | |
| 66 | .cache = .{ | |
| 67 | .gpa = arena, | |
| 68 | .manifest_dir = try local_cache_directory.handle.makeOpenPath("h", .{}), | |
| 69 | }, | |
| 70 | .zig_exe = zig_exe, | |
| 71 | .env_map = try process.getEnvMap(arena), | |
| 72 | .global_cache_root = global_cache_directory, | |
| 72 | 73 | }; |
| 73 | cache.addPrefix(.{ .path = null, .handle = std.fs.cwd() }); | |
| 74 | cache.addPrefix(build_root_directory); | |
| 75 | cache.addPrefix(local_cache_directory); | |
| 76 | cache.addPrefix(global_cache_directory); | |
| 77 | cache.hash.addBytes(builtin.zig_version_string); | |
| 74 | ||
| 75 | graph.cache.addPrefix(.{ .path = null, .handle = std.fs.cwd() }); | |
| 76 | graph.cache.addPrefix(build_root_directory); | |
| 77 | graph.cache.addPrefix(local_cache_directory); | |
| 78 | graph.cache.addPrefix(global_cache_directory); | |
| 79 | graph.cache.hash.addBytes(builtin.zig_version_string); | |
| 78 | 80 | |
| 79 | 81 | const builder = try std.Build.create( |
| 80 | arena, | |
| 81 | zig_exe, | |
| 82 | &graph, | |
| 82 | 83 | build_root_directory, |
| 83 | 84 | local_cache_directory, |
| 84 | global_cache_directory, | |
| 85 | host, | |
| 86 | &cache, | |
| 87 | 85 | dependencies.root_deps, |
| 88 | 86 | ); |
| 89 | defer builder.destroy(); | |
| 90 | 87 | |
| 91 | 88 | var targets = ArrayList([]const u8).init(arena); |
| 92 | 89 | var debug_log_scopes = ArrayList([]const u8).init(arena); |
| ... | ... | @@ -100,64 +97,67 @@ pub fn main() !void { |
| 100 | 97 | var color: Color = .auto; |
| 101 | 98 | var seed: u32 = 0; |
| 102 | 99 | var prominent_compile_errors: bool = false; |
| 103 | ||
| 104 | const stderr_stream = io.getStdErr().writer(); | |
| 105 | const stdout_stream = io.getStdOut().writer(); | |
| 100 | var help_menu: bool = false; | |
| 101 | var steps_menu: bool = false; | |
| 102 | var output_tmp_nonce: ?[16]u8 = null; | |
| 106 | 103 | |
| 107 | 104 | while (nextArg(args, &arg_idx)) |arg| { |
| 108 | if (mem.startsWith(u8, arg, "-D")) { | |
| 105 | if (mem.startsWith(u8, arg, "-Z")) { | |
| 106 | if (arg.len != 18) fatalWithHint("bad argument: '{s}'", .{arg}); | |
| 107 | output_tmp_nonce = arg[2..18].*; | |
| 108 | } else if (mem.startsWith(u8, arg, "-D")) { | |
| 109 | 109 | const option_contents = arg[2..]; |
| 110 | if (option_contents.len == 0) { | |
| 111 | std.debug.print("Expected option name after '-D'\n\n", .{}); | |
| 112 | usageAndErr(builder, false, stderr_stream); | |
| 113 | } | |
| 110 | if (option_contents.len == 0) | |
| 111 | fatalWithHint("expected option name after '-D'", .{}); | |
| 114 | 112 | if (mem.indexOfScalar(u8, option_contents, '=')) |name_end| { |
| 115 | 113 | const option_name = option_contents[0..name_end]; |
| 116 | 114 | const option_value = option_contents[name_end + 1 ..]; |
| 117 | 115 | if (try builder.addUserInputOption(option_name, option_value)) |
| 118 | usageAndErr(builder, false, stderr_stream); | |
| 116 | fatal(" access the help menu with 'zig build -h'", .{}); | |
| 119 | 117 | } else { |
| 120 | 118 | if (try builder.addUserInputFlag(option_contents)) |
| 121 | usageAndErr(builder, false, stderr_stream); | |
| 119 | fatal(" access the help menu with 'zig build -h'", .{}); | |
| 122 | 120 | } |
| 123 | 121 | } else if (mem.startsWith(u8, arg, "-")) { |
| 124 | 122 | if (mem.eql(u8, arg, "--verbose")) { |
| 125 | 123 | builder.verbose = true; |
| 126 | 124 | } else if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) { |
| 127 | return usage(builder, false, stdout_stream); | |
| 125 | help_menu = true; | |
| 128 | 126 | } else if (mem.eql(u8, arg, "-p") or mem.eql(u8, arg, "--prefix")) { |
| 129 | install_prefix = nextArg(args, &arg_idx) orelse { | |
| 130 | std.debug.print("Expected argument after {s}\n\n", .{arg}); | |
| 131 | usageAndErr(builder, false, stderr_stream); | |
| 132 | }; | |
| 127 | install_prefix = nextArgOrFatal(args, &arg_idx); | |
| 133 | 128 | } else if (mem.eql(u8, arg, "-l") or mem.eql(u8, arg, "--list-steps")) { |
| 134 | return steps(builder, false, stdout_stream); | |
| 135 | } else if (mem.eql(u8, arg, "--prefix-lib-dir")) { | |
| 136 | dir_list.lib_dir = nextArg(args, &arg_idx) orelse { | |
| 137 | std.debug.print("Expected argument after {s}\n\n", .{arg}); | |
| 138 | usageAndErr(builder, false, stderr_stream); | |
| 129 | steps_menu = true; | |
| 130 | } else if (mem.startsWith(u8, arg, "-fsys=")) { | |
| 131 | const name = arg["-fsys=".len..]; | |
| 132 | graph.system_library_options.put(arena, name, .user_enabled) catch @panic("OOM"); | |
| 133 | } else if (mem.startsWith(u8, arg, "-fno-sys=")) { | |
| 134 | const name = arg["-fno-sys=".len..]; | |
| 135 | graph.system_library_options.put(arena, name, .user_disabled) catch @panic("OOM"); | |
| 136 | } else if (mem.eql(u8, arg, "--release")) { | |
| 137 | builder.release_mode = .any; | |
| 138 | } else if (mem.startsWith(u8, arg, "--release=")) { | |
| 139 | const text = arg["--release=".len..]; | |
| 140 | builder.release_mode = std.meta.stringToEnum(std.Build.ReleaseMode, text) orelse { | |
| 141 | fatalWithHint("expected [off|any|fast|safe|small] in '{s}', found '{s}'", .{ | |
| 142 | arg, text, | |
| 143 | }); | |
| 139 | 144 | }; |
| 145 | } else if (mem.eql(u8, arg, "--host-target")) { | |
| 146 | graph.host_query_options.arch_os_abi = nextArgOrFatal(args, &arg_idx); | |
| 147 | } else if (mem.eql(u8, arg, "--host-cpu")) { | |
| 148 | graph.host_query_options.cpu_features = nextArgOrFatal(args, &arg_idx); | |
| 149 | } else if (mem.eql(u8, arg, "--host-dynamic-linker")) { | |
| 150 | graph.host_query_options.dynamic_linker = nextArgOrFatal(args, &arg_idx); | |
| 151 | } else if (mem.eql(u8, arg, "--prefix-lib-dir")) { | |
| 152 | dir_list.lib_dir = nextArgOrFatal(args, &arg_idx); | |
| 140 | 153 | } else if (mem.eql(u8, arg, "--prefix-exe-dir")) { |
| 141 | dir_list.exe_dir = nextArg(args, &arg_idx) orelse { | |
| 142 | std.debug.print("Expected argument after {s}\n\n", .{arg}); | |
| 143 | usageAndErr(builder, false, stderr_stream); | |
| 144 | }; | |
| 154 | dir_list.exe_dir = nextArgOrFatal(args, &arg_idx); | |
| 145 | 155 | } else if (mem.eql(u8, arg, "--prefix-include-dir")) { |
| 146 | dir_list.include_dir = nextArg(args, &arg_idx) orelse { | |
| 147 | std.debug.print("Expected argument after {s}\n\n", .{arg}); | |
| 148 | usageAndErr(builder, false, stderr_stream); | |
| 149 | }; | |
| 156 | dir_list.include_dir = nextArgOrFatal(args, &arg_idx); | |
| 150 | 157 | } else if (mem.eql(u8, arg, "--sysroot")) { |
| 151 | const sysroot = nextArg(args, &arg_idx) orelse { | |
| 152 | std.debug.print("Expected argument after {s}\n\n", .{arg}); | |
| 153 | usageAndErr(builder, false, stderr_stream); | |
| 154 | }; | |
| 155 | builder.sysroot = sysroot; | |
| 158 | builder.sysroot = nextArgOrFatal(args, &arg_idx); | |
| 156 | 159 | } else if (mem.eql(u8, arg, "--maxrss")) { |
| 157 | const max_rss_text = nextArg(args, &arg_idx) orelse { | |
| 158 | std.debug.print("Expected argument after {s}\n\n", .{arg}); | |
| 159 | usageAndErr(builder, false, stderr_stream); | |
| 160 | }; | |
| 160 | const max_rss_text = nextArgOrFatal(args, &arg_idx); | |
| 161 | 161 | max_rss = std.fmt.parseIntSizeSuffix(max_rss_text, 10) catch |err| { |
| 162 | 162 | std.debug.print("invalid byte size: '{s}': {s}\n", .{ |
| 163 | 163 | max_rss_text, @errorName(err), |
| ... | ... | @@ -167,66 +167,50 @@ pub fn main() !void { |
| 167 | 167 | } else if (mem.eql(u8, arg, "--skip-oom-steps")) { |
| 168 | 168 | skip_oom_steps = true; |
| 169 | 169 | } else if (mem.eql(u8, arg, "--search-prefix")) { |
| 170 | const search_prefix = nextArg(args, &arg_idx) orelse { | |
| 171 | std.debug.print("Expected argument after {s}\n\n", .{arg}); | |
| 172 | usageAndErr(builder, false, stderr_stream); | |
| 173 | }; | |
| 170 | const search_prefix = nextArgOrFatal(args, &arg_idx); | |
| 174 | 171 | builder.addSearchPrefix(search_prefix); |
| 175 | 172 | } else if (mem.eql(u8, arg, "--libc")) { |
| 176 | const libc_file = nextArg(args, &arg_idx) orelse { | |
| 177 | std.debug.print("Expected argument after {s}\n\n", .{arg}); | |
| 178 | usageAndErr(builder, false, stderr_stream); | |
| 179 | }; | |
| 180 | builder.libc_file = libc_file; | |
| 173 | builder.libc_file = nextArgOrFatal(args, &arg_idx); | |
| 181 | 174 | } else if (mem.eql(u8, arg, "--color")) { |
| 182 | const next_arg = nextArg(args, &arg_idx) orelse { | |
| 183 | std.debug.print("Expected [auto|on|off] after {s}\n\n", .{arg}); | |
| 184 | usageAndErr(builder, false, stderr_stream); | |
| 185 | }; | |
| 175 | const next_arg = nextArg(args, &arg_idx) orelse | |
| 176 | fatalWithHint("expected [auto|on|off] after '{s}'", .{arg}); | |
| 186 | 177 | color = std.meta.stringToEnum(Color, next_arg) orelse { |
| 187 | std.debug.print("Expected [auto|on|off] after {s}, found '{s}'\n\n", .{ arg, next_arg }); | |
| 188 | usageAndErr(builder, false, stderr_stream); | |
| 178 | fatalWithHint("expected [auto|on|off] after '{s}', found '{s}'", .{ | |
| 179 | arg, next_arg, | |
| 180 | }); | |
| 189 | 181 | }; |
| 190 | 182 | } else if (mem.eql(u8, arg, "--summary")) { |
| 191 | const next_arg = nextArg(args, &arg_idx) orelse { | |
| 192 | std.debug.print("Expected [all|failures|none] after {s}\n\n", .{arg}); | |
| 193 | usageAndErr(builder, false, stderr_stream); | |
| 194 | }; | |
| 183 | const next_arg = nextArg(args, &arg_idx) orelse | |
| 184 | fatalWithHint("expected [all|failures|none] after '{s}'", .{arg}); | |
| 195 | 185 | summary = std.meta.stringToEnum(Summary, next_arg) orelse { |
| 196 | std.debug.print("Expected [all|failures|none] after {s}, found '{s}'\n\n", .{ arg, next_arg }); | |
| 197 | usageAndErr(builder, false, stderr_stream); | |
| 186 | fatalWithHint("expected [all|failures|none] after '{s}', found '{s}'", .{ | |
| 187 | arg, next_arg, | |
| 188 | }); | |
| 198 | 189 | }; |
| 199 | 190 | } else if (mem.eql(u8, arg, "--zig-lib-dir")) { |
| 200 | builder.zig_lib_dir = .{ .cwd_relative = nextArg(args, &arg_idx) orelse { | |
| 201 | std.debug.print("Expected argument after {s}\n\n", .{arg}); | |
| 202 | usageAndErr(builder, false, stderr_stream); | |
| 203 | } }; | |
| 191 | builder.zig_lib_dir = .{ .cwd_relative = nextArgOrFatal(args, &arg_idx) }; | |
| 204 | 192 | } else if (mem.eql(u8, arg, "--seed")) { |
| 205 | const next_arg = nextArg(args, &arg_idx) orelse { | |
| 206 | std.debug.print("Expected u32 after {s}\n\n", .{arg}); | |
| 207 | usageAndErr(builder, false, stderr_stream); | |
| 208 | }; | |
| 193 | const next_arg = nextArg(args, &arg_idx) orelse | |
| 194 | fatalWithHint("expected u32 after '{s}'", .{arg}); | |
| 209 | 195 | seed = std.fmt.parseUnsigned(u32, next_arg, 0) catch |err| { |
| 210 | std.debug.print("unable to parse seed '{s}' as 32-bit integer: {s}\n", .{ | |
| 196 | fatal("unable to parse seed '{s}' as 32-bit integer: {s}\n", .{ | |
| 211 | 197 | next_arg, @errorName(err), |
| 212 | 198 | }); |
| 213 | process.exit(1); | |
| 214 | 199 | }; |
| 215 | 200 | } else if (mem.eql(u8, arg, "--debug-log")) { |
| 216 | const next_arg = nextArg(args, &arg_idx) orelse { | |
| 217 | std.debug.print("Expected argument after {s}\n\n", .{arg}); | |
| 218 | usageAndErr(builder, false, stderr_stream); | |
| 219 | }; | |
| 201 | const next_arg = nextArgOrFatal(args, &arg_idx); | |
| 220 | 202 | try debug_log_scopes.append(next_arg); |
| 221 | 203 | } else if (mem.eql(u8, arg, "--debug-pkg-config")) { |
| 222 | 204 | builder.debug_pkg_config = true; |
| 223 | 205 | } else if (mem.eql(u8, arg, "--debug-compile-errors")) { |
| 224 | 206 | builder.debug_compile_errors = true; |
| 207 | } else if (mem.eql(u8, arg, "--system")) { | |
| 208 | // The usage text shows another argument after this parameter | |
| 209 | // but it is handled by the parent process. The build runner | |
| 210 | // only sees this flag. | |
| 211 | graph.system_package_mode = true; | |
| 225 | 212 | } else if (mem.eql(u8, arg, "--glibc-runtimes")) { |
| 226 | builder.glibc_runtimes_dir = nextArg(args, &arg_idx) orelse { | |
| 227 | std.debug.print("Expected argument after {s}\n\n", .{arg}); | |
| 228 | usageAndErr(builder, false, stderr_stream); | |
| 229 | }; | |
| 213 | builder.glibc_runtimes_dir = nextArgOrFatal(args, &arg_idx); | |
| 230 | 214 | } else if (mem.eql(u8, arg, "--verbose-link")) { |
| 231 | 215 | builder.verbose_link = true; |
| 232 | 216 | } else if (mem.eql(u8, arg, "--verbose-air")) { |
| ... | ... | @@ -292,19 +276,26 @@ pub fn main() !void { |
| 292 | 276 | builder.args = argsRest(args, arg_idx); |
| 293 | 277 | break; |
| 294 | 278 | } else { |
| 295 | std.debug.print("Unrecognized argument: {s}\n\n", .{arg}); | |
| 296 | usageAndErr(builder, false, stderr_stream); | |
| 279 | fatalWithHint("unrecognized argument: '{s}'", .{arg}); | |
| 297 | 280 | } |
| 298 | 281 | } else { |
| 299 | 282 | try targets.append(arg); |
| 300 | 283 | } |
| 301 | 284 | } |
| 302 | 285 | |
| 286 | const host_query = std.Build.parseTargetQuery(graph.host_query_options) catch |err| switch (err) { | |
| 287 | error.ParseFailed => process.exit(1), | |
| 288 | }; | |
| 289 | builder.host = .{ | |
| 290 | .query = .{}, | |
| 291 | .result = try std.zig.system.resolveTargetQuery(host_query), | |
| 292 | }; | |
| 293 | ||
| 303 | 294 | const stderr = std.io.getStdErr(); |
| 304 | 295 | const ttyconf = get_tty_conf(color, stderr); |
| 305 | 296 | switch (ttyconf) { |
| 306 | .no_color => try builder.env_map.put("NO_COLOR", "1"), | |
| 307 | .escape_codes => try builder.env_map.put("YES_COLOR", "1"), | |
| 297 | .no_color => try graph.env_map.put("NO_COLOR", "1"), | |
| 298 | .escape_codes => try graph.env_map.put("YES_COLOR", "1"), | |
| 308 | 299 | .windows_api => {}, |
| 309 | 300 | } |
| 310 | 301 | |
| ... | ... | @@ -319,8 +310,39 @@ pub fn main() !void { |
| 319 | 310 | try builder.runBuild(root); |
| 320 | 311 | } |
| 321 | 312 | |
| 322 | if (builder.validateUserInputDidItFail()) | |
| 323 | usageAndErr(builder, true, stderr_stream); | |
| 313 | if (graph.needed_lazy_dependencies.entries.len != 0) { | |
| 314 | var buffer: std.ArrayListUnmanaged(u8) = .{}; | |
| 315 | for (graph.needed_lazy_dependencies.keys()) |k| { | |
| 316 | try buffer.appendSlice(arena, k); | |
| 317 | try buffer.append(arena, '\n'); | |
| 318 | } | |
| 319 | const s = std.fs.path.sep_str; | |
| 320 | const tmp_sub_path = "tmp" ++ s ++ (output_tmp_nonce orelse fatal("missing -Z arg", .{})); | |
| 321 | local_cache_directory.handle.writeFile2(.{ | |
| 322 | .sub_path = tmp_sub_path, | |
| 323 | .data = buffer.items, | |
| 324 | .flags = .{ .exclusive = true }, | |
| 325 | }) catch |err| { | |
| 326 | fatal("unable to write configuration results to '{}{s}': {s}", .{ | |
| 327 | local_cache_directory, tmp_sub_path, @errorName(err), | |
| 328 | }); | |
| 329 | }; | |
| 330 | process.exit(3); // Indicate configure phase failed with meaningful stdout. | |
| 331 | } | |
| 332 | ||
| 333 | if (builder.validateUserInputDidItFail()) { | |
| 334 | fatal(" access the help menu with 'zig build -h'", .{}); | |
| 335 | } | |
| 336 | ||
| 337 | validateSystemLibraryOptions(builder); | |
| 338 | ||
| 339 | const stdout_writer = io.getStdOut().writer(); | |
| 340 | ||
| 341 | if (help_menu) | |
| 342 | return usage(builder, stdout_writer); | |
| 343 | ||
| 344 | if (steps_menu) | |
| 345 | return steps(builder, stdout_writer); | |
| 324 | 346 | |
| 325 | 347 | var run: Run = .{ |
| 326 | 348 | .max_rss = max_rss, |
| ... | ... | @@ -389,7 +411,7 @@ fn runStepNames( |
| 389 | 411 | for (0..step_names.len) |i| { |
| 390 | 412 | const step_name = step_names[step_names.len - i - 1]; |
| 391 | 413 | const s = b.top_level_steps.get(step_name) orelse { |
| 392 | std.debug.print("no step named '{s}'. Access the help menu with 'zig build -h'\n", .{step_name}); | |
| 414 | std.debug.print("no step named '{s}'\n access the help menu with 'zig build -h'\n", .{step_name}); | |
| 393 | 415 | process.exit(1); |
| 394 | 416 | }; |
| 395 | 417 | step_stack.putAssumeCapacity(&s.step, {}); |
| ... | ... | @@ -1037,13 +1059,7 @@ fn printErrorMessages(b: *std.Build, failing_step: *Step, run: *const Run) !void |
| 1037 | 1059 | } |
| 1038 | 1060 | } |
| 1039 | 1061 | |
| 1040 | fn steps(builder: *std.Build, already_ran_build: bool, out_stream: anytype) !void { | |
| 1041 | // run the build script to collect the options | |
| 1042 | if (!already_ran_build) { | |
| 1043 | builder.resolveInstallPrefix(null, .{}); | |
| 1044 | try builder.runBuild(root); | |
| 1045 | } | |
| 1046 | ||
| 1062 | fn steps(builder: *std.Build, out_stream: anytype) !void { | |
| 1047 | 1063 | const allocator = builder.allocator; |
| 1048 | 1064 | for (builder.top_level_steps.values()) |top_level_step| { |
| 1049 | 1065 | const name = if (&top_level_step.step == builder.default_step) |
| ... | ... | @@ -1054,33 +1070,25 @@ fn steps(builder: *std.Build, already_ran_build: bool, out_stream: anytype) !voi |
| 1054 | 1070 | } |
| 1055 | 1071 | } |
| 1056 | 1072 | |
| 1057 | fn usage(builder: *std.Build, already_ran_build: bool, out_stream: anytype) !void { | |
| 1058 | // run the build script to collect the options | |
| 1059 | if (!already_ran_build) { | |
| 1060 | builder.resolveInstallPrefix(null, .{}); | |
| 1061 | try builder.runBuild(root); | |
| 1062 | } | |
| 1063 | ||
| 1073 | fn usage(b: *std.Build, out_stream: anytype) !void { | |
| 1064 | 1074 | try out_stream.print( |
| 1065 | \\ | |
| 1066 | 1075 | \\Usage: {s} build [steps] [options] |
| 1067 | 1076 | \\ |
| 1068 | 1077 | \\Steps: |
| 1069 | 1078 | \\ |
| 1070 | , .{builder.zig_exe}); | |
| 1071 | try steps(builder, true, out_stream); | |
| 1079 | , .{b.graph.zig_exe}); | |
| 1080 | try steps(b, out_stream); | |
| 1072 | 1081 | |
| 1073 | 1082 | try out_stream.writeAll( |
| 1074 | 1083 | \\ |
| 1075 | 1084 | \\General Options: |
| 1076 | \\ -p, --prefix [path] Override default install prefix | |
| 1077 | \\ --prefix-lib-dir [path] Override default library directory path | |
| 1078 | \\ --prefix-exe-dir [path] Override default executable directory path | |
| 1079 | \\ --prefix-include-dir [path] Override default include directory path | |
| 1085 | \\ -p, --prefix [path] Where to install files (default: zig-out) | |
| 1086 | \\ --prefix-lib-dir [path] Where to install libraries | |
| 1087 | \\ --prefix-exe-dir [path] Where to install executables | |
| 1088 | \\ --prefix-include-dir [path] Where to install C header files | |
| 1080 | 1089 | \\ |
| 1081 | \\ --sysroot [path] Set the system root directory (usually /) | |
| 1082 | \\ --search-prefix [path] Add a path to look for binaries, libraries, headers | |
| 1083 | \\ --libc [file] Provide a file which specifies libc paths | |
| 1090 | \\ --release[=mode] Request release mode, optionally specifying a | |
| 1091 | \\ preferred optimization mode: fast, safe, small | |
| 1084 | 1092 | \\ |
| 1085 | 1093 | \\ -fdarling, -fno-darling Integration with system-installed Darling to |
| 1086 | 1094 | \\ execute macOS programs on Linux hosts |
| ... | ... | @@ -1116,16 +1124,15 @@ fn usage(builder: *std.Build, already_ran_build: bool, out_stream: anytype) !voi |
| 1116 | 1124 | \\ |
| 1117 | 1125 | ); |
| 1118 | 1126 | |
| 1119 | const allocator = builder.allocator; | |
| 1120 | if (builder.available_options_list.items.len == 0) { | |
| 1127 | const arena = b.allocator; | |
| 1128 | if (b.available_options_list.items.len == 0) { | |
| 1121 | 1129 | try out_stream.print(" (none)\n", .{}); |
| 1122 | 1130 | } else { |
| 1123 | for (builder.available_options_list.items) |option| { | |
| 1124 | const name = try fmt.allocPrint(allocator, " -D{s}=[{s}]", .{ | |
| 1131 | for (b.available_options_list.items) |option| { | |
| 1132 | const name = try fmt.allocPrint(arena, " -D{s}=[{s}]", .{ | |
| 1125 | 1133 | option.name, |
| 1126 | 1134 | @tagName(option.type_id), |
| 1127 | 1135 | }); |
| 1128 | defer allocator.free(name); | |
| 1129 | 1136 | try out_stream.print("{s:<30} {s}\n", .{ name, option.description }); |
| 1130 | 1137 | if (option.enum_options) |enum_options| { |
| 1131 | 1138 | const padding = " " ** 33; |
| ... | ... | @@ -1137,6 +1144,37 @@ fn usage(builder: *std.Build, already_ran_build: bool, out_stream: anytype) !voi |
| 1137 | 1144 | } |
| 1138 | 1145 | } |
| 1139 | 1146 | |
| 1147 | try out_stream.writeAll( | |
| 1148 | \\ | |
| 1149 | \\System Integration Options: | |
| 1150 | \\ --search-prefix [path] Add a path to look for binaries, libraries, headers | |
| 1151 | \\ --sysroot [path] Set the system root directory (usually /) | |
| 1152 | \\ --libc [file] Provide a file which specifies libc paths | |
| 1153 | \\ | |
| 1154 | \\ --host-target [triple] Use the provided target as the host | |
| 1155 | \\ --host-cpu [cpu] Use the provided CPU as the host | |
| 1156 | \\ --host-dynamic-linker [path] Use the provided dynamic linker as the host | |
| 1157 | \\ | |
| 1158 | \\ --system [pkgdir] Disable package fetching; enable all integrations | |
| 1159 | \\ -fsys=[name] Enable a system integration | |
| 1160 | \\ -fno-sys=[name] Disable a system integration | |
| 1161 | \\ | |
| 1162 | \\ Available System Integrations: Enabled: | |
| 1163 | \\ | |
| 1164 | ); | |
| 1165 | if (b.graph.system_library_options.entries.len == 0) { | |
| 1166 | try out_stream.writeAll(" (none) -\n"); | |
| 1167 | } else { | |
| 1168 | for (b.graph.system_library_options.keys(), b.graph.system_library_options.values()) |k, v| { | |
| 1169 | const status = switch (v) { | |
| 1170 | .declared_enabled => "yes", | |
| 1171 | .declared_disabled => "no", | |
| 1172 | .user_enabled, .user_disabled => unreachable, // already emitted error | |
| 1173 | }; | |
| 1174 | try out_stream.print(" {s:<43} {s}\n", .{ k, status }); | |
| 1175 | } | |
| 1176 | } | |
| 1177 | ||
| 1140 | 1178 | try out_stream.writeAll( |
| 1141 | 1179 | \\ |
| 1142 | 1180 | \\Advanced Options: |
| ... | ... | @@ -1161,17 +1199,19 @@ fn usage(builder: *std.Build, already_ran_build: bool, out_stream: anytype) !voi |
| 1161 | 1199 | ); |
| 1162 | 1200 | } |
| 1163 | 1201 | |
| 1164 | fn usageAndErr(builder: *std.Build, already_ran_build: bool, out_stream: anytype) noreturn { | |
| 1165 | usage(builder, already_ran_build, out_stream) catch {}; | |
| 1166 | process.exit(1); | |
| 1167 | } | |
| 1168 | ||
| 1169 | 1202 | fn nextArg(args: [][:0]const u8, idx: *usize) ?[:0]const u8 { |
| 1170 | 1203 | if (idx.* >= args.len) return null; |
| 1171 | 1204 | defer idx.* += 1; |
| 1172 | 1205 | return args[idx.*]; |
| 1173 | 1206 | } |
| 1174 | 1207 | |
| 1208 | fn nextArgOrFatal(args: [][:0]const u8, idx: *usize) [:0]const u8 { | |
| 1209 | return nextArg(args, idx) orelse { | |
| 1210 | std.debug.print("expected argument after '{s}'\n access the help menu with 'zig build -h'\n", .{args[idx.*]}); | |
| 1211 | process.exit(1); | |
| 1212 | }; | |
| 1213 | } | |
| 1214 | ||
| 1175 | 1215 | fn argsRest(args: [][:0]const u8, idx: usize) ?[][:0]const u8 { |
| 1176 | 1216 | if (idx >= args.len) return null; |
| 1177 | 1217 | return args[idx..]; |
| ... | ... | @@ -1202,3 +1242,32 @@ fn renderOptions(ttyconf: std.io.tty.Config) std.zig.ErrorBundle.RenderOptions { |
| 1202 | 1242 | .include_reference_trace = ttyconf != .no_color, |
| 1203 | 1243 | }; |
| 1204 | 1244 | } |
| 1245 | ||
| 1246 | fn fatalWithHint(comptime f: []const u8, args: anytype) noreturn { | |
| 1247 | std.debug.print(f ++ "\n access the help menu with 'zig build -h'\n", args); | |
| 1248 | process.exit(1); | |
| 1249 | } | |
| 1250 | ||
| 1251 | fn fatal(comptime f: []const u8, args: anytype) noreturn { | |
| 1252 | std.debug.print(f ++ "\n", args); | |
| 1253 | process.exit(1); | |
| 1254 | } | |
| 1255 | ||
| 1256 | fn validateSystemLibraryOptions(b: *std.Build) void { | |
| 1257 | var bad = false; | |
| 1258 | for (b.graph.system_library_options.keys(), b.graph.system_library_options.values()) |k, v| { | |
| 1259 | switch (v) { | |
| 1260 | .user_disabled, .user_enabled => { | |
| 1261 | // The user tried to enable or disable a system library integration, but | |
| 1262 | // the build script did not recognize that option. | |
| 1263 | std.debug.print("system library name not recognized by build script: '{s}'\n", .{k}); | |
| 1264 | bad = true; | |
| 1265 | }, | |
| 1266 | .declared_disabled, .declared_enabled => {}, | |
| 1267 | } | |
| 1268 | } | |
| 1269 | if (bad) { | |
| 1270 | std.debug.print(" access the help menu with 'zig build -h'\n", .{}); | |
| 1271 | process.exit(1); | |
| 1272 | } | |
| 1273 | } |
lib/std/Build.zig+250-113| ... | ... | @@ -22,6 +22,8 @@ pub const Cache = @import("Build/Cache.zig"); |
| 22 | 22 | pub const Step = @import("Build/Step.zig"); |
| 23 | 23 | pub const Module = @import("Build/Module.zig"); |
| 24 | 24 | |
| 25 | /// Shared state among all Build instances. | |
| 26 | graph: *Graph, | |
| 25 | 27 | install_tls: TopLevelStep, |
| 26 | 28 | uninstall_tls: TopLevelStep, |
| 27 | 29 | allocator: Allocator, |
| ... | ... | @@ -38,9 +40,7 @@ verbose_cimport: bool, |
| 38 | 40 | verbose_llvm_cpu_features: bool, |
| 39 | 41 | reference_trace: ?u32 = null, |
| 40 | 42 | invalid_user_input: bool, |
| 41 | zig_exe: [:0]const u8, | |
| 42 | 43 | default_step: *Step, |
| 43 | env_map: *EnvMap, | |
| 44 | 44 | top_level_steps: std.StringArrayHashMapUnmanaged(*TopLevelStep), |
| 45 | 45 | install_prefix: []const u8, |
| 46 | 46 | dest_dir: ?[]const u8, |
| ... | ... | @@ -49,14 +49,12 @@ exe_dir: []const u8, |
| 49 | 49 | h_dir: []const u8, |
| 50 | 50 | install_path: []const u8, |
| 51 | 51 | sysroot: ?[]const u8 = null, |
| 52 | search_prefixes: ArrayList([]const u8), | |
| 52 | search_prefixes: std.ArrayListUnmanaged([]const u8), | |
| 53 | 53 | libc_file: ?[]const u8 = null, |
| 54 | 54 | installed_files: ArrayList(InstalledFile), |
| 55 | 55 | /// Path to the directory containing build.zig. |
| 56 | 56 | build_root: Cache.Directory, |
| 57 | 57 | cache_root: Cache.Directory, |
| 58 | global_cache_root: Cache.Directory, | |
| 59 | cache: *Cache, | |
| 60 | 58 | zig_lib_dir: ?LazyPath, |
| 61 | 59 | pkg_config_pkg_list: ?(PkgConfigError![]const PkgConfigPkg) = null, |
| 62 | 60 | args: ?[][]const u8 = null, |
| ... | ... | @@ -98,8 +96,47 @@ initialized_deps: *InitializedDepMap, |
| 98 | 96 | /// A mapping from dependency names to package hashes. |
| 99 | 97 | available_deps: AvailableDeps, |
| 100 | 98 | |
| 99 | release_mode: ReleaseMode, | |
| 100 | ||
| 101 | pub const ReleaseMode = enum { | |
| 102 | off, | |
| 103 | any, | |
| 104 | fast, | |
| 105 | safe, | |
| 106 | small, | |
| 107 | }; | |
| 108 | ||
| 109 | /// Shared state among all Build instances. | |
| 110 | /// Settings that are here rather than in Build are not configurable per-package. | |
| 111 | pub const Graph = struct { | |
| 112 | arena: Allocator, | |
| 113 | system_library_options: std.StringArrayHashMapUnmanaged(SystemLibraryMode) = .{}, | |
| 114 | system_package_mode: bool = false, | |
| 115 | cache: Cache, | |
| 116 | zig_exe: [:0]const u8, | |
| 117 | env_map: EnvMap, | |
| 118 | global_cache_root: Cache.Directory, | |
| 119 | host_query_options: std.Target.Query.ParseOptions = .{}, | |
| 120 | needed_lazy_dependencies: std.StringArrayHashMapUnmanaged(void) = .{}, | |
| 121 | }; | |
| 122 | ||
| 101 | 123 | const AvailableDeps = []const struct { []const u8, []const u8 }; |
| 102 | 124 | |
| 125 | const SystemLibraryMode = enum { | |
| 126 | /// User asked for the library to be disabled. | |
| 127 | /// The build runner has not confirmed whether the setting is recognized yet. | |
| 128 | user_disabled, | |
| 129 | /// User asked for the library to be enabled. | |
| 130 | /// The build runner has not confirmed whether the setting is recognized yet. | |
| 131 | user_enabled, | |
| 132 | /// The build runner has confirmed that this setting is recognized. | |
| 133 | /// System integration with this library has been resolved to off. | |
| 134 | declared_disabled, | |
| 135 | /// The build runner has confirmed that this setting is recognized. | |
| 136 | /// System integration with this library has been resolved to on. | |
| 137 | declared_enabled, | |
| 138 | }; | |
| 139 | ||
| 103 | 140 | const InitializedDepMap = std.HashMap(InitializedDepKey, *Dependency, InitializedDepContext, std.hash_map.default_max_load_percentage); |
| 104 | 141 | const InitializedDepKey = struct { |
| 105 | 142 | build_root_string: []const u8, |
| ... | ... | @@ -208,28 +245,20 @@ pub const DirList = struct { |
| 208 | 245 | }; |
| 209 | 246 | |
| 210 | 247 | pub fn create( |
| 211 | allocator: Allocator, | |
| 212 | zig_exe: [:0]const u8, | |
| 248 | graph: *Graph, | |
| 213 | 249 | build_root: Cache.Directory, |
| 214 | 250 | cache_root: Cache.Directory, |
| 215 | global_cache_root: Cache.Directory, | |
| 216 | host: ResolvedTarget, | |
| 217 | cache: *Cache, | |
| 218 | 251 | available_deps: AvailableDeps, |
| 219 | 252 | ) !*Build { |
| 220 | const env_map = try allocator.create(EnvMap); | |
| 221 | env_map.* = try process.getEnvMap(allocator); | |
| 253 | const arena = graph.arena; | |
| 254 | const initialized_deps = try arena.create(InitializedDepMap); | |
| 255 | initialized_deps.* = InitializedDepMap.initContext(arena, .{ .allocator = arena }); | |
| 222 | 256 | |
| 223 | const initialized_deps = try allocator.create(InitializedDepMap); | |
| 224 | initialized_deps.* = InitializedDepMap.initContext(allocator, .{ .allocator = allocator }); | |
| 225 | ||
| 226 | const self = try allocator.create(Build); | |
| 257 | const self = try arena.create(Build); | |
| 227 | 258 | self.* = .{ |
| 228 | .zig_exe = zig_exe, | |
| 259 | .graph = graph, | |
| 229 | 260 | .build_root = build_root, |
| 230 | 261 | .cache_root = cache_root, |
| 231 | .global_cache_root = global_cache_root, | |
| 232 | .cache = cache, | |
| 233 | 262 | .verbose = false, |
| 234 | 263 | .verbose_link = false, |
| 235 | 264 | .verbose_cc = false, |
| ... | ... | @@ -239,20 +268,19 @@ pub fn create( |
| 239 | 268 | .verbose_cimport = false, |
| 240 | 269 | .verbose_llvm_cpu_features = false, |
| 241 | 270 | .invalid_user_input = false, |
| 242 | .allocator = allocator, | |
| 243 | .user_input_options = UserInputOptionsMap.init(allocator), | |
| 244 | .available_options_map = AvailableOptionsMap.init(allocator), | |
| 245 | .available_options_list = ArrayList(AvailableOption).init(allocator), | |
| 271 | .allocator = arena, | |
| 272 | .user_input_options = UserInputOptionsMap.init(arena), | |
| 273 | .available_options_map = AvailableOptionsMap.init(arena), | |
| 274 | .available_options_list = ArrayList(AvailableOption).init(arena), | |
| 246 | 275 | .top_level_steps = .{}, |
| 247 | 276 | .default_step = undefined, |
| 248 | .env_map = env_map, | |
| 249 | .search_prefixes = ArrayList([]const u8).init(allocator), | |
| 277 | .search_prefixes = .{}, | |
| 250 | 278 | .install_prefix = undefined, |
| 251 | 279 | .lib_dir = undefined, |
| 252 | 280 | .exe_dir = undefined, |
| 253 | 281 | .h_dir = undefined, |
| 254 | .dest_dir = env_map.get("DESTDIR"), | |
| 255 | .installed_files = ArrayList(InstalledFile).init(allocator), | |
| 282 | .dest_dir = graph.env_map.get("DESTDIR"), | |
| 283 | .installed_files = ArrayList(InstalledFile).init(arena), | |
| 256 | 284 | .install_tls = .{ |
| 257 | 285 | .step = Step.init(.{ |
| 258 | 286 | .id = .top_level, |
| ... | ... | @@ -273,14 +301,15 @@ pub fn create( |
| 273 | 301 | .zig_lib_dir = null, |
| 274 | 302 | .install_path = undefined, |
| 275 | 303 | .args = null, |
| 276 | .host = host, | |
| 277 | .modules = std.StringArrayHashMap(*Module).init(allocator), | |
| 278 | .named_writefiles = std.StringArrayHashMap(*Step.WriteFile).init(allocator), | |
| 304 | .host = undefined, | |
| 305 | .modules = std.StringArrayHashMap(*Module).init(arena), | |
| 306 | .named_writefiles = std.StringArrayHashMap(*Step.WriteFile).init(arena), | |
| 279 | 307 | .initialized_deps = initialized_deps, |
| 280 | 308 | .available_deps = available_deps, |
| 309 | .release_mode = .off, | |
| 281 | 310 | }; |
| 282 | try self.top_level_steps.put(allocator, self.install_tls.step.name, &self.install_tls); | |
| 283 | try self.top_level_steps.put(allocator, self.uninstall_tls.step.name, &self.uninstall_tls); | |
| 311 | try self.top_level_steps.put(arena, self.install_tls.step.name, &self.install_tls); | |
| 312 | try self.top_level_steps.put(arena, self.uninstall_tls.step.name, &self.uninstall_tls); | |
| 284 | 313 | self.default_step = &self.install_tls.step; |
| 285 | 314 | return self; |
| 286 | 315 | } |
| ... | ... | @@ -297,10 +326,17 @@ fn createChild( |
| 297 | 326 | return child; |
| 298 | 327 | } |
| 299 | 328 | |
| 300 | fn createChildOnly(parent: *Build, dep_name: []const u8, build_root: Cache.Directory, pkg_deps: AvailableDeps, user_input_options: UserInputOptionsMap) !*Build { | |
| 329 | fn createChildOnly( | |
| 330 | parent: *Build, | |
| 331 | dep_name: []const u8, | |
| 332 | build_root: Cache.Directory, | |
| 333 | pkg_deps: AvailableDeps, | |
| 334 | user_input_options: UserInputOptionsMap, | |
| 335 | ) !*Build { | |
| 301 | 336 | const allocator = parent.allocator; |
| 302 | 337 | const child = try allocator.create(Build); |
| 303 | 338 | child.* = .{ |
| 339 | .graph = parent.graph, | |
| 304 | 340 | .allocator = allocator, |
| 305 | 341 | .install_tls = .{ |
| 306 | 342 | .step = Step.init(.{ |
| ... | ... | @@ -332,9 +368,7 @@ fn createChildOnly(parent: *Build, dep_name: []const u8, build_root: Cache.Direc |
| 332 | 368 | .verbose_llvm_cpu_features = parent.verbose_llvm_cpu_features, |
| 333 | 369 | .reference_trace = parent.reference_trace, |
| 334 | 370 | .invalid_user_input = false, |
| 335 | .zig_exe = parent.zig_exe, | |
| 336 | 371 | .default_step = undefined, |
| 337 | .env_map = parent.env_map, | |
| 338 | 372 | .top_level_steps = .{}, |
| 339 | 373 | .install_prefix = undefined, |
| 340 | 374 | .dest_dir = parent.dest_dir, |
| ... | ... | @@ -348,8 +382,6 @@ fn createChildOnly(parent: *Build, dep_name: []const u8, build_root: Cache.Direc |
| 348 | 382 | .installed_files = ArrayList(InstalledFile).init(allocator), |
| 349 | 383 | .build_root = build_root, |
| 350 | 384 | .cache_root = parent.cache_root, |
| 351 | .global_cache_root = parent.global_cache_root, | |
| 352 | .cache = parent.cache, | |
| 353 | 385 | .zig_lib_dir = parent.zig_lib_dir, |
| 354 | 386 | .debug_log_scopes = parent.debug_log_scopes, |
| 355 | 387 | .debug_compile_errors = parent.debug_compile_errors, |
| ... | ... | @@ -366,6 +398,7 @@ fn createChildOnly(parent: *Build, dep_name: []const u8, build_root: Cache.Direc |
| 366 | 398 | .named_writefiles = std.StringArrayHashMap(*Step.WriteFile).init(allocator), |
| 367 | 399 | .initialized_deps = parent.initialized_deps, |
| 368 | 400 | .available_deps = pkg_deps, |
| 401 | .release_mode = parent.release_mode, | |
| 369 | 402 | }; |
| 370 | 403 | try child.top_level_steps.put(allocator, child.install_tls.step.name, &child.install_tls); |
| 371 | 404 | try child.top_level_steps.put(allocator, child.uninstall_tls.step.name, &child.uninstall_tls); |
| ... | ... | @@ -543,7 +576,7 @@ fn hashUserInputOptionsMap(allocator: Allocator, user_input_options: UserInputOp |
| 543 | 576 | fn determineAndApplyInstallPrefix(b: *Build) !void { |
| 544 | 577 | // Create an installation directory local to this package. This will be used when |
| 545 | 578 | // dependant packages require a standard prefix, such as include directories for C headers. |
| 546 | var hash = b.cache.hash; | |
| 579 | var hash = b.graph.cache.hash; | |
| 547 | 580 | // Random bytes to make unique. Refresh this with new random bytes when |
| 548 | 581 | // implementation is modified in a non-backwards-compatible way. |
| 549 | 582 | hash.add(@as(u32, 0xd8cb0055)); |
| ... | ... | @@ -558,12 +591,6 @@ fn determineAndApplyInstallPrefix(b: *Build) !void { |
| 558 | 591 | b.resolveInstallPrefix(install_prefix, .{}); |
| 559 | 592 | } |
| 560 | 593 | |
| 561 | pub fn destroy(b: *Build) void { | |
| 562 | b.env_map.deinit(); | |
| 563 | b.top_level_steps.deinit(b.allocator); | |
| 564 | b.allocator.destroy(b); | |
| 565 | } | |
| 566 | ||
| 567 | 594 | /// This function is intended to be called by lib/build_runner.zig, not a build.zig file. |
| 568 | 595 | pub fn resolveInstallPrefix(self: *Build, install_prefix: ?[]const u8, dir_list: DirList) void { |
| 569 | 596 | if (self.dest_dir) |dest_dir| { |
| ... | ... | @@ -1216,20 +1243,33 @@ pub const StandardOptimizeOptionOptions = struct { |
| 1216 | 1243 | preferred_optimize_mode: ?std.builtin.OptimizeMode = null, |
| 1217 | 1244 | }; |
| 1218 | 1245 | |
| 1219 | pub fn standardOptimizeOption(self: *Build, options: StandardOptimizeOptionOptions) std.builtin.OptimizeMode { | |
| 1246 | pub fn standardOptimizeOption(b: *Build, options: StandardOptimizeOptionOptions) std.builtin.OptimizeMode { | |
| 1220 | 1247 | if (options.preferred_optimize_mode) |mode| { |
| 1221 | if (self.option(bool, "release", "optimize for end users") orelse false) { | |
| 1248 | if (b.option(bool, "release", "optimize for end users") orelse (b.release_mode != .off)) { | |
| 1222 | 1249 | return mode; |
| 1223 | 1250 | } else { |
| 1224 | 1251 | return .Debug; |
| 1225 | 1252 | } |
| 1226 | } else { | |
| 1227 | return self.option( | |
| 1228 | std.builtin.OptimizeMode, | |
| 1229 | "optimize", | |
| 1230 | "Prioritize performance, safety, or binary size (-O flag)", | |
| 1231 | ) orelse .Debug; | |
| 1232 | 1253 | } |
| 1254 | ||
| 1255 | if (b.option( | |
| 1256 | std.builtin.OptimizeMode, | |
| 1257 | "optimize", | |
| 1258 | "Prioritize performance, safety, or binary size", | |
| 1259 | )) |mode| { | |
| 1260 | return mode; | |
| 1261 | } | |
| 1262 | ||
| 1263 | return switch (b.release_mode) { | |
| 1264 | .off => .Debug, | |
| 1265 | .any => { | |
| 1266 | std.debug.print("the project does not declare a preferred optimization mode. choose: --release=fast, --release=safe, or --release=small\n", .{}); | |
| 1267 | process.exit(1); | |
| 1268 | }, | |
| 1269 | .fast => .ReleaseFast, | |
| 1270 | .safe => .ReleaseSafe, | |
| 1271 | .small => .ReleaseSmall, | |
| 1272 | }; | |
| 1233 | 1273 | } |
| 1234 | 1274 | |
| 1235 | 1275 | pub const StandardTargetOptionsArgs = struct { |
| ... | ... | @@ -1244,67 +1284,83 @@ pub fn standardTargetOptions(b: *Build, args: StandardTargetOptionsArgs) Resolve |
| 1244 | 1284 | return b.resolveTargetQuery(query); |
| 1245 | 1285 | } |
| 1246 | 1286 | |
| 1247 | /// Exposes standard `zig build` options for choosing a target. | |
| 1248 | pub fn standardTargetOptionsQueryOnly(b: *Build, args: StandardTargetOptionsArgs) Target.Query { | |
| 1249 | const maybe_triple = b.option( | |
| 1250 | []const u8, | |
| 1251 | "target", | |
| 1252 | "The CPU architecture, OS, and ABI to build for", | |
| 1253 | ); | |
| 1254 | const mcpu = b.option([]const u8, "cpu", "Target CPU features to add or subtract"); | |
| 1255 | ||
| 1256 | if (maybe_triple == null and mcpu == null) { | |
| 1257 | return args.default_target; | |
| 1258 | } | |
| 1259 | ||
| 1260 | const triple = maybe_triple orelse "native"; | |
| 1261 | ||
| 1287 | pub fn parseTargetQuery(options: std.Target.Query.ParseOptions) error{ParseFailed}!std.Target.Query { | |
| 1262 | 1288 | var diags: Target.Query.ParseOptions.Diagnostics = .{}; |
| 1263 | const selected_target = Target.Query.parse(.{ | |
| 1264 | .arch_os_abi = triple, | |
| 1265 | .cpu_features = mcpu, | |
| 1266 | .diagnostics = &diags, | |
| 1267 | }) catch |err| switch (err) { | |
| 1289 | var opts_copy = options; | |
| 1290 | opts_copy.diagnostics = &diags; | |
| 1291 | return std.Target.Query.parse(options) catch |err| switch (err) { | |
| 1268 | 1292 | error.UnknownCpuModel => { |
| 1269 | log.err("Unknown CPU: '{s}'\nAvailable CPUs for architecture '{s}':", .{ | |
| 1270 | diags.cpu_name.?, | |
| 1271 | @tagName(diags.arch.?), | |
| 1293 | std.debug.print("unknown CPU: '{s}'\navailable CPUs for architecture '{s}':\n", .{ | |
| 1294 | diags.cpu_name.?, @tagName(diags.arch.?), | |
| 1272 | 1295 | }); |
| 1273 | 1296 | for (diags.arch.?.allCpuModels()) |cpu| { |
| 1274 | log.err(" {s}", .{cpu.name}); | |
| 1297 | std.debug.print(" {s}\n", .{cpu.name}); | |
| 1275 | 1298 | } |
| 1276 | b.markInvalidUserInput(); | |
| 1277 | return args.default_target; | |
| 1299 | return error.ParseFailed; | |
| 1278 | 1300 | }, |
| 1279 | 1301 | error.UnknownCpuFeature => { |
| 1280 | log.err( | |
| 1281 | \\Unknown CPU feature: '{s}' | |
| 1282 | \\Available CPU features for architecture '{s}': | |
| 1302 | std.debug.print( | |
| 1303 | \\unknown CPU feature: '{s}' | |
| 1304 | \\available CPU features for architecture '{s}': | |
| 1283 | 1305 | \\ |
| 1284 | 1306 | , .{ |
| 1285 | 1307 | diags.unknown_feature_name.?, |
| 1286 | 1308 | @tagName(diags.arch.?), |
| 1287 | 1309 | }); |
| 1288 | 1310 | for (diags.arch.?.allFeaturesList()) |feature| { |
| 1289 | log.err(" {s}: {s}", .{ feature.name, feature.description }); | |
| 1311 | std.debug.print(" {s}: {s}\n", .{ feature.name, feature.description }); | |
| 1290 | 1312 | } |
| 1291 | b.markInvalidUserInput(); | |
| 1292 | return args.default_target; | |
| 1313 | return error.ParseFailed; | |
| 1293 | 1314 | }, |
| 1294 | 1315 | error.UnknownOperatingSystem => { |
| 1295 | log.err( | |
| 1296 | \\Unknown OS: '{s}' | |
| 1297 | \\Available operating systems: | |
| 1316 | std.debug.print( | |
| 1317 | \\unknown OS: '{s}' | |
| 1318 | \\available operating systems: | |
| 1298 | 1319 | \\ |
| 1299 | 1320 | , .{diags.os_name.?}); |
| 1300 | 1321 | inline for (std.meta.fields(Target.Os.Tag)) |field| { |
| 1301 | log.err(" {s}", .{field.name}); | |
| 1322 | std.debug.print(" {s}\n", .{field.name}); | |
| 1302 | 1323 | } |
| 1303 | b.markInvalidUserInput(); | |
| 1304 | return args.default_target; | |
| 1324 | return error.ParseFailed; | |
| 1305 | 1325 | }, |
| 1306 | 1326 | else => |e| { |
| 1307 | log.err("Unable to parse target '{s}': {s}\n", .{ triple, @errorName(e) }); | |
| 1327 | std.debug.print("unable to parse target '{s}': {s}\n", .{ | |
| 1328 | options.arch_os_abi, @errorName(e), | |
| 1329 | }); | |
| 1330 | return error.ParseFailed; | |
| 1331 | }, | |
| 1332 | }; | |
| 1333 | } | |
| 1334 | ||
| 1335 | /// Exposes standard `zig build` options for choosing a target. | |
| 1336 | pub fn standardTargetOptionsQueryOnly(b: *Build, args: StandardTargetOptionsArgs) Target.Query { | |
| 1337 | const maybe_triple = b.option( | |
| 1338 | []const u8, | |
| 1339 | "target", | |
| 1340 | "The CPU architecture, OS, and ABI to build for", | |
| 1341 | ); | |
| 1342 | const mcpu = b.option( | |
| 1343 | []const u8, | |
| 1344 | "cpu", | |
| 1345 | "Target CPU features to add or subtract", | |
| 1346 | ); | |
| 1347 | const dynamic_linker = b.option( | |
| 1348 | []const u8, | |
| 1349 | "dynamic-linker", | |
| 1350 | "Path to interpreter on the target system", | |
| 1351 | ); | |
| 1352 | ||
| 1353 | if (maybe_triple == null and mcpu == null and dynamic_linker == null) | |
| 1354 | return args.default_target; | |
| 1355 | ||
| 1356 | const triple = maybe_triple orelse "native"; | |
| 1357 | ||
| 1358 | const selected_target = parseTargetQuery(.{ | |
| 1359 | .arch_os_abi = triple, | |
| 1360 | .cpu_features = mcpu, | |
| 1361 | .dynamic_linker = dynamic_linker, | |
| 1362 | }) catch |err| switch (err) { | |
| 1363 | error.ParseFailed => { | |
| 1308 | 1364 | b.markInvalidUserInput(); |
| 1309 | 1365 | return args.default_target; |
| 1310 | 1366 | }, |
| ... | ... | @@ -1367,7 +1423,7 @@ pub fn addUserInputOption(self: *Build, name_raw: []const u8, value_raw: []const |
| 1367 | 1423 | }); |
| 1368 | 1424 | }, |
| 1369 | 1425 | .flag => { |
| 1370 | log.warn("Option '-D{s}={s}' conflicts with flag '-D{s}'.", .{ name, value, name }); | |
| 1426 | log.warn("option '-D{s}={s}' conflicts with flag '-D{s}'.", .{ name, value, name }); | |
| 1371 | 1427 | return true; |
| 1372 | 1428 | }, |
| 1373 | 1429 | .map => |*map| { |
| ... | ... | @@ -1427,17 +1483,17 @@ fn markInvalidUserInput(self: *Build) void { |
| 1427 | 1483 | self.invalid_user_input = true; |
| 1428 | 1484 | } |
| 1429 | 1485 | |
| 1430 | pub fn validateUserInputDidItFail(self: *Build) bool { | |
| 1431 | // make sure all args are used | |
| 1432 | var it = self.user_input_options.iterator(); | |
| 1486 | pub fn validateUserInputDidItFail(b: *Build) bool { | |
| 1487 | // Make sure all args are used. | |
| 1488 | var it = b.user_input_options.iterator(); | |
| 1433 | 1489 | while (it.next()) |entry| { |
| 1434 | 1490 | if (!entry.value_ptr.used) { |
| 1435 | log.err("Invalid option: -D{s}", .{entry.key_ptr.*}); | |
| 1436 | self.markInvalidUserInput(); | |
| 1491 | log.err("invalid option: -D{s}", .{entry.key_ptr.*}); | |
| 1492 | b.markInvalidUserInput(); | |
| 1437 | 1493 | } |
| 1438 | 1494 | } |
| 1439 | 1495 | |
| 1440 | return self.invalid_user_input; | |
| 1496 | return b.invalid_user_input; | |
| 1441 | 1497 | } |
| 1442 | 1498 | |
| 1443 | 1499 | fn allocPrintCmd(ally: Allocator, opt_cwd: ?[]const u8, argv: []const []const u8) ![]u8 { |
| ... | ... | @@ -1593,7 +1649,7 @@ pub fn findProgram(self: *Build, names: []const []const u8, paths: []const []con |
| 1593 | 1649 | return fs.realpathAlloc(self.allocator, full_path) catch continue; |
| 1594 | 1650 | } |
| 1595 | 1651 | } |
| 1596 | if (self.env_map.get("PATH")) |PATH| { | |
| 1652 | if (self.graph.env_map.get("PATH")) |PATH| { | |
| 1597 | 1653 | for (names) |name| { |
| 1598 | 1654 | if (fs.path.isAbsolute(name)) { |
| 1599 | 1655 | return name; |
| ... | ... | @@ -1639,7 +1695,7 @@ pub fn runAllowFail( |
| 1639 | 1695 | child.stdin_behavior = .Ignore; |
| 1640 | 1696 | child.stdout_behavior = .Pipe; |
| 1641 | 1697 | child.stderr_behavior = stderr_behavior; |
| 1642 | child.env_map = self.env_map; | |
| 1698 | child.env_map = &self.graph.env_map; | |
| 1643 | 1699 | |
| 1644 | 1700 | try child.spawn(); |
| 1645 | 1701 | |
| ... | ... | @@ -1685,8 +1741,8 @@ pub fn run(b: *Build, argv: []const []const u8) []u8 { |
| 1685 | 1741 | }; |
| 1686 | 1742 | } |
| 1687 | 1743 | |
| 1688 | pub fn addSearchPrefix(self: *Build, search_prefix: []const u8) void { | |
| 1689 | self.search_prefixes.append(self.dupePath(search_prefix)) catch @panic("OOM"); | |
| 1744 | pub fn addSearchPrefix(b: *Build, search_prefix: []const u8) void { | |
| 1745 | b.search_prefixes.append(b.allocator, b.dupePath(search_prefix)) catch @panic("OOM"); | |
| 1690 | 1746 | } |
| 1691 | 1747 | |
| 1692 | 1748 | pub fn getInstallPath(self: *Build, dir: InstallDir, dest_rel_path: []const u8) []const u8 { |
| ... | ... | @@ -1747,21 +1803,63 @@ pub const Dependency = struct { |
| 1747 | 1803 | } |
| 1748 | 1804 | }; |
| 1749 | 1805 | |
| 1750 | pub fn dependency(b: *Build, name: []const u8, args: anytype) *Dependency { | |
| 1806 | fn findPkgHashOrFatal(b: *Build, name: []const u8) []const u8 { | |
| 1807 | for (b.available_deps) |dep| { | |
| 1808 | if (mem.eql(u8, dep[0], name)) return dep[1]; | |
| 1809 | } | |
| 1810 | ||
| 1811 | const full_path = b.pathFromRoot("build.zig.zon"); | |
| 1812 | std.debug.panic("no dependency named '{s}' in '{s}'. All packages used in build.zig must be declared in this file", .{ name, full_path }); | |
| 1813 | } | |
| 1814 | ||
| 1815 | fn markNeededLazyDep(b: *Build, pkg_hash: []const u8) void { | |
| 1816 | b.graph.needed_lazy_dependencies.put(b.graph.arena, pkg_hash, {}) catch @panic("OOM"); | |
| 1817 | } | |
| 1818 | ||
| 1819 | /// When this function is called, it means that the current build does, in | |
| 1820 | /// fact, require this dependency. If the dependency is already fetched, it | |
| 1821 | /// proceeds in the same manner as `dependency`. However if the dependency was | |
| 1822 | /// not fetched, then when the build script is finished running, the build will | |
| 1823 | /// not proceed to the make phase. Instead, the parent process will | |
| 1824 | /// additionally fetch all the lazy dependencies that were actually required by | |
| 1825 | /// running the build script, rebuild the build script, and then run it again. | |
| 1826 | /// In other words, if this function returns `null` it means that the only | |
| 1827 | /// purpose of completing the configure phase is to find out all the other lazy | |
| 1828 | /// dependencies that are also required. | |
| 1829 | /// It is allowed to use this function for non-lazy dependencies, in which case | |
| 1830 | /// it will never return `null`. This allows toggling laziness via | |
| 1831 | /// build.zig.zon without changing build.zig logic. | |
| 1832 | pub fn lazyDependency(b: *Build, name: []const u8, args: anytype) ?*Dependency { | |
| 1751 | 1833 | const build_runner = @import("root"); |
| 1752 | 1834 | const deps = build_runner.dependencies; |
| 1835 | const pkg_hash = findPkgHashOrFatal(b, name); | |
| 1753 | 1836 | |
| 1754 | const pkg_hash = for (b.available_deps) |dep| { | |
| 1755 | if (mem.eql(u8, dep[0], name)) break dep[1]; | |
| 1756 | } else { | |
| 1757 | const full_path = b.pathFromRoot("build.zig.zon"); | |
| 1758 | std.debug.print("no dependency named '{s}' in '{s}'. All packages used in build.zig must be declared in this file.\n", .{ name, full_path }); | |
| 1759 | process.exit(1); | |
| 1760 | }; | |
| 1837 | inline for (@typeInfo(deps.packages).Struct.decls) |decl| { | |
| 1838 | if (mem.eql(u8, decl.name, pkg_hash)) { | |
| 1839 | const pkg = @field(deps.packages, decl.name); | |
| 1840 | const available = !@hasDecl(pkg, "available") or pkg.available; | |
| 1841 | if (!available) { | |
| 1842 | markNeededLazyDep(b, pkg_hash); | |
| 1843 | return null; | |
| 1844 | } | |
| 1845 | return dependencyInner(b, name, pkg.build_root, if (@hasDecl(pkg, "build_zig")) pkg.build_zig else null, pkg.deps, args); | |
| 1846 | } | |
| 1847 | } | |
| 1848 | ||
| 1849 | unreachable; // Bad @dependencies source | |
| 1850 | } | |
| 1851 | ||
| 1852 | pub fn dependency(b: *Build, name: []const u8, args: anytype) *Dependency { | |
| 1853 | const build_runner = @import("root"); | |
| 1854 | const deps = build_runner.dependencies; | |
| 1855 | const pkg_hash = findPkgHashOrFatal(b, name); | |
| 1761 | 1856 | |
| 1762 | 1857 | inline for (@typeInfo(deps.packages).Struct.decls) |decl| { |
| 1763 | 1858 | if (mem.eql(u8, decl.name, pkg_hash)) { |
| 1764 | 1859 | const pkg = @field(deps.packages, decl.name); |
| 1860 | if (@hasDecl(pkg, "available")) { | |
| 1861 | std.debug.panic("dependency '{s}{s}' is marked as lazy in build.zig.zon which means it must use the lazyDependency function instead", .{ b.dep_prefix, name }); | |
| 1862 | } | |
| 1765 | 1863 | return dependencyInner(b, name, pkg.build_root, if (@hasDecl(pkg, "build_zig")) pkg.build_zig else null, pkg.deps, args); |
| 1766 | 1864 | } |
| 1767 | 1865 | } |
| ... | ... | @@ -2281,9 +2379,14 @@ pub const ResolvedTarget = struct { |
| 2281 | 2379 | /// Converts a target query into a fully resolved target that can be passed to |
| 2282 | 2380 | /// various parts of the API. |
| 2283 | 2381 | pub fn resolveTargetQuery(b: *Build, query: Target.Query) ResolvedTarget { |
| 2284 | // This context will likely be required in the future when the target is | |
| 2285 | // resolved via a WASI API or via the build protocol. | |
| 2286 | _ = b; | |
| 2382 | if (query.isNative()) { | |
| 2383 | var adjusted = b.host; | |
| 2384 | if (query.ofmt) |ofmt| { | |
| 2385 | adjusted.query.ofmt = ofmt; | |
| 2386 | adjusted.result.ofmt = ofmt; | |
| 2387 | } | |
| 2388 | return adjusted; | |
| 2389 | } | |
| 2287 | 2390 | |
| 2288 | 2391 | return .{ |
| 2289 | 2392 | .query = query, |
| ... | ... | @@ -2296,6 +2399,40 @@ pub fn wantSharedLibSymLinks(target: Target) bool { |
| 2296 | 2399 | return target.os.tag != .windows; |
| 2297 | 2400 | } |
| 2298 | 2401 | |
| 2402 | pub const SystemIntegrationOptionConfig = struct { | |
| 2403 | /// If left as null, then the default will depend on system_package_mode. | |
| 2404 | default: ?bool = null, | |
| 2405 | }; | |
| 2406 | ||
| 2407 | pub fn systemIntegrationOption( | |
| 2408 | b: *Build, | |
| 2409 | name: []const u8, | |
| 2410 | config: SystemIntegrationOptionConfig, | |
| 2411 | ) bool { | |
| 2412 | const gop = b.graph.system_library_options.getOrPut(b.allocator, name) catch @panic("OOM"); | |
| 2413 | if (gop.found_existing) switch (gop.value_ptr.*) { | |
| 2414 | .user_disabled => { | |
| 2415 | gop.value_ptr.* = .declared_disabled; | |
| 2416 | return false; | |
| 2417 | }, | |
| 2418 | .user_enabled => { | |
| 2419 | gop.value_ptr.* = .declared_enabled; | |
| 2420 | return true; | |
| 2421 | }, | |
| 2422 | .declared_disabled => return false, | |
| 2423 | .declared_enabled => return true, | |
| 2424 | } else { | |
| 2425 | gop.key_ptr.* = b.dupe(name); | |
| 2426 | if (config.default orelse b.graph.system_package_mode) { | |
| 2427 | gop.value_ptr.* = .declared_enabled; | |
| 2428 | return true; | |
| 2429 | } else { | |
| 2430 | gop.value_ptr.* = .declared_disabled; | |
| 2431 | return false; | |
| 2432 | } | |
| 2433 | } | |
| 2434 | } | |
| 2435 | ||
| 2299 | 2436 | test { |
| 2300 | 2437 | _ = Cache; |
| 2301 | 2438 | _ = Step; |
lib/std/Build/Step.zig+1-1| ... | ... | @@ -314,7 +314,7 @@ pub fn evalZigProcess( |
| 314 | 314 | try handleVerbose(s.owner, null, argv); |
| 315 | 315 | |
| 316 | 316 | var child = std.ChildProcess.init(argv, arena); |
| 317 | child.env_map = b.env_map; | |
| 317 | child.env_map = &b.graph.env_map; | |
| 318 | 318 | child.stdin_behavior = .Pipe; |
| 319 | 319 | child.stdout_behavior = .Pipe; |
| 320 | 320 | child.stderr_behavior = .Pipe; |
lib/std/Build/Step/Compile.zig+12-2| ... | ... | @@ -923,7 +923,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { |
| 923 | 923 | var zig_args = ArrayList([]const u8).init(arena); |
| 924 | 924 | defer zig_args.deinit(); |
| 925 | 925 | |
| 926 | try zig_args.append(b.zig_exe); | |
| 926 | try zig_args.append(b.graph.zig_exe); | |
| 927 | 927 | |
| 928 | 928 | const cmd = switch (self.kind) { |
| 929 | 929 | .lib => "build-lib", |
| ... | ... | @@ -933,6 +933,16 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { |
| 933 | 933 | }; |
| 934 | 934 | try zig_args.append(cmd); |
| 935 | 935 | |
| 936 | if (!mem.eql(u8, b.graph.host_query_options.arch_os_abi, "native")) { | |
| 937 | try zig_args.appendSlice(&.{ "--host-target", b.graph.host_query_options.arch_os_abi }); | |
| 938 | } | |
| 939 | if (b.graph.host_query_options.cpu_features) |cpu| { | |
| 940 | try zig_args.appendSlice(&.{ "--host-cpu", cpu }); | |
| 941 | } | |
| 942 | if (b.graph.host_query_options.dynamic_linker) |dl| { | |
| 943 | try zig_args.appendSlice(&.{ "--host-dynamic-linker", dl }); | |
| 944 | } | |
| 945 | ||
| 936 | 946 | if (b.reference_trace) |some| { |
| 937 | 947 | try zig_args.append(try std.fmt.allocPrint(arena, "-freference-trace={d}", .{some})); |
| 938 | 948 | } |
| ... | ... | @@ -1393,7 +1403,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { |
| 1393 | 1403 | try zig_args.append(b.cache_root.path orelse "."); |
| 1394 | 1404 | |
| 1395 | 1405 | try zig_args.append("--global-cache-dir"); |
| 1396 | try zig_args.append(b.global_cache_root.path orelse "."); | |
| 1406 | try zig_args.append(b.graph.global_cache_root.path orelse "."); | |
| 1397 | 1407 | |
| 1398 | 1408 | try zig_args.append("--name"); |
| 1399 | 1409 | try zig_args.append(self.name); |
lib/std/Build/Step/ConfigHeader.zig+1-1| ... | ... | @@ -171,7 +171,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { |
| 171 | 171 | const gpa = b.allocator; |
| 172 | 172 | const arena = b.allocator; |
| 173 | 173 | |
| 174 | var man = b.cache.obtain(); | |
| 174 | var man = b.graph.cache.obtain(); | |
| 175 | 175 | defer man.deinit(); |
| 176 | 176 | |
| 177 | 177 | // Random bytes to make ConfigHeader unique. Refresh this with new |
lib/std/Build/Step/Fmt.zig+1-1| ... | ... | @@ -52,7 +52,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { |
| 52 | 52 | var argv: std.ArrayListUnmanaged([]const u8) = .{}; |
| 53 | 53 | try argv.ensureUnusedCapacity(arena, 2 + 1 + self.paths.len + 2 * self.exclude_paths.len); |
| 54 | 54 | |
| 55 | argv.appendAssumeCapacity(b.zig_exe); | |
| 55 | argv.appendAssumeCapacity(b.graph.zig_exe); | |
| 56 | 56 | argv.appendAssumeCapacity("fmt"); |
| 57 | 57 | |
| 58 | 58 | if (self.check) { |
lib/std/Build/Step/ObjCopy.zig+2-2| ... | ... | @@ -94,7 +94,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { |
| 94 | 94 | const b = step.owner; |
| 95 | 95 | const self = @fieldParentPtr(ObjCopy, "step", step); |
| 96 | 96 | |
| 97 | var man = b.cache.obtain(); | |
| 97 | var man = b.graph.cache.obtain(); | |
| 98 | 98 | defer man.deinit(); |
| 99 | 99 | |
| 100 | 100 | // Random bytes to make ObjCopy unique. Refresh this with new random |
| ... | ... | @@ -133,7 +133,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { |
| 133 | 133 | }; |
| 134 | 134 | |
| 135 | 135 | var argv = std.ArrayList([]const u8).init(b.allocator); |
| 136 | try argv.appendSlice(&.{ b.zig_exe, "objcopy" }); | |
| 136 | try argv.appendSlice(&.{ b.graph.zig_exe, "objcopy" }); | |
| 137 | 137 | |
| 138 | 138 | if (self.only_section) |only_section| { |
| 139 | 139 | try argv.appendSlice(&.{ "-j", only_section }); |
lib/std/Build/Step/Options.zig+16-15| ... | ... | @@ -222,7 +222,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { |
| 222 | 222 | const basename = "options.zig"; |
| 223 | 223 | |
| 224 | 224 | // Hash contents to file name. |
| 225 | var hash = b.cache.hash; | |
| 225 | var hash = b.graph.cache.hash; | |
| 226 | 226 | // Random bytes to make unique. Refresh this with new random bytes when |
| 227 | 227 | // implementation is modified in a non-backwards-compatible way. |
| 228 | 228 | hash.add(@as(u32, 0xad95e922)); |
| ... | ... | @@ -301,27 +301,28 @@ test Options { |
| 301 | 301 | var arena = std.heap.ArenaAllocator.init(std.testing.allocator); |
| 302 | 302 | defer arena.deinit(); |
| 303 | 303 | |
| 304 | const host: std.Build.ResolvedTarget = .{ | |
| 305 | .query = .{}, | |
| 306 | .result = try std.zig.system.resolveTargetQuery(.{}), | |
| 307 | }; | |
| 308 | ||
| 309 | var cache: std.Build.Cache = .{ | |
| 310 | .gpa = arena.allocator(), | |
| 311 | .manifest_dir = std.fs.cwd(), | |
| 304 | var graph: std.Build.Graph = .{ | |
| 305 | .arena = arena.allocator(), | |
| 306 | .cache = .{ | |
| 307 | .gpa = arena.allocator(), | |
| 308 | .manifest_dir = std.fs.cwd(), | |
| 309 | }, | |
| 310 | .zig_exe = "test", | |
| 311 | .env_map = std.process.EnvMap.init(arena.allocator()), | |
| 312 | .global_cache_root = .{ .path = "test", .handle = std.fs.cwd() }, | |
| 312 | 313 | }; |
| 313 | 314 | |
| 314 | 315 | var builder = try std.Build.create( |
| 315 | arena.allocator(), | |
| 316 | "test", | |
| 316 | &graph, | |
| 317 | 317 | .{ .path = "test", .handle = std.fs.cwd() }, |
| 318 | 318 | .{ .path = "test", .handle = std.fs.cwd() }, |
| 319 | .{ .path = "test", .handle = std.fs.cwd() }, | |
| 320 | host, | |
| 321 | &cache, | |
| 322 | 319 | &.{}, |
| 323 | 320 | ); |
| 324 | defer builder.destroy(); | |
| 321 | ||
| 322 | builder.host = .{ | |
| 323 | .query = .{}, | |
| 324 | .result = try std.zig.system.resolveTargetQuery(.{}), | |
| 325 | }; | |
| 325 | 326 | |
| 326 | 327 | const options = builder.addOptions(); |
| 327 | 328 |
lib/std/Build/Step/Run.zig+2-2| ... | ... | @@ -463,7 +463,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { |
| 463 | 463 | var argv_list = ArrayList([]const u8).init(arena); |
| 464 | 464 | var output_placeholders = ArrayList(IndexedOutput).init(arena); |
| 465 | 465 | |
| 466 | var man = b.cache.obtain(); | |
| 466 | var man = b.graph.cache.obtain(); | |
| 467 | 467 | defer man.deinit(); |
| 468 | 468 | |
| 469 | 469 | for (self.argv.items) |arg| { |
| ... | ... | @@ -1036,7 +1036,7 @@ fn spawnChildAndCollect( |
| 1036 | 1036 | child.cwd = b.build_root.path; |
| 1037 | 1037 | child.cwd_dir = b.build_root.handle; |
| 1038 | 1038 | } |
| 1039 | child.env_map = self.env_map orelse b.env_map; | |
| 1039 | child.env_map = self.env_map orelse &b.graph.env_map; | |
| 1040 | 1040 | child.request_resource_usage_statistics = true; |
| 1041 | 1041 | |
| 1042 | 1042 | child.stdin_behavior = switch (self.stdio) { |
lib/std/Build/Step/TranslateC.zig+1-1| ... | ... | @@ -121,7 +121,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { |
| 121 | 121 | const self = @fieldParentPtr(TranslateC, "step", step); |
| 122 | 122 | |
| 123 | 123 | var argv_list = std.ArrayList([]const u8).init(b.allocator); |
| 124 | try argv_list.append(b.zig_exe); | |
| 124 | try argv_list.append(b.graph.zig_exe); | |
| 125 | 125 | try argv_list.append("translate-c"); |
| 126 | 126 | if (self.link_libc) { |
| 127 | 127 | try argv_list.append("-lc"); |
lib/std/Build/Step/WriteFile.zig+1-1| ... | ... | @@ -190,7 +190,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { |
| 190 | 190 | // If, for example, a hard-coded path was used as the location to put WriteFile |
| 191 | 191 | // files, then two WriteFiles executing in parallel might clobber each other. |
| 192 | 192 | |
| 193 | var man = b.cache.obtain(); | |
| 193 | var man = b.graph.cache.obtain(); | |
| 194 | 194 | defer man.deinit(); |
| 195 | 195 | |
| 196 | 196 | // Random bytes to make WriteFile unique. Refresh this with |
lib/std/Target/Query.zig+1-1| ... | ... | @@ -468,7 +468,7 @@ pub fn zigTriple(self: Query, allocator: Allocator) Allocator.Error![]u8 { |
| 468 | 468 | } |
| 469 | 469 | |
| 470 | 470 | if (self.glibc_version) |v| { |
| 471 | const name = @tagName(self.abi orelse builtin.target.abi); | |
| 471 | const name = if (self.abi) |abi| @tagName(abi) else "gnu"; | |
| 472 | 472 | try result.ensureUnusedCapacity(name.len + 2); |
| 473 | 473 | result.appendAssumeCapacity('-'); |
| 474 | 474 | result.appendSliceAssumeCapacity(name); |
lib/std/child_process.zig+3-1| ... | ... | @@ -298,7 +298,9 @@ pub const ChildProcess = struct { |
| 298 | 298 | // we could make this work with multiple allocators but YAGNI |
| 299 | 299 | if (stdout.allocator.ptr != stderr.allocator.ptr or |
| 300 | 300 | stdout.allocator.vtable != stderr.allocator.vtable) |
| 301 | @panic("ChildProcess.collectOutput only supports 1 allocator"); | |
| 301 | { | |
| 302 | unreachable; // ChildProcess.collectOutput only supports 1 allocator | |
| 303 | } | |
| 302 | 304 | |
| 303 | 305 | var poller = std.io.poll(stdout.allocator, enum { stdout, stderr }, .{ |
| 304 | 306 | .stdout = child.stdout.?, |
src/Compilation.zig+3| ... | ... | @@ -4530,6 +4530,9 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: *std.P |
| 4530 | 4530 | log.err("{}: failed to parse clang diagnostics: {s}", .{ err, stderr }); |
| 4531 | 4531 | return comp.failCObj(c_object, "clang exited with code {d}", .{code}); |
| 4532 | 4532 | }; |
| 4533 | zig_cache_tmp_dir.deleteFile(out_diag_path) catch |err| { | |
| 4534 | log.warn("failed to delete '{s}': {s}", .{ out_diag_path, @errorName(err) }); | |
| 4535 | }; | |
| 4533 | 4536 | return comp.failCObjWithOwnedDiagBundle(c_object, bundle); |
| 4534 | 4537 | } |
| 4535 | 4538 | }, |
src/Package/Fetch.zig+81-4| ... | ... | @@ -31,6 +31,8 @@ arena: std.heap.ArenaAllocator, |
| 31 | 31 | location: Location, |
| 32 | 32 | location_tok: std.zig.Ast.TokenIndex, |
| 33 | 33 | hash_tok: std.zig.Ast.TokenIndex, |
| 34 | name_tok: std.zig.Ast.TokenIndex, | |
| 35 | lazy_status: LazyStatus, | |
| 34 | 36 | parent_package_root: Package.Path, |
| 35 | 37 | parent_manifest_ast: ?*const std.zig.Ast, |
| 36 | 38 | prog_node: *std.Progress.Node, |
| ... | ... | @@ -64,6 +66,15 @@ oom_flag: bool, |
| 64 | 66 | /// the root source file. |
| 65 | 67 | module: ?*Package.Module, |
| 66 | 68 | |
| 69 | pub const LazyStatus = enum { | |
| 70 | /// Not lazy. | |
| 71 | eager, | |
| 72 | /// Lazy, found. | |
| 73 | available, | |
| 74 | /// Lazy, not found. | |
| 75 | unavailable, | |
| 76 | }; | |
| 77 | ||
| 67 | 78 | /// Contains shared state among all `Fetch` tasks. |
| 68 | 79 | pub const JobQueue = struct { |
| 69 | 80 | mutex: std.Thread.Mutex = .{}, |
| ... | ... | @@ -80,14 +91,27 @@ pub const JobQueue = struct { |
| 80 | 91 | thread_pool: *ThreadPool, |
| 81 | 92 | wait_group: WaitGroup = .{}, |
| 82 | 93 | global_cache: Cache.Directory, |
| 94 | /// If true then, no fetching occurs, and: | |
| 95 | /// * The `global_cache` directory is assumed to be the direct parent | |
| 96 | /// directory of on-disk packages rather than having the "p/" directory | |
| 97 | /// prefix inside of it. | |
| 98 | /// * An error occurs if any non-lazy packages are not already present in | |
| 99 | /// the package cache directory. | |
| 100 | /// * Missing hash field causes an error, and no fetching occurs so it does | |
| 101 | /// not print the correct hash like usual. | |
| 102 | read_only: bool, | |
| 83 | 103 | recursive: bool, |
| 84 | 104 | /// Dumps hash information to stdout which can be used to troubleshoot why |
| 85 | 105 | /// two hashes of the same package do not match. |
| 86 | 106 | /// If this is true, `recursive` must be false. |
| 87 | 107 | debug_hash: bool, |
| 88 | 108 | work_around_btrfs_bug: bool, |
| 109 | /// Set of hashes that will be additionally fetched even if they are marked | |
| 110 | /// as lazy. | |
| 111 | unlazy_set: UnlazySet = .{}, | |
| 89 | 112 | |
| 90 | 113 | pub const Table = std.AutoArrayHashMapUnmanaged(Manifest.MultiHashHexDigest, *Fetch); |
| 114 | pub const UnlazySet = std.AutoArrayHashMapUnmanaged(Manifest.MultiHashHexDigest, void); | |
| 91 | 115 | |
| 92 | 116 | pub fn deinit(jq: *JobQueue) void { |
| 93 | 117 | if (jq.all_fetches.items.len == 0) return; |
| ... | ... | @@ -141,11 +165,37 @@ pub const JobQueue = struct { |
| 141 | 165 | // The first one is a dummy package for the current project. |
| 142 | 166 | continue; |
| 143 | 167 | } |
| 168 | ||
| 144 | 169 | try buf.writer().print( |
| 145 | 170 | \\ pub const {} = struct {{ |
| 171 | \\ | |
| 172 | , .{std.zig.fmtId(&hash)}); | |
| 173 | ||
| 174 | lazy: { | |
| 175 | switch (fetch.lazy_status) { | |
| 176 | .eager => break :lazy, | |
| 177 | .available => { | |
| 178 | try buf.appendSlice( | |
| 179 | \\ pub const available = true; | |
| 180 | \\ | |
| 181 | ); | |
| 182 | break :lazy; | |
| 183 | }, | |
| 184 | .unavailable => { | |
| 185 | try buf.appendSlice( | |
| 186 | \\ pub const available = false; | |
| 187 | \\ }; | |
| 188 | \\ | |
| 189 | ); | |
| 190 | continue; | |
| 191 | }, | |
| 192 | } | |
| 193 | } | |
| 194 | ||
| 195 | try buf.writer().print( | |
| 146 | 196 | \\ pub const build_root = "{q}"; |
| 147 | 197 | \\ |
| 148 | , .{ std.zig.fmtId(&hash), fetch.package_root }); | |
| 198 | , .{fetch.package_root}); | |
| 149 | 199 | |
| 150 | 200 | if (fetch.has_build_zig) { |
| 151 | 201 | try buf.writer().print( |
| ... | ... | @@ -270,7 +320,8 @@ pub fn run(f: *Fetch) RunError!void { |
| 270 | 320 | // We want to fail unless the resolved relative path has a |
| 271 | 321 | // prefix of "p/$hash/". |
| 272 | 322 | const digest_len = @typeInfo(Manifest.MultiHashHexDigest).Array.len; |
| 273 | const expected_prefix = f.parent_package_root.sub_path[0 .. "p/".len + digest_len]; | |
| 323 | const prefix_len: usize = if (f.job_queue.read_only) 0 else "p/".len; | |
| 324 | const expected_prefix = f.parent_package_root.sub_path[0 .. prefix_len + digest_len]; | |
| 274 | 325 | if (!std.mem.startsWith(u8, pkg_root.sub_path, expected_prefix)) { |
| 275 | 326 | return f.fail( |
| 276 | 327 | f.location_tok, |
| ... | ... | @@ -311,8 +362,11 @@ pub fn run(f: *Fetch) RunError!void { |
| 311 | 362 | |
| 312 | 363 | const s = fs.path.sep_str; |
| 313 | 364 | if (remote.hash) |expected_hash| { |
| 314 | const pkg_sub_path = "p" ++ s ++ expected_hash; | |
| 365 | const prefixed_pkg_sub_path = "p" ++ s ++ expected_hash; | |
| 366 | const prefix_len: usize = if (f.job_queue.read_only) "p/".len else 0; | |
| 367 | const pkg_sub_path = prefixed_pkg_sub_path[prefix_len..]; | |
| 315 | 368 | if (cache_root.handle.access(pkg_sub_path, .{})) |_| { |
| 369 | assert(f.lazy_status != .unavailable); | |
| 316 | 370 | f.package_root = .{ |
| 317 | 371 | .root_dir = cache_root, |
| 318 | 372 | .sub_path = try arena.dupe(u8, pkg_sub_path), |
| ... | ... | @@ -322,7 +376,22 @@ pub fn run(f: *Fetch) RunError!void { |
| 322 | 376 | if (!f.job_queue.recursive) return; |
| 323 | 377 | return queueJobsForDeps(f); |
| 324 | 378 | } else |err| switch (err) { |
| 325 | error.FileNotFound => {}, | |
| 379 | error.FileNotFound => { | |
| 380 | switch (f.lazy_status) { | |
| 381 | .eager => {}, | |
| 382 | .available => if (!f.job_queue.unlazy_set.contains(expected_hash)) { | |
| 383 | f.lazy_status = .unavailable; | |
| 384 | return; | |
| 385 | }, | |
| 386 | .unavailable => unreachable, | |
| 387 | } | |
| 388 | if (f.job_queue.read_only) return f.fail( | |
| 389 | f.name_tok, | |
| 390 | try eb.printString("package not found at '{}{s}'", .{ | |
| 391 | cache_root, pkg_sub_path, | |
| 392 | }), | |
| 393 | ); | |
| 394 | }, | |
| 326 | 395 | else => |e| { |
| 327 | 396 | try eb.addRootErrorMessage(.{ |
| 328 | 397 | .msg = try eb.printString("unable to open global package cache directory '{}{s}': {s}", .{ |
| ... | ... | @@ -332,6 +401,12 @@ pub fn run(f: *Fetch) RunError!void { |
| 332 | 401 | return error.FetchFailed; |
| 333 | 402 | }, |
| 334 | 403 | } |
| 404 | } else { | |
| 405 | try eb.addRootErrorMessage(.{ | |
| 406 | .msg = try eb.addString("dependency is missing hash field"), | |
| 407 | .src_loc = try f.srcLoc(f.location_tok), | |
| 408 | }); | |
| 409 | return error.FetchFailed; | |
| 335 | 410 | } |
| 336 | 411 | |
| 337 | 412 | // Fetch and unpack the remote into a temporary directory. |
| ... | ... | @@ -602,6 +677,8 @@ fn queueJobsForDeps(f: *Fetch) RunError!void { |
| 602 | 677 | .location = location, |
| 603 | 678 | .location_tok = dep.location_tok, |
| 604 | 679 | .hash_tok = dep.hash_tok, |
| 680 | .name_tok = dep.name_tok, | |
| 681 | .lazy_status = if (dep.lazy) .available else .eager, | |
| 605 | 682 | .parent_package_root = f.package_root, |
| 606 | 683 | .parent_manifest_ast = &f.manifest_ast, |
| 607 | 684 | .prog_node = f.prog_node, |
src/Package/Manifest.zig+28| ... | ... | @@ -12,6 +12,8 @@ pub const Dependency = struct { |
| 12 | 12 | hash: ?[]const u8, |
| 13 | 13 | hash_tok: Ast.TokenIndex, |
| 14 | 14 | node: Ast.Node.Index, |
| 15 | name_tok: Ast.TokenIndex, | |
| 16 | lazy: bool, | |
| 15 | 17 | |
| 16 | 18 | pub const Location = union(enum) { |
| 17 | 19 | url: []const u8, |
| ... | ... | @@ -303,11 +305,14 @@ const Parse = struct { |
| 303 | 305 | .hash = null, |
| 304 | 306 | .hash_tok = 0, |
| 305 | 307 | .node = node, |
| 308 | .name_tok = 0, | |
| 309 | .lazy = false, | |
| 306 | 310 | }; |
| 307 | 311 | var has_location = false; |
| 308 | 312 | |
| 309 | 313 | for (struct_init.ast.fields) |field_init| { |
| 310 | 314 | const name_token = ast.firstToken(field_init) - 2; |
| 315 | dep.name_tok = name_token; | |
| 311 | 316 | const field_name = try identifierTokenString(p, name_token); |
| 312 | 317 | // We could get fancy with reflection and comptime logic here but doing |
| 313 | 318 | // things manually provides an opportunity to do any additional verification |
| ... | ... | @@ -342,6 +347,11 @@ const Parse = struct { |
| 342 | 347 | else => |e| return e, |
| 343 | 348 | }; |
| 344 | 349 | dep.hash_tok = main_tokens[field_init]; |
| 350 | } else if (mem.eql(u8, field_name, "lazy")) { | |
| 351 | dep.lazy = parseBool(p, field_init) catch |err| switch (err) { | |
| 352 | error.ParseFailure => continue, | |
| 353 | else => |e| return e, | |
| 354 | }; | |
| 345 | 355 | } else { |
| 346 | 356 | // Ignore unknown fields so that we can add fields in future zig |
| 347 | 357 | // versions without breaking older zig versions. |
| ... | ... | @@ -374,6 +384,24 @@ const Parse = struct { |
| 374 | 384 | } |
| 375 | 385 | } |
| 376 | 386 | |
| 387 | fn parseBool(p: *Parse, node: Ast.Node.Index) !bool { | |
| 388 | const ast = p.ast; | |
| 389 | const node_tags = ast.nodes.items(.tag); | |
| 390 | const main_tokens = ast.nodes.items(.main_token); | |
| 391 | if (node_tags[node] != .identifier) { | |
| 392 | return fail(p, main_tokens[node], "expected identifier", .{}); | |
| 393 | } | |
| 394 | const ident_token = main_tokens[node]; | |
| 395 | const token_bytes = ast.tokenSlice(ident_token); | |
| 396 | if (mem.eql(u8, token_bytes, "true")) { | |
| 397 | return true; | |
| 398 | } else if (mem.eql(u8, token_bytes, "false")) { | |
| 399 | return false; | |
| 400 | } else { | |
| 401 | return fail(p, ident_token, "expected boolean", .{}); | |
| 402 | } | |
| 403 | } | |
| 404 | ||
| 377 | 405 | fn parseString(p: *Parse, node: Ast.Node.Index) ![]const u8 { |
| 378 | 406 | const ast = p.ast; |
| 379 | 407 | const node_tags = ast.nodes.items(.tag); |
src/main.zig+545-422| ... | ... | @@ -969,6 +969,9 @@ fn buildOutputType( |
| 969 | 969 | .libc_paths_file = try EnvVar.ZIG_LIBC.get(arena), |
| 970 | 970 | .link_objects = .{}, |
| 971 | 971 | .native_system_include_paths = &.{}, |
| 972 | .host_triple = null, | |
| 973 | .host_cpu = null, | |
| 974 | .host_dynamic_linker = null, | |
| 972 | 975 | }; |
| 973 | 976 | |
| 974 | 977 | // before arg parsing, check for the NO_COLOR environment variable |
| ... | ... | @@ -1262,6 +1265,12 @@ fn buildOutputType( |
| 1262 | 1265 | mod_opts.optimize_mode = parseOptimizeMode(arg["-O".len..]); |
| 1263 | 1266 | } else if (mem.eql(u8, arg, "--dynamic-linker")) { |
| 1264 | 1267 | create_module.dynamic_linker = args_iter.nextOrFatal(); |
| 1268 | } else if (mem.eql(u8, arg, "--host-target")) { | |
| 1269 | create_module.host_triple = args_iter.nextOrFatal(); | |
| 1270 | } else if (mem.eql(u8, arg, "--host-cpu")) { | |
| 1271 | create_module.host_cpu = args_iter.nextOrFatal(); | |
| 1272 | } else if (mem.eql(u8, arg, "--host-dynamic-linker")) { | |
| 1273 | create_module.host_dynamic_linker = args_iter.nextOrFatal(); | |
| 1265 | 1274 | } else if (mem.eql(u8, arg, "--sysroot")) { |
| 1266 | 1275 | const next_arg = args_iter.nextOrFatal(); |
| 1267 | 1276 | create_module.sysroot = next_arg; |
| ... | ... | @@ -3455,6 +3464,9 @@ const CreateModule = struct { |
| 3455 | 3464 | each_lib_rpath: ?bool, |
| 3456 | 3465 | libc_paths_file: ?[]const u8, |
| 3457 | 3466 | link_objects: std.ArrayListUnmanaged(Compilation.LinkObject), |
| 3467 | host_triple: ?[]const u8, | |
| 3468 | host_cpu: ?[]const u8, | |
| 3469 | host_dynamic_linker: ?[]const u8, | |
| 3458 | 3470 | }; |
| 3459 | 3471 | |
| 3460 | 3472 | fn createModule( |
| ... | ... | @@ -3539,7 +3551,15 @@ fn createModule( |
| 3539 | 3551 | } |
| 3540 | 3552 | |
| 3541 | 3553 | const target_query = parseTargetQueryOrReportFatalError(arena, target_parse_options); |
| 3542 | const target = resolveTargetQueryOrFatal(target_query); | |
| 3554 | const adjusted_target_query = a: { | |
| 3555 | if (!target_query.isNative()) break :a target_query; | |
| 3556 | if (create_module.host_triple) |triple| target_parse_options.arch_os_abi = triple; | |
| 3557 | if (create_module.host_cpu) |cpu| target_parse_options.cpu_features = cpu; | |
| 3558 | if (create_module.host_dynamic_linker) |dl| target_parse_options.dynamic_linker = dl; | |
| 3559 | break :a parseTargetQueryOrReportFatalError(arena, target_parse_options); | |
| 3560 | }; | |
| 3561 | ||
| 3562 | const target = resolveTargetQueryOrFatal(adjusted_target_query); | |
| 3543 | 3563 | break :t .{ |
| 3544 | 3564 | .result = target, |
| 3545 | 3565 | .is_native_os = target_query.isNativeOs(), |
| ... | ... | @@ -5130,476 +5150,576 @@ pub const usage_build = |
| 5130 | 5150 | ; |
| 5131 | 5151 | |
| 5132 | 5152 | pub fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void { |
| 5133 | const work_around_btrfs_bug = builtin.os.tag == .linux and | |
| 5134 | EnvVar.ZIG_BTRFS_WORKAROUND.isSet(); | |
| 5135 | const color: Color = .auto; | |
| 5153 | var progress: std.Progress = .{ .dont_print_on_dumb = true }; | |
| 5136 | 5154 | |
| 5137 | // We want to release all the locks before executing the child process, so we make a nice | |
| 5138 | // big block here to ensure the cleanup gets run when we extract out our argv. | |
| 5139 | const child_argv = argv: { | |
| 5140 | const self_exe_path = try introspect.findZigExePath(arena); | |
| 5155 | var build_file: ?[]const u8 = null; | |
| 5156 | var override_lib_dir: ?[]const u8 = try EnvVar.ZIG_LIB_DIR.get(arena); | |
| 5157 | var override_global_cache_dir: ?[]const u8 = try EnvVar.ZIG_GLOBAL_CACHE_DIR.get(arena); | |
| 5158 | var override_local_cache_dir: ?[]const u8 = try EnvVar.ZIG_LOCAL_CACHE_DIR.get(arena); | |
| 5159 | var override_build_runner: ?[]const u8 = try EnvVar.ZIG_BUILD_RUNNER.get(arena); | |
| 5160 | var child_argv = std.ArrayList([]const u8).init(arena); | |
| 5161 | var reference_trace: ?u32 = null; | |
| 5162 | var debug_compile_errors = false; | |
| 5163 | var verbose_link = (builtin.os.tag != .wasi or builtin.link_libc) and | |
| 5164 | EnvVar.ZIG_VERBOSE_LINK.isSet(); | |
| 5165 | var verbose_cc = (builtin.os.tag != .wasi or builtin.link_libc) and | |
| 5166 | EnvVar.ZIG_VERBOSE_CC.isSet(); | |
| 5167 | var verbose_air = false; | |
| 5168 | var verbose_intern_pool = false; | |
| 5169 | var verbose_generic_instances = false; | |
| 5170 | var verbose_llvm_ir: ?[]const u8 = null; | |
| 5171 | var verbose_llvm_bc: ?[]const u8 = null; | |
| 5172 | var verbose_cimport = false; | |
| 5173 | var verbose_llvm_cpu_features = false; | |
| 5174 | var fetch_only = false; | |
| 5175 | var system_pkg_dir_path: ?[]const u8 = null; | |
| 5141 | 5176 | |
| 5142 | var build_file: ?[]const u8 = null; | |
| 5143 | var override_lib_dir: ?[]const u8 = try EnvVar.ZIG_LIB_DIR.get(arena); | |
| 5144 | var override_global_cache_dir: ?[]const u8 = try EnvVar.ZIG_GLOBAL_CACHE_DIR.get(arena); | |
| 5145 | var override_local_cache_dir: ?[]const u8 = try EnvVar.ZIG_LOCAL_CACHE_DIR.get(arena); | |
| 5146 | var override_build_runner: ?[]const u8 = try EnvVar.ZIG_BUILD_RUNNER.get(arena); | |
| 5147 | var child_argv = std.ArrayList([]const u8).init(arena); | |
| 5148 | var reference_trace: ?u32 = null; | |
| 5149 | var debug_compile_errors = false; | |
| 5150 | var verbose_link = (builtin.os.tag != .wasi or builtin.link_libc) and | |
| 5151 | EnvVar.ZIG_VERBOSE_LINK.isSet(); | |
| 5152 | var verbose_cc = (builtin.os.tag != .wasi or builtin.link_libc) and | |
| 5153 | EnvVar.ZIG_VERBOSE_CC.isSet(); | |
| 5154 | var verbose_air = false; | |
| 5155 | var verbose_intern_pool = false; | |
| 5156 | var verbose_generic_instances = false; | |
| 5157 | var verbose_llvm_ir: ?[]const u8 = null; | |
| 5158 | var verbose_llvm_bc: ?[]const u8 = null; | |
| 5159 | var verbose_cimport = false; | |
| 5160 | var verbose_llvm_cpu_features = false; | |
| 5161 | var fetch_only = false; | |
| 5162 | ||
| 5163 | const argv_index_exe = child_argv.items.len; | |
| 5164 | _ = try child_argv.addOne(); | |
| 5165 | ||
| 5166 | try child_argv.append(self_exe_path); | |
| 5167 | ||
| 5168 | const argv_index_build_file = child_argv.items.len; | |
| 5169 | _ = try child_argv.addOne(); | |
| 5170 | ||
| 5171 | const argv_index_cache_dir = child_argv.items.len; | |
| 5172 | _ = try child_argv.addOne(); | |
| 5173 | ||
| 5174 | const argv_index_global_cache_dir = child_argv.items.len; | |
| 5175 | _ = try child_argv.addOne(); | |
| 5176 | ||
| 5177 | try child_argv.appendSlice(&.{ | |
| 5178 | "--seed", | |
| 5179 | try std.fmt.allocPrint(arena, "0x{x}", .{std.crypto.random.int(u32)}), | |
| 5180 | }); | |
| 5181 | const argv_index_seed = child_argv.items.len - 1; | |
| 5177 | const argv_index_exe = child_argv.items.len; | |
| 5178 | _ = try child_argv.addOne(); | |
| 5182 | 5179 | |
| 5183 | { | |
| 5184 | var i: usize = 0; | |
| 5185 | while (i < args.len) : (i += 1) { | |
| 5186 | const arg = args[i]; | |
| 5187 | if (mem.startsWith(u8, arg, "-")) { | |
| 5188 | if (mem.eql(u8, arg, "--build-file")) { | |
| 5189 | if (i + 1 >= args.len) fatal("expected argument after '{s}'", .{arg}); | |
| 5190 | i += 1; | |
| 5191 | build_file = args[i]; | |
| 5192 | continue; | |
| 5193 | } else if (mem.eql(u8, arg, "--zig-lib-dir")) { | |
| 5194 | if (i + 1 >= args.len) fatal("expected argument after '{s}'", .{arg}); | |
| 5195 | i += 1; | |
| 5196 | override_lib_dir = args[i]; | |
| 5197 | try child_argv.appendSlice(&.{ arg, args[i] }); | |
| 5198 | continue; | |
| 5199 | } else if (mem.eql(u8, arg, "--build-runner")) { | |
| 5200 | if (i + 1 >= args.len) fatal("expected argument after '{s}'", .{arg}); | |
| 5201 | i += 1; | |
| 5202 | override_build_runner = args[i]; | |
| 5203 | continue; | |
| 5204 | } else if (mem.eql(u8, arg, "--cache-dir")) { | |
| 5205 | if (i + 1 >= args.len) fatal("expected argument after '{s}'", .{arg}); | |
| 5206 | i += 1; | |
| 5207 | override_local_cache_dir = args[i]; | |
| 5208 | continue; | |
| 5209 | } else if (mem.eql(u8, arg, "--global-cache-dir")) { | |
| 5210 | if (i + 1 >= args.len) fatal("expected argument after '{s}'", .{arg}); | |
| 5211 | i += 1; | |
| 5212 | override_global_cache_dir = args[i]; | |
| 5213 | continue; | |
| 5214 | } else if (mem.eql(u8, arg, "-freference-trace")) { | |
| 5215 | reference_trace = 256; | |
| 5216 | } else if (mem.eql(u8, arg, "--fetch")) { | |
| 5217 | fetch_only = true; | |
| 5218 | } else if (mem.startsWith(u8, arg, "-freference-trace=")) { | |
| 5219 | const num = arg["-freference-trace=".len..]; | |
| 5220 | reference_trace = std.fmt.parseUnsigned(u32, num, 10) catch |err| { | |
| 5221 | fatal("unable to parse reference_trace count '{s}': {s}", .{ num, @errorName(err) }); | |
| 5222 | }; | |
| 5223 | } else if (mem.eql(u8, arg, "-fno-reference-trace")) { | |
| 5224 | reference_trace = null; | |
| 5225 | } else if (mem.eql(u8, arg, "--debug-log")) { | |
| 5226 | if (i + 1 >= args.len) fatal("expected argument after '{s}'", .{arg}); | |
| 5227 | try child_argv.appendSlice(args[i .. i + 2]); | |
| 5228 | i += 1; | |
| 5229 | if (!build_options.enable_logging) { | |
| 5230 | warn("Zig was compiled without logging enabled (-Dlog). --debug-log has no effect.", .{}); | |
| 5231 | } else { | |
| 5232 | try log_scopes.append(arena, args[i]); | |
| 5233 | } | |
| 5234 | continue; | |
| 5235 | } else if (mem.eql(u8, arg, "--debug-compile-errors")) { | |
| 5236 | if (!crash_report.is_enabled) { | |
| 5237 | warn("Zig was compiled in a release mode. --debug-compile-errors has no effect.", .{}); | |
| 5238 | } else { | |
| 5239 | debug_compile_errors = true; | |
| 5240 | } | |
| 5241 | } else if (mem.eql(u8, arg, "--verbose-link")) { | |
| 5242 | verbose_link = true; | |
| 5243 | } else if (mem.eql(u8, arg, "--verbose-cc")) { | |
| 5244 | verbose_cc = true; | |
| 5245 | } else if (mem.eql(u8, arg, "--verbose-air")) { | |
| 5246 | verbose_air = true; | |
| 5247 | } else if (mem.eql(u8, arg, "--verbose-intern-pool")) { | |
| 5248 | verbose_intern_pool = true; | |
| 5249 | } else if (mem.eql(u8, arg, "--verbose-generic-instances")) { | |
| 5250 | verbose_generic_instances = true; | |
| 5251 | } else if (mem.eql(u8, arg, "--verbose-llvm-ir")) { | |
| 5252 | verbose_llvm_ir = "-"; | |
| 5253 | } else if (mem.startsWith(u8, arg, "--verbose-llvm-ir=")) { | |
| 5254 | verbose_llvm_ir = arg["--verbose-llvm-ir=".len..]; | |
| 5255 | } else if (mem.startsWith(u8, arg, "--verbose-llvm-bc=")) { | |
| 5256 | verbose_llvm_bc = arg["--verbose-llvm-bc=".len..]; | |
| 5257 | } else if (mem.eql(u8, arg, "--verbose-cimport")) { | |
| 5258 | verbose_cimport = true; | |
| 5259 | } else if (mem.eql(u8, arg, "--verbose-llvm-cpu-features")) { | |
| 5260 | verbose_llvm_cpu_features = true; | |
| 5261 | } else if (mem.eql(u8, arg, "--seed")) { | |
| 5262 | if (i + 1 >= args.len) fatal("expected argument after '{s}'", .{arg}); | |
| 5263 | i += 1; | |
| 5264 | child_argv.items[argv_index_seed] = args[i]; | |
| 5265 | continue; | |
| 5180 | const self_exe_path = try introspect.findZigExePath(arena); | |
| 5181 | try child_argv.append(self_exe_path); | |
| 5182 | ||
| 5183 | const argv_index_build_file = child_argv.items.len; | |
| 5184 | _ = try child_argv.addOne(); | |
| 5185 | ||
| 5186 | const argv_index_cache_dir = child_argv.items.len; | |
| 5187 | _ = try child_argv.addOne(); | |
| 5188 | ||
| 5189 | const argv_index_global_cache_dir = child_argv.items.len; | |
| 5190 | _ = try child_argv.addOne(); | |
| 5191 | ||
| 5192 | try child_argv.appendSlice(&.{ | |
| 5193 | "--seed", | |
| 5194 | try std.fmt.allocPrint(arena, "0x{x}", .{std.crypto.random.int(u32)}), | |
| 5195 | }); | |
| 5196 | const argv_index_seed = child_argv.items.len - 1; | |
| 5197 | ||
| 5198 | // This parent process needs a way to obtain results from the configuration | |
| 5199 | // phase of the child process. In the future, the make phase will be | |
| 5200 | // executed in a separate process than the configure phase, and we can then | |
| 5201 | // use stdout from the configuration phase for this purpose. | |
| 5202 | // | |
| 5203 | // However, currently, both phases are in the same process, and Run Step | |
| 5204 | // provides API for making the runned subprocesses inherit stdout and stderr | |
| 5205 | // which means these streams are not available for passing metadata back | |
| 5206 | // to the parent. | |
| 5207 | // | |
| 5208 | // Until make and configure phases are separated into different processes, | |
| 5209 | // the strategy is to choose a temporary file name ahead of time, and then | |
| 5210 | // read this file in the parent to obtain the results, in the case the child | |
| 5211 | // exits with code 3. | |
| 5212 | const results_tmp_file_nonce = Package.Manifest.hex64(std.crypto.random.int(u64)); | |
| 5213 | try child_argv.append("-Z" ++ results_tmp_file_nonce); | |
| 5214 | ||
| 5215 | { | |
| 5216 | var i: usize = 0; | |
| 5217 | while (i < args.len) : (i += 1) { | |
| 5218 | const arg = args[i]; | |
| 5219 | if (mem.startsWith(u8, arg, "-")) { | |
| 5220 | if (mem.eql(u8, arg, "--build-file")) { | |
| 5221 | if (i + 1 >= args.len) fatal("expected argument after '{s}'", .{arg}); | |
| 5222 | i += 1; | |
| 5223 | build_file = args[i]; | |
| 5224 | continue; | |
| 5225 | } else if (mem.eql(u8, arg, "--zig-lib-dir")) { | |
| 5226 | if (i + 1 >= args.len) fatal("expected argument after '{s}'", .{arg}); | |
| 5227 | i += 1; | |
| 5228 | override_lib_dir = args[i]; | |
| 5229 | try child_argv.appendSlice(&.{ arg, args[i] }); | |
| 5230 | continue; | |
| 5231 | } else if (mem.eql(u8, arg, "--build-runner")) { | |
| 5232 | if (i + 1 >= args.len) fatal("expected argument after '{s}'", .{arg}); | |
| 5233 | i += 1; | |
| 5234 | override_build_runner = args[i]; | |
| 5235 | continue; | |
| 5236 | } else if (mem.eql(u8, arg, "--cache-dir")) { | |
| 5237 | if (i + 1 >= args.len) fatal("expected argument after '{s}'", .{arg}); | |
| 5238 | i += 1; | |
| 5239 | override_local_cache_dir = args[i]; | |
| 5240 | continue; | |
| 5241 | } else if (mem.eql(u8, arg, "--global-cache-dir")) { | |
| 5242 | if (i + 1 >= args.len) fatal("expected argument after '{s}'", .{arg}); | |
| 5243 | i += 1; | |
| 5244 | override_global_cache_dir = args[i]; | |
| 5245 | continue; | |
| 5246 | } else if (mem.eql(u8, arg, "-freference-trace")) { | |
| 5247 | reference_trace = 256; | |
| 5248 | } else if (mem.eql(u8, arg, "--fetch")) { | |
| 5249 | fetch_only = true; | |
| 5250 | } else if (mem.eql(u8, arg, "--system")) { | |
| 5251 | if (i + 1 >= args.len) fatal("expected argument after '{s}'", .{arg}); | |
| 5252 | i += 1; | |
| 5253 | system_pkg_dir_path = args[i]; | |
| 5254 | try child_argv.append("--system"); | |
| 5255 | continue; | |
| 5256 | } else if (mem.startsWith(u8, arg, "-freference-trace=")) { | |
| 5257 | const num = arg["-freference-trace=".len..]; | |
| 5258 | reference_trace = std.fmt.parseUnsigned(u32, num, 10) catch |err| { | |
| 5259 | fatal("unable to parse reference_trace count '{s}': {s}", .{ num, @errorName(err) }); | |
| 5260 | }; | |
| 5261 | } else if (mem.eql(u8, arg, "-fno-reference-trace")) { | |
| 5262 | reference_trace = null; | |
| 5263 | } else if (mem.eql(u8, arg, "--debug-log")) { | |
| 5264 | if (i + 1 >= args.len) fatal("expected argument after '{s}'", .{arg}); | |
| 5265 | try child_argv.appendSlice(args[i .. i + 2]); | |
| 5266 | i += 1; | |
| 5267 | if (!build_options.enable_logging) { | |
| 5268 | warn("Zig was compiled without logging enabled (-Dlog). --debug-log has no effect.", .{}); | |
| 5269 | } else { | |
| 5270 | try log_scopes.append(arena, args[i]); | |
| 5271 | } | |
| 5272 | continue; | |
| 5273 | } else if (mem.eql(u8, arg, "--debug-compile-errors")) { | |
| 5274 | if (!crash_report.is_enabled) { | |
| 5275 | warn("Zig was compiled in a release mode. --debug-compile-errors has no effect.", .{}); | |
| 5276 | } else { | |
| 5277 | debug_compile_errors = true; | |
| 5266 | 5278 | } |
| 5279 | } else if (mem.eql(u8, arg, "--verbose-link")) { | |
| 5280 | verbose_link = true; | |
| 5281 | } else if (mem.eql(u8, arg, "--verbose-cc")) { | |
| 5282 | verbose_cc = true; | |
| 5283 | } else if (mem.eql(u8, arg, "--verbose-air")) { | |
| 5284 | verbose_air = true; | |
| 5285 | } else if (mem.eql(u8, arg, "--verbose-intern-pool")) { | |
| 5286 | verbose_intern_pool = true; | |
| 5287 | } else if (mem.eql(u8, arg, "--verbose-generic-instances")) { | |
| 5288 | verbose_generic_instances = true; | |
| 5289 | } else if (mem.eql(u8, arg, "--verbose-llvm-ir")) { | |
| 5290 | verbose_llvm_ir = "-"; | |
| 5291 | } else if (mem.startsWith(u8, arg, "--verbose-llvm-ir=")) { | |
| 5292 | verbose_llvm_ir = arg["--verbose-llvm-ir=".len..]; | |
| 5293 | } else if (mem.startsWith(u8, arg, "--verbose-llvm-bc=")) { | |
| 5294 | verbose_llvm_bc = arg["--verbose-llvm-bc=".len..]; | |
| 5295 | } else if (mem.eql(u8, arg, "--verbose-cimport")) { | |
| 5296 | verbose_cimport = true; | |
| 5297 | } else if (mem.eql(u8, arg, "--verbose-llvm-cpu-features")) { | |
| 5298 | verbose_llvm_cpu_features = true; | |
| 5299 | } else if (mem.eql(u8, arg, "--seed")) { | |
| 5300 | if (i + 1 >= args.len) fatal("expected argument after '{s}'", .{arg}); | |
| 5301 | i += 1; | |
| 5302 | child_argv.items[argv_index_seed] = args[i]; | |
| 5303 | continue; | |
| 5267 | 5304 | } |
| 5268 | try child_argv.append(arg); | |
| 5269 | 5305 | } |
| 5306 | try child_argv.append(arg); | |
| 5270 | 5307 | } |
| 5308 | } | |
| 5271 | 5309 | |
| 5272 | var zig_lib_directory: Compilation.Directory = if (override_lib_dir) |lib_dir| .{ | |
| 5273 | .path = lib_dir, | |
| 5274 | .handle = fs.cwd().openDir(lib_dir, .{}) catch |err| { | |
| 5275 | fatal("unable to open zig lib directory from 'zig-lib-dir' argument: '{s}': {s}", .{ lib_dir, @errorName(err) }); | |
| 5276 | }, | |
| 5277 | } else introspect.findZigLibDirFromSelfExe(arena, self_exe_path) catch |err| { | |
| 5278 | fatal("unable to find zig installation directory '{s}': {s}", .{ self_exe_path, @errorName(err) }); | |
| 5279 | }; | |
| 5280 | defer zig_lib_directory.handle.close(); | |
| 5310 | const work_around_btrfs_bug = builtin.os.tag == .linux and | |
| 5311 | EnvVar.ZIG_BTRFS_WORKAROUND.isSet(); | |
| 5312 | const color: Color = .auto; | |
| 5281 | 5313 | |
| 5282 | var cleanup_build_dir: ?fs.Dir = null; | |
| 5283 | defer if (cleanup_build_dir) |*dir| dir.close(); | |
| 5314 | const target_query: std.Target.Query = .{}; | |
| 5315 | const resolved_target: Package.Module.ResolvedTarget = .{ | |
| 5316 | .result = resolveTargetQueryOrFatal(target_query), | |
| 5317 | .is_native_os = true, | |
| 5318 | .is_native_abi = true, | |
| 5319 | }; | |
| 5284 | 5320 | |
| 5285 | const cwd_path = try process.getCwdAlloc(arena); | |
| 5286 | const build_root = try findBuildRoot(arena, .{ | |
| 5287 | .cwd_path = cwd_path, | |
| 5288 | .build_file = build_file, | |
| 5289 | }); | |
| 5290 | child_argv.items[argv_index_build_file] = build_root.directory.path orelse cwd_path; | |
| 5321 | const exe_basename = try std.zig.binNameAlloc(arena, .{ | |
| 5322 | .root_name = "build", | |
| 5323 | .target = resolved_target.result, | |
| 5324 | .output_mode = .Exe, | |
| 5325 | }); | |
| 5326 | const emit_bin: Compilation.EmitLoc = .{ | |
| 5327 | .directory = null, // Use the local zig-cache. | |
| 5328 | .basename = exe_basename, | |
| 5329 | }; | |
| 5291 | 5330 | |
| 5292 | var global_cache_directory: Compilation.Directory = l: { | |
| 5293 | const p = override_global_cache_dir orelse try introspect.resolveGlobalCacheDir(arena); | |
| 5294 | break :l .{ | |
| 5295 | .handle = try fs.cwd().makeOpenPath(p, .{}), | |
| 5296 | .path = p, | |
| 5297 | }; | |
| 5331 | gimmeMoreOfThoseSweetSweetFileDescriptors(); | |
| 5332 | ||
| 5333 | var zig_lib_directory: Compilation.Directory = if (override_lib_dir) |lib_dir| .{ | |
| 5334 | .path = lib_dir, | |
| 5335 | .handle = fs.cwd().openDir(lib_dir, .{}) catch |err| { | |
| 5336 | fatal("unable to open zig lib directory from 'zig-lib-dir' argument: '{s}': {s}", .{ lib_dir, @errorName(err) }); | |
| 5337 | }, | |
| 5338 | } else introspect.findZigLibDirFromSelfExe(arena, self_exe_path) catch |err| { | |
| 5339 | fatal("unable to find zig installation directory '{s}': {s}", .{ self_exe_path, @errorName(err) }); | |
| 5340 | }; | |
| 5341 | defer zig_lib_directory.handle.close(); | |
| 5342 | ||
| 5343 | const cwd_path = try process.getCwdAlloc(arena); | |
| 5344 | const build_root = try findBuildRoot(arena, .{ | |
| 5345 | .cwd_path = cwd_path, | |
| 5346 | .build_file = build_file, | |
| 5347 | }); | |
| 5348 | child_argv.items[argv_index_build_file] = build_root.directory.path orelse cwd_path; | |
| 5349 | ||
| 5350 | var global_cache_directory: Compilation.Directory = l: { | |
| 5351 | const p = override_global_cache_dir orelse try introspect.resolveGlobalCacheDir(arena); | |
| 5352 | break :l .{ | |
| 5353 | .handle = try fs.cwd().makeOpenPath(p, .{}), | |
| 5354 | .path = p, | |
| 5298 | 5355 | }; |
| 5299 | defer global_cache_directory.handle.close(); | |
| 5356 | }; | |
| 5357 | defer global_cache_directory.handle.close(); | |
| 5300 | 5358 | |
| 5301 | child_argv.items[argv_index_global_cache_dir] = global_cache_directory.path orelse cwd_path; | |
| 5359 | child_argv.items[argv_index_global_cache_dir] = global_cache_directory.path orelse cwd_path; | |
| 5302 | 5360 | |
| 5303 | var local_cache_directory: Compilation.Directory = l: { | |
| 5304 | if (override_local_cache_dir) |local_cache_dir_path| { | |
| 5305 | break :l .{ | |
| 5306 | .handle = try fs.cwd().makeOpenPath(local_cache_dir_path, .{}), | |
| 5307 | .path = local_cache_dir_path, | |
| 5308 | }; | |
| 5309 | } | |
| 5310 | const cache_dir_path = try build_root.directory.join(arena, &[_][]const u8{"zig-cache"}); | |
| 5361 | var local_cache_directory: Compilation.Directory = l: { | |
| 5362 | if (override_local_cache_dir) |local_cache_dir_path| { | |
| 5311 | 5363 | break :l .{ |
| 5312 | .handle = try build_root.directory.handle.makeOpenPath("zig-cache", .{}), | |
| 5313 | .path = cache_dir_path, | |
| 5364 | .handle = try fs.cwd().makeOpenPath(local_cache_dir_path, .{}), | |
| 5365 | .path = local_cache_dir_path, | |
| 5314 | 5366 | }; |
| 5367 | } | |
| 5368 | const cache_dir_path = try build_root.directory.join(arena, &[_][]const u8{"zig-cache"}); | |
| 5369 | break :l .{ | |
| 5370 | .handle = try build_root.directory.handle.makeOpenPath("zig-cache", .{}), | |
| 5371 | .path = cache_dir_path, | |
| 5315 | 5372 | }; |
| 5316 | defer local_cache_directory.handle.close(); | |
| 5373 | }; | |
| 5374 | defer local_cache_directory.handle.close(); | |
| 5317 | 5375 | |
| 5318 | child_argv.items[argv_index_cache_dir] = local_cache_directory.path orelse cwd_path; | |
| 5376 | child_argv.items[argv_index_cache_dir] = local_cache_directory.path orelse cwd_path; | |
| 5319 | 5377 | |
| 5320 | gimmeMoreOfThoseSweetSweetFileDescriptors(); | |
| 5378 | var thread_pool: ThreadPool = undefined; | |
| 5379 | try thread_pool.init(.{ .allocator = gpa }); | |
| 5380 | defer thread_pool.deinit(); | |
| 5321 | 5381 | |
| 5322 | const target_query: std.Target.Query = .{}; | |
| 5323 | const resolved_target: Package.Module.ResolvedTarget = .{ | |
| 5324 | .result = resolveTargetQueryOrFatal(target_query), | |
| 5325 | .is_native_os = true, | |
| 5326 | .is_native_abi = true, | |
| 5327 | }; | |
| 5382 | // Dummy http client that is not actually used when only_core_functionality is enabled. | |
| 5383 | // Prevents bootstrap from depending on a bunch of unnecessary stuff. | |
| 5384 | const HttpClient = if (build_options.only_core_functionality) struct { | |
| 5385 | allocator: Allocator, | |
| 5386 | fn deinit(self: *@This()) void { | |
| 5387 | _ = self; | |
| 5388 | } | |
| 5389 | } else std.http.Client; | |
| 5328 | 5390 | |
| 5329 | const exe_basename = try std.zig.binNameAlloc(arena, .{ | |
| 5330 | .root_name = "build", | |
| 5331 | .target = resolved_target.result, | |
| 5332 | .output_mode = .Exe, | |
| 5333 | }); | |
| 5334 | const emit_bin: Compilation.EmitLoc = .{ | |
| 5335 | .directory = null, // Use the local zig-cache. | |
| 5336 | .basename = exe_basename, | |
| 5337 | }; | |
| 5338 | var thread_pool: ThreadPool = undefined; | |
| 5339 | try thread_pool.init(.{ .allocator = gpa }); | |
| 5340 | defer thread_pool.deinit(); | |
| 5391 | var http_client: HttpClient = .{ .allocator = gpa }; | |
| 5392 | defer http_client.deinit(); | |
| 5341 | 5393 | |
| 5342 | const main_mod_paths: Package.Module.CreateOptions.Paths = if (override_build_runner) |runner| .{ | |
| 5343 | .root = .{ | |
| 5344 | .root_dir = Cache.Directory.cwd(), | |
| 5345 | .sub_path = fs.path.dirname(runner) orelse "", | |
| 5346 | }, | |
| 5347 | .root_src_path = fs.path.basename(runner), | |
| 5348 | } else .{ | |
| 5349 | .root = .{ .root_dir = zig_lib_directory }, | |
| 5350 | .root_src_path = "build_runner.zig", | |
| 5351 | }; | |
| 5394 | var unlazy_set: Package.Fetch.JobQueue.UnlazySet = .{}; | |
| 5352 | 5395 | |
| 5353 | const config = try Compilation.Config.resolve(.{ | |
| 5354 | .output_mode = .Exe, | |
| 5355 | .resolved_target = resolved_target, | |
| 5356 | .have_zcu = true, | |
| 5357 | .emit_bin = true, | |
| 5358 | .is_test = false, | |
| 5359 | }); | |
| 5396 | // This loop is re-evaluated when the build script exits with an indication that it | |
| 5397 | // could not continue due to missing lazy dependencies. | |
| 5398 | while (true) { | |
| 5399 | // We want to release all the locks before executing the child process, so we make a nice | |
| 5400 | // big block here to ensure the cleanup gets run when we extract out our argv. | |
| 5401 | { | |
| 5402 | const main_mod_paths: Package.Module.CreateOptions.Paths = if (override_build_runner) |runner| .{ | |
| 5403 | .root = .{ | |
| 5404 | .root_dir = Cache.Directory.cwd(), | |
| 5405 | .sub_path = fs.path.dirname(runner) orelse "", | |
| 5406 | }, | |
| 5407 | .root_src_path = fs.path.basename(runner), | |
| 5408 | } else .{ | |
| 5409 | .root = .{ .root_dir = zig_lib_directory }, | |
| 5410 | .root_src_path = "build_runner.zig", | |
| 5411 | }; | |
| 5360 | 5412 | |
| 5361 | const root_mod = try Package.Module.create(arena, .{ | |
| 5362 | .global_cache_directory = global_cache_directory, | |
| 5363 | .paths = main_mod_paths, | |
| 5364 | .fully_qualified_name = "root", | |
| 5365 | .cc_argv = &.{}, | |
| 5366 | .inherited = .{ | |
| 5413 | const config = try Compilation.Config.resolve(.{ | |
| 5414 | .output_mode = .Exe, | |
| 5367 | 5415 | .resolved_target = resolved_target, |
| 5368 | }, | |
| 5369 | .global = config, | |
| 5370 | .parent = null, | |
| 5371 | .builtin_mod = null, | |
| 5372 | }); | |
| 5416 | .have_zcu = true, | |
| 5417 | .emit_bin = true, | |
| 5418 | .is_test = false, | |
| 5419 | }); | |
| 5373 | 5420 | |
| 5374 | const builtin_mod = root_mod.getBuiltinDependency(); | |
| 5421 | const root_mod = try Package.Module.create(arena, .{ | |
| 5422 | .global_cache_directory = global_cache_directory, | |
| 5423 | .paths = main_mod_paths, | |
| 5424 | .fully_qualified_name = "root", | |
| 5425 | .cc_argv = &.{}, | |
| 5426 | .inherited = .{ | |
| 5427 | .resolved_target = resolved_target, | |
| 5428 | }, | |
| 5429 | .global = config, | |
| 5430 | .parent = null, | |
| 5431 | .builtin_mod = null, | |
| 5432 | }); | |
| 5375 | 5433 | |
| 5376 | const build_mod = try Package.Module.create(arena, .{ | |
| 5377 | .global_cache_directory = global_cache_directory, | |
| 5378 | .paths = .{ | |
| 5379 | .root = .{ .root_dir = build_root.directory }, | |
| 5380 | .root_src_path = build_root.build_zig_basename, | |
| 5381 | }, | |
| 5382 | .fully_qualified_name = "root.@build", | |
| 5383 | .cc_argv = &.{}, | |
| 5384 | .inherited = .{}, | |
| 5385 | .global = config, | |
| 5386 | .parent = root_mod, | |
| 5387 | .builtin_mod = builtin_mod, | |
| 5388 | }); | |
| 5389 | if (build_options.only_core_functionality) { | |
| 5390 | try createEmptyDependenciesModule( | |
| 5391 | arena, | |
| 5392 | root_mod, | |
| 5393 | global_cache_directory, | |
| 5394 | local_cache_directory, | |
| 5395 | builtin_mod, | |
| 5396 | config, | |
| 5397 | ); | |
| 5398 | } else { | |
| 5399 | var http_client: std.http.Client = .{ .allocator = gpa }; | |
| 5400 | defer http_client.deinit(); | |
| 5434 | const builtin_mod = root_mod.getBuiltinDependency(); | |
| 5401 | 5435 | |
| 5402 | try http_client.loadDefaultProxies(); | |
| 5436 | const build_mod = try Package.Module.create(arena, .{ | |
| 5437 | .global_cache_directory = global_cache_directory, | |
| 5438 | .paths = .{ | |
| 5439 | .root = .{ .root_dir = build_root.directory }, | |
| 5440 | .root_src_path = build_root.build_zig_basename, | |
| 5441 | }, | |
| 5442 | .fully_qualified_name = "root.@build", | |
| 5443 | .cc_argv = &.{}, | |
| 5444 | .inherited = .{}, | |
| 5445 | .global = config, | |
| 5446 | .parent = root_mod, | |
| 5447 | .builtin_mod = builtin_mod, | |
| 5448 | }); | |
| 5403 | 5449 | |
| 5404 | var progress: std.Progress = .{ .dont_print_on_dumb = true }; | |
| 5405 | const root_prog_node = progress.start("Fetch Packages", 0); | |
| 5406 | defer root_prog_node.end(); | |
| 5450 | var cleanup_build_dir: ?fs.Dir = null; | |
| 5451 | defer if (cleanup_build_dir) |*dir| dir.close(); | |
| 5452 | ||
| 5453 | if (build_options.only_core_functionality) { | |
| 5454 | try createEmptyDependenciesModule( | |
| 5455 | arena, | |
| 5456 | root_mod, | |
| 5457 | global_cache_directory, | |
| 5458 | local_cache_directory, | |
| 5459 | builtin_mod, | |
| 5460 | config, | |
| 5461 | ); | |
| 5462 | } else { | |
| 5463 | const root_prog_node = progress.start("Fetch Packages", 0); | |
| 5464 | defer root_prog_node.end(); | |
| 5465 | ||
| 5466 | var job_queue: Package.Fetch.JobQueue = .{ | |
| 5467 | .http_client = &http_client, | |
| 5468 | .thread_pool = &thread_pool, | |
| 5469 | .global_cache = global_cache_directory, | |
| 5470 | .read_only = false, | |
| 5471 | .recursive = true, | |
| 5472 | .debug_hash = false, | |
| 5473 | .work_around_btrfs_bug = work_around_btrfs_bug, | |
| 5474 | .unlazy_set = unlazy_set, | |
| 5475 | }; | |
| 5476 | defer job_queue.deinit(); | |
| 5477 | ||
| 5478 | if (system_pkg_dir_path) |p| { | |
| 5479 | job_queue.global_cache = .{ | |
| 5480 | .path = p, | |
| 5481 | .handle = fs.cwd().openDir(p, .{}) catch |err| { | |
| 5482 | fatal("unable to open system package directory '{s}': {s}", .{ | |
| 5483 | p, @errorName(err), | |
| 5484 | }); | |
| 5485 | }, | |
| 5486 | }; | |
| 5487 | job_queue.read_only = true; | |
| 5488 | cleanup_build_dir = job_queue.global_cache.handle; | |
| 5489 | } else { | |
| 5490 | try http_client.loadDefaultProxies(); | |
| 5491 | } | |
| 5407 | 5492 | |
| 5408 | var job_queue: Package.Fetch.JobQueue = .{ | |
| 5409 | .http_client = &http_client, | |
| 5410 | .thread_pool = &thread_pool, | |
| 5411 | .global_cache = global_cache_directory, | |
| 5412 | .recursive = true, | |
| 5413 | .debug_hash = false, | |
| 5414 | .work_around_btrfs_bug = work_around_btrfs_bug, | |
| 5415 | }; | |
| 5416 | defer job_queue.deinit(); | |
| 5417 | ||
| 5418 | try job_queue.all_fetches.ensureUnusedCapacity(gpa, 1); | |
| 5419 | try job_queue.table.ensureUnusedCapacity(gpa, 1); | |
| 5420 | ||
| 5421 | var fetch: Package.Fetch = .{ | |
| 5422 | .arena = std.heap.ArenaAllocator.init(gpa), | |
| 5423 | .location = .{ .relative_path = build_mod.root }, | |
| 5424 | .location_tok = 0, | |
| 5425 | .hash_tok = 0, | |
| 5426 | .parent_package_root = build_mod.root, | |
| 5427 | .parent_manifest_ast = null, | |
| 5428 | .prog_node = root_prog_node, | |
| 5429 | .job_queue = &job_queue, | |
| 5430 | .omit_missing_hash_error = true, | |
| 5431 | .allow_missing_paths_field = false, | |
| 5432 | ||
| 5433 | .package_root = undefined, | |
| 5434 | .error_bundle = undefined, | |
| 5435 | .manifest = null, | |
| 5436 | .manifest_ast = undefined, | |
| 5437 | .actual_hash = undefined, | |
| 5438 | .has_build_zig = true, | |
| 5439 | .oom_flag = false, | |
| 5440 | ||
| 5441 | .module = build_mod, | |
| 5442 | }; | |
| 5443 | job_queue.all_fetches.appendAssumeCapacity(&fetch); | |
| 5493 | try job_queue.all_fetches.ensureUnusedCapacity(gpa, 1); | |
| 5494 | try job_queue.table.ensureUnusedCapacity(gpa, 1); | |
| 5495 | ||
| 5496 | var fetch: Package.Fetch = .{ | |
| 5497 | .arena = std.heap.ArenaAllocator.init(gpa), | |
| 5498 | .location = .{ .relative_path = build_mod.root }, | |
| 5499 | .location_tok = 0, | |
| 5500 | .hash_tok = 0, | |
| 5501 | .name_tok = 0, | |
| 5502 | .lazy_status = .eager, | |
| 5503 | .parent_package_root = build_mod.root, | |
| 5504 | .parent_manifest_ast = null, | |
| 5505 | .prog_node = root_prog_node, | |
| 5506 | .job_queue = &job_queue, | |
| 5507 | .omit_missing_hash_error = true, | |
| 5508 | .allow_missing_paths_field = false, | |
| 5509 | ||
| 5510 | .package_root = undefined, | |
| 5511 | .error_bundle = undefined, | |
| 5512 | .manifest = null, | |
| 5513 | .manifest_ast = undefined, | |
| 5514 | .actual_hash = undefined, | |
| 5515 | .has_build_zig = true, | |
| 5516 | .oom_flag = false, | |
| 5517 | ||
| 5518 | .module = build_mod, | |
| 5519 | }; | |
| 5520 | job_queue.all_fetches.appendAssumeCapacity(&fetch); | |
| 5444 | 5521 | |
| 5445 | job_queue.table.putAssumeCapacityNoClobber( | |
| 5446 | Package.Fetch.relativePathDigest(build_mod.root, global_cache_directory), | |
| 5447 | &fetch, | |
| 5448 | ); | |
| 5522 | job_queue.table.putAssumeCapacityNoClobber( | |
| 5523 | Package.Fetch.relativePathDigest(build_mod.root, global_cache_directory), | |
| 5524 | &fetch, | |
| 5525 | ); | |
| 5449 | 5526 | |
| 5450 | job_queue.wait_group.start(); | |
| 5451 | try job_queue.thread_pool.spawn(Package.Fetch.workerRun, .{ &fetch, "root" }); | |
| 5452 | job_queue.wait_group.wait(); | |
| 5527 | job_queue.wait_group.start(); | |
| 5528 | try job_queue.thread_pool.spawn(Package.Fetch.workerRun, .{ &fetch, "root" }); | |
| 5529 | job_queue.wait_group.wait(); | |
| 5453 | 5530 | |
| 5454 | try job_queue.consolidateErrors(); | |
| 5531 | try job_queue.consolidateErrors(); | |
| 5455 | 5532 | |
| 5456 | if (fetch.error_bundle.root_list.items.len > 0) { | |
| 5457 | var errors = try fetch.error_bundle.toOwnedBundle(""); | |
| 5458 | errors.renderToStdErr(renderOptions(color)); | |
| 5459 | process.exit(1); | |
| 5460 | } | |
| 5533 | if (fetch.error_bundle.root_list.items.len > 0) { | |
| 5534 | var errors = try fetch.error_bundle.toOwnedBundle(""); | |
| 5535 | errors.renderToStdErr(renderOptions(color)); | |
| 5536 | process.exit(1); | |
| 5537 | } | |
| 5461 | 5538 | |
| 5462 | if (fetch_only) return cleanExit(); | |
| 5463 | ||
| 5464 | var source_buf = std.ArrayList(u8).init(gpa); | |
| 5465 | defer source_buf.deinit(); | |
| 5466 | try job_queue.createDependenciesSource(&source_buf); | |
| 5467 | const deps_mod = try createDependenciesModule( | |
| 5468 | arena, | |
| 5469 | source_buf.items, | |
| 5470 | root_mod, | |
| 5471 | global_cache_directory, | |
| 5472 | local_cache_directory, | |
| 5473 | builtin_mod, | |
| 5474 | config, | |
| 5475 | ); | |
| 5539 | if (fetch_only) return cleanExit(); | |
| 5540 | ||
| 5541 | var source_buf = std.ArrayList(u8).init(gpa); | |
| 5542 | defer source_buf.deinit(); | |
| 5543 | try job_queue.createDependenciesSource(&source_buf); | |
| 5544 | const deps_mod = try createDependenciesModule( | |
| 5545 | arena, | |
| 5546 | source_buf.items, | |
| 5547 | root_mod, | |
| 5548 | global_cache_directory, | |
| 5549 | local_cache_directory, | |
| 5550 | builtin_mod, | |
| 5551 | config, | |
| 5552 | ); | |
| 5476 | 5553 | |
| 5477 | { | |
| 5478 | // We need a Module for each package's build.zig. | |
| 5479 | const hashes = job_queue.table.keys(); | |
| 5480 | const fetches = job_queue.table.values(); | |
| 5481 | try deps_mod.deps.ensureUnusedCapacity(arena, @intCast(hashes.len)); | |
| 5482 | for (hashes, fetches) |hash, f| { | |
| 5483 | if (f == &fetch) { | |
| 5484 | // The first one is a dummy package for the current project. | |
| 5485 | continue; | |
| 5554 | { | |
| 5555 | // We need a Module for each package's build.zig. | |
| 5556 | const hashes = job_queue.table.keys(); | |
| 5557 | const fetches = job_queue.table.values(); | |
| 5558 | try deps_mod.deps.ensureUnusedCapacity(arena, @intCast(hashes.len)); | |
| 5559 | for (hashes, fetches) |hash, f| { | |
| 5560 | if (f == &fetch) { | |
| 5561 | // The first one is a dummy package for the current project. | |
| 5562 | continue; | |
| 5563 | } | |
| 5564 | if (!f.has_build_zig) | |
| 5565 | continue; | |
| 5566 | const m = try Package.Module.create(arena, .{ | |
| 5567 | .global_cache_directory = global_cache_directory, | |
| 5568 | .paths = .{ | |
| 5569 | .root = try f.package_root.clone(arena), | |
| 5570 | .root_src_path = Package.build_zig_basename, | |
| 5571 | }, | |
| 5572 | .fully_qualified_name = try std.fmt.allocPrint( | |
| 5573 | arena, | |
| 5574 | "root.@dependencies.{s}", | |
| 5575 | .{&hash}, | |
| 5576 | ), | |
| 5577 | .cc_argv = &.{}, | |
| 5578 | .inherited = .{}, | |
| 5579 | .global = config, | |
| 5580 | .parent = root_mod, | |
| 5581 | .builtin_mod = builtin_mod, | |
| 5582 | }); | |
| 5583 | const hash_cloned = try arena.dupe(u8, &hash); | |
| 5584 | deps_mod.deps.putAssumeCapacityNoClobber(hash_cloned, m); | |
| 5585 | f.module = m; | |
| 5486 | 5586 | } |
| 5487 | if (!f.has_build_zig) | |
| 5488 | continue; | |
| 5489 | const m = try Package.Module.create(arena, .{ | |
| 5490 | .global_cache_directory = global_cache_directory, | |
| 5491 | .paths = .{ | |
| 5492 | .root = try f.package_root.clone(arena), | |
| 5493 | .root_src_path = Package.build_zig_basename, | |
| 5494 | }, | |
| 5495 | .fully_qualified_name = try std.fmt.allocPrint( | |
| 5496 | arena, | |
| 5497 | "root.@dependencies.{s}", | |
| 5498 | .{&hash}, | |
| 5499 | ), | |
| 5500 | .cc_argv = &.{}, | |
| 5501 | .inherited = .{}, | |
| 5502 | .global = config, | |
| 5503 | .parent = root_mod, | |
| 5504 | .builtin_mod = builtin_mod, | |
| 5505 | }); | |
| 5506 | const hash_cloned = try arena.dupe(u8, &hash); | |
| 5507 | deps_mod.deps.putAssumeCapacityNoClobber(hash_cloned, m); | |
| 5508 | f.module = m; | |
| 5509 | } | |
| 5510 | 5587 | |
| 5511 | // Each build.zig module needs access to each of its | |
| 5512 | // dependencies' build.zig modules by name. | |
| 5513 | for (fetches) |f| { | |
| 5514 | const mod = f.module orelse continue; | |
| 5515 | const man = f.manifest orelse continue; | |
| 5516 | const dep_names = man.dependencies.keys(); | |
| 5517 | try mod.deps.ensureUnusedCapacity(arena, @intCast(dep_names.len)); | |
| 5518 | for (dep_names, man.dependencies.values()) |name, dep| { | |
| 5519 | const dep_digest = Package.Fetch.depDigest( | |
| 5520 | f.package_root, | |
| 5521 | global_cache_directory, | |
| 5522 | dep, | |
| 5523 | ) orelse continue; | |
| 5524 | const dep_mod = job_queue.table.get(dep_digest).?.module orelse continue; | |
| 5525 | const name_cloned = try arena.dupe(u8, name); | |
| 5526 | mod.deps.putAssumeCapacityNoClobber(name_cloned, dep_mod); | |
| 5588 | // Each build.zig module needs access to each of its | |
| 5589 | // dependencies' build.zig modules by name. | |
| 5590 | for (fetches) |f| { | |
| 5591 | const mod = f.module orelse continue; | |
| 5592 | const man = f.manifest orelse continue; | |
| 5593 | const dep_names = man.dependencies.keys(); | |
| 5594 | try mod.deps.ensureUnusedCapacity(arena, @intCast(dep_names.len)); | |
| 5595 | for (dep_names, man.dependencies.values()) |name, dep| { | |
| 5596 | const dep_digest = Package.Fetch.depDigest( | |
| 5597 | f.package_root, | |
| 5598 | global_cache_directory, | |
| 5599 | dep, | |
| 5600 | ) orelse continue; | |
| 5601 | const dep_mod = job_queue.table.get(dep_digest).?.module orelse continue; | |
| 5602 | const name_cloned = try arena.dupe(u8, name); | |
| 5603 | mod.deps.putAssumeCapacityNoClobber(name_cloned, dep_mod); | |
| 5604 | } | |
| 5527 | 5605 | } |
| 5528 | 5606 | } |
| 5529 | 5607 | } |
| 5530 | } | |
| 5531 | 5608 | |
| 5532 | try root_mod.deps.put(arena, "@build", build_mod); | |
| 5609 | try root_mod.deps.put(arena, "@build", build_mod); | |
| 5533 | 5610 | |
| 5534 | const comp = Compilation.create(gpa, arena, .{ | |
| 5535 | .zig_lib_directory = zig_lib_directory, | |
| 5536 | .local_cache_directory = local_cache_directory, | |
| 5537 | .global_cache_directory = global_cache_directory, | |
| 5538 | .root_name = "build", | |
| 5539 | .config = config, | |
| 5540 | .root_mod = root_mod, | |
| 5541 | .main_mod = build_mod, | |
| 5542 | .emit_bin = emit_bin, | |
| 5543 | .emit_h = null, | |
| 5544 | .self_exe_path = self_exe_path, | |
| 5545 | .thread_pool = &thread_pool, | |
| 5546 | .verbose_cc = verbose_cc, | |
| 5547 | .verbose_link = verbose_link, | |
| 5548 | .verbose_air = verbose_air, | |
| 5549 | .verbose_intern_pool = verbose_intern_pool, | |
| 5550 | .verbose_generic_instances = verbose_generic_instances, | |
| 5551 | .verbose_llvm_ir = verbose_llvm_ir, | |
| 5552 | .verbose_llvm_bc = verbose_llvm_bc, | |
| 5553 | .verbose_cimport = verbose_cimport, | |
| 5554 | .verbose_llvm_cpu_features = verbose_llvm_cpu_features, | |
| 5555 | .cache_mode = .whole, | |
| 5556 | .reference_trace = reference_trace, | |
| 5557 | .debug_compile_errors = debug_compile_errors, | |
| 5558 | }) catch |err| { | |
| 5559 | fatal("unable to create compilation: {s}", .{@errorName(err)}); | |
| 5560 | }; | |
| 5561 | defer comp.destroy(); | |
| 5611 | const comp = Compilation.create(gpa, arena, .{ | |
| 5612 | .zig_lib_directory = zig_lib_directory, | |
| 5613 | .local_cache_directory = local_cache_directory, | |
| 5614 | .global_cache_directory = global_cache_directory, | |
| 5615 | .root_name = "build", | |
| 5616 | .config = config, | |
| 5617 | .root_mod = root_mod, | |
| 5618 | .main_mod = build_mod, | |
| 5619 | .emit_bin = emit_bin, | |
| 5620 | .emit_h = null, | |
| 5621 | .self_exe_path = self_exe_path, | |
| 5622 | .thread_pool = &thread_pool, | |
| 5623 | .verbose_cc = verbose_cc, | |
| 5624 | .verbose_link = verbose_link, | |
| 5625 | .verbose_air = verbose_air, | |
| 5626 | .verbose_intern_pool = verbose_intern_pool, | |
| 5627 | .verbose_generic_instances = verbose_generic_instances, | |
| 5628 | .verbose_llvm_ir = verbose_llvm_ir, | |
| 5629 | .verbose_llvm_bc = verbose_llvm_bc, | |
| 5630 | .verbose_cimport = verbose_cimport, | |
| 5631 | .verbose_llvm_cpu_features = verbose_llvm_cpu_features, | |
| 5632 | .cache_mode = .whole, | |
| 5633 | .reference_trace = reference_trace, | |
| 5634 | .debug_compile_errors = debug_compile_errors, | |
| 5635 | }) catch |err| { | |
| 5636 | fatal("unable to create compilation: {s}", .{@errorName(err)}); | |
| 5637 | }; | |
| 5638 | defer comp.destroy(); | |
| 5562 | 5639 | |
| 5563 | updateModule(comp, color) catch |err| switch (err) { | |
| 5564 | error.SemanticAnalyzeFail => process.exit(2), | |
| 5565 | else => |e| return e, | |
| 5566 | }; | |
| 5640 | updateModule(comp, color) catch |err| switch (err) { | |
| 5641 | error.SemanticAnalyzeFail => process.exit(2), | |
| 5642 | else => |e| return e, | |
| 5643 | }; | |
| 5567 | 5644 | |
| 5568 | // Since incremental compilation isn't done yet, we use cache_mode = whole | |
| 5569 | // above, and thus the output file is already closed. | |
| 5570 | //try comp.makeBinFileExecutable(); | |
| 5571 | child_argv.items[argv_index_exe] = | |
| 5572 | try local_cache_directory.join(arena, &.{comp.cache_use.whole.bin_sub_path.?}); | |
| 5645 | // Since incremental compilation isn't done yet, we use cache_mode = whole | |
| 5646 | // above, and thus the output file is already closed. | |
| 5647 | //try comp.makeBinFileExecutable(); | |
| 5648 | child_argv.items[argv_index_exe] = | |
| 5649 | try local_cache_directory.join(arena, &.{comp.cache_use.whole.bin_sub_path.?}); | |
| 5650 | } | |
| 5573 | 5651 | |
| 5574 | break :argv child_argv.items; | |
| 5575 | }; | |
| 5652 | if (process.can_spawn) { | |
| 5653 | var child = std.ChildProcess.init(child_argv.items, gpa); | |
| 5654 | child.stdin_behavior = .Inherit; | |
| 5655 | child.stdout_behavior = .Inherit; | |
| 5656 | child.stderr_behavior = .Inherit; | |
| 5576 | 5657 | |
| 5577 | if (process.can_spawn) { | |
| 5578 | var child = std.ChildProcess.init(child_argv, gpa); | |
| 5579 | child.stdin_behavior = .Inherit; | |
| 5580 | child.stdout_behavior = .Inherit; | |
| 5581 | child.stderr_behavior = .Inherit; | |
| 5658 | const term = try child.spawnAndWait(); | |
| 5659 | switch (term) { | |
| 5660 | .Exited => |code| { | |
| 5661 | if (code == 0) return cleanExit(); | |
| 5662 | // Indicates that the build runner has reported compile errors | |
| 5663 | // and this parent process does not need to report any further | |
| 5664 | // diagnostics. | |
| 5665 | if (code == 2) process.exit(2); | |
| 5666 | ||
| 5667 | if (code == 3) { | |
| 5668 | if (build_options.only_core_functionality) process.exit(3); | |
| 5669 | // Indicates the configure phase failed due to missing lazy | |
| 5670 | // dependencies and stdout contains the hashes of the ones | |
| 5671 | // that are missing. | |
| 5672 | const s = fs.path.sep_str; | |
| 5673 | const tmp_sub_path = "tmp" ++ s ++ results_tmp_file_nonce; | |
| 5674 | const stdout = local_cache_directory.handle.readFileAlloc(arena, tmp_sub_path, 50 * 1024 * 1024) catch |err| { | |
| 5675 | fatal("unable to read results of configure phase from '{}{s}': {s}", .{ | |
| 5676 | local_cache_directory, tmp_sub_path, @errorName(err), | |
| 5677 | }); | |
| 5678 | }; | |
| 5679 | local_cache_directory.handle.deleteFile(tmp_sub_path) catch {}; | |
| 5680 | ||
| 5681 | var it = mem.splitScalar(u8, stdout, '\n'); | |
| 5682 | var any_errors = false; | |
| 5683 | while (it.next()) |hash| { | |
| 5684 | if (hash.len == 0) continue; | |
| 5685 | const digest_len = @typeInfo(Package.Manifest.MultiHashHexDigest).Array.len; | |
| 5686 | if (hash.len != digest_len) { | |
| 5687 | std.log.err("invalid digest (length {d} instead of {d}): '{s}'", .{ | |
| 5688 | hash.len, digest_len, hash, | |
| 5689 | }); | |
| 5690 | any_errors = true; | |
| 5691 | continue; | |
| 5692 | } | |
| 5693 | try unlazy_set.put(arena, hash[0..digest_len].*, {}); | |
| 5694 | } | |
| 5695 | if (any_errors) process.exit(3); | |
| 5696 | if (system_pkg_dir_path) |p| { | |
| 5697 | // In this mode, the system needs to provide these packages; they | |
| 5698 | // cannot be fetched by Zig. | |
| 5699 | for (unlazy_set.keys()) |hash| { | |
| 5700 | std.log.err("lazy dependency package not found: {s}" ++ s ++ "{s}", .{ | |
| 5701 | p, hash, | |
| 5702 | }); | |
| 5703 | } | |
| 5704 | std.log.info("remote package fetching disabled due to --system mode", .{}); | |
| 5705 | std.log.info("dependencies might be avoidable depending on build configuration", .{}); | |
| 5706 | process.exit(3); | |
| 5707 | } | |
| 5708 | continue; | |
| 5709 | } | |
| 5582 | 5710 | |
| 5583 | const term = try child.spawnAndWait(); | |
| 5584 | switch (term) { | |
| 5585 | .Exited => |code| { | |
| 5586 | if (code == 0) return cleanExit(); | |
| 5587 | // Indicates that the build runner has reported compile errors | |
| 5588 | // and this parent process does not need to report any further | |
| 5589 | // diagnostics. | |
| 5590 | if (code == 2) process.exit(2); | |
| 5591 | ||
| 5592 | const cmd = try std.mem.join(arena, " ", child_argv); | |
| 5593 | fatal("the following build command failed with exit code {d}:\n{s}", .{ code, cmd }); | |
| 5594 | }, | |
| 5595 | else => { | |
| 5596 | const cmd = try std.mem.join(arena, " ", child_argv); | |
| 5597 | fatal("the following build command crashed:\n{s}", .{cmd}); | |
| 5598 | }, | |
| 5711 | const cmd = try std.mem.join(arena, " ", child_argv.items); | |
| 5712 | fatal("the following build command failed with exit code {d}:\n{s}", .{ code, cmd }); | |
| 5713 | }, | |
| 5714 | else => { | |
| 5715 | const cmd = try std.mem.join(arena, " ", child_argv.items); | |
| 5716 | fatal("the following build command crashed:\n{s}", .{cmd}); | |
| 5717 | }, | |
| 5718 | } | |
| 5719 | } else { | |
| 5720 | const cmd = try std.mem.join(arena, " ", child_argv.items); | |
| 5721 | fatal("the following command cannot be executed ({s} does not support spawning a child process):\n{s}", .{ @tagName(builtin.os.tag), cmd }); | |
| 5599 | 5722 | } |
| 5600 | } else { | |
| 5601 | const cmd = try std.mem.join(arena, " ", child_argv); | |
| 5602 | fatal("the following command cannot be executed ({s} does not support spawning a child process):\n{s}", .{ @tagName(builtin.os.tag), cmd }); | |
| 5603 | 5723 | } |
| 5604 | 5724 | } |
| 5605 | 5725 | |
| ... | ... | @@ -7343,6 +7463,7 @@ fn cmdFetch( |
| 7343 | 7463 | .thread_pool = &thread_pool, |
| 7344 | 7464 | .global_cache = global_cache_directory, |
| 7345 | 7465 | .recursive = false, |
| 7466 | .read_only = false, | |
| 7346 | 7467 | .debug_hash = debug_hash, |
| 7347 | 7468 | .work_around_btrfs_bug = work_around_btrfs_bug, |
| 7348 | 7469 | }; |
| ... | ... | @@ -7353,6 +7474,8 @@ fn cmdFetch( |
| 7353 | 7474 | .location = .{ .path_or_url = path_or_url }, |
| 7354 | 7475 | .location_tok = 0, |
| 7355 | 7476 | .hash_tok = 0, |
| 7477 | .name_tok = 0, | |
| 7478 | .lazy_status = .eager, | |
| 7356 | 7479 | .parent_package_root = undefined, |
| 7357 | 7480 | .parent_manifest_ast = null, |
| 7358 | 7481 | .prog_node = root_prog_node, |
test/src/Cases.zig+2-2| ... | ... | @@ -562,7 +562,7 @@ pub fn lowerToBuildSteps( |
| 562 | 562 | run.setName(incr_case.base_path); |
| 563 | 563 | run.addArgs(&.{ |
| 564 | 564 | case_base_path_with_dir, |
| 565 | b.zig_exe, | |
| 565 | b.graph.zig_exe, | |
| 566 | 566 | }); |
| 567 | 567 | run.expectStdOutEqual(""); |
| 568 | 568 | parent_step.dependOn(&run.step); |
| ... | ... | @@ -653,7 +653,7 @@ pub fn lowerToBuildSteps( |
| 653 | 653 | break :no_exec; |
| 654 | 654 | } |
| 655 | 655 | const run_c = b.addSystemCommand(&.{ |
| 656 | b.zig_exe, | |
| 656 | b.graph.zig_exe, | |
| 657 | 657 | "run", |
| 658 | 658 | "-cflags", |
| 659 | 659 | "-Ilib", |
test/tests.zig+11-11| ... | ... | @@ -796,7 +796,7 @@ pub fn addCliTests(b: *std.Build) *Step { |
| 796 | 796 | { |
| 797 | 797 | // Test `zig init`. |
| 798 | 798 | const tmp_path = b.makeTempPath(); |
| 799 | const init_exe = b.addSystemCommand(&.{ b.zig_exe, "init" }); | |
| 799 | const init_exe = b.addSystemCommand(&.{ b.graph.zig_exe, "init" }); | |
| 800 | 800 | init_exe.setCwd(.{ .cwd_relative = tmp_path }); |
| 801 | 801 | init_exe.setName("zig init"); |
| 802 | 802 | init_exe.expectStdOutEqual(""); |
| ... | ... | @@ -810,20 +810,20 @@ pub fn addCliTests(b: *std.Build) *Step { |
| 810 | 810 | const bad_out_arg = "-femit-bin=does" ++ s ++ "not" ++ s ++ "exist" ++ s ++ "foo.exe"; |
| 811 | 811 | const ok_src_arg = "src" ++ s ++ "main.zig"; |
| 812 | 812 | const expected = "error: unable to open output directory 'does" ++ s ++ "not" ++ s ++ "exist': FileNotFound\n"; |
| 813 | const run_bad = b.addSystemCommand(&.{ b.zig_exe, "build-exe", ok_src_arg, bad_out_arg }); | |
| 813 | const run_bad = b.addSystemCommand(&.{ b.graph.zig_exe, "build-exe", ok_src_arg, bad_out_arg }); | |
| 814 | 814 | run_bad.setName("zig build-exe error message for bad -femit-bin arg"); |
| 815 | 815 | run_bad.expectExitCode(1); |
| 816 | 816 | run_bad.expectStdErrEqual(expected); |
| 817 | 817 | run_bad.expectStdOutEqual(""); |
| 818 | 818 | run_bad.step.dependOn(&init_exe.step); |
| 819 | 819 | |
| 820 | const run_test = b.addSystemCommand(&.{ b.zig_exe, "build", "test" }); | |
| 820 | const run_test = b.addSystemCommand(&.{ b.graph.zig_exe, "build", "test" }); | |
| 821 | 821 | run_test.setCwd(.{ .cwd_relative = tmp_path }); |
| 822 | 822 | run_test.setName("zig build test"); |
| 823 | 823 | run_test.expectStdOutEqual(""); |
| 824 | 824 | run_test.step.dependOn(&init_exe.step); |
| 825 | 825 | |
| 826 | const run_run = b.addSystemCommand(&.{ b.zig_exe, "build", "run" }); | |
| 826 | const run_run = b.addSystemCommand(&.{ b.graph.zig_exe, "build", "run" }); | |
| 827 | 827 | run_run.setCwd(.{ .cwd_relative = tmp_path }); |
| 828 | 828 | run_run.setName("zig build run"); |
| 829 | 829 | run_run.expectStdOutEqual("Run `zig build test` to run the tests.\n"); |
| ... | ... | @@ -857,7 +857,7 @@ pub fn addCliTests(b: *std.Build) *Step { |
| 857 | 857 | |
| 858 | 858 | // This is intended to be the exact CLI usage used by godbolt.org. |
| 859 | 859 | const run = b.addSystemCommand(&.{ |
| 860 | b.zig_exe, "build-obj", | |
| 860 | b.graph.zig_exe, "build-obj", | |
| 861 | 861 | "--cache-dir", tmp_path, |
| 862 | 862 | "--name", "example", |
| 863 | 863 | "-fno-emit-bin", "-fno-emit-h", |
| ... | ... | @@ -900,7 +900,7 @@ pub fn addCliTests(b: *std.Build) *Step { |
| 900 | 900 | subdir.writeFile("fmt3.zig", unformatted_code) catch @panic("unhandled"); |
| 901 | 901 | |
| 902 | 902 | // Test zig fmt affecting only the appropriate files. |
| 903 | const run1 = b.addSystemCommand(&.{ b.zig_exe, "fmt", "fmt1.zig" }); | |
| 903 | const run1 = b.addSystemCommand(&.{ b.graph.zig_exe, "fmt", "fmt1.zig" }); | |
| 904 | 904 | run1.setName("run zig fmt one file"); |
| 905 | 905 | run1.setCwd(.{ .cwd_relative = tmp_path }); |
| 906 | 906 | run1.has_side_effects = true; |
| ... | ... | @@ -908,7 +908,7 @@ pub fn addCliTests(b: *std.Build) *Step { |
| 908 | 908 | run1.expectStdOutEqual("fmt1.zig\n"); |
| 909 | 909 | |
| 910 | 910 | // Test excluding files and directories from a run |
| 911 | const run2 = b.addSystemCommand(&.{ b.zig_exe, "fmt", "--exclude", "fmt2.zig", "--exclude", "subdir", "." }); | |
| 911 | const run2 = b.addSystemCommand(&.{ b.graph.zig_exe, "fmt", "--exclude", "fmt2.zig", "--exclude", "subdir", "." }); | |
| 912 | 912 | run2.setName("run zig fmt on directory with exclusions"); |
| 913 | 913 | run2.setCwd(.{ .cwd_relative = tmp_path }); |
| 914 | 914 | run2.has_side_effects = true; |
| ... | ... | @@ -916,7 +916,7 @@ pub fn addCliTests(b: *std.Build) *Step { |
| 916 | 916 | run2.step.dependOn(&run1.step); |
| 917 | 917 | |
| 918 | 918 | // Test excluding non-existent file |
| 919 | const run3 = b.addSystemCommand(&.{ b.zig_exe, "fmt", "--exclude", "fmt2.zig", "--exclude", "nonexistent.zig", "." }); | |
| 919 | const run3 = b.addSystemCommand(&.{ b.graph.zig_exe, "fmt", "--exclude", "fmt2.zig", "--exclude", "nonexistent.zig", "." }); | |
| 920 | 920 | run3.setName("run zig fmt on directory with non-existent exclusion"); |
| 921 | 921 | run3.setCwd(.{ .cwd_relative = tmp_path }); |
| 922 | 922 | run3.has_side_effects = true; |
| ... | ... | @@ -924,7 +924,7 @@ pub fn addCliTests(b: *std.Build) *Step { |
| 924 | 924 | run3.step.dependOn(&run2.step); |
| 925 | 925 | |
| 926 | 926 | // running it on the dir, only the new file should be changed |
| 927 | const run4 = b.addSystemCommand(&.{ b.zig_exe, "fmt", "." }); | |
| 927 | const run4 = b.addSystemCommand(&.{ b.graph.zig_exe, "fmt", "." }); | |
| 928 | 928 | run4.setName("run zig fmt the directory"); |
| 929 | 929 | run4.setCwd(.{ .cwd_relative = tmp_path }); |
| 930 | 930 | run4.has_side_effects = true; |
| ... | ... | @@ -932,7 +932,7 @@ pub fn addCliTests(b: *std.Build) *Step { |
| 932 | 932 | run4.step.dependOn(&run3.step); |
| 933 | 933 | |
| 934 | 934 | // both files have been formatted, nothing should change now |
| 935 | const run5 = b.addSystemCommand(&.{ b.zig_exe, "fmt", "." }); | |
| 935 | const run5 = b.addSystemCommand(&.{ b.graph.zig_exe, "fmt", "." }); | |
| 936 | 936 | run5.setName("run zig fmt with nothing to do"); |
| 937 | 937 | run5.setCwd(.{ .cwd_relative = tmp_path }); |
| 938 | 938 | run5.has_side_effects = true; |
| ... | ... | @@ -946,7 +946,7 @@ pub fn addCliTests(b: *std.Build) *Step { |
| 946 | 946 | write6.step.dependOn(&run5.step); |
| 947 | 947 | |
| 948 | 948 | // Test `zig fmt` handling UTF-16 decoding. |
| 949 | const run6 = b.addSystemCommand(&.{ b.zig_exe, "fmt", "." }); | |
| 949 | const run6 = b.addSystemCommand(&.{ b.graph.zig_exe, "fmt", "." }); | |
| 950 | 950 | run6.setName("run zig fmt convert UTF-16 to UTF-8"); |
| 951 | 951 | run6.setCwd(.{ .cwd_relative = tmp_path }); |
| 952 | 952 | run6.has_side_effects = true; |