使用 Buck2 编译构建 Rust 工程

最近觉得 FacebooK Meta 开源项目都挺良心, 从 React 到 SaplingBuck2 等等, 更是有 AI 大模型的 Llama , 让多少国产大模型实现了自主可控。 当然我关注的点都集中在 Rust 开发的项目中, 先是 Monorepo 解决方案 Sapling 让我感到自己做 Mega 其实路还有很长; 再有 Buck2 (Rust 重写 Meta 的构建系统 Buck), 让我明白没有构建系统的 Monorepo & Monolithic 解决方案是不完整的。 之前因为参加 BazelCon 2023 临时加入了 Bazel 不完整的支持, 其实整个项目都还在 Demo 的状态。 春节前最后整理好第一版的数据库结果, 也确定了是使用 Buck2 作为构建系统, 让整个解决方案更加 Rusty

当边看文档边在 Mega 中加入 Buck2 的支持时, 发现还是有很多概念需要学习, 没办法只能从 Hello World 开始尝试构建, 并且记录对 Buck2 的学习。

按照 Buck2

首先是安装 Buck2 , 目前还在 pre-release 阶段, 我是直接从 GitHub 直接下载了 Buck2 的二进制文件, 并且放到了 /usr/local/bin 目录下。 开发环境是 Arch Linux, 我提前安装了 clanglld , 如果还有什么其他的依赖, 请自行安装。

$ paru -S clang lld

创建 Rust 项目, 初始化 Buck2 支持

首先使用 cargo 命令创建一个 Rust 项目:

$ cargo new rust-buck2

然后进入目录初始化 Buck2 支持:

$ cd rust-buck2
$ buck2 init --git --allow-dirty
Reinitialized existing Git repository in /home/eli/GitMono/rust-buck2/.git/
Cloning into '/home/eli/GitMono/rust-buck2/prelude'...
remote: Enumerating objects: 19987, done.
remote: Counting objects: 100% (15879/15879), done.
remote: Compressing objects: 100% (4026/4026), done.
remote: Total 19987 (delta 11767), reused 15823 (delta 11737), pack-reused 4108
Receiving objects: 100% (19987/19987), 5.50 MiB | 641.00 KiB/s, done.
Resolving deltas: 100% (15035/15035), done.

这个时候目录结构如下, 添加了 Buck2 的一些配置文件和 prelude 目录,

$tree -a -L 1

├── BUCK
├── .buckconfig
├── .buckroot
├── Cargo.toml
├── .git
├── .gitignore
├── .gitmodules
├── prelude
├── src
└── toolchains

编译

当前 BUCK 文件内容还是初始化的部分, 执行后会在 buck-out 目录下生成 out.txt 文件。

# A list of available rules and their signatures can be found here: https://buck2.build/docs/api/rules/

genrule(
    name = "hello_world",
    out = "out.txt",
    cmd = "echo BUILT BY BUCK2> $OUT",
)
$ buck2 build //...
Could not connect to buck2 daemon, starting a new one...
Connected to new buck2 daemon.
Build ID: 20514717-e6cc-443e-bfa9-b375e5adabf8
Jobs completed: 42. Time elapsed: 0.0s.
Cache hits: 0%. Commands: 1 (cached: 0, remote: 0, local: 1)
BUILD SUCCEEDED

BUCK 文件进行修改, 使用编译 Rust ToolChain 编译代码,

rust_binary(
    name = "rust-buck2",
    srcs = glob(["src/**/*.rs"]),
    crate_root = "src/main.rs",
)
$ buck2 build //:rust-buck2
File changed: root//BUCK
Build ID: 5106983d-7d75-4a7b-ad91-c700a0633851
Jobs completed: 40. Time elapsed: 0.1s.
Cache hits: 0%. Commands: 1 (cached: 0, remote: 0, local: 1)
BUILD SUCCEEDED
$ buck2 run //:rust-buck2
Build ID: f407f0d4-b7b5-4309-960b-01e265a2a02b
Jobs completed: 3. Time elapsed: 0.0s.
BUILD SUCCEEDED
Hello, world!

修改 Toolchain 配置

使用 prelude 目录下的规则文件修改 toolchains 目录下的 BUCK 文件, 删除默认的 load("@prelude//toolchains:demo.bzl", "system_demo_toolchains")system_demo_toolchains()

load("@prelude//toolchains:rust.bzl", "system_rust_toolchain")
load("@prelude//toolchains:genrule.bzl", "system_genrule_toolchain")
load("@prelude//toolchains:cxx.bzl", "system_cxx_toolchain")
load("@prelude//toolchains:python.bzl", "system_python_bootstrap_toolchain")

system_genrule_toolchain(
    name = "genrule",
    visibility = ["PUBLIC"],
)

system_rust_toolchain(
    name = "rust",
    default_edition = "2021",
    visibility = ["PUBLIC"],
)

system_cxx_toolchain(
    name = "cxx",
    visibility = ["PUBLIC"],
)

system_python_bootstrap_toolchain(
    name = "python_bootstrap",
    visibility = ["PUBLIC"],
)

目前这个 Toolchain 可以用于更多的项目, 例如 C++ 项目, Python 项目等等。


测试的项目在 GitHub - Rust Buck2 Example , 后续会持续更新。

Rust Monorepo Template with Buck2 中, 正在持续尝试构建一个完整的 Rust Monorepo 工程模板, 通过 Buck2Reindeer 管理整个工程的构建和测试, 可以从这个项目中开始你的 Rust Monorepo 之旅。