本地食谱索引仓库

本地食谱索引 (Local Recipes Index) 是 Conan 中引入的一项 实验性 仓库类型,旨在增强管理 C/C++ 包食谱的灵活性。这种仓库类型允许用户将本地目录用作 Conan 远程仓库,其中目录结构模仿了 conan-center-index GitHub 仓库的结构。

这种设置特别适用于:

  • 从私有的 conan-center-index 分支构建二进制文件。

  • 共享您自己的某些库或工具的食谱,这些库或工具由于许可限制或专有性质,不适合 ConanCenter。请在文档的专门章节 本地食谱索引仓库 中查看如何为此目的使用它。

从私有的 conan-center-index 分支构建二进制文件

正如我们在 Conan DevOps 指南的前一节 中介绍的,一些组织(尤其是大型企业)倾向于不使用从互联网下载的二进制文件。相反,他们使用 conan-center-index 食谱在内部构建自己的二进制文件。这些组织经常需要自定义这些食谱以满足更广泛的社区不适用的独特需求,使得这些贡献不适合上游仓库。

local-recipes-index 允许用户维护一个与 conan-center-index GitHub 仓库具有相同结构的本地文件夹,并将其用作包食谱的来源。这种新型仓库仅包含食谱,因此需要在每个使用该包的机器上从源代码构建包的二进制文件。对于跨团队共享二进制文件,我们继续建议在生产环境中使用 Conan 远程服务器,如 Artifactory

../_images/local-repo-general-flow-diagram.png

local-recipes-index 仓库允许您轻松地从 conan-center-index 的分支构建二进制文件,然后将其托管在 Artifactory 等 Conan 远程仓库中。与上一节 中解释的流程 的主要区别在于,无需在每次修改食谱时导出,即可立即测试多个本地更改。

请注意,在这种情况下,不建议将来自 ConanCenter 的二进制文件与本地构建的二进制文件混合使用,原因如下:

  • 二进制兼容性:ConanCenter CI 和用户 CI 之间的设置可能存在细微差异。为所有二进制文件维护一致的设置可以缓解一些问题。

  • 完全控制构建:构建所有二进制文件可确保您对编译环境和依赖版本拥有完全控制权。

相反,建议从分支构建所有直接和传递依赖项。首先,删除上游 ConanCenter,因为它将不被使用,所有内容将来自我们自己的分支。

$ conan remote remove conancenter

然后,我们将克隆我们的分支(在此示例中,我们直接克隆上游以进行演示,但您将克隆您的分支)

$ git clone https://github.com/conan-io/conan-center-index

将此添加为我们的 mycenter 远程仓库。

# Add the mycenter remote pointing to the local folder
$ conan remote add mycenter ./conan-center-index

这就完成了!现在您已准备好列出并使用来自您的 conan-center-index 本地文件夹的包。

$ conan list "zlib/*" -r=mycenter
mycenter
  zlib
    zlib/1.2.11
    zlib/1.2.12
    zlib/1.2.13
    zlib/1.3
    zlib/1.3.1

我们还可以从此仓库安装包,例如,我们可以执行

$ conan install --requires=zlib/1.3
...
======== Computing dependency graph ========
zlib/1.3: Not found in local cache, looking in remotes...
zlib/1.3: Checking remote: mycenter
zlib/1.3: Downloaded recipe revision 5c0f3a1a222eebb6bff34980bcd3e024
Graph root
    cli
Requirements
    zlib/1.3#5c0f3a1a222eebb6bff34980bcd3e024 - Downloaded (mycenter)

======== Computing necessary packages ========
Requirements
    zlib/1.3#5c0f3a1a222eebb6bff34980bcd3e024:72c852c5f0ae27ca0b1741e5fd7c8b8be91a590a - Missing
ERROR: Missing binary: zlib/1.3:72c852c5f0ae27ca0b1741e5fd7c8b8be91a590a

正如我们所见,Conan 成功地从 mycenter 获取了 zlib/1.3 的食谱,但由于没有二进制文件而失败。这是预期的,该仓库仅包含食谱,但不包含二进制文件。我们可以使用 --build=missing 参数从源代码构建二进制文件。

$ conan install --requires=zlib/1.3 --build=missing
...
zlib/1.3: package(): Packaged 2 '.h' files: zconf.h, zlib.h
zlib/1.3: package(): Packaged 1 file: LICENSE
zlib/1.3: package(): Packaged 1 '.a' file: libz.a
zlib/1.3: Created package revision 0466b3475bcac5c2ce37bb5deda835c3
zlib/1.3: Package '72c852c5f0ae27ca0b1741e5fd7c8b8be91a590a' created
zlib/1.3: Full package reference: zlib/1.3#5c0f3a1a222eebb6bff34980bcd3e024:72c852c5f0ae27ca0b1741e5fd7c8b8be91a590a#0466b3475bcac5c2ce37bb5deda835c3
zlib/1.3: Package folder /home/conan/.conan2/p/b/zlib1ed9fe13537a2/p
WARN: deprecated: Usage of deprecated Conan 1.X features that will be removed in Conan 2.X:
WARN: deprecated:     'cpp_info.names' used in: zlib/1.3

