From 5492b1e3264af7151adb215cdf905a41f93d2713 Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Tue, 14 Apr 2026 10:26:35 +0100 Subject: [PATCH] tests: move incremental target matrix out of manifests Having the matrix of test targets for incremental compilation in the individual test manifests has turned out to be inconvenient for a few reasons: the tests are almost certain to accidentally get out of sync, disabling targets entirely is annoying to do, and incr-check needs to take care to print the target in all error messages (which currently does not always happen). If I recall correctly, I originally designed it this way because it allows targets to be disabled at the granularity of individual tests, but there's an easier approach to that: just let a test manifest that it should be *skipped* on a certain target! As skipping is the rare case, and also the case you want readers to notice, it makes sense for *it* to be explicitly specified, like how unit tests use `error.SkipZigTest`. So, `incr-check` no longer runs through a list of targets specified in the manifest. Instead, it accepts (and, in fact, requires) a single target on the command line, and runs the test for that specific target. If the file contains a `#skip_target` directive for that target, then `incr-check` exits immediately, so we can still disable targets at individual test granularity, but you can also disable a target for all tests by just commenting it out of the matrix in `test/tests.zig`. As a nice bonus, this also allows the build system to run different incremental test targets in parallel, because the targets are now different steps. This definitely seems like a better way to split the work between the build system and incr-check---sorry for getting this wrong initially! --- test/incremental/add_decl | 6 - test/incremental/add_decl_namespaced | 6 - test/incremental/add_remove_struct_fields | 6 - test/incremental/add_remove_toplevel_fields | 6 - .../analysis_error_and_syntax_error | 6 - test/incremental/bad_import | 7 - test/incremental/change_embed_file | 6 - test/incremental/change_enum_tag_type | 6 - test/incremental/change_exports | 6 - test/incremental/change_fn_type | 6 - test/incremental/change_generic_line_number | 4 - test/incremental/change_line_number | 4 - test/incremental/change_module | 6 - test/incremental/change_panic_handler | 6 - .../incremental/change_panic_handler_explicit | 6 - test/incremental/change_shift_op | 6 - test/incremental/change_struct_same_fields | 6 - test/incremental/change_zon_file | 6 - .../change_zon_file_no_result_type | 6 - test/incremental/compile_error_then_log | 6 - test/incremental/compile_log | 7 - test/incremental/delete_comptime_decls | 6 - .../dependency_on_type_of_inferred_global | 6 - test/incremental/fix_astgen_failure | 6 - test/incremental/function_becomes_inline | 6 - test/incremental/hello | 6 - test/incremental/make_decl_pub | 6 - test/incremental/modify_inline_fn | 6 - test/incremental/move_src | 6 - .../incremental/no_change_preserves_tag_names | 6 - .../recursive_function_becomes_non_recursive | 6 - test/incremental/remove_enum_field | 6 - .../remove_invalid_union_backing_enum | 6 - test/incremental/temporary_parse_error | 6 - test/incremental/type_becomes_comptime_only | 6 - test/incremental/type_dependency_loop | 6 - test/incremental/unreferenced_error | 6 - test/tests.zig | 48 +- tools/incr-check.zig | 411 ++++++++++-------- 39 files changed, 256 insertions(+), 423 deletions(-) diff --git a/test/incremental/add_decl b/test/incremental/add_decl index aca2e9744e8e637a3ea42377ce24d9cbf54c98b7..50d961da7b88f00b78b2895ebfeae18e76219d6a 100644 --- a/test/incremental/add_decl +++ b/test/incremental/add_decl @@ -1,9 +1,3 @@ -#target=x86_64-linux-selfhosted -//#target=x86_64-windows-selfhosted -#target=x86_64-linux-cbe -#target=x86_64-windows-cbe -#target=x86_64-linux-llvm -//#target=wasm32-wasi-selfhosted #update=initial version #file=main.zig const std = @import("std"); diff --git a/test/incremental/add_decl_namespaced b/test/incremental/add_decl_namespaced index 09f569d02ed6392c01c27b7c49939ccc3ae46406..e1fa74a3ad7ecd6bb70b481f73d6db0702c27d22 100644 --- a/test/incremental/add_decl_namespaced +++ b/test/incremental/add_decl_namespaced @@ -1,9 +1,3 @@ -#target=x86_64-linux-selfhosted -//#target=x86_64-windows-selfhosted -#target=x86_64-linux-cbe -#target=x86_64-windows-cbe -#target=x86_64-linux-llvm -//#target=wasm32-wasi-selfhosted #update=initial version #file=main.zig const std = @import("std"); diff --git a/test/incremental/add_remove_struct_fields b/test/incremental/add_remove_struct_fields index dabe2dcd03c94e1dd3d2aae4d269ee15bf1a92c9..44d17e618e0c47ade8b9ec48c74b7c967ebd8075 100644 --- a/test/incremental/add_remove_struct_fields +++ b/test/incremental/add_remove_struct_fields @@ -1,9 +1,3 @@ -#target=x86_64-linux-selfhosted -//#target=x86_64-windows-selfhosted -#target=x86_64-linux-cbe -#target=x86_64-windows-cbe -#target=x86_64-linux-llvm -//#target=wasm32-wasi-selfhosted #update=initial version #file=main.zig const S = struct { x: u8 }; diff --git a/test/incremental/add_remove_toplevel_fields b/test/incremental/add_remove_toplevel_fields index 8ed1a7af8bb0659a715439a10afc59c17eede4e2..4c36acb74a6195a41cab523791ad209292856584 100644 --- a/test/incremental/add_remove_toplevel_fields +++ b/test/incremental/add_remove_toplevel_fields @@ -1,9 +1,3 @@ -#target=x86_64-linux-selfhosted -//#target=x86_64-windows-selfhosted -#target=x86_64-linux-cbe -#target=x86_64-windows-cbe -#target=x86_64-linux-llvm -//#target=wasm32-wasi-selfhosted #update=initial version #file=main.zig const S = @This(); diff --git a/test/incremental/analysis_error_and_syntax_error b/test/incremental/analysis_error_and_syntax_error index 7347920b14593ba33a3dfe75584f46f68ee8cb17..6c703db7545fd51153794b18ab696e25851bf8a5 100644 --- a/test/incremental/analysis_error_and_syntax_error +++ b/test/incremental/analysis_error_and_syntax_error @@ -1,9 +1,3 @@ -#target=x86_64-linux-selfhosted -//#target=x86_64-windows-selfhosted -#target=x86_64-linux-cbe -#target=x86_64-windows-cbe -#target=x86_64-linux-llvm -//#target=wasm32-wasi-selfhosted #update=initial version #file=main.zig pub fn main() !void { diff --git a/test/incremental/bad_import b/test/incremental/bad_import index db507df8577bef27a620119fe7fd1bb1c46c4e3a..ab6369bee38a0d8c0c3e01b42458cc52051e4f5f 100644 --- a/test/incremental/bad_import +++ b/test/incremental/bad_import @@ -1,10 +1,3 @@ -#target=x86_64-linux-selfhosted -//#target=x86_64-windows-selfhosted -#target=x86_64-linux-cbe -#target=x86_64-windows-cbe -#target=x86_64-linux-llvm -//#target=wasm32-wasi-selfhosted - #update=initial version #file=main.zig pub fn main() !void { diff --git a/test/incremental/change_embed_file b/test/incremental/change_embed_file index 5b053b857cea9d407fec7e8dad7ddce5b21d3f82..34efcdcc5a4fb112e35c862173e85afd96a15ddd 100644 --- a/test/incremental/change_embed_file +++ b/test/incremental/change_embed_file @@ -1,9 +1,3 @@ -#target=x86_64-linux-selfhosted -//#target=x86_64-windows-selfhosted -#target=x86_64-linux-cbe -#target=x86_64-windows-cbe -#target=x86_64-linux-llvm -//#target=wasm32-wasi-selfhosted #update=initial version #file=main.zig const std = @import("std"); diff --git a/test/incremental/change_enum_tag_type b/test/incremental/change_enum_tag_type index 0d47c705643a6491f115c3908dfd989cf232f7bb..3e1d184fc82cba834a413c1ce01838397b9e1d94 100644 --- a/test/incremental/change_enum_tag_type +++ b/test/incremental/change_enum_tag_type @@ -1,9 +1,3 @@ -#target=x86_64-linux-selfhosted -//#target=x86_64-windows-selfhosted -#target=x86_64-linux-cbe -#target=x86_64-windows-cbe -#target=x86_64-linux-llvm -//#target=wasm32-wasi-selfhosted #update=initial version #file=main.zig const Tag = u2; diff --git a/test/incremental/change_exports b/test/incremental/change_exports index 2f7e9afb1db91aee909568e1e50664a5a2d5028b..64aec0288cbbf82420b8eaf5345245bea34d72b0 100644 --- a/test/incremental/change_exports +++ b/test/incremental/change_exports @@ -1,9 +1,3 @@ -#target=x86_64-linux-selfhosted -//#target=x86_64-windows-selfhosted -#target=x86_64-linux-cbe -#target=x86_64-windows-cbe -#target=x86_64-linux-llvm - #update=initial version #file=main.zig export fn foo() void {} diff --git a/test/incremental/change_fn_type b/test/incremental/change_fn_type index e4df97a99fc484aca5c65bf053f8d987701a9092..ca0667d8041e05c363a9c975b865c6e1a7640904 100644 --- a/test/incremental/change_fn_type +++ b/test/incremental/change_fn_type @@ -1,9 +1,3 @@ -#target=x86_64-linux-selfhosted -//#target=x86_64-windows-selfhosted -#target=x86_64-linux-cbe -#target=x86_64-windows-cbe -#target=x86_64-linux-llvm -//#target=wasm32-wasi-selfhosted #update=initial version #file=main.zig pub fn main() !void { diff --git a/test/incremental/change_generic_line_number b/test/incremental/change_generic_line_number index dbc49fdc712c1a05d788342d6c92132d917841df..23b3f2c0190a47c9c5e8a124af324b308fc100a3 100644 --- a/test/incremental/change_generic_line_number +++ b/test/incremental/change_generic_line_number @@ -1,7 +1,3 @@ -#target=x86_64-linux-selfhosted -//#target=x86_64-windows-selfhosted -#target=x86_64-linux-llvm -//#target=wasm32-wasi-selfhosted #update=initial version #file=main.zig const std = @import("std"); diff --git a/test/incremental/change_line_number b/test/incremental/change_line_number index 0d139c49b97f787e8bb08f88471208d91dbc5f80..90a1edb95c924143792363c8b14c6414f0fbac13 100644 --- a/test/incremental/change_line_number +++ b/test/incremental/change_line_number @@ -1,7 +1,3 @@ -#target=x86_64-linux-selfhosted -//#target=x86_64-windows-selfhosted -#target=x86_64-linux-llvm -//#target=wasm32-wasi-selfhosted #update=initial version #file=main.zig const std = @import("std"); diff --git a/test/incremental/change_module b/test/incremental/change_module index dbf9a849df62012eb74f17ec5ce0b1b1d06426af..4e573eecac23bd86de3bfe3df850585dbb7a8a77 100644 --- a/test/incremental/change_module +++ b/test/incremental/change_module @@ -1,9 +1,3 @@ -#target=x86_64-linux-selfhosted -//#target=x86_64-windows-selfhosted -#target=x86_64-linux-cbe -#target=x86_64-windows-cbe -#target=x86_64-linux-llvm -//#target=wasm32-wasi-selfhosted #module=foo=foo.zig #update=initial version diff --git a/test/incremental/change_panic_handler b/test/incremental/change_panic_handler index a3d42aab8e1036505167c2a291af32c3760c15af..b250c9867985a683a209279835f366703f2f5161 100644 --- a/test/incremental/change_panic_handler +++ b/test/incremental/change_panic_handler @@ -1,9 +1,3 @@ -#target=x86_64-linux-selfhosted -//#target=x86_64-windows-selfhosted -#target=x86_64-linux-cbe -#target=x86_64-windows-cbe -#target=x86_64-linux-llvm -//#target=wasm32-wasi-selfhosted #update=initial version #file=main.zig pub fn main() !u8 { diff --git a/test/incremental/change_panic_handler_explicit b/test/incremental/change_panic_handler_explicit index 44415ea5900ad4eea4878b2b0b350382d060ac4f..662d13847f9800553b41fca4e9545e3bc07dbb17 100644 --- a/test/incremental/change_panic_handler_explicit +++ b/test/incremental/change_panic_handler_explicit @@ -1,9 +1,3 @@ -#target=x86_64-linux-selfhosted -//#target=x86_64-windows-selfhosted -#target=x86_64-linux-cbe -#target=x86_64-windows-cbe -#target=x86_64-linux-llvm -//#target=wasm32-wasi-selfhosted #update=initial version #file=main.zig pub fn main() !u8 { diff --git a/test/incremental/change_shift_op b/test/incremental/change_shift_op index cfbbc8e4f634b1a66992d75eeeacc7c7f45a8d8d..d1fa6e747e125af9506bdff9766bbb5fa0dcd368 100644 --- a/test/incremental/change_shift_op +++ b/test/incremental/change_shift_op @@ -1,9 +1,3 @@ -#target=x86_64-linux-selfhosted -//#target=x86_64-windows-selfhosted -#target=x86_64-linux-cbe -#target=x86_64-windows-cbe -#target=x86_64-linux-llvm -//#target=wasm32-wasi-selfhosted #update=initial version #file=main.zig pub fn main() !void { diff --git a/test/incremental/change_struct_same_fields b/test/incremental/change_struct_same_fields index 18dff1f43bc319883eb5fbf6f1c71f615665482f..b94f03778b21467cf255a13c48c95cce59f99329 100644 --- a/test/incremental/change_struct_same_fields +++ b/test/incremental/change_struct_same_fields @@ -1,9 +1,3 @@ -#target=x86_64-linux-selfhosted -//#target=x86_64-windows-selfhosted -#target=x86_64-linux-cbe -#target=x86_64-windows-cbe -#target=x86_64-linux-llvm -//#target=wasm32-wasi-selfhosted #update=initial version #file=main.zig const S = extern struct { x: u8, y: u8 }; diff --git a/test/incremental/change_zon_file b/test/incremental/change_zon_file index 00edb5200a72355f83fbf3edf60b9d3bfcf4544b..080dc235199d21b5dded5136bd6baf04b72142a0 100644 --- a/test/incremental/change_zon_file +++ b/test/incremental/change_zon_file @@ -1,9 +1,3 @@ -#target=x86_64-linux-selfhosted -//#target=x86_64-windows-selfhosted -#target=x86_64-linux-cbe -#target=x86_64-windows-cbe -#target=x86_64-linux-llvm -//#target=wasm32-wasi-selfhosted #update=initial version #file=main.zig const std = @import("std"); diff --git a/test/incremental/change_zon_file_no_result_type b/test/incremental/change_zon_file_no_result_type index a8f640c1eaee7bdcde64b77b48dfe390e79feafa..5deca8c7fda5e77995ec385bea0ed4e58839dd2e 100644 --- a/test/incremental/change_zon_file_no_result_type +++ b/test/incremental/change_zon_file_no_result_type @@ -1,9 +1,3 @@ -#target=x86_64-linux-selfhosted -//#target=x86_64-windows-selfhosted -#target=x86_64-linux-cbe -#target=x86_64-windows-cbe -#target=x86_64-linux-llvm -//#target=wasm32-wasi-selfhosted #update=initial version #file=main.zig const std = @import("std"); diff --git a/test/incremental/compile_error_then_log b/test/incremental/compile_error_then_log index 14d2e1f8a2f424156090fe3d45d2664a6b42e66f..a19430f7cd2a2e45a7fadb4c6b8b57a3a9927608 100644 --- a/test/incremental/compile_error_then_log +++ b/test/incremental/compile_error_then_log @@ -1,9 +1,3 @@ -#target=x86_64-linux-selfhosted -//#target=x86_64-windows-selfhosted -#target=x86_64-linux-cbe -#target=x86_64-windows-cbe -#target=x86_64-linux-llvm -//#target=wasm32-wasi-selfhosted #update=initial version with compile error #file=main.zig pub fn main() void {} diff --git a/test/incremental/compile_log b/test/incremental/compile_log index a21936d4d6711735dad1ce768717a36d67be81b6..cc4c6368391979358ac215f6b9c73a080cd39ff0 100644 --- a/test/incremental/compile_log +++ b/test/incremental/compile_log @@ -1,10 +1,3 @@ -#target=x86_64-linux-selfhosted -//#target=x86_64-windows-selfhosted -#target=x86_64-linux-cbe -#target=x86_64-windows-cbe -#target=x86_64-linux-llvm -//#target=wasm32-wasi-selfhosted - #update=initial version with no compile log #file=main.zig const std = @import("std"); diff --git a/test/incremental/delete_comptime_decls b/test/incremental/delete_comptime_decls index 850c5de3dc66e6fec5fc903f50d90383eda8ce31..3d653d6d7dea5296437618569edb701d43bbf3ba 100644 --- a/test/incremental/delete_comptime_decls +++ b/test/incremental/delete_comptime_decls @@ -1,9 +1,3 @@ -#target=x86_64-linux-selfhosted -//#target=x86_64-windows-selfhosted -#target=x86_64-linux-cbe -#target=x86_64-windows-cbe -#target=x86_64-linux-llvm -//#target=wasm32-wasi-selfhosted #update=initial version #file=main.zig pub fn main() void {} diff --git a/test/incremental/dependency_on_type_of_inferred_global b/test/incremental/dependency_on_type_of_inferred_global index 25c232ec3226414f59b2b67f477e74f6a05744ff..66e52d58394bec7274dec9b0e1767a72338109ac 100644 --- a/test/incremental/dependency_on_type_of_inferred_global +++ b/test/incremental/dependency_on_type_of_inferred_global @@ -1,9 +1,3 @@ -#target=x86_64-linux-selfhosted -//#target=x86_64-windows-selfhosted -#target=x86_64-linux-cbe -#target=x86_64-windows-cbe -#target=x86_64-linux-llvm -//#target=wasm32-wasi-selfhosted #update=initial version #file=main.zig const foo = @as(u8, 123); diff --git a/test/incremental/fix_astgen_failure b/test/incremental/fix_astgen_failure index ddcfbf4d4840092b6b70ad7561e34682aee20b28..adddc9ac054c2d95709467018ef70af6a71d2a8a 100644 --- a/test/incremental/fix_astgen_failure +++ b/test/incremental/fix_astgen_failure @@ -1,9 +1,3 @@ -#target=x86_64-linux-selfhosted -//#target=x86_64-windows-selfhosted -#target=x86_64-linux-cbe -#target=x86_64-windows-cbe -#target=x86_64-linux-llvm -//#target=wasm32-wasi-selfhosted #update=initial version with error #file=main.zig pub fn main() !void { diff --git a/test/incremental/function_becomes_inline b/test/incremental/function_becomes_inline index 21248c7f93a8775f77e42b251823a96cadcb3253..91afe196ab4d1c28fb041a5f9dd8f0b6956ea463 100644 --- a/test/incremental/function_becomes_inline +++ b/test/incremental/function_becomes_inline @@ -1,9 +1,3 @@ -#target=x86_64-linux-selfhosted -//#target=x86_64-windows-selfhosted -#target=x86_64-linux-cbe -#target=x86_64-windows-cbe -#target=x86_64-linux-llvm -//#target=wasm32-wasi-selfhosted #update=non-inline version #file=main.zig pub fn main() !void { diff --git a/test/incremental/hello b/test/incremental/hello index 2b71f2f4a2e00bee642d6da6a4a4c3438aeccb5f..6988323d3dbb504cad158ad134fccc4ed4023087 100644 --- a/test/incremental/hello +++ b/test/incremental/hello @@ -1,9 +1,3 @@ -#target=x86_64-linux-selfhosted -//#target=x86_64-windows-selfhosted -#target=x86_64-linux-cbe -#target=x86_64-windows-cbe -#target=x86_64-linux-llvm -//#target=wasm32-wasi-selfhosted #update=initial version #file=main.zig const std = @import("std"); diff --git a/test/incremental/make_decl_pub b/test/incremental/make_decl_pub index a518e3df3d34b47ca09013345ba4a53d91fbe25e..cdb057a7dc1fbc0f72d5ed935d47f47c91855f9e 100644 --- a/test/incremental/make_decl_pub +++ b/test/incremental/make_decl_pub @@ -1,9 +1,3 @@ -#target=x86_64-linux-selfhosted -//#target=x86_64-windows-selfhosted -#target=x86_64-linux-cbe -#target=x86_64-windows-cbe -#target=x86_64-linux-llvm -//#target=wasm32-wasi-selfhosted #update=initial version #file=main.zig const foo = @import("foo.zig"); diff --git a/test/incremental/modify_inline_fn b/test/incremental/modify_inline_fn index e0240fde128a71c259552603b42b1754f6552c04..aa7223f6ace49b27eaadfbc92bebffbe6affcc44 100644 --- a/test/incremental/modify_inline_fn +++ b/test/incremental/modify_inline_fn @@ -1,9 +1,3 @@ -#target=x86_64-linux-selfhosted -//#target=x86_64-windows-selfhosted -#target=x86_64-linux-cbe -#target=x86_64-windows-cbe -#target=x86_64-linux-llvm -//#target=wasm32-wasi-selfhosted #update=initial version #file=main.zig const std = @import("std"); diff --git a/test/incremental/move_src b/test/incremental/move_src index 260123bd8f249976be4529159075dae7135989c6..20134267d1244fefb659ffc3d204f55c5db347d3 100644 --- a/test/incremental/move_src +++ b/test/incremental/move_src @@ -1,9 +1,3 @@ -#target=x86_64-linux-selfhosted -//#target=x86_64-windows-selfhosted -#target=x86_64-linux-cbe -#target=x86_64-windows-cbe -#target=x86_64-linux-llvm -//#target=wasm32-wasi-selfhosted #update=initial version #file=main.zig const std = @import("std"); diff --git a/test/incremental/no_change_preserves_tag_names b/test/incremental/no_change_preserves_tag_names index 417cb1f7a18c576a1533fa202ba2a68fe9c53914..138bd919e3d176d11556c37341b51cfba3fa0440 100644 --- a/test/incremental/no_change_preserves_tag_names +++ b/test/incremental/no_change_preserves_tag_names @@ -1,9 +1,3 @@ -#target=x86_64-linux-selfhosted -//#target=x86_64-windows-selfhosted -#target=x86_64-linux-cbe -#target=x86_64-windows-cbe -#target=x86_64-linux-llvm -//#target=wasm32-wasi-selfhosted #update=initial version #file=main.zig const std = @import("std"); diff --git a/test/incremental/recursive_function_becomes_non_recursive b/test/incremental/recursive_function_becomes_non_recursive index ea26ae78864ee1047c9de476d35b821cc2cab454..e789f3860de557247e84240918773ada0362feaa 100644 --- a/test/incremental/recursive_function_becomes_non_recursive +++ b/test/incremental/recursive_function_becomes_non_recursive @@ -1,9 +1,3 @@ -#target=x86_64-linux-selfhosted -//#target=x86_64-windows-selfhosted -#target=x86_64-linux-cbe -#target=x86_64-windows-cbe -#target=x86_64-linux-llvm -//#target=wasm32-wasi-selfhosted #update=initial version #file=main.zig pub fn main() !void { diff --git a/test/incremental/remove_enum_field b/test/incremental/remove_enum_field index b44d6129c27a3814138c3b9e4a1cd6df45622560..f478ea7f5528410cb20c367cb01aa0157a34fc12 100644 --- a/test/incremental/remove_enum_field +++ b/test/incremental/remove_enum_field @@ -1,9 +1,3 @@ -#target=x86_64-linux-selfhosted -//#target=x86_64-windows-selfhosted -#target=x86_64-linux-cbe -#target=x86_64-windows-cbe -#target=x86_64-linux-llvm -//#target=wasm32-wasi-selfhosted #update=initial version #file=main.zig const MyEnum = enum(u8) { diff --git a/test/incremental/remove_invalid_union_backing_enum b/test/incremental/remove_invalid_union_backing_enum index c8a4dd9545792fc2203fa41165a22e4e7af3dde9..04970380fb621c4e2e9cb2d3c5069d6448c5b989 100644 --- a/test/incremental/remove_invalid_union_backing_enum +++ b/test/incremental/remove_invalid_union_backing_enum @@ -1,9 +1,3 @@ -#target=x86_64-linux-selfhosted -//#target=x86_64-windows-selfhosted -#target=x86_64-linux-cbe -#target=x86_64-windows-cbe -#target=x86_64-linux-llvm -//#target=wasm32-wasi-selfhosted #update=initial version #file=main.zig const E = enum { a, b, c }; diff --git a/test/incremental/temporary_parse_error b/test/incremental/temporary_parse_error index 07843a29a0b1c496b08acd400eed8cddc7e9b89c..b19636e4455a8c19a028372276b96560c5c523da 100644 --- a/test/incremental/temporary_parse_error +++ b/test/incremental/temporary_parse_error @@ -1,9 +1,3 @@ -#target=x86_64-linux-selfhosted -//#target=x86_64-windows-selfhosted -#target=x86_64-linux-cbe -#target=x86_64-windows-cbe -#target=x86_64-linux-llvm -//#target=wasm32-wasi-selfhosted #update=initial version #file=main.zig const std = @import("std"); diff --git a/test/incremental/type_becomes_comptime_only b/test/incremental/type_becomes_comptime_only index d344a8549e1c11afd0fff656895d8306657a38b4..f5b0f9b5786a684d7e2dc72f78438d18ffad84e5 100644 --- a/test/incremental/type_becomes_comptime_only +++ b/test/incremental/type_becomes_comptime_only @@ -1,9 +1,3 @@ -#target=x86_64-linux-selfhosted -//#target=x86_64-windows-selfhosted -#target=x86_64-linux-cbe -#target=x86_64-windows-cbe -#target=x86_64-linux-llvm -//#target=wasm32-wasi-selfhosted #update=initial version #file=main.zig const SomeType = u32; diff --git a/test/incremental/type_dependency_loop b/test/incremental/type_dependency_loop index 1b22780e9b72ee00de5dd22493850e160e93af6a..b645d4266215f712826dee9291dc3150c397108f 100644 --- a/test/incremental/type_dependency_loop +++ b/test/incremental/type_dependency_loop @@ -1,9 +1,3 @@ -#target=x86_64-linux-selfhosted -//#target=x86_64-windows-selfhosted -#target=x86_64-linux-cbe -#target=x86_64-windows-cbe -#target=x86_64-linux-llvm -//#target=wasm32-wasi-selfhosted #update=initial version #file=main.zig pub const A = struct { b: B }; diff --git a/test/incremental/unreferenced_error b/test/incremental/unreferenced_error index 32474d15af47abd686fd303da253f6dc7792d7c5..f0ab8062594912c7b990472104877bd61a3d6680 100644 --- a/test/incremental/unreferenced_error +++ b/test/incremental/unreferenced_error @@ -1,9 +1,3 @@ -#target=x86_64-linux-selfhosted -//#target=x86_64-windows-selfhosted -#target=x86_64-linux-cbe -#target=x86_64-windows-cbe -#target=x86_64-linux-llvm -//#target=wasm32-wasi-selfhosted #update=initial version #file=main.zig const std = @import("std"); diff --git a/test/tests.zig b/test/tests.zig index ce9a55f3cf4f81bb00b6f38eeecd6702a39f4427..79802156525928cd56207a109873866b86998496 100644 --- a/test/tests.zig +++ b/test/tests.zig @@ -1989,6 +1989,26 @@ const c_abi_targets = blk: { }; }; +/// Unlike `test_targets` and `c_abi_targets`, these targets are just simple strings which we pass +/// directly to `incr-check`. They include the target triple and the compiler backend. +/// +/// If only one specific test is failing on a target, instead of entirely disabling the target here, +/// you can skip the target for that specific test only by adding a line like this to the manifest: +/// #skip_target=x86_64-linux-selfhosted +const incremental_targets: []const []const u8 = &.{ + // Avoid adding more CBE or LLVM targets without good reason: they're a lot slower than others + // to run due to the output (C source code or LLVM IR) being built non-incrementally (by Clang + // or LLVM). We just have a couple here to make sure that it works. + "x86_64-linux-cbe", + "x86_64-linux-llvm", + + "x86_64-linux-selfhosted", + // https://codeberg.org/ziglang/zig/issues/31773 + //"x86_64-windows-selfhosted", + // https://codeberg.org/ziglang/zig/issues/31810 + //"wasm32-wasi-selfhosted", +}; + fn compatible32bitArch(b: *std.Build) ?std.Target.Cpu.Arch { const host = b.graph.host.result; return switch (host.os.tag) { @@ -2935,21 +2955,27 @@ pub fn addIncrementalTests(b: *std.Build, test_step: *Step, test_filters: []cons if (std.mem.indexOf(u8, entry.path, test_filter)) |_| break; } else if (test_filters.len > 0) continue; - const run = b.addRunArtifact(incr_check); - run.setName(b.fmt("incr-check '{s}'", .{entry.basename})); + for (incremental_targets) |target_str| { + const run = b.addRunArtifact(incr_check); + run.setName(b.fmt("incr-check {s} '{s}'", .{ target_str, entry.basename })); - run.addArg(b.graph.zig_exe); - run.addFileArg(b.path("test/incremental/").path(b, entry.path)); - run.addArgs(&.{ "--zig-lib-dir", b.fmt("{f}", .{b.graph.zig_lib_directory}) }); + run.addArg(b.graph.zig_exe); + run.addFileArg(b.path("test/incremental/").path(b, entry.path)); + run.addArgs(&.{ + "--zig-lib-dir", b.graph.zig_lib_directory.path orelse ".", + "--target", target_str, + }); - if (b.enable_qemu) run.addArg("-fqemu"); - if (b.enable_wine) run.addArg("-fwine"); - if (b.enable_wasmtime) run.addArg("-fwasmtime"); - if (b.enable_darling) run.addArg("-fdarling"); + run.addArg("--quiet"); // don't fill stderr telling us about skipped tests etc - run.addCheck(.{ .expect_term = .{ .exited = 0 } }); + if (b.enable_qemu) run.addArg("-fqemu"); + if (b.enable_wine) run.addArg("-fwine"); + if (b.enable_wasmtime) run.addArg("-fwasmtime"); + if (b.enable_darling) run.addArg("-fdarling"); - test_step.dependOn(&run.step); + run.addCheck(.{ .expect_term = .{ .exited = 0 } }); + test_step.dependOn(&run.step); + } } } diff --git a/tools/incr-check.zig b/tools/incr-check.zig index 97ed993c2bed3747c8da1d9c65a13e02bd20d4e9..75906424b18cbfc7e9258906d38b7ac54032c026 100644 --- a/tools/incr-check.zig +++ b/tools/incr-check.zig @@ -4,32 +4,44 @@ const Dir = std.Io.Dir; const Allocator = std.mem.Allocator; const Cache = std.Build.Cache; -const usage = "usage: incr-check [--zig-lib-dir lib] [--debug-log foo] [--preserve-tmp] [--zig-cc-binary /path/to/zig]"; +const usage = + \\Usage: incr-check [options] + \\Options: + \\ --target triple-backend + \\ --quiet + \\ --zig-lib-dir /path/to/zig/lib + \\ --zig-cc-binary /path/to/zig + \\ -fqemu + \\ -fwine + \\ -fwasmtime + \\Debug Options: + \\ --preserve-tmp + \\ --debug-log foo +; pub const std_options: std.Options = .{ .logFn = logImpl, }; -var log_cur_update: ?struct { *const Case.Target, *const Case.Update } = null; +var log_cur_update: ?*const Case.Update = null; fn logImpl( comptime level: std.log.Level, comptime scope: @EnumLiteral(), comptime format: []const u8, args: anytype, ) void { - const target, const update = log_cur_update orelse { + const update = log_cur_update orelse { return std.log.defaultLog(level, scope, format, args); }; std.log.defaultLog( level, scope, - "[{s}-{t} '{s}'] " ++ format, - .{ target.query, target.backend, update.name } ++ args, + "['{s}'] " ++ format, + .{update.name} ++ args, ); } pub fn main(init: std.process.Init) !void { const gpa = init.gpa; - const fatal = std.process.fatal; const arena = init.arena.allocator(); const io = init.io; const environ_map = init.environ_map; @@ -39,11 +51,13 @@ pub fn main(init: std.process.Init) !void { var opt_input_file_name: ?[]const u8 = null; var opt_lib_dir: ?[]const u8 = null; var opt_cc_zig: ?[]const u8 = null; + var opt_target: ?struct { std.Target.Query, Backend } = null; var preserve_tmp = false; var enable_qemu: bool = false; var enable_wine: bool = false; var enable_wasmtime: bool = false; var enable_darling: bool = false; + var quiet: bool = false; var debug_log_args: std.ArrayList([]const u8) = .empty; @@ -52,11 +66,16 @@ pub fn main(init: std.process.Init) !void { while (arg_it.next()) |arg| { if (arg.len > 0 and arg[0] == '-') { if (std.mem.eql(u8, arg, "--zig-lib-dir")) { - opt_lib_dir = arg_it.next() orelse fatal("expected arg after --zig-lib-dir\n{s}", .{usage}); + opt_lib_dir = arg_it.next() orelse badUsage("expected arg after --zig-lib-dir", .{}); + } else if (std.mem.eql(u8, arg, "--target")) { + const str = arg_it.next() orelse badUsage("expected arg after --zig-cc-binary", .{}); + opt_target = parseTargetQueryAndBackend(str, ""); + } else if (std.mem.eql(u8, arg, "--quiet")) { + quiet = true; } else if (std.mem.eql(u8, arg, "--debug-log")) { try debug_log_args.append( arena, - arg_it.next() orelse fatal("expected arg after --debug-log\n{s}", .{usage}), + arg_it.next() orelse badUsage("expected arg after --debug-log", .{}), ); } else if (std.mem.eql(u8, arg, "--preserve-tmp")) { preserve_tmp = true; @@ -69,9 +88,9 @@ pub fn main(init: std.process.Init) !void { } else if (std.mem.eql(u8, arg, "-fdarling")) { enable_darling = true; } else if (std.mem.eql(u8, arg, "--zig-cc-binary")) { - opt_cc_zig = arg_it.next() orelse fatal("expected arg after --zig-cc-binary\n{s}", .{usage}); + opt_cc_zig = arg_it.next() orelse badUsage("expected arg after --zig-cc-binary", .{}); } else { - fatal("unknown option '{s}'\n{s}", .{ arg, usage }); + badUsage("unknown option '{s}'", .{arg}); } continue; } @@ -80,24 +99,29 @@ pub fn main(init: std.process.Init) !void { } else if (opt_input_file_name == null) { opt_input_file_name = arg; } else { - fatal("unknown argument '{s}'\n{s}", .{ arg, usage }); + badUsage("unknown argument '{s}'\n{s}", .{ arg, usage }); } } - const zig_exe = opt_zig_exe orelse fatal("missing path to zig\n{s}", .{usage}); - const input_file_name = opt_input_file_name orelse fatal("missing input file\n{s}", .{usage}); + const zig_exe = opt_zig_exe orelse badUsage("missing path to zig", .{}); + const input_file_name = opt_input_file_name orelse badUsage("missing input file", .{}); + const target_query, const backend = opt_target orelse badUsage("missing required option '--target'", .{}); + + if (backend == .cbe and opt_lib_dir == null) { + std.process.fatal("'--zig-lib-dir' required when using backend 'cbe'", .{}); + } const input_file_bytes = try Dir.cwd().readFileAlloc(io, input_file_name, arena, .limited(std.math.maxInt(u32))); - const case = try Case.parse(arena, io, input_file_bytes); + const case: Case = try .parse(arena, input_file_bytes); - // Check now: if there are any targets using the `cbe` backend, we need the lib dir. - if (opt_lib_dir == null) { - for (case.targets) |target| { - if (target.backend == .cbe) { - fatal("'--zig-lib-dir' requried when using backend 'cbe'", .{}); - } + for (case.skip_targets) |skip| { + if (target_query.eql(skip.query) and backend == skip.backend) { + if (!quiet) std.log.warn("skipping test because of a 'skip_target' match", .{}); + return; } } + const target = try std.zig.system.resolveTargetQuery(io, target_query); + const prog_node = std.Progress.start(io, .{}); defer prog_node.end(); @@ -122,143 +146,137 @@ pub fn main(init: std.process.Init) !void { const host = try std.zig.system.resolveTargetQuery(io, .{}); - const debug_log_verbose = debug_log_args.items.len != 0; + var child_args: std.ArrayList([]const u8) = .empty; + try child_args.appendSlice(arena, &.{ + resolved_zig_exe, + "build-exe", + "-fincremental", + "-fno-ubsan-rt", + "-target", + try target_query.zigTriple(arena), + "--cache-dir", + ".local-cache", + "--global-cache-dir", + ".global-cache", + }); + try child_args.append(arena, "--listen=-"); - for (case.targets) |target| { - const target_prog_node = node: { - var name_buf: [std.Progress.Node.max_name_len]u8 = undefined; - const name = std.fmt.bufPrint(&name_buf, "{s}-{t}", .{ target.query, target.backend }) catch &name_buf; - break :node prog_node.start(name, case.updates.len); - }; - defer target_prog_node.end(); + if (opt_resolved_lib_dir) |resolved_lib_dir| { + try child_args.appendSlice(arena, &.{ "--zig-lib-dir", resolved_lib_dir }); + } + switch (backend) { + .sema => try child_args.append(arena, "-fno-emit-bin"), + .selfhosted => try child_args.appendSlice(arena, &.{ "-fno-llvm", "-fno-lld" }), + .llvm => try child_args.appendSlice(arena, &.{ "-fllvm", "-flld" }), + .cbe => try child_args.appendSlice(arena, &.{ "-ofmt=c", "-lc" }), + } + for (debug_log_args.items) |arg| { + try child_args.appendSlice(arena, &.{ "--debug-log", arg }); + } + for (case.modules) |mod| { + try child_args.appendSlice(arena, &.{ "--dep", mod.name }); + } + try child_args.append(arena, try std.fmt.allocPrint(arena, "-Mroot={s}", .{case.root_source_file})); + for (case.modules) |mod| { + try child_args.append(arena, try std.fmt.allocPrint(arena, "-M{s}={s}", .{ mod.name, mod.file })); + } - if (debug_log_verbose) { - std.log.scoped(.status).info("target: '{s}-{t}'", .{ target.query, target.backend }); - } - var child_args: std.ArrayList([]const u8) = .empty; - try child_args.appendSlice(arena, &.{ - resolved_zig_exe, - "build-exe", - "-fincremental", - "-fno-ubsan-rt", + const zig_prog_node = prog_node.start("zig", 0); + defer zig_prog_node.end(); + + var cc_child_args: std.ArrayList([]const u8) = .empty; + if (backend == .cbe) { + const resolved_cc_zig_exe = if (opt_cc_zig) |cc_zig_exe| + try Dir.path.relative(arena, cwd_path, environ_map, tmp_dir_path, cc_zig_exe) + else + resolved_zig_exe; + + try cc_child_args.appendSlice(arena, &.{ + resolved_cc_zig_exe, + "cc", "-target", - target.query, - "--cache-dir", - ".local-cache", - "--global-cache-dir", - ".global-cache", + try target_query.zigTriple(arena), + "-I", + opt_resolved_lib_dir.?, // verified earlier }); - try child_args.append(arena, "--listen=-"); - if (opt_resolved_lib_dir) |resolved_lib_dir| { - try child_args.appendSlice(arena, &.{ "--zig-lib-dir", resolved_lib_dir }); - } - switch (target.backend) { - .sema => try child_args.append(arena, "-fno-emit-bin"), - .selfhosted => try child_args.appendSlice(arena, &.{ "-fno-llvm", "-fno-lld" }), - .llvm => try child_args.appendSlice(arena, &.{ "-fllvm", "-flld" }), - .cbe => try child_args.appendSlice(arena, &.{ "-ofmt=c", "-lc" }), - } - for (debug_log_args.items) |arg| { - try child_args.appendSlice(arena, &.{ "--debug-log", arg }); - } - for (case.modules) |mod| { - try child_args.appendSlice(arena, &.{ "--dep", mod.name }); - } - try child_args.append(arena, try std.fmt.allocPrint(arena, "-Mroot={s}", .{case.root_source_file})); - for (case.modules) |mod| { - try child_args.append(arena, try std.fmt.allocPrint(arena, "-M{s}={s}", .{ mod.name, mod.file })); - } - - const zig_prog_node = target_prog_node.start("zig build-exe", 0); - defer zig_prog_node.end(); - - var cc_child_args: std.ArrayList([]const u8) = .empty; - if (target.backend == .cbe) { - const resolved_cc_zig_exe = if (opt_cc_zig) |cc_zig_exe| - try Dir.path.relative(arena, cwd_path, environ_map, tmp_dir_path, cc_zig_exe) - else - resolved_zig_exe; - - try cc_child_args.appendSlice(arena, &.{ - resolved_cc_zig_exe, - "cc", - "-target", - target.query, - "-I", - opt_resolved_lib_dir.?, // verified earlier - }); - - try cc_child_args.append(arena, "-o"); - } - - var child = try std.process.spawn(io, .{ - .argv = child_args.items, - .stdin = .pipe, - .stdout = .pipe, - .stderr = .pipe, - .progress_node = zig_prog_node, - .cwd = .{ .path = tmp_dir_path }, - }); - defer child.kill(io); + try cc_child_args.append(arena, "-o"); + } - var eval: Eval = .{ - .arena = arena, - .io = io, - .case = case, - .host = host, - .target = target, - .tmp_dir = tmp_dir, - .tmp_dir_path = tmp_dir_path, - .child = &child, - .allow_stderr = debug_log_verbose, - .preserve_tmp_on_fatal = preserve_tmp, - .cc_child_args = &cc_child_args, - .enable_qemu = enable_qemu, - .enable_wine = enable_wine, - .enable_wasmtime = enable_wasmtime, - .enable_darling = enable_darling, - }; + var child = try std.process.spawn(io, .{ + .argv = child_args.items, + .stdin = .pipe, + .stdout = .pipe, + .stderr = .pipe, + .progress_node = zig_prog_node, + .cwd = .{ .path = tmp_dir_path }, + }); + defer child.kill(io); - var multi_reader_buffer: Io.File.MultiReader.Buffer(2) = undefined; - var multi_reader: Io.File.MultiReader = undefined; - multi_reader.init(gpa, io, multi_reader_buffer.toStreams(), &.{ child.stdout.?, child.stderr.? }); - defer multi_reader.deinit(); + const updates_prog_node = prog_node.start("updates", case.updates.len); + defer updates_prog_node.end(); - for (case.updates) |update| { - var update_node = target_prog_node.start(update.name, 0); - defer update_node.end(); + var eval: Eval = .{ + .arena = arena, + .io = io, + .case = case, + .host = host, + .target = target, + .backend = backend, + .tmp_dir = tmp_dir, + .tmp_dir_path = tmp_dir_path, + .child = &child, + .allow_compiler_stderr = debug_log_args.items.len != 0, + .quiet = quiet, + .preserve_tmp_on_fatal = preserve_tmp, + .cc_child_args = &cc_child_args, + .enable_qemu = enable_qemu, + .enable_wine = enable_wine, + .enable_wasmtime = enable_wasmtime, + .enable_darling = enable_darling, + }; - if (debug_log_verbose) { - std.log.scoped(.status).info("update: '{s}'", .{update.name}); - } + var multi_reader_buffer: Io.File.MultiReader.Buffer(2) = undefined; + var multi_reader: Io.File.MultiReader = undefined; + multi_reader.init(gpa, io, multi_reader_buffer.toStreams(), &.{ child.stdout.?, child.stderr.? }); + defer multi_reader.deinit(); - log_cur_update = .{ &target, &update }; - defer log_cur_update = null; + for (case.updates) |update| { + var update_prog_node = updates_prog_node.start(update.name, 0); + defer update_prog_node.end(); - eval.write(update); - try eval.requestUpdate(); - try eval.check(&multi_reader, update, update_node); + if (debug_log_args.items.len != 0) { + // Print a line separating the debug logs from the compiler in the stderr output. + std.log.scoped(.status).info("update: '{s}'", .{update.name}); } - try eval.end(&multi_reader); + log_cur_update = &update; + defer log_cur_update = null; - waitChild(&child, &eval); + eval.write(update); + try eval.requestUpdate(); + try eval.check(&multi_reader, update, update_prog_node); } + + try eval.end(&multi_reader); + + waitChild(&child, &eval); } const Eval = struct { arena: Allocator, io: Io, - host: std.Target, case: Case, - target: Case.Target, + host: std.Target, + target: std.Target, + backend: Backend, tmp_dir: Dir, tmp_dir_path: []const u8, child: *std.process.Child, - allow_stderr: bool, + allow_compiler_stderr: bool, + quiet: bool, preserve_tmp_on_fatal: bool, - /// When `target.backend == .cbe`, this contains the first few arguments to `zig cc` to build the generated binary. + /// When `backend == .cbe`, this contains the first few arguments to `zig cc` to build the generated binary. /// The arguments `out.c in.c` must be appended before spawning the subprocess. cc_child_args: *std.ArrayList([]const u8), @@ -307,7 +325,7 @@ const Eval = struct { .error_bundle => { const result_error_bundle = try std.zig.Server.allocErrorBundle(arena, body); if (stderr.bufferedLen() > 0) { - if (eval.allow_stderr) { + if (eval.allow_compiler_stderr) { std.log.info("error_bundle stderr:\n{s}", .{stderr.buffered()}); } else { eval.fatal("error_bundle unexpected stderr:\n{s}", .{stderr.buffered()}); @@ -325,14 +343,14 @@ const Eval = struct { _ = r.takeStruct(std.zig.Server.Message.EmitDigest, .little) catch unreachable; if (stderr.bufferedLen() > 0) { - if (eval.allow_stderr) { + if (eval.allow_compiler_stderr) { std.log.info("emit_digest stderr:\n{s}", .{stderr.buffered()}); } else { eval.fatal("emit_digest unexpected stderr:\n{s}", .{stderr.buffered()}); } stderr.tossBuffered(); } - if (eval.target.backend == .sema) { + if (eval.backend == .sema) { try eval.checkSuccessOutcome(update, null, prog_node); continue; } @@ -342,7 +360,7 @@ const Eval = struct { const bin_name = try std.zig.EmitArtifact.bin.cacheName(arena, .{ .root_name = "root", // corresponds to the module name "root" - .target = &eval.target.resolved, + .target = &eval.target, .output_mode = .Exe, }); const bin_path = try Dir.path.join(arena, &.{ result_dir, bin_name }); @@ -357,7 +375,7 @@ const Eval = struct { const buffered_stderr = stderr.buffered(); if (buffered_stderr.len > 0) { - if (eval.allow_stderr) { + if (eval.allow_compiler_stderr) { std.log.info("stderr:\n{s}", .{buffered_stderr}); } else { eval.fatal("unexpected stderr:\n{s}", .{buffered_stderr}); @@ -450,12 +468,12 @@ const Eval = struct { .stdout, .exit_code => {}, } const emitted_path = opt_emitted_path orelse { - std.debug.assert(eval.target.backend == .sema); + std.debug.assert(eval.backend == .sema); return; }; const io = eval.io; - const binary_path = switch (eval.target.backend) { + const binary_path = switch (eval.backend) { .sema => unreachable, .selfhosted, .llvm => emitted_path, .cbe => bin: { @@ -470,15 +488,15 @@ const Eval = struct { const argv: []const []const u8, const is_foreign: bool = sw: switch (std.zig.system.getExternalExecutor( io, &eval.host, - &eval.target.resolved, - .{ .link_libc = eval.target.backend == .cbe }, + &eval.target, + .{ .link_libc = eval.backend == .cbe }, )) { .bad_dl, .bad_os_or_cpu => { // This binary cannot be executed on this host. - if (eval.allow_stderr) { + if (!eval.quiet) { std.log.warn("skipping execution because host '{s}' cannot execute binaries for foreign target '{s}'", .{ try eval.host.zigTriple(eval.arena), - try eval.target.resolved.zigTriple(eval.arena), + try eval.target.zigTriple(eval.arena), }); } return; @@ -534,10 +552,10 @@ const Eval = struct { }) catch |err| { if (is_foreign) { // Chances are the foreign executor isn't available. Skip this evaluation. - if (eval.allow_stderr) { + if (!eval.quiet) { std.log.warn("skipping execution of '{s}' via executor for foreign target '{s}': {t}", .{ binary_path, - try eval.target.resolved.zigTriple(eval.arena), + try eval.target.zigTriple(eval.arena), err, }); } @@ -658,30 +676,30 @@ const Eval = struct { } }; +const Backend = enum { + /// Run semantic analysis only. Runtime output will not be tested, but we still verify + /// that compilation succeeds. Corresponds to `-fno-emit-bin`. + sema, + /// Use the self-hosted code generation backend for this target. + /// Corresponds to `-fno-llvm -fno-lld`. + selfhosted, + /// Use the LLVM backend. + /// Corresponds to `-fllvm -flld`. + llvm, + /// Use the C backend. The output is compiled with `zig cc`. + /// Corresponds to `-ofmt=c`. + cbe, +}; + const Case = struct { updates: []Update, root_source_file: []const u8, - targets: []const Target, + skip_targets: []const SkipTarget, modules: []const Module, - const Target = struct { - query: []const u8, - resolved: std.Target, + const SkipTarget = struct { + query: std.Target.Query, backend: Backend, - const Backend = enum { - /// Run semantic analysis only. Runtime output will not be tested, but we still verify - /// that compilation succeeds. Corresponds to `-fno-emit-bin`. - sema, - /// Use the self-hosted code generation backend for this target. - /// Corresponds to `-fno-llvm -fno-lld`. - selfhosted, - /// Use the LLVM backend. - /// Corresponds to `-fllvm -flld`. - llvm, - /// Use the C backend. The output is compiled with `zig cc`. - /// Corresponds to `-ofmt=c`. - cbe, - }; }; const Module = struct { @@ -721,10 +739,10 @@ const Case = struct { }, }; - fn parse(arena: Allocator, io: Io, bytes: []const u8) !Case { + fn parse(arena: Allocator, bytes: []const u8) !Case { const fatal = std.process.fatal; - var targets: std.ArrayList(Target) = .empty; + var skip_targets: std.ArrayList(SkipTarget) = .empty; var modules: std.ArrayList(Module) = .empty; var updates: std.ArrayList(Update) = .empty; var changes: std.ArrayList(FullContents) = .empty; @@ -739,29 +757,13 @@ const Case = struct { const val = std.mem.trimEnd(u8, line_it.rest(), "\r"); // windows moment if (val.len == 0) { fatal("line {d}: missing value", .{line_n}); - } else if (std.mem.eql(u8, key, "target")) { - const split_idx = std.mem.lastIndexOfScalar(u8, val, '-') orelse - fatal("line {d}: target does not include backend", .{line_n}); - - const query = val[0..split_idx]; - - const backend_str = val[split_idx + 1 ..]; - const backend: Target.Backend = std.meta.stringToEnum(Target.Backend, backend_str) orelse - fatal("line {d}: invalid backend '{s}'", .{ line_n, backend_str }); - - const parsed_query = std.Build.parseTargetQuery(.{ - .arch_os_abi = query, - .object_format = switch (backend) { - .sema, .selfhosted, .llvm => null, - .cbe => "c", - }, - }) catch fatal("line {d}: invalid target query '{s}'", .{ line_n, query }); - - const resolved = try std.zig.system.resolveTargetQuery(io, parsed_query); - - try targets.append(arena, .{ + } else if (std.mem.eql(u8, key, "skip_target")) { + const query, const backend = parseTargetQueryAndBackend( + val, + try std.fmt.allocPrint(arena, "line {d}: ", .{line_n}), + ); + try skip_targets.append(arena, .{ .query = query, - .resolved = resolved, .backend = backend, }); } else if (std.mem.eql(u8, key, "module")) { @@ -872,10 +874,6 @@ const Case = struct { } } - if (targets.items.len == 0) { - fatal("missing target", .{}); - } - if (changes.items.len > 0) { const last_update = &updates.items[updates.items.len - 1]; last_update.changes = changes.items; // arena so no need for toOwnedSlice @@ -885,7 +883,7 @@ const Case = struct { return .{ .updates = updates.items, .root_source_file = root_source_file orelse fatal("missing root source file", .{}), - .targets = targets.items, // arena so no need for toOwnedSlice + .skip_targets = skip_targets.items, // arena so no need for toOwnedSlice .modules = modules.items, }; } @@ -970,3 +968,32 @@ fn rand64(io: Io) u64 { io.random(@ptrCast(&x)); return x; } + +/// Calls `std.process.fatal` on error. The error messages are prefixed with `err_prefix`. +fn parseTargetQueryAndBackend(input_str: []const u8, err_prefix: []const u8) struct { std.Target.Query, Backend } { + const fatal = std.process.fatal; + + const split_idx = std.mem.lastIndexOfScalar(u8, input_str, '-') orelse + fatal("{s}target does not include backend", .{err_prefix}); + + const query = input_str[0..split_idx]; + + const backend_str = input_str[split_idx + 1 ..]; + const backend: Backend = std.meta.stringToEnum(Backend, backend_str) orelse + fatal("{s}invalid backend '{s}'", .{ err_prefix, backend_str }); + + const parsed_query = std.Build.parseTargetQuery(.{ + .arch_os_abi = query, + .object_format = switch (backend) { + .sema, .selfhosted, .llvm => null, + .cbe => "c", + }, + }) catch fatal("{s}invalid target query '{s}'", .{ err_prefix, query }); + + return .{ parsed_query, backend }; +} + +fn badUsage(comptime fmt: []const u8, args: anytype) noreturn { + std.log.err(fmt ++ "\n{s}", args ++ .{usage}); + std.process.exit(1); +} -- 2.54.0