Skip to main content

Documentation Index

Fetch the complete documentation index at: https://bun.com/docs/llms.txt

Use this file to discover all available pages before exploring further.

This document describes the build process for Windows. If you run into problems, please join the #contributing channel on our Discord for help. It is strongly recommended to use PowerShell 7 (pwsh.exe) instead of the default powershell.exe.

Prerequisites

Enable Scripts

By default, running unverified scripts are blocked.
Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy Unrestricted

System Dependencies

Bun v1.1 or later. We use Bun to run it’s own code generators.
irm bun.sh/install.ps1 | iex
Visual Studio with the “Desktop Development with C++” workload. While installing, make sure to install Git as well, if Git for Windows is not already installed. Visual Studio can be installed graphically using the wizard or through WinGet:
winget install "Visual Studio Community 2022" --override "--add Microsoft.VisualStudio.Workload.NativeDesktop Microsoft.VisualStudio.Component.Git " -s msstore
After Visual Studio, you need the following:
  • LLVM 21.1.8
  • Go
  • Rust (via rustup)
  • NASM
  • Perl
  • Ruby
  • Node.js
The pinned Rust nightly toolchain in rust-toolchain.toml is automatically installed by rustup on first build.
Use Scoop to install these remaining tools.
Scoop (x64)
irm https://get.scoop.sh | iex
scoop install nodejs-lts go rustup nasm ruby perl ccache
# scoop seems to be buggy if you install llvm and the rest at the same time
scoop install llvm@21.1.8
For Windows ARM64, download LLVM 21.1.8 directly from GitHub releases (first version with ARM64 Windows builds):
ARM64
# Download and install LLVM for ARM64
Invoke-WebRequest -Uri "https://github.com/llvm/llvm-project/releases/download/llvmorg-21.1.8/LLVM-21.1.8-woa64.exe" -OutFile "$env:TEMP\LLVM-21.1.8-woa64.exe"
Start-Process -FilePath "$env:TEMP\LLVM-21.1.8-woa64.exe" -ArgumentList "/S" -Wait
Please do not use WinGet/other package manager for these, as you will likely install Strawberry Perl instead of a more minimal installation of Perl. Strawberry Perl includes many other utilities that get installed into $Env:PATH that will conflict with MSVC and break the build.
If you intend on building WebKit locally (optional, x64 only), you should install these packages:
Scoop
scoop install make cygwin python
Cygwin is not required for ARM64 builds as WebKit is provided as a pre-built binary.
From here on out, it is expected you use a PowerShell Terminal with .\scripts\vs-shell.ps1 sourced. This script is available in the Bun repository and can be loaded by executing it:
.\scripts\vs-shell.ps1
To verify, you can check for an MSVC-only command line such as mt.exe
Get-Command mt
It is not recommended to install ninja / cmake into your global path, because you may run into a situation where you try to build bun without .\scripts\vs-shell.ps1 sourced.

Building

bun run build

# after the initial `bun run build` you can use the following to build
ninja -Cbuild/debug
If this was successful, you should have a bun-debug.exe in the build/debug folder.
.\build\debug\bun-debug.exe --revision
You should add this to $Env:PATH. The simplest way to do so is to open the start menu, type “Path”, and then navigate the environment variables menu to add C:\.....\bun\build\debug to the user environment variable PATH. You should then restart your editor (if it does not update still, log out and log back in).

Extra paths

  • WebKit is extracted to build/debug/cache/webkit/

Tests

You can run the test suite either using bun test <path> or by using the wrapper script bun node:test <path>. The bun node:test command runs every test file in a separate instance of bun.exe, to prevent a crash in the test runner from stopping the entire suite.
# Setup
bun i --cwd packages\bun-internal-test

# Run the entire test suite with reporter
# the package.json script "test" uses "build/debug/bun-debug.exe" by default
bun run test

