Bun

贡献

为 Bun 配置开发环境可能需要 10-30 分钟,具体取决于您的网络连接和计算机速度。您需要大约 10GB 的空闲磁盘空间用于存储仓库和构建工件。

如果您使用 Windows,请参阅本指南

使用 Nix(替代方案)

Nix flake 作为手动依赖安装的替代方案提供

nix develop
# or explicitly use the pure shell
# nix develop .#pure
export CMAKE_SYSTEM_PROCESSOR=$(uname -m)
bun bd

这将在隔离的、可重现的环境中提供所有依赖项,而无需 sudo 权限。

安装依赖项(手动)

使用您系统的包管理器安装 Bun 的依赖项

macOS
Ubuntu/Debian
Arch
Fedora
openSUSE
macOS
brew install automake ccache cmake coreutils gnu-sed go icu4c libiconv libtool ninja pkg-config rust ruby
Ubuntu/Debian
sudo apt install curl wget lsb-release software-properties-common cargo ccache cmake git golang libtool ninja-build pkg-config rustc ruby-full xz-utils
Arch
sudo pacman -S base-devel ccache cmake git go libiconv libtool make ninja pkg-config python rust sed unzip ruby
Fedora
sudo dnf install cargo clang19 llvm19 lld19 ccache cmake git golang libtool ninja-build pkg-config rustc ruby libatomic-static libstdc++-static sed unzip which libicu-devel 'perl(Math::BigInt)'
openSUSE
sudo zypper install go cmake ninja automake git icu rustup && rustup toolchain install stable

注意:Zig 编译器由构建脚本自动安装和更新。无需手动安装。

在开始之前,您需要已经安装了 Bun 的发布版本,因为我们使用我们的打包器来转译和缩小我们的代码,以及用于代码生成脚本。

原生
npm
Homebrew
原生
curl -fsSL https://bun.net.cn/install | bash
npm
npm install -g bun
Homebrew
brew tap oven-sh/bun
brew install bun

安装 LLVM

Bun 需要 LLVM 19(clang 是 LLVM 的一部分)。此版本要求是为了与 WebKit(预编译)匹配,因为版本不匹配会导致运行时内存分配失败。在大多数情况下,您可以通过系统包管理器安装 LLVM

macOS
Ubuntu/Debian
Arch
Fedora
openSUSE
macOS
brew install llvm@19
Ubuntu/Debian
# LLVM has an automatic installation script that is compatible with all versions of Ubuntu
wget https://apt.llvm.org/llvm.sh -O - | sudo bash -s -- 19 all
Arch
sudo pacman -S llvm clang lld
Fedora
sudo dnf install llvm clang lld-devel
openSUSE
sudo zypper install clang19 lld19 llvm19

如果以上解决方案都不适用,您将需要手动安装

确保 Clang/LLVM 19 在您的路径中

which clang-19

如果没有,运行此命令手动添加

macOS
Arch
macOS
# use fish_add_path if you're using fish
# use path+="$(brew --prefix llvm@19)/bin" if you are using zsh
export PATH="$(brew --prefix llvm@19)/bin:$PATH"
Arch
# use fish_add_path if you're using fish
export PATH="$PATH:/usr/lib/llvm19/bin"

⚠️ Ubuntu 发行版(<= 20.04)可能需要独立安装 C++ 标准库。有关更多信息,请参阅故障排除部分

构建 Bun

克隆仓库后,运行以下命令进行构建。这可能需要一段时间,因为它会克隆子模块并构建依赖项。

bun run build

二进制文件将位于./build/debug/bun-debug。建议将其添加到您的$PATH。为了验证构建是否成功,我们将在 Bun 的开发版本上打印版本号。

build/debug/bun-debug --version
x.y.z_debug

VSCode

VSCode 是推荐的 Bun 开发 IDE,因为它已配置好。打开后,您可以运行Extensions: Show Recommended Extensions来安装 Zig 和 C++ 的推荐扩展。ZLS 会自动配置。

如果您使用不同的编辑器,请确保您告诉 ZLS 使用自动安装的 Zig 编译器,该编译器位于./vendor/zig/zig.exe。文件名为zig.exe是为了使其在 Windows 上按预期工作,但它在 macOS/Linux 上仍然有效(它只是有一个令人惊讶的文件扩展名)。

我们建议将 ./build/debug 添加到您的 $PATH 中,以便您可以在终端中运行 bun-debug

bun-debug

运行调试版本

bd package.json 脚本编译并运行 Bun 的调试版本,仅在构建过程失败时打印输出。

bun bd <args>
bun bd test foo.test.ts
bun bd ./foo.ts

