| 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,7 +45,7 @@ pub fn build(b: *std.Build) !void { |
| 45 | }); | 45 | }); |
| 46 | 46 | ||
| 47 | const docgen_cmd = b.addRunArtifact(docgen_exe); | 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 | if (b.zig_lib_dir) |p| { | 49 | if (b.zig_lib_dir) |p| { |
| 50 | docgen_cmd.addArg("--zig-lib-dir"); | 50 | docgen_cmd.addArg("--zig-lib-dir"); |
| 51 | docgen_cmd.addDirectoryArg(p); | 51 | docgen_cmd.addDirectoryArg(p); |
| ... | @@ -884,7 +884,7 @@ fn findConfigH(b: *std.Build, config_h_path_option: ?[]const u8) ?[]const u8 { | ... | @@ -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 | while (true) { | 888 | while (true) { |
| 889 | var dir = fs.cwd().openDir(check_dir, .{}) catch unreachable; | 889 | var dir = fs.cwd().openDir(check_dir, .{}) catch unreachable; |
| 890 | defer dir.close(); | 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,7 +53,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { |
| 53 | const self = @fieldParentPtr(GenerateDef, "step", step); | 53 | const self = @fieldParentPtr(GenerateDef, "step", step); |
| 54 | const arena = b.allocator; | 54 | const arena = b.allocator; |
| 55 | 55 | ||
| 56 | var man = b.cache.obtain(); | 56 | var man = b.graph.cache.obtain(); |
| 57 | defer man.deinit(); | 57 | defer man.deinit(); |
| 58 | 58 | ||
| 59 | // Random bytes to make GenerateDef unique. Refresh this with new | 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,11 +46,6 @@ pub fn main() !void { |
| 46 | return error.InvalidArgs; | 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 | const build_root_directory: std.Build.Cache.Directory = .{ | 49 | const build_root_directory: std.Build.Cache.Directory = .{ |
| 55 | .path = build_root, | 50 | .path = build_root, |
| 56 | .handle = try std.fs.cwd().openDir(build_root, .{}), | 51 | .handle = try std.fs.cwd().openDir(build_root, .{}), |
| ... | @@ -66,27 +61,29 @@ pub fn main() !void { | ... | @@ -66,27 +61,29 @@ pub fn main() !void { |
| 66 | .handle = try std.fs.cwd().makeOpenPath(global_cache_root, .{}), | 61 | .handle = try std.fs.cwd().makeOpenPath(global_cache_root, .{}), |
| 67 | }; | 62 | }; |
| 68 | 63 | ||
| 69 | var cache: std.Build.Cache = .{ | 64 | var graph: std.Build.Graph = .{ |
| 70 | .gpa = arena, | 65 | .arena = arena, |
| 71 | .manifest_dir = try local_cache_directory.handle.makeOpenPath("h", .{}), | 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 | |
| 74 | cache.addPrefix(build_root_directory); | 75 | graph.cache.addPrefix(.{ .path = null, .handle = std.fs.cwd() }); |
| 75 | cache.addPrefix(local_cache_directory); | 76 | graph.cache.addPrefix(build_root_directory); |
| 76 | cache.addPrefix(global_cache_directory); | 77 | graph.cache.addPrefix(local_cache_directory); |
| 77 | cache.hash.addBytes(builtin.zig_version_string); | 78 | graph.cache.addPrefix(global_cache_directory); |
| 79 | graph.cache.hash.addBytes(builtin.zig_version_string); | ||
| 78 | 80 | ||
| 79 | const builder = try std.Build.create( | 81 | const builder = try std.Build.create( |
| 80 | arena, | 82 | &graph, |
| 81 | zig_exe, | ||
| 82 | build_root_directory, | 83 | build_root_directory, |
| 83 | local_cache_directory, | 84 | local_cache_directory, |
| 84 | global_cache_directory, | ||
| 85 | host, | ||
| 86 | &cache, | ||
| 87 | dependencies.root_deps, | 85 | dependencies.root_deps, |
| 88 | ); | 86 | ); |
| 89 | defer builder.destroy(); | ||
| 90 | 87 | ||
| 91 | var targets = ArrayList([]const u8).init(arena); | 88 | var targets = ArrayList([]const u8).init(arena); |
| 92 | var debug_log_scopes = ArrayList([]const u8).init(arena); | 89 | var debug_log_scopes = ArrayList([]const u8).init(arena); |
| ... | @@ -100,64 +97,67 @@ pub fn main() !void { | ... | @@ -100,64 +97,67 @@ pub fn main() !void { |
| 100 | var color: Color = .auto; | 97 | var color: Color = .auto; |
| 101 | var seed: u32 = 0; | 98 | var seed: u32 = 0; |
| 102 | var prominent_compile_errors: bool = false; | 99 | var prominent_compile_errors: bool = false; |
| 103 | 100 | var help_menu: bool = false; | |
| 104 | const stderr_stream = io.getStdErr().writer(); | 101 | var steps_menu: bool = false; |
| 105 | const stdout_stream = io.getStdOut().writer(); | 102 | var output_tmp_nonce: ?[16]u8 = null; |
| 106 | 103 | ||
| 107 | while (nextArg(args, &arg_idx)) |arg| { | 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 | const option_contents = arg[2..]; | 109 | const option_contents = arg[2..]; |
| 110 | if (option_contents.len == 0) { | 110 | if (option_contents.len == 0) |
| 111 | std.debug.print("Expected option name after '-D'\n\n", .{}); | 111 | fatalWithHint("expected option name after '-D'", .{}); |
| 112 | usageAndErr(builder, false, stderr_stream); | ||
| 113 | } | ||
| 114 | if (mem.indexOfScalar(u8, option_contents, '=')) |name_end| { | 112 | if (mem.indexOfScalar(u8, option_contents, '=')) |name_end| { |
| 115 | const option_name = option_contents[0..name_end]; | 113 | const option_name = option_contents[0..name_end]; |
| 116 | const option_value = option_contents[name_end + 1 ..]; | 114 | const option_value = option_contents[name_end + 1 ..]; |
| 117 | if (try builder.addUserInputOption(option_name, option_value)) | 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 | } else { | 117 | } else { |
| 120 | if (try builder.addUserInputFlag(option_contents)) | 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 | } else if (mem.startsWith(u8, arg, "-")) { | 121 | } else if (mem.startsWith(u8, arg, "-")) { |
| 124 | if (mem.eql(u8, arg, "--verbose")) { | 122 | if (mem.eql(u8, arg, "--verbose")) { |
| 125 | builder.verbose = true; | 123 | builder.verbose = true; |
| 126 | } else if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) { | 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 | } else if (mem.eql(u8, arg, "-p") or mem.eql(u8, arg, "--prefix")) { | 126 | } else if (mem.eql(u8, arg, "-p") or mem.eql(u8, arg, "--prefix")) { |
| 129 | install_prefix = nextArg(args, &arg_idx) orelse { | 127 | install_prefix = nextArgOrFatal(args, &arg_idx); |
| 130 | std.debug.print("Expected argument after {s}\n\n", .{arg}); | ||
| 131 | usageAndErr(builder, false, stderr_stream); | ||
| 132 | }; | ||
| 133 | } else if (mem.eql(u8, arg, "-l") or mem.eql(u8, arg, "--list-steps")) { | 128 | } else if (mem.eql(u8, arg, "-l") or mem.eql(u8, arg, "--list-steps")) { |
| 134 | return steps(builder, false, stdout_stream); | 129 | steps_menu = true; |
| 135 | } else if (mem.eql(u8, arg, "--prefix-lib-dir")) { | 130 | } else if (mem.startsWith(u8, arg, "-fsys=")) { |
| 136 | dir_list.lib_dir = nextArg(args, &arg_idx) orelse { | 131 | const name = arg["-fsys=".len..]; |
| 137 | std.debug.print("Expected argument after {s}\n\n", .{arg}); | 132 | graph.system_library_options.put(arena, name, .user_enabled) catch @panic("OOM"); |
| 138 | usageAndErr(builder, false, stderr_stream); | 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 | } else if (mem.eql(u8, arg, "--prefix-exe-dir")) { | 153 | } else if (mem.eql(u8, arg, "--prefix-exe-dir")) { |
| 141 | dir_list.exe_dir = nextArg(args, &arg_idx) orelse { | 154 | dir_list.exe_dir = nextArgOrFatal(args, &arg_idx); |
| 142 | std.debug.print("Expected argument after {s}\n\n", .{arg}); | ||
| 143 | usageAndErr(builder, false, stderr_stream); | ||
| 144 | }; | ||
| 145 | } else if (mem.eql(u8, arg, "--prefix-include-dir")) { | 155 | } else if (mem.eql(u8, arg, "--prefix-include-dir")) { |
| 146 | dir_list.include_dir = nextArg(args, &arg_idx) orelse { | 156 | dir_list.include_dir = nextArgOrFatal(args, &arg_idx); |
| 147 | std.debug.print("Expected argument after {s}\n\n", .{arg}); | ||
| 148 | usageAndErr(builder, false, stderr_stream); | ||
| 149 | }; | ||
| 150 | } else if (mem.eql(u8, arg, "--sysroot")) { | 157 | } else if (mem.eql(u8, arg, "--sysroot")) { |
| 151 | const sysroot = nextArg(args, &arg_idx) orelse { | 158 | builder.sysroot = nextArgOrFatal(args, &arg_idx); |
| 152 | std.debug.print("Expected argument after {s}\n\n", .{arg}); | ||
| 153 | usageAndErr(builder, false, stderr_stream); | ||
| 154 | }; | ||
| 155 | builder.sysroot = sysroot; | ||
| 156 | } else if (mem.eql(u8, arg, "--maxrss")) { | 159 | } else if (mem.eql(u8, arg, "--maxrss")) { |
| 157 | const max_rss_text = nextArg(args, &arg_idx) orelse { | 160 | const max_rss_text = nextArgOrFatal(args, &arg_idx); |
| 158 | std.debug.print("Expected argument after {s}\n\n", .{arg}); | ||
| 159 | usageAndErr(builder, false, stderr_stream); | ||
| 160 | }; | ||
| 161 | max_rss = std.fmt.parseIntSizeSuffix(max_rss_text, 10) catch |err| { | 161 | max_rss = std.fmt.parseIntSizeSuffix(max_rss_text, 10) catch |err| { |
| 162 | std.debug.print("invalid byte size: '{s}': {s}\n", .{ | 162 | std.debug.print("invalid byte size: '{s}': {s}\n", .{ |
| 163 | max_rss_text, @errorName(err), | 163 | max_rss_text, @errorName(err), |
| ... | @@ -167,66 +167,50 @@ pub fn main() !void { | ... | @@ -167,66 +167,50 @@ pub fn main() !void { |
| 167 | } else if (mem.eql(u8, arg, "--skip-oom-steps")) { | 167 | } else if (mem.eql(u8, arg, "--skip-oom-steps")) { |
| 168 | skip_oom_steps = true; | 168 | skip_oom_steps = true; |
| 169 | } else if (mem.eql(u8, arg, "--search-prefix")) { | 169 | } else if (mem.eql(u8, arg, "--search-prefix")) { |
| 170 | const search_prefix = nextArg(args, &arg_idx) orelse { | 170 | const search_prefix = nextArgOrFatal(args, &arg_idx); |
| 171 | std.debug.print("Expected argument after {s}\n\n", .{arg}); | ||
| 172 | usageAndErr(builder, false, stderr_stream); | ||
| 173 | }; | ||
| 174 | builder.addSearchPrefix(search_prefix); | 171 | builder.addSearchPrefix(search_prefix); |
| 175 | } else if (mem.eql(u8, arg, "--libc")) { | 172 | } else if (mem.eql(u8, arg, "--libc")) { |
| 176 | const libc_file = nextArg(args, &arg_idx) orelse { | 173 | builder.libc_file = nextArgOrFatal(args, &arg_idx); |
| 177 | std.debug.print("Expected argument after {s}\n\n", .{arg}); | ||
| 178 | usageAndErr(builder, false, stderr_stream); | ||
| 179 | }; | ||
| 180 | builder.libc_file = libc_file; | ||
| 181 | } else if (mem.eql(u8, arg, "--color")) { | 174 | } else if (mem.eql(u8, arg, "--color")) { |
| 182 | const next_arg = nextArg(args, &arg_idx) orelse { | 175 | const next_arg = nextArg(args, &arg_idx) orelse |
| 183 | std.debug.print("Expected [auto|on|off] after {s}\n\n", .{arg}); | 176 | fatalWithHint("expected [auto|on|off] after '{s}'", .{arg}); |
| 184 | usageAndErr(builder, false, stderr_stream); | ||
| 185 | }; | ||
| 186 | color = std.meta.stringToEnum(Color, next_arg) orelse { | 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 }); | 178 | fatalWithHint("expected [auto|on|off] after '{s}', found '{s}'", .{ |
| 188 | usageAndErr(builder, false, stderr_stream); | 179 | arg, next_arg, |
| 180 | }); | ||
| 189 | }; | 181 | }; |
| 190 | } else if (mem.eql(u8, arg, "--summary")) { | 182 | } else if (mem.eql(u8, arg, "--summary")) { |
| 191 | const next_arg = nextArg(args, &arg_idx) orelse { | 183 | const next_arg = nextArg(args, &arg_idx) orelse |
| 192 | std.debug.print("Expected [all|failures|none] after {s}\n\n", .{arg}); | 184 | fatalWithHint("expected [all|failures|none] after '{s}'", .{arg}); |
| 193 | usageAndErr(builder, false, stderr_stream); | ||
| 194 | }; | ||
| 195 | summary = std.meta.stringToEnum(Summary, next_arg) orelse { | 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 }); | 186 | fatalWithHint("expected [all|failures|none] after '{s}', found '{s}'", .{ |
| 197 | usageAndErr(builder, false, stderr_stream); | 187 | arg, next_arg, |
| 188 | }); | ||
| 198 | }; | 189 | }; |
| 199 | } else if (mem.eql(u8, arg, "--zig-lib-dir")) { | 190 | } else if (mem.eql(u8, arg, "--zig-lib-dir")) { |
| 200 | builder.zig_lib_dir = .{ .cwd_relative = nextArg(args, &arg_idx) orelse { | 191 | builder.zig_lib_dir = .{ .cwd_relative = nextArgOrFatal(args, &arg_idx) }; |
| 201 | std.debug.print("Expected argument after {s}\n\n", .{arg}); | ||
| 202 | usageAndErr(builder, false, stderr_stream); | ||
| 203 | } }; | ||
| 204 | } else if (mem.eql(u8, arg, "--seed")) { | 192 | } else if (mem.eql(u8, arg, "--seed")) { |
| 205 | const next_arg = nextArg(args, &arg_idx) orelse { | 193 | const next_arg = nextArg(args, &arg_idx) orelse |
| 206 | std.debug.print("Expected u32 after {s}\n\n", .{arg}); | 194 | fatalWithHint("expected u32 after '{s}'", .{arg}); |
| 207 | usageAndErr(builder, false, stderr_stream); | ||
| 208 | }; | ||
| 209 | seed = std.fmt.parseUnsigned(u32, next_arg, 0) catch |err| { | 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 | next_arg, @errorName(err), | 197 | next_arg, @errorName(err), |
| 212 | }); | 198 | }); |
| 213 | process.exit(1); | ||
| 214 | }; | 199 | }; |
| 215 | } else if (mem.eql(u8, arg, "--debug-log")) { | 200 | } else if (mem.eql(u8, arg, "--debug-log")) { |
| 216 | const next_arg = nextArg(args, &arg_idx) orelse { | 201 | const next_arg = nextArgOrFatal(args, &arg_idx); |
| 217 | std.debug.print("Expected argument after {s}\n\n", .{arg}); | ||
| 218 | usageAndErr(builder, false, stderr_stream); | ||
| 219 | }; | ||
| 220 | try debug_log_scopes.append(next_arg); | 202 | try debug_log_scopes.append(next_arg); |
| 221 | } else if (mem.eql(u8, arg, "--debug-pkg-config")) { | 203 | } else if (mem.eql(u8, arg, "--debug-pkg-config")) { |
| 222 | builder.debug_pkg_config = true; | 204 | builder.debug_pkg_config = true; |
| 223 | } else if (mem.eql(u8, arg, "--debug-compile-errors")) { | 205 | } else if (mem.eql(u8, arg, "--debug-compile-errors")) { |
| 224 | builder.debug_compile_errors = true; | 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 | } else if (mem.eql(u8, arg, "--glibc-runtimes")) { | 212 | } else if (mem.eql(u8, arg, "--glibc-runtimes")) { |
| 226 | builder.glibc_runtimes_dir = nextArg(args, &arg_idx) orelse { | 213 | builder.glibc_runtimes_dir = nextArgOrFatal(args, &arg_idx); |
| 227 | std.debug.print("Expected argument after {s}\n\n", .{arg}); | ||
| 228 | usageAndErr(builder, false, stderr_stream); | ||
| 229 | }; | ||
| 230 | } else if (mem.eql(u8, arg, "--verbose-link")) { | 214 | } else if (mem.eql(u8, arg, "--verbose-link")) { |
| 231 | builder.verbose_link = true; | 215 | builder.verbose_link = true; |
| 232 | } else if (mem.eql(u8, arg, "--verbose-air")) { | 216 | } else if (mem.eql(u8, arg, "--verbose-air")) { |
| ... | @@ -292,19 +276,26 @@ pub fn main() !void { | ... | @@ -292,19 +276,26 @@ pub fn main() !void { |
| 292 | builder.args = argsRest(args, arg_idx); | 276 | builder.args = argsRest(args, arg_idx); |
| 293 | break; | 277 | break; |
| 294 | } else { | 278 | } else { |
| 295 | std.debug.print("Unrecognized argument: {s}\n\n", .{arg}); | 279 | fatalWithHint("unrecognized argument: '{s}'", .{arg}); |
| 296 | usageAndErr(builder, false, stderr_stream); | ||
| 297 | } | 280 | } |
| 298 | } else { | 281 | } else { |
| 299 | try targets.append(arg); | 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 | const stderr = std.io.getStdErr(); | 294 | const stderr = std.io.getStdErr(); |
| 304 | const ttyconf = get_tty_conf(color, stderr); | 295 | const ttyconf = get_tty_conf(color, stderr); |
| 305 | switch (ttyconf) { | 296 | switch (ttyconf) { |
| 306 | .no_color => try builder.env_map.put("NO_COLOR", "1"), | 297 | .no_color => try graph.env_map.put("NO_COLOR", "1"), |
| 307 | .escape_codes => try builder.env_map.put("YES_COLOR", "1"), | 298 | .escape_codes => try graph.env_map.put("YES_COLOR", "1"), |
| 308 | .windows_api => {}, | 299 | .windows_api => {}, |
| 309 | } | 300 | } |
| 310 | 301 | ||
| ... | @@ -319,8 +310,39 @@ pub fn main() !void { | ... | @@ -319,8 +310,39 @@ pub fn main() !void { |
| 319 | try builder.runBuild(root); | 310 | try builder.runBuild(root); |
| 320 | } | 311 | } |
| 321 | 312 | ||
| 322 | if (builder.validateUserInputDidItFail()) | 313 | if (graph.needed_lazy_dependencies.entries.len != 0) { |
| 323 | usageAndErr(builder, true, stderr_stream); | 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 | var run: Run = .{ | 347 | var run: Run = .{ |
| 326 | .max_rss = max_rss, | 348 | .max_rss = max_rss, |
| ... | @@ -389,7 +411,7 @@ fn runStepNames( | ... | @@ -389,7 +411,7 @@ fn runStepNames( |
| 389 | for (0..step_names.len) |i| { | 411 | for (0..step_names.len) |i| { |
| 390 | const step_name = step_names[step_names.len - i - 1]; | 412 | const step_name = step_names[step_names.len - i - 1]; |
| 391 | const s = b.top_level_steps.get(step_name) orelse { | 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 | process.exit(1); | 415 | process.exit(1); |
| 394 | }; | 416 | }; |
| 395 | step_stack.putAssumeCapacity(&s.step, {}); | 417 | step_stack.putAssumeCapacity(&s.step, {}); |
| ... | @@ -1037,13 +1059,7 @@ fn printErrorMessages(b: *std.Build, failing_step: *Step, run: *const Run) !void | ... | @@ -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 { | 1062 | fn steps(builder: *std.Build, 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 | |||
| 1047 | const allocator = builder.allocator; | 1063 | const allocator = builder.allocator; |
| 1048 | for (builder.top_level_steps.values()) |top_level_step| { | 1064 | for (builder.top_level_steps.values()) |top_level_step| { |
| 1049 | const name = if (&top_level_step.step == builder.default_step) | 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,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 { | 1073 | fn usage(b: *std.Build, 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 | |||
| 1064 | try out_stream.print( | 1074 | try out_stream.print( |
| 1065 | \\ | ||
| 1066 | \\Usage: {s} build [steps] [options] | 1075 | \\Usage: {s} build [steps] [options] |
| 1067 | \\ | 1076 | \\ |
| 1068 | \\Steps: | 1077 | \\Steps: |
| 1069 | \\ | 1078 | \\ |
| 1070 | , .{builder.zig_exe}); | 1079 | , .{b.graph.zig_exe}); |
| 1071 | try steps(builder, true, out_stream); | 1080 | try steps(b, out_stream); |
| 1072 | 1081 | ||
| 1073 | try out_stream.writeAll( | 1082 | try out_stream.writeAll( |
| 1074 | \\ | 1083 | \\ |
| 1075 | \\General Options: | 1084 | \\General Options: |
| 1076 | \\ -p, --prefix [path] Override default install prefix | 1085 | \\ -p, --prefix [path] Where to install files (default: zig-out) |
| 1077 | \\ --prefix-lib-dir [path] Override default library directory path | 1086 | \\ --prefix-lib-dir [path] Where to install libraries |
| 1078 | \\ --prefix-exe-dir [path] Override default executable directory path | 1087 | \\ --prefix-exe-dir [path] Where to install executables |
| 1079 | \\ --prefix-include-dir [path] Override default include directory path | 1088 | \\ --prefix-include-dir [path] Where to install C header files |
| 1080 | \\ | 1089 | \\ |
| 1081 | \\ --sysroot [path] Set the system root directory (usually /) | 1090 | \\ --release[=mode] Request release mode, optionally specifying a |
| 1082 | \\ --search-prefix [path] Add a path to look for binaries, libraries, headers | 1091 | \\ preferred optimization mode: fast, safe, small |
| 1083 | \\ --libc [file] Provide a file which specifies libc paths | ||
| 1084 | \\ | 1092 | \\ |
| 1085 | \\ -fdarling, -fno-darling Integration with system-installed Darling to | 1093 | \\ -fdarling, -fno-darling Integration with system-installed Darling to |
| 1086 | \\ execute macOS programs on Linux hosts | 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,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; | 1127 | const arena = b.allocator; |
| 1120 | if (builder.available_options_list.items.len == 0) { | 1128 | if (b.available_options_list.items.len == 0) { |
| 1121 | try out_stream.print(" (none)\n", .{}); | 1129 | try out_stream.print(" (none)\n", .{}); |
| 1122 | } else { | 1130 | } else { |
| 1123 | for (builder.available_options_list.items) |option| { | 1131 | for (b.available_options_list.items) |option| { |
| 1124 | const name = try fmt.allocPrint(allocator, " -D{s}=[{s}]", .{ | 1132 | const name = try fmt.allocPrint(arena, " -D{s}=[{s}]", .{ |
| 1125 | option.name, | 1133 | option.name, |
| 1126 | @tagName(option.type_id), | 1134 | @tagName(option.type_id), |
| 1127 | }); | 1135 | }); |
| 1128 | defer allocator.free(name); | ||
| 1129 | try out_stream.print("{s:<30} {s}\n", .{ name, option.description }); | 1136 | try out_stream.print("{s:<30} {s}\n", .{ name, option.description }); |
| 1130 | if (option.enum_options) |enum_options| { | 1137 | if (option.enum_options) |enum_options| { |
| 1131 | const padding = " " ** 33; | 1138 | const padding = " " ** 33; |
| ... | @@ -1137,6 +1144,37 @@ fn usage(builder: *std.Build, already_ran_build: bool, out_stream: anytype) !voi | ... | @@ -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 | try out_stream.writeAll( | 1178 | try out_stream.writeAll( |
| 1141 | \\ | 1179 | \\ |
| 1142 | \\Advanced Options: | 1180 | \\Advanced Options: |
| ... | @@ -1161,17 +1199,19 @@ fn usage(builder: *std.Build, already_ran_build: bool, out_stream: anytype) !voi | ... | @@ -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 | fn nextArg(args: [][:0]const u8, idx: *usize) ?[:0]const u8 { | 1202 | fn nextArg(args: [][:0]const u8, idx: *usize) ?[:0]const u8 { |
| 1170 | if (idx.* >= args.len) return null; | 1203 | if (idx.* >= args.len) return null; |
| 1171 | defer idx.* += 1; | 1204 | defer idx.* += 1; |
| 1172 | return args[idx.*]; | 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 | fn argsRest(args: [][:0]const u8, idx: usize) ?[][:0]const u8 { | 1215 | fn argsRest(args: [][:0]const u8, idx: usize) ?[][:0]const u8 { |
| 1176 | if (idx >= args.len) return null; | 1216 | if (idx >= args.len) return null; |
| 1177 | return args[idx..]; | 1217 | return args[idx..]; |
| ... | @@ -1202,3 +1242,32 @@ fn renderOptions(ttyconf: std.io.tty.Config) std.zig.ErrorBundle.RenderOptions { | ... | @@ -1202,3 +1242,32 @@ fn renderOptions(ttyconf: std.io.tty.Config) std.zig.ErrorBundle.RenderOptions { |
| 1202 | .include_reference_trace = ttyconf != .no_color, | 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,6 +22,8 @@ pub const Cache = @import("Build/Cache.zig"); |
| 22 | pub const Step = @import("Build/Step.zig"); | 22 | pub const Step = @import("Build/Step.zig"); |
| 23 | pub const Module = @import("Build/Module.zig"); | 23 | pub const Module = @import("Build/Module.zig"); |
| 24 | 24 | ||
| 25 | /// Shared state among all Build instances. | ||
| 26 | graph: *Graph, | ||
| 25 | install_tls: TopLevelStep, | 27 | install_tls: TopLevelStep, |
| 26 | uninstall_tls: TopLevelStep, | 28 | uninstall_tls: TopLevelStep, |
| 27 | allocator: Allocator, | 29 | allocator: Allocator, |
| ... | @@ -38,9 +40,7 @@ verbose_cimport: bool, | ... | @@ -38,9 +40,7 @@ verbose_cimport: bool, |
| 38 | verbose_llvm_cpu_features: bool, | 40 | verbose_llvm_cpu_features: bool, |
| 39 | reference_trace: ?u32 = null, | 41 | reference_trace: ?u32 = null, |
| 40 | invalid_user_input: bool, | 42 | invalid_user_input: bool, |
| 41 | zig_exe: [:0]const u8, | ||
| 42 | default_step: *Step, | 43 | default_step: *Step, |
| 43 | env_map: *EnvMap, | ||
| 44 | top_level_steps: std.StringArrayHashMapUnmanaged(*TopLevelStep), | 44 | top_level_steps: std.StringArrayHashMapUnmanaged(*TopLevelStep), |
| 45 | install_prefix: []const u8, | 45 | install_prefix: []const u8, |
| 46 | dest_dir: ?[]const u8, | 46 | dest_dir: ?[]const u8, |
| ... | @@ -49,14 +49,12 @@ exe_dir: []const u8, | ... | @@ -49,14 +49,12 @@ exe_dir: []const u8, |
| 49 | h_dir: []const u8, | 49 | h_dir: []const u8, |
| 50 | install_path: []const u8, | 50 | install_path: []const u8, |
| 51 | sysroot: ?[]const u8 = null, | 51 | sysroot: ?[]const u8 = null, |
| 52 | search_prefixes: ArrayList([]const u8), | 52 | search_prefixes: std.ArrayListUnmanaged([]const u8), |
| 53 | libc_file: ?[]const u8 = null, | 53 | libc_file: ?[]const u8 = null, |
| 54 | installed_files: ArrayList(InstalledFile), | 54 | installed_files: ArrayList(InstalledFile), |
| 55 | /// Path to the directory containing build.zig. | 55 | /// Path to the directory containing build.zig. |
| 56 | build_root: Cache.Directory, | 56 | build_root: Cache.Directory, |
| 57 | cache_root: Cache.Directory, | 57 | cache_root: Cache.Directory, |
| 58 | global_cache_root: Cache.Directory, | ||
| 59 | cache: *Cache, | ||
| 60 | zig_lib_dir: ?LazyPath, | 58 | zig_lib_dir: ?LazyPath, |
| 61 | pkg_config_pkg_list: ?(PkgConfigError![]const PkgConfigPkg) = null, | 59 | pkg_config_pkg_list: ?(PkgConfigError![]const PkgConfigPkg) = null, |
| 62 | args: ?[][]const u8 = null, | 60 | args: ?[][]const u8 = null, |
| ... | @@ -98,8 +96,47 @@ initialized_deps: *InitializedDepMap, | ... | @@ -98,8 +96,47 @@ initialized_deps: *InitializedDepMap, |
| 98 | /// A mapping from dependency names to package hashes. | 96 | /// A mapping from dependency names to package hashes. |
| 99 | available_deps: AvailableDeps, | 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 | const AvailableDeps = []const struct { []const u8, []const u8 }; | 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 | const InitializedDepMap = std.HashMap(InitializedDepKey, *Dependency, InitializedDepContext, std.hash_map.default_max_load_percentage); | 140 | const InitializedDepMap = std.HashMap(InitializedDepKey, *Dependency, InitializedDepContext, std.hash_map.default_max_load_percentage); |
| 104 | const InitializedDepKey = struct { | 141 | const InitializedDepKey = struct { |
| 105 | build_root_string: []const u8, | 142 | build_root_string: []const u8, |
| ... | @@ -208,28 +245,20 @@ pub const DirList = struct { | ... | @@ -208,28 +245,20 @@ pub const DirList = struct { |
| 208 | }; | 245 | }; |
| 209 | 246 | ||
| 210 | pub fn create( | 247 | pub fn create( |
| 211 | allocator: Allocator, | 248 | graph: *Graph, |
| 212 | zig_exe: [:0]const u8, | ||
| 213 | build_root: Cache.Directory, | 249 | build_root: Cache.Directory, |
| 214 | cache_root: Cache.Directory, | 250 | cache_root: Cache.Directory, |
| 215 | global_cache_root: Cache.Directory, | ||
| 216 | host: ResolvedTarget, | ||
| 217 | cache: *Cache, | ||
| 218 | available_deps: AvailableDeps, | 251 | available_deps: AvailableDeps, |
| 219 | ) !*Build { | 252 | ) !*Build { |
| 220 | const env_map = try allocator.create(EnvMap); | 253 | const arena = graph.arena; |
| 221 | env_map.* = try process.getEnvMap(allocator); | 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); | 257 | const self = try arena.create(Build); |
| 224 | initialized_deps.* = InitializedDepMap.initContext(allocator, .{ .allocator = allocator }); | ||
| 225 | |||
| 226 | const self = try allocator.create(Build); | ||
| 227 | self.* = .{ | 258 | self.* = .{ |
| 228 | .zig_exe = zig_exe, | 259 | .graph = graph, |
| 229 | .build_root = build_root, | 260 | .build_root = build_root, |
| 230 | .cache_root = cache_root, | 261 | .cache_root = cache_root, |
| 231 | .global_cache_root = global_cache_root, | ||
| 232 | .cache = cache, | ||
| 233 | .verbose = false, | 262 | .verbose = false, |
| 234 | .verbose_link = false, | 263 | .verbose_link = false, |
| 235 | .verbose_cc = false, | 264 | .verbose_cc = false, |
| ... | @@ -239,20 +268,19 @@ pub fn create( | ... | @@ -239,20 +268,19 @@ pub fn create( |
| 239 | .verbose_cimport = false, | 268 | .verbose_cimport = false, |
| 240 | .verbose_llvm_cpu_features = false, | 269 | .verbose_llvm_cpu_features = false, |
| 241 | .invalid_user_input = false, | 270 | .invalid_user_input = false, |
| 242 | .allocator = allocator, | 271 | .allocator = arena, |
| 243 | .user_input_options = UserInputOptionsMap.init(allocator), | 272 | .user_input_options = UserInputOptionsMap.init(arena), |
| 244 | .available_options_map = AvailableOptionsMap.init(allocator), | 273 | .available_options_map = AvailableOptionsMap.init(arena), |
| 245 | .available_options_list = ArrayList(AvailableOption).init(allocator), | 274 | .available_options_list = ArrayList(AvailableOption).init(arena), |
| 246 | .top_level_steps = .{}, | 275 | .top_level_steps = .{}, |
| 247 | .default_step = undefined, | 276 | .default_step = undefined, |
| 248 | .env_map = env_map, | 277 | .search_prefixes = .{}, |
| 249 | .search_prefixes = ArrayList([]const u8).init(allocator), | ||
| 250 | .install_prefix = undefined, | 278 | .install_prefix = undefined, |
| 251 | .lib_dir = undefined, | 279 | .lib_dir = undefined, |
| 252 | .exe_dir = undefined, | 280 | .exe_dir = undefined, |
| 253 | .h_dir = undefined, | 281 | .h_dir = undefined, |
| 254 | .dest_dir = env_map.get("DESTDIR"), | 282 | .dest_dir = graph.env_map.get("DESTDIR"), |
| 255 | .installed_files = ArrayList(InstalledFile).init(allocator), | 283 | .installed_files = ArrayList(InstalledFile).init(arena), |
| 256 | .install_tls = .{ | 284 | .install_tls = .{ |
| 257 | .step = Step.init(.{ | 285 | .step = Step.init(.{ |
| 258 | .id = .top_level, | 286 | .id = .top_level, |
| ... | @@ -273,14 +301,15 @@ pub fn create( | ... | @@ -273,14 +301,15 @@ pub fn create( |
| 273 | .zig_lib_dir = null, | 301 | .zig_lib_dir = null, |
| 274 | .install_path = undefined, | 302 | .install_path = undefined, |
| 275 | .args = null, | 303 | .args = null, |
| 276 | .host = host, | 304 | .host = undefined, |
| 277 | .modules = std.StringArrayHashMap(*Module).init(allocator), | 305 | .modules = std.StringArrayHashMap(*Module).init(arena), |
| 278 | .named_writefiles = std.StringArrayHashMap(*Step.WriteFile).init(allocator), | 306 | .named_writefiles = std.StringArrayHashMap(*Step.WriteFile).init(arena), |
| 279 | .initialized_deps = initialized_deps, | 307 | .initialized_deps = initialized_deps, |
| 280 | .available_deps = available_deps, | 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); | 311 | try self.top_level_steps.put(arena, self.install_tls.step.name, &self.install_tls); |
| 283 | try self.top_level_steps.put(allocator, self.uninstall_tls.step.name, &self.uninstall_tls); | 312 | try self.top_level_steps.put(arena, self.uninstall_tls.step.name, &self.uninstall_tls); |
| 284 | self.default_step = &self.install_tls.step; | 313 | self.default_step = &self.install_tls.step; |
| 285 | return self; | 314 | return self; |
| 286 | } | 315 | } |
| ... | @@ -297,10 +326,17 @@ fn createChild( | ... | @@ -297,10 +326,17 @@ fn createChild( |
| 297 | return child; | 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 | const allocator = parent.allocator; | 336 | const allocator = parent.allocator; |
| 302 | const child = try allocator.create(Build); | 337 | const child = try allocator.create(Build); |
| 303 | child.* = .{ | 338 | child.* = .{ |
| 339 | .graph = parent.graph, | ||
| 304 | .allocator = allocator, | 340 | .allocator = allocator, |
| 305 | .install_tls = .{ | 341 | .install_tls = .{ |
| 306 | .step = Step.init(.{ | 342 | .step = Step.init(.{ |
| ... | @@ -332,9 +368,7 @@ fn createChildOnly(parent: *Build, dep_name: []const u8, build_root: Cache.Direc | ... | @@ -332,9 +368,7 @@ fn createChildOnly(parent: *Build, dep_name: []const u8, build_root: Cache.Direc |
| 332 | .verbose_llvm_cpu_features = parent.verbose_llvm_cpu_features, | 368 | .verbose_llvm_cpu_features = parent.verbose_llvm_cpu_features, |
| 333 | .reference_trace = parent.reference_trace, | 369 | .reference_trace = parent.reference_trace, |
| 334 | .invalid_user_input = false, | 370 | .invalid_user_input = false, |
| 335 | .zig_exe = parent.zig_exe, | ||
| 336 | .default_step = undefined, | 371 | .default_step = undefined, |
| 337 | .env_map = parent.env_map, | ||
| 338 | .top_level_steps = .{}, | 372 | .top_level_steps = .{}, |
| 339 | .install_prefix = undefined, | 373 | .install_prefix = undefined, |
| 340 | .dest_dir = parent.dest_dir, | 374 | .dest_dir = parent.dest_dir, |
| ... | @@ -348,8 +382,6 @@ fn createChildOnly(parent: *Build, dep_name: []const u8, build_root: Cache.Direc | ... | @@ -348,8 +382,6 @@ fn createChildOnly(parent: *Build, dep_name: []const u8, build_root: Cache.Direc |
| 348 | .installed_files = ArrayList(InstalledFile).init(allocator), | 382 | .installed_files = ArrayList(InstalledFile).init(allocator), |
| 349 | .build_root = build_root, | 383 | .build_root = build_root, |
| 350 | .cache_root = parent.cache_root, | 384 | .cache_root = parent.cache_root, |
| 351 | .global_cache_root = parent.global_cache_root, | ||
| 352 | .cache = parent.cache, | ||
| 353 | .zig_lib_dir = parent.zig_lib_dir, | 385 | .zig_lib_dir = parent.zig_lib_dir, |
| 354 | .debug_log_scopes = parent.debug_log_scopes, | 386 | .debug_log_scopes = parent.debug_log_scopes, |
| 355 | .debug_compile_errors = parent.debug_compile_errors, | 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,6 +398,7 @@ fn createChildOnly(parent: *Build, dep_name: []const u8, build_root: Cache.Direc |
| 366 | .named_writefiles = std.StringArrayHashMap(*Step.WriteFile).init(allocator), | 398 | .named_writefiles = std.StringArrayHashMap(*Step.WriteFile).init(allocator), |
| 367 | .initialized_deps = parent.initialized_deps, | 399 | .initialized_deps = parent.initialized_deps, |
| 368 | .available_deps = pkg_deps, | 400 | .available_deps = pkg_deps, |
| 401 | .release_mode = parent.release_mode, | ||
| 369 | }; | 402 | }; |
| 370 | try child.top_level_steps.put(allocator, child.install_tls.step.name, &child.install_tls); | 403 | try child.top_level_steps.put(allocator, child.install_tls.step.name, &child.install_tls); |
| 371 | try child.top_level_steps.put(allocator, child.uninstall_tls.step.name, &child.uninstall_tls); | 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,7 +576,7 @@ fn hashUserInputOptionsMap(allocator: Allocator, user_input_options: UserInputOp |
| 543 | fn determineAndApplyInstallPrefix(b: *Build) !void { | 576 | fn determineAndApplyInstallPrefix(b: *Build) !void { |
| 544 | // Create an installation directory local to this package. This will be used when | 577 | // Create an installation directory local to this package. This will be used when |
| 545 | // dependant packages require a standard prefix, such as include directories for C headers. | 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 | // Random bytes to make unique. Refresh this with new random bytes when | 580 | // Random bytes to make unique. Refresh this with new random bytes when |
| 548 | // implementation is modified in a non-backwards-compatible way. | 581 | // implementation is modified in a non-backwards-compatible way. |
| 549 | hash.add(@as(u32, 0xd8cb0055)); | 582 | hash.add(@as(u32, 0xd8cb0055)); |
| ... | @@ -558,12 +591,6 @@ fn determineAndApplyInstallPrefix(b: *Build) !void { | ... | @@ -558,12 +591,6 @@ fn determineAndApplyInstallPrefix(b: *Build) !void { |
| 558 | b.resolveInstallPrefix(install_prefix, .{}); | 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 | /// This function is intended to be called by lib/build_runner.zig, not a build.zig file. | 594 | /// This function is intended to be called by lib/build_runner.zig, not a build.zig file. |
| 568 | pub fn resolveInstallPrefix(self: *Build, install_prefix: ?[]const u8, dir_list: DirList) void { | 595 | pub fn resolveInstallPrefix(self: *Build, install_prefix: ?[]const u8, dir_list: DirList) void { |
| 569 | if (self.dest_dir) |dest_dir| { | 596 | if (self.dest_dir) |dest_dir| { |
| ... | @@ -1216,20 +1243,33 @@ pub const StandardOptimizeOptionOptions = struct { | ... | @@ -1216,20 +1243,33 @@ pub const StandardOptimizeOptionOptions = struct { |
| 1216 | preferred_optimize_mode: ?std.builtin.OptimizeMode = null, | 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 | if (options.preferred_optimize_mode) |mode| { | 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 | return mode; | 1249 | return mode; |
| 1223 | } else { | 1250 | } else { |
| 1224 | return .Debug; | 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 | pub const StandardTargetOptionsArgs = struct { | 1275 | pub const StandardTargetOptionsArgs = struct { |
| ... | @@ -1244,67 +1284,83 @@ pub fn standardTargetOptions(b: *Build, args: StandardTargetOptionsArgs) Resolve | ... | @@ -1244,67 +1284,83 @@ pub fn standardTargetOptions(b: *Build, args: StandardTargetOptionsArgs) Resolve |
| 1244 | return b.resolveTargetQuery(query); | 1284 | return b.resolveTargetQuery(query); |
| 1245 | } | 1285 | } |
| 1246 | 1286 | ||
| 1247 | /// Exposes standard `zig build` options for choosing a target. | 1287 | pub fn parseTargetQuery(options: std.Target.Query.ParseOptions) error{ParseFailed}!std.Target.Query { |
| 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 | |||
| 1262 | var diags: Target.Query.ParseOptions.Diagnostics = .{}; | 1288 | var diags: Target.Query.ParseOptions.Diagnostics = .{}; |
| 1263 | const selected_target = Target.Query.parse(.{ | 1289 | var opts_copy = options; |
| 1264 | .arch_os_abi = triple, | 1290 | opts_copy.diagnostics = &diags; |
| 1265 | .cpu_features = mcpu, | 1291 | return std.Target.Query.parse(options) catch |err| switch (err) { |
| 1266 | .diagnostics = &diags, | ||
| 1267 | }) catch |err| switch (err) { | ||
| 1268 | error.UnknownCpuModel => { | 1292 | error.UnknownCpuModel => { |
| 1269 | log.err("Unknown CPU: '{s}'\nAvailable CPUs for architecture '{s}':", .{ | 1293 | std.debug.print("unknown CPU: '{s}'\navailable CPUs for architecture '{s}':\n", .{ |
| 1270 | diags.cpu_name.?, | 1294 | diags.cpu_name.?, @tagName(diags.arch.?), |
| 1271 | @tagName(diags.arch.?), | ||
| 1272 | }); | 1295 | }); |
| 1273 | for (diags.arch.?.allCpuModels()) |cpu| { | 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(); | 1299 | return error.ParseFailed; |
| 1277 | return args.default_target; | ||
| 1278 | }, | 1300 | }, |
| 1279 | error.UnknownCpuFeature => { | 1301 | error.UnknownCpuFeature => { |
| 1280 | log.err( | 1302 | std.debug.print( |
| 1281 | \\Unknown CPU feature: '{s}' | 1303 | \\unknown CPU feature: '{s}' |
| 1282 | \\Available CPU features for architecture '{s}': | 1304 | \\available CPU features for architecture '{s}': |
| 1283 | \\ | 1305 | \\ |
| 1284 | , .{ | 1306 | , .{ |
| 1285 | diags.unknown_feature_name.?, | 1307 | diags.unknown_feature_name.?, |
| 1286 | @tagName(diags.arch.?), | 1308 | @tagName(diags.arch.?), |
| 1287 | }); | 1309 | }); |
| 1288 | for (diags.arch.?.allFeaturesList()) |feature| { | 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(); | 1313 | return error.ParseFailed; |
| 1292 | return args.default_target; | ||
| 1293 | }, | 1314 | }, |
| 1294 | error.UnknownOperatingSystem => { | 1315 | error.UnknownOperatingSystem => { |
| 1295 | log.err( | 1316 | std.debug.print( |
| 1296 | \\Unknown OS: '{s}' | 1317 | \\unknown OS: '{s}' |
| 1297 | \\Available operating systems: | 1318 | \\available operating systems: |
| 1298 | \\ | 1319 | \\ |
| 1299 | , .{diags.os_name.?}); | 1320 | , .{diags.os_name.?}); |
| 1300 | inline for (std.meta.fields(Target.Os.Tag)) |field| { | 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(); | 1324 | return error.ParseFailed; |
| 1304 | return args.default_target; | ||
| 1305 | }, | 1325 | }, |
| 1306 | else => |e| { | 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 | b.markInvalidUserInput(); | 1364 | b.markInvalidUserInput(); |
| 1309 | return args.default_target; | 1365 | return args.default_target; |
| 1310 | }, | 1366 | }, |
| ... | @@ -1367,7 +1423,7 @@ pub fn addUserInputOption(self: *Build, name_raw: []const u8, value_raw: []const | ... | @@ -1367,7 +1423,7 @@ pub fn addUserInputOption(self: *Build, name_raw: []const u8, value_raw: []const |
| 1367 | }); | 1423 | }); |
| 1368 | }, | 1424 | }, |
| 1369 | .flag => { | 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 | return true; | 1427 | return true; |
| 1372 | }, | 1428 | }, |
| 1373 | .map => |*map| { | 1429 | .map => |*map| { |
| ... | @@ -1427,17 +1483,17 @@ fn markInvalidUserInput(self: *Build) void { | ... | @@ -1427,17 +1483,17 @@ fn markInvalidUserInput(self: *Build) void { |
| 1427 | self.invalid_user_input = true; | 1483 | self.invalid_user_input = true; |
| 1428 | } | 1484 | } |
| 1429 | 1485 | ||
| 1430 | pub fn validateUserInputDidItFail(self: *Build) bool { | 1486 | pub fn validateUserInputDidItFail(b: *Build) bool { |
| 1431 | // make sure all args are used | 1487 | // Make sure all args are used. |
| 1432 | var it = self.user_input_options.iterator(); | 1488 | var it = b.user_input_options.iterator(); |
| 1433 | while (it.next()) |entry| { | 1489 | while (it.next()) |entry| { |
| 1434 | if (!entry.value_ptr.used) { | 1490 | if (!entry.value_ptr.used) { |
| 1435 | log.err("Invalid option: -D{s}", .{entry.key_ptr.*}); | 1491 | log.err("invalid option: -D{s}", .{entry.key_ptr.*}); |
| 1436 | self.markInvalidUserInput(); | 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 | fn allocPrintCmd(ally: Allocator, opt_cwd: ?[]const u8, argv: []const []const u8) ![]u8 { | 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,7 +1649,7 @@ pub fn findProgram(self: *Build, names: []const []const u8, paths: []const []con |
| 1593 | return fs.realpathAlloc(self.allocator, full_path) catch continue; | 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 | for (names) |name| { | 1653 | for (names) |name| { |
| 1598 | if (fs.path.isAbsolute(name)) { | 1654 | if (fs.path.isAbsolute(name)) { |
| 1599 | return name; | 1655 | return name; |
| ... | @@ -1639,7 +1695,7 @@ pub fn runAllowFail( | ... | @@ -1639,7 +1695,7 @@ pub fn runAllowFail( |
| 1639 | child.stdin_behavior = .Ignore; | 1695 | child.stdin_behavior = .Ignore; |
| 1640 | child.stdout_behavior = .Pipe; | 1696 | child.stdout_behavior = .Pipe; |
| 1641 | child.stderr_behavior = stderr_behavior; | 1697 | child.stderr_behavior = stderr_behavior; |
| 1642 | child.env_map = self.env_map; | 1698 | child.env_map = &self.graph.env_map; |
| 1643 | 1699 | ||
| 1644 | try child.spawn(); | 1700 | try child.spawn(); |
| 1645 | 1701 | ||
| ... | @@ -1685,8 +1741,8 @@ pub fn run(b: *Build, argv: []const []const u8) []u8 { | ... | @@ -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 { | 1744 | pub fn addSearchPrefix(b: *Build, search_prefix: []const u8) void { |
| 1689 | self.search_prefixes.append(self.dupePath(search_prefix)) catch @panic("OOM"); | 1745 | b.search_prefixes.append(b.allocator, b.dupePath(search_prefix)) catch @panic("OOM"); |
| 1690 | } | 1746 | } |
| 1691 | 1747 | ||
| 1692 | pub fn getInstallPath(self: *Build, dir: InstallDir, dest_rel_path: []const u8) []const u8 { | 1748 | pub fn getInstallPath(self: *Build, dir: InstallDir, dest_rel_path: []const u8) []const u8 { |
| ... | @@ -1747,21 +1803,63 @@ pub const Dependency = struct { | ... | @@ -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 | const build_runner = @import("root"); | 1833 | const build_runner = @import("root"); |
| 1752 | const deps = build_runner.dependencies; | 1834 | const deps = build_runner.dependencies; |
| 1835 | const pkg_hash = findPkgHashOrFatal(b, name); | ||
| 1753 | 1836 | ||
| 1754 | const pkg_hash = for (b.available_deps) |dep| { | 1837 | inline for (@typeInfo(deps.packages).Struct.decls) |decl| { |
| 1755 | if (mem.eql(u8, dep[0], name)) break dep[1]; | 1838 | if (mem.eql(u8, decl.name, pkg_hash)) { |
| 1756 | } else { | 1839 | const pkg = @field(deps.packages, decl.name); |
| 1757 | const full_path = b.pathFromRoot("build.zig.zon"); | 1840 | const available = !@hasDecl(pkg, "available") or pkg.available; |
| 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 }); | 1841 | if (!available) { |
| 1759 | process.exit(1); | 1842 | markNeededLazyDep(b, pkg_hash); |
| 1760 | }; | 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 | inline for (@typeInfo(deps.packages).Struct.decls) |decl| { | 1857 | inline for (@typeInfo(deps.packages).Struct.decls) |decl| { |
| 1763 | if (mem.eql(u8, decl.name, pkg_hash)) { | 1858 | if (mem.eql(u8, decl.name, pkg_hash)) { |
| 1764 | const pkg = @field(deps.packages, decl.name); | 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 | return dependencyInner(b, name, pkg.build_root, if (@hasDecl(pkg, "build_zig")) pkg.build_zig else null, pkg.deps, args); | 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,9 +2379,14 @@ pub const ResolvedTarget = struct { |
| 2281 | /// Converts a target query into a fully resolved target that can be passed to | 2379 | /// Converts a target query into a fully resolved target that can be passed to |
| 2282 | /// various parts of the API. | 2380 | /// various parts of the API. |
| 2283 | pub fn resolveTargetQuery(b: *Build, query: Target.Query) ResolvedTarget { | 2381 | pub fn resolveTargetQuery(b: *Build, query: Target.Query) ResolvedTarget { |
| 2284 | // This context will likely be required in the future when the target is | 2382 | if (query.isNative()) { |
| 2285 | // resolved via a WASI API or via the build protocol. | 2383 | var adjusted = b.host; |
| 2286 | _ = b; | 2384 | if (query.ofmt) |ofmt| { |
| 2385 | adjusted.query.ofmt = ofmt; | ||
| 2386 | adjusted.result.ofmt = ofmt; | ||
| 2387 | } | ||
| 2388 | return adjusted; | ||
| 2389 | } | ||
| 2287 | 2390 | ||
| 2288 | return .{ | 2391 | return .{ |
| 2289 | .query = query, | 2392 | .query = query, |
| ... | @@ -2296,6 +2399,40 @@ pub fn wantSharedLibSymLinks(target: Target) bool { | ... | @@ -2296,6 +2399,40 @@ pub fn wantSharedLibSymLinks(target: Target) bool { |
| 2296 | return target.os.tag != .windows; | 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 | test { | 2436 | test { |
| 2300 | _ = Cache; | 2437 | _ = Cache; |
| 2301 | _ = Step; | 2438 | _ = Step; |
lib/std/Build/Step.zig+1-1| ... | @@ -314,7 +314,7 @@ pub fn evalZigProcess( | ... | @@ -314,7 +314,7 @@ pub fn evalZigProcess( |
| 314 | try handleVerbose(s.owner, null, argv); | 314 | try handleVerbose(s.owner, null, argv); |
| 315 | 315 | ||
| 316 | var child = std.ChildProcess.init(argv, arena); | 316 | var child = std.ChildProcess.init(argv, arena); |
| 317 | child.env_map = b.env_map; | 317 | child.env_map = &b.graph.env_map; |
| 318 | child.stdin_behavior = .Pipe; | 318 | child.stdin_behavior = .Pipe; |
| 319 | child.stdout_behavior = .Pipe; | 319 | child.stdout_behavior = .Pipe; |
| 320 | child.stderr_behavior = .Pipe; | 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,7 +923,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { |
| 923 | var zig_args = ArrayList([]const u8).init(arena); | 923 | var zig_args = ArrayList([]const u8).init(arena); |
| 924 | defer zig_args.deinit(); | 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 | const cmd = switch (self.kind) { | 928 | const cmd = switch (self.kind) { |
| 929 | .lib => "build-lib", | 929 | .lib => "build-lib", |
| ... | @@ -933,6 +933,16 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { | ... | @@ -933,6 +933,16 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { |
| 933 | }; | 933 | }; |
| 934 | try zig_args.append(cmd); | 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 | if (b.reference_trace) |some| { | 946 | if (b.reference_trace) |some| { |
| 937 | try zig_args.append(try std.fmt.allocPrint(arena, "-freference-trace={d}", .{some})); | 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,7 +1403,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { |
| 1393 | try zig_args.append(b.cache_root.path orelse "."); | 1403 | try zig_args.append(b.cache_root.path orelse "."); |
| 1394 | 1404 | ||
| 1395 | try zig_args.append("--global-cache-dir"); | 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 | try zig_args.append("--name"); | 1408 | try zig_args.append("--name"); |
| 1399 | try zig_args.append(self.name); | 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,7 +171,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { |
| 171 | const gpa = b.allocator; | 171 | const gpa = b.allocator; |
| 172 | const arena = b.allocator; | 172 | const arena = b.allocator; |
| 173 | 173 | ||
| 174 | var man = b.cache.obtain(); | 174 | var man = b.graph.cache.obtain(); |
| 175 | defer man.deinit(); | 175 | defer man.deinit(); |
| 176 | 176 | ||
| 177 | // Random bytes to make ConfigHeader unique. Refresh this with new | 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,7 +52,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { |
| 52 | var argv: std.ArrayListUnmanaged([]const u8) = .{}; | 52 | var argv: std.ArrayListUnmanaged([]const u8) = .{}; |
| 53 | try argv.ensureUnusedCapacity(arena, 2 + 1 + self.paths.len + 2 * self.exclude_paths.len); | 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 | argv.appendAssumeCapacity("fmt"); | 56 | argv.appendAssumeCapacity("fmt"); |
| 57 | 57 | ||
| 58 | if (self.check) { | 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,7 +94,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { |
| 94 | const b = step.owner; | 94 | const b = step.owner; |
| 95 | const self = @fieldParentPtr(ObjCopy, "step", step); | 95 | const self = @fieldParentPtr(ObjCopy, "step", step); |
| 96 | 96 | ||
| 97 | var man = b.cache.obtain(); | 97 | var man = b.graph.cache.obtain(); |
| 98 | defer man.deinit(); | 98 | defer man.deinit(); |
| 99 | 99 | ||
| 100 | // Random bytes to make ObjCopy unique. Refresh this with new random | 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,7 +133,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { |
| 133 | }; | 133 | }; |
| 134 | 134 | ||
| 135 | var argv = std.ArrayList([]const u8).init(b.allocator); | 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 | if (self.only_section) |only_section| { | 138 | if (self.only_section) |only_section| { |
| 139 | try argv.appendSlice(&.{ "-j", only_section }); | 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,7 +222,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { |
| 222 | const basename = "options.zig"; | 222 | const basename = "options.zig"; |
| 223 | 223 | ||
| 224 | // Hash contents to file name. | 224 | // Hash contents to file name. |
| 225 | var hash = b.cache.hash; | 225 | var hash = b.graph.cache.hash; |
| 226 | // Random bytes to make unique. Refresh this with new random bytes when | 226 | // Random bytes to make unique. Refresh this with new random bytes when |
| 227 | // implementation is modified in a non-backwards-compatible way. | 227 | // implementation is modified in a non-backwards-compatible way. |
| 228 | hash.add(@as(u32, 0xad95e922)); | 228 | hash.add(@as(u32, 0xad95e922)); |
| ... | @@ -301,27 +301,28 @@ test Options { | ... | @@ -301,27 +301,28 @@ test Options { |
| 301 | var arena = std.heap.ArenaAllocator.init(std.testing.allocator); | 301 | var arena = std.heap.ArenaAllocator.init(std.testing.allocator); |
| 302 | defer arena.deinit(); | 302 | defer arena.deinit(); |
| 303 | 303 | ||
| 304 | const host: std.Build.ResolvedTarget = .{ | 304 | var graph: std.Build.Graph = .{ |
| 305 | .query = .{}, | 305 | .arena = arena.allocator(), |
| 306 | .result = try std.zig.system.resolveTargetQuery(.{}), | 306 | .cache = .{ |
| 307 | }; | 307 | .gpa = arena.allocator(), |
| 308 | 308 | .manifest_dir = std.fs.cwd(), | |
| 309 | var cache: std.Build.Cache = .{ | 309 | }, |
| 310 | .gpa = arena.allocator(), | 310 | .zig_exe = "test", |
| 311 | .manifest_dir = std.fs.cwd(), | 311 | .env_map = std.process.EnvMap.init(arena.allocator()), |
| 312 | .global_cache_root = .{ .path = "test", .handle = std.fs.cwd() }, | ||
| 312 | }; | 313 | }; |
| 313 | 314 | ||
| 314 | var builder = try std.Build.create( | 315 | var builder = try std.Build.create( |
| 315 | arena.allocator(), | 316 | &graph, |
| 316 | "test", | ||
| 317 | .{ .path = "test", .handle = std.fs.cwd() }, | 317 | .{ .path = "test", .handle = std.fs.cwd() }, |
| 318 | .{ .path = "test", .handle = std.fs.cwd() }, | 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 | const options = builder.addOptions(); | 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,7 +463,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { |
| 463 | var argv_list = ArrayList([]const u8).init(arena); | 463 | var argv_list = ArrayList([]const u8).init(arena); |
| 464 | var output_placeholders = ArrayList(IndexedOutput).init(arena); | 464 | var output_placeholders = ArrayList(IndexedOutput).init(arena); |
| 465 | 465 | ||
| 466 | var man = b.cache.obtain(); | 466 | var man = b.graph.cache.obtain(); |
| 467 | defer man.deinit(); | 467 | defer man.deinit(); |
| 468 | 468 | ||
| 469 | for (self.argv.items) |arg| { | 469 | for (self.argv.items) |arg| { |
| ... | @@ -1036,7 +1036,7 @@ fn spawnChildAndCollect( | ... | @@ -1036,7 +1036,7 @@ fn spawnChildAndCollect( |
| 1036 | child.cwd = b.build_root.path; | 1036 | child.cwd = b.build_root.path; |
| 1037 | child.cwd_dir = b.build_root.handle; | 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 | child.request_resource_usage_statistics = true; | 1040 | child.request_resource_usage_statistics = true; |
| 1041 | 1041 | ||
| 1042 | child.stdin_behavior = switch (self.stdio) { | 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,7 +121,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { |
| 121 | const self = @fieldParentPtr(TranslateC, "step", step); | 121 | const self = @fieldParentPtr(TranslateC, "step", step); |
| 122 | 122 | ||
| 123 | var argv_list = std.ArrayList([]const u8).init(b.allocator); | 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 | try argv_list.append("translate-c"); | 125 | try argv_list.append("translate-c"); |
| 126 | if (self.link_libc) { | 126 | if (self.link_libc) { |
| 127 | try argv_list.append("-lc"); | 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,7 +190,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { |
| 190 | // If, for example, a hard-coded path was used as the location to put WriteFile | 190 | // If, for example, a hard-coded path was used as the location to put WriteFile |
| 191 | // files, then two WriteFiles executing in parallel might clobber each other. | 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 | defer man.deinit(); | 194 | defer man.deinit(); |
| 195 | 195 | ||
| 196 | // Random bytes to make WriteFile unique. Refresh this with | 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,7 +468,7 @@ pub fn zigTriple(self: Query, allocator: Allocator) Allocator.Error![]u8 { |
| 468 | } | 468 | } |
| 469 | 469 | ||
| 470 | if (self.glibc_version) |v| { | 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 | try result.ensureUnusedCapacity(name.len + 2); | 472 | try result.ensureUnusedCapacity(name.len + 2); |
| 473 | result.appendAssumeCapacity('-'); | 473 | result.appendAssumeCapacity('-'); |
| 474 | result.appendSliceAssumeCapacity(name); | 474 | result.appendSliceAssumeCapacity(name); |
lib/std/child_process.zig+3-1| ... | @@ -298,7 +298,9 @@ pub const ChildProcess = struct { | ... | @@ -298,7 +298,9 @@ pub const ChildProcess = struct { |
| 298 | // we could make this work with multiple allocators but YAGNI | 298 | // we could make this work with multiple allocators but YAGNI |
| 299 | if (stdout.allocator.ptr != stderr.allocator.ptr or | 299 | if (stdout.allocator.ptr != stderr.allocator.ptr or |
| 300 | stdout.allocator.vtable != stderr.allocator.vtable) | 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 | var poller = std.io.poll(stdout.allocator, enum { stdout, stderr }, .{ | 305 | var poller = std.io.poll(stdout.allocator, enum { stdout, stderr }, .{ |
| 304 | .stdout = child.stdout.?, | 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,6 +4530,9 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: *std.P |
| 4530 | log.err("{}: failed to parse clang diagnostics: {s}", .{ err, stderr }); | 4530 | log.err("{}: failed to parse clang diagnostics: {s}", .{ err, stderr }); |
| 4531 | return comp.failCObj(c_object, "clang exited with code {d}", .{code}); | 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 | return comp.failCObjWithOwnedDiagBundle(c_object, bundle); | 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,6 +31,8 @@ arena: std.heap.ArenaAllocator, |
| 31 | location: Location, | 31 | location: Location, |
| 32 | location_tok: std.zig.Ast.TokenIndex, | 32 | location_tok: std.zig.Ast.TokenIndex, |
| 33 | hash_tok: std.zig.Ast.TokenIndex, | 33 | hash_tok: std.zig.Ast.TokenIndex, |
| 34 | name_tok: std.zig.Ast.TokenIndex, | ||
| 35 | lazy_status: LazyStatus, | ||
| 34 | parent_package_root: Package.Path, | 36 | parent_package_root: Package.Path, |
| 35 | parent_manifest_ast: ?*const std.zig.Ast, | 37 | parent_manifest_ast: ?*const std.zig.Ast, |
| 36 | prog_node: *std.Progress.Node, | 38 | prog_node: *std.Progress.Node, |
| ... | @@ -64,6 +66,15 @@ oom_flag: bool, | ... | @@ -64,6 +66,15 @@ oom_flag: bool, |
| 64 | /// the root source file. | 66 | /// the root source file. |
| 65 | module: ?*Package.Module, | 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 | /// Contains shared state among all `Fetch` tasks. | 78 | /// Contains shared state among all `Fetch` tasks. |
| 68 | pub const JobQueue = struct { | 79 | pub const JobQueue = struct { |
| 69 | mutex: std.Thread.Mutex = .{}, | 80 | mutex: std.Thread.Mutex = .{}, |
| ... | @@ -80,14 +91,27 @@ pub const JobQueue = struct { | ... | @@ -80,14 +91,27 @@ pub const JobQueue = struct { |
| 80 | thread_pool: *ThreadPool, | 91 | thread_pool: *ThreadPool, |
| 81 | wait_group: WaitGroup = .{}, | 92 | wait_group: WaitGroup = .{}, |
| 82 | global_cache: Cache.Directory, | 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 | recursive: bool, | 103 | recursive: bool, |
| 84 | /// Dumps hash information to stdout which can be used to troubleshoot why | 104 | /// Dumps hash information to stdout which can be used to troubleshoot why |
| 85 | /// two hashes of the same package do not match. | 105 | /// two hashes of the same package do not match. |
| 86 | /// If this is true, `recursive` must be false. | 106 | /// If this is true, `recursive` must be false. |
| 87 | debug_hash: bool, | 107 | debug_hash: bool, |
| 88 | work_around_btrfs_bug: bool, | 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 | pub const Table = std.AutoArrayHashMapUnmanaged(Manifest.MultiHashHexDigest, *Fetch); | 113 | pub const Table = std.AutoArrayHashMapUnmanaged(Manifest.MultiHashHexDigest, *Fetch); |
| 114 | pub const UnlazySet = std.AutoArrayHashMapUnmanaged(Manifest.MultiHashHexDigest, void); | ||
| 91 | 115 | ||
| 92 | pub fn deinit(jq: *JobQueue) void { | 116 | pub fn deinit(jq: *JobQueue) void { |
| 93 | if (jq.all_fetches.items.len == 0) return; | 117 | if (jq.all_fetches.items.len == 0) return; |
| ... | @@ -141,11 +165,37 @@ pub const JobQueue = struct { | ... | @@ -141,11 +165,37 @@ pub const JobQueue = struct { |
| 141 | // The first one is a dummy package for the current project. | 165 | // The first one is a dummy package for the current project. |
| 142 | continue; | 166 | continue; |
| 143 | } | 167 | } |
| 168 | |||
| 144 | try buf.writer().print( | 169 | try buf.writer().print( |
| 145 | \\ pub const {} = struct {{ | 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 | \\ pub const build_root = "{q}"; | 196 | \\ pub const build_root = "{q}"; |
| 147 | \\ | 197 | \\ |
| 148 | , .{ std.zig.fmtId(&hash), fetch.package_root }); | 198 | , .{fetch.package_root}); |
| 149 | 199 | ||
| 150 | if (fetch.has_build_zig) { | 200 | if (fetch.has_build_zig) { |
| 151 | try buf.writer().print( | 201 | try buf.writer().print( |
| ... | @@ -270,7 +320,8 @@ pub fn run(f: *Fetch) RunError!void { | ... | @@ -270,7 +320,8 @@ pub fn run(f: *Fetch) RunError!void { |
| 270 | // We want to fail unless the resolved relative path has a | 320 | // We want to fail unless the resolved relative path has a |
| 271 | // prefix of "p/$hash/". | 321 | // prefix of "p/$hash/". |
| 272 | const digest_len = @typeInfo(Manifest.MultiHashHexDigest).Array.len; | 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 | if (!std.mem.startsWith(u8, pkg_root.sub_path, expected_prefix)) { | 325 | if (!std.mem.startsWith(u8, pkg_root.sub_path, expected_prefix)) { |
| 275 | return f.fail( | 326 | return f.fail( |
| 276 | f.location_tok, | 327 | f.location_tok, |
| ... | @@ -311,8 +362,11 @@ pub fn run(f: *Fetch) RunError!void { | ... | @@ -311,8 +362,11 @@ pub fn run(f: *Fetch) RunError!void { |
| 311 | 362 | ||
| 312 | const s = fs.path.sep_str; | 363 | const s = fs.path.sep_str; |
| 313 | if (remote.hash) |expected_hash| { | 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 | if (cache_root.handle.access(pkg_sub_path, .{})) |_| { | 368 | if (cache_root.handle.access(pkg_sub_path, .{})) |_| { |
| 369 | assert(f.lazy_status != .unavailable); | ||
| 316 | f.package_root = .{ | 370 | f.package_root = .{ |
| 317 | .root_dir = cache_root, | 371 | .root_dir = cache_root, |
| 318 | .sub_path = try arena.dupe(u8, pkg_sub_path), | 372 | .sub_path = try arena.dupe(u8, pkg_sub_path), |
| ... | @@ -322,7 +376,22 @@ pub fn run(f: *Fetch) RunError!void { | ... | @@ -322,7 +376,22 @@ pub fn run(f: *Fetch) RunError!void { |
| 322 | if (!f.job_queue.recursive) return; | 376 | if (!f.job_queue.recursive) return; |
| 323 | return queueJobsForDeps(f); | 377 | return queueJobsForDeps(f); |
| 324 | } else |err| switch (err) { | 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 | else => |e| { | 395 | else => |e| { |
| 327 | try eb.addRootErrorMessage(.{ | 396 | try eb.addRootErrorMessage(.{ |
| 328 | .msg = try eb.printString("unable to open global package cache directory '{}{s}': {s}", .{ | 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,6 +401,12 @@ pub fn run(f: *Fetch) RunError!void { |
| 332 | return error.FetchFailed; | 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 | // Fetch and unpack the remote into a temporary directory. | 412 | // Fetch and unpack the remote into a temporary directory. |
| ... | @@ -602,6 +677,8 @@ fn queueJobsForDeps(f: *Fetch) RunError!void { | ... | @@ -602,6 +677,8 @@ fn queueJobsForDeps(f: *Fetch) RunError!void { |
| 602 | .location = location, | 677 | .location = location, |
| 603 | .location_tok = dep.location_tok, | 678 | .location_tok = dep.location_tok, |
| 604 | .hash_tok = dep.hash_tok, | 679 | .hash_tok = dep.hash_tok, |
| 680 | .name_tok = dep.name_tok, | ||
| 681 | .lazy_status = if (dep.lazy) .available else .eager, | ||
| 605 | .parent_package_root = f.package_root, | 682 | .parent_package_root = f.package_root, |
| 606 | .parent_manifest_ast = &f.manifest_ast, | 683 | .parent_manifest_ast = &f.manifest_ast, |
| 607 | .prog_node = f.prog_node, | 684 | .prog_node = f.prog_node, |
src/Package/Manifest.zig+28| ... | @@ -12,6 +12,8 @@ pub const Dependency = struct { | ... | @@ -12,6 +12,8 @@ pub const Dependency = struct { |
| 12 | hash: ?[]const u8, | 12 | hash: ?[]const u8, |
| 13 | hash_tok: Ast.TokenIndex, | 13 | hash_tok: Ast.TokenIndex, |
| 14 | node: Ast.Node.Index, | 14 | node: Ast.Node.Index, |
| 15 | name_tok: Ast.TokenIndex, | ||
| 16 | lazy: bool, | ||
| 15 | 17 | ||
| 16 | pub const Location = union(enum) { | 18 | pub const Location = union(enum) { |
| 17 | url: []const u8, | 19 | url: []const u8, |
| ... | @@ -303,11 +305,14 @@ const Parse = struct { | ... | @@ -303,11 +305,14 @@ const Parse = struct { |
| 303 | .hash = null, | 305 | .hash = null, |
| 304 | .hash_tok = 0, | 306 | .hash_tok = 0, |
| 305 | .node = node, | 307 | .node = node, |
| 308 | .name_tok = 0, | ||
| 309 | .lazy = false, | ||
| 306 | }; | 310 | }; |
| 307 | var has_location = false; | 311 | var has_location = false; |
| 308 | 312 | ||
| 309 | for (struct_init.ast.fields) |field_init| { | 313 | for (struct_init.ast.fields) |field_init| { |
| 310 | const name_token = ast.firstToken(field_init) - 2; | 314 | const name_token = ast.firstToken(field_init) - 2; |
| 315 | dep.name_tok = name_token; | ||
| 311 | const field_name = try identifierTokenString(p, name_token); | 316 | const field_name = try identifierTokenString(p, name_token); |
| 312 | // We could get fancy with reflection and comptime logic here but doing | 317 | // We could get fancy with reflection and comptime logic here but doing |
| 313 | // things manually provides an opportunity to do any additional verification | 318 | // things manually provides an opportunity to do any additional verification |
| ... | @@ -342,6 +347,11 @@ const Parse = struct { | ... | @@ -342,6 +347,11 @@ const Parse = struct { |
| 342 | else => |e| return e, | 347 | else => |e| return e, |
| 343 | }; | 348 | }; |
| 344 | dep.hash_tok = main_tokens[field_init]; | 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 | } else { | 355 | } else { |
| 346 | // Ignore unknown fields so that we can add fields in future zig | 356 | // Ignore unknown fields so that we can add fields in future zig |
| 347 | // versions without breaking older zig versions. | 357 | // versions without breaking older zig versions. |
| ... | @@ -374,6 +384,24 @@ const Parse = struct { | ... | @@ -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 | fn parseString(p: *Parse, node: Ast.Node.Index) ![]const u8 { | 405 | fn parseString(p: *Parse, node: Ast.Node.Index) ![]const u8 { |
| 378 | const ast = p.ast; | 406 | const ast = p.ast; |
| 379 | const node_tags = ast.nodes.items(.tag); | 407 | const node_tags = ast.nodes.items(.tag); |
src/main.zig+545-422| ... | @@ -969,6 +969,9 @@ fn buildOutputType( | ... | @@ -969,6 +969,9 @@ fn buildOutputType( |
| 969 | .libc_paths_file = try EnvVar.ZIG_LIBC.get(arena), | 969 | .libc_paths_file = try EnvVar.ZIG_LIBC.get(arena), |
| 970 | .link_objects = .{}, | 970 | .link_objects = .{}, |
| 971 | .native_system_include_paths = &.{}, | 971 | .native_system_include_paths = &.{}, |
| 972 | .host_triple = null, | ||
| 973 | .host_cpu = null, | ||
| 974 | .host_dynamic_linker = null, | ||
| 972 | }; | 975 | }; |
| 973 | 976 | ||
| 974 | // before arg parsing, check for the NO_COLOR environment variable | 977 | // before arg parsing, check for the NO_COLOR environment variable |
| ... | @@ -1262,6 +1265,12 @@ fn buildOutputType( | ... | @@ -1262,6 +1265,12 @@ fn buildOutputType( |
| 1262 | mod_opts.optimize_mode = parseOptimizeMode(arg["-O".len..]); | 1265 | mod_opts.optimize_mode = parseOptimizeMode(arg["-O".len..]); |
| 1263 | } else if (mem.eql(u8, arg, "--dynamic-linker")) { | 1266 | } else if (mem.eql(u8, arg, "--dynamic-linker")) { |
| 1264 | create_module.dynamic_linker = args_iter.nextOrFatal(); | 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 | } else if (mem.eql(u8, arg, "--sysroot")) { | 1274 | } else if (mem.eql(u8, arg, "--sysroot")) { |
| 1266 | const next_arg = args_iter.nextOrFatal(); | 1275 | const next_arg = args_iter.nextOrFatal(); |
| 1267 | create_module.sysroot = next_arg; | 1276 | create_module.sysroot = next_arg; |
| ... | @@ -3455,6 +3464,9 @@ const CreateModule = struct { | ... | @@ -3455,6 +3464,9 @@ const CreateModule = struct { |
| 3455 | each_lib_rpath: ?bool, | 3464 | each_lib_rpath: ?bool, |
| 3456 | libc_paths_file: ?[]const u8, | 3465 | libc_paths_file: ?[]const u8, |
| 3457 | link_objects: std.ArrayListUnmanaged(Compilation.LinkObject), | 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 | fn createModule( | 3472 | fn createModule( |
| ... | @@ -3539,7 +3551,15 @@ fn createModule( | ... | @@ -3539,7 +3551,15 @@ fn createModule( |
| 3539 | } | 3551 | } |
| 3540 | 3552 | ||
| 3541 | const target_query = parseTargetQueryOrReportFatalError(arena, target_parse_options); | 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 | break :t .{ | 3563 | break :t .{ |
| 3544 | .result = target, | 3564 | .result = target, |
| 3545 | .is_native_os = target_query.isNativeOs(), | 3565 | .is_native_os = target_query.isNativeOs(), |
| ... | @@ -5130,476 +5150,576 @@ pub const usage_build = | ... | @@ -5130,476 +5150,576 @@ pub const usage_build = |
| 5130 | ; | 5150 | ; |
| 5131 | 5151 | ||
| 5132 | pub fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void { | 5152 | pub fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void { |
| 5133 | const work_around_btrfs_bug = builtin.os.tag == .linux and | 5153 | var progress: std.Progress = .{ .dont_print_on_dumb = true }; |
| 5134 | EnvVar.ZIG_BTRFS_WORKAROUND.isSet(); | ||
| 5135 | const color: Color = .auto; | ||
| 5136 | 5154 | ||
| 5137 | // We want to release all the locks before executing the child process, so we make a nice | 5155 | var build_file: ?[]const u8 = null; |
| 5138 | // big block here to ensure the cleanup gets run when we extract out our argv. | 5156 | var override_lib_dir: ?[]const u8 = try EnvVar.ZIG_LIB_DIR.get(arena); |
| 5139 | const child_argv = argv: { | 5157 | var override_global_cache_dir: ?[]const u8 = try EnvVar.ZIG_GLOBAL_CACHE_DIR.get(arena); |
| 5140 | const self_exe_path = try introspect.findZigExePath(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; | 5177 | const argv_index_exe = child_argv.items.len; |
| 5143 | var override_lib_dir: ?[]const u8 = try EnvVar.ZIG_LIB_DIR.get(arena); | 5178 | _ = try child_argv.addOne(); |
| 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; | ||
| 5182 | 5179 | ||
| 5183 | { | 5180 | const self_exe_path = try introspect.findZigExePath(arena); |
| 5184 | var i: usize = 0; | 5181 | try child_argv.append(self_exe_path); |
| 5185 | while (i < args.len) : (i += 1) { | 5182 | |
| 5186 | const arg = args[i]; | 5183 | const argv_index_build_file = child_argv.items.len; |
| 5187 | if (mem.startsWith(u8, arg, "-")) { | 5184 | _ = try child_argv.addOne(); |
| 5188 | if (mem.eql(u8, arg, "--build-file")) { | 5185 | |
| 5189 | if (i + 1 >= args.len) fatal("expected argument after '{s}'", .{arg}); | 5186 | const argv_index_cache_dir = child_argv.items.len; |
| 5190 | i += 1; | 5187 | _ = try child_argv.addOne(); |
| 5191 | build_file = args[i]; | 5188 | |
| 5192 | continue; | 5189 | const argv_index_global_cache_dir = child_argv.items.len; |
| 5193 | } else if (mem.eql(u8, arg, "--zig-lib-dir")) { | 5190 | _ = try child_argv.addOne(); |
| 5194 | if (i + 1 >= args.len) fatal("expected argument after '{s}'", .{arg}); | 5191 | |
| 5195 | i += 1; | 5192 | try child_argv.appendSlice(&.{ |
| 5196 | override_lib_dir = args[i]; | 5193 | "--seed", |
| 5197 | try child_argv.appendSlice(&.{ arg, args[i] }); | 5194 | try std.fmt.allocPrint(arena, "0x{x}", .{std.crypto.random.int(u32)}), |
| 5198 | continue; | 5195 | }); |
| 5199 | } else if (mem.eql(u8, arg, "--build-runner")) { | 5196 | const argv_index_seed = child_argv.items.len - 1; |
| 5200 | if (i + 1 >= args.len) fatal("expected argument after '{s}'", .{arg}); | 5197 | |
| 5201 | i += 1; | 5198 | // This parent process needs a way to obtain results from the configuration |
| 5202 | override_build_runner = args[i]; | 5199 | // phase of the child process. In the future, the make phase will be |
| 5203 | continue; | 5200 | // executed in a separate process than the configure phase, and we can then |
| 5204 | } else if (mem.eql(u8, arg, "--cache-dir")) { | 5201 | // use stdout from the configuration phase for this purpose. |
| 5205 | if (i + 1 >= args.len) fatal("expected argument after '{s}'", .{arg}); | 5202 | // |
| 5206 | i += 1; | 5203 | // However, currently, both phases are in the same process, and Run Step |
| 5207 | override_local_cache_dir = args[i]; | 5204 | // provides API for making the runned subprocesses inherit stdout and stderr |
| 5208 | continue; | 5205 | // which means these streams are not available for passing metadata back |
| 5209 | } else if (mem.eql(u8, arg, "--global-cache-dir")) { | 5206 | // to the parent. |
| 5210 | if (i + 1 >= args.len) fatal("expected argument after '{s}'", .{arg}); | 5207 | // |
| 5211 | i += 1; | 5208 | // Until make and configure phases are separated into different processes, |
| 5212 | override_global_cache_dir = args[i]; | 5209 | // the strategy is to choose a temporary file name ahead of time, and then |
| 5213 | continue; | 5210 | // read this file in the parent to obtain the results, in the case the child |
| 5214 | } else if (mem.eql(u8, arg, "-freference-trace")) { | 5211 | // exits with code 3. |
| 5215 | reference_trace = 256; | 5212 | const results_tmp_file_nonce = Package.Manifest.hex64(std.crypto.random.int(u64)); |
| 5216 | } else if (mem.eql(u8, arg, "--fetch")) { | 5213 | try child_argv.append("-Z" ++ results_tmp_file_nonce); |
| 5217 | fetch_only = true; | 5214 | |
| 5218 | } else if (mem.startsWith(u8, arg, "-freference-trace=")) { | 5215 | { |
| 5219 | const num = arg["-freference-trace=".len..]; | 5216 | var i: usize = 0; |
| 5220 | reference_trace = std.fmt.parseUnsigned(u32, num, 10) catch |err| { | 5217 | while (i < args.len) : (i += 1) { |
| 5221 | fatal("unable to parse reference_trace count '{s}': {s}", .{ num, @errorName(err) }); | 5218 | const arg = args[i]; |
| 5222 | }; | 5219 | if (mem.startsWith(u8, arg, "-")) { |
| 5223 | } else if (mem.eql(u8, arg, "-fno-reference-trace")) { | 5220 | if (mem.eql(u8, arg, "--build-file")) { |
| 5224 | reference_trace = null; | 5221 | if (i + 1 >= args.len) fatal("expected argument after '{s}'", .{arg}); |
| 5225 | } else if (mem.eql(u8, arg, "--debug-log")) { | 5222 | i += 1; |
| 5226 | if (i + 1 >= args.len) fatal("expected argument after '{s}'", .{arg}); | 5223 | build_file = args[i]; |
| 5227 | try child_argv.appendSlice(args[i .. i + 2]); | 5224 | continue; |
| 5228 | i += 1; | 5225 | } else if (mem.eql(u8, arg, "--zig-lib-dir")) { |
| 5229 | if (!build_options.enable_logging) { | 5226 | if (i + 1 >= args.len) fatal("expected argument after '{s}'", .{arg}); |
| 5230 | warn("Zig was compiled without logging enabled (-Dlog). --debug-log has no effect.", .{}); | 5227 | i += 1; |
| 5231 | } else { | 5228 | override_lib_dir = args[i]; |
| 5232 | try log_scopes.append(arena, args[i]); | 5229 | try child_argv.appendSlice(&.{ arg, args[i] }); |
| 5233 | } | 5230 | continue; |
| 5234 | continue; | 5231 | } else if (mem.eql(u8, arg, "--build-runner")) { |
| 5235 | } else if (mem.eql(u8, arg, "--debug-compile-errors")) { | 5232 | if (i + 1 >= args.len) fatal("expected argument after '{s}'", .{arg}); |
| 5236 | if (!crash_report.is_enabled) { | 5233 | i += 1; |
| 5237 | warn("Zig was compiled in a release mode. --debug-compile-errors has no effect.", .{}); | 5234 | override_build_runner = args[i]; |
| 5238 | } else { | 5235 | continue; |
| 5239 | debug_compile_errors = true; | 5236 | } else if (mem.eql(u8, arg, "--cache-dir")) { |
| 5240 | } | 5237 | if (i + 1 >= args.len) fatal("expected argument after '{s}'", .{arg}); |
| 5241 | } else if (mem.eql(u8, arg, "--verbose-link")) { | 5238 | i += 1; |
| 5242 | verbose_link = true; | 5239 | override_local_cache_dir = args[i]; |
| 5243 | } else if (mem.eql(u8, arg, "--verbose-cc")) { | 5240 | continue; |
| 5244 | verbose_cc = true; | 5241 | } else if (mem.eql(u8, arg, "--global-cache-dir")) { |
| 5245 | } else if (mem.eql(u8, arg, "--verbose-air")) { | 5242 | if (i + 1 >= args.len) fatal("expected argument after '{s}'", .{arg}); |
| 5246 | verbose_air = true; | 5243 | i += 1; |
| 5247 | } else if (mem.eql(u8, arg, "--verbose-intern-pool")) { | 5244 | override_global_cache_dir = args[i]; |
| 5248 | verbose_intern_pool = true; | 5245 | continue; |
| 5249 | } else if (mem.eql(u8, arg, "--verbose-generic-instances")) { | 5246 | } else if (mem.eql(u8, arg, "-freference-trace")) { |
| 5250 | verbose_generic_instances = true; | 5247 | reference_trace = 256; |
| 5251 | } else if (mem.eql(u8, arg, "--verbose-llvm-ir")) { | 5248 | } else if (mem.eql(u8, arg, "--fetch")) { |
| 5252 | verbose_llvm_ir = "-"; | 5249 | fetch_only = true; |
| 5253 | } else if (mem.startsWith(u8, arg, "--verbose-llvm-ir=")) { | 5250 | } else if (mem.eql(u8, arg, "--system")) { |
| 5254 | verbose_llvm_ir = arg["--verbose-llvm-ir=".len..]; | 5251 | if (i + 1 >= args.len) fatal("expected argument after '{s}'", .{arg}); |
| 5255 | } else if (mem.startsWith(u8, arg, "--verbose-llvm-bc=")) { | 5252 | i += 1; |
| 5256 | verbose_llvm_bc = arg["--verbose-llvm-bc=".len..]; | 5253 | system_pkg_dir_path = args[i]; |
| 5257 | } else if (mem.eql(u8, arg, "--verbose-cimport")) { | 5254 | try child_argv.append("--system"); |
| 5258 | verbose_cimport = true; | 5255 | continue; |
| 5259 | } else if (mem.eql(u8, arg, "--verbose-llvm-cpu-features")) { | 5256 | } else if (mem.startsWith(u8, arg, "-freference-trace=")) { |
| 5260 | verbose_llvm_cpu_features = true; | 5257 | const num = arg["-freference-trace=".len..]; |
| 5261 | } else if (mem.eql(u8, arg, "--seed")) { | 5258 | reference_trace = std.fmt.parseUnsigned(u32, num, 10) catch |err| { |
| 5262 | if (i + 1 >= args.len) fatal("expected argument after '{s}'", .{arg}); | 5259 | fatal("unable to parse reference_trace count '{s}': {s}", .{ num, @errorName(err) }); |
| 5263 | i += 1; | 5260 | }; |
| 5264 | child_argv.items[argv_index_seed] = args[i]; | 5261 | } else if (mem.eql(u8, arg, "-fno-reference-trace")) { |
| 5265 | continue; | 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| .{ | 5310 | const work_around_btrfs_bug = builtin.os.tag == .linux and |
| 5273 | .path = lib_dir, | 5311 | EnvVar.ZIG_BTRFS_WORKAROUND.isSet(); |
| 5274 | .handle = fs.cwd().openDir(lib_dir, .{}) catch |err| { | 5312 | const color: Color = .auto; |
| 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(); | ||
| 5281 | 5313 | ||
| 5282 | var cleanup_build_dir: ?fs.Dir = null; | 5314 | const target_query: std.Target.Query = .{}; |
| 5283 | defer if (cleanup_build_dir) |*dir| dir.close(); | 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); | 5321 | const exe_basename = try std.zig.binNameAlloc(arena, .{ |
| 5286 | const build_root = try findBuildRoot(arena, .{ | 5322 | .root_name = "build", |
| 5287 | .cwd_path = cwd_path, | 5323 | .target = resolved_target.result, |
| 5288 | .build_file = build_file, | 5324 | .output_mode = .Exe, |
| 5289 | }); | 5325 | }); |
| 5290 | child_argv.items[argv_index_build_file] = build_root.directory.path orelse cwd_path; | 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: { | 5331 | gimmeMoreOfThoseSweetSweetFileDescriptors(); |
| 5293 | const p = override_global_cache_dir orelse try introspect.resolveGlobalCacheDir(arena); | 5332 | |
| 5294 | break :l .{ | 5333 | var zig_lib_directory: Compilation.Directory = if (override_lib_dir) |lib_dir| .{ |
| 5295 | .handle = try fs.cwd().makeOpenPath(p, .{}), | 5334 | .path = lib_dir, |
| 5296 | .path = p, | 5335 | .handle = fs.cwd().openDir(lib_dir, .{}) catch |err| { |
| 5297 | }; | 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: { | 5361 | var local_cache_directory: Compilation.Directory = l: { |
| 5304 | if (override_local_cache_dir) |local_cache_dir_path| { | 5362 | 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"}); | ||
| 5311 | break :l .{ | 5363 | break :l .{ |
| 5312 | .handle = try build_root.directory.handle.makeOpenPath("zig-cache", .{}), | 5364 | .handle = try fs.cwd().makeOpenPath(local_cache_dir_path, .{}), |
| 5313 | .path = 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 = .{}; | 5382 | // Dummy http client that is not actually used when only_core_functionality is enabled. |
| 5323 | const resolved_target: Package.Module.ResolvedTarget = .{ | 5383 | // Prevents bootstrap from depending on a bunch of unnecessary stuff. |
| 5324 | .result = resolveTargetQueryOrFatal(target_query), | 5384 | const HttpClient = if (build_options.only_core_functionality) struct { |
| 5325 | .is_native_os = true, | 5385 | allocator: Allocator, |
| 5326 | .is_native_abi = true, | 5386 | fn deinit(self: *@This()) void { |
| 5327 | }; | 5387 | _ = self; |
| 5388 | } | ||
| 5389 | } else std.http.Client; | ||
| 5328 | 5390 | ||
| 5329 | const exe_basename = try std.zig.binNameAlloc(arena, .{ | 5391 | var http_client: HttpClient = .{ .allocator = gpa }; |
| 5330 | .root_name = "build", | 5392 | defer http_client.deinit(); |
| 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(); | ||
| 5341 | 5393 | ||
| 5342 | const main_mod_paths: Package.Module.CreateOptions.Paths = if (override_build_runner) |runner| .{ | 5394 | var unlazy_set: Package.Fetch.JobQueue.UnlazySet = .{}; |
| 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 | }; | ||
| 5352 | 5395 | ||
| 5353 | const config = try Compilation.Config.resolve(.{ | 5396 | // This loop is re-evaluated when the build script exits with an indication that it |
| 5354 | .output_mode = .Exe, | 5397 | // could not continue due to missing lazy dependencies. |
| 5355 | .resolved_target = resolved_target, | 5398 | while (true) { |
| 5356 | .have_zcu = true, | 5399 | // We want to release all the locks before executing the child process, so we make a nice |
| 5357 | .emit_bin = true, | 5400 | // big block here to ensure the cleanup gets run when we extract out our argv. |
| 5358 | .is_test = false, | 5401 | { |
| 5359 | }); | 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, .{ | 5413 | const config = try Compilation.Config.resolve(.{ |
| 5362 | .global_cache_directory = global_cache_directory, | 5414 | .output_mode = .Exe, |
| 5363 | .paths = main_mod_paths, | ||
| 5364 | .fully_qualified_name = "root", | ||
| 5365 | .cc_argv = &.{}, | ||
| 5366 | .inherited = .{ | ||
| 5367 | .resolved_target = resolved_target, | 5415 | .resolved_target = resolved_target, |
| 5368 | }, | 5416 | .have_zcu = true, |
| 5369 | .global = config, | 5417 | .emit_bin = true, |
| 5370 | .parent = null, | 5418 | .is_test = false, |
| 5371 | .builtin_mod = null, | 5419 | }); |
| 5372 | }); | ||
| 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, .{ | 5434 | const builtin_mod = root_mod.getBuiltinDependency(); |
| 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(); | ||
| 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 }; | 5450 | var cleanup_build_dir: ?fs.Dir = null; |
| 5405 | const root_prog_node = progress.start("Fetch Packages", 0); | 5451 | defer if (cleanup_build_dir) |*dir| dir.close(); |
| 5406 | defer root_prog_node.end(); | 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 = .{ | 5493 | try job_queue.all_fetches.ensureUnusedCapacity(gpa, 1); |
| 5409 | .http_client = &http_client, | 5494 | try job_queue.table.ensureUnusedCapacity(gpa, 1); |
| 5410 | .thread_pool = &thread_pool, | 5495 | |
| 5411 | .global_cache = global_cache_directory, | 5496 | var fetch: Package.Fetch = .{ |
| 5412 | .recursive = true, | 5497 | .arena = std.heap.ArenaAllocator.init(gpa), |
| 5413 | .debug_hash = false, | 5498 | .location = .{ .relative_path = build_mod.root }, |
| 5414 | .work_around_btrfs_bug = work_around_btrfs_bug, | 5499 | .location_tok = 0, |
| 5415 | }; | 5500 | .hash_tok = 0, |
| 5416 | defer job_queue.deinit(); | 5501 | .name_tok = 0, |
| 5417 | 5502 | .lazy_status = .eager, | |
| 5418 | try job_queue.all_fetches.ensureUnusedCapacity(gpa, 1); | 5503 | .parent_package_root = build_mod.root, |
| 5419 | try job_queue.table.ensureUnusedCapacity(gpa, 1); | 5504 | .parent_manifest_ast = null, |
| 5420 | 5505 | .prog_node = root_prog_node, | |
| 5421 | var fetch: Package.Fetch = .{ | 5506 | .job_queue = &job_queue, |
| 5422 | .arena = std.heap.ArenaAllocator.init(gpa), | 5507 | .omit_missing_hash_error = true, |
| 5423 | .location = .{ .relative_path = build_mod.root }, | 5508 | .allow_missing_paths_field = false, |
| 5424 | .location_tok = 0, | 5509 | |
| 5425 | .hash_tok = 0, | 5510 | .package_root = undefined, |
| 5426 | .parent_package_root = build_mod.root, | 5511 | .error_bundle = undefined, |
| 5427 | .parent_manifest_ast = null, | 5512 | .manifest = null, |
| 5428 | .prog_node = root_prog_node, | 5513 | .manifest_ast = undefined, |
| 5429 | .job_queue = &job_queue, | 5514 | .actual_hash = undefined, |
| 5430 | .omit_missing_hash_error = true, | 5515 | .has_build_zig = true, |
| 5431 | .allow_missing_paths_field = false, | 5516 | .oom_flag = false, |
| 5432 | 5517 | ||
| 5433 | .package_root = undefined, | 5518 | .module = build_mod, |
| 5434 | .error_bundle = undefined, | 5519 | }; |
| 5435 | .manifest = null, | 5520 | job_queue.all_fetches.appendAssumeCapacity(&fetch); |
| 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); | ||
| 5444 | 5521 | ||
| 5445 | job_queue.table.putAssumeCapacityNoClobber( | 5522 | job_queue.table.putAssumeCapacityNoClobber( |
| 5446 | Package.Fetch.relativePathDigest(build_mod.root, global_cache_directory), | 5523 | Package.Fetch.relativePathDigest(build_mod.root, global_cache_directory), |
| 5447 | &fetch, | 5524 | &fetch, |
| 5448 | ); | 5525 | ); |
| 5449 | 5526 | ||
| 5450 | job_queue.wait_group.start(); | 5527 | job_queue.wait_group.start(); |
| 5451 | try job_queue.thread_pool.spawn(Package.Fetch.workerRun, .{ &fetch, "root" }); | 5528 | try job_queue.thread_pool.spawn(Package.Fetch.workerRun, .{ &fetch, "root" }); |
| 5452 | job_queue.wait_group.wait(); | 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) { | 5533 | if (fetch.error_bundle.root_list.items.len > 0) { |
| 5457 | var errors = try fetch.error_bundle.toOwnedBundle(""); | 5534 | var errors = try fetch.error_bundle.toOwnedBundle(""); |
| 5458 | errors.renderToStdErr(renderOptions(color)); | 5535 | errors.renderToStdErr(renderOptions(color)); |
| 5459 | process.exit(1); | 5536 | process.exit(1); |
| 5460 | } | 5537 | } |
| 5461 | 5538 | ||
| 5462 | if (fetch_only) return cleanExit(); | 5539 | if (fetch_only) return cleanExit(); |
| 5463 | 5540 | ||
| 5464 | var source_buf = std.ArrayList(u8).init(gpa); | 5541 | var source_buf = std.ArrayList(u8).init(gpa); |
| 5465 | defer source_buf.deinit(); | 5542 | defer source_buf.deinit(); |
| 5466 | try job_queue.createDependenciesSource(&source_buf); | 5543 | try job_queue.createDependenciesSource(&source_buf); |
| 5467 | const deps_mod = try createDependenciesModule( | 5544 | const deps_mod = try createDependenciesModule( |
| 5468 | arena, | 5545 | arena, |
| 5469 | source_buf.items, | 5546 | source_buf.items, |
| 5470 | root_mod, | 5547 | root_mod, |
| 5471 | global_cache_directory, | 5548 | global_cache_directory, |
| 5472 | local_cache_directory, | 5549 | local_cache_directory, |
| 5473 | builtin_mod, | 5550 | builtin_mod, |
| 5474 | config, | 5551 | config, |
| 5475 | ); | 5552 | ); |
| 5476 | 5553 | ||
| 5477 | { | 5554 | { |
| 5478 | // We need a Module for each package's build.zig. | 5555 | // We need a Module for each package's build.zig. |
| 5479 | const hashes = job_queue.table.keys(); | 5556 | const hashes = job_queue.table.keys(); |
| 5480 | const fetches = job_queue.table.values(); | 5557 | const fetches = job_queue.table.values(); |
| 5481 | try deps_mod.deps.ensureUnusedCapacity(arena, @intCast(hashes.len)); | 5558 | try deps_mod.deps.ensureUnusedCapacity(arena, @intCast(hashes.len)); |
| 5482 | for (hashes, fetches) |hash, f| { | 5559 | for (hashes, fetches) |hash, f| { |
| 5483 | if (f == &fetch) { | 5560 | if (f == &fetch) { |
| 5484 | // The first one is a dummy package for the current project. | 5561 | // The first one is a dummy package for the current project. |
| 5485 | continue; | 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 | 5588 | // Each build.zig module needs access to each of its |
| 5512 | // dependencies' build.zig modules by name. | 5589 | // dependencies' build.zig modules by name. |
| 5513 | for (fetches) |f| { | 5590 | for (fetches) |f| { |
| 5514 | const mod = f.module orelse continue; | 5591 | const mod = f.module orelse continue; |
| 5515 | const man = f.manifest orelse continue; | 5592 | const man = f.manifest orelse continue; |
| 5516 | const dep_names = man.dependencies.keys(); | 5593 | const dep_names = man.dependencies.keys(); |
| 5517 | try mod.deps.ensureUnusedCapacity(arena, @intCast(dep_names.len)); | 5594 | try mod.deps.ensureUnusedCapacity(arena, @intCast(dep_names.len)); |
| 5518 | for (dep_names, man.dependencies.values()) |name, dep| { | 5595 | for (dep_names, man.dependencies.values()) |name, dep| { |
| 5519 | const dep_digest = Package.Fetch.depDigest( | 5596 | const dep_digest = Package.Fetch.depDigest( |
| 5520 | f.package_root, | 5597 | f.package_root, |
| 5521 | global_cache_directory, | 5598 | global_cache_directory, |
| 5522 | dep, | 5599 | dep, |
| 5523 | ) orelse continue; | 5600 | ) orelse continue; |
| 5524 | const dep_mod = job_queue.table.get(dep_digest).?.module orelse continue; | 5601 | const dep_mod = job_queue.table.get(dep_digest).?.module orelse continue; |
| 5525 | const name_cloned = try arena.dupe(u8, name); | 5602 | const name_cloned = try arena.dupe(u8, name); |
| 5526 | mod.deps.putAssumeCapacityNoClobber(name_cloned, dep_mod); | 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, .{ | 5611 | const comp = Compilation.create(gpa, arena, .{ |
| 5535 | .zig_lib_directory = zig_lib_directory, | 5612 | .zig_lib_directory = zig_lib_directory, |
| 5536 | .local_cache_directory = local_cache_directory, | 5613 | .local_cache_directory = local_cache_directory, |
| 5537 | .global_cache_directory = global_cache_directory, | 5614 | .global_cache_directory = global_cache_directory, |
| 5538 | .root_name = "build", | 5615 | .root_name = "build", |
| 5539 | .config = config, | 5616 | .config = config, |
| 5540 | .root_mod = root_mod, | 5617 | .root_mod = root_mod, |
| 5541 | .main_mod = build_mod, | 5618 | .main_mod = build_mod, |
| 5542 | .emit_bin = emit_bin, | 5619 | .emit_bin = emit_bin, |
| 5543 | .emit_h = null, | 5620 | .emit_h = null, |
| 5544 | .self_exe_path = self_exe_path, | 5621 | .self_exe_path = self_exe_path, |
| 5545 | .thread_pool = &thread_pool, | 5622 | .thread_pool = &thread_pool, |
| 5546 | .verbose_cc = verbose_cc, | 5623 | .verbose_cc = verbose_cc, |
| 5547 | .verbose_link = verbose_link, | 5624 | .verbose_link = verbose_link, |
| 5548 | .verbose_air = verbose_air, | 5625 | .verbose_air = verbose_air, |
| 5549 | .verbose_intern_pool = verbose_intern_pool, | 5626 | .verbose_intern_pool = verbose_intern_pool, |
| 5550 | .verbose_generic_instances = verbose_generic_instances, | 5627 | .verbose_generic_instances = verbose_generic_instances, |
| 5551 | .verbose_llvm_ir = verbose_llvm_ir, | 5628 | .verbose_llvm_ir = verbose_llvm_ir, |
| 5552 | .verbose_llvm_bc = verbose_llvm_bc, | 5629 | .verbose_llvm_bc = verbose_llvm_bc, |
| 5553 | .verbose_cimport = verbose_cimport, | 5630 | .verbose_cimport = verbose_cimport, |
| 5554 | .verbose_llvm_cpu_features = verbose_llvm_cpu_features, | 5631 | .verbose_llvm_cpu_features = verbose_llvm_cpu_features, |
| 5555 | .cache_mode = .whole, | 5632 | .cache_mode = .whole, |
| 5556 | .reference_trace = reference_trace, | 5633 | .reference_trace = reference_trace, |
| 5557 | .debug_compile_errors = debug_compile_errors, | 5634 | .debug_compile_errors = debug_compile_errors, |
| 5558 | }) catch |err| { | 5635 | }) catch |err| { |
| 5559 | fatal("unable to create compilation: {s}", .{@errorName(err)}); | 5636 | fatal("unable to create compilation: {s}", .{@errorName(err)}); |
| 5560 | }; | 5637 | }; |
| 5561 | defer comp.destroy(); | 5638 | defer comp.destroy(); |
| 5562 | 5639 | ||
| 5563 | updateModule(comp, color) catch |err| switch (err) { | 5640 | updateModule(comp, color) catch |err| switch (err) { |
| 5564 | error.SemanticAnalyzeFail => process.exit(2), | 5641 | error.SemanticAnalyzeFail => process.exit(2), |
| 5565 | else => |e| return e, | 5642 | else => |e| return e, |
| 5566 | }; | 5643 | }; |
| 5567 | 5644 | ||
| 5568 | // Since incremental compilation isn't done yet, we use cache_mode = whole | 5645 | // Since incremental compilation isn't done yet, we use cache_mode = whole |
| 5569 | // above, and thus the output file is already closed. | 5646 | // above, and thus the output file is already closed. |
| 5570 | //try comp.makeBinFileExecutable(); | 5647 | //try comp.makeBinFileExecutable(); |
| 5571 | child_argv.items[argv_index_exe] = | 5648 | child_argv.items[argv_index_exe] = |
| 5572 | try local_cache_directory.join(arena, &.{comp.cache_use.whole.bin_sub_path.?}); | 5649 | try local_cache_directory.join(arena, &.{comp.cache_use.whole.bin_sub_path.?}); |
| 5650 | } | ||
| 5573 | 5651 | ||
| 5574 | break :argv child_argv.items; | 5652 | if (process.can_spawn) { |
| 5575 | }; | 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) { | 5658 | const term = try child.spawnAndWait(); |
| 5578 | var child = std.ChildProcess.init(child_argv, gpa); | 5659 | switch (term) { |
| 5579 | child.stdin_behavior = .Inherit; | 5660 | .Exited => |code| { |
| 5580 | child.stdout_behavior = .Inherit; | 5661 | if (code == 0) return cleanExit(); |
| 5581 | child.stderr_behavior = .Inherit; | 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(); | 5711 | const cmd = try std.mem.join(arena, " ", child_argv.items); |
| 5584 | switch (term) { | 5712 | fatal("the following build command failed with exit code {d}:\n{s}", .{ code, cmd }); |
| 5585 | .Exited => |code| { | 5713 | }, |
| 5586 | if (code == 0) return cleanExit(); | 5714 | else => { |
| 5587 | // Indicates that the build runner has reported compile errors | 5715 | const cmd = try std.mem.join(arena, " ", child_argv.items); |
| 5588 | // and this parent process does not need to report any further | 5716 | fatal("the following build command crashed:\n{s}", .{cmd}); |
| 5589 | // diagnostics. | 5717 | }, |
| 5590 | if (code == 2) process.exit(2); | 5718 | } |
| 5591 | 5719 | } else { | |
| 5592 | const cmd = try std.mem.join(arena, " ", child_argv); | 5720 | const cmd = try std.mem.join(arena, " ", child_argv.items); |
| 5593 | fatal("the following build command failed with exit code {d}:\n{s}", .{ code, cmd }); | 5721 | fatal("the following command cannot be executed ({s} does not support spawning a child process):\n{s}", .{ @tagName(builtin.os.tag), 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 | }, | ||
| 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,6 +7463,7 @@ fn cmdFetch( |
| 7343 | .thread_pool = &thread_pool, | 7463 | .thread_pool = &thread_pool, |
| 7344 | .global_cache = global_cache_directory, | 7464 | .global_cache = global_cache_directory, |
| 7345 | .recursive = false, | 7465 | .recursive = false, |
| 7466 | .read_only = false, | ||
| 7346 | .debug_hash = debug_hash, | 7467 | .debug_hash = debug_hash, |
| 7347 | .work_around_btrfs_bug = work_around_btrfs_bug, | 7468 | .work_around_btrfs_bug = work_around_btrfs_bug, |
| 7348 | }; | 7469 | }; |
| ... | @@ -7353,6 +7474,8 @@ fn cmdFetch( | ... | @@ -7353,6 +7474,8 @@ fn cmdFetch( |
| 7353 | .location = .{ .path_or_url = path_or_url }, | 7474 | .location = .{ .path_or_url = path_or_url }, |
| 7354 | .location_tok = 0, | 7475 | .location_tok = 0, |
| 7355 | .hash_tok = 0, | 7476 | .hash_tok = 0, |
| 7477 | .name_tok = 0, | ||
| 7478 | .lazy_status = .eager, | ||
| 7356 | .parent_package_root = undefined, | 7479 | .parent_package_root = undefined, |
| 7357 | .parent_manifest_ast = null, | 7480 | .parent_manifest_ast = null, |
| 7358 | .prog_node = root_prog_node, | 7481 | .prog_node = root_prog_node, |
test/src/Cases.zig+2-2| ... | @@ -562,7 +562,7 @@ pub fn lowerToBuildSteps( | ... | @@ -562,7 +562,7 @@ pub fn lowerToBuildSteps( |
| 562 | run.setName(incr_case.base_path); | 562 | run.setName(incr_case.base_path); |
| 563 | run.addArgs(&.{ | 563 | run.addArgs(&.{ |
| 564 | case_base_path_with_dir, | 564 | case_base_path_with_dir, |
| 565 | b.zig_exe, | 565 | b.graph.zig_exe, |
| 566 | }); | 566 | }); |
| 567 | run.expectStdOutEqual(""); | 567 | run.expectStdOutEqual(""); |
| 568 | parent_step.dependOn(&run.step); | 568 | parent_step.dependOn(&run.step); |
| ... | @@ -653,7 +653,7 @@ pub fn lowerToBuildSteps( | ... | @@ -653,7 +653,7 @@ pub fn lowerToBuildSteps( |
| 653 | break :no_exec; | 653 | break :no_exec; |
| 654 | } | 654 | } |
| 655 | const run_c = b.addSystemCommand(&.{ | 655 | const run_c = b.addSystemCommand(&.{ |
| 656 | b.zig_exe, | 656 | b.graph.zig_exe, |
| 657 | "run", | 657 | "run", |
| 658 | "-cflags", | 658 | "-cflags", |
| 659 | "-Ilib", | 659 | "-Ilib", |
test/tests.zig+11-11| ... | @@ -796,7 +796,7 @@ pub fn addCliTests(b: *std.Build) *Step { | ... | @@ -796,7 +796,7 @@ pub fn addCliTests(b: *std.Build) *Step { |
| 796 | { | 796 | { |
| 797 | // Test `zig init`. | 797 | // Test `zig init`. |
| 798 | const tmp_path = b.makeTempPath(); | 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 | init_exe.setCwd(.{ .cwd_relative = tmp_path }); | 800 | init_exe.setCwd(.{ .cwd_relative = tmp_path }); |
| 801 | init_exe.setName("zig init"); | 801 | init_exe.setName("zig init"); |
| 802 | init_exe.expectStdOutEqual(""); | 802 | init_exe.expectStdOutEqual(""); |
| ... | @@ -810,20 +810,20 @@ pub fn addCliTests(b: *std.Build) *Step { | ... | @@ -810,20 +810,20 @@ pub fn addCliTests(b: *std.Build) *Step { |
| 810 | const bad_out_arg = "-femit-bin=does" ++ s ++ "not" ++ s ++ "exist" ++ s ++ "foo.exe"; | 810 | const bad_out_arg = "-femit-bin=does" ++ s ++ "not" ++ s ++ "exist" ++ s ++ "foo.exe"; |
| 811 | const ok_src_arg = "src" ++ s ++ "main.zig"; | 811 | const ok_src_arg = "src" ++ s ++ "main.zig"; |
| 812 | const expected = "error: unable to open output directory 'does" ++ s ++ "not" ++ s ++ "exist': FileNotFound\n"; | 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 | run_bad.setName("zig build-exe error message for bad -femit-bin arg"); | 814 | run_bad.setName("zig build-exe error message for bad -femit-bin arg"); |
| 815 | run_bad.expectExitCode(1); | 815 | run_bad.expectExitCode(1); |
| 816 | run_bad.expectStdErrEqual(expected); | 816 | run_bad.expectStdErrEqual(expected); |
| 817 | run_bad.expectStdOutEqual(""); | 817 | run_bad.expectStdOutEqual(""); |
| 818 | run_bad.step.dependOn(&init_exe.step); | 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 | run_test.setCwd(.{ .cwd_relative = tmp_path }); | 821 | run_test.setCwd(.{ .cwd_relative = tmp_path }); |
| 822 | run_test.setName("zig build test"); | 822 | run_test.setName("zig build test"); |
| 823 | run_test.expectStdOutEqual(""); | 823 | run_test.expectStdOutEqual(""); |
| 824 | run_test.step.dependOn(&init_exe.step); | 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 | run_run.setCwd(.{ .cwd_relative = tmp_path }); | 827 | run_run.setCwd(.{ .cwd_relative = tmp_path }); |
| 828 | run_run.setName("zig build run"); | 828 | run_run.setName("zig build run"); |
| 829 | run_run.expectStdOutEqual("Run `zig build test` to run the tests.\n"); | 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,7 +857,7 @@ pub fn addCliTests(b: *std.Build) *Step { |
| 857 | 857 | ||
| 858 | // This is intended to be the exact CLI usage used by godbolt.org. | 858 | // This is intended to be the exact CLI usage used by godbolt.org. |
| 859 | const run = b.addSystemCommand(&.{ | 859 | const run = b.addSystemCommand(&.{ |
| 860 | b.zig_exe, "build-obj", | 860 | b.graph.zig_exe, "build-obj", |
| 861 | "--cache-dir", tmp_path, | 861 | "--cache-dir", tmp_path, |
| 862 | "--name", "example", | 862 | "--name", "example", |
| 863 | "-fno-emit-bin", "-fno-emit-h", | 863 | "-fno-emit-bin", "-fno-emit-h", |
| ... | @@ -900,7 +900,7 @@ pub fn addCliTests(b: *std.Build) *Step { | ... | @@ -900,7 +900,7 @@ pub fn addCliTests(b: *std.Build) *Step { |
| 900 | subdir.writeFile("fmt3.zig", unformatted_code) catch @panic("unhandled"); | 900 | subdir.writeFile("fmt3.zig", unformatted_code) catch @panic("unhandled"); |
| 901 | 901 | ||
| 902 | // Test zig fmt affecting only the appropriate files. | 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 | run1.setName("run zig fmt one file"); | 904 | run1.setName("run zig fmt one file"); |
| 905 | run1.setCwd(.{ .cwd_relative = tmp_path }); | 905 | run1.setCwd(.{ .cwd_relative = tmp_path }); |
| 906 | run1.has_side_effects = true; | 906 | run1.has_side_effects = true; |
| ... | @@ -908,7 +908,7 @@ pub fn addCliTests(b: *std.Build) *Step { | ... | @@ -908,7 +908,7 @@ pub fn addCliTests(b: *std.Build) *Step { |
| 908 | run1.expectStdOutEqual("fmt1.zig\n"); | 908 | run1.expectStdOutEqual("fmt1.zig\n"); |
| 909 | 909 | ||
| 910 | // Test excluding files and directories from a run | 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 | run2.setName("run zig fmt on directory with exclusions"); | 912 | run2.setName("run zig fmt on directory with exclusions"); |
| 913 | run2.setCwd(.{ .cwd_relative = tmp_path }); | 913 | run2.setCwd(.{ .cwd_relative = tmp_path }); |
| 914 | run2.has_side_effects = true; | 914 | run2.has_side_effects = true; |
| ... | @@ -916,7 +916,7 @@ pub fn addCliTests(b: *std.Build) *Step { | ... | @@ -916,7 +916,7 @@ pub fn addCliTests(b: *std.Build) *Step { |
| 916 | run2.step.dependOn(&run1.step); | 916 | run2.step.dependOn(&run1.step); |
| 917 | 917 | ||
| 918 | // Test excluding non-existent file | 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 | run3.setName("run zig fmt on directory with non-existent exclusion"); | 920 | run3.setName("run zig fmt on directory with non-existent exclusion"); |
| 921 | run3.setCwd(.{ .cwd_relative = tmp_path }); | 921 | run3.setCwd(.{ .cwd_relative = tmp_path }); |
| 922 | run3.has_side_effects = true; | 922 | run3.has_side_effects = true; |
| ... | @@ -924,7 +924,7 @@ pub fn addCliTests(b: *std.Build) *Step { | ... | @@ -924,7 +924,7 @@ pub fn addCliTests(b: *std.Build) *Step { |
| 924 | run3.step.dependOn(&run2.step); | 924 | run3.step.dependOn(&run2.step); |
| 925 | 925 | ||
| 926 | // running it on the dir, only the new file should be changed | 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 | run4.setName("run zig fmt the directory"); | 928 | run4.setName("run zig fmt the directory"); |
| 929 | run4.setCwd(.{ .cwd_relative = tmp_path }); | 929 | run4.setCwd(.{ .cwd_relative = tmp_path }); |
| 930 | run4.has_side_effects = true; | 930 | run4.has_side_effects = true; |
| ... | @@ -932,7 +932,7 @@ pub fn addCliTests(b: *std.Build) *Step { | ... | @@ -932,7 +932,7 @@ pub fn addCliTests(b: *std.Build) *Step { |
| 932 | run4.step.dependOn(&run3.step); | 932 | run4.step.dependOn(&run3.step); |
| 933 | 933 | ||
| 934 | // both files have been formatted, nothing should change now | 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 | run5.setName("run zig fmt with nothing to do"); | 936 | run5.setName("run zig fmt with nothing to do"); |
| 937 | run5.setCwd(.{ .cwd_relative = tmp_path }); | 937 | run5.setCwd(.{ .cwd_relative = tmp_path }); |
| 938 | run5.has_side_effects = true; | 938 | run5.has_side_effects = true; |
| ... | @@ -946,7 +946,7 @@ pub fn addCliTests(b: *std.Build) *Step { | ... | @@ -946,7 +946,7 @@ pub fn addCliTests(b: *std.Build) *Step { |
| 946 | write6.step.dependOn(&run5.step); | 946 | write6.step.dependOn(&run5.step); |
| 947 | 947 | ||
| 948 | // Test `zig fmt` handling UTF-16 decoding. | 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 | run6.setName("run zig fmt convert UTF-16 to UTF-8"); | 950 | run6.setName("run zig fmt convert UTF-16 to UTF-8"); |
| 951 | run6.setCwd(.{ .cwd_relative = tmp_path }); | 951 | run6.setCwd(.{ .cwd_relative = tmp_path }); |
| 952 | run6.has_side_effects = true; | 952 | run6.has_side_effects = true; |