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