This document covers Bun's multi-language build system, which orchestrates compilation of Zig, C++, and TypeScript code into a single executable. It also details the CI/CD infrastructure that builds, tests, and releases Bun across multiple platforms and architectures.
For information about the JavaScript bundler that Bun provides to users, see Bundler Architecture. For information about the test runner used to test user code, see Testing Framework.
Bun's build system is a hybrid of CMake (for C++ and orchestration) and Zig's build system (for Zig code). The build process involves several stages:
The system supports incremental builds, cross-compilation, and multiple build configurations (Debug, Release, RelWithDebInfo, MinSizeRel).
Figure 1: CMake Module Hierarchy
The top-level CMakeLists.txt1-67 orchestrates the entire build system by including specialized CMake modules. The build starts with policy and global configuration, sets up compilers and tools, generates code, defines build targets, and optionally configures analysis tools.
Sources: CMakeLists.txt1-67
The build system begins at CMakeLists.txt1-2 with a minimum CMake version requirement of 3.24. The version is parsed from package.json1-98 using the parse_package_json function at CMakeLists.txt30 with the default version being "1.3.10" from package.json4
The module search path is configured at CMakeLists.txt4-10 to include subdirectories for targets, tools, analysis, and scripts.
The build system uses a custom LLVM setup:
SetupMacSDK.cmake to configure the macOS SDK path before compiler initializationSetupLLVM.cmake to configure the LLVM toolchainAfter compiler setup, the build system loads:
Options.cmake: Configures build options like ENABLE_ASAN, ENABLE_LTO, ENABLE_LOGSCompilerFlags.cmake: Sets platform-specific compiler flagsThe build requires several external tools, configured through dedicated modules at CMakeLists.txt42-48:
| Tool | Purpose | CMake Module |
|---|---|---|
| Git | Version control operations | SetupGit.cmake |
| Buildkite | CI/CD pipeline | SetupBuildkite.cmake |
| Bun | Self-hosting (using Bun to build Bun) | SetupBun.cmake |
| esbuild | Bundling internal TypeScript modules | SetupEsbuild.cmake |
| Zig | Zig language compiler | SetupZig.cmake |
| Rust | Dependency version generation | SetupRust.cmake |
| ccache | Compilation caching | SetupCcache.cmake |
Sources: CMakeLists.txt1-51
The package.json29-97 file defines numerous build scripts for different scenarios:
Figure 2: Build Configuration Matrix
Each build script invokes ./scripts/build.mjs with different CMake flags. The most common configurations:
Sources: package.json29-48
Bun requires code generation to bridge between TypeScript, C++, and Zig. This happens before compilation:
Figure 3: Code Generation Flow
The CMakeLists.txt53 includes GenerateDependencyVersions.cmake, which runs Rust tooling to extract dependency versions from Cargo.lock files. The generated outputs are:
.gitignore at .gitignore128)These generated files are excluded from version control as shown in .gitignore125-141
Sources: CMakeLists.txt53 .gitignore125-141
C++ source files are compiled with:
SetupLLVM.cmake)bun-cpp.aZig code is compiled using Zig's build system:
build.zig (invoked by SetupZig.cmake)-DZIG_OPTIMIZE flag
Debug: No optimizations, safety checks enabledReleaseSafe: Optimizations with runtime safetyReleaseFast: Maximum optimizations (default for Release builds)ReleaseSmall: Optimize for binary sizebun-zig.oThe Zig compiler is controlled from package.json scripts like package.json32 for watch mode:
"watch": "bun run zig build check --watch -fincremental --prominent-compile-errors"
The CMakeLists.txt57 includes BuildBun.cmake, which defines the final linking step that combines:
The result is the bun executable.
Sources: CMakeLists.txt34-57 package.json32
Bun targets multiple platforms and architectures:
| Platform | Architectures | Variants |
|---|---|---|
| Linux | x64, aarch64 | glibc, musl |
| macOS | x64, aarch64 | - |
| Windows | x64, aarch64 | - |
| FreeBSD | x64 | - |
Baseline builds exclude modern CPU instructions for broader compatibility:
These builds are verified using QEMU emulation in CI to ensure they run on older CPUs.
The build system detects the host platform at CMakeLists.txt15-19 and adjusts settings:
Platform-specific build dependencies are handled in separate CMake modules like SetupMacSDK.cmake for macOS.
Sources: CMakeLists.txt15-25
The CI/CD pipeline uses Buildkite, configured through CMakeLists.txt44 which includes SetupBuildkite.cmake. The pipeline definition is generated dynamically by a script referenced in the package.json.
The CI pipeline script is invoked via package.json31:
"ci": "bun scripts/buildkite-failures.ts"
The CI system builds Bun for all platform/architecture combinations:
Figure 4: CI/CD Build and Test Pipeline
Tests are run via package.json63:
"test": "node scripts/runner.node.mjs --exec-path ./build/debug/bun-debug"
The runner.node.mjs script orchestrates:
Test results influence deployment decisions. Failed tests block releases.
The codebase detects CI environments to modify behavior. For example, test/js/bun/test/ci-restrictions.test.ts4-334 tests CI-specific restrictions:
test.only is disabled when GITHUB_ACTIONS=1 (test/js/bun/test/ci-restrictions.test.ts35-60)CI environment variable can be explicitly set to "false" to override (test/js/bun/test/ci-restrictions.test.ts6-33)Sources: package.json31-88 test/js/bun/test/ci-restrictions.test.ts4-334
Developers use package.json scripts for local builds:
Quick debug build (package.json30-36):
Watch mode for incremental compilation (package.json32):
Helper scripts (package.json34-35):
| Script | Configuration | Use Case |
|---|---|---|
build:debug | Debug + ASAN | Local development |
build:release | Release optimizations | Performance testing |
build:assert | RelWithDebInfo + assertions | Testing with checks |
build:asan | Release + ASAN | Memory leak detection |
build:logs | Release + logs | Debugging optimized builds |
build:safe | ReleaseSafe | Zig safety checks |
build:smol | MinSizeRel | Size-optimized binary |
Sources: package.json30-48
Run tests (package.json63-65):
Type checking (package.json57):
Specific test types (package.json69-75):
Sources: package.json57-88
The build system includes optional analysis targets at CMakeLists.txt61-66:
Enable analysis with (package.json76-77):
| Tool | Target Files | Script |
|---|---|---|
| clang-format | C++ source | clang-format (package.json78) |
| zig fmt | Zig source | zig-format (package.json84) |
| prettier | JS/TS/docs | prettier (package.json86) |
Each formatter has three modes:
Example usage (package.json78-86):
JavaScript/TypeScript linting uses oxlint (package.json61-62):
Sources: CMakeLists.txt61-66 package.json61-86
Build artifacts are excluded from version control via .gitignore55-104:
CMake artifacts:
build/, build-*/ - Build directoriesCMakeCache.txt, CMakeFiles/ - CMake metadatacompile_commands.json - Compilation databaseBuild outputs:
*.o, *.a, *.lib - Object files and libraries*.dSYM - Debug symbols (macOS)*.pdb - Program database (Windows)bun-binary, bun-zigld - Executable variantsZig cache:
.zig-cache/, zig-cache/, zig-out/ - Zig build cacheThe .gitignore163-183 excludes vendored dependencies that are managed by the build system:
/vendor - All third-party dependenciesIncremental compilation is supported through:
-fincremental flag (package.json32)-GNinja in build scripts)Sources: .gitignore55-183 CMakeLists.txt50 package.json32
Bun uses a custom build of JavaScriptCore (JSC) from WebKit. The setup is handled by a dedicated CMake module referenced in the build system.
The package.json54-56 includes scripts for building JavaScriptCore:
The build system supports two WebKit modes:
Local WebKit builds are useful for:
The .gitignore55 excludes /.webkit-cache, where local WebKit builds are stored.
Sources: package.json46-56 .gitignore55
Docker-based development environment (package.json50):
Machine provisioning scripts (package.json90-95):
These scripts provision cloud instances for testing on different platforms.
Windows builds have special handling:
COMSPEC in build scripts (package.json36)Sources: package.json33-95 CMakeLists.txt15-19
The current version is stored in multiple locations:
"version": "1.3.10"1.3.9 (previous release)The CMakeLists.txt30 parses the version from package.json using parse_package_json().
The CMakeLists.txt53 includes GenerateDependencyVersions.cmake, which:
After successful CI builds and tests, the pipeline:
Sources: CMakeLists.txt30-53 package.json4 LATEST1
The package.json89 provides a clean script:
This removes:
The package.json67 includes a utility to list source files:
This is used to regenerate the source file lists in cmake/sources/*.txt (which are .gitignored at .gitignore196).
Platform-specific bootstrap scripts handle initial setup:
bootstrap.sh - Unix-like systemsbootstrap.ps1 - Windows PowerShellThese scripts:
Sources: package.json67-89 .gitignore196
Refresh this wiki