======== Finalizing install (deploy, generators) ========
cli: Generating aggregated env files
cli: Generated aggregated env files: ['conanbuild.sh', 'conanrun.sh']
Install finished successfully

现在我们可以在本地缓存中看到二进制包。

$ conan list "zlib:*"
Local Cache
  zlib
    zlib/1.3
    revisions
      5c0f3a1a222eebb6bff34980bcd3e024 (2024-04-10 11:50:34 UTC)
      packages
        72c852c5f0ae27ca0b1741e5fd7c8b8be91a590a
        info
          settings
            arch: x86_64
            build_type: Release
            compiler: gcc
            compiler.version: 9
            os: Linux
          options
            fPIC: True
            shared: False

最后,将二进制包上传到我们的 Artifactory 仓库,使其可供我们的组织、用户和 CI 作业使用。

$ conan remote add myartifactoryrepo <artifactory_url>
$ conan upload zlib* -r=myartifactoryrepo -c

这样,包的消费者不仅可以享用预编译的二进制文件,避免总是从源代码重新构建所有依赖项,而且还能确保依赖项的构建和工作正常,所有依赖项和传递依赖项都能良好协作等等。将二进制文件的创建过程与二进制文件的消耗过程解耦是实现更快、更可靠的依赖项使用的途径。

请记住,在生产环境中,conan upload 命令应由 CI 执行,而不是开发人员,并遵循 Conan 指南。这种方法可确保包的消费者享用预编译的二进制文件以及跨依赖项的一致性。

修改 local-recipes-index 仓库文件

这种方法的一个优点是,我们在每个食谱中所做的所有更改都会自动被 Conan 客户端识别。例如,对 recipes/zlib/config.yml 文件的更改会立即被 Conan 客户端识别。如果您编辑该文件并删除除最新版本之外的所有版本,然后我们 list 这些食谱

$ conan list "zlib/*" -r=mycenter
mycenter
  zlib
    zlib/1.3.1

当某些食谱发生更改时,请注意,当前的 Conan 主目录已包含该包的缓存副本,因此除非我们明确使用 --update,否则它不会更新,这与其他 Conan 远程仓库行为一致。

因此,如果我们对 recipes/zlib/all/conanfile.py 中的 zlib 食谱进行更改并重复

$ conan install --requires=zlib/1.3.1 -r=mycenter --update --build=missing

我们将立即在 Conan 主目录中获得从新修改的食谱从源代码本地构建的新包二进制文件。

在生产环境中使用 Local-Recipes-Index 仓库

在使用此新功能时,应考虑几个要点:

  • 它适用于 第三方包,其中一个仓库中的食谱正在创建来自其他位置的源的包。要打包您自己的代码,建议采用将 conanfile.py 食谱与源代码一起添加并使用标准的 conan create 流程。

  • local-recipes-index 仓库指向 文件系统中的本地文件夹。虽然用户可能会选择将该文件夹与 git 仓库或其他版本控制机制同步,但 Conan 对此是无关紧要的,因为它只知道指向仓库(当前)状态的文件系统中的文件夹。用户可以选择直接运行 git 命令来切换分支/提交/标签,Conan 会自动识别更改。

  • 这种方法在源代码层面运行,不生成包的二进制文件。对于开发和生产环境的部署,使用 Artifactory 等远程包服务器至关重要。需要注意的是,此功能不能替代 Conan 的远程包服务器,后者在托管常规使用的包方面起着至关重要的作用。

  • 此外,请注意,服务器远程仓库可以保留存储多个食谱修订版的变化历史。相比之下,local-recipes-index 远程仓库在任何给定时间只能代表一个快照。

  • ConanCenter 不使用 python-requires,因为这是一种更适用于第一方包的机制。目前,在 local-recipes-index 仓库中使用 python-requires 是可能的(且处于实验阶段),但前提是 python-requires 也在同一个索引仓库中。不支持或计划支持将这些 python-requires 放在其他仓库或用户 Conan 缓存中。

此外,此功能不支持直接在食谱中放置服务器 URL;必须通过 conan remote add 显式添加远程仓库。将抽象包要求(如“zlib/1.3.1”)与其特定来源分离对于正确解析依赖项和利用 Conan 的图功能(包括版本冲突检测和解析、版本范围解析、选择预发布版本platform_requiresreplace_requires 等)至关重要。这种分离还有助于实现现代 DevOps 实践,例如包的不可变性、完全可重定位性和包提升。