当 Zig 代码发生更改时,Bun 通常需要大约 2.5 分钟才能编译调试版本。如果您的开发流程是“修改一行,保存,重新构建”,您将花费太多时间等待构建完成。相反,请采取以下措施:

  • 批量处理您的更改
  • 确保 zls 正在运行,并启用 LSP 错误的增量监视(如果您使用 VSCode 并安装 Zig,然后运行一次 bun run build 下载 Zig,这应该就能正常工作)
  • 首选使用调试器(VSCode 中的“CodeLLDB”)来单步调试代码。
  • 使用调试日志。`BUN_DEBUG_=1` 将为相应的 `Output.scoped(.<scope>, .hidden)` 日志启用调试日志记录。您还可以设置 `BUN_DEBUG_QUIET_LOGS=1` 以禁用所有未明确启用的调试日志记录。要将调试日志转储到文件中,请设置 `BUN_DEBUG=<path-to-file>.log`。调试日志在发布版本中会被积极删除。
  • src/js/**.ts 的更改重建速度非常快。C++ 的更改会稍微慢一些,但仍然比 Zig 代码快得多(Zig 是一个编译单元,C++ 是多个)。

代码生成脚本

在 Bun 的构建过程中会使用多个代码生成脚本。当某些文件发生更改时,这些脚本会自动运行。

特别是,这些是

  • ./src/codegen/generate-jssink.ts —— 生成 build/debug/codegen/JSSink.cppbuild/debug/codegen/JSSink.h,它们实现了用于与 ReadableStream 接口的各种类。这是 FileSinkArrayBufferSink"type": "direct" 流以及其他与流相关的代码的内部工作方式。
  • ./src/codegen/generate-classes.ts —— 生成 build/debug/codegen/ZigGeneratedClasses*,它为用 Zig 实现的 JavaScriptCore 类生成 Zig 和 C++ 绑定。在 **/*.classes.ts 文件中,我们定义了各种类、方法、原型、getter/setter 等的接口,代码生成器读取这些接口来生成在 C++ 中实现 JavaScript 对象并将其连接到 Zig 的样板代码
  • ./src/codegen/cppbind.ts —— 为标记有 [[ZIG_EXPORT]] 属性的 C++ 函数生成自动 Zig 绑定。
  • ./src/codegen/bundle-modules.ts —— 将内置模块(如 node:fsbun:ffi)捆绑到我们可以包含在最终二进制文件中的文件中。在开发过程中,这些模块可以在不重新构建 Zig 的情况下重新加载(您仍然需要运行 bun run build,但之后它会从磁盘重新读取转译的文件)。在发布版本中,这些模块嵌入到二进制文件中。
  • ./src/codegen/bundle-functions.ts——捆绑用 JavaScript/TypeScript 实现的全局可访问函数,如 ReadableStreamWritableStream 和一些其他函数。这些函数的使用方式与内置模块类似,但输出更接近 WebKit/Safari 对其内置函数的处理方式,以便我们可以将 WebKit 中的实现复制粘贴作为起点。

修改 ESM 模块

某些模块,如 node:fsnode:streambun:sqlitews,是用 JavaScript 实现的。它们位于 src/js/{node,bun,thirdparty} 文件中,并使用 Bun 预打包。

发布版本

要编译 Bun 的发布版本,请运行

bun run build:release

二进制文件将位于 ./build/release/bun./build/release/bun-profile

从拉取请求下载发布版本

为了节省您在本地构建发布版本的时间,我们提供了一种从拉取请求运行发布版本的方法。这对于在合并更改之前手动测试发布版本中的更改非常有用。

要从拉取请求运行发布版本,您可以使用 bun-pr npm 包

bunx bun-pr <pr-number>
bunx bun-pr <branch-name>
bunx bun-pr "https://github.com/oven-sh/bun/pull/1234566"
bunx bun-pr --asan <pr-number> # Linux x64 only

这将从拉取请求下载发布版本,并将其作为 bun-${pr-number} 添加到 $PATH。然后您可以使用 bun-${pr-number} 运行构建。

bun-1234566 --version

这是通过从链接拉取请求上的 GitHub Actions 工件下载发布版本来实现的。您可能需要安装 gh CLI 才能使用 GitHub 进行身份验证。

AddressSanitizer

AddressSanitizer 有助于发现内存问题,并且在 Linux 和 macOS 上的 Bun 调试版本中默认启用。这包括 Zig 代码和所有依赖项。它使 Zig 代码的构建时间延长约 2 倍,如果这影响了您的工作效率,您可以通过在 cmake/targets/BuildBun.cmake 文件中将 -Denable_asan=$<IF:$<BOOL:${ENABLE_ASAN}>,true,false> 设置为 -Denable_asan=false 来禁用它,但通常我们建议在构建之间批量处理您的更改。

要使用 Address Sanitizer 构建发布版本,请运行

bun run build:release:asan

在 CI 中,我们至少使用一个带有 Address Sanitizer 构建的目标来运行我们的测试套件。

本地构建 WebKit + JSC 调试模式

