authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-04-07 16:08:23-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2024-04-07 16:08:23-07:00
log1b27146792de2f1e437ede19a38e9fde8842fd05
tree6ab81a564f4a06e7a7e7a7b39a0400c48296fd0a
parent09f1bbe11b17bd26641c7e36da34b1370ab025b2
parente5bf1a5d50612c51d131e8843eeaccd672c79af4
signaturebadge-check Signed by PGP key B5690EEEBB952194

Merge pull request #18590 from castholm/move-standalone-test-cases

std.Build: Remove `anonymousDependency`

37 files changed, 1060 insertions(+), 1010 deletions(-)

build.zig+1-2
...@@ -521,11 +521,10 @@ pub fn build(b: *std.Build) !void {...@@ -521,11 +521,10 @@ pub fn build(b: *std.Build) !void {
521 optimization_modes,521 optimization_modes,
522 enable_macos_sdk,522 enable_macos_sdk,
523 enable_ios_sdk,523 enable_ios_sdk,
524 false,
525 enable_symlinks_windows,524 enable_symlinks_windows,
526 ));525 ));
527 test_step.dependOn(tests.addCAbiTests(b, skip_non_native, skip_release));526 test_step.dependOn(tests.addCAbiTests(b, skip_non_native, skip_release));
528 test_step.dependOn(tests.addLinkTests(b, enable_macos_sdk, enable_ios_sdk, false, enable_symlinks_windows));527 test_step.dependOn(tests.addLinkTests(b, enable_macos_sdk, enable_ios_sdk, enable_symlinks_windows));
529 test_step.dependOn(tests.addStackTraceTests(b, test_filters, optimization_modes));528 test_step.dependOn(tests.addStackTraceTests(b, test_filters, optimization_modes));
530 test_step.dependOn(tests.addCliTests(b));529 test_step.dependOn(tests.addCliTests(b));
531 test_step.dependOn(tests.addAssembleAndLinkTests(b, test_filters, optimization_modes));530 test_step.dependOn(tests.addAssembleAndLinkTests(b, test_filters, optimization_modes));
build.zig.zon created+15
...@@ -0,0 +1,15 @@
1// The Zig compiler is not intended to be consumed as a package.
2// The sole purpose of this manifest file is to test the compiler.
3.{
4 .name = "zig",
5 .version = "0.0.0",
6 .dependencies = .{
7 .standalone_test_cases = .{
8 .path = "test/standalone",
9 },
10 .link_test_cases = .{
11 .path = "test/link",
12 },
13 },
14 .paths = .{""},
15}
lib/std/Build.zig+1-20
...@@ -1967,25 +1967,6 @@ pub fn dependencyFromBuildZig(...@@ -1967,25 +1967,6 @@ pub fn dependencyFromBuildZig(
1967 debug.panic("'{}' is not a build.zig struct of a dependecy in '{s}'", .{ build_zig, full_path });1967 debug.panic("'{}' is not a build.zig struct of a dependecy in '{s}'", .{ build_zig, full_path });
1968}1968}
19691969
1970pub fn anonymousDependency(
1971 b: *Build,
1972 /// The path to the directory containing the dependency's build.zig file,
1973 /// relative to the current package's build.zig.
1974 relative_build_root: []const u8,
1975 /// A direct `@import` of the build.zig of the dependency.
1976 comptime build_zig: type,
1977 args: anytype,
1978) *Dependency {
1979 const arena = b.allocator;
1980 const build_root = b.build_root.join(arena, &.{relative_build_root}) catch @panic("OOM");
1981 const name = arena.dupe(u8, relative_build_root) catch @panic("OOM");
1982 for (name) |*byte| switch (byte.*) {
1983 '/', '\\' => byte.* = '.',
1984 else => continue,
1985 };
1986 return dependencyInner(b, name, build_root, build_zig, "anonymous", &.{}, args);
1987}
1988
1989fn userValuesAreSame(lhs: UserValue, rhs: UserValue) bool {1970fn userValuesAreSame(lhs: UserValue, rhs: UserValue) bool {
1990 switch (lhs) {1971 switch (lhs) {
1991 .flag => {},1972 .flag => {},
...@@ -2033,7 +2014,7 @@ fn userValuesAreSame(lhs: UserValue, rhs: UserValue) bool {...@@ -2033,7 +2014,7 @@ fn userValuesAreSame(lhs: UserValue, rhs: UserValue) bool {
2033 return true;2014 return true;
2034}2015}
20352016
2036pub fn dependencyInner(2017fn dependencyInner(
2037 b: *Build,2018 b: *Build,
2038 name: []const u8,2019 name: []const u8,
2039 build_root_string: []const u8,2020 build_root_string: []const u8,
test/link.zig deleted-94
...@@ -1,94 +0,0 @@
1pub const Case = struct {
2 build_root: []const u8,
3 import: type,
4};
5
6pub const cases = [_]Case{
7 .{
8 .build_root = "test/link",
9 .import = @import("link/link.zig"),
10 },
11
12 .{
13 .build_root = "test/link/bss",
14 .import = @import("link/bss/build.zig"),
15 },
16 .{
17 .build_root = "test/link/common_symbols",
18 .import = @import("link/common_symbols/build.zig"),
19 },
20 .{
21 .build_root = "test/link/common_symbols_alignment",
22 .import = @import("link/common_symbols_alignment/build.zig"),
23 },
24 .{
25 .build_root = "test/link/interdependent_static_c_libs",
26 .import = @import("link/interdependent_static_c_libs/build.zig"),
27 },
28 .{
29 .build_root = "test/link/static_libs_from_object_files",
30 .import = @import("link/static_libs_from_object_files/build.zig"),
31 },
32 .{
33 .build_root = "test/link/glibc_compat",
34 .import = @import("link/glibc_compat/build.zig"),
35 },
36
37 // WASM Cases
38 .{
39 .build_root = "test/link/wasm/archive",
40 .import = @import("link/wasm/archive/build.zig"),
41 },
42 .{
43 .build_root = "test/link/wasm/basic-features",
44 .import = @import("link/wasm/basic-features/build.zig"),
45 },
46 .{
47 .build_root = "test/link/wasm/bss",
48 .import = @import("link/wasm/bss/build.zig"),
49 },
50 .{
51 .build_root = "test/link/wasm/export",
52 .import = @import("link/wasm/export/build.zig"),
53 },
54 .{
55 .build_root = "test/link/wasm/export-data",
56 .import = @import("link/wasm/export-data/build.zig"),
57 },
58 .{
59 .build_root = "test/link/wasm/extern",
60 .import = @import("link/wasm/extern/build.zig"),
61 },
62 .{
63 .build_root = "test/link/wasm/extern-mangle",
64 .import = @import("link/wasm/extern-mangle/build.zig"),
65 },
66 .{
67 .build_root = "test/link/wasm/function-table",
68 .import = @import("link/wasm/function-table/build.zig"),
69 },
70 .{
71 .build_root = "test/link/wasm/infer-features",
72 .import = @import("link/wasm/infer-features/build.zig"),
73 },
74 .{
75 .build_root = "test/link/wasm/producers",
76 .import = @import("link/wasm/producers/build.zig"),
77 },
78 .{
79 .build_root = "test/link/wasm/segments",
80 .import = @import("link/wasm/segments/build.zig"),
81 },
82 .{
83 .build_root = "test/link/wasm/shared-memory",
84 .import = @import("link/wasm/shared-memory/build.zig"),
85 },
86 .{
87 .build_root = "test/link/wasm/stack_pointer",
88 .import = @import("link/wasm/stack_pointer/build.zig"),
89 },
90 .{
91 .build_root = "test/link/wasm/type",
92 .import = @import("link/wasm/type/build.zig"),
93 },
94};
test/link/build.zig created+54
...@@ -0,0 +1,54 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const link = @import("link.zig");
4
5pub fn build(b: *std.Build) void {
6 const step = b.step("test", "Run link test cases");
7 b.default_step = step;
8
9 const enable_ios_sdk = b.option(bool, "enable_ios_sdk", "Run tests requiring presence of iOS SDK and frameworks") orelse false;
10 const enable_macos_sdk = b.option(bool, "enable_macos_sdk", "Run tests requiring presence of macOS SDK and frameworks") orelse enable_ios_sdk;
11 const enable_symlinks_windows = b.option(bool, "enable_symlinks_windows", "Run tests requiring presence of symlinks on Windows") orelse false;
12 const omit_symlinks = builtin.os.tag == .windows and !enable_symlinks_windows;
13
14 const build_opts: link.BuildOptions = .{
15 .has_ios_sdk = enable_ios_sdk,
16 .has_macos_sdk = enable_macos_sdk,
17 .has_symlinks_windows = omit_symlinks,
18 };
19 step.dependOn(@import("elf.zig").testAll(b, build_opts));
20 step.dependOn(@import("macho.zig").testAll(b, build_opts));
21
22 add_dep_steps: for (b.available_deps) |available_dep| {
23 const dep_name, const dep_hash = available_dep;
24
25 const all_pkgs = @import("root").dependencies.packages;
26 inline for (@typeInfo(all_pkgs).Struct.decls) |decl| {
27 const pkg_hash = decl.name;
28 if (std.mem.eql(u8, dep_hash, pkg_hash)) {
29 const pkg = @field(all_pkgs, pkg_hash);
30 if (!@hasDecl(pkg, "build_zig")) {
31 std.debug.panic("link test case '{s}' is missing a 'build.zig' file", .{dep_name});
32 }
33 const requires_ios_sdk = @hasDecl(pkg.build_zig, "requires_ios_sdk") and
34 pkg.build_zig.requires_ios_sdk;
35 const requires_macos_sdk = @hasDecl(pkg.build_zig, "requires_macos_sdk") and
36 pkg.build_zig.requires_macos_sdk;
37 const requires_symlinks = @hasDecl(pkg.build_zig, "requires_symlinks") and
38 pkg.build_zig.requires_symlinks;
39 if ((requires_symlinks and omit_symlinks) or
40 (requires_macos_sdk and !enable_macos_sdk) or
41 (requires_ios_sdk and !enable_ios_sdk))
42 {
43 continue :add_dep_steps;
44 }
45 break;
46 }
47 } else unreachable;
48
49 const dep = b.dependency(dep_name, .{});
50 const dep_step = dep.builder.default_step;
51 dep_step.name = b.fmt("link_test_cases.{s}", .{dep_name});
52 step.dependOn(dep_step);
53 }
54}
test/link/build.zig.zon created+69
...@@ -0,0 +1,69 @@
1.{
2 .name = "link_test_cases",
3 .version = "0.0.0",
4 .dependencies = .{
5 .bss = .{
6 .path = "bss",
7 },
8 .common_symbols_alignment = .{
9 .path = "common_symbols_alignment",
10 },
11 .interdependent_static_c_libs = .{
12 .path = "interdependent_static_c_libs",
13 },
14 .static_libs_from_object_files = .{
15 .path = "static_libs_from_object_files",
16 },
17 .glibc_compat = .{
18 .path = "glibc_compat",
19 },
20 // WASM Cases
21 .wasm_archive = .{
22 .path = "wasm/archive",
23 },
24 .wasm_basic_features = .{
25 .path = "wasm/basic-features",
26 },
27 .wasm_bss = .{
28 .path = "wasm/bss",
29 },
30 .wasm_export = .{
31 .path = "wasm/export",
32 },
33 .wasm_export_data = .{
34 .path = "wasm/export-data",
35 },
36 .wasm_extern = .{
37 .path = "wasm/extern",
38 },
39 .wasm_extern_mangle = .{
40 .path = "wasm/extern-mangle",
41 },
42 .wasm_function_table = .{
43 .path = "wasm/function-table",
44 },
45 .wasm_infer_features = .{
46 .path = "wasm/infer-features",
47 },
48 .wasm_producers = .{
49 .path = "wasm/producers",
50 },
51 .wasm_segments = .{
52 .path = "wasm/segments",
53 },
54 .wasm_shared_memory = .{
55 .path = "wasm/shared-memory",
56 },
57 .wasm_stack_pointer = .{
58 .path = "wasm/stack_pointer",
59 },
60 .wasm_type = .{
61 .path = "wasm/type",
62 },
63 },
64 .paths = .{
65 "build.zig",
66 "build.zig.zon",
67 "link.zig",
68 },
69}
test/standalone.zig deleted-275
...@@ -1,275 +0,0 @@
1pub const SimpleCase = struct {
2 src_path: []const u8,
3 link_libc: bool = false,
4 all_modes: bool = false,
5 target: std.Target.Query = .{},
6 is_test: bool = false,
7 is_exe: bool = true,
8 /// Run only on this OS.
9 os_filter: ?std.Target.Os.Tag = null,
10};
11
12pub const BuildCase = struct {
13 build_root: []const u8,
14 import: type,
15};
16
17pub const simple_cases = [_]SimpleCase{
18 .{
19 .src_path = "test/standalone/hello_world/hello.zig",
20 .all_modes = true,
21 },
22 .{
23 .src_path = "test/standalone/hello_world/hello_libc.zig",
24 .link_libc = true,
25 .all_modes = true,
26 },
27 .{
28 .src_path = "test/standalone/cat/main.zig",
29 },
30 // https://github.com/ziglang/zig/issues/6025
31 //.{
32 // .src_path = "test/standalone/issue_9693/main.zig",
33 //},
34 .{
35 .src_path = "test/standalone/brace_expansion.zig",
36 .is_test = true,
37 },
38 .{
39 .src_path = "test/standalone/issue_7030.zig",
40 .target = .{
41 .cpu_arch = .wasm32,
42 .os_tag = .freestanding,
43 },
44 },
45
46 .{ .src_path = "test/standalone/issue_12471/main.zig" },
47 .{ .src_path = "test/standalone/guess_number/main.zig" },
48 .{ .src_path = "test/standalone/main_return_error/error_u8.zig" },
49 .{ .src_path = "test/standalone/main_return_error/error_u8_non_zero.zig" },
50 .{ .src_path = "test/standalone/noreturn_call/inline.zig" },
51 .{ .src_path = "test/standalone/noreturn_call/as_arg.zig" },
52 .{ .src_path = "test/standalone/std_enums_big_enums.zig" },
53
54 .{
55 .src_path = "test/standalone/issue_9402/main.zig",
56 .os_filter = .windows,
57 .link_libc = true,
58 },
59
60 // Ensure the development tools are buildable. Alphabetically sorted.
61 // No need to build `tools/spirv/grammar.zig`.
62 .{ .src_path = "tools/gen_outline_atomics.zig" },
63 .{ .src_path = "tools/gen_spirv_spec.zig" },
64 .{ .src_path = "tools/gen_stubs.zig" },
65 .{ .src_path = "tools/generate_linux_syscalls.zig" },
66 .{ .src_path = "tools/process_headers.zig" },
67 .{ .src_path = "tools/update-linux-headers.zig" },
68 .{ .src_path = "tools/update_clang_options.zig" },
69 .{ .src_path = "tools/update_cpu_features.zig" },
70 .{ .src_path = "tools/update_glibc.zig" },
71 .{ .src_path = "tools/update_spirv_features.zig" },
72};
73
74pub const build_cases = [_]BuildCase{
75 .{
76 .build_root = "test/standalone/test_runner_path",
77 .import = @import("standalone/test_runner_path/build.zig"),
78 },
79 .{
80 .build_root = "test/standalone/test_runner_module_imports",
81 .import = @import("standalone/test_runner_module_imports/build.zig"),
82 },
83 // https://github.com/ziglang/zig/issues/17483
84 //.{
85 // .build_root = "test/standalone/issue_13970",
86 // .import = @import("standalone/issue_13970/build.zig"),
87 //},
88 .{
89 .build_root = "test/standalone/shared_library",
90 .import = @import("standalone/shared_library/build.zig"),
91 },
92 .{
93 .build_root = "test/standalone/mix_o_files",
94 .import = @import("standalone/mix_o_files/build.zig"),
95 },
96 .{
97 .build_root = "test/standalone/mix_c_files",
98 .import = @import("standalone/mix_c_files/build.zig"),
99 },
100 .{
101 .build_root = "test/standalone/global_linkage",
102 .import = @import("standalone/global_linkage/build.zig"),
103 },
104 .{
105 .build_root = "test/standalone/static_c_lib",
106 .import = @import("standalone/static_c_lib/build.zig"),
107 },
108 .{
109 .build_root = "test/standalone/issue_339",
110 .import = @import("standalone/issue_339/build.zig"),
111 },
112 .{
113 .build_root = "test/standalone/issue_8550",
114 .import = @import("standalone/issue_8550/build.zig"),
115 },
116 .{
117 .build_root = "test/standalone/issue_794",
118 .import = @import("standalone/issue_794/build.zig"),
119 },
120 .{
121 .build_root = "test/standalone/issue_5825",
122 .import = @import("standalone/issue_5825/build.zig"),
123 },
124 .{
125 .build_root = "test/standalone/pkg_import",
126 .import = @import("standalone/pkg_import/build.zig"),
127 },
128 .{
129 .build_root = "test/standalone/use_alias",
130 .import = @import("standalone/use_alias/build.zig"),
131 },
132 .{
133 .build_root = "test/standalone/install_raw_hex",
134 .import = @import("standalone/install_raw_hex/build.zig"),
135 },
136 // https://github.com/ziglang/zig/issues/17484
137 //.{
138 // .build_root = "test/standalone/emit_asm_and_bin",
139 // .import = @import("standalone/emit_asm_and_bin/build.zig"),
140 //},
141 // https://github.com/ziglang/zig/issues/17484
142 //.{
143 // .build_root = "test/standalone/issue_12588",
144 // .import = @import("standalone/issue_12588/build.zig"),
145 //},
146 .{
147 .build_root = "test/standalone/child_process",
148 .import = @import("standalone/child_process/build.zig"),
149 },
150 .{
151 .build_root = "test/standalone/embed_generated_file",
152 .import = @import("standalone/embed_generated_file/build.zig"),
153 },
154 .{
155 .build_root = "test/standalone/extern",
156 .import = @import("standalone/extern/build.zig"),
157 },
158 .{
159 .build_root = "test/standalone/dep_diamond",
160 .import = @import("standalone/dep_diamond/build.zig"),
161 },
162 .{
163 .build_root = "test/standalone/dep_triangle",
164 .import = @import("standalone/dep_triangle/build.zig"),
165 },
166 .{
167 .build_root = "test/standalone/dep_recursive",
168 .import = @import("standalone/dep_recursive/build.zig"),
169 },
170 .{
171 .build_root = "test/standalone/dep_mutually_recursive",
172 .import = @import("standalone/dep_mutually_recursive/build.zig"),
173 },
174 .{
175 .build_root = "test/standalone/dep_shared_builtin",
176 .import = @import("standalone/dep_shared_builtin/build.zig"),
177 },
178 .{
179 .build_root = "test/standalone/dirname",
180 .import = @import("standalone/dirname/build.zig"),
181 },
182 .{
183 .build_root = "test/standalone/empty_env",
184 .import = @import("standalone/empty_env/build.zig"),
185 },
186 .{
187 .build_root = "test/standalone/issue_11595",
188 .import = @import("standalone/issue_11595/build.zig"),
189 },
190 .{
191 .build_root = "test/standalone/load_dynamic_library",
192 .import = @import("standalone/load_dynamic_library/build.zig"),
193 },
194 .{
195 .build_root = "test/standalone/windows_resources",
196 .import = @import("standalone/windows_resources/build.zig"),
197 },
198 .{
199 .build_root = "test/standalone/windows_entry_points",
200 .import = @import("standalone/windows_entry_points/build.zig"),
201 },
202 .{
203 .build_root = "test/standalone/windows_spawn",
204 .import = @import("standalone/windows_spawn/build.zig"),
205 },
206 .{
207 .build_root = "test/standalone/self_exe_symlink",
208 .import = @import("standalone/self_exe_symlink/build.zig"),
209 },
210 .{
211 .build_root = "test/standalone/c_compiler",
212 .import = @import("standalone/c_compiler/build.zig"),
213 },
214 .{
215 .build_root = "test/standalone/pie",
216 .import = @import("standalone/pie/build.zig"),
217 },
218 .{
219 .build_root = "test/standalone/issue_12706",
220 .import = @import("standalone/issue_12706/build.zig"),
221 },
222 // TODO This test is disabled for doing naughty things in the build script.
223 // The logic needs to get moved to a child process instead of build.zig.
224 //.{
225 // .build_root = "test/standalone/sigpipe",
226 // .import = @import("standalone/sigpipe/build.zig"),
227 //},
228 // TODO restore this test
229 //.{
230 // .build_root = "test/standalone/options",
231 // .import = @import("standalone/options/build.zig"),
232 //},
233 .{
234 .build_root = "test/standalone/strip_empty_loop",
235 .import = @import("standalone/strip_empty_loop/build.zig"),
236 },
237 .{
238 .build_root = "test/standalone/strip_struct_init",
239 .import = @import("standalone/strip_struct_init/build.zig"),
240 },
241 .{
242 .build_root = "test/standalone/cmakedefine",
243 .import = @import("standalone/cmakedefine/build.zig"),
244 },
245 .{
246 .build_root = "test/standalone/zerolength_check",
247 .import = @import("standalone/zerolength_check/build.zig"),
248 },
249 .{
250 .build_root = "test/standalone/stack_iterator",
251 .import = @import("standalone/stack_iterator/build.zig"),
252 },
253 .{
254 .build_root = "test/standalone/coff_dwarf",
255 .import = @import("standalone/coff_dwarf/build.zig"),
256 },
257 .{
258 .build_root = "test/standalone/compiler_rt_panic",
259 .import = @import("standalone/compiler_rt_panic/build.zig"),
260 },
261 .{
262 .build_root = "test/standalone/ios",
263 .import = @import("standalone/ios/build.zig"),
264 },
265 .{
266 .build_root = "test/standalone/depend_on_main_mod",
267 .import = @import("standalone/depend_on_main_mod/build.zig"),
268 },
269 .{
270 .build_root = "test/standalone/install_headers",
271 .import = @import("standalone/install_headers/build.zig"),
272 },
273};
274
275const std = @import("std");
test/standalone/brace_expansion.zig deleted-292
...@@ -1,292 +0,0 @@
1const std = @import("std");
2const io = std.io;
3const mem = std.mem;
4const debug = std.debug;
5const assert = debug.assert;
6const testing = std.testing;
7const ArrayList = std.ArrayList;
8const maxInt = std.math.maxInt;
9
10const Token = union(enum) {
11 Word: []const u8,
12 OpenBrace,
13 CloseBrace,
14 Comma,
15 Eof,
16};
17
18var gpa = std.heap.GeneralPurposeAllocator(.{}){};
19var global_allocator = gpa.allocator();
20
21fn tokenize(input: []const u8) !ArrayList(Token) {
22 const State = enum {
23 Start,
24 Word,
25 };
26
27 var token_list = ArrayList(Token).init(global_allocator);
28 errdefer token_list.deinit();
29 var tok_begin: usize = undefined;
30 var state = State.Start;
31
32 for (input, 0..) |b, i| {
33 switch (state) {
34 .Start => switch (b) {
35 'a'...'z', 'A'...'Z' => {
36 state = State.Word;
37 tok_begin = i;
38 },
39 '{' => try token_list.append(Token.OpenBrace),
40 '}' => try token_list.append(Token.CloseBrace),
41 ',' => try token_list.append(Token.Comma),
42 else => return error.InvalidInput,
43 },
44 .Word => switch (b) {
45 'a'...'z', 'A'...'Z' => {},
46 '{', '}', ',' => {
47 try token_list.append(Token{ .Word = input[tok_begin..i] });
48 switch (b) {
49 '{' => try token_list.append(Token.OpenBrace),
50 '}' => try token_list.append(Token.CloseBrace),
51 ',' => try token_list.append(Token.Comma),
52 else => unreachable,
53 }
54 state = State.Start;
55 },
56 else => return error.InvalidInput,
57 },
58 }
59 }
60 switch (state) {
61 State.Start => {},
62 State.Word => try token_list.append(Token{ .Word = input[tok_begin..] }),
63 }
64 try token_list.append(Token.Eof);
65 return token_list;
66}
67
68const Node = union(enum) {
69 Scalar: []const u8,
70 List: ArrayList(Node),
71 Combine: []Node,
72
73 fn deinit(self: Node) void {
74 switch (self) {
75 .Scalar => {},
76 .Combine => |pair| {
77 pair[0].deinit();
78 pair[1].deinit();
79 global_allocator.free(pair);
80 },
81 .List => |list| {
82 for (list.items) |item| {
83 item.deinit();
84 }
85 list.deinit();
86 },
87 }
88 }
89};
90
91const ParseError = error{
92 InvalidInput,
93 OutOfMemory,
94};
95
96fn parse(tokens: *const ArrayList(Token), token_index: *usize) ParseError!Node {
97 const first_token = tokens.items[token_index.*];
98 token_index.* += 1;
99
100 const result_node = switch (first_token) {
101 .Word => |word| Node{ .Scalar = word },
102 .OpenBrace => blk: {
103 var list = ArrayList(Node).init(global_allocator);
104 errdefer {
105 for (list.items) |node| node.deinit();
106 list.deinit();
107 }
108 while (true) {
109 try list.append(try parse(tokens, token_index));
110
111 const token = tokens.items[token_index.*];
112 token_index.* += 1;
113
114 switch (token) {
115 .CloseBrace => break,
116 .Comma => continue,
117 else => return error.InvalidInput,
118 }
119 }
120 break :blk Node{ .List = list };
121 },
122 else => return error.InvalidInput,
123 };
124
125 switch (tokens.items[token_index.*]) {
126 .Word, .OpenBrace => {
127 const pair = try global_allocator.alloc(Node, 2);
128 errdefer global_allocator.free(pair);
129 pair[0] = result_node;
130 pair[1] = try parse(tokens, token_index);
131 return Node{ .Combine = pair };
132 },
133 else => return result_node,
134 }
135}
136
137fn expandString(input: []const u8, output: *ArrayList(u8)) !void {
138 const tokens = try tokenize(input);
139 defer tokens.deinit();
140 if (tokens.items.len == 1) {
141 return output.resize(0);
142 }
143
144 var token_index: usize = 0;
145 const root = try parse(&tokens, &token_index);
146 defer root.deinit();
147 const last_token = tokens.items[token_index];
148 switch (last_token) {
149 Token.Eof => {},
150 else => return error.InvalidInput,
151 }
152
153 var result_list = ArrayList(ArrayList(u8)).init(global_allocator);
154 defer {
155 for (result_list.items) |*buf| buf.deinit();
156 result_list.deinit();
157 }
158
159 try expandNode(root, &result_list);
160
161 try output.resize(0);
162 for (result_list.items, 0..) |buf, i| {
163 if (i != 0) {
164 try output.append(' ');
165 }
166 try output.appendSlice(buf.items);
167 }
168}
169
170const ExpandNodeError = error{OutOfMemory};
171
172fn expandNode(node: Node, output: *ArrayList(ArrayList(u8))) ExpandNodeError!void {
173 assert(output.items.len == 0);
174 switch (node) {
175 .Scalar => |scalar| {
176 var list = ArrayList(u8).init(global_allocator);
177 errdefer list.deinit();
178 try list.appendSlice(scalar);
179 try output.append(list);
180 },
181 .Combine => |pair| {
182 const a_node = pair[0];
183 const b_node = pair[1];
184
185 var child_list_a = ArrayList(ArrayList(u8)).init(global_allocator);
186 defer {
187 for (child_list_a.items) |*buf| buf.deinit();
188 child_list_a.deinit();
189 }
190 try expandNode(a_node, &child_list_a);
191
192 var child_list_b = ArrayList(ArrayList(u8)).init(global_allocator);
193 defer {
194 for (child_list_b.items) |*buf| buf.deinit();
195 child_list_b.deinit();
196 }
197 try expandNode(b_node, &child_list_b);
198
199 for (child_list_a.items) |buf_a| {
200 for (child_list_b.items) |buf_b| {
201 var combined_buf = ArrayList(u8).init(global_allocator);
202 errdefer combined_buf.deinit();
203
204 try combined_buf.appendSlice(buf_a.items);
205 try combined_buf.appendSlice(buf_b.items);
206 try output.append(combined_buf);
207 }
208 }
209 },
210 .List => |list| {
211 for (list.items) |child_node| {
212 var child_list = ArrayList(ArrayList(u8)).init(global_allocator);
213 errdefer for (child_list.items) |*buf| buf.deinit();
214 defer child_list.deinit();
215
216 try expandNode(child_node, &child_list);
217
218 for (child_list.items) |buf| {
219 try output.append(buf);
220 }
221 }
222 },
223 }
224}
225
226pub fn main() !void {
227 defer _ = gpa.deinit();
228 const stdin_file = io.getStdIn();
229 const stdout_file = io.getStdOut();
230
231 const stdin = try stdin_file.reader().readAllAlloc(global_allocator, std.math.maxInt(usize));
232 defer global_allocator.free(stdin);
233
234 var result_buf = ArrayList(u8).init(global_allocator);
235 defer result_buf.deinit();
236
237 try expandString(stdin, &result_buf);
238 try stdout_file.writeAll(result_buf.items);
239}
240
241test "invalid inputs" {
242 global_allocator = std.testing.allocator;
243
244 try expectError("}ABC", error.InvalidInput);
245 try expectError("{ABC", error.InvalidInput);
246 try expectError("}{", error.InvalidInput);
247 try expectError("{}", error.InvalidInput);
248 try expectError("A,B,C", error.InvalidInput);
249 try expectError("{A{B,C}", error.InvalidInput);
250 try expectError("{A,}", error.InvalidInput);
251
252 try expectError("\n", error.InvalidInput);
253}
254
255fn expectError(test_input: []const u8, expected_err: anyerror) !void {
256 var output_buf = ArrayList(u8).init(global_allocator);
257 defer output_buf.deinit();
258
259 try testing.expectError(expected_err, expandString(test_input, &output_buf));
260}
261
262test "valid inputs" {
263 global_allocator = std.testing.allocator;
264
265 try expectExpansion("{x,y,z}", "x y z");
266 try expectExpansion("{A,B}{x,y}", "Ax Ay Bx By");
267 try expectExpansion("{A,B{x,y}}", "A Bx By");
268
269 try expectExpansion("{ABC}", "ABC");
270 try expectExpansion("{A,B,C}", "A B C");
271 try expectExpansion("ABC", "ABC");
272
273 try expectExpansion("", "");
274 try expectExpansion("{A,B}{C,{x,y}}{g,h}", "ACg ACh Axg Axh Ayg Ayh BCg BCh Bxg Bxh Byg Byh");
275 try expectExpansion("{A,B}{C,C{x,y}}{g,h}", "ACg ACh ACxg ACxh ACyg ACyh BCg BCh BCxg BCxh BCyg BCyh");
276 try expectExpansion("{A,B}a", "Aa Ba");
277 try expectExpansion("{C,{x,y}}", "C x y");
278 try expectExpansion("z{C,{x,y}}", "zC zx zy");
279 try expectExpansion("a{b,c{d,e{f,g}}}", "ab acd acef aceg");
280 try expectExpansion("a{x,y}b", "axb ayb");
281 try expectExpansion("z{{a,b}}", "za zb");
282 try expectExpansion("a{b}", "ab");
283}
284
285fn expectExpansion(test_input: []const u8, expected_result: []const u8) !void {
286 var result = ArrayList(u8).init(global_allocator);
287 defer result.deinit();
288
289 expandString(test_input, &result) catch unreachable;
290
291 try testing.expectEqualSlices(u8, expected_result, result.items);
292}
test/standalone/build.zig created+90
...@@ -0,0 +1,90 @@
1const std = @import("std");
2const builtin = @import("builtin");
3
4pub fn build(b: *std.Build) void {
5 const step = b.step("test", "Run standalone test cases");
6 b.default_step = step;
7
8 const enable_ios_sdk = b.option(bool, "enable_ios_sdk", "Run tests requiring presence of iOS SDK and frameworks") orelse false;
9 const enable_macos_sdk = b.option(bool, "enable_macos_sdk", "Run tests requiring presence of macOS SDK and frameworks") orelse enable_ios_sdk;
10 const enable_symlinks_windows = b.option(bool, "enable_symlinks_windows", "Run tests requiring presence of symlinks on Windows") orelse false;
11 const omit_symlinks = builtin.os.tag == .windows and !enable_symlinks_windows;
12
13 const simple_skip_debug = b.option(bool, "simple_skip_debug", "Simple tests skip debug builds") orelse false;
14 const simple_skip_release_safe = b.option(bool, "simple_skip_release_safe", "Simple tests skip release-safe builds") orelse false;
15 const simple_skip_release_fast = b.option(bool, "simple_skip_release_fast", "Simple tests skip release-fast builds") orelse false;
16 const simple_skip_release_small = b.option(bool, "simple_skip_release_small", "Simple tests skip release-small builds") orelse false;
17
18 const simple_dep = b.dependency("simple", .{
19 .skip_debug = simple_skip_debug,
20 .skip_release_safe = simple_skip_release_safe,
21 .skip_release_fast = simple_skip_release_fast,
22 .skip_release_small = simple_skip_release_small,
23 });
24 const simple_dep_step = simple_dep.builder.default_step;
25 simple_dep_step.name = "standalone_test_cases.simple";
26 step.dependOn(simple_dep_step);
27
28 // Ensure the development tools are buildable.
29 const tools_tests_step = b.step("standalone_test_cases.tools", "Test tools");
30 step.dependOn(tools_tests_step);
31 const tools_target = b.resolveTargetQuery(.{});
32 for ([_][]const u8{
33 // Alphabetically sorted. No need to build `tools/spirv/grammar.zig`.
34 "../../tools/gen_outline_atomics.zig",
35 "../../tools/gen_spirv_spec.zig",
36 "../../tools/gen_stubs.zig",
37 "../../tools/generate_linux_syscalls.zig",
38 "../../tools/process_headers.zig",
39 "../../tools/update-linux-headers.zig",
40 "../../tools/update_clang_options.zig",
41 "../../tools/update_cpu_features.zig",
42 "../../tools/update_glibc.zig",
43 "../../tools/update_spirv_features.zig",
44 }) |tool_src_path| {
45 const tool = b.addTest(.{
46 .name = std.fs.path.stem(tool_src_path),
47 .root_source_file = .{ .path = tool_src_path },
48 .optimize = .Debug,
49 .target = tools_target,
50 });
51 const run = b.addRunArtifact(tool);
52 tools_tests_step.dependOn(&run.step);
53 }
54
55 add_dep_steps: for (b.available_deps) |available_dep| {
56 const dep_name, const dep_hash = available_dep;
57
58 // The 'simple' dependency was already handled manually above.
59 if (std.mem.eql(u8, dep_name, "simple")) continue;
60
61 const all_pkgs = @import("root").dependencies.packages;
62 inline for (@typeInfo(all_pkgs).Struct.decls) |decl| {
63 const pkg_hash = decl.name;
64 if (std.mem.eql(u8, dep_hash, pkg_hash)) {
65 const pkg = @field(all_pkgs, pkg_hash);
66 if (!@hasDecl(pkg, "build_zig")) {
67 std.debug.panic("standalone test case '{s}' is missing a 'build.zig' file", .{dep_name});
68 }
69 const requires_ios_sdk = @hasDecl(pkg.build_zig, "requires_ios_sdk") and
70 pkg.build_zig.requires_ios_sdk;
71 const requires_macos_sdk = @hasDecl(pkg.build_zig, "requires_macos_sdk") and
72 pkg.build_zig.requires_macos_sdk;
73 const requires_symlinks = @hasDecl(pkg.build_zig, "requires_symlinks") and
74 pkg.build_zig.requires_symlinks;
75 if ((requires_symlinks and omit_symlinks) or
76 (requires_macos_sdk and !enable_macos_sdk) or
77 (requires_ios_sdk and !enable_ios_sdk))
78 {
79 continue :add_dep_steps;
80 }
81 break;
82 }
83 } else unreachable;
84
85 const dep = b.dependency(dep_name, .{});
86 const dep_step = dep.builder.default_step;
87 dep_step.name = b.fmt("standalone_test_cases.{s}", .{dep_name});
88 step.dependOn(dep_step);
89 }
90}
test/standalone/build.zig.zon created+163
...@@ -0,0 +1,163 @@
1.{
2 .name = "standalone_test_cases",
3 .version = "0.0.0",
4 .dependencies = .{
5 .simple = .{
6 .path = "simple",
7 },
8 .test_runner_path = .{
9 .path = "test_runner_path",
10 },
11 .test_runner_module_imports = .{
12 .path = "test_runner_module_imports",
13 },
14 // https://github.com/ziglang/zig/issues/17483
15 //.issue_13970 = .{
16 // .path = "issue_13970",
17 //},
18 .shared_library = .{
19 .path = "shared_library",
20 },
21 .mix_o_files = .{
22 .path = "mix_o_files",
23 },
24 .mix_c_files = .{
25 .path = "mix_c_files",
26 },
27 .global_linkage = .{
28 .path = "global_linkage",
29 },
30 .static_c_lib = .{
31 .path = "static_c_lib",
32 },
33 .issue_339 = .{
34 .path = "issue_339",
35 },
36 .issue_8550 = .{
37 .path = "issue_8550",
38 },
39 .issue_794 = .{
40 .path = "issue_794",
41 },
42 .issue_5825 = .{
43 .path = "issue_5825",
44 },
45 .pkg_import = .{
46 .path = "pkg_import",
47 },
48 .use_alias = .{
49 .path = "use_alias",
50 },
51 .install_raw_hex = .{
52 .path = "install_raw_hex",
53 },
54 // https://github.com/ziglang/zig/issues/17484
55 //.emit_asm_and_bin = .{
56 // .path = "emit_asm_and_bin",
57 //},
58 // https://github.com/ziglang/zig/issues/17484
59 //.issue_12588 = .{
60 // .path = "issue_12588",
61 //},
62 .child_process = .{
63 .path = "child_process",
64 },
65 .embed_generated_file = .{
66 .path = "embed_generated_file",
67 },
68 .@"extern" = .{
69 .path = "extern",
70 },
71 .dep_diamond = .{
72 .path = "dep_diamond",
73 },
74 .dep_triangle = .{
75 .path = "dep_triangle",
76 },
77 .dep_recursive = .{
78 .path = "dep_recursive",
79 },
80 .dep_mutually_recursive = .{
81 .path = "dep_mutually_recursive",
82 },
83 .dep_shared_builtin = .{
84 .path = "dep_shared_builtin",
85 },
86 .dirname = .{
87 .path = "dirname",
88 },
89 .empty_env = .{
90 .path = "empty_env",
91 },
92 .issue_11595 = .{
93 .path = "issue_11595",
94 },
95 .load_dynamic_library = .{
96 .path = "load_dynamic_library",
97 },
98 .windows_resources = .{
99 .path = "windows_resources",
100 },
101 .windows_entry_points = .{
102 .path = "windows_entry_points",
103 },
104 .windows_spawn = .{
105 .path = "windows_spawn",
106 },
107 .self_exe_symlink = .{
108 .path = "self_exe_symlink",
109 },
110 .c_compiler = .{
111 .path = "c_compiler",
112 },
113 .pie = .{
114 .path = "pie",
115 },
116 .issue_12706 = .{
117 .path = "issue_12706",
118 },
119 // TODO This test is disabled for doing naughty things in the build script.
120 // The logic needs to get moved to a child process instead of build.zig.
121 //.sigpipe = .{
122 // .path = "sigpipe",
123 //},
124 // TODO restore this test
125 //.options = .{
126 // .path = "options",
127 //},
128 .strip_empty_loop = .{
129 .path = "strip_empty_loop",
130 },
131 .strip_struct_init = .{
132 .path = "strip_struct_init",
133 },
134 .cmakedefine = .{
135 .path = "cmakedefine",
136 },
137 .zerolength_check = .{
138 .path = "zerolength_check",
139 },
140 .stack_iterator = .{
141 .path = "stack_iterator",
142 },
143 .coff_dwarf = .{
144 .path = "coff_dwarf",
145 },
146 .compiler_rt_panic = .{
147 .path = "compiler_rt_panic",
148 },
149 .ios = .{
150 .path = "ios",
151 },
152 .depend_on_main_mod = .{
153 .path = "depend_on_main_mod",
154 },
155 .install_headers = .{
156 .path = "install_headers",
157 },
158 },
159 .paths = .{
160 "build.zig",
161 "build.zig.zon",
162 },
163}
test/standalone/cat/main.zig deleted-46
...@@ -1,46 +0,0 @@
1const std = @import("std");
2const io = std.io;
3const process = std.process;
4const fs = std.fs;
5const mem = std.mem;
6const warn = std.log.warn;
7
8pub fn main() !void {
9 var arena_instance = std.heap.ArenaAllocator.init(std.heap.page_allocator);
10 defer arena_instance.deinit();
11 const arena = arena_instance.allocator();
12
13 const args = try process.argsAlloc(arena);
14
15 const exe = args[0];
16 var catted_anything = false;
17 const stdout_file = io.getStdOut();
18
19 const cwd = fs.cwd();
20
21 for (args[1..]) |arg| {
22 if (mem.eql(u8, arg, "-")) {
23 catted_anything = true;
24 try stdout_file.writeFileAll(io.getStdIn(), .{});
25 } else if (mem.startsWith(u8, arg, "-")) {
26 return usage(exe);
27 } else {
28 const file = cwd.openFile(arg, .{}) catch |err| {
29 warn("Unable to open file: {s}\n", .{@errorName(err)});
30 return err;
31 };
32 defer file.close();
33
34 catted_anything = true;
35 try stdout_file.writeFileAll(file, .{});
36 }
37 }
38 if (!catted_anything) {
39 try stdout_file.writeFileAll(io.getStdIn(), .{});
40 }
41}
42
43fn usage(exe: []const u8) !void {
44 warn("Usage: {s} [FILE]...\n", .{exe});
45 return error.Invalid;
46}
test/standalone/guess_number/main.zig deleted-38
...@@ -1,38 +0,0 @@
1const builtin = @import("builtin");
2const std = @import("std");
3const io = std.io;
4const fmt = std.fmt;
5
6pub fn main() !void {
7 const stdout = io.getStdOut().writer();
8 const stdin = io.getStdIn();
9
10 try stdout.print("Welcome to the Guess Number Game in Zig.\n", .{});
11
12 const answer = std.crypto.random.intRangeLessThan(u8, 0, 100) + 1;
13
14 while (true) {
15 try stdout.print("\nGuess a number between 1 and 100: ", .{});
16 var line_buf: [20]u8 = undefined;
17
18 const amt = try stdin.read(&line_buf);
19 if (amt == line_buf.len) {
20 try stdout.print("Input too long.\n", .{});
21 continue;
22 }
23 const line = std.mem.trimRight(u8, line_buf[0..amt], "\r\n");
24
25 const guess = fmt.parseUnsigned(u8, line, 10) catch {
26 try stdout.print("Invalid number.\n", .{});
27 continue;
28 };
29 if (guess > answer) {
30 try stdout.print("Guess lower.\n", .{});
31 } else if (guess < answer) {
32 try stdout.print("Guess higher.\n", .{});
33 } else {
34 try stdout.print("You win!\n", .{});
35 return;
36 }
37 }
38}
test/standalone/hello_world/hello.zig deleted-5
...@@ -1,5 +0,0 @@
1const std = @import("std");
2
3pub fn main() !void {
4 try std.io.getStdOut().writeAll("Hello, World!\n");
5}
test/standalone/hello_world/hello_libc.zig deleted-15
...@@ -1,15 +0,0 @@
1const c = @cImport({
2 // See https://github.com/ziglang/zig/issues/515
3 @cDefine("_NO_CRT_STDIO_INLINE", "1");
4 @cInclude("stdio.h");
5 @cInclude("string.h");
6});
7
8const msg = "Hello, world!\n";
9
10pub export fn main(argc: c_int, argv: **u8) c_int {
11 _ = argv;
12 _ = argc;
13 if (c.printf(msg) != @as(c_int, @intCast(c.strlen(msg)))) return -1;
14 return 0;
15}
test/standalone/issue_12471/main.zig deleted-12
...@@ -1,12 +0,0 @@
1const c = @cImport({
2 @cDefine("FOO", "FOO");
3 @cDefine("BAR", "FOO");
4
5 @cDefine("BAZ", "QUX");
6 @cDefine("QUX", "QUX");
7});
8
9pub fn main() u8 {
10 _ = c;
11 return 0;
12}
test/standalone/issue_7030.zig deleted-21
...@@ -1,21 +0,0 @@
1const std = @import("std");
2
3pub const std_options = .{
4 .logFn = log,
5};
6
7pub fn log(
8 comptime message_level: std.log.Level,
9 comptime scope: @Type(.EnumLiteral),
10 comptime format: []const u8,
11 args: anytype,
12) void {
13 _ = message_level;
14 _ = scope;
15 _ = format;
16 _ = args;
17}
18
19pub fn main() anyerror!void {
20 std.log.info("All your codebase are belong to us.", .{});
21}
test/standalone/issue_9402/main.zig deleted-14
...@@ -1,14 +0,0 @@
1const FILE = extern struct {
2 dummy_field: u8,
3};
4
5extern fn _ftelli64([*c]FILE) i64;
6extern fn _fseeki64([*c]FILE, i64, c_int) c_int;
7
8pub export fn main(argc: c_int, argv: **u8) c_int {
9 _ = argv;
10 _ = argc;
11 _ = _ftelli64(null);
12 _ = _fseeki64(null, 123, 2);
13 return 0;
14}
test/standalone/main_return_error/error_u8.zig deleted-5
...@@ -1,5 +0,0 @@
1const Err = error{Foo};
2
3pub fn main() !u8 {
4 return Err.Foo;
5}
test/standalone/main_return_error/error_u8_non_zero.zig deleted-10
...@@ -1,10 +0,0 @@
1const Err = error{Foo};
2
3fn foo() u8 {
4 return @intCast(9);
5}
6
7pub fn main() !u8 {
8 if (foo() == 7) return Err.Foo;
9 return 123;
10}
test/standalone/noreturn_call/as_arg.zig deleted-8
...@@ -1,8 +0,0 @@
1const std = @import("std");
2fn foo() noreturn {
3 std.process.exit(0);
4}
5fn bar(_: u8, _: u8) void {}
6pub fn main() void {
7 bar(foo(), @compileError("bad"));
8}
test/standalone/noreturn_call/inline.zig deleted-10
...@@ -1,10 +0,0 @@
1pub fn main() void {
2 _ = bar();
3}
4inline fn bar() u8 {
5 noret();
6}
7const std = @import("std");
8inline fn noret() noreturn {
9 std.process.exit(0);
10}
test/standalone/simple/brace_expansion.zig created+292
...@@ -0,0 +1,292 @@
1const std = @import("std");
2const io = std.io;
3const mem = std.mem;
4const debug = std.debug;
5const assert = debug.assert;
6const testing = std.testing;
7const ArrayList = std.ArrayList;
8const maxInt = std.math.maxInt;
9
10const Token = union(enum) {
11 Word: []const u8,
12 OpenBrace,
13 CloseBrace,
14 Comma,
15 Eof,
16};
17
18var gpa = std.heap.GeneralPurposeAllocator(.{}){};
19var global_allocator = gpa.allocator();
20
21fn tokenize(input: []const u8) !ArrayList(Token) {
22 const State = enum {
23 Start,
24 Word,
25 };
26
27 var token_list = ArrayList(Token).init(global_allocator);
28 errdefer token_list.deinit();
29 var tok_begin: usize = undefined;
30 var state = State.Start;
31
32 for (input, 0..) |b, i| {
33 switch (state) {
34 .Start => switch (b) {
35 'a'...'z', 'A'...'Z' => {
36 state = State.Word;
37 tok_begin = i;
38 },
39 '{' => try token_list.append(Token.OpenBrace),
40 '}' => try token_list.append(Token.CloseBrace),
41 ',' => try token_list.append(Token.Comma),
42 else => return error.InvalidInput,
43 },
44 .Word => switch (b) {
45 'a'...'z', 'A'...'Z' => {},
46 '{', '}', ',' => {
47 try token_list.append(Token{ .Word = input[tok_begin..i] });
48 switch (b) {
49 '{' => try token_list.append(Token.OpenBrace),
50 '}' => try token_list.append(Token.CloseBrace),
51 ',' => try token_list.append(Token.Comma),
52 else => unreachable,
53 }
54 state = State.Start;
55 },
56 else => return error.InvalidInput,
57 },
58 }
59 }
60 switch (state) {
61 State.Start => {},
62 State.Word => try token_list.append(Token{ .Word = input[tok_begin..] }),
63 }
64 try token_list.append(Token.Eof);
65 return token_list;
66}
67
68const Node = union(enum) {
69 Scalar: []const u8,
70 List: ArrayList(Node),
71 Combine: []Node,
72
73 fn deinit(self: Node) void {
74 switch (self) {
75 .Scalar => {},
76 .Combine => |pair| {
77 pair[0].deinit();
78 pair[1].deinit();
79 global_allocator.free(pair);
80 },
81 .List => |list| {
82 for (list.items) |item| {
83 item.deinit();
84 }
85 list.deinit();
86 },
87 }
88 }
89};
90
91const ParseError = error{
92 InvalidInput,
93 OutOfMemory,
94};
95
96fn parse(tokens: *const ArrayList(Token), token_index: *usize) ParseError!Node {
97 const first_token = tokens.items[token_index.*];
98 token_index.* += 1;
99
100 const result_node = switch (first_token) {
101 .Word => |word| Node{ .Scalar = word },
102 .OpenBrace => blk: {
103 var list = ArrayList(Node).init(global_allocator);
104 errdefer {
105 for (list.items) |node| node.deinit();
106 list.deinit();
107 }
108 while (true) {
109 try list.append(try parse(tokens, token_index));
110
111 const token = tokens.items[token_index.*];
112 token_index.* += 1;
113
114 switch (token) {
115 .CloseBrace => break,
116 .Comma => continue,
117 else => return error.InvalidInput,
118 }
119 }
120 break :blk Node{ .List = list };
121 },
122 else => return error.InvalidInput,
123 };
124
125 switch (tokens.items[token_index.*]) {
126 .Word, .OpenBrace => {
127 const pair = try global_allocator.alloc(Node, 2);
128 errdefer global_allocator.free(pair);
129 pair[0] = result_node;
130 pair[1] = try parse(tokens, token_index);
131 return Node{ .Combine = pair };
132 },
133 else => return result_node,
134 }
135}
136
137fn expandString(input: []const u8, output: *ArrayList(u8)) !void {
138 const tokens = try tokenize(input);
139 defer tokens.deinit();
140 if (tokens.items.len == 1) {
141 return output.resize(0);
142 }
143
144 var token_index: usize = 0;
145 const root = try parse(&tokens, &token_index);
146 defer root.deinit();
147 const last_token = tokens.items[token_index];
148 switch (last_token) {
149 Token.Eof => {},
150 else => return error.InvalidInput,
151 }
152
153 var result_list = ArrayList(ArrayList(u8)).init(global_allocator);
154 defer {
155 for (result_list.items) |*buf| buf.deinit();
156 result_list.deinit();
157 }
158
159 try expandNode(root, &result_list);
160
161 try output.resize(0);
162 for (result_list.items, 0..) |buf, i| {
163 if (i != 0) {
164 try output.append(' ');
165 }
166 try output.appendSlice(buf.items);
167 }
168}
169
170const ExpandNodeError = error{OutOfMemory};
171
172fn expandNode(node: Node, output: *ArrayList(ArrayList(u8))) ExpandNodeError!void {
173 assert(output.items.len == 0);
174 switch (node) {
175 .Scalar => |scalar| {
176 var list = ArrayList(u8).init(global_allocator);
177 errdefer list.deinit();
178 try list.appendSlice(scalar);
179 try output.append(list);
180 },
181 .Combine => |pair| {
182 const a_node = pair[0];
183 const b_node = pair[1];
184
185 var child_list_a = ArrayList(ArrayList(u8)).init(global_allocator);
186 defer {
187 for (child_list_a.items) |*buf| buf.deinit();
188 child_list_a.deinit();
189 }
190 try expandNode(a_node, &child_list_a);
191
192 var child_list_b = ArrayList(ArrayList(u8)).init(global_allocator);
193 defer {
194 for (child_list_b.items) |*buf| buf.deinit();
195 child_list_b.deinit();
196 }
197 try expandNode(b_node, &child_list_b);
198
199 for (child_list_a.items) |buf_a| {
200 for (child_list_b.items) |buf_b| {
201 var combined_buf = ArrayList(u8).init(global_allocator);
202 errdefer combined_buf.deinit();
203
204 try combined_buf.appendSlice(buf_a.items);
205 try combined_buf.appendSlice(buf_b.items);
206 try output.append(combined_buf);
207 }
208 }
209 },
210 .List => |list| {
211 for (list.items) |child_node| {
212 var child_list = ArrayList(ArrayList(u8)).init(global_allocator);
213 errdefer for (child_list.items) |*buf| buf.deinit();
214 defer child_list.deinit();
215
216 try expandNode(child_node, &child_list);
217
218 for (child_list.items) |buf| {
219 try output.append(buf);
220 }
221 }
222 },
223 }
224}
225
226pub fn main() !void {
227 defer _ = gpa.deinit();
228 const stdin_file = io.getStdIn();
229 const stdout_file = io.getStdOut();
230
231 const stdin = try stdin_file.reader().readAllAlloc(global_allocator, std.math.maxInt(usize));
232 defer global_allocator.free(stdin);
233
234 var result_buf = ArrayList(u8).init(global_allocator);
235 defer result_buf.deinit();
236
237 try expandString(stdin, &result_buf);
238 try stdout_file.writeAll(result_buf.items);
239}
240
241test "invalid inputs" {
242 global_allocator = std.testing.allocator;
243
244 try expectError("}ABC", error.InvalidInput);
245 try expectError("{ABC", error.InvalidInput);
246 try expectError("}{", error.InvalidInput);
247 try expectError("{}", error.InvalidInput);
248 try expectError("A,B,C", error.InvalidInput);
249 try expectError("{A{B,C}", error.InvalidInput);
250 try expectError("{A,}", error.InvalidInput);
251
252 try expectError("\n", error.InvalidInput);
253}
254
255fn expectError(test_input: []const u8, expected_err: anyerror) !void {
256 var output_buf = ArrayList(u8).init(global_allocator);
257 defer output_buf.deinit();
258
259 try testing.expectError(expected_err, expandString(test_input, &output_buf));
260}
261
262test "valid inputs" {
263 global_allocator = std.testing.allocator;
264
265 try expectExpansion("{x,y,z}", "x y z");
266 try expectExpansion("{A,B}{x,y}", "Ax Ay Bx By");
267 try expectExpansion("{A,B{x,y}}", "A Bx By");
268
269 try expectExpansion("{ABC}", "ABC");
270 try expectExpansion("{A,B,C}", "A B C");
271 try expectExpansion("ABC", "ABC");
272
273 try expectExpansion("", "");
274 try expectExpansion("{A,B}{C,{x,y}}{g,h}", "ACg ACh Axg Axh Ayg Ayh BCg BCh Bxg Bxh Byg Byh");
275 try expectExpansion("{A,B}{C,C{x,y}}{g,h}", "ACg ACh ACxg ACxh ACyg ACyh BCg BCh BCxg BCxh BCyg BCyh");
276 try expectExpansion("{A,B}a", "Aa Ba");
277 try expectExpansion("{C,{x,y}}", "C x y");
278 try expectExpansion("z{C,{x,y}}", "zC zx zy");
279 try expectExpansion("a{b,c{d,e{f,g}}}", "ab acd acef aceg");
280 try expectExpansion("a{x,y}b", "axb ayb");
281 try expectExpansion("z{{a,b}}", "za zb");
282 try expectExpansion("a{b}", "ab");
283}
284
285fn expectExpansion(test_input: []const u8, expected_result: []const u8) !void {
286 var result = ArrayList(u8).init(global_allocator);
287 defer result.deinit();
288
289 expandString(test_input, &result) catch unreachable;
290
291 try testing.expectEqualSlices(u8, expected_result, result.items);
292}
test/standalone/simple/build.zig created+123
...@@ -0,0 +1,123 @@
1const std = @import("std");
2const builtin = @import("builtin");
3
4pub fn build(b: *std.Build) void {
5 const step = b.step("test", "Run simple standalone test cases");
6 b.default_step = step;
7
8 const skip_debug = b.option(bool, "skip_debug", "Skip debug builds") orelse false;
9 const skip_release_safe = b.option(bool, "skip_release_safe", "Skip release-safe builds") orelse false;
10 const skip_release_fast = b.option(bool, "skip_release_fast", "Skip release-fast builds") orelse false;
11 const skip_release_small = b.option(bool, "skip_release_small", "Skip release-small builds") orelse false;
12
13 var optimize_modes_buf: [4]std.builtin.OptimizeMode = undefined;
14 var optimize_modes_len: usize = 0;
15 if (!skip_debug) {
16 optimize_modes_buf[optimize_modes_len] = .Debug;
17 optimize_modes_len += 1;
18 }
19 if (!skip_release_safe) {
20 optimize_modes_buf[optimize_modes_len] = .ReleaseSafe;
21 optimize_modes_len += 1;
22 }
23 if (!skip_release_fast) {
24 optimize_modes_buf[optimize_modes_len] = .ReleaseFast;
25 optimize_modes_len += 1;
26 }
27 if (!skip_release_small) {
28 optimize_modes_buf[optimize_modes_len] = .ReleaseSmall;
29 optimize_modes_len += 1;
30 }
31 const optimize_modes = optimize_modes_buf[0..optimize_modes_len];
32
33 for (cases) |case| {
34 for (optimize_modes) |optimize| {
35 if (!case.all_modes and optimize != .Debug) continue;
36 if (case.os_filter) |os_tag| {
37 if (os_tag != builtin.os.tag) continue;
38 }
39
40 const resolved_target = b.resolveTargetQuery(case.target);
41
42 if (case.is_exe) {
43 const exe = b.addExecutable(.{
44 .name = std.fs.path.stem(case.src_path),
45 .root_source_file = .{ .path = case.src_path },
46 .optimize = optimize,
47 .target = resolved_target,
48 });
49 if (case.link_libc) exe.linkLibC();
50
51 _ = exe.getEmittedBin();
52
53 step.dependOn(&exe.step);
54 }
55
56 if (case.is_test) {
57 const exe = b.addTest(.{
58 .name = std.fs.path.stem(case.src_path),
59 .root_source_file = .{ .path = case.src_path },
60 .optimize = optimize,
61 .target = resolved_target,
62 });
63 if (case.link_libc) exe.linkLibC();
64
65 const run = b.addRunArtifact(exe);
66 step.dependOn(&run.step);
67 }
68 }
69 }
70}
71
72const Case = struct {
73 src_path: []const u8,
74 link_libc: bool = false,
75 all_modes: bool = false,
76 target: std.Target.Query = .{},
77 is_test: bool = false,
78 is_exe: bool = true,
79 /// Run only on this OS.
80 os_filter: ?std.Target.Os.Tag = null,
81};
82
83const cases = [_]Case{
84 .{
85 .src_path = "hello_world/hello.zig",
86 .all_modes = true,
87 },
88 .{
89 .src_path = "hello_world/hello_libc.zig",
90 .link_libc = true,
91 .all_modes = true,
92 },
93 .{
94 .src_path = "cat/main.zig",
95 },
96 // https://github.com/ziglang/zig/issues/6025
97 //.{
98 // .src_path = "issue_9693/main.zig",
99 //},
100 .{
101 .src_path = "brace_expansion.zig",
102 .is_test = true,
103 },
104 .{
105 .src_path = "issue_7030.zig",
106 .target = .{
107 .cpu_arch = .wasm32,
108 .os_tag = .freestanding,
109 },
110 },
111 .{ .src_path = "issue_12471/main.zig" },
112 .{ .src_path = "guess_number/main.zig" },
113 .{ .src_path = "main_return_error/error_u8.zig" },
114 .{ .src_path = "main_return_error/error_u8_non_zero.zig" },
115 .{ .src_path = "noreturn_call/inline.zig" },
116 .{ .src_path = "noreturn_call/as_arg.zig" },
117 .{ .src_path = "std_enums_big_enums.zig" },
118 .{
119 .src_path = "issue_9402/main.zig",
120 .os_filter = .windows,
121 .link_libc = true,
122 },
123};
test/standalone/simple/cat/main.zig created+46
...@@ -0,0 +1,46 @@
1const std = @import("std");
2const io = std.io;
3const process = std.process;
4const fs = std.fs;
5const mem = std.mem;
6const warn = std.log.warn;
7
8pub fn main() !void {
9 var arena_instance = std.heap.ArenaAllocator.init(std.heap.page_allocator);
10 defer arena_instance.deinit();
11 const arena = arena_instance.allocator();
12
13 const args = try process.argsAlloc(arena);
14
15 const exe = args[0];
16 var catted_anything = false;
17 const stdout_file = io.getStdOut();
18
19 const cwd = fs.cwd();
20
21 for (args[1..]) |arg| {
22 if (mem.eql(u8, arg, "-")) {
23 catted_anything = true;
24 try stdout_file.writeFileAll(io.getStdIn(), .{});
25 } else if (mem.startsWith(u8, arg, "-")) {
26 return usage(exe);
27 } else {
28 const file = cwd.openFile(arg, .{}) catch |err| {
29 warn("Unable to open file: {s}\n", .{@errorName(err)});
30 return err;
31 };
32 defer file.close();
33
34 catted_anything = true;
35 try stdout_file.writeFileAll(file, .{});
36 }
37 }
38 if (!catted_anything) {
39 try stdout_file.writeFileAll(io.getStdIn(), .{});
40 }
41}
42
43fn usage(exe: []const u8) !void {
44 warn("Usage: {s} [FILE]...\n", .{exe});
45 return error.Invalid;
46}
test/standalone/simple/guess_number/main.zig created+38
...@@ -0,0 +1,38 @@
1const builtin = @import("builtin");
2const std = @import("std");
3const io = std.io;
4const fmt = std.fmt;
5
6pub fn main() !void {
7 const stdout = io.getStdOut().writer();
8 const stdin = io.getStdIn();
9
10 try stdout.print("Welcome to the Guess Number Game in Zig.\n", .{});
11
12 const answer = std.crypto.random.intRangeLessThan(u8, 0, 100) + 1;
13
14 while (true) {
15 try stdout.print("\nGuess a number between 1 and 100: ", .{});
16 var line_buf: [20]u8 = undefined;
17
18 const amt = try stdin.read(&line_buf);
19 if (amt == line_buf.len) {
20 try stdout.print("Input too long.\n", .{});
21 continue;
22 }
23 const line = std.mem.trimRight(u8, line_buf[0..amt], "\r\n");
24
25 const guess = fmt.parseUnsigned(u8, line, 10) catch {
26 try stdout.print("Invalid number.\n", .{});
27 continue;
28 };
29 if (guess > answer) {
30 try stdout.print("Guess lower.\n", .{});
31 } else if (guess < answer) {
32 try stdout.print("Guess higher.\n", .{});
33 } else {
34 try stdout.print("You win!\n", .{});
35 return;
36 }
37 }
38}
test/standalone/simple/hello_world/hello.zig created+5
...@@ -0,0 +1,5 @@
1const std = @import("std");
2
3pub fn main() !void {
4 try std.io.getStdOut().writeAll("Hello, World!\n");
5}
test/standalone/simple/hello_world/hello_libc.zig created+15
...@@ -0,0 +1,15 @@
1const c = @cImport({
2 // See https://github.com/ziglang/zig/issues/515
3 @cDefine("_NO_CRT_STDIO_INLINE", "1");
4 @cInclude("stdio.h");
5 @cInclude("string.h");
6});
7
8const msg = "Hello, world!\n";
9
10pub export fn main(argc: c_int, argv: **u8) c_int {
11 _ = argv;
12 _ = argc;
13 if (c.printf(msg) != @as(c_int, @intCast(c.strlen(msg)))) return -1;
14 return 0;
15}
test/standalone/simple/issue_12471/main.zig created+12
...@@ -0,0 +1,12 @@
1const c = @cImport({
2 @cDefine("FOO", "FOO");
3 @cDefine("BAR", "FOO");
4
5 @cDefine("BAZ", "QUX");
6 @cDefine("QUX", "QUX");
7});
8
9pub fn main() u8 {
10 _ = c;
11 return 0;
12}
test/standalone/simple/issue_7030.zig created+21
...@@ -0,0 +1,21 @@
1const std = @import("std");
2
3pub const std_options = .{
4 .logFn = log,
5};
6
7pub fn log(
8 comptime message_level: std.log.Level,
9 comptime scope: @Type(.EnumLiteral),
10 comptime format: []const u8,
11 args: anytype,
12) void {
13 _ = message_level;
14 _ = scope;
15 _ = format;
16 _ = args;
17}
18
19pub fn main() anyerror!void {
20 std.log.info("All your codebase are belong to us.", .{});
21}
test/standalone/simple/issue_9402/main.zig created+14
...@@ -0,0 +1,14 @@
1const FILE = extern struct {
2 dummy_field: u8,
3};
4
5extern fn _ftelli64([*c]FILE) i64;
6extern fn _fseeki64([*c]FILE, i64, c_int) c_int;
7
8pub export fn main(argc: c_int, argv: **u8) c_int {
9 _ = argv;
10 _ = argc;
11 _ = _ftelli64(null);
12 _ = _fseeki64(null, 123, 2);
13 return 0;
14}
test/standalone/simple/main_return_error/error_u8.zig created+5
...@@ -0,0 +1,5 @@
1const Err = error{Foo};
2
3pub fn main() !u8 {
4 return Err.Foo;
5}
test/standalone/simple/main_return_error/error_u8_non_zero.zig created+10
...@@ -0,0 +1,10 @@
1const Err = error{Foo};
2
3fn foo() u8 {
4 return @intCast(9);
5}
6
7pub fn main() !u8 {
8 if (foo() == 7) return Err.Foo;
9 return 123;
10}
test/standalone/simple/noreturn_call/as_arg.zig created+8
...@@ -0,0 +1,8 @@
1const std = @import("std");
2fn foo() noreturn {
3 std.process.exit(0);
4}
5fn bar(_: u8, _: u8) void {}
6pub fn main() void {
7 bar(foo(), @compileError("bad"));
8}
test/standalone/simple/noreturn_call/inline.zig created+10
...@@ -0,0 +1,10 @@
1pub fn main() void {
2 _ = bar();
3}
4inline fn bar() u8 {
5 noret();
6}
7const std = @import("std");
8inline fn noret() noreturn {
9 std.process.exit(0);
10}
test/standalone/simple/std_enums_big_enums.zig created+38
...@@ -0,0 +1,38 @@
1const std = @import("std");
2
3// big enums should not hit the eval branch quota
4pub fn main() void {
5 const big = struct {
6 const Big = @Type(@as(std.builtin.Type, .{
7 .Enum = .{
8 .tag_type = u16,
9 .fields = make_fields: {
10 var fields: [1001]std.builtin.Type.EnumField = undefined;
11 for (&fields, 0..) |*field, i| {
12 field.* = .{ .name = std.fmt.comptimePrint("field_{d}", .{i}), .value = i };
13 }
14 fields[1000] = .{ .name = "field_9999", .value = 9999 };
15 break :make_fields &fields;
16 },
17 .decls = &.{},
18 .is_exhaustive = true,
19 },
20 }));
21 };
22
23 var set = std.enums.EnumSet(big.Big).init(.{});
24 _ = &set;
25
26 var map = std.enums.EnumMap(big.Big, u8).init(undefined);
27 map = std.enums.EnumMap(big.Big, u8).initFullWith(undefined);
28 map = std.enums.EnumMap(big.Big, u8).initFullWithDefault(123, .{});
29
30 var multiset = std.enums.EnumMultiset(big.Big).init(.{});
31 _ = &multiset;
32
33 var bounded_multiset = std.enums.BoundedEnumMultiset(big.Big, u8).init(.{});
34 _ = &bounded_multiset;
35
36 var array = std.enums.EnumArray(big.Big, u8).init(undefined);
37 array = std.enums.EnumArray(big.Big, u8).initDefault(123, .{});
38}
test/standalone/std_enums_big_enums.zig deleted-38
...@@ -1,38 +0,0 @@
1const std = @import("std");
2
3// big enums should not hit the eval branch quota
4pub fn main() void {
5 const big = struct {
6 const Big = @Type(@as(std.builtin.Type, .{
7 .Enum = .{
8 .tag_type = u16,
9 .fields = make_fields: {
10 var fields: [1001]std.builtin.Type.EnumField = undefined;
11 for (&fields, 0..) |*field, i| {
12 field.* = .{ .name = std.fmt.comptimePrint("field_{d}", .{i}), .value = i };
13 }
14 fields[1000] = .{ .name = "field_9999", .value = 9999 };
15 break :make_fields &fields;
16 },
17 .decls = &.{},
18 .is_exhaustive = true,
19 },
20 }));
21 };
22
23 var set = std.enums.EnumSet(big.Big).init(.{});
24 _ = &set;
25
26 var map = std.enums.EnumMap(big.Big, u8).init(undefined);
27 map = std.enums.EnumMap(big.Big, u8).initFullWith(undefined);
28 map = std.enums.EnumMap(big.Big, u8).initFullWithDefault(123, .{});
29
30 var multiset = std.enums.EnumMultiset(big.Big).init(.{});
31 _ = &multiset;
32
33 var bounded_multiset = std.enums.BoundedEnumMultiset(big.Big, u8).init(.{});
34 _ = &bounded_multiset;
35
36 var array = std.enums.EnumArray(big.Big, u8).init(undefined);
37 array = std.enums.EnumArray(big.Big, u8).initDefault(123, .{});
38}
test/tests.zig+30-105
...@@ -7,12 +7,10 @@ const Step = std.Build.Step;...@@ -7,12 +7,10 @@ const Step = std.Build.Step;
77
8// Cases8// Cases
9const compare_output = @import("compare_output.zig");9const compare_output = @import("compare_output.zig");
10const standalone = @import("standalone.zig");
11const stack_traces = @import("stack_traces.zig");10const stack_traces = @import("stack_traces.zig");
12const assemble_and_link = @import("assemble_and_link.zig");11const assemble_and_link = @import("assemble_and_link.zig");
13const translate_c = @import("translate_c.zig");12const translate_c = @import("translate_c.zig");
14const run_translated_c = @import("run_translated_c.zig");13const run_translated_c = @import("run_translated_c.zig");
15const link = @import("link.zig");
1614
17// Implementations15// Implementations
18pub const TranslateCContext = @import("src/TranslateC.zig");16pub const TranslateCContext = @import("src/TranslateC.zig");
...@@ -663,79 +661,35 @@ pub fn addStackTraceTests(...@@ -663,79 +661,35 @@ pub fn addStackTraceTests(
663 return cases.step;661 return cases.step;
664}662}
665663
664fn compilerHasPackageManager(b: *std.Build) bool {
665 // We can only use dependencies if the compiler was built with support for package management.
666 // (zig2 doesn't support it, but we still need to construct a build graph to build stage3.)
667 return b.available_deps.len != 0;
668}
669
666pub fn addStandaloneTests(670pub fn addStandaloneTests(
667 b: *std.Build,671 b: *std.Build,
668 optimize_modes: []const OptimizeMode,672 optimize_modes: []const OptimizeMode,
669 enable_macos_sdk: bool,673 enable_macos_sdk: bool,
670 enable_ios_sdk: bool,674 enable_ios_sdk: bool,
671 omit_stage2: bool,
672 enable_symlinks_windows: bool,675 enable_symlinks_windows: bool,
673) *Step {676) *Step {
674 const step = b.step("test-standalone", "Run the standalone tests");677 const step = b.step("test-standalone", "Run the standalone tests");
675 const omit_symlinks = builtin.os.tag == .windows and !enable_symlinks_windows;678 if (compilerHasPackageManager(b)) {
676679 const test_cases_dep_name = "standalone_test_cases";
677 for (standalone.simple_cases) |case| {680 const test_cases_dep = b.dependency(test_cases_dep_name, .{
678 for (optimize_modes) |optimize| {681 .enable_ios_sdk = enable_ios_sdk,
679 if (!case.all_modes and optimize != .Debug) continue;682 .enable_macos_sdk = enable_macos_sdk,
680 if (case.os_filter) |os_tag| {683 .enable_symlinks_windows = enable_symlinks_windows,
681 if (os_tag != builtin.os.tag) continue;684 .simple_skip_debug = mem.indexOfScalar(OptimizeMode, optimize_modes, .Debug) == null,
682 }685 .simple_skip_release_safe = mem.indexOfScalar(OptimizeMode, optimize_modes, .ReleaseSafe) == null,
683686 .simple_skip_release_fast = mem.indexOfScalar(OptimizeMode, optimize_modes, .ReleaseFast) == null,
684 const resolved_target = b.resolveTargetQuery(case.target);687 .simple_skip_release_small = mem.indexOfScalar(OptimizeMode, optimize_modes, .ReleaseSmall) == null,
685688 });
686 if (case.is_exe) {689 const test_cases_dep_step = test_cases_dep.builder.default_step;
687 const exe = b.addExecutable(.{690 test_cases_dep_step.name = b.dupe(test_cases_dep_name);
688 .name = std.fs.path.stem(case.src_path),691 step.dependOn(test_cases_dep.builder.default_step);
689 .root_source_file = .{ .path = case.src_path },
690 .optimize = optimize,
691 .target = resolved_target,
692 });
693 if (case.link_libc) exe.linkLibC();
694
695 _ = exe.getEmittedBin();
696
697 step.dependOn(&exe.step);
698 }
699
700 if (case.is_test) {
701 const exe = b.addTest(.{
702 .name = std.fs.path.stem(case.src_path),
703 .root_source_file = .{ .path = case.src_path },
704 .optimize = optimize,
705 .target = resolved_target,
706 });
707 if (case.link_libc) exe.linkLibC();
708
709 const run = b.addRunArtifact(exe);
710 step.dependOn(&run.step);
711 }
712 }
713 }
714
715 inline for (standalone.build_cases) |case| {
716 const requires_stage2 = @hasDecl(case.import, "requires_stage2") and
717 case.import.requires_stage2;
718 const requires_symlinks = @hasDecl(case.import, "requires_symlinks") and
719 case.import.requires_symlinks;
720 const requires_macos_sdk = @hasDecl(case.import, "requires_macos_sdk") and
721 case.import.requires_macos_sdk;
722 const requires_ios_sdk = @hasDecl(case.import, "requires_ios_sdk") and
723 case.import.requires_ios_sdk;
724 const bad =
725 (requires_stage2 and omit_stage2) or
726 (requires_symlinks and omit_symlinks) or
727 (requires_macos_sdk and !enable_macos_sdk) or
728 (requires_ios_sdk and !enable_ios_sdk);
729 if (!bad) {
730 const dep = b.anonymousDependency(case.build_root, case.import, .{});
731 const dep_step = dep.builder.default_step;
732 assert(mem.startsWith(u8, dep.builder.dep_prefix, "test."));
733 const dep_prefix_adjusted = dep.builder.dep_prefix["test.".len..];
734 dep_step.name = b.fmt("{s}{s}", .{ dep_prefix_adjusted, dep_step.name });
735 step.dependOn(dep_step);
736 }
737 }692 }
738
739 return step;693 return step;
740}694}
741695
...@@ -743,49 +697,20 @@ pub fn addLinkTests(...@@ -743,49 +697,20 @@ pub fn addLinkTests(
743 b: *std.Build,697 b: *std.Build,
744 enable_macos_sdk: bool,698 enable_macos_sdk: bool,
745 enable_ios_sdk: bool,699 enable_ios_sdk: bool,
746 omit_stage2: bool,
747 enable_symlinks_windows: bool,700 enable_symlinks_windows: bool,
748) *Step {701) *Step {
749 const step = b.step("test-link", "Run the linker tests");702 const step = b.step("test-link", "Run the linker tests");
750 const omit_symlinks = builtin.os.tag == .windows and !enable_symlinks_windows;703 if (compilerHasPackageManager(b)) {
751704 const test_cases_dep_name = "link_test_cases";
752 inline for (link.cases) |case| {705 const test_cases_dep = b.dependency(test_cases_dep_name, .{
753 if (mem.eql(u8, @typeName(case.import), "test.link.link")) {706 .enable_ios_sdk = enable_ios_sdk,
754 const dep = b.anonymousDependency(case.build_root, case.import, .{707 .enable_macos_sdk = enable_macos_sdk,
755 .has_macos_sdk = enable_macos_sdk,708 .enable_symlinks_windows = enable_symlinks_windows,
756 .has_ios_sdk = enable_ios_sdk,709 });
757 .has_symlinks_windows = !omit_symlinks,710 const test_cases_dep_step = test_cases_dep.builder.default_step;
758 });711 test_cases_dep_step.name = b.dupe(test_cases_dep_name);
759 const dep_step = dep.builder.default_step;712 step.dependOn(test_cases_dep.builder.default_step);
760 assert(mem.startsWith(u8, dep.builder.dep_prefix, "test."));
761 const dep_prefix_adjusted = dep.builder.dep_prefix["test.".len..];
762 dep_step.name = b.fmt("{s}{s}", .{ dep_prefix_adjusted, dep_step.name });
763 step.dependOn(dep_step);
764 } else {
765 const requires_stage2 = @hasDecl(case.import, "requires_stage2") and
766 case.import.requires_stage2;
767 const requires_symlinks = @hasDecl(case.import, "requires_symlinks") and
768 case.import.requires_symlinks;
769 const requires_macos_sdk = @hasDecl(case.import, "requires_macos_sdk") and
770 case.import.requires_macos_sdk;
771 const requires_ios_sdk = @hasDecl(case.import, "requires_ios_sdk") and
772 case.import.requires_ios_sdk;
773 const bad =
774 (requires_stage2 and omit_stage2) or
775 (requires_symlinks and omit_symlinks) or
776 (requires_macos_sdk and !enable_macos_sdk) or
777 (requires_ios_sdk and !enable_ios_sdk);
778 if (!bad) {
779 const dep = b.anonymousDependency(case.build_root, case.import, .{});
780 const dep_step = dep.builder.default_step;
781 assert(mem.startsWith(u8, dep.builder.dep_prefix, "test."));
782 const dep_prefix_adjusted = dep.builder.dep_prefix["test.".len..];
783 dep_step.name = b.fmt("{s}{s}", .{ dep_prefix_adjusted, dep_step.name });
784 step.dependOn(dep_step);
785 }
786 }
787 }713 }
788
789 return step;714 return step;
790}715}
791716