Commit 5d5e89aa8d

Carl Åstholm <carl@astholm.se>
2024-02-17 17:47:13
Promote linker test cases to packages
1 parent 33b8fdb
test/link/build.zig
@@ -0,0 +1,54 @@
+const std = @import("std");
+const builtin = @import("builtin");
+const link = @import("link.zig");
+
+pub fn build(b: *std.Build) void {
+    const step = b.step("test", "Run link test cases");
+    b.default_step = step;
+
+    const enable_ios_sdk = b.option(bool, "enable_ios_sdk", "Run tests requiring presence of iOS SDK and frameworks") orelse false;
+    const enable_macos_sdk = b.option(bool, "enable_macos_sdk", "Run tests requiring presence of macOS SDK and frameworks") orelse enable_ios_sdk;
+    const enable_symlinks_windows = b.option(bool, "enable_symlinks_windows", "Run tests requiring presence of symlinks on Windows") orelse false;
+    const omit_symlinks = builtin.os.tag == .windows and !enable_symlinks_windows;
+
+    const build_opts: link.BuildOptions = .{
+        .has_ios_sdk = enable_ios_sdk,
+        .has_macos_sdk = enable_macos_sdk,
+        .has_symlinks_windows = omit_symlinks,
+    };
+    step.dependOn(@import("elf.zig").testAll(b, build_opts));
+    step.dependOn(@import("macho.zig").testAll(b, build_opts));
+
+    add_dep_steps: for (b.available_deps) |available_dep| {
+        const dep_name, const dep_hash = available_dep;
+
+        const all_pkgs = @import("root").dependencies.packages;
+        inline for (@typeInfo(all_pkgs).Struct.decls) |decl| {
+            const pkg_hash = decl.name;
+            if (std.mem.eql(u8, dep_hash, pkg_hash)) {
+                const pkg = @field(all_pkgs, pkg_hash);
+                if (!@hasDecl(pkg, "build_zig")) {
+                    std.debug.panic("link test case '{s}' is missing a 'build.zig' file", .{dep_name});
+                }
+                const requires_ios_sdk = @hasDecl(pkg.build_zig, "requires_ios_sdk") and
+                    pkg.build_zig.requires_ios_sdk;
+                const requires_macos_sdk = @hasDecl(pkg.build_zig, "requires_macos_sdk") and
+                    pkg.build_zig.requires_macos_sdk;
+                const requires_symlinks = @hasDecl(pkg.build_zig, "requires_symlinks") and
+                    pkg.build_zig.requires_symlinks;
+                if ((requires_symlinks and omit_symlinks) or
+                    (requires_macos_sdk and !enable_macos_sdk) or
+                    (requires_ios_sdk and !enable_ios_sdk))
+                {
+                    continue :add_dep_steps;
+                }
+                break;
+            }
+        } else unreachable;
+
+        const dep = b.dependency(dep_name, .{});
+        const dep_step = dep.builder.default_step;
+        dep_step.name = b.fmt("link_test_cases.{s}", .{dep_name});
+        step.dependOn(dep_step);
+    }
+}
test/link/build.zig.zon
@@ -0,0 +1,69 @@
+.{
+    .name = "link_test_cases",
+    .version = "0.0.0",
+    .dependencies = .{
+        .bss = .{
+            .path = "bss",
+        },
+        .common_symbols_alignment = .{
+            .path = "common_symbols_alignment",
+        },
+        .interdependent_static_c_libs = .{
+            .path = "interdependent_static_c_libs",
+        },
+        .static_libs_from_object_files = .{
+            .path = "static_libs_from_object_files",
+        },
+        .glibc_compat = .{
+            .path = "glibc_compat",
+        },
+        // WASM Cases
+        .wasm_archive = .{
+            .path = "wasm/archive",
+        },
+        .wasm_basic_features = .{
+            .path = "wasm/basic-features",
+        },
+        .wasm_bss = .{
+            .path = "wasm/bss",
+        },
+        .wasm_export = .{
+            .path = "wasm/export",
+        },
+        .wasm_export_data = .{
+            .path = "wasm/export-data",
+        },
+        .wasm_extern = .{
+            .path = "wasm/extern",
+        },
+        .wasm_extern_mangle = .{
+            .path = "wasm/extern-mangle",
+        },
+        .wasm_function_table = .{
+            .path = "wasm/function-table",
+        },
+        .wasm_infer_features = .{
+            .path = "wasm/infer-features",
+        },
+        .wasm_producers = .{
+            .path = "wasm/producers",
+        },
+        .wasm_segments = .{
+            .path = "wasm/segments",
+        },
+        .wasm_shared_memory = .{
+            .path = "wasm/shared-memory",
+        },
+        .wasm_stack_pointer = .{
+            .path = "wasm/stack_pointer",
+        },
+        .wasm_type = .{
+            .path = "wasm/type",
+        },
+    },
+    .paths = .{
+        "build.zig",
+        "build.zig.zon",
+        "link.zig",
+    },
+}
test/link.zig
@@ -1,94 +0,0 @@
-pub const Case = struct {
-    build_root: []const u8,
-    import: type,
-};
-
-pub const cases = [_]Case{
-    .{
-        .build_root = "test/link",
-        .import = @import("link/link.zig"),
-    },
-
-    .{
-        .build_root = "test/link/bss",
-        .import = @import("link/bss/build.zig"),
-    },
-    .{
-        .build_root = "test/link/common_symbols",
-        .import = @import("link/common_symbols/build.zig"),
-    },
-    .{
-        .build_root = "test/link/common_symbols_alignment",
-        .import = @import("link/common_symbols_alignment/build.zig"),
-    },
-    .{
-        .build_root = "test/link/interdependent_static_c_libs",
-        .import = @import("link/interdependent_static_c_libs/build.zig"),
-    },
-    .{
-        .build_root = "test/link/static_libs_from_object_files",
-        .import = @import("link/static_libs_from_object_files/build.zig"),
-    },
-    .{
-        .build_root = "test/link/glibc_compat",
-        .import = @import("link/glibc_compat/build.zig"),
-    },
-
-    // WASM Cases
-    .{
-        .build_root = "test/link/wasm/archive",
-        .import = @import("link/wasm/archive/build.zig"),
-    },
-    .{
-        .build_root = "test/link/wasm/basic-features",
-        .import = @import("link/wasm/basic-features/build.zig"),
-    },
-    .{
-        .build_root = "test/link/wasm/bss",
-        .import = @import("link/wasm/bss/build.zig"),
-    },
-    .{
-        .build_root = "test/link/wasm/export",
-        .import = @import("link/wasm/export/build.zig"),
-    },
-    .{
-        .build_root = "test/link/wasm/export-data",
-        .import = @import("link/wasm/export-data/build.zig"),
-    },
-    .{
-        .build_root = "test/link/wasm/extern",
-        .import = @import("link/wasm/extern/build.zig"),
-    },
-    .{
-        .build_root = "test/link/wasm/extern-mangle",
-        .import = @import("link/wasm/extern-mangle/build.zig"),
-    },
-    .{
-        .build_root = "test/link/wasm/function-table",
-        .import = @import("link/wasm/function-table/build.zig"),
-    },
-    .{
-        .build_root = "test/link/wasm/infer-features",
-        .import = @import("link/wasm/infer-features/build.zig"),
-    },
-    .{
-        .build_root = "test/link/wasm/producers",
-        .import = @import("link/wasm/producers/build.zig"),
-    },
-    .{
-        .build_root = "test/link/wasm/segments",
-        .import = @import("link/wasm/segments/build.zig"),
-    },
-    .{
-        .build_root = "test/link/wasm/shared-memory",
-        .import = @import("link/wasm/shared-memory/build.zig"),
-    },
-    .{
-        .build_root = "test/link/wasm/stack_pointer",
-        .import = @import("link/wasm/stack_pointer/build.zig"),
-    },
-    .{
-        .build_root = "test/link/wasm/type",
-        .import = @import("link/wasm/type/build.zig"),
-    },
-};
test/tests.zig
@@ -11,7 +11,6 @@ const stack_traces = @import("stack_traces.zig");
 const assemble_and_link = @import("assemble_and_link.zig");
 const translate_c = @import("translate_c.zig");
 const run_translated_c = @import("run_translated_c.zig");
