build_id()

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

它主要是一种优化工具,适用于 **分别构建每种配置不可行** 的情况。

在某些情况下,这可能很有用,例如,当一个包的构建

  • 在单次构建运行中生成多种配置:一些构建脚本总是同时生成 Debug 和 Release 产物,而无法单独构建它们。

  • 生成一种配置但集合不同的产物:构建可以生成主库以及一些测试可执行文件,而您希望创建

    • 一个仅包含库(供通用使用)的包,以及

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

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

构建文件夹如何与包 ID 和构建 ID 相关联?

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

  • 一般来说,**包 ID** 取决于 settingsoptions 和依赖项的组合。

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

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

  • 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 只打包一个包二进制文件**。