build_requirements()¶
build_requirements()
方法在功能上等同于 requirements()
方法,它紧随后者执行。理论上,此方法中的所有内容都可以在 requirements()
方法的末尾完成,因此它并非严格必要。不过,build_requirements()
提供了一个专用位置来定义 tool_requires
和 test_requires
,这很有益处。
def build_requirements(self):
self.tool_requires("cmake/3.23.5")
self.test_requires("gtest/1.13.0")
对于简单的情况,属性语法就足够了,例如 tool_requires = "cmake/3.23.5"
和 test_requires = "gtest/1.13.0"
。对于条件性或参数化的依赖,则可能需要方法形式。
tool_requires
和 test_requires
方法只是 requires
的一个特殊实例,预定义了一些特性值。关于特性的更多信息,请参阅 requires() 参考。
有 2 个实验性 confs
可用于避免这些类型依赖的扩展
tools.graph:skip_build
允许完全跳过tool_requires
依赖。这需要在满足两个条件时才能实现:要求这些工具的包不需要从源代码构建,并且工具依赖不影响消费者的package_id
。如果出现这种情况,Conan 将会抛出错误。tools.graph:skip_test
允许完全跳过test_requires
依赖。如果这些依赖被跳过,但随后某些包需要从源代码构建且tools.build:skip_test
未激活,则会找不到test_requires
。因此在大多数情况下,tools.build:skip_test
也应该被定义。
请注意,如果工具和/或测试依赖被跳过,它们将不会成为依赖图的一部分,也不会成为可能生成的锁定文件或包列表的一部分,这可能会影响未来的可重现性。此外,在大多数情况下,Conan 能够将工具和测试依赖标记为非必要 (Skip
),从而避免下载大型二进制文件,只下载通常非常快速的配方。这意味着在大多数情况下,这些 confs
是不必要的,并且 Conan 的默认设置很好,请在使用它们时了解其中的权衡。
tool_requires()¶
tool_requires
等同于带有以下特性的 requires()
build=True
。此依赖位于“构建”上下文,在构建时是必需的,但在应用运行时则不是,并且将接收“构建”配置文件和配置。visible=False
。工具依赖不会向下游传播。例如,一个包可以调用tool_requires("cmake/3.23.5")
,但这不意味着消费者包也使用cmake
,它们甚至可以使用不同的构建系统或不同的版本,而不会引起冲突。run=True
。此依赖包含一些在构建时需要运行的可执行文件或运行时。headers=False
:工具依赖没有头文件。libs=False
:工具依赖不包含可供消费者链接的库(如果它包含库,它们将位于“构建”上下文,并可能与消费者包的“主机”上下文不兼容)。
请注意,tool_requires
仅用于依赖在“构建”上下文运行的工具,如 cmake
或 ninja
,而不用于将链接到二进制文件的库类依赖。对于库或库类依赖,请使用 requires
或 test_requires
。
<host_version>¶
警告
此特性是实验性的,可能会发生破坏性更改。更多信息请参阅 Conan 稳定性 部分。
当您将同一个包配方同时用作 requires 和 tool_requires 时,此语法非常有用,它可以帮助避免下游冲突,特别是在任何用户决定覆盖 host 上下文中的原始 requires 版本时。换句话说,用户可能会在同一个依赖的主机和构建上下文中得到两个不同的版本。
简而言之,<host_version>
指定符允许我们确保为 tool_requires 解析的版本始终与主机依赖的版本匹配。
例如,让我们展示一个使用 protobuf 的简单配方
from conan import ConanFile
class mylibRecipe(ConanFile):
name = "mylib"
version = "0.1"
def requirements(self):
self.requires("protobuf/3.18.1")
def build_requirements(self):
self.tool_requires("protobuf/<host_version>")
然后,如果任何用户想要使用 mylib/0.1,但同时使用 protobuf 的另一个版本,覆盖它应该不会有任何问题
from conan import ConanFile
class myappRecipe(ConanFile):
name = "myapp"
version = "0.1"
def requirements(self):
self.requires("mylib/0.1")
self.requires("protobuf/3.21.9", override=True)
上游定义的 <host_version>
确保主机和构建上下文使用该依赖的相同版本。
此外,如果 requires 和 tool_requires 具有不同的名称,可以使用 <host_version:mylib>
语法来指定要跟踪的包名称。例如
from conan import ConanFile
class mylibRecipe(ConanFile):
name = "mylib"
version = "0.1"
def requirements(self):
self.requires("gettext/2.31")
def build_requirements(self):
self.tool_requires("libgettext/<host_version:gettext>")
test_requires¶
test_requires
等同于带有以下特性的 requires()
test=True
。此依赖是“测试”依赖,存在于“主机”上下文,但不旨在成为最终产品的一部分。visible=False
。测试依赖不会向下游传播。例如,一个包可以调用self.test_requires("gtest/1.13.0")
,但这不意味着消费者包也使用gtest
,它们甚至可以使用不同的测试框架,或者使用不同版本的gtest
,而不会引起冲突。
如果需要,可以进一步修改 tool_requires()
和 test_requires()
的单独特性,例如
def build_requirements(self):
self.tool_requires("cmake/3.23.5", options={"shared": False})
test_requires()
允许使用 force=True
特性,以应对存在传递性测试依赖版本冲突的情况;类似地,tool_requires()
支持 override=True
特性,用于覆盖直接工具依赖可能存在的传递性依赖。
注意
最佳实践
tool_requires
专门用于构建时工具,而不是用于会被包含并链接到消费者包中的库。对于具有某些特殊特性的库,请使用带有自定义特性值的requires()
。self.test_requires()
和self.tool_requires()
方法应仅在build_requirements()
方法中使用,唯一可能的例外是requirements()
方法。禁止在任何其他方法中使用它们。要在某些方法中必要时访问依赖信息,应使用 self.dependencies 属性。