From 9ef95f2131186f9e7f45a87c9b68ab7a333b1841 Mon Sep 17 00:00:00 2001 From: Matthias Fechner Date: Sun, 23 Aug 2026 08:47:00 +0200 Subject: [PATCH 1/7] vp_js_runtime: add FreeBSD to the supported OS set vp_js_runtime's Os enum only lists Linux, Darwin, and Windows, and Os::current() has a compile_error! for any other target. FreeBSD is a legitimate target for the `vp` binary (the rest of the toolchain builds fine), so add a FreeBSD variant and route it through the same tar.gz + bin/node + bin/ conventions the other unix platforms use. Node.js publishes no official FreeBSD build, so on FreeBSD `vp` must not download a Node.js runtime at all: the only candidate in the standard dist layout is the Linux build, which segfaults on FreeBSD. Add a JsRuntimeProvider::is_download_supported() hook (default true) that NodeProvider answers with `platform.os != Os::FreeBSD`, and have download_runtime() honour it by falling back to a system-installed `node` (e.g. from the FreeBSD Ports lang/node or lang/node22) instead of attempting a download. If no system node is found, report a clear UnsupportedPlatform error rather than pulling a binary that will not work. The platform_string() token for FreeBSD is kept distinct from "linux" even though it is not used for any real download URL, so no code path can ever point at a Linux binary. Signed-off-by: Matthias Fechner --- crates/vp_js_runtime/src/platform.rs | 15 +++++- crates/vp_js_runtime/src/provider.rs | 12 +++++ crates/vp_js_runtime/src/providers/node.rs | 24 +++++++-- crates/vp_js_runtime/src/runtime.rs | 62 ++++++++++++++++++++++ 4 files changed, 108 insertions(+), 5 deletions(-) diff --git a/crates/vp_js_runtime/src/platform.rs b/crates/vp_js_runtime/src/platform.rs index eb986da1b4..c41e9f62ab 100644 --- a/crates/vp_js_runtime/src/platform.rs +++ b/crates/vp_js_runtime/src/platform.rs @@ -13,6 +13,7 @@ pub enum Os { Linux, Darwin, Windows, + FreeBSD, } /// CPU architecture @@ -59,10 +60,19 @@ impl Os { { Self::Windows } - #[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))] + #[cfg(target_os = "freebsd")] + { + Self::FreeBSD + } + #[cfg(not(any( + target_os = "linux", + target_os = "macos", + target_os = "windows", + target_os = "freebsd" + )))] { compile_error!( - "Unsupported operating system. vp_js_runtime only supports Linux, macOS, and Windows." + "Unsupported operating system. vp_js_runtime only supports Linux, macOS, Windows, and FreeBSD." ) } } @@ -74,6 +84,7 @@ impl fmt::Display for Os { Self::Linux => write!(f, "linux"), Self::Darwin => write!(f, "darwin"), Self::Windows => write!(f, "windows"), + Self::FreeBSD => write!(f, "freebsd"), } } } diff --git a/crates/vp_js_runtime/src/provider.rs b/crates/vp_js_runtime/src/provider.rs index fc8e02bcc4..51424f620c 100644 --- a/crates/vp_js_runtime/src/provider.rs +++ b/crates/vp_js_runtime/src/provider.rs @@ -102,4 +102,16 @@ pub trait JsRuntimeProvider: Send + Sync { /// /// Returns an error if the filename is not found in the SHASUMS content. fn parse_shasums(&self, shasums_content: &str, filename: &str) -> Result; + + /// Whether this provider has official builds available for the given platform. + /// + /// Platforms without official builds (e.g. FreeBSD for Node.js) should + /// return `false` so callers can fall back to a system-installed binary + /// instead of attempting a download that would 404 or pull in an + /// incompatible binary. + /// + /// The default implementation returns `true`. + fn is_download_supported(&self, _platform: Platform) -> bool { + true + } } diff --git a/crates/vp_js_runtime/src/providers/node.rs b/crates/vp_js_runtime/src/providers/node.rs index 29688dc70f..2a2eaf7dae 100644 --- a/crates/vp_js_runtime/src/providers/node.rs +++ b/crates/vp_js_runtime/src/providers/node.rs @@ -171,7 +171,7 @@ impl NodeProvider { const fn archive_format(platform: Platform) -> ArchiveFormat { match platform.os { Os::Windows => ArchiveFormat::Zip, - Os::Linux | Os::Darwin => ArchiveFormat::TarGz, + Os::Linux | Os::Darwin | Os::FreeBSD => ArchiveFormat::TarGz, } } @@ -599,6 +599,13 @@ impl JsRuntimeProvider for NodeProvider { Os::Linux => "linux", Os::Darwin => "darwin", Os::Windows => "win", + // Node.js publishes no official FreeBSD build, and `download_runtime` + // refuses to download a Node.js runtime on FreeBSD (see + // `is_download_supported`), falling back to a system-installed + // `node` instead. This token is therefore never used to build a + // real download URL, but it is kept distinct from `"linux"` so no + // code path could ever silently point at a Linux binary. + Os::FreeBSD => "freebsd", }; let arch = match platform.arch { crate::platform::Arch::X64 => "x64", @@ -653,14 +660,14 @@ impl JsRuntimeProvider for NodeProvider { fn binary_relative_path(&self, platform: Platform) -> Str { match platform.os { Os::Windows => "node.exe".into(), - Os::Linux | Os::Darwin => "bin/node".into(), + Os::Linux | Os::Darwin | Os::FreeBSD => "bin/node".into(), } } fn bin_dir_relative_path(&self, platform: Platform) -> Str { match platform.os { Os::Windows => "".into(), - Os::Linux | Os::Darwin => "bin".into(), + Os::Linux | Os::Darwin | Os::FreeBSD => "bin".into(), } } @@ -679,6 +686,17 @@ impl JsRuntimeProvider for NodeProvider { Err(Error::HashNotFound { filename: filename.into() }) } + + fn is_download_supported(&self, platform: Platform) -> bool { + // Node.js does not publish official FreeBSD builds. The + // `unofficial-builds.nodejs.org` site also lacks a FreeBSD + // platform, and the only way to get a node binary from the + // standard dist layout is the Linux build, which segfaults on + // FreeBSD. Return `false` so `download_runtime` falls back to a + // system-installed `node` (e.g. from the FreeBSD Ports + // `lang/node` or `lang/node22`) instead of attempting a download. + platform.os != Os::FreeBSD + } } #[cfg(test)] diff --git a/crates/vp_js_runtime/src/runtime.rs b/crates/vp_js_runtime/src/runtime.rs index 4ab54567c4..9194624287 100644 --- a/crates/vp_js_runtime/src/runtime.rs +++ b/crates/vp_js_runtime/src/runtime.rs @@ -17,6 +17,46 @@ use crate::{ providers::NodeProvider, }; +/// Look for a `node` executable on `PATH` and return its absolute path. +/// +/// Used as a fallback on platforms where the managed download is not +/// available (e.g. FreeBSD, where Node.js publishes no official build). +/// The returned path is the first `node` found scanning `PATH` directories, +/// excluding the Vite+ `node` shim (which canonicalises back to the running +/// `vp` executable). +/// +/// Returns `None` if no suitable binary is found. +fn find_system_node() -> Option { + let path = std::env::var_os("PATH")?; + for dir in std::env::split_paths(&path) { + let candidate = dir.join("node"); + let Ok(meta) = std::fs::metadata(&candidate) else { + continue; + }; + if !meta.is_file() { + continue; + } + // Skip Vite+ shims. The codebase's own `shim::find_system_tool` + // canonicalizes the candidate and treats it as a shim when the result + // resolves back to the `vp` executable (or is a Windows trampoline). + // Mirror that here without pulling in `vp_shared`: a `node` that is a + // Vite+ shim either *is* the current executable (symlinked into PATH + // by `vp env setup`) or canonicalises to it; a real `node` from + // FreeBSD Ports (lang/node, lang/node22, …) resolves somewhere else. + let canonical = candidate.canonicalize().ok(); + if let Some(self_real) = std::env::current_exe().ok().and_then(|exe| exe.canonicalize().ok()) + { + if canonical.as_ref() == Some(&self_real) { + continue; + } + } + if let Some(abs) = AbsolutePathBuf::new(candidate.to_path_buf()) { + return Some(abs); + } + } + None +} + /// Supported JavaScript runtime types #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum JsRuntimeType { @@ -113,6 +153,28 @@ pub async fn download_runtime( match runtime_type { JsRuntimeType::Node => { let provider = NodeProvider::new(); + // If this platform has no managed download available (e.g. FreeBSD, + // where Node.js publishes no official build), fall back to the + // system-installed `node` binary instead of attempting a download + // that would pull an incompatible binary (e.g. a Linux build that + // segfaults on FreeBSD). + if !provider.is_download_supported(Platform::current()) { + match find_system_node() { + Some(bin) => { + tracing::info!( + "No managed Node.js download for this platform; \ + using system node at {bin:?}" + ); + return Ok(JsRuntime::from_system(JsRuntimeType::Node, bin)); + } + None => { + return Err(Error::UnsupportedPlatform { + platform: Platform::current().to_string().into(), + runtime: "node".into(), + }) + } + } + } download_runtime_with_provider(&provider, JsRuntimeType::Node, version).await } } From 376cc8b94e2d3bfdb926e66195b1338a22dcc044 Mon Sep 17 00:00:00 2001 From: MK Date: Tue, 13 Oct 2026 21:00:30 +0800 Subject: [PATCH 2/7] feat: publish experimental FreeBSD x64 artifacts --- .github/workflows/reusable-release-build.yml | 112 +++++++++++++++++++ crates/vp_js_runtime/src/runtime.rs | 5 +- crates/vp_setup/src/platform.rs | 7 +- crates/vp_setup/src/registry.rs | 2 + docs/guide/index.md | 1 + packages/cli/install.sh | 1 + packages/cli/package.json | 1 + 7 files changed, 126 insertions(+), 3 deletions(-) diff --git a/.github/workflows/reusable-release-build.yml b/.github/workflows/reusable-release-build.yml index aca6f03482..1b52421a35 100644 --- a/.github/workflows/reusable-release-build.yml +++ b/.github/workflows/reusable-release-build.yml @@ -261,3 +261,115 @@ jobs: ./packages/core/LICENSE ./packages/cli/LICENSE if-no-files-found: error + + build-freebsd: + name: Build (x86_64-unknown-freebsd) + runs-on: ubuntu-latest + permissions: + contents: read + env: + VERSION: ${{ inputs.version }} + VITE_PLUS_DOCS_ORIGIN: ${{ inputs.docs-origin }} + RUSTUP_IO_THREADS: '1' + steps: + - uses: taiki-e/checkout-action@7d1e50e93dc4fb3bba58f85018fadf77898aee8b # v1.4.2 + - uses: ./.github/actions/clone + + - name: Set build version + run: | + for f in crates/vp_global_cli/Cargo.toml packages/cli/binding/Cargo.toml; do + node -e 'const fs=require("fs"),f=process.argv[1];fs.writeFileSync(f,fs.readFileSync(f,"utf8").replace(/^version = "[^"]*"/m,`version = "${process.env.VERSION}"`))' "$f" + done + + # Match Rolldown's native FreeBSD build. Build JS on Linux and only + # compile the CLI and merged NAPI binding inside the VM. + - name: Build and test FreeBSD binaries + uses: cross-platform-actions/action@e0b9770014ba65d5e0815f15b74031c3a635f641 # v1.6.0 + with: + operating_system: freebsd + version: '15.0' + memory: 8G + cpu_count: 3 + environment_variables: 'VERSION VITE_PLUS_DOCS_ORIGIN RUSTUP_IO_THREADS' + shell: bash + run: | + set -euo pipefail + sudo pkg install -y curl git node24 cmake pkgconf + curl -fsSL https://sh.rustup.rs -o /tmp/vp-rustup.sh + sh /tmp/vp-rustup.sh -y --profile minimal --default-toolchain none + source "$HOME/.cargo/env" + rustup toolchain install --profile minimal + cargo update --workspace + + # Keep intermediate files outside the workspace that the VM syncs. + build_dir=$(mktemp -d) + cargo build --locked --release --target x86_64-unknown-freebsd \ + --target-dir "$build_dir" -p vp_global_cli -p vite-plus-cli \ + --features vite-plus-cli/rolldown + cargo test --locked --release --target x86_64-unknown-freebsd \ + --target-dir "$build_dir" -p vp_js_runtime -p vp_setup platform + + mkdir -p target/x86_64-unknown-freebsd/release + cp "$build_dir/x86_64-unknown-freebsd/release/vp" target/x86_64-unknown-freebsd/release/vp + cp "$build_dir/x86_64-unknown-freebsd/release/libvite_plus_cli.so" packages/cli/binding/vite-plus.freebsd-x64.node + node -e 'const assert=require("node:assert/strict"),binding=require("./packages/cli/binding/vite-plus.freebsd-x64.node");assert.equal(typeof binding.run,"function");assert.equal(typeof binding.BindingBundler,"function")' + + # Exercise the installer and system Node.js fallback without + # downloading this release's not-yet-published npm packages. + export VP_HOME="$(mktemp -d)" + local_tgz=$(mktemp) + VP_LOCAL_BINARY="$PWD/target/x86_64-unknown-freebsd/release/vp" \ + VP_LOCAL_TGZ="$local_tgz" VP_SELF_SETUP_NO_MODIFY_PATH=1 \ + VP_VERSION="$VERSION" VP_SKIP_DEPS_INSTALL=1 \ + VP_NODE_MANAGER=no VP_PM_MANAGER=no bash packages/cli/install.sh + "$VP_HOME/bin/vp" --version + "$VP_HOME/bin/vp" node -e 'if (process.platform !== "freebsd") process.exit(1)' + + - name: Upload Vite+ native artifact + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: vite-plus-native-x86_64-unknown-freebsd + path: packages/cli/binding/vite-plus.freebsd-x64.node + if-no-files-found: error + + - name: Upload Rust CLI binary artifact + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: vp-global-cli-x86_64-unknown-freebsd + path: target/x86_64-unknown-freebsd/release/vp + if-no-files-found: error + + package-freebsd: + name: Package FreeBSD release archive + needs: [build-rust, build-freebsd] + runs-on: ubuntu-latest + permissions: + contents: read + steps: + - name: Download Rust CLI binary + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: vp-global-cli-x86_64-unknown-freebsd + path: target/x86_64-unknown-freebsd/release + + - name: Download cli dist + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: cli + path: packages/cli/dist + + - name: Package release archive + working-directory: target/x86_64-unknown-freebsd/release + run: | + chmod +x vp + mkdir -p sync-versions + cp ../../../packages/cli/dist/sync-versions/bin.mjs sync-versions/bin.mjs + cp ../../../packages/cli/dist/toolchain.json toolchain.json + tar -czf vp-x86_64-unknown-freebsd.tar.gz vp sync-versions/bin.mjs toolchain.json + + - name: Upload release archive + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: vp-release-archive-x86_64-unknown-freebsd + path: target/x86_64-unknown-freebsd/release/vp-x86_64-unknown-freebsd.tar.gz + if-no-files-found: error diff --git a/crates/vp_js_runtime/src/runtime.rs b/crates/vp_js_runtime/src/runtime.rs index 9194624287..3a68716d34 100644 --- a/crates/vp_js_runtime/src/runtime.rs +++ b/crates/vp_js_runtime/src/runtime.rs @@ -44,7 +44,8 @@ fn find_system_node() -> Option { // by `vp env setup`) or canonicalises to it; a real `node` from // FreeBSD Ports (lang/node, lang/node22, …) resolves somewhere else. let canonical = candidate.canonicalize().ok(); - if let Some(self_real) = std::env::current_exe().ok().and_then(|exe| exe.canonicalize().ok()) + if let Some(self_real) = + std::env::current_exe().ok().and_then(|exe| exe.canonicalize().ok()) { if canonical.as_ref() == Some(&self_real) { continue; @@ -171,7 +172,7 @@ pub async fn download_runtime( return Err(Error::UnsupportedPlatform { platform: Platform::current().to_string().into(), runtime: "node".into(), - }) + }); } } } diff --git a/crates/vp_setup/src/platform.rs b/crates/vp_setup/src/platform.rs index 5283e51e59..b8351f007a 100644 --- a/crates/vp_setup/src/platform.rs +++ b/crates/vp_setup/src/platform.rs @@ -7,7 +7,7 @@ use crate::error::Error; /// Detect the current platform suffix for npm package naming. /// -/// Returns strings like `darwin-arm64`, `linux-x64-gnu`, `linux-arm64-musl`, `win32-x64-msvc`. +/// Returns strings like `darwin-arm64`, `linux-x64-gnu`, `freebsd-x64`, `win32-x64-msvc`. pub fn detect_platform_suffix() -> Result { let os_name = if cfg!(target_os = "macos") { "darwin" @@ -15,6 +15,8 @@ pub fn detect_platform_suffix() -> Result { "linux" } else if cfg!(target_os = "windows") { "win32" + } else if cfg!(target_os = "freebsd") { + "freebsd" } else { return Err(Error::Setup( format!("Unsupported operating system: {}", std::env::consts::OS).into(), @@ -71,5 +73,8 @@ mod tests { #[cfg(all(target_os = "windows", target_arch = "x86_64"))] assert_eq!(suffix, "win32-x64-msvc"); + + #[cfg(all(target_os = "freebsd", target_arch = "x86_64"))] + assert_eq!(suffix, "freebsd-x64"); } } diff --git a/crates/vp_setup/src/registry.rs b/crates/vp_setup/src/registry.rs index 62d8697702..59fda1af06 100644 --- a/crates/vp_setup/src/registry.rs +++ b/crates/vp_setup/src/registry.rs @@ -382,6 +382,7 @@ mod tests { let published_suffixes = [ "darwin-arm64", "darwin-x64", + "freebsd-x64", "linux-arm64-gnu", "linux-arm64-musl", "linux-x64-gnu", @@ -399,6 +400,7 @@ mod tests { let detection_suffixes = [ "darwin-arm64", "darwin-x64", + "freebsd-x64", "linux-arm64-gnu", "linux-x64-gnu", "linux-arm64-musl", diff --git a/docs/guide/index.md b/docs/guide/index.md index 18dbdbd793..2e3faf1db2 100644 --- a/docs/guide/index.md +++ b/docs/guide/index.md @@ -62,6 +62,7 @@ Prebuilt binaries are distributed for the following platforms (grouped by [Node. - Windows arm64 (`aarch64-pc-windows-msvc`) - Experimental - Linux x64 musl (`x86_64-unknown-linux-musl`) + - FreeBSD x64 (`x86_64-unknown-freebsd`) - Other - Linux arm64 musl (`aarch64-unknown-linux-musl`) diff --git a/packages/cli/install.sh b/packages/cli/install.sh index 0200b13018..b89a0a71d3 100644 --- a/packages/cli/install.sh +++ b/packages/cli/install.sh @@ -190,6 +190,7 @@ detect_platform() { case "$os" in Darwin) os="darwin" ;; Linux) os="linux" ;; + FreeBSD) os="freebsd" ;; MINGW*|MSYS*|CYGWIN*) os="win32" ;; *) error "Unsupported operating system: $os" ;; esac diff --git a/packages/cli/package.json b/packages/cli/package.json index 185b900ed6..631f93d355 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -417,6 +417,7 @@ "aarch64-unknown-linux-musl", "x86_64-unknown-linux-gnu", "x86_64-unknown-linux-musl", + "x86_64-unknown-freebsd", "x86_64-pc-windows-msvc", "aarch64-pc-windows-msvc" ] From f274c977b7480631b8b26cf9bb40b2bf5f5e8c18 Mon Sep 17 00:00:00 2001 From: MK Date: Tue, 13 Oct 2026 21:06:20 +0800 Subject: [PATCH 3/7] fix: exclude unsupported file tracking on FreeBSD --- .github/workflows/reusable-release-build.yml | 19 ++++++- crates/vp_command/Cargo.toml | 6 ++- crates/vp_command/src/lib.rs | 9 +++- packages/cli/binding/Cargo.toml | 4 +- packages/cli/binding/src/utils.rs | 53 +++++++++++++------- 5 files changed, 68 insertions(+), 23 deletions(-) diff --git a/.github/workflows/reusable-release-build.yml b/.github/workflows/reusable-release-build.yml index 1b52421a35..b7b31ebe48 100644 --- a/.github/workflows/reusable-release-build.yml +++ b/.github/workflows/reusable-release-build.yml @@ -312,7 +312,24 @@ jobs: mkdir -p target/x86_64-unknown-freebsd/release cp "$build_dir/x86_64-unknown-freebsd/release/vp" target/x86_64-unknown-freebsd/release/vp cp "$build_dir/x86_64-unknown-freebsd/release/libvite_plus_cli.so" packages/cli/binding/vite-plus.freebsd-x64.node - node -e 'const assert=require("node:assert/strict"),binding=require("./packages/cli/binding/vite-plus.freebsd-x64.node");assert.equal(typeof binding.run,"function");assert.equal(typeof binding.BindingBundler,"function")' + node <<'JS' + const assert = require('node:assert/strict'); + const binding = require('./packages/cli/binding/vite-plus.freebsd-x64.node'); + assert.equal(typeof binding.run, 'function'); + assert.equal(typeof binding.BindingBundler, 'function'); + binding.runCommand({ + binName: process.execPath, + args: ['-e', 'process.exit(7)'], + envs: {}, + cwd: process.cwd(), + }).then((result) => { + assert.equal(result.exitCode, 7); + assert.deepEqual(result.pathAccesses, {}); + }).catch((error) => { + console.error(error); + process.exitCode = 1; + }); + JS # Exercise the installer and system Node.js fallback without # downloading this release's not-yet-published npm packages. diff --git a/crates/vp_command/Cargo.toml b/crates/vp_command/Cargo.toml index 3c462d477c..88c7746ec0 100644 --- a/crates/vp_command/Cargo.toml +++ b/crates/vp_command/Cargo.toml @@ -8,9 +8,7 @@ publish = false rust-version.workspace = true [dependencies] -fspy = { workspace = true } tokio = { workspace = true } -tokio-util = { workspace = true } tracing = { workspace = true } vp_error = { workspace = true } vt_path = { workspace = true } @@ -18,6 +16,10 @@ vt_powershell = { workspace = true } vp_shared = { workspace = true } which = { workspace = true, features = ["tracing"] } +[target.'cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))'.dependencies] +fspy = { workspace = true } +tokio-util = { workspace = true } + [target.'cfg(not(target_os = "windows"))'.dependencies] nix = { workspace = true, features = ["signal", "term"] } diff --git a/crates/vp_command/src/lib.rs b/crates/vp_command/src/lib.rs index 7f6ebd6099..f4bdd30611 100644 --- a/crates/vp_command/src/lib.rs +++ b/crates/vp_command/src/lib.rs @@ -13,17 +13,22 @@ use std::{ process::{ExitStatus, Stdio}, }; +#[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))] use fspy::AccessMode; use tokio::process::Command; +#[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))] use tokio_util::sync::CancellationToken; use vp_error::Error; -use vt_path::{AbsolutePath, AbsolutePathBuf, RelativePathBuf}; +#[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))] +use vt_path::RelativePathBuf; +use vt_path::{AbsolutePath, AbsolutePathBuf}; mod ps1_shim; pub use ps1_shim::rewrite_cmd_to_powershell; /// Result of running a command with fspy tracking. +#[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))] #[derive(Debug)] pub struct FspyCommandResult { /// The termination status of the command. @@ -215,6 +220,7 @@ where /// # Returns /// /// Returns a `FspyCommandResult` containing the exit status and path accesses. +#[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))] pub async fn run_command_with_fspy( bin_name: &str, args: I, @@ -570,6 +576,7 @@ mod tests { } } + #[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))] mod run_command_with_fspy_tests { use super::*; diff --git a/packages/cli/binding/Cargo.toml b/packages/cli/binding/Cargo.toml index 8c3614b148..319ecf4c9f 100644 --- a/packages/cli/binding/Cargo.toml +++ b/packages/cli/binding/Cargo.toml @@ -17,7 +17,6 @@ async-trait = { workspace = true } base64-simd = { workspace = true } clap = { workspace = true, features = ["derive"] } cow-utils = { workspace = true } -fspy = { workspace = true } rustc-hash = { workspace = true } napi = { workspace = true } napi-derive = { workspace = true } @@ -45,6 +44,9 @@ vt_workspace = { workspace = true } rolldown_binding = { workspace = true, optional = true, features = ["disable_panic_hook"] } oxc-node = { workspace = true, optional = true } +[target.'cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))'.dependencies] +fspy = { workspace = true } + [build-dependencies] napi-build = { workspace = true } diff --git a/packages/cli/binding/src/utils.rs b/packages/cli/binding/src/utils.rs index 27f354b159..463bf0b978 100644 --- a/packages/cli/binding/src/utils.rs +++ b/packages/cli/binding/src/utils.rs @@ -1,8 +1,10 @@ use std::{collections::HashMap, path::PathBuf}; +#[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))] use fspy::AccessMode; use napi::{anyhow, bindgen_prelude::*}; use napi_derive::napi; +#[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))] use vp_command::run_command_with_fspy; use vt_path::AbsolutePathBuf; @@ -63,6 +65,7 @@ pub struct RunCommandResult { /// This function wraps `vp_command::run_command_with_fspy` to provide /// a JavaScript-friendly interface for executing commands and tracking /// their file system accesses. +/// On platforms without file tracking, it runs the command and returns no path accesses. /// /// ## Parameters /// @@ -101,25 +104,39 @@ pub async fn run_command(options: RunCommandOptions) -> Result // Convert args from Vec to Vec<&str> let args: Vec<&str> = options.args.iter().map(|s| s.as_str()).collect(); - // Call the core run_command_with_fspy function - let result = run_command_with_fspy(&options.bin_name, &args, &options.envs, &cwd) - .await - .map_err(anyhow::Error::from)?; - - // Convert path accesses to JavaScript-friendly format - let mut path_accesses = HashMap::new(); - for (path, mode) in result.path_accesses { - path_accesses.insert( - path.as_str().to_string(), - PathAccess { - read: mode.contains(AccessMode::READ), - write: mode.contains(AccessMode::WRITE), - read_dir: mode.contains(AccessMode::READ_DIR), - }, - ); + #[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))] + { + let status = vp_command::run_command(&options.bin_name, &args, &options.envs, &cwd) + .await + .map_err(anyhow::Error::from)?; + Ok(RunCommandResult { + exit_code: vp_shared::exit_code_from_status(status), + path_accesses: HashMap::new(), + }) } - let exit_code = vp_shared::exit_code_from_status(result.status); + #[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))] + { + // Call the core run_command_with_fspy function + let result = run_command_with_fspy(&options.bin_name, &args, &options.envs, &cwd) + .await + .map_err(anyhow::Error::from)?; + + // Convert path accesses to JavaScript-friendly format + let mut path_accesses = HashMap::new(); + for (path, mode) in result.path_accesses { + path_accesses.insert( + path.as_str().to_string(), + PathAccess { + read: mode.contains(AccessMode::READ), + write: mode.contains(AccessMode::WRITE), + read_dir: mode.contains(AccessMode::READ_DIR), + }, + ); + } - Ok(RunCommandResult { exit_code, path_accesses }) + let exit_code = vp_shared::exit_code_from_status(result.status); + + Ok(RunCommandResult { exit_code, path_accesses }) + } } From 1819cc564ffcac08d1b8a7f3ab02fa5253d7740d Mon Sep 17 00:00:00 2001 From: MK Date: Tue, 13 Oct 2026 21:15:38 +0800 Subject: [PATCH 4/7] refactor: build FreeBSD in the release matrix --- .github/workflows/reusable-release-build.yml | 224 +++++++------------ 1 file changed, 87 insertions(+), 137 deletions(-) diff --git a/.github/workflows/reusable-release-build.yml b/.github/workflows/reusable-release-build.yml index b7b31ebe48..1e47237f73 100644 --- a/.github/workflows/reusable-release-build.yml +++ b/.github/workflows/reusable-release-build.yml @@ -47,6 +47,8 @@ jobs: os: ubuntu-latest - target: x86_64-unknown-linux-musl os: ubuntu-latest + - target: x86_64-unknown-freebsd + os: ubuntu-latest - target: x86_64-pc-windows-msvc os: namespace-profile-windows-4c-8g - target: aarch64-pc-windows-msvc @@ -55,16 +57,12 @@ jobs: - uses: taiki-e/checkout-action@7d1e50e93dc4fb3bba58f85018fadf77898aee8b # v1.4.2 - uses: ./.github/actions/clone - uses: ./.github/actions/setup-rust + if: matrix.settings.target != 'x86_64-unknown-freebsd' with: save-cache: ${{ github.ref_name == 'main' }} cache-key: ${{ inputs.cache-key }} - - name: Rustup Adds Target - run: rustup target add ${{ matrix.settings.target }} - - - uses: oxc-project/setup-node@1f1a5b4450c8905bd1830c3a908d22b960c4559a # main (Node before pnpm; unreleased) - - - name: Set build version + - name: Set native build version shell: bash run: | set -euo pipefail @@ -76,9 +74,89 @@ jobs: # shellcheck disable=SC2016 # JavaScript expands process.env.VERSION. node -e 'const fs=require("fs"),f=process.argv[1];fs.writeFileSync(f,fs.readFileSync(f,"utf8").replace(/^version = "[^"]*"/m,`version = "${process.env.VERSION}"`))' "$f" done - # Keep the workspace package entries in Cargo.lock consistent with - # the stamped versions before later commands use --locked. + + # Build before installing host dependencies so the VM only syncs source + # files. The shared build step later builds JavaScript on the Linux host. + - name: Build and test FreeBSD binaries + if: matrix.settings.target == 'x86_64-unknown-freebsd' + env: + RUSTUP_IO_THREADS: '1' + uses: cross-platform-actions/action@e0b9770014ba65d5e0815f15b74031c3a635f641 # v1.6.0 + with: + operating_system: freebsd + version: '15.0' + memory: 8G + cpu_count: 3 + environment_variables: 'VERSION VITE_PLUS_DOCS_ORIGIN RUSTUP_IO_THREADS' + shell: bash + run: | + set -euo pipefail + sudo pkg install -y curl git node24 cmake pkgconf jq + curl -fsSL https://sh.rustup.rs -o /tmp/vp-rustup.sh + sh /tmp/vp-rustup.sh -y --profile minimal --default-toolchain none + source "$HOME/.cargo/env" + rustup toolchain install --profile minimal + cargo update --workspace + + # Keep intermediate files outside the workspace that the VM syncs. + build_dir=$(mktemp -d) + cargo build --locked --release --target x86_64-unknown-freebsd \ + --target-dir "$build_dir" -p vp_global_cli -p vite-plus-cli \ + --features vite-plus-cli/rolldown + cargo test --locked --release --target x86_64-unknown-freebsd \ + --target-dir "$build_dir" -p vp_js_runtime -p vp_setup platform + + mkdir -p target/x86_64-unknown-freebsd/release + cp "$build_dir/x86_64-unknown-freebsd/release/vp" target/x86_64-unknown-freebsd/release/vp + cp "$build_dir/x86_64-unknown-freebsd/release/libvite_plus_cli.so" packages/cli/binding/vite-plus.freebsd-x64.node + cargo metadata --locked --format-version 1 \ + | jq '{packages: [.packages[] | {name, version, source}]}' \ + > packages/cli/binding/vite-plus.cargo-metadata.json + node <<'JS' + const assert = require('node:assert/strict'); + const binding = require('./packages/cli/binding/vite-plus.freebsd-x64.node'); + assert.equal(typeof binding.run, 'function'); + assert.equal(typeof binding.BindingBundler, 'function'); + binding.runCommand({ + binName: process.execPath, + args: ['-e', 'process.exit(7)'], + envs: {}, + cwd: process.cwd(), + }).then((result) => { + assert.equal(result.exitCode, 7); + assert.deepEqual(result.pathAccesses, {}); + }).catch((error) => { + console.error(error); + process.exitCode = 1; + }); + JS + + # Exercise the installer and system Node.js fallback without + # downloading this release's not-yet-published npm packages. + VP_HOME=$(mktemp -d) + export VP_HOME + local_tgz=$(mktemp) + VP_LOCAL_BINARY="$PWD/target/x86_64-unknown-freebsd/release/vp" \ + VP_LOCAL_TGZ="$local_tgz" VP_SELF_SETUP_NO_MODIFY_PATH=1 \ + VP_VERSION="$VERSION" VP_SKIP_DEPS_INSTALL=1 \ + VP_NODE_MANAGER=no VP_PM_MANAGER=no bash packages/cli/install.sh + "$VP_HOME/bin/vp" --version + "$VP_HOME/bin/vp" node -e 'if (process.platform !== "freebsd") process.exit(1)' + + - name: Prepare Rust build + if: matrix.settings.target != 'x86_64-unknown-freebsd' + shell: bash + run: | + rustup target add ${{ matrix.settings.target }} + # Keep Cargo.lock consistent with the stamped package versions. cargo update --workspace + + - uses: oxc-project/setup-node@1f1a5b4450c8905bd1830c3a908d22b960c4559a # main (Node before pnpm; unreleased) + + - name: Set JavaScript build version + shell: bash + run: | + set -euo pipefail # Stamp the package.json files too: # - packages/cli: the bundled JS dist inlines ${VERSION} as # cliPkg.version (VITE_PLUS_VERSION). Without this a preview @@ -117,6 +195,7 @@ jobs: uses: ./.github/actions/build-upstream with: target: ${{ matrix.settings.target }} + skip-native: ${{ matrix.settings.target == 'x86_64-unknown-freebsd' }} - name: Upload Vite+ native artifact uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 @@ -261,132 +340,3 @@ jobs: ./packages/core/LICENSE ./packages/cli/LICENSE if-no-files-found: error - - build-freebsd: - name: Build (x86_64-unknown-freebsd) - runs-on: ubuntu-latest - permissions: - contents: read - env: - VERSION: ${{ inputs.version }} - VITE_PLUS_DOCS_ORIGIN: ${{ inputs.docs-origin }} - RUSTUP_IO_THREADS: '1' - steps: - - uses: taiki-e/checkout-action@7d1e50e93dc4fb3bba58f85018fadf77898aee8b # v1.4.2 - - uses: ./.github/actions/clone - - - name: Set build version - run: | - for f in crates/vp_global_cli/Cargo.toml packages/cli/binding/Cargo.toml; do - node -e 'const fs=require("fs"),f=process.argv[1];fs.writeFileSync(f,fs.readFileSync(f,"utf8").replace(/^version = "[^"]*"/m,`version = "${process.env.VERSION}"`))' "$f" - done - - # Match Rolldown's native FreeBSD build. Build JS on Linux and only - # compile the CLI and merged NAPI binding inside the VM. - - name: Build and test FreeBSD binaries - uses: cross-platform-actions/action@e0b9770014ba65d5e0815f15b74031c3a635f641 # v1.6.0 - with: - operating_system: freebsd - version: '15.0' - memory: 8G - cpu_count: 3 - environment_variables: 'VERSION VITE_PLUS_DOCS_ORIGIN RUSTUP_IO_THREADS' - shell: bash - run: | - set -euo pipefail - sudo pkg install -y curl git node24 cmake pkgconf - curl -fsSL https://sh.rustup.rs -o /tmp/vp-rustup.sh - sh /tmp/vp-rustup.sh -y --profile minimal --default-toolchain none - source "$HOME/.cargo/env" - rustup toolchain install --profile minimal - cargo update --workspace - - # Keep intermediate files outside the workspace that the VM syncs. - build_dir=$(mktemp -d) - cargo build --locked --release --target x86_64-unknown-freebsd \ - --target-dir "$build_dir" -p vp_global_cli -p vite-plus-cli \ - --features vite-plus-cli/rolldown - cargo test --locked --release --target x86_64-unknown-freebsd \ - --target-dir "$build_dir" -p vp_js_runtime -p vp_setup platform - - mkdir -p target/x86_64-unknown-freebsd/release - cp "$build_dir/x86_64-unknown-freebsd/release/vp" target/x86_64-unknown-freebsd/release/vp - cp "$build_dir/x86_64-unknown-freebsd/release/libvite_plus_cli.so" packages/cli/binding/vite-plus.freebsd-x64.node - node <<'JS' - const assert = require('node:assert/strict'); - const binding = require('./packages/cli/binding/vite-plus.freebsd-x64.node'); - assert.equal(typeof binding.run, 'function'); - assert.equal(typeof binding.BindingBundler, 'function'); - binding.runCommand({ - binName: process.execPath, - args: ['-e', 'process.exit(7)'], - envs: {}, - cwd: process.cwd(), - }).then((result) => { - assert.equal(result.exitCode, 7); - assert.deepEqual(result.pathAccesses, {}); - }).catch((error) => { - console.error(error); - process.exitCode = 1; - }); - JS - - # Exercise the installer and system Node.js fallback without - # downloading this release's not-yet-published npm packages. - export VP_HOME="$(mktemp -d)" - local_tgz=$(mktemp) - VP_LOCAL_BINARY="$PWD/target/x86_64-unknown-freebsd/release/vp" \ - VP_LOCAL_TGZ="$local_tgz" VP_SELF_SETUP_NO_MODIFY_PATH=1 \ - VP_VERSION="$VERSION" VP_SKIP_DEPS_INSTALL=1 \ - VP_NODE_MANAGER=no VP_PM_MANAGER=no bash packages/cli/install.sh - "$VP_HOME/bin/vp" --version - "$VP_HOME/bin/vp" node -e 'if (process.platform !== "freebsd") process.exit(1)' - - - name: Upload Vite+ native artifact - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 - with: - name: vite-plus-native-x86_64-unknown-freebsd - path: packages/cli/binding/vite-plus.freebsd-x64.node - if-no-files-found: error - - - name: Upload Rust CLI binary artifact - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 - with: - name: vp-global-cli-x86_64-unknown-freebsd - path: target/x86_64-unknown-freebsd/release/vp - if-no-files-found: error - - package-freebsd: - name: Package FreeBSD release archive - needs: [build-rust, build-freebsd] - runs-on: ubuntu-latest - permissions: - contents: read - steps: - - name: Download Rust CLI binary - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 - with: - name: vp-global-cli-x86_64-unknown-freebsd - path: target/x86_64-unknown-freebsd/release - - - name: Download cli dist - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 - with: - name: cli - path: packages/cli/dist - - - name: Package release archive - working-directory: target/x86_64-unknown-freebsd/release - run: | - chmod +x vp - mkdir -p sync-versions - cp ../../../packages/cli/dist/sync-versions/bin.mjs sync-versions/bin.mjs - cp ../../../packages/cli/dist/toolchain.json toolchain.json - tar -czf vp-x86_64-unknown-freebsd.tar.gz vp sync-versions/bin.mjs toolchain.json - - - name: Upload release archive - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 - with: - name: vp-release-archive-x86_64-unknown-freebsd - path: target/x86_64-unknown-freebsd/release/vp-x86_64-unknown-freebsd.tar.gz - if-no-files-found: error From 9b37193b23e810a403b578a9bf2636820ea6e95b Mon Sep 17 00:00:00 2001 From: MK Date: Tue, 13 Oct 2026 21:22:19 +0800 Subject: [PATCH 5/7] fix: use the FreeBSD runtime fallback in Node shims --- .github/workflows/reusable-release-build.yml | 5 +++-- crates/vp_global_cli/src/shim/dispatch.rs | 5 +++-- crates/vp_js_runtime/src/providers/node.rs | 12 ++++++++++++ packages/cli/binding/index.d.cts | 1 + 4 files changed, 19 insertions(+), 4 deletions(-) diff --git a/.github/workflows/reusable-release-build.yml b/.github/workflows/reusable-release-build.yml index 1e47237f73..2f9561f344 100644 --- a/.github/workflows/reusable-release-build.yml +++ b/.github/workflows/reusable-release-build.yml @@ -139,9 +139,10 @@ jobs: VP_LOCAL_BINARY="$PWD/target/x86_64-unknown-freebsd/release/vp" \ VP_LOCAL_TGZ="$local_tgz" VP_SELF_SETUP_NO_MODIFY_PATH=1 \ VP_VERSION="$VERSION" VP_SKIP_DEPS_INSTALL=1 \ - VP_NODE_MANAGER=no VP_PM_MANAGER=no bash packages/cli/install.sh + VP_NODE_MANAGER=yes VP_PM_MANAGER=no bash packages/cli/install.sh "$VP_HOME/bin/vp" --version - "$VP_HOME/bin/vp" node -e 'if (process.platform !== "freebsd") process.exit(1)' + PATH="$VP_HOME/bin:$PATH" VP_NODE_VERSION=24.11.0 \ + "$VP_HOME/bin/node" -e 'if (process.platform !== "freebsd") process.exit(1)' - name: Prepare Rust build if: matrix.settings.target != 'x86_64-unknown-freebsd' diff --git a/crates/vp_global_cli/src/shim/dispatch.rs b/crates/vp_global_cli/src/shim/dispatch.rs index 90a9429928..2f9ac81717 100644 --- a/crates/vp_global_cli/src/shim/dispatch.rs +++ b/crates/vp_global_cli/src/shim/dispatch.rs @@ -1235,10 +1235,11 @@ pub(crate) async fn ensure_installed(version: &str) -> Result; * This function wraps `vp_command::run_command_with_fspy` to provide * a JavaScript-friendly interface for executing commands and tracking * their file system accesses. + * On platforms without file tracking, it runs the command and returns no path accesses. * * ## Parameters * From 94496f1717c929b57ed119839fac537da8712c92 Mon Sep 17 00:00:00 2001 From: MK Date: Tue, 13 Oct 2026 21:39:30 +0800 Subject: [PATCH 6/7] test: cover FreeBSD native binding rewrites --- .../fixtures/rolldown-binding-loader.txt | 10 +++++++- .../rewrite-rolldown-binding.spec.ts | 24 +++++++++---------- 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/packages/core/__tests__/fixtures/rolldown-binding-loader.txt b/packages/core/__tests__/fixtures/rolldown-binding-loader.txt index fb50881d20..327f3d31cc 100644 --- a/packages/core/__tests__/fixtures/rolldown-binding-loader.txt +++ b/packages/core/__tests__/fixtures/rolldown-binding-loader.txt @@ -66,7 +66,7 @@ var require_webcontainer_fallback = /* @__PURE__ */ __commonJSMin(((exports, mod } // #endregion -// #region freebsd-x64 branch (unsupported platform) +// #region freebsd-x64 branch (supported platform) try { const binding = __require("@rolldown/binding-freebsd-x64"); const bindingPackageVersion = __require("@rolldown/binding-freebsd-x64/package.json").version; @@ -81,6 +81,14 @@ var require_webcontainer_fallback = /* @__PURE__ */ __commonJSMin(((exports, mod } catch (e) { loadErrors.push(e); } + try { + const binding = __require("@rolldown/binding-freebsd-arm64"); + const bindingPackageVersion = __require("@rolldown/binding-freebsd-arm64/package.json").version; + if (bindingPackageVersion !== "1.2.1" && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== "0") throw new Error(`Native binding package version mismatch, expected 1.2.1 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`); + return binding; + } catch (e) { + loadErrors.push(e); + } // #endregion // #region linux-x64-musl branch (supported platform) diff --git a/packages/core/__tests__/rewrite-rolldown-binding.spec.ts b/packages/core/__tests__/rewrite-rolldown-binding.spec.ts index 136088e57f..09ea84bbb4 100644 --- a/packages/core/__tests__/rewrite-rolldown-binding.spec.ts +++ b/packages/core/__tests__/rewrite-rolldown-binding.spec.ts @@ -22,6 +22,7 @@ const PACKAGE_NAME = '@voidzero-dev/vite-plus'; const platformSuffixes = new Set([ 'darwin-arm64', 'darwin-x64', + 'freebsd-x64', 'linux-arm64-gnu', 'linux-arm64-musl', 'linux-x64-gnu', @@ -40,9 +41,8 @@ describe('rewriteRolldownBindingRequires', () => { }); it('rewrites supported platform branches to Vite+ platform packages', () => { - // Fixture contains three supported branches: darwin-x64, darwin-arm64, - // linux-x64-musl. Each requires the package and its package.json. - for (const suffix of ['darwin-x64', 'darwin-arm64', 'linux-x64-musl']) { + // Each supported branch requires the package and its package.json. + for (const suffix of ['darwin-x64', 'darwin-arm64', 'freebsd-x64', 'linux-x64-musl']) { expect(result.source).toContain(`__require("@voidzero-dev/vite-plus-${suffix}")`); expect(result.source).toContain( `__require("@voidzero-dev/vite-plus-${suffix}/package.json")`, @@ -50,25 +50,25 @@ describe('rewriteRolldownBindingRequires', () => { expect(result.source).not.toContain(`@rolldown/binding-${suffix}`); } expect(result.rewrittenSuffixes).toEqual( - new Set(['darwin-x64', 'darwin-arm64', 'linux-x64-musl']), + new Set(['darwin-x64', 'darwin-arm64', 'freebsd-x64', 'linux-x64-musl']), ); - expect(result.specifierRewrites).toBe(6); + expect(result.specifierRewrites).toBe(8); }); it('rewrites version guards only for rewritten branches', () => { - expect(result.guardRewrites).toBe(3); + expect(result.guardRewrites).toBe(4); const guardMatches = result.source.match(/bindingPackageVersion !== "9\.9\.9"/g); - expect(guardMatches).toHaveLength(3); + expect(guardMatches).toHaveLength(4); const messageMatches = result.source.match(/expected 9\.9\.9 but got/g); - expect(messageMatches).toHaveLength(3); + expect(messageMatches).toHaveLength(4); }); it('leaves unsupported platform branches on the Rolldown packages and version', () => { - expect(result.source).toContain('__require("@rolldown/binding-freebsd-x64")'); - expect(result.source).toContain('__require("@rolldown/binding-freebsd-x64/package.json")'); - // The freebsd guard still compares against the Rolldown version. + expect(result.source).toContain('__require("@rolldown/binding-freebsd-arm64")'); + expect(result.source).toContain('__require("@rolldown/binding-freebsd-arm64/package.json")'); + // The FreeBSD arm64 guard still compares against the Rolldown version. const freebsdGuard = result.source.slice( - result.source.indexOf('@rolldown/binding-freebsd-x64/package.json'), + result.source.indexOf('@rolldown/binding-freebsd-arm64/package.json'), ); expect(freebsdGuard).toContain('bindingPackageVersion !== "1.2.1"'); expect(freebsdGuard).toContain('expected 1.2.1 but got'); From 97f4f0cc3da604239a056f2c04b62be33d02d208 Mon Sep 17 00:00:00 2001 From: MK Date: Wed, 21 Oct 2026 01:03:57 +0800 Subject: [PATCH 7/7] fix: include the script loader in FreeBSD builds --- .github/workflows/reusable-release-build.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/reusable-release-build.yml b/.github/workflows/reusable-release-build.yml index 2f9561f344..ebc16d474e 100644 --- a/.github/workflows/reusable-release-build.yml +++ b/.github/workflows/reusable-release-build.yml @@ -102,7 +102,7 @@ jobs: build_dir=$(mktemp -d) cargo build --locked --release --target x86_64-unknown-freebsd \ --target-dir "$build_dir" -p vp_global_cli -p vite-plus-cli \ - --features vite-plus-cli/rolldown + --features vite-plus-cli/rolldown,vite-plus-cli/oxc-node cargo test --locked --release --target x86_64-unknown-freebsd \ --target-dir "$build_dir" -p vp_js_runtime -p vp_setup platform @@ -117,6 +117,7 @@ jobs: const binding = require('./packages/cli/binding/vite-plus.freebsd-x64.node'); assert.equal(typeof binding.run, 'function'); assert.equal(typeof binding.BindingBundler, 'function'); + assert.equal(typeof binding.oxcNode.OxcTransformer, 'function'); binding.runCommand({ binName: process.execPath, args: ['-e', 'process.exit(7)'],