包管道:使用锁定文件的多配置

在之前的示例中,我们为 ai/1.1.0 构建了 DebugRelease 包二进制文件。在实际场景中,要构建的二进制文件将是不同的平台(Windows、Linux、嵌入式)、不同的架构,而且通常不可能在同一台机器上构建它们,需要不同的计算机。

之前的示例有一个重要的假设:ai/1.1.0 的依赖关系在构建过程中完全不会改变。在许多情况下,这种假设不成立,例如,如果有任何其他并发的 CI 作业,并且一个成功的作业在 develop 仓库中发布了新的 mathlib/1.1 版本。

那么,ai/1.1.0 的一个构建,例如,在 Linux 服务器上运行的那个,可能会更早开始并使用之前的 mathlib/1.0 版本作为依赖项,而 Windows 服务器稍后启动,那么它们的构建将使用最新的 mathlib/1.1 版本作为依赖项。这是一个非常不希望出现的情况,同一个 ai/1.1.0 版本的二进制文件使用了不同的依赖项版本。这可能导致以后的图解析问题,甚至更糟糕的是,导致不同平台的行为不同。

避免依赖关系出现这种差异的方法是强制使用相同的依赖项版本和修订版,这可以使用锁定文件来实现。

创建和应用锁定文件相对简单。创建和提升配置的过程将与上一节相同,只是应用锁定文件。

创建锁定文件

像往常一样,让我们确保从干净的状态开始

$ conan remove "*" -c  # Make sure no packages from last run

然后我们可以创建锁定文件 conan.lock 文件

# Capture a lockfile for the Release configuration
$ conan lock create . -s build_type=Release --lockfile-out=conan.lock
# extend the lockfile so it also covers the Debug configuration
# in case there are Debug-specific dependencies
$ conan lock create . -s build_type=Debug --lockfile=conan.lock --lockfile-out=conan.lock

请注意,使用不同配置文件或设置的不同配置可能会导致不同的依赖关系图。可以使用锁定文件来锁定不同的配置,但重要的是迭代不同的配置/配置文件并将它们的信息捕获到锁定文件中。

注意

conan.lock 是默认参数,如果存在 conan.lock 文件,conan install/create 和其他图命令可能会自动使用它。这可以简化许多命令,但本教程为了清晰和教学目的,展示了完整的显式命令。

conan.lock 文件可以检查,它将类似于

{
    "version": "0.5",
    "requires": [
        "mathlib/1.0#f2b05681ed843bf50d8b7b7bdb5163ea%1724319985.398"
    ],
    "build_requires": [],
    "python_requires": [],
    "config_requires": []
}

正如我们所看到的,它锁定了 mathlib/1.0 依赖项版本和修订版。

有了锁定文件,创建不同的配置完全相同,但将 --lockfile=conan.lock 参数提供给 conan create 步骤,它将保证 mathlib/1.0#f2b05681ed843bf50d8b7b7bdb5163ea 将始终是使用的确切依赖项,无论是否存在新的 mathlib/1.1 版本或可用的新修订版。以下构建可以并行启动,但在不同的时间执行,它们仍然会始终使用相同的 mathlib/1.0 依赖项

Release 构建
$ cd ai  # If you were not inside "ai" folder already
$ conan create . --build="missing:ai/*" --lockfile=conan.lock -s build_type=Release --format=json > graph.json
$ conan list --graph=graph.json --graph-binaries=build --format=json > built.json
$ conan remote enable packages
$ conan upload -l=built.json -r=packages -c --format=json > uploaded_release.json
$ conan remote disable packages
Debug 构建
$ conan create . --build="missing:ai/*" --lockfile=conan.lock -s build_type=Debug --format=json > graph.json
$ conan list --graph=graph.json --graph-binaries=build --format=json > built.json
$ conan remote enable packages
$ conan upload -l=built.json -r=packages -c --format=json > uploaded_debug.json
$ conan remote disable packages

请注意,与之前示例的唯一修改是添加了 --lockfile=conan.lock。提升也将与之前的相同

从 packages->product 提升
# aggregate the package list
$ conan pkglist merge -l uploaded_release.json -l uploaded_debug.json --format=json > uploaded.json

$ conan remote enable packages
$ conan remote enable products
# Promotion using Conan download/upload commands
# (slow, can be improved with art:promote custom command)
$ conan download --list=uploaded.json -r=packages --format=json > promote.json
$ conan upload --list=promote.json -r=products -c
$ conan remote disable packages
$ conan remote disable products

最终结果将与上一节相同,但这次保证 DebugRelease 二进制文件都是使用完全相同的 mathlib 版本构建的

digraph repositories { node [fillcolor="lightskyblue", style=filled, shape=box] rankdir="LR"; subgraph cluster_0 { label="Packages server"; style=filled; color=lightgrey; subgraph cluster_1 { label = "packages\n repository" shape = "box"; style=filled; color=lightblue; "packages" [style=invis]; "ai/1.1.0\n (Release)"; "ai/1.1.0\n (Debug)"; } subgraph cluster_2 { label = "products\n repository" shape = "box"; style=filled; color=lightblue; "products" [style=invis]; "ai/promoted release" [label="ai/1.1.0\n (Release)"]; "ai/promoted debug" [label="ai/1.1.0\n (Debug)"]; } subgraph cluster_3 { rankdir="BT"; shape = "box"; label = "develop repository"; color=lightblue; rankdir="BT"; node [fillcolor="lightskyblue", style=filled, shape=box] "game/1.0" -> "engine/1.0" -> "ai/1.0" -> "mathlib/1.0"; "engine/1.0" -> "graphics/1.0" -> "mathlib/1.0"; "mapviewer/1.0" -> "graphics/1.0"; "game/1.0" [fillcolor="lightgreen"]; "mapviewer/1.0" [fillcolor="lightgreen"]; } { edge[style=invis]; "packages" -> "products" -> "game/1.0" ; rankdir="BT"; } } }

现在我们在 products 仓库中有了新的 ai/1.1.0 二进制文件,我们可以认为 packages pipeline 已经完成,并转到下一节,构建和检查我们的产品,看看这个新的 ai/1.1.0 版本是否正确集成。