| ... | ... | @@ -3166,6 +3166,8 @@ fn buildOutputType( |
| 3166 | 3166 | else => process.executablePathAlloc(io, arena) catch |err| fatal("unable to find zig self exe path: {t}", .{err}), |
| 3167 | 3167 | }; |
| 3168 | 3168 | |
| 3169 | const cwd_path = try introspect.getResolvedCwd(io, arena); |
| 3170 | |
| 3169 | 3171 | // This `init` calls `fatal` on error. |
| 3170 | 3172 | var dirs: Compilation.Directories = .init( |
| 3171 | 3173 | arena, |
| ... | ... | @@ -3182,6 +3184,7 @@ fn buildOutputType( |
| 3182 | 3184 | preopens, |
| 3183 | 3185 | self_exe_path, |
| 3184 | 3186 | environ_map, |
| 3187 | cwd_path, |
| 3185 | 3188 | ); |
| 3186 | 3189 | defer dirs.deinit(io); |
| 3187 | 3190 | |
| ... | ... | @@ -4936,16 +4939,21 @@ test sanitizeExampleName { |
| 4936 | 4939 | try std.testing.expectEqualStrings("test_project", try sanitizeExampleName(arena, "test project")); |
| 4937 | 4940 | } |
| 4938 | 4941 | |
| 4939 | | fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8, environ_map: *process.Environ.Map) !void { |
| 4940 | | dev.check(.build_command); |
| 4941 | | |
| 4942 | fn cmdBuild( |
| 4943 | gpa: Allocator, |
| 4944 | arena: Allocator, |
| 4945 | io: Io, |
| 4946 | args: []const []const u8, |
| 4947 | environ_map: *process.Environ.Map, |
| 4948 | ) !void { |
| 4942 | 4949 | var build_file: ?[]const u8 = null; |
| 4943 | 4950 | var override_lib_dir: ?[]const u8 = EnvVar.ZIG_LIB_DIR.get(environ_map); |
| 4944 | 4951 | var override_global_cache_dir: ?[]const u8 = EnvVar.ZIG_GLOBAL_CACHE_DIR.get(environ_map); |
| 4945 | 4952 | var override_local_cache_dir: ?[]const u8 = EnvVar.ZIG_LOCAL_CACHE_DIR.get(environ_map); |
| 4946 | 4953 | var override_pkg_dir: ?[]const u8 = EnvVar.ZIG_LOCAL_PKG_DIR.get(environ_map); |
| 4947 | | var override_build_runner: ?[]const u8 = EnvVar.ZIG_BUILD_RUNNER.get(environ_map); |
| 4948 | | var child_argv: std.ArrayList([]const u8) = .empty; |
| 4954 | var override_make_runner: ?[]const u8 = EnvVar.ZIG_BUILD_RUNNER.get(environ_map); |
| 4955 | var configure_argv: std.ArrayList([]const u8) = .empty; |
| 4956 | var make_argv: std.ArrayList([]const u8) = .empty; |
| 4949 | 4957 | var forks: std.ArrayList(Fork) = .empty; |
| 4950 | 4958 | var reference_trace: ?u32 = null; |
| 4951 | 4959 | var debug_compile_errors = false; |
| ... | ... | @@ -4965,46 +4973,32 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8, |
| 4965 | 4973 | var debug_target: ?[]const u8 = null; |
| 4966 | 4974 | var debug_libc_paths_file: ?[]const u8 = null; |
| 4967 | 4975 | |
| 4968 | | const argv_index_exe = child_argv.items.len; |
| 4969 | | _ = try child_argv.addOne(arena); |
| 4976 | const argv_index_exe = configure_argv.items.len; |
| 4977 | _ = try configure_argv.addOne(arena); |
| 4970 | 4978 | |
| 4971 | 4979 | const self_exe_path = try process.executablePathAlloc(io, arena); |
| 4972 | | try child_argv.append(arena, self_exe_path); |
| 4980 | try configure_argv.append(arena, self_exe_path); |
| 4973 | 4981 | |
| 4974 | | const argv_index_zig_lib_dir = child_argv.items.len; |
| 4975 | | _ = try child_argv.addOne(arena); |
| 4982 | const argv_index_zig_lib_dir = configure_argv.items.len; |
| 4983 | _ = try configure_argv.addOne(arena); |
| 4976 | 4984 | |
| 4977 | | const argv_index_build_file = child_argv.items.len; |
| 4978 | | _ = try child_argv.addOne(arena); |
| 4985 | const argv_index_build_file = configure_argv.items.len; |
| 4986 | _ = try configure_argv.addOne(arena); |
| 4979 | 4987 | |
| 4980 | | const argv_index_cache_dir = child_argv.items.len; |
| 4981 | | _ = try child_argv.addOne(arena); |
| 4988 | const argv_index_cache_dir = configure_argv.items.len; |
| 4989 | _ = try configure_argv.addOne(arena); |
| 4982 | 4990 | |
| 4983 | | const argv_index_global_cache_dir = child_argv.items.len; |
| 4984 | | _ = try child_argv.addOne(arena); |
| 4991 | const argv_index_global_cache_dir = configure_argv.items.len; |
| 4992 | _ = try configure_argv.addOne(arena); |
| 4985 | 4993 | |
| 4986 | | try child_argv.appendSlice(arena, &.{ |
| 4994 | try configure_argv.appendSlice(arena, &.{ |
| 4987 | 4995 | "--seed", |
| 4988 | 4996 | try std.fmt.allocPrint(arena, "0x{x}", .{randInt(io, u32)}), |
| 4989 | 4997 | }); |
| 4990 | | const argv_index_seed = child_argv.items.len - 1; |
| 4991 | | |
| 4992 | | // This parent process needs a way to obtain results from the configuration |
| 4993 | | // phase of the child process. In the future, the make phase will be |
| 4994 | | // executed in a separate process than the configure phase, and we can then |
| 4995 | | // use stdout from the configuration phase for this purpose. |
| 4996 | | // |
| 4997 | | // However, currently, both phases are in the same process, and Run Step |
| 4998 | | // provides API for making the runned subprocesses inherit stdout and stderr |
| 4999 | | // which means these streams are not available for passing metadata back |
| 5000 | | // to the parent. |
| 5001 | | // |
| 5002 | | // Until make and configure phases are separated into different processes, |
| 5003 | | // the strategy is to choose a temporary file name ahead of time, and then |
| 5004 | | // read this file in the parent to obtain the results, in the case the child |
| 5005 | | // exits with code 3. |
| 5006 | | const results_tmp_file_nonce = std.fmt.hex(randInt(io, u64)); |
| 5007 | | try child_argv.append(arena, "-Z" ++ results_tmp_file_nonce); |
| 4998 | const argv_index_seed = configure_argv.items.len - 1; |
| 4999 | |
| 5000 | const argv_index_configuration_file = make_argv.items.len; |
| 5001 | _ = try make_argv.addOne(arena); |
| 5008 | 5002 | |
| 5009 | 5003 | var color: Color = .auto; |
| 5010 | 5004 | var n_jobs: ?u32 = null; |
| ... | ... | @@ -5027,7 +5021,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8, |
| 5027 | 5021 | } else if (mem.eql(u8, arg, "--build-runner")) { |
| 5028 | 5022 | if (i + 1 >= args.len) fatal("expected argument after '{s}'", .{arg}); |
| 5029 | 5023 | i += 1; |
| 5030 | | override_build_runner = args[i]; |
| 5024 | override_make_runner = args[i]; |
| 5031 | 5025 | continue; |
| 5032 | 5026 | } else if (mem.eql(u8, arg, "--cache-dir")) { |
| 5033 | 5027 | if (i + 1 >= args.len) fatal("expected argument after '{s}'", .{arg}); |
| ... | ... | @@ -5071,7 +5065,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8, |
| 5071 | 5065 | if (i + 1 >= args.len) fatal("expected argument after '{s}'", .{arg}); |
| 5072 | 5066 | i += 1; |
| 5073 | 5067 | system_pkg_dir_path = args[i]; |
| 5074 | | try child_argv.append(arena, "--system"); |
| 5068 | try configure_argv.append(arena, "--system"); |
| 5075 | 5069 | continue; |
| 5076 | 5070 | } else if (mem.cutPrefix(u8, arg, "-freference-trace=")) |num| { |
| 5077 | 5071 | reference_trace = std.fmt.parseUnsigned(u32, num, 10) catch |err| { |
| ... | ... | @@ -5081,7 +5075,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8, |
| 5081 | 5075 | reference_trace = null; |
| 5082 | 5076 | } else if (mem.eql(u8, arg, "--debug-log")) { |
| 5083 | 5077 | if (i + 1 >= args.len) fatal("expected argument after '{s}'", .{arg}); |
| 5084 | | try child_argv.appendSlice(arena, args[i .. i + 2]); |
| 5078 | try make_argv.appendSlice(arena, args[i .. i + 2]); |
| 5085 | 5079 | i += 1; |
| 5086 | 5080 | try addDebugLog(arena, args[i]); |
| 5087 | 5081 | continue; |
| ... | ... | @@ -5131,7 +5125,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8, |
| 5131 | 5125 | color = std.meta.stringToEnum(Color, args[i]) orelse { |
| 5132 | 5126 | fatal("expected [auto|on|off] after {s}, found '{s}'", .{ arg, args[i] }); |
| 5133 | 5127 | }; |
| 5134 | | try child_argv.appendSlice(arena, &.{ arg, args[i] }); |
| 5128 | try configure_argv.appendSlice(arena, &.{ arg, args[i] }); |
| 5135 | 5129 | continue; |
| 5136 | 5130 | } else if (mem.cutPrefix(u8, arg, "-j")) |str| { |
| 5137 | 5131 | const num = std.fmt.parseUnsigned(u32, str, 10) catch |err| { |
| ... | ... | @@ -5146,25 +5140,85 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8, |
| 5146 | 5140 | } else if (mem.eql(u8, arg, "--seed")) { |
| 5147 | 5141 | if (i + 1 >= args.len) fatal("expected argument after '{s}'", .{arg}); |
| 5148 | 5142 | i += 1; |
| 5149 | | child_argv.items[argv_index_seed] = args[i]; |
| 5143 | configure_argv.items[argv_index_seed] = args[i]; |
| 5150 | 5144 | continue; |
| 5151 | 5145 | } else if (mem.eql(u8, arg, "--")) { |
| 5152 | 5146 | // The rest of the args are supposed to get passed onto |
| 5153 | 5147 | // build runner's `build.args` |
| 5154 | | try child_argv.appendSlice(arena, args[i..]); |
| 5148 | try configure_argv.appendSlice(arena, args[i..]); |
| 5155 | 5149 | break; |
| 5156 | 5150 | } |
| 5157 | 5151 | } |
| 5158 | | try child_argv.append(arena, arg); |
| 5152 | try make_argv.append(arena, arg); |
| 5159 | 5153 | } |
| 5160 | 5154 | } |
| 5161 | 5155 | |
| 5162 | 5156 | const root_prog_node = std.Progress.start(io, .{ |
| 5163 | 5157 | .disable_printing = (color == .off), |
| 5164 | | .root_name = "Compile Build Script", |
| 5158 | .root_name = "", |
| 5165 | 5159 | }); |
| 5166 | 5160 | defer root_prog_node.end(); |
| 5167 | 5161 | |
| 5162 | process.raiseFileDescriptorLimit(); |
| 5163 | |
| 5164 | const cwd_path = introspect.getResolvedCwd(io, arena) catch |err| |
| 5165 | fatal("failed to get current directory path: {t}", .{err}); |
| 5166 | |
| 5167 | const build_root = try findBuildRoot(arena, io, .{ |
| 5168 | .cwd_path = cwd_path, |
| 5169 | .build_file = build_file, |
| 5170 | }); |
| 5171 | |
| 5172 | // This `init` calls `fatal` on error. |
| 5173 | var dirs: Compilation.Directories = .init( |
| 5174 | arena, |
| 5175 | io, |
| 5176 | override_lib_dir, |
| 5177 | override_global_cache_dir, |
| 5178 | .{ .override = path: { |
| 5179 | if (override_local_cache_dir) |d| break :path d; |
| 5180 | break :path try build_root.directory.join(arena, &.{introspect.default_local_zig_cache_basename}); |
| 5181 | } }, |
| 5182 | .empty, |
| 5183 | self_exe_path, |
| 5184 | environ_map, |
| 5185 | cwd_path, |
| 5186 | ); |
| 5187 | defer dirs.deinit(io); |
| 5188 | |
| 5189 | const thread_limit = @min( |
| 5190 | @max(n_jobs orelse std.Thread.getCpuCount() catch 1, 1), |
| 5191 | std.math.maxInt(Zcu.PerThread.IdBacking), |
| 5192 | ); |
| 5193 | try setThreadLimit(arena, thread_limit); |
| 5194 | |
| 5195 | // Kick off an optimized compilation of the make runner. |
| 5196 | var make_runner_task = io.async(compileMakeRunner, .{ io, .{ |
| 5197 | .dirs = &dirs, |
| 5198 | .optimize = .ReleaseSafe, |
| 5199 | .parent_prog_node = root_prog_node, |
| 5200 | } }); |
| 5201 | defer if (make_runner_task.cancel(io)) |mr| mr.deinit(io) else |_| {}; |
| 5202 | |
| 5203 | // Cache lookup for configure options. If we get a match, we can skip |
| 5204 | // execution of the configure script. If not, we get the file path to pass |
| 5205 | // to the configure process. |
| 5206 | var local_cache: Cache = .{ |
| 5207 | .gpa = gpa, |
| 5208 | .io = io, |
| 5209 | .manifest_dir = try dirs.local_cache.handle.createDirPathOpen(io, "h", .{}), |
| 5210 | .cwd = cwd_path, |
| 5211 | }; |
| 5212 | local_cache.addPrefix(.{ .path = null, .handle = Io.Dir.cwd() }); |
| 5213 | local_cache.addPrefix(dirs.zig_lib); |
| 5214 | local_cache.addPrefix(dirs.local_cache); |
| 5215 | local_cache.addPrefix(dirs.global_cache); |
| 5216 | defer local_cache.manifest_dir.close(io); |
| 5217 | |
| 5218 | var config_man = local_cache.obtain(); |
| 5219 | defer config_man.deinit(); |
| 5220 | config_man.hash.addBytes(build_options.version); |
| 5221 | |
| 5168 | 5222 | // Normally the build runner is compiled for the host target but here is |
| 5169 | 5223 | // some code to help when debugging edits to the build runner so that you |
| 5170 | 5224 | // can make sure it compiles successfully on other targets. |
| ... | ... | @@ -5174,6 +5228,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8, |
| 5174 | 5228 | const target_query = try std.Target.Query.parse(.{ |
| 5175 | 5229 | .arch_os_abi = triple, |
| 5176 | 5230 | }); |
| 5231 | config_man.hash.addBytes(triple); |
| 5177 | 5232 | break :t .{ |
| 5178 | 5233 | .result = std.zig.resolveTargetQueryOrFatal(io, target_query), |
| 5179 | 5234 | .is_native_os = false, |
| ... | ... | @@ -5189,49 +5244,21 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8, |
| 5189 | 5244 | .is_explicit_dynamic_linker = false, |
| 5190 | 5245 | }; |
| 5191 | 5246 | }; |
| 5247 | |
| 5192 | 5248 | // Likewise, `--debug-libc` allows overriding the libc installation. |
| 5193 | 5249 | const libc_installation: ?*const LibCInstallation = lci: { |
| 5194 | 5250 | const paths_file = debug_libc_paths_file orelse break :lci null; |
| 5195 | 5251 | if (!build_options.enable_debug_extensions) unreachable; |
| 5196 | 5252 | const lci = try arena.create(LibCInstallation); |
| 5197 | 5253 | lci.* = try .parse(arena, io, paths_file, &resolved_target.result); |
| 5254 | LibCInstallation.addToHash(lci, &config_man.hash, resolved_target.result.abi); |
| 5198 | 5255 | break :lci lci; |
| 5199 | 5256 | }; |
| 5200 | 5257 | |
| 5201 | | process.raiseFileDescriptorLimit(); |
| 5202 | | |
| 5203 | | const cwd_path = try introspect.getResolvedCwd(io, arena); |
| 5204 | | const build_root = try findBuildRoot(arena, io, .{ |
| 5205 | | .cwd_path = cwd_path, |
| 5206 | | .build_file = build_file, |
| 5207 | | }); |
| 5208 | | |
| 5209 | | // This `init` calls `fatal` on error. |
| 5210 | | var dirs: Compilation.Directories = .init( |
| 5211 | | arena, |
| 5212 | | io, |
| 5213 | | override_lib_dir, |
| 5214 | | override_global_cache_dir, |
| 5215 | | .{ .override = path: { |
| 5216 | | if (override_local_cache_dir) |d| break :path d; |
| 5217 | | break :path try build_root.directory.join(arena, &.{introspect.default_local_zig_cache_basename}); |
| 5218 | | } }, |
| 5219 | | .empty, |
| 5220 | | self_exe_path, |
| 5221 | | environ_map, |
| 5222 | | ); |
| 5223 | | defer dirs.deinit(io); |
| 5224 | | |
| 5225 | | child_argv.items[argv_index_zig_lib_dir] = dirs.zig_lib.path orelse cwd_path; |
| 5226 | | child_argv.items[argv_index_build_file] = build_root.directory.path orelse cwd_path; |
| 5227 | | child_argv.items[argv_index_global_cache_dir] = dirs.global_cache.path orelse cwd_path; |
| 5228 | | child_argv.items[argv_index_cache_dir] = dirs.local_cache.path orelse cwd_path; |
| 5229 | | |
| 5230 | | const thread_limit = @min( |
| 5231 | | @max(n_jobs orelse std.Thread.getCpuCount() catch 1, 1), |
| 5232 | | std.math.maxInt(Zcu.PerThread.IdBacking), |
| 5233 | | ); |
| 5234 | | try setThreadLimit(arena, thread_limit); |
| 5258 | configure_argv.items[argv_index_zig_lib_dir] = dirs.zig_lib.path orelse cwd_path; |
| 5259 | configure_argv.items[argv_index_build_file] = build_root.directory.path orelse cwd_path; |
| 5260 | configure_argv.items[argv_index_global_cache_dir] = dirs.global_cache.path orelse cwd_path; |
| 5261 | configure_argv.items[argv_index_cache_dir] = dirs.local_cache.path orelse cwd_path; |
| 5235 | 5262 | |
| 5236 | 5263 | // Dummy http client that is not actually used when fetch_command is unsupported. |
| 5237 | 5264 | // Prevents bootstrap from depending on a bunch of unnecessary stuff. |
| ... | ... | @@ -5269,11 +5296,11 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8, |
| 5269 | 5296 | |
| 5270 | 5297 | // This loop is re-evaluated when the build script exits with an indication that it |
| 5271 | 5298 | // could not continue due to missing lazy dependencies. |
| 5272 | | while (true) { |
| 5299 | const configuration_path: Path = cp: while (true) { |
| 5273 | 5300 | // We want to release all the locks before executing the child process, so we make a nice |
| 5274 | 5301 | // big block here to ensure the cleanup gets run when we extract out our argv. |
| 5275 | 5302 | { |
| 5276 | | const main_mod_paths: Package.Module.CreateOptions.Paths = if (override_build_runner) |runner| .{ |
| 5303 | const main_mod_paths: Package.Module.CreateOptions.Paths = if (override_make_runner) |runner| .{ |
| 5277 | 5304 | .root = try .fromUnresolved(arena, dirs, &.{fs.path.dirname(runner) orelse "."}), |
| 5278 | 5305 | .root_src_path = fs.path.basename(runner), |
| 5279 | 5306 | } else .{ |
| ... | ... | @@ -5497,6 +5524,9 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8, |
| 5497 | 5524 | config, |
| 5498 | 5525 | ); |
| 5499 | 5526 | |
| 5527 | const compile_prog_node = root_prog_node.start("Compile Configure Script", 0); |
| 5528 | defer compile_prog_node.end(); |
| 5529 | |
| 5500 | 5530 | try root_mod.deps.put(arena, "@build", build_mod); |
| 5501 | 5531 | |
| 5502 | 5532 | var create_diag: Compilation.CreateDiagnostic = undefined; |
| ... | ... | @@ -5528,7 +5558,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8, |
| 5528 | 5558 | }; |
| 5529 | 5559 | defer comp.destroy(); |
| 5530 | 5560 | |
| 5531 | | updateModule(comp, color, root_prog_node) catch |err| switch (err) { |
| 5561 | updateModule(comp, color, compile_prog_node) catch |err| switch (err) { |
| 5532 | 5562 | error.CompileErrorsReported => process.exit(2), |
| 5533 | 5563 | else => |e| return e, |
| 5534 | 5564 | }; |
| ... | ... | @@ -5536,52 +5566,74 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8, |
| 5536 | 5566 | // Since incremental compilation isn't done yet, we use cache_mode = whole |
| 5537 | 5567 | // above, and thus the output file is already closed. |
| 5538 | 5568 | //try comp.makeBinFileExecutable(); |
| 5539 | | child_argv.items[argv_index_exe] = try dirs.local_cache.join(arena, &.{ |
| 5540 | | "o", |
| 5541 | | &Cache.binToHex(comp.digest.?), |
| 5542 | | comp.emit_bin.?, |
| 5543 | | }); |
| 5569 | const hex_digest: []const u8 = &Cache.binToHex(comp.digest.?); |
| 5570 | const exe_path: Path = .{ |
| 5571 | .root_dir = dirs.local_cache, |
| 5572 | .sub_path = try std.fmt.allocPrint(arena, "o/{s}/{s}", .{ hex_digest, comp.emit_bin.? }), |
| 5573 | }; |
| 5574 | _ = try config_man.addFilePath(exe_path, null); |
| 5575 | configure_argv.items[argv_index_exe] = try exe_path.toString(arena); |
| 5576 | |
| 5577 | if (try config_man.hit()) { |
| 5578 | const digest = config_man.final(); |
| 5579 | break :cp .{ |
| 5580 | .root_dir = dirs.local_cache, |
| 5581 | .sub_path = try std.fmt.allocPrint(arena, "o/{s}", .{&digest}), |
| 5582 | }; |
| 5583 | } |
| 5544 | 5584 | } |
| 5545 | 5585 | |
| 5546 | 5586 | if (!process.can_spawn) { |
| 5547 | | const cmd = try std.mem.join(arena, " ", child_argv.items); |
| 5587 | const cmd = try std.mem.join(arena, " ", configure_argv.items); |
| 5548 | 5588 | fatal("the following command cannot be executed ({t} does not support spawning a child process):\n{s}", .{ native_os, cmd }); |
| 5549 | 5589 | } |
| 5590 | |
| 5591 | const rand_int = randInt(io, u64); |
| 5592 | const tmp_dir_sub_path = "tmp" ++ fs.path.sep_str ++ std.fmt.hex(rand_int); |
| 5593 | const config_tmp_path: Path = .{ |
| 5594 | .root_dir = dirs.local_cache, |
| 5595 | .sub_path = tmp_dir_sub_path, |
| 5596 | }; |
| 5597 | const config_tmp_file: Io.File = try config_tmp_path.root_dir.handle.createFile( |
| 5598 | io, |
| 5599 | config_tmp_path.sub_path, |
| 5600 | .{ .read = true, .exclusive = true }, |
| 5601 | ); |
| 5602 | defer config_tmp_file.close(io); |
| 5603 | |
| 5550 | 5604 | switch (term: { |
| 5551 | | _ = try io.lockStderr(&.{}, .no_color); |
| 5552 | | defer io.unlockStderr(); |
| 5605 | const child_node = root_prog_node.start("Run Configure Script", 0); |
| 5606 | defer child_node.end(); |
| 5553 | 5607 | var child = std.process.spawn(io, .{ |
| 5554 | | .argv = child_argv.items, |
| 5555 | | }) catch |err| fatal("failed to spawn build runner {s}: {t}", .{ child_argv.items[0], err }); |
| 5608 | .argv = configure_argv.items, |
| 5609 | .stdout = .{ .file = config_tmp_file }, |
| 5610 | .progress_node = child_node, |
| 5611 | }) catch |err| fatal("failed to spawn configure script {s}: {t}", .{ configure_argv.items[0], err }); |
| 5556 | 5612 | defer child.kill(io); |
| 5557 | 5613 | break :term child.wait(io) catch |err| |
| 5558 | | fatal("failed to wait build runner {s}: {t}", .{ child_argv.items[0], err }); |
| 5614 | fatal("failed to wait configure script {s}: {t}", .{ configure_argv.items[0], err }); |
| 5559 | 5615 | }) { |
| 5560 | 5616 | .exited => |code| { |
| 5561 | | if (code == 0) return cleanExit(io); |
| 5562 | | // Indicates that the build runner has reported compile errors |
| 5563 | | // and this parent process does not need to report any further |
| 5564 | | // diagnostics. |
| 5565 | | if (code == 2) process.exit(2); |
| 5566 | | |
| 5567 | | if (code == 3) { |
| 5568 | | if (!dev.env.supports(.fetch_command)) process.exit(3); |
| 5569 | | // Indicates the configure phase failed due to missing lazy |
| 5570 | | // dependencies and stdout contains the hashes of the ones |
| 5571 | | // that are missing. |
| 5572 | | const s = fs.path.sep_str; |
| 5573 | | const tmp_sub_path = "tmp" ++ s ++ results_tmp_file_nonce; |
| 5574 | | const stdout = dirs.local_cache.handle.readFileAlloc(io, tmp_sub_path, arena, .limited(50 * 1024 * 1024)) catch |err| { |
| 5575 | | fatal("unable to read results of configure phase from '{f}{s}': {t}", .{ |
| 5576 | | dirs.local_cache, tmp_sub_path, err, |
| 5577 | | }); |
| 5578 | | }; |
| 5579 | | dirs.local_cache.handle.deleteFile(io, tmp_sub_path) catch {}; |
| 5580 | | |
| 5581 | | var it = mem.splitScalar(u8, stdout, '\n'); |
| 5617 | if (code != 0) { |
| 5618 | // Failure to produce the configuration file. |
| 5619 | const cmd = try std.mem.join(arena, " ", configure_argv.items); |
| 5620 | fatal("the following configure command failed with exit code {d}:\n{s}", .{ code, cmd }); |
| 5621 | } |
| 5622 | // Even though the file is designed to be sent directly to make |
| 5623 | // runner, we must load it now because: |
| 5624 | // * If it contains additional file dependencies, we need to |
| 5625 | // add them to `config_man` before obtaining the final digest. |
| 5626 | // * If it contains a set of lazy packages that need to be |
| 5627 | // fetched, we need to fetch those now and re-run configure. |
| 5628 | var configuration = std.zig.Configuration.load(arena, io, config_tmp_file) catch |err| |
| 5629 | fatal("failed to load configuration file {f}: {t}", .{ config_tmp_path, err }); |
| 5630 | |
| 5631 | if (configuration.unlazy_deps.len != 0) { |
| 5632 | if (!dev.env.supports(.fetch_command)) process.exit(1); |
| 5582 | 5633 | var any_errors = false; |
| 5583 | | while (it.next()) |hash| { |
| 5584 | | if (hash.len == 0) continue; |
| 5634 | for (configuration.unlazy_deps) |hash_string| { |
| 5635 | const hash = hash_string.slice(&configuration); |
| 5636 | assert(hash.len != 0); |
| 5585 | 5637 | if (hash.len > Package.Hash.max_len) { |
| 5586 | 5638 | std.log.err("invalid digest (length {d} exceeds maximum): '{s}'", .{ |
| 5587 | 5639 | hash.len, hash, |
| ... | ... | @@ -5591,10 +5643,11 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8, |
| 5591 | 5643 | } |
| 5592 | 5644 | try unlazy_set.put(arena, .fromSlice(hash), {}); |
| 5593 | 5645 | } |
| 5594 | | if (any_errors) process.exit(3); |
| 5646 | if (any_errors) process.exit(1); |
| 5595 | 5647 | if (system_pkg_dir_path) |p| { |
| 5596 | 5648 | // In this mode, the system needs to provide these packages; they |
| 5597 | 5649 | // cannot be fetched by Zig. |
| 5650 | const s = fs.path.sep_str; |
| 5598 | 5651 | for (unlazy_set.keys()) |*hash| { |
| 5599 | 5652 | std.log.err("lazy dependency package not found: {s}" ++ s ++ "{s}", .{ |
| 5600 | 5653 | p, hash.toSlice(), |
| ... | ... | @@ -5602,28 +5655,115 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8, |
| 5602 | 5655 | } |
| 5603 | 5656 | std.log.info("remote package fetching disabled due to --system mode", .{}); |
| 5604 | 5657 | std.log.info("dependencies might be avoidable depending on build configuration", .{}); |
| 5605 | | process.exit(3); |
| 5658 | process.exit(1); |
| 5606 | 5659 | } |
| 5607 | | continue; |
| 5660 | continue :cp; |
| 5661 | } |
| 5662 | |
| 5663 | for (configuration.path_deps_base, configuration.path_deps_sub) |base, sub| { |
| 5664 | const conf_path: std.zig.Configuration.Path = .{ .base = base, .sub = sub }; |
| 5665 | try config_man.addPathPost(conf_path.toCachePath(&configuration, arena)); |
| 5608 | 5666 | } |
| 5609 | 5667 | |
| 5610 | | const cmd = try std.mem.join(arena, " ", child_argv.items); |
| 5611 | | fatal("the following build command failed with exit code {d}:\n{s}", .{ code, cmd }); |
| 5668 | const digest = config_man.final(); |
| 5669 | const final_path: Path = .{ |
| 5670 | .root_dir = dirs.local_cache, |
| 5671 | .sub_path = try std.fmt.allocPrint(arena, "o/{s}", .{&digest}), |
| 5672 | }; |
| 5673 | Io.Dir.rename( |
| 5674 | config_tmp_path.root_dir.handle, |
| 5675 | config_tmp_path.sub_path, |
| 5676 | final_path.root_dir.handle, |
| 5677 | final_path.sub_path, |
| 5678 | io, |
| 5679 | ) catch |err| { |
| 5680 | fatal("failed to rename configuration file from {f} into {f}: {t}", .{ |
| 5681 | config_tmp_path, final_path, err, |
| 5682 | }); |
| 5683 | }; |
| 5684 | config_man.writeManifest() catch |err| warn("failed to write cache manifest: {t}", .{err}); |
| 5685 | |
| 5686 | break :cp final_path; |
| 5612 | 5687 | }, |
| 5613 | 5688 | .signal => |sig| { |
| 5614 | | const cmd = try std.mem.join(arena, " ", child_argv.items); |
| 5615 | | fatal("the following build command terminated with signal {t}:\n{s}", .{ sig, cmd }); |
| 5689 | const cmd = try std.mem.join(arena, " ", configure_argv.items); |
| 5690 | fatal("the following configure command terminated with signal {t}:\n{s}", .{ sig, cmd }); |
| 5616 | 5691 | }, |
| 5617 | 5692 | .stopped => |sig| { |
| 5618 | | const cmd = try std.mem.join(arena, " ", child_argv.items); |
| 5693 | const cmd = try std.mem.join(arena, " ", configure_argv.items); |
| 5619 | 5694 | fatal("the following build command stopped with signal {t}:\n{s}", .{ sig, cmd }); |
| 5620 | 5695 | }, |
| 5621 | 5696 | .unknown => { |
| 5622 | | const cmd = try std.mem.join(arena, " ", child_argv.items); |
| 5697 | const cmd = try std.mem.join(arena, " ", configure_argv.items); |
| 5623 | 5698 | fatal("the following build command crashed:\n{s}", .{cmd}); |
| 5624 | 5699 | }, |
| 5625 | 5700 | } |
| 5701 | }; |
| 5702 | |
| 5703 | { |
| 5704 | // Release all file system locks just before running the maker process. |
| 5705 | var configuration_lock = config_man.toOwnedLock(); |
| 5706 | defer configuration_lock.release(io); |
| 5707 | |
| 5708 | const make_runner = make_runner_task.await(io) catch |err| |
| 5709 | fatal("failed to compile maker: {t}", .{err}); |
| 5710 | defer make_runner.deinit(io); |
| 5711 | |
| 5712 | make_argv.items[0] = try make_runner.exe_path.toString(arena); |
| 5713 | make_argv.items[argv_index_configuration_file] = try configuration_path.toString(arena); |
| 5714 | } |
| 5715 | |
| 5716 | if (!process.can_spawn) { |
| 5717 | const cmd = try std.mem.join(arena, " ", make_argv.items); |
| 5718 | fatal("the following command cannot be executed ({t} does not support spawning a child process):\n{s}", .{ native_os, cmd }); |
| 5719 | } |
| 5720 | |
| 5721 | switch (term: { |
| 5722 | _ = try io.lockStderr(&.{}, .no_color); |
| 5723 | defer io.unlockStderr(); |
| 5724 | var child = std.process.spawn(io, .{ |
| 5725 | .argv = make_argv.items, |
| 5726 | }) catch |err| fatal("failed to spawn maker {s}: {t}", .{ make_argv.items[0], err }); |
| 5727 | defer child.kill(io); |
| 5728 | break :term child.wait(io) catch |err| |
| 5729 | fatal("failed to wait maker {s}: {t}", .{ make_argv.items[0], err }); |
| 5730 | }) { |
| 5731 | .exited => |code| { |
| 5732 | if (code == 0) return cleanExit(io); |
| 5733 | const cmd = try std.mem.join(arena, " ", configure_argv.items); |
| 5734 | fatal("the following maker command failed with exit code {d}:\n{s}", .{ code, cmd }); |
| 5735 | }, |
| 5736 | .signal => |sig| { |
| 5737 | const cmd = try std.mem.join(arena, " ", configure_argv.items); |
| 5738 | fatal("the following maker command terminated with signal {t}:\n{s}", .{ sig, cmd }); |
| 5739 | }, |
| 5740 | else => { |
| 5741 | const cmd = try std.mem.join(arena, " ", configure_argv.items); |
| 5742 | fatal("the following maker command crashed:\n{s}", .{cmd}); |
| 5743 | }, |
| 5744 | } |
| 5745 | } |
| 5746 | |
| 5747 | const MakeRunner = struct { |
| 5748 | exe_path: Path, |
| 5749 | |
| 5750 | const Options = struct { |
| 5751 | dirs: *Compilation.Directories, |
| 5752 | optimize: std.builtin.OptimizeMode, |
| 5753 | parent_prog_node: std.Progress.Node, |
| 5754 | }; |
| 5755 | |
| 5756 | fn deinit(mr: MakeRunner, io: Io) void { |
| 5757 | _ = mr; |
| 5758 | _ = io; |
| 5759 | @panic("TODO"); |
| 5626 | 5760 | } |
| 5761 | }; |
| 5762 | |
| 5763 | fn compileMakeRunner(io: Io, options: MakeRunner.Options) !MakeRunner { |
| 5764 | _ = io; |
| 5765 | _ = options; |
| 5766 | @panic("TODO"); |
| 5627 | 5767 | } |
| 5628 | 5768 | |
| 5629 | 5769 | const Fork = struct { |
| ... | ... | @@ -5749,6 +5889,8 @@ fn jitCmdInner( |
| 5749 | 5889 | const override_lib_dir: ?[]const u8 = EnvVar.ZIG_LIB_DIR.get(environ_map); |
| 5750 | 5890 | const override_global_cache_dir: ?[]const u8 = EnvVar.ZIG_GLOBAL_CACHE_DIR.get(environ_map); |
| 5751 | 5891 | |
| 5892 | const cwd_path = try introspect.getResolvedCwd(io, arena); |
| 5893 | |
| 5752 | 5894 | // This `init` calls `fatal` on error. |
| 5753 | 5895 | var dirs: Compilation.Directories = .init( |
| 5754 | 5896 | arena, |
| ... | ... | @@ -5759,6 +5901,7 @@ fn jitCmdInner( |
| 5759 | 5901 | preopens, |
| 5760 | 5902 | self_exe_path, |
| 5761 | 5903 | environ_map, |
| 5904 | cwd_path, |
| 5762 | 5905 | ); |
| 5763 | 5906 | defer dirs.deinit(io); |
| 5764 | 5907 | |