Install Dependencies
Using your system’s package manager, install Bun’s dependencies:Note: The Zig compiler is automatically installed and updated by the build scripts. Manual installation is not required.Before starting, you will need to already have a release build of Bun installed, as we use our bundler to transpile and minify our code, as well as for code generation scripts.
Install LLVM
Bun requires LLVM 19 (clang is part of LLVM). This version requirement is to match WebKit (precompiled), as mismatching versions will cause memory allocation failures at runtime. In most cases, you can install LLVM through your system package manager:
⚠️ Ubuntu distributions (<= 20.04) may require installation of the C++ standard library independently. See the troubleshooting section for more information.
Building Bun
After cloning the repository, run the following command to build. This may take a while as it will clone submodules and build dependencies../build/debug/bun-debug. It is recommended to add this to your $PATH. To verify the build worked, let’s print the version number on the development build of Bun.
VSCode
VSCode is the recommended IDE for working on Bun, as it has been configured. Once opening, you can runExtensions: Show Recommended Extensions to install the recommended extensions for Zig and C++. ZLS is automatically configured.
If you use a different editor, make sure that you tell ZLS to use the automatically installed Zig compiler, which is located at ./vendor/zig/zig.exe. The filename is zig.exe so that it works as expected on Windows, but it still works on macOS/Linux (it just has a surprising file extension).
We recommend adding ./build/debug to your $PATH so that you can run bun-debug in your terminal:
Running debug builds
Thebd package.json script compiles and runs a debug build of Bun, only printing the output of the build process if it fails.
- Batch up your changes
- Ensure zls is running with incremental watching for LSP errors (if you use VSCode and install Zig and run
bun run buildonce to download Zig, this should just work) - Prefer using the debugger (“CodeLLDB” in VSCode) to step through the code.
- Use debug logs.
BUN_DEBUG_<scope>=1will enable debug logging for the correspondingOutput.scoped(.<scope>, false)logs. You can also setBUN_DEBUG_QUIET_LOGS=1to disable all debug logging that isn’t explicitly enabled. To dump debug lgos into a file,BUN_DEBUG=<path-to-file>.log. Debug logs are aggressively removed in release builds. - src/js/**.ts changes are pretty much instant to rebuild. C++ changes are a bit slower, but still much faster than the Zig code (Zig is one compilation unit, C++ is many).
Code generation scripts
Several code generation scripts are used during Bun’s build process. These are run automatically when changes are made to certain files. In particular, these are:./src/codegen/generate-jssink.ts— Generatesbuild/debug/codegen/JSSink.cpp,build/debug/codegen/JSSink.hwhich implement various classes for interfacing withReadableStream. This is internally howFileSink,ArrayBufferSink,"type": "direct"streams and other code related to streams works../src/codegen/generate-classes.ts— Generatesbuild/debug/codegen/ZigGeneratedClasses*, which generates Zig & C++ bindings for JavaScriptCore classes implemented in Zig. In**/*.classes.tsfiles, we define the interfaces for various classes, methods, prototypes, getters/setters etc which the code generator reads to generate boilerplate code implementing the JavaScript objects in C++ and wiring them up to Zig./src/codegen/cppbind.ts— Generates automatic Zig bindings for C++ functions marked with[[ZIG_EXPORT]]attributes../src/codegen/bundle-modules.ts— Bundles built-in modules likenode:fs,bun:ffiinto files we can include in the final binary. In development, these can be reloaded without rebuilding Zig (you still need to runbun run build, but it re-reads the transpiled files from disk afterwards). In release builds, these are embedded into the binary../src/codegen/bundle-functions.ts— Bundles globally-accessible functions implemented in JavaScript/TypeScript likeReadableStream,WritableStream, and a handful more. These are used similarly to the builtin modules, but the output more closely aligns with what WebKit/Safari does for Safari’s built-in functions so that we can copy-paste the implementations from WebKit as a starting point.
Modifying ESM modules
Certain modules likenode:fs, node:stream, bun:sqlite, and ws are implemented in JavaScript. These live in src/js/{node,bun,thirdparty} files and are pre-bundled using Bun.
Release build
To compile a release build of Bun, run:./build/release/bun and ./build/release/bun-profile.
Download release build from pull requests
To save you time spent building a release build locally, we provide a way to run release builds from pull requests. This is useful for manually testing changes in a release build before they are merged. To run a release build from a pull request, you can use thebun-pr npm package:
$PATH as bun-${pr-number}. You can then run the build with bun-${pr-number}.
gh CLI installed to authenticate with GitHub.
AddressSanitizer
AddressSanitizer helps find memory issues, and is enabled by default in debug builds of Bun on Linux and macOS. This includes the Zig code and all dependencies. It makes the Zig code take about 2x longer to build, if that’s stopping you from being productive you can disable it by setting-Denable_asan=$<IF:$<BOOL:${ENABLE_ASAN}>,true,false> to -Denable_asan=false in the cmake/targets/BuildBun.cmake file, but generally we recommend batching your changes up between builds.
To build a release build with Address Sanitizer, run:
Building WebKit locally + Debug mode of JSC
WebKit is not cloned by default (to save time and disk space). To clone and build WebKit locally, run:bun run build:local will build Bun in the ./build/debug-local directory (instead of ./build/debug), you’ll have to change a couple of places to use this new directory:
- The first line in
src/js/builtins.d.ts - The
CompilationDatabaseline in.clangdconfig should beCompilationDatabase: build/debug-local - In
build.zig, thecodegen_pathoption should bebuild/debug-local/codegen(instead ofbuild/debug/codegen) - In
.vscode/launch.json, many configurations use./build/debug/, change them as you see fit
C/C++: Select a Configuration command to configure intellisense to find the debug headers.
Note that if you change make changes to our WebKit fork, you will also have to change SetupWebKit.cmake to point to the commit hash.
Troubleshooting
’span’ file not found on Ubuntu
⚠️ Please note that the instructions below are specific to issues occurring on Ubuntu. It is unlikely that the same
issues will occur on other Linux distributions.
libstdc++ C++ standard library by default. libstdc++ is the default C++ Standard Library implementation provided by the GNU Compiler Collection (GCC). While Clang may link against the libc++ library, this requires explicitly providing the -stdlib flag when running Clang.
Bun relies on C++20 features like std::span, which are not available in GCC versions lower than 11. GCC 10 doesn’t have all of the C++20 features implemented. As a result, running make setup may fail with the following error:
bun setup as Clang being unable to compile a simple program:
libarchive
If you see an error on macOS when compilinglibarchive, run:
macOS library not found for -lSystem
If you see this error when compiling, run:
Cannot find libatomic.a
Bun defaults to linking libatomic statically, as not all systems have it. If you are building on a distro that does not have a static libatomic available, you can run the following command to enable dynamic linking:
ccache conflicts with building TinyCC on macOS
If you run into issues withccache when building TinyCC, try reinstalling ccache
Using bun-debug
- Disable logging:
BUN_DEBUG_QUIET_LOGS=1 bun-debug ...(to disable all debug logging) - Enable logging for a specific zig scope:
BUN_DEBUG_EventLoop=1 bun-debug ...(to allowstd.log.scoped(.EventLoop)) - Bun transpiles every file it runs, to see the actual executed source in a debug build find it in
/tmp/bun-debug-src/...path/to/file, for example the transpiled version of/home/bun/index.tswould be in/tmp/bun-debug-src/home/bun/index.ts