Conan 2 新的图形功能:用系统需求和 API 兼容依赖项替换依赖项
我们很高兴地宣布,Conan 2.0 的最新版本实现了一些长期以来一直被要求的功能,但由于 Conan 1.X 的遗留问题和限制,这些功能几乎不可能实现。Conan 2.0 的一大优势在于其新的架构和设计允许维护人员快速构建和发布像这三个新功能这样的功能。
- 能够完全删除任何 Conan recipe 中依赖关系图中定义的
requires
,并使用系统安装的依赖项,使用[plaform_requires]
功能。此功能在不同的场景中非常有用,例如避免 recipe 获取cmake
Conan 包,因为它们是tool_requires = "cmake/version"
并使用系统安装的版本,而无需修改任何 recipe。 - 能够用任何其他依赖项(只要它与 API 兼容)替换依赖关系图中任何 recipe 的
requires
依赖项,使用[replace_requires]
功能。此功能可用于替换常规的requires
,以实现系统包装器等效项,或替换 API 兼容的包,例如将zlib
替换为zlib-ng
或libjpeg
替换为libjpeg-turbo
,而无需修改任何 recipe。 - 能够详细解释何时缺少二进制文件,将缺少的二进制文件的设置、选项和依赖项与缓存和远程仓库中现有的二进制文件进行比较,并显示类似 diff 的结果,使用新的
conan graph explain
命令。
此外,前两个功能能够应用于常规的 requires
和 tool_requires
。让我们详细了解一下这些新功能。
用系统依赖项替换 Conan 依赖项
Conan recipe 在其代码中可以同时具有 requires
和 tool_requires
,例如,让我们使用一个典型的 tool_requires
到 Conan cmake
包,版本至少为 3.25,因为 mypkg
中的 CMakeLists.txt
需要一些现代 CMake 功能。
from conan import ConanFile
class Pkg(ConanFile):
name = "mypkg"
tool_requires = "cmake/[>=3.25]"
现在,每当从源代码构建 mypkg
时,它都会下载一个 cmake/xxx
Conan 包,注入它并使用它来构建。过去,无论用户在系统中安装了哪个 CMake,都会发生这种情况。使用此新功能,用户可以在其配置文件中定义:
[platform_tool_requires]
cmake/3.26
定义他们在系统中安装的版本。使用此配置文件,现在 mypkg
将不再从服务器下载 cmake
包,而是使用系统安装的版本。唯一的条件是系统安装的版本必须可用于构建,在本例中,即 CMake,它应该位于系统 PATH(或在 tools.cmake:cmake_program
配置中定义的位置)。
平台需求系统能够检查版本。例如,如果某个 recipe 有一个 tool_requires = "cmake/[>=3.27]"
,那么它将知道系统安装的 CMake 不够,它仍然会下载一个满足约束的 cmake
包,并将其用于该包,对于所有对系统 3.26 版本满意的其他包,则使用系统安装的 CMake。
通过 [platform_requires]
功能,为常规的 requires
提供了相同的功能。这可能是删除像 requires = "openssl/3.1"
这样的 Conan 依赖项的情况,该依赖项需要一个 Conan 包,并改为使用系统安装的 openssl
。例如,当交叉构建到某些嵌入式目标时,这可能是可取的,这些目标将在系统中提供自己的特定 openssl
(如在构建期间的 sysroot 中),必须使用它。请注意,系统 openssl
必须可用且可供使用者链接,以便完全透明地链接它,因为 Conan 将不再向使用者注入有关它的任何信息。在许多情况下,这种透明的使用将不可能,因为使用者仍然需要一些额外信息来定位和使用这些系统安装的依赖项。在这种情况下,以下 [replace_requires]
将是推荐的方法。
使用 [replace_requires] 替换 API 兼容的需求
在某些情况下,更改依赖关系图中定义的 requires
可能会非常方便。
例如,如果我们项目中的所有 recipe 都需要 requires = "zlib/1.3"
,然后我们想引入使用 zlib-ng
替代方案的功能,则有两种不同的方法:只需在所有地方替换需求并始终使用 zlib-ng
(如果我们可以删除 zlib
),或者根据输入 options
或 conf
实现条件需求。第一种方法在 ConanCenter 等地方可能是不可行的,第二种方法可能很繁琐且容易出错。
使用此新功能,可以通过在配置文件中定义:
[replace_requires]
zlib/*: zlib-ng/*
这将替换每个 requires = "zlib/<anyversion>"
,以实现相同的要求,相当于 requires = "zlib-ng/<anyversion>"
,使用与声明版本相同的版本。
但有时,版本之间没有 1:1 映射,对于这些情况,也可以显式声明映射。
[replace_requires]
zlib/1.0: zlib-ng/11.0
zlib/2.0: zlib-ng/12.0
同样,也可以使用版本范围进行替换。
[replace_requires]
zlib/3.0: zlib-ng/[>=13.0]
在这种情况下,与 zlib/3.0
完全匹配的将被该特定范围内的 zlib-ng
替换。但其他版本的 zlib/xxx
将不会被替换。也可以在第一个模式中定义版本范围。
[replace_requires]
zlib/[>=3.0]: zlib-ng/[>=13.0]
在这种情况下,如果原始范围 zlib/[>=3.0]
由 recipe 的 requires
满足,则将发生替换,无论是范围内的精确版本,还是如果 recipe 也声明了一个版本范围,只要范围之间存在一些重叠。
此功能还有一些其他有趣的用例:例如,它可以用于在根本无需修改任何 conanfile
的情况下**临时**解决冲突。请注意,这不是作为永久冲突解决策略,但它在开发和测试事物时可能很有用。
最后,对于上面必须从系统中使用 openssl
的情况(可能它在 sysroot 中),但它需要一些额外信息以便其他包能够轻松使用它。在这种情况下,用户可以:
-
首先编写一个替代的
openssl/<version>@system
,它不构建任何内容,而主要是在其package_info()
中定义用于定位和为其他包使用它的信息。 -
然后定义包含以下内容的配置文件:
[replace_requires] openssl/*: openssl/*@system
使用该配置文件,requires = "openssl/version"
的出现将被 requires = "openssl/version@system"
替换,后者将使用之前提供的包装 recipe,其中包含有关该 sysroot 中该依赖项的详细信息。
[replace_requires]
对常规的 requires
有效。还有一个 [replace_tool_requires]
用于相同目的,但用于 tool_requires
,规则和行为相同。
在构建和主机配置文件中使用 [platform_requires] 和 [replace_requires]
由于 [platform_requires]
、[platform_tool_requires]
、[replace_requires]
和 [replace_tool_requires]
在配置文件中定义,因此可以在“主机”和“构建”配置文件中定义它们。
这意味着可以控制在哪个上下文中执行这些替换。例如,使用 sysroot 中 openssl
的交叉构建场景中的 [replace_requires]
,如果由于某种原因构建上下文碰巧需要 openssl 作为传递依赖项,则构建上下文很可能不想使用 sysroot 中的 openssl
。因此,[replace_requires]
应该只在“主机”配置文件中发生,而不是在“构建”配置文件中发生。
另一方面,上面使用 [platform_tool_requires]
的 CMake 示例将适用于这两种情况。即使我们是否正在交叉构建, “主机”(常规库和应用程序)上下文中的包都将使用系统安装的 CMake。但是,如果“构建”上下文中的任何依赖项,我们用作 tool_requires
的任何应用程序都需要从源代码构建,它可能需要 CMake 本身作为传递 tool_requires
,并且如果可能,它可以使用系统安装的 CMake。对于这种情况,我们希望在“主机”和“构建”配置文件中都定义相同的 [platform_tool_requires]
。
额外图形功能:使用“conan graph explain”了解某些二进制文件丢失的原因
Conan 1.X 中一个常见的问题是安装本应作为预编译二进制文件存在的 Conan 包时遇到“缺少二进制文件”错误。该错误看起来像这样
$ conan install --requires=zlib/1.3 -s build_type=Debug
即使此错误消息提供了一些有关缺少二进制文件的信息,但也不清楚为什么缺少该二进制文件。现在,正如错误消息所建议的那样,我们有 conan graph explain
命令。基本上输入相同的 conan install
命令,但现在使用 graph explain
来获取类似以下内容的信息
$ conan graph explain --requires=zlib/1.3 -s build_type=Debug
这清楚地解释并用颜色突出显示了缺少此二进制文件的原因。在本例中,这是因为 ConanCenter 没有为该编译器版本构建 Debug 二进制文件,并且只有 Release 二进制文件可用。
conan graph explain
命令旨在解释导致二进制文件丢失的所有可能差异,从设置、选项、依赖项版本、配置等方面的差异。
结论
Conan 2 中的新增功能提供了一些非常强大的功能,这些功能允许在依赖项解析中获得更大的灵活性,并实现了长期以来的请求,例如能够替换 API 兼容的依赖项或使用系统安装的工具而不是声明的配方。
请查看 replace_requires、platform_requires 和 conan graph explain 的文档。我们期待收到您对此的反馈,请随时分享您的反馈、报告任何错误或在 GitHub 问题中提出任何问题。