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() 参考。
有两种 实验性的 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
。 此依赖项位于“build”上下文中,在构建时是必需的,但在应用程序运行时则不需要,并且将接收“build”配置文件和配置。visible=False
。 工具需求的依赖项不会向下游传播。 例如,一个包可以调用tool_requires("cmake/3.23.5")
,但这并不意味着使用者包也使用cmake
,它们甚至可以使用不同的构建系统或不同的版本,而不会引起冲突。run=True
。 此依赖项有一些需要在构建时运行的可执行文件或运行时。headers=False
工具需求没有头文件。libs=False
:工具需求没有使用者要链接的库(如果它有库,它们将位于“build”上下文中,并且可能与使用者包的“host”上下文不兼容)。
回想一下,tool_requires
专门用于依赖于像 cmake
或 ninja
这样的工具,这些工具在“build”上下文中运行,而不是用于链接到二进制文件中的类似库的依赖项。 对于库或类似库的依赖项,请使用 requires
或 test_requires
。
<host_version>¶
警告
此功能是实验性的,可能会发生重大更改。 有关更多信息,请参见Conan 的稳定性部分。
当您将相同的软件包配方用作 *requires* 和 *tool_requires*,并且您想避免任何用户决定覆盖 *host* 上下文中的原始 *requires* 版本时,避免发生下游冲突,此语法很有用,即,用户最终可能会在同一依赖项的 host 和 build 上下文中具有两个不同的版本。
简而言之,<host_version>
说明符使我们能够确保为 *tool_requires* 解析的版本始终与 host 需求的版本匹配。
例如,让我们展示一个使用 *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 和 build 上下文使用该需求的相同版本。
此外,语法 <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
。 此依赖项是“test”依赖项,存在于“host”上下文中,但目的不是成为最终产品的一部分。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 属性。
另请参阅