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