# Run an individual test file:
bun-debug test node\fs
bun-debug test "C:\bun\test\js\bun\resolve\import-meta.test.js"

Troubleshooting

.rc file fails to build

llvm-rc.exe is odd. don’t use it. use rc.exe, to do this make sure you are in a visual studio dev terminal, check rc /? to ensure it is Microsoft Resource Compiler

failed to write output ‘bun-debug.exe’: permission denied

you cannot overwrite bun-debug.exe if it is already open. you likely have a running instance, maybe in the vscode debugger?

Cross-compiling from Linux

Windows binaries (both x64 and arm64) can also be built on a Linux host. The build uses the host LLVM’s clang-cl, lld-link, llvm-lib and llvm-rc — which are part of every LLVM distribution — plus an “xwin splat” of the MSVC CRT/STL and Windows SDK for headers and import libraries.

Prerequisites

  1. The same LLVM version a native build uses (see scripts/bootstrap.sh llvm_version_exact), installed so that clang-cl, lld-link, llvm-lib and llvm-rc are available. On Debian/Ubuntu, apt.llvm.org packages provide all of them.
  2. nasm (only needed for Windows x64 — BoringSSL’s x64 assembly is NASM syntax).
  3. Rust std for the Windows targets (rust-toolchain.toml lists them; rustup target add x86_64-pc-windows-msvc aarch64-pc-windows-msvc if missing).
  4. A Windows sysroot: an xwin splat of the MSVC CRT, Windows SDK, and ATL laid out like a Visual Studio install. Note that downloading these components means accepting Microsoft’s license terms for them.
cargo install xwin # or download a release binary
xwin --accept-license --arch x86_64,aarch64 --sdk-version 10.0.26100 --crt-version 14.44.17.14 --include-atl splat \
  --use-winsysroot-style --preserve-ms-arch-notation --include-debug-libs \
  --output /opt/winsysroot
# clang-cl/lld-link look up SDK paths as "Include"/"Lib"; the splat writes
# them lowercase, so alias both spellings (needs the same privileges as the
# splat — configure creates these itself when the directory is writable).
ln -s include "/opt/winsysroot/Windows Kits/10/Include"
ln -s lib "/opt/winsysroot/Windows Kits/10/Lib"
The build looks for the sysroot at /opt/winsysroot (or /opt/xwin) automatically; elsewhere, set WINDOWS_SYSROOT=<path> or pass --winsysroot=<path> (a user-writable path also lets configure manage the aliases for you). Configure validates the splat at the start of every cross build. CI agents bake the same splat into their images (.buildkite/Dockerfile, scripts/bootstrap.sh); when an agent doesn’t have one, the build fetches it into its cache dir at configure time.

Building

# Debug builds
bun run build --profile=windows-x64
bun run build --profile=windows-arm64

# Release builds
bun run build --profile=windows-x64-release
bun run build --profile=windows-arm64-release
Output lands in build/debug-windows-x64/bun-debug.exe, build/release-windows-aarch64/bun-profile.exe + bun.exe, etc. Equivalent raw flags: bun run build --os=windows --arch=aarch64. Cross-compiled executables are not run on the host (the --revision smoke test is skipped), so test them on a Windows machine or under Wine.

LTO

x64 release cross builds support ThinLTO with cross-language (Rust↔C++) LTO, and CI’s windows x64 cross lane builds with it by default. Locally it’s opt-in:
bun run build --profile=windows-x64-release --lto=on
This compiles bun’s C/C++ with -flto=thin, makes rustc emit LLVM bitcode (-Clinker-plugin-lto), pulls the bun-webkit-windows-amd64-lto ThinLTO prebuilt, and links everything with rustc’s bundled lld-link (its LLVM is new enough to read both compilers’ bitcode). There is no LTO for arm64 (no -lto WebKit prebuilt — LLVM’s CodeView emitter can’t handle ARM64 NEON tuple registers during LTO codegen) or for --baseline.