diff --git a/.github/actions/setup-wasm/action.yaml b/.github/actions/setup-wasm/action.yaml index f70dc23a..59e42031 100644 --- a/.github/actions/setup-wasm/action.yaml +++ b/.github/actions/setup-wasm/action.yaml @@ -3,8 +3,12 @@ description: Restore the Cargo cache and install the pinned WASM toolchain runs: using: composite steps: - - name: Add WASM target - run: rustup target add wasm32-unknown-unknown + - name: Install WASM Rust toolchain + run: | + rustup toolchain install "$(cat wasm-rust-toolchain)" \ + --profile minimal \ + --component rust-src \ + --target wasm32-unknown-unknown shell: bash - name: Restore Cargo build cache uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 @@ -16,11 +20,12 @@ runs: ~/.cargo/registry/index target key: >- - wasm-${{ runner.os }}-${{ hashFiles('Cargo.lock', 'rust-toolchain.toml', '.cargo/config.toml') }}-${{ + wasm-${{ runner.os }}-${{ + hashFiles('Cargo.lock', '*rust-toolchain*', '.cargo/config.toml', 'scripts/build-wasm.js') }}-${{ hashFiles('Cargo.toml', 'crates/**/Cargo.toml', 'crates/**/*.rs') }} restore-keys: >- wasm-${{ runner.os }}-${{ - hashFiles('Cargo.lock', 'rust-toolchain.toml', '.cargo/config.toml') }}- + hashFiles('Cargo.lock', '*rust-toolchain*', '.cargo/config.toml', 'scripts/build-wasm.js') }}- - name: Install wasm-pack env: WASM_PACK_SHA256: 278a8d668085821f4d1a637bd864f1713f872b0ae3a118c77562a308c0abfe8d diff --git a/scripts/build-wasm.js b/scripts/build-wasm.js index a6717f93..62ef1a02 100644 --- a/scripts/build-wasm.js +++ b/scripts/build-wasm.js @@ -16,6 +16,10 @@ const path = require('node:path') const childProcess = require('node:child_process') const isMacOS = os.platform() === 'darwin' +const wasmRustToolchain = fs.readFileSync( + path.join(__dirname, '..', 'wasm-rust-toolchain'), + 'utf8', +).trim() const libraries = [ 'library_config', 'pipeline', @@ -25,6 +29,20 @@ const libraries = [ const env = { ...process.env, } +const pathKey = Object.keys(env).find(key => key.toUpperCase() === 'PATH') ?? 'PATH' +const rustFlagsKey = Object.keys(env).find(key => key.toUpperCase() === 'RUSTFLAGS') ?? 'RUSTFLAGS' +const rustupToolchainKey = Object.keys(env).find(key => key.toUpperCase() === 'RUSTUP_TOOLCHAIN') ?? 'RUSTUP_TOOLCHAIN' +const cargoPath = childProcess.execFileSync( + 'rustup', + ['which', 'cargo', '--toolchain', wasmRustToolchain], + { encoding: 'utf8' }, +).trim() + +env[pathKey] = `${path.dirname(cargoPath)}${path.delimiter}${env[pathKey]}` +env[rustFlagsKey] = [env[rustFlagsKey], '-Zunstable-options', '-Cpanic=immediate-abort'] + .filter(Boolean) + .join(' ') +env[rustupToolchainKey] = wasmRustToolchain if (isMacOS) { const homebrewDir = env.HOMEBREW_DIR ?? '/opt/homebrew' @@ -42,9 +60,9 @@ if (isMacOS) { process.exit(1) // eslint-disable-line unicorn/no-process-exit } - if (!env.PATH.includes(llvmBinDir)) { + if (!env[pathKey].includes(llvmBinDir)) { // Add LLVM to PATH if not already included - env.PATH = `${llvmBinDir}:${env.PATH}` + env[pathKey] = `${llvmBinDir}${path.delimiter}${env[pathKey]}` } // Force C/C++ code (e.g. zstd-sys) to use Homebrew's clang for wasm32. Otherwise a global @@ -68,7 +86,7 @@ function buildWasm (cratePath, outputDirectory, options = {}) { const args = ['build'] if (profiling) args.push('--profiling') if (skipOptimization) args.push('--no-opt') - args.push('--target', 'nodejs', cratePath, '--out-dir', resolvedOutputDirectory) + args.push('--target', 'nodejs', cratePath, '--out-dir', resolvedOutputDirectory, '--', '-Z', 'build-std=std') childProcess.execFileSync('wasm-pack', args, { env: { ...env, diff --git a/wasm-rust-toolchain b/wasm-rust-toolchain new file mode 100644 index 00000000..ee9644bc --- /dev/null +++ b/wasm-rust-toolchain @@ -0,0 +1 @@ +nightly-2026-07-26