diff --git a/build.zig b/build.zig index b96f35b3ce..96cf176221 100644 --- a/build.zig +++ b/build.zig @@ -1443,22 +1443,6 @@ fn setupTestPlatforms( clear_cache_step.dependOn(©_step.step); } - // Build the wasm-elem test platform host for wasm32-freestanding (tests parameterized opaque types with requires clause) - { - const wasm_target = b.resolveTargetQuery(.{ .cpu_arch = .wasm32, .os_tag = .freestanding, .abi = .none }); - const copy_step = buildAndCopyTestPlatformHostLib( - b, - "wasm-elem", - wasm_target, - "wasm32", - optimize, - roc_modules, - strip, - omit_frame_pointer, - ); - clear_cache_step.dependOn(©_step.step); - } - b.getInstallStep().dependOn(clear_cache_step); test_platforms_step.dependOn(clear_cache_step); } @@ -1680,8 +1664,7 @@ pub fn build(b: *std.Build) void { b.installArtifact(test_runner_exe); // CLI integration tests - run actual roc programs like CI does - // NOTE: These tests must run sequentially to avoid race conditions on the Roc cache - // Order: test_runner int -> test_runner str -> roc_subcommands_test + // These tests can run in parallel since each build uses content-hashed shim files if (!no_bin) { const install = b.addInstallArtifact(roc_exe, .{}); const install_runner = b.addInstallArtifact(test_runner_exe, .{}); @@ -1694,16 +1677,19 @@ pub fn build(b: *std.Build) void { run_int_tests.step.dependOn(&install.step); run_int_tests.step.dependOn(&install_runner.step); run_int_tests.step.dependOn(test_platforms_step); + test_cli_step.dependOn(&run_int_tests.step); // Test str platform (native mode only for now) - // Run after int tests to avoid cache race conditions const run_str_tests = b.addRunArtifact(test_runner_exe); run_str_tests.addArg("zig-out/bin/roc"); run_str_tests.addArg("str"); run_str_tests.addArg("--mode=native"); - run_str_tests.step.dependOn(&run_int_tests.step); + run_str_tests.step.dependOn(&install.step); + run_str_tests.step.dependOn(&install_runner.step); + run_str_tests.step.dependOn(test_platforms_step); + test_cli_step.dependOn(&run_str_tests.step); - // Roc subcommands integration test - runs after test_runner tests + // Roc subcommands integration test const roc_subcommands_test = b.addTest(.{ .name = "roc_subcommands_test", .root_module = b.createModule(.{ @@ -1718,8 +1704,8 @@ pub fn build(b: *std.Build) void { if (run_args.len != 0) { run_roc_subcommands_test.addArgs(run_args); } - run_roc_subcommands_test.step.dependOn(&run_str_tests.step); // Run after test_runner - + run_roc_subcommands_test.step.dependOn(&install.step); + run_roc_subcommands_test.step.dependOn(test_platforms_step); test_cli_step.dependOn(&run_roc_subcommands_test.step); } diff --git a/src/cli/main.zig b/src/cli/main.zig index 48a3381e77..35075c15e7 100644 --- a/src/cli/main.zig +++ b/src/cli/main.zig @@ -827,12 +827,28 @@ fn generatePlatformHostShim(allocs: *Allocators, cache_dir: []const u8, entrypoi }; // Generate paths for temporary files - const bitcode_path = std.fs.path.join(allocs.arena, &.{ cache_dir, "platform_shim.bc" }) catch |err| { + // Use a hash of the serialized module content to avoid race conditions when multiple + // builds run in parallel. Each unique module content gets its own shim files. + const content_hash = if (serialized_module) |module_bytes| + std.hash.Crc32.hash(module_bytes) + else + 0; // For IPC mode (roc run), use a fixed name since there's no embedded data + + const bitcode_filename = std.fmt.allocPrint(allocs.arena, "platform_shim_{x}.bc", .{content_hash}) catch |err| { + std.log.err("Failed to create bitcode filename: {}", .{err}); + return err; + }; + const object_filename = std.fmt.allocPrint(allocs.arena, "platform_shim_{x}.o", .{content_hash}) catch |err| { + std.log.err("Failed to create object filename: {}", .{err}); + return err; + }; + + const bitcode_path = std.fs.path.join(allocs.arena, &.{ cache_dir, bitcode_filename }) catch |err| { std.log.err("Failed to create bitcode path: {}", .{err}); return err; }; - const object_path = std.fs.path.join(allocs.arena, &.{ cache_dir, "platform_shim.o" }) catch |err| { + const object_path = std.fs.path.join(allocs.arena, &.{ cache_dir, object_filename }) catch |err| { std.log.err("Failed to create object path: {}", .{err}); return err; };