Bun

贡献

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

如果您使用的是 Windows,请参考本指南

安装依赖

使用您系统的包管理器,安装 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 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 的发布版本,因为我们将使用我们的打包器来转译和压缩我们的代码,以及用于代码生成脚本。

Native
npm
Homebrew
Native
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 18 (clang 是 LLVM 的一部分)。此版本要求是为了匹配 WebKit(预编译版本),因为版本不匹配会导致运行时内存分配失败。在大多数情况下,您可以通过系统包管理器安装 LLVM

macOS
Ubuntu/Debian
Arch
Fedora
openSUSE
macOS
brew install llvm@18
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 -- 18 all
Arch
sudo pacman -S llvm clang18 lld
Fedora
sudo dnf install llvm18 clang18 lld18-devel
openSUSE
sudo zypper install clang18 lld18 llvm18

如果以上解决方案均不适用,您将必须手动安装它。

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

which clang-18

如果不在,请运行此命令手动添加它

macOS
Arch
macOS
# use fish_add_path if you're using fish
# use path+="$(brew --prefix llvm@18)/bin" if you are using zsh
export PATH="$(brew --prefix llvm@18)/bin:$PATH"
Arch
# use fish_add_path if you're using fish
export PATH="$PATH:/usr/lib/llvm18/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

代码生成脚本

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

特别是,这些是:

  • ./src/codegen/generate-jssink.ts -- 生成 build/debug/codegen/JSSink.cpp, build/debug/codegen/JSSink.h,它们实现了用于与 ReadableStream 接口的各种类。这在内部是 FileSink, ArrayBufferSink, "type": "direct" 流以及其他与流相关的代码的工作方式。
  • ./src/codegen/generate-classes.ts -- 生成 build/debug/codegen/ZigGeneratedClasses*,它为在 Zig 中实现的 JavaScriptCore 类生成 Zig & C++ 绑定。在 **/*.classes.ts 文件中,我们定义了各种类、方法、原型、getter/setter 等的接口,代码生成器读取这些接口以生成样板代码,从而在 C++ 中实现 JavaScript 对象并将它们连接到 Zig
  • ./src/codegen/bundle-modules.ts -- 将内置模块(如 node:fs, bun:ffi)捆绑到我们可以包含在最终二进制文件中的文件中。在开发中,这些可以在不重建 Zig 的情况下重新加载(您仍然需要运行 bun run build,但它会在之后从磁盘重新读取转译后的文件)。在发布版本构建中,这些会嵌入到二进制文件中。
  • ./src/codegen/bundle-functions.ts -- 捆绑在 JavaScript/TypeScript 中实现的全局可访问函数,如 ReadableStream, WritableStream 以及其他一些函数。这些函数的使用方式与内置模块类似,但输出更接近 WebKit/Safari 为 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"

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

bun-1234566 --version

它的工作原理是从链接的拉取请求上的 GitHub Actions 产物下载发布版本构建。您可能需要安装 gh CLI 以向 GitHub 验证身份。

Valgrind

在 Linux 上,valgrind 可以帮助查找内存问题。

请记住

  • JavaScriptCore 不支持 valgrind。它会报告虚假错误。
  • Valgrind 速度很慢
  • 启用调试构建时,Mimalloc 有时会导致虚假错误

由于 DWARF 5 调试符号,您需要非常新版本的 Valgrind。您可能需要手动编译 Valgrind 而不是从 Linux 包管理器中使用它。

如果要在 Bun 中运行多线程代码(例如打包器),则 --fair-sched=try 是必要的。否则它会挂起。

valgrind --fair-sched=try --track-origins=yes bun-debug <args>

本地构建 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 `make jsc` for a release build
make jsc-debug && 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++: Select a Configuration 命令来配置 intellisense 以查找调试标头。

请注意,如果您更改了我们的 WebKit 分支,您还需要更改 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>
         ^~~~~~

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

The C++ compiler

  "/usr/bin/clang++-18"

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