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