Buck2 编译 Rust 工程处理 feature 的问题

feature 是 Rust 开发过程中非常重要的特性,开发者可以通过 Feature 实现代码编码在不同条件下的行为,以下是一个简单的 Feature 示例:

fn main() {
    #[cfg(feature = "debug")]
    println!("Debug mode is enabled!");

    #[cfg(feature = "release")]
    println!("Release mode is enabled!");

    println!("Hello, world!");
}

当编译我们使用 cargo build --release 编译时,会启用 release Feature,输出如下:

cargo run --features="release"
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.00s
Running `target/debug/buck2-build-rust-feature`
Release mode is enabled!
Hello, world!

当我们编写 BUCK 文件的时候如何处理呢,当然我们可以写几个目标任务,例如:

load("@prelude//toolchains:rust.bzl", "system_rust_toolchain")

rust_binary(
    name = "main-release",
    srcs = glob(["src/**/*.rs"]),
    crate_root = "src/main.rs",
    features = ["release"],
)

rust_binary(
    name = "main-debug",
    srcs = glob(["src/**/*.rs"]),
    crate_root = "src/main.rs",
    features = ["debug"],
)

这样 BUCK 文件非常臃肿,当 Feature 有多个且需要组合的时候, 这个方式就变得不再可行。所以我们要编写一个 rule 来处理外部传入的 Feature 参数,实现动态的构建:

# config.bzl
def get_rust_features():
    features_config = read_config("rust", "features", "")
    
    if features_config == "":
        return []
    return [f.strip() for f in features_config.split(",") if f.strip()]
load("@prelude//toolchains:rust.bzl", "system_rust_toolchain")
load("//:config.bzl", "get_rust_features")

rust_binary(
    name = "rust-features",
    srcs = glob(["src/**/*.rs"]),
    crate_root = "src/main.rs",
    features = get_rust_features(),
)

当执行 buck2 build 命令时,使用参数 --config 参数传入 Feature 即可:

buck2 run //:rust-features                             
Build ID: b28ffbd2-3244-453f-80fc-ffab59e4ee2c
Loading targets.   Remaining     0/1                                                                                                                                                                          56 dirs read, 1 targets declared
Analyzing targets. Remaining     0/50                                                                                                                                                                         35 actions, 64 artifacts declared
Executing actions. Remaining     0/7                                                                                                                                                                          0.8s exec time total
Command: run.      Finished 1 local                                                                                                                                                                                                                                                
Time elapsed: 0.8s
BUILD SUCCEEDED
Starting RUN of `//:rust-features`
Running defined output located at: `/Users/eli/GitMono/buck2-build-rust-feature/buck-out/v2/gen/root/200212f73efcd57d/__rust-features__/rust_features`
Hello, world!

#---

buck2 run //:rust-features --config rust.features=debug
Build ID: daf63b18-34a0-4a1d-80cc-da10e64f7983
Loading targets.   Remaining     0/1                                                                                                                                                                          1 targets declared
Analyzing targets. Remaining     0/1                                                                                                                                                                          35 actions, 64 artifacts declared
Executing actions. Remaining     0/5                                                                                                                                                                          0.4s exec time total
Command: run.      Finished 1 local                                                                                                                                                                                                                                                
Time elapsed: 0.4s
BUILD SUCCEEDED
Starting RUN of `//:rust-features`
Running defined output located at: `/Users/eli/GitMono/buck2-build-rust-feature/buck-out/v2/gen/root/200212f73efcd57d/__rust-features__/rust_features`
Debug mode is enabled!
Hello, world

#---

buck2 run //:rust-features --config rust.features=debug,release
File changed: root//README.md
Build ID: a6c85fd0-8e8e-44eb-9a60-48c9223d41e1
Loading targets.   Remaining     0/1                                                                                                                                                                          1 targets declared
Analyzing targets. Remaining     0/1                                                                                                                                                                          35 actions, 64 artifacts declared
Executing actions. Remaining     0/5                                                                                                                                                                          0.4s exec time total
Command: run.      Finished 1 local                                                                                                                                                                                                                                                
Time elapsed: 0.4s
BUILD SUCCEEDED
Starting RUN of `//:rust-features`
Running defined output located at: `/Users/eli/GitMono/buck2-build-rust-feature/buck-out/v2/gen/root/200212f73efcd57d/__rust-features__/rust_features`
Debug mode is enabled!
Release mode is enabled!
Hello, world!

当然这只是简单的一个 Feature 示例,实际情况可能要比这个还要复杂,所以下一篇找一个实际项目来编写更复杂的 BUCK 文件。

代码托管在 GitHub 上,请访问 buck2-build-rust-feature