#build-script #configuration #cargo

conf_test

从 build.rs 运行配置测试并设置可用功能

8个版本 (4个破坏性更新)

0.5.0 2023年5月4日
0.4.0 2023年5月3日
0.3.2 2023年5月3日
0.3.1 2022年12月22日
0.1.2 2021年4月28日

#584配置

Download history 9/week @ 2024-03-12 4/week @ 2024-03-26 33/week @ 2024-04-02

每月104 次下载
2 个包中使用 (通过 openat_ct)

MIT/Apache

19KB
258

Rust conf_test

从 build.rs 运行配置测试并设置可用功能,类似于 autotools 配置脚本。

描述

ConfTest::run() 从 'build.rs' 中调用,解析 'Cargo.toml'。然后对于每个定义的 [feature],它检查该功能是否未手动设置(使用 --features)并且 'conf_tests/' 中存在测试。然后编译并构建此测试。如果成功,则该功能会自动启用。


lib.rs:

从 build.rs 运行配置测试并设置可用功能,类似于 autotools 配置脚本。

描述

ConfTest::run() 从 'build.rs' 中调用,解析 'Cargo.toml'。然后对于每个定义的 [feature],它检查该功能是否未手动设置(使用 --features)并且 'conf_tests/' 中存在测试。然后编译并构建此测试。如果成功,则该功能会自动启用。

'docs.rs' 的特殊案例

当在 'docs.rs' 上为文档构建包时,conf_test 会检测并检查 'Cargo.toml' 中是否有可用的 docs_rs = [] 功能,如果有,则启用。如果没有,则不进行探测。

理由

编译器版本和操作系统在功能和标准一致性方面有时存在细微差异。有时为了提高性能会添加非标准功能。这些差异使得编写可移植软件变得困难,同时仍能为不同的操作系统提供最佳性能。此外,开发者可能甚至不知道其他操作系统可能提供哪些功能集,或者这些可能由内核或用户空间版本或配置更改。在构建时探测这些功能的存在可以解决这些问题。

此外,还可以测试 Rust stdlib 功能,例如检查夜间功能是否可用或已成为稳定功能。

如何使用

检查操作系统功能

当存在时,'cargo'(构建和)在构建包时执行一个 build.rs 脚本。这是首次将 ConfTest 集成的位置。

fn main() {
    conf_test::ConfTest::run();
    // any other build.rs steps follow below
}

接下来,需要在 'Cargo.toml' 中定义一组功能和依赖项。请注意,'build.rs' 会在 '[dependencies]' 构建之前运行。因此,所有必需的测试依赖项都必须放入 '[build-dependencies]'。例如

[dependencies]
libc = "0.2.34"

[build-dependencies]
libc = "0.2.34"
conf_test = "0.4"

[features]
default = []
o_path = []

最后一步是在包目录中创建 'conf_tests/',其中包含要探测的功能命名的 Rust 文件。包含一个单独的 fn main(),它将探测单个东西。

// This goes into conf_tests/o_path.rs
extern crate libc;

fn main() {
    unsafe {
        let conf_tests = std::ffi::CString::new("conf_tests").unwrap();
        // Compilation will fail when the libc does not define O_PATH
        libc::open(conf_tests.as_ptr(), libc::O_PATH);
    }
}

在crate实现源代码中,通常会使用条件编译,如下所示:#[cfg(feature = "o_path")]

依赖于其他功能的测试

测试可能依赖于其他测试发现的或手动设置的特性。为了简化,这里没有依赖解析器,但测试将按照特性名称的顺序运行。每个后续测试都将使用到目前为止已经发现的特性标志进行编译。为了利用这个功能,很少需要更改特性名称。例如,当'bar'依赖于'foo'时,需要通过将这些特性重命名为'aa_foo'和'bb_bar'来强制排序。只有被发现的特性才会用于测试编译,从测试脚本中打印的cargo指令设置的特性集不会使用。

详细控制

测试可以发出特殊的指令到cargo的stdout。这些指令只有在测试成功退出时才会生效。请参阅https://doc.rust-lang.net.cn/cargo/reference/build-scripts.html#outputs-of-the-build-script

可以通过设置环境变量CONF_TEST_INHIBIT来控制ConfTest,可以是以下之一:

  • skip 不会执行任何conf_tests,但会继续执行'build.rs'。
  • stop 成功退出'build.rs',不执行任何测试。
  • fail 以失败状态退出'build.rs',不执行任何测试。

其他任何值都会使脚本崩溃。

限制

  • 在构建软件的机器上运行测试,使用构建依赖项。当软件进行交叉编译时,这会成为一个问题。对于交叉编译,请设置'CONF_TEST_INHIBIT=skip'并使用'--features'选项手动设置所需的特性。

  • 特性只能设置,不能取消设置。这是故意的,不是限制。只进行确认测试,检查特性的存在。

良好实践

  • 只有当其他方法(如将特定于OS的项提取到自己的crate中)不适用时才使用ConfTest。

  • 提供一个基线实现,它是可移植的,没有启用任何特性。这可能不会表现得太好或缺少一些特殊特性,但应该可以编译。

依赖项

~1–1.7MB
~36K SLoC