build_id()

`build_id()` 方法允许您**重用单个构建**来创建 Conan 缓存中的多个二进制包,从而节省时间,避免不必要的重建。

它主要是一种优化工具,用于在**单独构建每个配置不可行**的情况下。

以下是一些可能用到的场景,例如,当一个包的构建

  • **在单个构建运行中生成多个配置**:某些构建脚本始终会一起生成 Debug 和 Release 构件,而无法单独构建它们。

  • **生成一个配置,但生成不同的一组构件**:构建可以生成主库以及一些测试可执行文件,您希望创建

    • 一个只包含库的包(用于通用用途),以及

    • 另一个包含库和测试二进制文件的包(用于合规性、调试或可重现性)。

在这些情况下,**重用相同的构建文件夹可以避免多次重新编译相同的源代码**,仅仅因为您需要略有不同的打包方式。

构建文件夹与包 ID 和构建 ID 有什么关系?

默认情况下,Conan 为每个唯一的包 ID 创建**一个构建文件夹**,其中

  • 通常,**包 ID** 取决于 settingsoptions 和依赖项的组合。

  • 每个不同的**包 ID** 会触发一次单独的 `build()` 执行,并生成一个单独的构建文件夹。

当您定义 `build_id()` 方法时,您可以**通过自定义 `self.info_build` 来强制不同的包 ID 共享相同的构建文件夹**

  • `self.info_build` 类似于 `self.info`,但它仅影响**构建 ID** 的计算,而不影响最终的包 ID。

  • 具有相同构建 ID 的任何包 ID 都将重用相同的构建文件夹和相同的构建步骤。

示例:共享 Debug 和 Release 的构建

settings = "os", "compiler", "arch", "build_type"

def build_id(self):
    self.info_build.settings.build_type = "Any"
  • 使用此配方,Debug 和 Release 将各自生成自己的包 ID(因此各自的二进制包),但它们将**共享相同的构建文件夹**,因为构建 ID 忽略了 `build_type` 设置。

  • **但是,您仍然需要运行一个** conan create **命令来处理每个配置**(例如,一次用于 Debug,一次用于 Release)。Conan 将检查构建文件夹是否已经存在(基于共享的构建 ID),如果它已经构建过,则跳过实际的编译,仅执行 `package()` 来创建相应的包。

示例工作流程

# First build: creates the build folder + packages the Debug package
$ conan create . -s build_type=Debug

# Second build: reuses the previous build folder + packages the Release package without rebuilding
$ conan create . -s build_type=Release

这样,虽然我们调用了两次 conan create(一次用于每个包 ID),但实际的构建只会发生一次。

注意

您还可以根据选项自定义 `build_id()`

def build_id(self):
    self.info_build.options.myoption = "MyValue"
    self.info_build.options.fullsource = "Always"

构建 ID 的条件使用

如果 `build_id()` 方法没有修改 `self.info_build` 数据,并且生成与包 ID 相同的构建 ID,则将应用标准行为。例如

settings = "os", "compiler", "arch", "build_type"

def build_id(self):
    if self.settings.os == "Windows":
        self.info_build.settings.build_type = "Any"

这将仅为 Windows 生成不同的**构建 ID**,因此它将仅为所有 `build_type` 值运行一次 `build()` 方法。

对于任何其他操作系统,Conan 的行为将与往常一样(就像未定义 `build_id()` 方法一样),为每个 `build_type` 配置运行 `build()` 方法。

注意

最佳实践

`build_id()` 方法的目的是处理无法轻松更改为一次编译一个配置的遗留构建脚本。我们强烈建议为每个不同的配置打包**每个包 ID 的一个包二进制文件**。