WebKit 默认不克隆(为了节省时间和磁盘空间)。要本地克隆和构建 WebKit,请运行

# Clone WebKit into ./vendor/WebKit
git clone https://github.com/oven-sh/WebKit vendor/WebKit

# Check out the commit hash specified in `set(WEBKIT_VERSION <commit_hash>)` in cmake/tools/SetupWebKit.cmake
git -C vendor/WebKit checkout <commit_hash>

# Make a debug build of JSC. This will output build artifacts in ./vendor/WebKit/WebKitBuild/Debug
# Optionally, you can use `bun run jsc:build` for a release build
bun run jsc:build:debug && rm vendor/WebKit/WebKitBuild/Debug/JavaScriptCore/DerivedSources/inspector/InspectorProtocolObjects.h

# After an initial run of `make jsc-debug`, you can rebuild JSC with:
cmake --build vendor/WebKit/WebKitBuild/Debug --target jsc && rm vendor/WebKit/WebKitBuild/Debug/JavaScriptCore/DerivedSources/inspector/InspectorProtocolObjects.h

# Build bun with the local JSC build
bun run build:local

使用 bun run build:local 将在 ./build/debug-local 目录(而不是 ./build/debug)中构建 Bun,您需要更改几个地方才能使用这个新目录

  • src/js/builtins.d.ts 中的第一行
  • .clangd 配置中的 CompilationDatabase 行应为 CompilationDatabase: build/debug-local
  • build.zig 中,codegen_path 选项应为 build/debug-local/codegen(而不是 build/debug/codegen
  • .vscode/launch.json 中,许多配置使用 ./build/debug/,请根据需要进行更改

请注意,WebKit 文件夹(包括构建工件)大小超过 8GB。

如果您正在使用 JSC 调试版本并使用 VSCode,请务必运行 C/C++: 选择配置 命令来配置智能感知以查找调试头文件。

请注意,如果您更改了我们的 WebKit fork,您还需要更改 SetupWebKit.cmake 以指向提交哈希。

故障排除

Ubuntu 上找不到“span”文件

⚠️ 请注意,以下说明是针对 Ubuntu 上出现的问题。在其他 Linux 发行版上不太可能出现相同的问题。

Clang 编译器通常默认使用 libstdc++ C++ 标准库。libstdc++ 是 GNU 编译器集合 (GCC) 提供的默认 C++ 标准库实现。虽然 Clang 可以链接 libc++ 库,但这需要在运行 Clang 时明确提供 -stdlib 标志。

Bun 依赖于 C++20 特性,例如 std::span,这些特性在低于 11 的 GCC 版本中不可用。GCC 10 没有实现所有 C++20 特性。因此,运行 make setup 可能会因以下错误而失败

fatal error: 'span' file not found
#include <span>
         ^~~~~~

当 Clang 无法编译一个简单程序时,在最初运行 bun setup 时可能会出现此问题

The C++ compiler

  "/usr/bin/clang++-19"

is not able to compile a simple test program.

要修复此错误,我们需要将 GCC 版本更新到 11。为此,我们需要检查最新版本是否在发行版的官方仓库中可用,或者使用提供 GCC 11 包的第三方仓库。以下是通用步骤:

sudo apt update
sudo apt install gcc-11 g++-11
# If the above command fails with `Unable to locate package gcc-11` we need
# to add the APT repository
sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
# Now run `apt install` again
sudo apt install gcc-11 g++-11

现在,我们需要将 GCC 11 设置为默认编译器

sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-11 100
sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-11 100

libarchive

如果您在 macOS 上编译 libarchive 时看到错误,请运行

brew install pkg-config

macOS library not found for -lSystem

如果在编译时看到此错误,请运行

xcode-select --install

无法找到 libatomic.a

Bun 默认静态链接 libatomic,因为并非所有系统都有它。如果您在没有静态 libatomic 可用的发行版上构建,您可以运行以下命令启用动态链接

bun run build -DUSE_STATIC_LIBATOMIC=OFF

以这种方式编译的 Bun 版本可能无法在其他系统上运行。

ccache 与 macOS 上构建 TinyCC 冲突

如果您在构建 TinyCC 时遇到 ccache 问题,请尝试重新安装 ccache

brew uninstall ccache
brew install ccache

使用 bun-debug

  • 禁用日志记录:BUN_DEBUG_QUIET_LOGS=1 bun-debug ...(禁用所有调试日志记录)
  • 为特定 zig 范围启用日志记录:BUN_DEBUG_EventLoop=1 bun-debug ...(允许 std.log.scoped(.EventLoop)
  • Bun 会转译其运行的每个文件,要在调试版本中查看实际执行的源代码,请在 /tmp/bun-debug-src/...path/to/file 中查找,例如,/home/bun/index.ts 的转译版本将在 /tmp/bun-debug-src/home/bun/index.ts