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>
确保主机和构建上下文使用相同版本的该需求。
此外,语法 <host_version:mylib>
可用于指定要跟踪的包的名称,以防 requires 和 tool_requires 具有不同的名称。例如
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
,而不会引起冲突。
警告
由于 test_requires
定义了一个 visible=False
特性,因此必须小心避免与 test_requires
中使用的相同包存在带有普通需求的传递依赖。这是因为如果传递依赖对当前配方作为测试依赖所要求的同一个包有 visible=True
需求,则直接的 visible=False
需求可能会造成冲突。在这些不同的可见性规则到达同一个包的情况下,可见的传递依赖将被使用并向下游传播。
如果需要,可以进一步修改 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 属性。