| author | |
| committer | |
| log | 648e0e0cc0d6d1940d3bb2ebc265067f7eb62432 |
| tree | 454bf5f1be181b7c06f53d077a87e44adf9dc8df |
| parent | 6b040d631fd5090d85c56b39006162f2aa4991b1 |
5 files changed, 500 insertions(+), 162 deletions(-)
lib/compiler/configure_runner.zig+105-1| ... | @@ -269,7 +269,105 @@ fn serialize(b: *std.Build, wc: *Configuration.Wip, writer: *Io.Writer) !void { | ... | @@ -269,7 +269,105 @@ fn serialize(b: *std.Build, wc: *Configuration.Wip, writer: *Io.Writer) !void { |
| 269 | .description = try wc.addString(top_level.description), | 269 | .description = try wc.addString(top_level.description), |
| 270 | })); | 270 | })); |
| 271 | }, | 271 | }, |
| 272 | .compile => @panic("TODO"), | 272 | .compile => e: { |
| 273 | const c: *Step.Compile = @fieldParentPtr("step", step); | ||
| 274 | const extra_index = try wc.addExtra(@as(Configuration.Step.Compile, .{ | ||
| 275 | .flags = .{ | ||
| 276 | .filters_len = c.filters.len != 0, | ||
| 277 | .exec_cmd_args_len = if (c.exec_cmd_args) |a| a.len != 0 else false, | ||
| 278 | .installed_headers_len = c.installed_headers.items.len != 0, | ||
| 279 | .force_undefined_symbols_len = c.force_undefined_symbols.entries.len != 0, | ||
| 280 | |||
| 281 | .verbose_link = c.verbose_link, | ||
| 282 | .verbose_cc = c.verbose_cc, | ||
| 283 | .rdynamic = c.rdynamic, | ||
| 284 | .import_memory = c.import_memory, | ||
| 285 | .export_memory = c.export_memory, | ||
| 286 | .import_symbols = c.import_symbols, | ||
| 287 | .import_table = c.import_table, | ||
| 288 | .export_table = c.export_table, | ||
| 289 | .shared_memory = c.shared_memory, | ||
| 290 | .link_eh_frame_hdr = c.link_eh_frame_hdr, | ||
| 291 | .link_emit_relocs = c.link_emit_relocs, | ||
| 292 | .link_function_sections = c.link_function_sections, | ||
| 293 | .link_data_sections = c.link_data_sections, | ||
| 294 | .linker_dynamicbase = c.linker_dynamicbase, | ||
| 295 | .link_z_notext = c.link_z_notext, | ||
| 296 | .link_z_relro = c.link_z_relro, | ||
| 297 | .link_z_lazy = c.link_z_lazy, | ||
| 298 | .link_z_defs = c.link_z_defs, | ||
| 299 | .headerpad_max_install_names = c.headerpad_max_install_names, | ||
| 300 | .dead_strip_dylibs = c.dead_strip_dylibs, | ||
| 301 | .force_load_objc = c.force_load_objc, | ||
| 302 | .discard_local_symbols = c.discard_local_symbols, | ||
| 303 | .mingw_unicode_entry_point = c.mingw_unicode_entry_point, | ||
| 304 | }, | ||
| 305 | .flags2 = .{ | ||
| 306 | .pie = .init(c.pie), | ||
| 307 | .formatted_panics = .init(c.formatted_panics), | ||
| 308 | .bundle_compiler_rt = .init(c.bundle_compiler_rt), | ||
| 309 | .bundle_ubsan_rt = .init(c.bundle_ubsan_rt), | ||
| 310 | .each_lib_rpath = .init(c.each_lib_rpath), | ||
| 311 | .link_gc_sections = .init(c.link_gc_sections), | ||
| 312 | .linker_allow_shlib_undefined = .init(c.linker_allow_shlib_undefined), | ||
| 313 | .linker_allow_undefined_version = .init(c.linker_allow_undefined_version), | ||
| 314 | .linker_enable_new_dtags = .init(c.linker_enable_new_dtags), | ||
| 315 | .dll_export_fns = .init(c.dll_export_fns), | ||
| 316 | .use_llvm = .init(c.use_llvm), | ||
| 317 | .use_lld = .init(c.use_lld), | ||
| 318 | .use_new_linker = .init(c.use_new_linker), | ||
| 319 | .allow_so_scripts = .init(c.allow_so_scripts), | ||
| 320 | .sanitize_coverage_trace_pc_guard = .init(c.sanitize_coverage_trace_pc_guard), | ||
| 321 | .linkage = .init(c.linkage), | ||
| 322 | }, | ||
| 323 | .flags3 = .{ | ||
| 324 | .is_linking_libc = c.is_linking_libc, | ||
| 325 | .is_linking_libcpp = c.is_linking_libcpp, | ||
| 326 | .version = c.version != null, | ||
| 327 | .compress_debug_sections = c.compress_debug_sections, | ||
| 328 | .initial_memory = c.initial_memory != null, | ||
| 329 | .max_memory = c.max_memory != null, | ||
| 330 | .kind = c.kind, | ||
| 331 | .global_base = c.global_base != null, | ||
| 332 | .test_runner_mode = if (c.test_runner) |tr| switch (tr.mode) { | ||
| 333 | .simple => .simple, | ||
| 334 | .server => .server, | ||
| 335 | } else .default, | ||
| 336 | .wasi_exec_model = .init(c.wasi_exec_model), | ||
| 337 | .win32_manifest = c.win32_manifest != null, | ||
| 338 | .win32_module_definition = c.win32_module_definition != null, | ||
| 339 | .zig_lib_dir = c.zig_lib_dir != null, | ||
| 340 | .rc_includes = c.rc_includes, | ||
| 341 | .image_base = c.image_base != null, | ||
| 342 | .build_id = .init(c.build_id), | ||
| 343 | .entry = switch (c.entry) { | ||
| 344 | .default => .default, | ||
| 345 | .disabled => .disabled, | ||
| 346 | .enabled => .enabled, | ||
| 347 | .symbol_name => .symbol_name, | ||
| 348 | }, | ||
| 349 | .lto = .init(c.lto), | ||
| 350 | .subsystem = .init(c.subsystem), | ||
| 351 | }, | ||
| 352 | .flags4 = .{ | ||
| 353 | .libc_file = c.libc_file != null, | ||
| 354 | .link_z_common_page_size = c.link_z_common_page_size != null, | ||
| 355 | .link_z_max_page_size = c.link_z_max_page_size != null, | ||
| 356 | .pagezero_size = c.pagezero_size != null, | ||
| 357 | .stack_size = c.stack_size != null, | ||
| 358 | .headerpad_size = c.headerpad_size != null, | ||
| 359 | .error_limit = c.error_limit != null, | ||
| 360 | .install_name = c.install_name != null, | ||
| 361 | .entitlements = c.entitlements != null, | ||
| 362 | }, | ||
| 363 | .root_module = try addModule(wc, c.root_module), | ||
| 364 | .root_name = try wc.addString(c.name), | ||
| 365 | })); | ||
| 366 | |||
| 367 | std.log.err("TODO serialize the trailing Compile step data", .{}); | ||
| 368 | |||
| 369 | break :e extra_index; | ||
| 370 | }, | ||
| 273 | .install_artifact => e: { | 371 | .install_artifact => e: { |
| 274 | const ia: *Step.InstallArtifact = @fieldParentPtr("step", step); | 372 | const ia: *Step.InstallArtifact = @fieldParentPtr("step", step); |
| 275 | break :e try wc.addExtra(@as(Configuration.Step.InstallArtifact, .{ | 373 | break :e try wc.addExtra(@as(Configuration.Step.InstallArtifact, .{ |
| ... | @@ -364,6 +462,12 @@ fn serialize(b: *std.Build, wc: *Configuration.Wip, writer: *Io.Writer) !void { | ... | @@ -364,6 +462,12 @@ fn serialize(b: *std.Build, wc: *Configuration.Wip, writer: *Io.Writer) !void { |
| 364 | }); | 462 | }); |
| 365 | } | 463 | } |
| 366 | 464 | ||
| 465 | fn addModule(wc: *Configuration.Wip, module: *std.Build.Module) !Configuration.Module { | ||
| 466 | _ = wc; | ||
| 467 | _ = module; | ||
| 468 | @panic("TODO"); | ||
| 469 | } | ||
| 470 | |||
| 367 | fn addOptionalLazyPath(wc: *Configuration.Wip, lp: ?std.Build.LazyPath) !Configuration.OptionalLazyPath { | 471 | fn addOptionalLazyPath(wc: *Configuration.Wip, lp: ?std.Build.LazyPath) !Configuration.OptionalLazyPath { |
| 368 | return @enumFromInt(switch (lp orelse return .none) { | 472 | return @enumFromInt(switch (lp orelse return .none) { |
| 369 | .src_path => |src_path| i: { | 473 | .src_path => |src_path| i: { |
lib/compiler/maker/Step/Compile.zig+128-2| ... | @@ -98,8 +98,7 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 { | ... | @@ -98,8 +98,7 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 { |
| 98 | } | 98 | } |
| 99 | 99 | ||
| 100 | { | 100 | { |
| 101 | var symbol_it = compile.force_undefined_symbols.keyIterator(); | 101 | for (compile.force_undefined_symbols.keys()) |symbol_name| { |
| 102 | while (symbol_it.next()) |symbol_name| { | ||
| 103 | try zig_args.append("--force_undefined"); | 102 | try zig_args.append("--force_undefined"); |
| 104 | try zig_args.append(symbol_name.*); | 103 | try zig_args.append(symbol_name.*); |
| 105 | } | 104 | } |
| ... | @@ -1071,4 +1070,131 @@ fn runPkgConfig(compile: *Compile, lib_name: []const u8) !PkgConfigResult { | ... | @@ -1071,4 +1070,131 @@ fn runPkgConfig(compile: *Compile, lib_name: []const u8) !PkgConfigResult { |
| 1071 | }; | 1070 | }; |
| 1072 | } | 1071 | } |
| 1073 | 1072 | ||
| 1073 | fn checkCompileErrors(compile: *Compile) !void { | ||
| 1074 | // Clear this field so that it does not get printed by the build runner. | ||
| 1075 | const actual_eb = compile.step.result_error_bundle; | ||
| 1076 | compile.step.result_error_bundle = .empty; | ||
| 1077 | |||
| 1078 | const arena = compile.step.owner.allocator; | ||
| 1079 | |||
| 1080 | const actual_errors = ae: { | ||
| 1081 | var aw: std.Io.Writer.Allocating = .init(arena); | ||
| 1082 | defer aw.deinit(); | ||
| 1083 | try actual_eb.renderToWriter(.{ | ||
| 1084 | .include_reference_trace = false, | ||
| 1085 | .include_source_line = false, | ||
| 1086 | }, &aw.writer); | ||
| 1087 | break :ae try aw.toOwnedSlice(); | ||
| 1088 | }; | ||
| 1089 | |||
| 1090 | // Render the expected lines into a string that we can compare verbatim. | ||
| 1091 | var expected_generated: std.ArrayList(u8) = .empty; | ||
| 1092 | const expect_errors = compile.expect_errors.?; | ||
| 1093 | |||
| 1094 | var actual_line_it = mem.splitScalar(u8, actual_errors, '\n'); | ||
| 1095 | |||
| 1096 | // TODO merge this with the testing.expectEqualStrings logic, and also CheckFile | ||
| 1097 | switch (expect_errors) { | ||
| 1098 | .starts_with => |expect_starts_with| { | ||
| 1099 | if (std.mem.startsWith(u8, actual_errors, expect_starts_with)) return; | ||
| 1100 | return compile.step.fail( | ||
| 1101 | \\ | ||
| 1102 | \\========= should start with: ============ | ||
| 1103 | \\{s} | ||
| 1104 | \\========= but not found: ================ | ||
| 1105 | \\{s} | ||
| 1106 | \\========================================= | ||
| 1107 | , .{ expect_starts_with, actual_errors }); | ||
| 1108 | }, | ||
| 1109 | .contains => |expect_line| { | ||
| 1110 | while (actual_line_it.next()) |actual_line| { | ||
| 1111 | if (!matchCompileError(actual_line, expect_line)) continue; | ||
| 1112 | return; | ||
| 1113 | } | ||
| 1114 | |||
| 1115 | return compile.step.fail( | ||
| 1116 | \\ | ||
| 1117 | \\========= should contain: =============== | ||
| 1118 | \\{s} | ||
| 1119 | \\========= but not found: ================ | ||
| 1120 | \\{s} | ||
| 1121 | \\========================================= | ||
| 1122 | , .{ expect_line, actual_errors }); | ||
| 1123 | }, | ||
| 1124 | .stderr_contains => |expect_line| { | ||
| 1125 | const actual_stderr: []const u8 = if (compile.step.result_error_msgs.items.len > 0) | ||
| 1126 | compile.step.result_error_msgs.items[0] | ||
| 1127 | else | ||
| 1128 | &.{}; | ||
| 1129 | compile.step.result_error_msgs.clearRetainingCapacity(); | ||
| 1130 | |||
| 1131 | var stderr_line_it = mem.splitScalar(u8, actual_stderr, '\n'); | ||
| 1132 | |||
| 1133 | while (stderr_line_it.next()) |actual_line| { | ||
| 1134 | if (!matchCompileError(actual_line, expect_line)) continue; | ||
| 1135 | return; | ||
| 1136 | } | ||
| 1137 | |||
| 1138 | return compile.step.fail( | ||
| 1139 | \\ | ||
| 1140 | \\========= should contain: =============== | ||
| 1141 | \\{s} | ||
| 1142 | \\========= but not found: ================ | ||
| 1143 | \\{s} | ||
| 1144 | \\========================================= | ||
| 1145 | , .{ expect_line, actual_stderr }); | ||
| 1146 | }, | ||
| 1147 | .exact => |expect_lines| { | ||
| 1148 | for (expect_lines) |expect_line| { | ||
| 1149 | const actual_line = actual_line_it.next() orelse { | ||
| 1150 | try expected_generated.appendSlice(arena, expect_line); | ||
| 1151 | try expected_generated.append(arena, '\n'); | ||
| 1152 | continue; | ||
| 1153 | }; | ||
| 1154 | if (matchCompileError(actual_line, expect_line)) { | ||
| 1155 | try expected_generated.appendSlice(arena, actual_line); | ||
| 1156 | try expected_generated.append(arena, '\n'); | ||
| 1157 | continue; | ||
| 1158 | } | ||
| 1159 | try expected_generated.appendSlice(arena, expect_line); | ||
| 1160 | try expected_generated.append(arena, '\n'); | ||
| 1161 | } | ||
| 1162 | |||
| 1163 | if (mem.eql(u8, expected_generated.items, actual_errors)) return; | ||
| 1164 | |||
| 1165 | return compile.step.fail( | ||
| 1166 | \\ | ||
| 1167 | \\========= expected: ===================== | ||
| 1168 | \\{s} | ||
| 1169 | \\========= but found: ==================== | ||
| 1170 | \\{s} | ||
| 1171 | \\========================================= | ||
| 1172 | , .{ expected_generated.items, actual_errors }); | ||
| 1173 | }, | ||
| 1174 | } | ||
| 1175 | } | ||
| 1176 | |||
| 1177 | fn matchCompileError(actual: []const u8, expected: []const u8) bool { | ||
| 1178 | if (mem.endsWith(u8, actual, expected)) return true; | ||
| 1179 | if (mem.startsWith(u8, expected, ":?:?: ")) { | ||
| 1180 | if (mem.endsWith(u8, actual, expected[":?:?: ".len..])) return true; | ||
| 1181 | } | ||
| 1182 | // We scan for /?/ in expected line and if there is a match, we match everything | ||
| 1183 | // up to and after /?/. | ||
| 1184 | const expected_trim = mem.trim(u8, expected, " "); | ||
| 1185 | if (mem.find(u8, expected_trim, "/?/")) |index| { | ||
| 1186 | const actual_trim = mem.trim(u8, actual, " "); | ||
| 1187 | const lhs = expected_trim[0..index]; | ||
| 1188 | const rhs = expected_trim[index + "/?/".len ..]; | ||
| 1189 | if (mem.startsWith(u8, actual_trim, lhs) and mem.endsWith(u8, actual_trim, rhs)) return true; | ||
| 1190 | } | ||
| 1191 | return false; | ||
| 1192 | } | ||
| 1193 | |||
| 1194 | fn moduleNeedsCliArg(mod: *const Module) bool { | ||
| 1195 | return for (mod.link_objects.items) |o| switch (o) { | ||
| 1196 | .c_source_file, .c_source_files, .assembly_file, .win32_resource_file => break true, | ||
| 1197 | else => continue, | ||
| 1198 | } else false; | ||
| 1199 | } | ||
| 1074 | 1200 |
lib/std/Build/Step/Compile.zig+11-153| ... | @@ -60,7 +60,7 @@ filters: []const []const u8, | ... | @@ -60,7 +60,7 @@ filters: []const []const u8, |
| 60 | test_runner: ?TestRunner, | 60 | test_runner: ?TestRunner, |
| 61 | wasi_exec_model: ?std.builtin.WasiExecModel = null, | 61 | wasi_exec_model: ?std.builtin.WasiExecModel = null, |
| 62 | 62 | ||
| 63 | installed_headers: std.array_list.Managed(HeaderInstallation), | 63 | installed_headers: std.ArrayList(HeaderInstallation), |
| 64 | 64 | ||
| 65 | /// This step is used to create an include tree that dependent modules can add to their include | 65 | /// This step is used to create an include tree that dependent modules can add to their include |
| 66 | /// search paths. Installed headers are copied to this step. | 66 | /// search paths. Installed headers are copied to this step. |
| ... | @@ -83,8 +83,6 @@ win32_manifest: ?LazyPath = null, | ... | @@ -83,8 +83,6 @@ win32_manifest: ?LazyPath = null, |
| 83 | /// Set via options; intended to be read-only after that. | 83 | /// Set via options; intended to be read-only after that. |
| 84 | win32_module_definition: ?LazyPath = null, | 84 | win32_module_definition: ?LazyPath = null, |
| 85 | 85 | ||
| 86 | installed_path: ?[]const u8, | ||
| 87 | |||
| 88 | /// Base address for an executable image. | 86 | /// Base address for an executable image. |
| 89 | image_base: ?u64 = null, | 87 | image_base: ?u64 = null, |
| 90 | 88 | ||
| ... | @@ -189,7 +187,7 @@ entry: Entry = .default, | ... | @@ -189,7 +187,7 @@ entry: Entry = .default, |
| 189 | /// List of symbols forced as undefined in the symbol table | 187 | /// List of symbols forced as undefined in the symbol table |
| 190 | /// thus forcing their resolution by the linker. | 188 | /// thus forcing their resolution by the linker. |
| 191 | /// Corresponds to `-u <symbol>` for ELF/MachO and `/include:<symbol>` for COFF/PE. | 189 | /// Corresponds to `-u <symbol>` for ELF/MachO and `/include:<symbol>` for COFF/PE. |
| 192 | force_undefined_symbols: std.StringHashMap(void), | 190 | force_undefined_symbols: std.StringArrayHashMapUnmanaged(void), |
| 193 | 191 | ||
| 194 | /// Overrides the default stack size | 192 | /// Overrides the default stack size |
| 195 | stack_size: ?u64 = null, | 193 | stack_size: ?u64 = null, |
| ... | @@ -290,20 +288,7 @@ pub const Options = struct { | ... | @@ -290,20 +288,7 @@ pub const Options = struct { |
| 290 | win32_module_definition: ?LazyPath = null, | 288 | win32_module_definition: ?LazyPath = null, |
| 291 | }; | 289 | }; |
| 292 | 290 | ||
| 293 | pub const Kind = enum { | 291 | pub const Kind = std.Build.Configuration.Step.Compile.Kind; |
| 294 | exe, | ||
| 295 | lib, | ||
| 296 | obj, | ||
| 297 | @"test", | ||
| 298 | test_obj, | ||
| 299 | |||
| 300 | pub fn isTest(kind: Kind) bool { | ||
| 301 | return switch (kind) { | ||
| 302 | .exe, .lib, .obj => false, | ||
| 303 | .@"test", .test_obj => true, | ||
| 304 | }; | ||
| 305 | } | ||
| 306 | }; | ||
| 307 | 292 | ||
| 308 | pub const HeaderInstallation = union(enum) { | 293 | pub const HeaderInstallation = union(enum) { |
| 309 | file: File, | 294 | file: File, |
| ... | @@ -424,14 +409,13 @@ pub fn create(owner: *std.Build, options: Options) *Compile { | ... | @@ -424,14 +409,13 @@ pub fn create(owner: *std.Build, options: Options) *Compile { |
| 424 | .out_lib_filename = undefined, | 409 | .out_lib_filename = undefined, |
| 425 | .major_only_filename = null, | 410 | .major_only_filename = null, |
| 426 | .name_only_filename = null, | 411 | .name_only_filename = null, |
| 427 | .installed_headers = std.array_list.Managed(HeaderInstallation).init(owner.allocator), | 412 | .installed_headers = .empty, |
| 428 | .zig_lib_dir = null, | 413 | .zig_lib_dir = null, |
| 429 | .exec_cmd_args = null, | 414 | .exec_cmd_args = null, |
| 430 | .filters = options.filters, | 415 | .filters = options.filters, |
| 431 | .test_runner = null, // set below | 416 | .test_runner = null, // set below |
| 432 | .rdynamic = false, | 417 | .rdynamic = false, |
| 433 | .installed_path = null, | 418 | .force_undefined_symbols = .empty, |
| 434 | .force_undefined_symbols = StringHashMap(void).init(owner.allocator), | ||
| 435 | 419 | ||
| 436 | .emit_directory = null, | 420 | .emit_directory = null, |
| 437 | .generated_docs = null, | 421 | .generated_docs = null, |
| ... | @@ -519,7 +503,7 @@ pub fn installHeader(cs: *Compile, source: LazyPath, dest_rel_path: []const u8) | ... | @@ -519,7 +503,7 @@ pub fn installHeader(cs: *Compile, source: LazyPath, dest_rel_path: []const u8) |
| 519 | .source = source.dupe(b), | 503 | .source = source.dupe(b), |
| 520 | .dest_rel_path = b.dupePath(dest_rel_path), | 504 | .dest_rel_path = b.dupePath(dest_rel_path), |
| 521 | } }; | 505 | } }; |
| 522 | cs.installed_headers.append(installation) catch @panic("OOM"); | 506 | cs.installed_headers.append(b.allocator, installation) catch @panic("OOM"); |
| 523 | cs.addHeaderInstallationToIncludeTree(installation); | 507 | cs.addHeaderInstallationToIncludeTree(installation); |
| 524 | installation.getSource().addStepDependencies(&cs.step); | 508 | installation.getSource().addStepDependencies(&cs.step); |
| 525 | } | 509 | } |
| ... | @@ -539,7 +523,7 @@ pub fn installHeadersDirectory( | ... | @@ -539,7 +523,7 @@ pub fn installHeadersDirectory( |
| 539 | .dest_rel_path = b.dupePath(dest_rel_path), | 523 | .dest_rel_path = b.dupePath(dest_rel_path), |
| 540 | .options = options.dupe(b), | 524 | .options = options.dupe(b), |
| 541 | } }; | 525 | } }; |
| 542 | cs.installed_headers.append(installation) catch @panic("OOM"); | 526 | cs.installed_headers.append(b.allocator, installation) catch @panic("OOM"); |
| 543 | cs.addHeaderInstallationToIncludeTree(installation); | 527 | cs.addHeaderInstallationToIncludeTree(installation); |
| 544 | installation.getSource().addStepDependencies(&cs.step); | 528 | installation.getSource().addStepDependencies(&cs.step); |
| 545 | } | 529 | } |
| ... | @@ -556,9 +540,10 @@ pub fn installConfigHeader(cs: *Compile, config_header: *Step.ConfigHeader) void | ... | @@ -556,9 +540,10 @@ pub fn installConfigHeader(cs: *Compile, config_header: *Step.ConfigHeader) void |
| 556 | /// module's include search path. | 540 | /// module's include search path. |
| 557 | pub fn installLibraryHeaders(cs: *Compile, lib: *Compile) void { | 541 | pub fn installLibraryHeaders(cs: *Compile, lib: *Compile) void { |
| 558 | assert(lib.kind == .lib); | 542 | assert(lib.kind == .lib); |
| 543 | const arena = cs.owner.allocator; | ||
| 559 | for (lib.installed_headers.items) |installation| { | 544 | for (lib.installed_headers.items) |installation| { |
| 560 | const installation_copy = installation.dupe(lib.step.owner); | 545 | const installation_copy = installation.dupe(lib.step.owner); |
| 561 | cs.installed_headers.append(installation_copy) catch @panic("OOM"); | 546 | cs.installed_headers.append(arena, installation_copy) catch @panic("OOM"); |
| 562 | cs.addHeaderInstallationToIncludeTree(installation_copy); | 547 | cs.addHeaderInstallationToIncludeTree(installation_copy); |
| 563 | installation_copy.getSource().addStepDependencies(&cs.step); | 548 | installation_copy.getSource().addStepDependencies(&cs.step); |
| 564 | } | 549 | } |
| ... | @@ -618,7 +603,8 @@ pub fn setVersionScript(compile: *Compile, source: LazyPath) void { | ... | @@ -618,7 +603,8 @@ pub fn setVersionScript(compile: *Compile, source: LazyPath) void { |
| 618 | 603 | ||
| 619 | pub fn forceUndefinedSymbol(compile: *Compile, symbol_name: []const u8) void { | 604 | pub fn forceUndefinedSymbol(compile: *Compile, symbol_name: []const u8) void { |
| 620 | const b = compile.step.owner; | 605 | const b = compile.step.owner; |
| 621 | compile.force_undefined_symbols.put(b.dupe(symbol_name), {}) catch @panic("OOM"); | 606 | const arena = b.allocator; |
| 607 | compile.force_undefined_symbols.put(arena, b.dupe(symbol_name), {}) catch @panic("OOM"); | ||
| 622 | } | 608 | } |
| 623 | 609 | ||
| 624 | /// Returns whether the library, executable, or object depends on a particular system library. | 610 | /// Returns whether the library, executable, or object depends on a particular system library. |
| ... | @@ -867,139 +853,11 @@ fn outputPath(c: *Compile, out_dir: std.Build.Cache.Path, ea: std.zig.EmitArtifa | ... | @@ -867,139 +853,11 @@ fn outputPath(c: *Compile, out_dir: std.Build.Cache.Path, ea: std.zig.EmitArtifa |
| 867 | return out_dir.joinString(arena, name) catch @panic("OOM"); | 853 | return out_dir.joinString(arena, name) catch @panic("OOM"); |
| 868 | } | 854 | } |
| 869 | 855 | ||
| 870 | fn checkCompileErrors(compile: *Compile) !void { | ||
| 871 | // Clear this field so that it does not get printed by the build runner. | ||
| 872 | const actual_eb = compile.step.result_error_bundle; | ||
| 873 | compile.step.result_error_bundle = .empty; | ||
| 874 | |||
| 875 | const arena = compile.step.owner.allocator; | ||
| 876 | |||
| 877 | const actual_errors = ae: { | ||
| 878 | var aw: std.Io.Writer.Allocating = .init(arena); | ||
| 879 | defer aw.deinit(); | ||
| 880 | try actual_eb.renderToWriter(.{ | ||
| 881 | .include_reference_trace = false, | ||
| 882 | .include_source_line = false, | ||
| 883 | }, &aw.writer); | ||
| 884 | break :ae try aw.toOwnedSlice(); | ||
| 885 | }; | ||
| 886 | |||
| 887 | // Render the expected lines into a string that we can compare verbatim. | ||
| 888 | var expected_generated: std.ArrayList(u8) = .empty; | ||
| 889 | const expect_errors = compile.expect_errors.?; | ||
| 890 | |||
| 891 | var actual_line_it = mem.splitScalar(u8, actual_errors, '\n'); | ||
| 892 | |||
| 893 | // TODO merge this with the testing.expectEqualStrings logic, and also CheckFile | ||
| 894 | switch (expect_errors) { | ||
| 895 | .starts_with => |expect_starts_with| { | ||
| 896 | if (std.mem.startsWith(u8, actual_errors, expect_starts_with)) return; | ||
| 897 | return compile.step.fail( | ||
| 898 | \\ | ||
| 899 | \\========= should start with: ============ | ||
| 900 | \\{s} | ||
| 901 | \\========= but not found: ================ | ||
| 902 | \\{s} | ||
| 903 | \\========================================= | ||
| 904 | , .{ expect_starts_with, actual_errors }); | ||
| 905 | }, | ||
| 906 | .contains => |expect_line| { | ||
| 907 | while (actual_line_it.next()) |actual_line| { | ||
| 908 | if (!matchCompileError(actual_line, expect_line)) continue; | ||
| 909 | return; | ||
| 910 | } | ||
| 911 | |||
| 912 | return compile.step.fail( | ||
| 913 | \\ | ||
| 914 | \\========= should contain: =============== | ||
| 915 | \\{s} | ||
| 916 | \\========= but not found: ================ | ||
| 917 | \\{s} | ||
| 918 | \\========================================= | ||
| 919 | , .{ expect_line, actual_errors }); | ||
| 920 | }, | ||
| 921 | .stderr_contains => |expect_line| { | ||
| 922 | const actual_stderr: []const u8 = if (compile.step.result_error_msgs.items.len > 0) | ||
| 923 | compile.step.result_error_msgs.items[0] | ||
| 924 | else | ||
| 925 | &.{}; | ||
| 926 | compile.step.result_error_msgs.clearRetainingCapacity(); | ||
| 927 | |||
| 928 | var stderr_line_it = mem.splitScalar(u8, actual_stderr, '\n'); | ||
| 929 | |||
| 930 | while (stderr_line_it.next()) |actual_line| { | ||
| 931 | if (!matchCompileError(actual_line, expect_line)) continue; | ||
| 932 | return; | ||
| 933 | } | ||
| 934 | |||
| 935 | return compile.step.fail( | ||
| 936 | \\ | ||
| 937 | \\========= should contain: =============== | ||
| 938 | \\{s} | ||
| 939 | \\========= but not found: ================ | ||
| 940 | \\{s} | ||
| 941 | \\========================================= | ||
| 942 | , .{ expect_line, actual_stderr }); | ||
| 943 | }, | ||
| 944 | .exact => |expect_lines| { | ||
| 945 | for (expect_lines) |expect_line| { | ||
| 946 | const actual_line = actual_line_it.next() orelse { | ||
| 947 | try expected_generated.appendSlice(arena, expect_line); | ||
| 948 | try expected_generated.append(arena, '\n'); | ||
| 949 | continue; | ||
| 950 | }; | ||
| 951 | if (matchCompileError(actual_line, expect_line)) { | ||
| 952 | try expected_generated.appendSlice(arena, actual_line); | ||
| 953 | try expected_generated.append(arena, '\n'); | ||
| 954 | continue; | ||
| 955 | } | ||
| 956 | try expected_generated.appendSlice(arena, expect_line); | ||
| 957 | try expected_generated.append(arena, '\n'); | ||
| 958 | } | ||
| 959 | |||
| 960 | if (mem.eql(u8, expected_generated.items, actual_errors)) return; | ||
| 961 | |||
| 962 | return compile.step.fail( | ||
| 963 | \\ | ||
| 964 | \\========= expected: ===================== | ||
| 965 | \\{s} | ||
| 966 | \\========= but found: ==================== | ||
| 967 | \\{s} | ||
| 968 | \\========================================= | ||
| 969 | , .{ expected_generated.items, actual_errors }); | ||
| 970 | }, | ||
| 971 | } | ||
| 972 | } | ||
| 973 | |||
| 974 | fn matchCompileError(actual: []const u8, expected: []const u8) bool { | ||
| 975 | if (mem.endsWith(u8, actual, expected)) return true; | ||
| 976 | if (mem.startsWith(u8, expected, ":?:?: ")) { | ||
| 977 | if (mem.endsWith(u8, actual, expected[":?:?: ".len..])) return true; | ||
| 978 | } | ||
| 979 | // We scan for /?/ in expected line and if there is a match, we match everything | ||
| 980 | // up to and after /?/. | ||
| 981 | const expected_trim = mem.trim(u8, expected, " "); | ||
| 982 | if (mem.find(u8, expected_trim, "/?/")) |index| { | ||
| 983 | const actual_trim = mem.trim(u8, actual, " "); | ||
| 984 | const lhs = expected_trim[0..index]; | ||
| 985 | const rhs = expected_trim[index + "/?/".len ..]; | ||
| 986 | if (mem.startsWith(u8, actual_trim, lhs) and mem.endsWith(u8, actual_trim, rhs)) return true; | ||
| 987 | } | ||
| 988 | return false; | ||
| 989 | } | ||
| 990 | |||
| 991 | pub fn rootModuleTarget(c: *Compile) std.Target { | 856 | pub fn rootModuleTarget(c: *Compile) std.Target { |
| 992 | // The root module is always given a target, so we know this to be non-null. | 857 | // The root module is always given a target, so we know this to be non-null. |
| 993 | return c.root_module.resolved_target.?.result; | 858 | return c.root_module.resolved_target.?.result; |
| 994 | } | 859 | } |
| 995 | 860 | ||
| 996 | fn moduleNeedsCliArg(mod: *const Module) bool { | ||
| 997 | return for (mod.link_objects.items) |o| switch (o) { | ||
| 998 | .c_source_file, .c_source_files, .assembly_file, .win32_resource_file => break true, | ||
| 999 | else => continue, | ||
| 1000 | } else false; | ||
| 1001 | } | ||
| 1002 | |||
| 1003 | /// Return the full set of `Step.Compile` which `start` depends on, recursively. `start` itself is | 861 | /// Return the full set of `Step.Compile` which `start` depends on, recursively. `start` itself is |
| 1004 | /// always returned as the first element. If `chase_dynamic` is `false`, then dynamic libraries are | 862 | /// always returned as the first element. If `chase_dynamic` is `false`, then dynamic libraries are |
| 1005 | /// not included, and their dependencies are not considered; if `chase_dynamic` is `true`, dynamic | 863 | /// not included, and their dependencies are not considered; if `chase_dynamic` is `true`, dynamic |
lib/std/zig.zig+2-2| ... | @@ -374,9 +374,9 @@ pub const Subsystem = enum { | ... | @@ -374,9 +374,9 @@ pub const Subsystem = enum { |
| 374 | pub const EfiRuntimeDriver: Subsystem = .efi_runtime_driver; | 374 | pub const EfiRuntimeDriver: Subsystem = .efi_runtime_driver; |
| 375 | }; | 375 | }; |
| 376 | 376 | ||
| 377 | pub const CompressDebugSections = enum { none, zlib, zstd }; | 377 | pub const CompressDebugSections = enum(u2) { none, zlib, zstd }; |
| 378 | 378 | ||
| 379 | pub const RcIncludes = enum { | 379 | pub const RcIncludes = enum(u2) { |
| 380 | /// Use MSVC if available, fall back to MinGW. | 380 | /// Use MSVC if available, fall back to MinGW. |
| 381 | any, | 381 | any, |
| 382 | /// Use MSVC include paths (MSVC install + Windows SDK, must be present on the system). | 382 | /// Use MSVC include paths (MSVC install + Windows SDK, must be present on the system). |
lib/std/zig/Configuration.zig+254-4| ... | @@ -206,7 +206,7 @@ pub const Step = extern struct { | ... | @@ -206,7 +206,7 @@ pub const Step = extern struct { |
| 206 | _, | 206 | _, |
| 207 | }; | 207 | }; |
| 208 | 208 | ||
| 209 | pub const Tag = enum(u8) { | 209 | pub const Tag = enum(u5) { |
| 210 | top_level, | 210 | top_level, |
| 211 | compile, | 211 | compile, |
| 212 | install_artifact, | 212 | install_artifact, |
| ... | @@ -232,7 +232,7 @@ pub const Step = extern struct { | ... | @@ -232,7 +232,7 @@ pub const Step = extern struct { |
| 232 | 232 | ||
| 233 | pub const Flags = packed struct(u32) { | 233 | pub const Flags = packed struct(u32) { |
| 234 | tag: Tag = .top_level, | 234 | tag: Tag = .top_level, |
| 235 | _: u24 = 0, | 235 | _: u27 = 0, |
| 236 | }; | 236 | }; |
| 237 | }; | 237 | }; |
| 238 | 238 | ||
| ... | @@ -258,7 +258,7 @@ pub const Step = extern struct { | ... | @@ -258,7 +258,7 @@ pub const Step = extern struct { |
| 258 | pub const Flags = packed struct(u32) { | 258 | pub const Flags = packed struct(u32) { |
| 259 | tag: Tag = .install_artifact, | 259 | tag: Tag = .install_artifact, |
| 260 | dylib_symlinks: bool, | 260 | dylib_symlinks: bool, |
| 261 | _: u23 = 0, | 261 | _: u26 = 0, |
| 262 | }; | 262 | }; |
| 263 | }; | 263 | }; |
| 264 | 264 | ||
| ... | @@ -342,7 +342,253 @@ pub const Step = extern struct { | ... | @@ -342,7 +342,253 @@ pub const Step = extern struct { |
| 342 | stderr_trim_whitespace: TrimWhitespace, | 342 | stderr_trim_whitespace: TrimWhitespace, |
| 343 | stdio_limit: bool, | 343 | stdio_limit: bool, |
| 344 | producer: bool, | 344 | producer: bool, |
| 345 | _: u5 = 0, | 345 | _: u8 = 0, |
| 346 | }; | ||
| 347 | }; | ||
| 348 | |||
| 349 | /// Trailing: | ||
| 350 | /// * filters_len: u32, // if flag is set | ||
| 351 | /// * exec_cmd_args_len: u32, // if flag is set | ||
| 352 | /// * installed_headers_len: u32, // if flag is set | ||
| 353 | /// * force_undefined_symbols_len: u32, // if flag is set | ||
| 354 | /// * exacts_len: u32 if expected_compile_errors is exact | ||
| 355 | /// * filter: String for each filters_len | ||
| 356 | /// * exec_cmd_arg: String for each exec_cmd_args_len | ||
| 357 | /// * InstalledHeader for each installed_headers_len | ||
| 358 | /// * force_undefined_symbol: String for each force_undefined_symbols_len | ||
| 359 | /// * String for each exacts_len | ||
| 360 | /// * linker_script: LazyPath if flag is set | ||
| 361 | /// * version_script: LazyPath if flag is set | ||
| 362 | /// * zig_lib_dir: LazyPath if flag is set | ||
| 363 | /// * libc_file: LazyPath if flag is set | ||
| 364 | /// * test_runner: LazyPath if test_runner_mode is not default | ||
| 365 | /// * win32_manifest: LazyPath if flag is set | ||
| 366 | /// * win32_module_definition: LazyPath if flag is set | ||
| 367 | /// * entitlements: LazyPath if flag is set | ||
| 368 | /// * version: String if flag is set (semantic version string) | ||
| 369 | /// * entry: String if entry is symbol | ||
| 370 | /// * install_name: String if flag is set | ||
| 371 | /// * String if expected_compile_errors is contains, starts_with, or stderr_contains | ||
| 372 | /// * initial_memory: u64 if flag is set | ||
| 373 | /// * max_memory: u64 if flag is set | ||
| 374 | /// * global_base: u64 if flag is set | ||
| 375 | /// * image_base: u64 if flag is set | ||
| 376 | /// * link_z_common_page_size if flag is set | ||
| 377 | /// * link_z_max_page_size if flag is set | ||
| 378 | /// * pagezero_size if flag is set | ||
| 379 | /// * stack_size if flag is set | ||
| 380 | /// * headerpad_size if flag is set | ||
| 381 | /// * error_limit if flag is set | ||
| 382 | /// * Hexstring if build_id is hexstring | ||
| 383 | pub const Compile = struct { | ||
| 384 | flags: Flags, | ||
| 385 | flags2: Flags2, | ||
| 386 | flags3: Flags3, | ||
| 387 | flags4: Flags4, | ||
| 388 | |||
| 389 | root_module: Module, | ||
| 390 | root_name: String, | ||
| 391 | |||
| 392 | pub const ExpectedCompileErrors = enum(u3) { contains, exact, starts_with, stderr_contains, none }; | ||
| 393 | pub const TestRunnerMode = enum(u2) { default, simple, server }; | ||
| 394 | pub const Entry = enum(u2) { default, disabled, enabled, symbol_name }; | ||
| 395 | |||
| 396 | pub const Lto = enum(u2) { | ||
| 397 | none, | ||
| 398 | full, | ||
| 399 | thin, | ||
| 400 | default, | ||
| 401 | |||
| 402 | pub fn init(lto: ?std.zig.LtoMode) Lto { | ||
| 403 | return switch (lto orelse return .default) { | ||
| 404 | .none => .none, | ||
| 405 | .full => .full, | ||
| 406 | .thin => .thin, | ||
| 407 | }; | ||
| 408 | } | ||
| 409 | }; | ||
| 410 | |||
| 411 | pub const BuildId = enum(u3) { | ||
| 412 | none, | ||
| 413 | fast, | ||
| 414 | uuid, | ||
| 415 | sha1, | ||
| 416 | md5, | ||
| 417 | hexstring, | ||
| 418 | default, | ||
| 419 | |||
| 420 | pub fn init(build_id: ?std.zig.BuildId) BuildId { | ||
| 421 | return switch (build_id orelse return .default) { | ||
| 422 | .none => .none, | ||
| 423 | .fast => .fast, | ||
| 424 | .uuid => .uuid, | ||
| 425 | .sha1 => .sha1, | ||
| 426 | .md5 => .md5, | ||
| 427 | .hexstring => .hexstring, | ||
| 428 | }; | ||
| 429 | } | ||
| 430 | }; | ||
| 431 | pub const WasiExecModel = enum(u2) { | ||
| 432 | default, | ||
| 433 | command, | ||
| 434 | reactor, | ||
| 435 | |||
| 436 | pub fn init(wasi_exec_model: ?std.builtin.WasiExecModel) WasiExecModel { | ||
| 437 | return switch (wasi_exec_model orelse return .default) { | ||
| 438 | .command => .command, | ||
| 439 | .reactor => .reactor, | ||
| 440 | }; | ||
| 441 | } | ||
| 442 | }; | ||
| 443 | pub const Linkage = enum(u2) { | ||
| 444 | static, | ||
| 445 | dynamic, | ||
| 446 | default, | ||
| 447 | |||
| 448 | pub fn init(link_mode: ?std.builtin.LinkMode) Linkage { | ||
| 449 | return switch (link_mode orelse return .default) { | ||
| 450 | .static => .static, | ||
| 451 | .dynamic => .dynamic, | ||
| 452 | }; | ||
| 453 | } | ||
| 454 | }; | ||
| 455 | pub const Kind = enum(u3) { | ||
| 456 | exe, | ||
| 457 | lib, | ||
| 458 | obj, | ||
| 459 | @"test", | ||
| 460 | test_obj, | ||
| 461 | |||
| 462 | pub fn isTest(kind: Kind) bool { | ||
| 463 | return switch (kind) { | ||
| 464 | .exe, .lib, .obj => false, | ||
| 465 | .@"test", .test_obj => true, | ||
| 466 | }; | ||
| 467 | } | ||
| 468 | }; | ||
| 469 | pub const DefaultingBool = enum(u2) { | ||
| 470 | false, | ||
| 471 | true, | ||
| 472 | default, | ||
| 473 | |||
| 474 | pub fn init(b: ?bool) DefaultingBool { | ||
| 475 | return switch (b orelse return .default) { | ||
| 476 | false => .false, | ||
| 477 | true => .true, | ||
| 478 | }; | ||
| 479 | } | ||
| 480 | }; | ||
| 481 | |||
| 482 | pub const Subsystem = enum(u4) { | ||
| 483 | console, | ||
| 484 | windows, | ||
| 485 | posix, | ||
| 486 | native, | ||
| 487 | efi_application, | ||
| 488 | efi_boot_service_driver, | ||
| 489 | efi_rom, | ||
| 490 | efi_runtime_driver, | ||
| 491 | default, | ||
| 492 | |||
| 493 | pub fn init(subsystem: ?std.zig.Subsystem) Subsystem { | ||
| 494 | return switch (subsystem orelse return .default) { | ||
| 495 | .console => .console, | ||
| 496 | .windows => .windows, | ||
| 497 | .posix => .posix, | ||
| 498 | .native => .native, | ||
| 499 | .efi_application => .efi_application, | ||
| 500 | .efi_boot_service_driver => .efi_boot_service_driver, | ||
| 501 | .efi_rom => .efi_rom, | ||
| 502 | .efi_runtime_driver => .efi_runtime_driver, | ||
| 503 | }; | ||
| 504 | } | ||
| 505 | }; | ||
| 506 | |||
| 507 | pub const Flags = packed struct(u32) { | ||
| 508 | tag: Tag = .compile, | ||
| 509 | |||
| 510 | filters_len: bool, | ||
| 511 | exec_cmd_args_len: bool, | ||
| 512 | installed_headers_len: bool, | ||
| 513 | force_undefined_symbols_len: bool, | ||
| 514 | |||
| 515 | verbose_link: bool, | ||
| 516 | verbose_cc: bool, | ||
| 517 | rdynamic: bool, | ||
| 518 | import_memory: bool, | ||
| 519 | export_memory: bool, | ||
| 520 | import_symbols: bool, | ||
| 521 | import_table: bool, | ||
| 522 | export_table: bool, | ||
| 523 | shared_memory: bool, | ||
| 524 | link_eh_frame_hdr: bool, | ||
| 525 | link_emit_relocs: bool, | ||
| 526 | link_function_sections: bool, | ||
| 527 | link_data_sections: bool, | ||
| 528 | linker_dynamicbase: bool, | ||
| 529 | link_z_notext: bool, | ||
| 530 | link_z_relro: bool, | ||
| 531 | link_z_lazy: bool, | ||
| 532 | link_z_defs: bool, | ||
| 533 | headerpad_max_install_names: bool, | ||
| 534 | dead_strip_dylibs: bool, | ||
| 535 | force_load_objc: bool, | ||
| 536 | discard_local_symbols: bool, | ||
| 537 | mingw_unicode_entry_point: bool, | ||
| 538 | }; | ||
| 539 | |||
| 540 | pub const Flags2 = packed struct(u32) { | ||
| 541 | pie: DefaultingBool, | ||
| 542 | formatted_panics: DefaultingBool, | ||
| 543 | bundle_compiler_rt: DefaultingBool, | ||
| 544 | bundle_ubsan_rt: DefaultingBool, | ||
| 545 | each_lib_rpath: DefaultingBool, | ||
| 546 | link_gc_sections: DefaultingBool, | ||
| 547 | linker_allow_shlib_undefined: DefaultingBool, | ||
| 548 | linker_allow_undefined_version: DefaultingBool, | ||
| 549 | linker_enable_new_dtags: DefaultingBool, | ||
| 550 | dll_export_fns: DefaultingBool, | ||
| 551 | use_llvm: DefaultingBool, | ||
| 552 | use_lld: DefaultingBool, | ||
| 553 | use_new_linker: DefaultingBool, | ||
| 554 | allow_so_scripts: DefaultingBool, | ||
| 555 | sanitize_coverage_trace_pc_guard: DefaultingBool, | ||
| 556 | linkage: Linkage, | ||
| 557 | }; | ||
| 558 | |||
| 559 | pub const Flags3 = packed struct(u32) { | ||
| 560 | is_linking_libc: bool, | ||
| 561 | is_linking_libcpp: bool, | ||
| 562 | version: bool, | ||
| 563 | initial_memory: bool, | ||
| 564 | max_memory: bool, | ||
| 565 | kind: Kind, | ||
| 566 | compress_debug_sections: std.zig.CompressDebugSections, | ||
| 567 | global_base: bool, | ||
| 568 | test_runner_mode: TestRunnerMode, | ||
| 569 | wasi_exec_model: WasiExecModel, | ||
| 570 | win32_manifest: bool, | ||
| 571 | win32_module_definition: bool, | ||
| 572 | zig_lib_dir: bool, | ||
| 573 | rc_includes: std.zig.RcIncludes, | ||
| 574 | image_base: bool, | ||
| 575 | build_id: BuildId, | ||
| 576 | entry: Entry, | ||
| 577 | lto: Lto, | ||
| 578 | subsystem: Subsystem, | ||
| 579 | }; | ||
| 580 | |||
| 581 | pub const Flags4 = packed struct(u32) { | ||
| 582 | libc_file: bool, | ||
| 583 | link_z_common_page_size: bool, | ||
| 584 | link_z_max_page_size: bool, | ||
| 585 | pagezero_size: bool, | ||
| 586 | stack_size: bool, | ||
| 587 | headerpad_size: bool, | ||
| 588 | error_limit: bool, | ||
| 589 | install_name: bool, | ||
| 590 | entitlements: bool, | ||
| 591 | _: u23 = 0, | ||
| 346 | }; | 592 | }; |
| 347 | }; | 593 | }; |
| 348 | }; | 594 | }; |
| ... | @@ -420,6 +666,10 @@ pub const Package = enum(u32) { | ... | @@ -420,6 +666,10 @@ pub const Package = enum(u32) { |
| 420 | _, | 666 | _, |
| 421 | }; | 667 | }; |
| 422 | 668 | ||
| 669 | pub const Module = enum(u32) { | ||
| 670 | _, | ||
| 671 | }; | ||
| 672 | |||
| 423 | /// Points into `extra`, where the first element is number of deps, | 673 | /// Points into `extra`, where the first element is number of deps, |
| 424 | /// following elements is `Step.Index` per dep. | 674 | /// following elements is `Step.Index` per dep. |
| 425 | pub const Deps = enum(u32) { | 675 | pub const Deps = enum(u32) { |