-const link = @import("link.zig");
 
 // Implementations
 pub const TranslateCContext = @import("src/TranslateC.zig");
@@ -662,6 +661,12 @@ pub fn addStackTraceTests(
     return cases.step;
 }
 
+fn compilerHasPackageManager(b: *std.Build) bool {
+    // We can only use dependencies if the compiler was built with support for package management.
+    // (zig2 doesn't support it, but we still need to construct a build graph to build stage3.)
+    return b.available_deps.len != 0;
+}
+
 pub fn addStandaloneTests(
     b: *std.Build,
     optimize_modes: []const OptimizeMode,
@@ -670,12 +675,7 @@ pub fn addStandaloneTests(
     enable_symlinks_windows: bool,
 ) *Step {
     const step = b.step("test-standalone", "Run the standalone tests");
-
-    // We can only use dependencies if the compiler was built with support for package management.
-    // (zig2 doesn't support it, but we still need to construct a build graph to build stage3.)
-    const package_management_available = b.available_deps.len != 0;
-
-    if (package_management_available) {
+    if (compilerHasPackageManager(b)) {
         const test_cases_dep_name = "standalone_test_cases";
         const test_cases_dep = b.dependency(test_cases_dep_name, .{
             .enable_ios_sdk = enable_ios_sdk,
@@ -690,7 +690,6 @@ pub fn addStandaloneTests(
         test_cases_dep_step.name = b.dupe(test_cases_dep_name);
         step.dependOn(test_cases_dep.builder.default_step);
     }
-
     return step;
 }
 
@@ -698,49 +697,20 @@ pub fn addLinkTests(
     b: *std.Build,
     enable_macos_sdk: bool,
     enable_ios_sdk: bool,
-    omit_stage2: bool,
     enable_symlinks_windows: bool,
 ) *Step {
     const step = b.step("test-link", "Run the linker tests");
-    const omit_symlinks = builtin.os.tag == .windows and !enable_symlinks_windows;
-
-    inline for (link.cases) |case| {
-        if (mem.eql(u8, @typeName(case.import), "test.link.link")) {
-            const dep = b.anonymousDependency(case.build_root, case.import, .{
-                .has_macos_sdk = enable_macos_sdk,
-                .has_ios_sdk = enable_ios_sdk,
-                .has_symlinks_windows = !omit_symlinks,
-            });
-            const dep_step = dep.builder.default_step;
-            assert(mem.startsWith(u8, dep.builder.dep_prefix, "test."));
-            const dep_prefix_adjusted = dep.builder.dep_prefix["test.".len..];
-            dep_step.name = b.fmt("{s}{s}", .{ dep_prefix_adjusted, dep_step.name });
-            step.dependOn(dep_step);
-        } else {
-            const requires_stage2 = @hasDecl(case.import, "requires_stage2") and
-                case.import.requires_stage2;
-            const requires_symlinks = @hasDecl(case.import, "requires_symlinks") and
-                case.import.requires_symlinks;
-            const requires_macos_sdk = @hasDecl(case.import, "requires_macos_sdk") and
-                case.import.requires_macos_sdk;
-            const requires_ios_sdk = @hasDecl(case.import, "requires_ios_sdk") and
-                case.import.requires_ios_sdk;
-            const bad =
-                (requires_stage2 and omit_stage2) or
-                (requires_symlinks and omit_symlinks) or
-                (requires_macos_sdk and !enable_macos_sdk) or
-                (requires_ios_sdk and !enable_ios_sdk);
-            if (!bad) {
-                const dep = b.anonymousDependency(case.build_root, case.import, .{});
-                const dep_step = dep.builder.default_step;
-                assert(mem.startsWith(u8, dep.builder.dep_prefix, "test."));
-                const dep_prefix_adjusted = dep.builder.dep_prefix["test.".len..];
-                dep_step.name = b.fmt("{s}{s}", .{ dep_prefix_adjusted, dep_step.name });
-                step.dependOn(dep_step);
-            }
-        }
+    if (compilerHasPackageManager(b)) {
+        const test_cases_dep_name = "link_test_cases";
+        const test_cases_dep = b.dependency(test_cases_dep_name, .{
+            .enable_ios_sdk = enable_ios_sdk,
+            .enable_macos_sdk = enable_macos_sdk,
+            .enable_symlinks_windows = enable_symlinks_windows,
+        });
+        const test_cases_dep_step = test_cases_dep.builder.default_step;
+        test_cases_dep_step.name = b.dupe(test_cases_dep_name);
+        step.dependOn(test_cases_dep.builder.default_step);
     }
-
     return step;
 }
 
build.zig
@@ -524,7 +524,7 @@ pub fn build(b: *std.Build) !void {
         enable_symlinks_windows,
     ));
     test_step.dependOn(tests.addCAbiTests(b, skip_non_native, skip_release));
-    test_step.dependOn(tests.addLinkTests(b, enable_macos_sdk, enable_ios_sdk, false, enable_symlinks_windows));
+    test_step.dependOn(tests.addLinkTests(b, enable_macos_sdk, enable_ios_sdk, enable_symlinks_windows));
     test_step.dependOn(tests.addStackTraceTests(b, test_filters, optimization_modes));
     test_step.dependOn(tests.addCliTests(b));
     test_step.dependOn(tests.addAssembleAndLinkTests(b, test_filters, optimization_modes));
build.zig.zon
@@ -7,6 +7,9 @@
         .standalone_test_cases = .{
             .path = "test/standalone",
         },
+        .link_test_cases = .{
+            .path = "test/link",
+        },
     },
     .paths = .{""},
 }