一个 C 或 C++ 包通常由多个 C 和 C++ 构件、头文件、编译后的库和可执行文件组成。但也有一些文件可能对于正常使用该包并不必要,但对于技术或业务原因可能非常重要,例如法规、合规性、安全性、可重复性和可追溯性。一些例子包括

  • 完整构建日志
  • 测试可执行文件
  • 运行测试套件的测试结果
  • 调试构件,例如大型 .pdb 文件
  • 覆盖率、消毒剂或其他源代码或二进制分析工具的结果
  • 关于构建的上下文和元数据,包括确切的机器、环境、作者、CI 数据
  • 其他合规性和安全相关文件

这些文件的问题在于它们可能很大/很重,如果我们将它们存储在包内(仅将构件复制到 package() 方法中),这将使包变得更大,并且会影响下载、解压缩和使用包的速度。这种情况在开发人员机器和 CI 中经常发生,会影响开发人员体验和基础设施成本。此外,包是不可变的,也就是说,一旦创建了包,就不能修改它。如果我们想要在创建包后或甚至在上传包后添加额外的元数据文件,这可能是一个问题。

新的 **元数据文件** 功能允许以集成和统一的方式创建、上传、追加和存储与包关联的元数据,同时避免对开发人员和 CI 速度和成本的影响,因为元数据文件在使用包时默认不会下载和解压缩。

创建元数据

配方可以直接定义元数据,一个常见的用例是将构建日志作为元数据存储,在配方中明确地进行存储,可以通过将文件或文件夹复制到 self.package_metadata_folder 来实现。

import os
from conan import ConanFile
from conan.tools.files import copy


class Pkg(ConanFile):
  name = "pkg"
  version = "0.1"

  def build(self):
      # logs originated at build() step, the most common ones
      # assume that "mylogs.txt" is the output of some build steps 
      copy(self, "mylogs.txt", src=self.build_folder,
          dst=os.path.join(self.package_metadata_folder, "logs"))

当该配方从源代码构建时,无论是在 Conan 缓存中使用 conan create 还是在本地使用 conan build,它都会将这些日志复制到“metadata”文件夹。当包在缓存中创建时,我们可以借助 conan cache path 命令轻松检查 metadata 文件夹。

$ conan create .
$ conan cache path pkg/0.1:package_id --folder=metadata
# folder containing the specific "package_id" binary metadata

如果相同的文件在多个包的构建中创建,我们也可以使用钩子。让我们看一下这个更简单的配方,它没有明确地存储构建日志的元数据,而是在构建时只生成文件。

from conan import ConanFile
from conan.tools.files import save


class Pkg(ConanFile):
  name = "pkg"
  version = "0.1"

  def build(self):
      # logs originated at build() step, the most common ones
      # assume that "mylogs.txt" is the output of some build steps
      save(self, "mylogs.txt", "some logs!!!")

可以定义一个 post_build 钩子,它与配方内版本具有相同的效果,主要区别在于钩子适用于所有包。

import os
from conan.tools.files import copy


def post_build(conanfile):
      conanfile.output.info("post_build")
      copy(conanfile, "*", src=conanfile.build_folder,
        dst=os.path.join(conanfile.package_metadata_folder, "logs"))

元数据文件也可以在创建包后添加或修改。为此,使用 conan cache path 命令将返回执行该操作的文件夹,因此在该位置复制、创建或修改文件将实现此目的。并且允许执行此操作,与修改包文件相反,因为包必须是不可变的。

$ conan create . --name=pkg --version=0.1
$ conan cache path pkg/0.1:package_id --folder=metadata
# we can copy and put files in that folder

上传元数据

到目前为止,元数据已在本地创建并存储在 Conan 缓存中。将元数据上传到服务器已与现有的 conan upload 命令集成。

$ conan upload "*" -c -r=myremote
# Uploads recipes, packages and metadata to the "myremote" remote
...
pkg/0.1: Recipe metadata: 1 files
pkg/0.1:da39a3ee5e6b4b0d3255bfef95601890afd80709: Package metadata: 1 files

默认情况下,conan upload 会在将配方或包上传到服务器时上传配方和包的元数据。

但有些情况下,Conan 会完全避免此上传,如果它检测到修订版已存在于服务器中,则不会上传配方或包。如果元数据已在本地修改或添加了新文件,我们可以使用 --metadata 参数显式强制上传元数据。

# We added some metadata to the packages in the cache
# But those packages already exist in the server
$ conan upload "*" -c -r=myremote --metadata="*"
...
pkg/0.1: Recipe metadata: 1 files
pkg/0.1:da39a3ee5e6b4b0d3255bfef95601890afd80709: Package metadata: 1 files

使用 --metadata 参数,我们可以指定要上传的元数据文件。如果我们将它们组织在文件夹中,例如,我们可以指定 --metadata=logs* 仅上传 logs 元数据。

# Upload only the logs metadata of the zlib/1.2.13 binaries
# This will upload the logs even if zlib/1.2.13 is already in the server
$ conan upload "zlib/1.2.13:*" -r=myremote -c --metadata="logs/*"
# Multiple patterns are allowed:
$ conan upload "*" -r=myremote -c --metadata="logs/*" --metadata="tests/*"

下载元数据

如引言中所述,元数据默认不会下载。当使用 conan installconan create 从服务器获取依赖项下载包时,不会下载来自这些服务器的元数据。

从服务器恢复元数据的方法是使用 conan download 命令显式指定它。

# Get the metadata of the "pkg/0.1" package
$ conan download pkg/0.1 -r=myremote --metadata="*"
...
$ conan cache path pkg/0.1:package_id --folder=metadata
# Inspect the package metadata for binary "package_id"

元数据的检索是通过 download 命令针对每个包进行的。如果我们要下载整个依赖关系图的元数据,则需要使用“package-lists”。

$ conan install . --format=json -r=myremote > graph.json
$ conan list --graph=graph.json --format=json > pkglist.json
# the list will contain the "myremote" origin of downloaded packages
$ conan download --list=pkglist.json --metadata="*" -r=myremote

请注意,“package-list”只包含与“myremote”来源关联的已下载的包。如果它们之前已经在缓存中,那么它们不会列在“myremote”来源下,元数据也不会被下载。如果你想收集依赖项的元数据,请记住在从服务器安装包时下载它。还有其他可能性,例如一个自定义命令,可以自动从服务器收集和下载依赖项的元数据。

结论

**元数据文件** 一直是人们期待已久的功能,我们很高兴能够发布它。我们相信它将帮助许多用户更好地管理他们的元数据文件和资产,简化这些文件的管理、存储、跟踪和检索。这可以减少实施更好合规性、可重复性、可追溯性和安全性的工作量和成本。

重要的是要强调,这项新功能的添加得益于新的 Conan 2.0 架构和功能。Conan 2.0 这个新主要版本的必要原因之一是解锁这些期待已久的功能,这些功能在 Conan 1.X 中无法实现。

有关元数据文件和其他相关功能的更多信息,请查看新的文档 Devops 指南

我们期待收到您的反馈、用例和需求,以便不断改进此功能。请在 Github 问题 中报告。