requirements()

requirements() 方法用于指定包的依赖项。

def requirements(self):
    self.requires("zlib/1.2.11")

对于简单的情况,可以使用属性语法,例如 requires = "zlib/1.2.11"

依赖项特性

特性是 requires 子句的属性。它们决定了 Conan 如何处理和传播依赖项的各个部分。特性的值通常由 Conan 根据依赖项的 package_type 计算得出,但也可以手动指定。

Conan 2.0 中的高级依赖项模型 演讲中提供了关于特性很好的介绍。

在下面的示例中,headerslibs 是特性。

self.requires("math/1.0", headers=True, libs=True)

headers

表明此包中包含在编译时将通过 #included 包含的头文件。该依赖项将在 host context 中。

libs

该依赖项包含一些库或工件,这些库或工件将在消费者的链接时使用。对于直接的共享库和静态库,此特性通常为 True,但对于通过共享库使用的间接静态库可能为 false。该依赖项将在 host context 中。

build

该依赖项是一个构建工具、应用程序或可执行文件,例如 cmake,它仅在构建时使用。它不会被链接/嵌入到二进制文件中,并且将在 build context 中。

警告

定义 build=True 的构建时依赖项(tool_requires, build_requires)被设计为与其默认的 visible=False 一起工作,目前强烈建议将它们保持为 visible=False。如果您认为可能存在用例,最好先在 https://github.com/conan-io/conan/issues 中讨论并询问,而不是尝试启用 visible=True

对于一些非常特殊的用例,实验性地支持定义 visible=Truebuild=True 构建/工具依赖项,但这仍处于实验阶段,未来的 Conan 版本中可能会有破坏性变更。已知并设计为不传播所有特性,例如 headers/libs 将不会被传播,因为来自“build” context 的头文件和库不能在 host context 中链接。

run

该依赖项包含一些可执行文件,可以是应用程序或共享库,这些文件需要可用才能执行(通常在 PATH 或其他系统环境变量中)。此特性在 build=False 时可以为 True,在这种情况下,该包将包含一些在安装时可在 host 系统中运行的可执行文件,通常像一个最终用户应用程序。此特性在 build=True 时可以为 True,该包将包含一些可在 build context 中运行的可执行文件,通常在用于构建其他包时。

visible

require 将向下游传播,即使它不传播 headers, libsrun 特性。向下游传播的依赖项可能导致版本冲突。这通常为 True,因为在大多数情况下,在同一依赖项图中存在同一库的两个不同版本至少是复杂的,如果不是直接违反 ODR 或导致链接错误的话。在高级场景中,当我们在构建期间想要使用同一包的不同版本时,可以将其设置为 False

transitive_headers

如果为 True,则该依赖项的头文件将在下游可见。请参阅头文件传递性教程以了解有关此特性的更多信息。

transitive_libs

如果为 True,则该依赖项的用于链接的库将在下游可见。

test

此依赖项是一个测试库或框架,例如 Catch2 或 gtest。它主要是一个需要包含和链接的库,但不会向下游传播。

package_id_mode

如果 recipe 想要指定依赖项版本如何影响当前包的 package_id,可以直接在此处指定。

虽然也可以在 package_id() 方法中完成,但在 requires 中指定似乎更简单,同时避免了一些歧义。

# We set the package_id_mode so it is part of the package_id
self.tool_requires("tool/1.1.1", package_id_mode="minor_mode")

这等同于

def package_id(self):
  self.info.requires["tool"].minor_mode()

force

requires 将在上游依赖项图中强制使用其版本,覆盖其他现有版本,即使是传递依赖项的版本,并解决潜在的现有冲突。下游消费者的 force 特性总是具有更高的优先级。

override

force 特性相同,但不会添加 direct 依赖项。如果没有要覆盖的传递依赖项,此 ``require`` 将被丢弃。此特性仅在定义 requires 时存在,但在图完全评估后将不会作为实际的 requires 存在。

注意

最佳实践

  • 不建议将 forceoverride 特性作为通用的版本管理解决方案来解决冲突,它们只是解决版本冲突的临时权宜之计。应尽可能避免使用它们,在图中更新版本或版本范围以避免冲突,而不是使用覆盖和强制是推荐的方法。

  • 一个关键的要点是,override 特性不会从您的包创建直接依赖项,而 force 特性会。这意味着 override 特性仅在您想要覆盖某个传递依赖项的版本,同时不向其添加直接依赖项时有用。

direct

如果该依赖项是一个直接依赖项,也就是说,它已被当前 recipe 显式声明,或者它是一个传递依赖项。

options

可以将依赖项的选项值定义为特性

self.requires("mydep/0.1", options={"dep_option": "value"})

警告

在 recipes 中定义选项值没有强有力的保证,请查看 关于依赖项选项值的 FAQ。推荐的定义选项值的方法是在 profile 文件中。

no_skip

此特性是 Conan 2.16 中引入的实验性功能,可能会发生破坏性变更。有关更多信息,请参阅Conan 稳定性部分。

当传递依赖项的二进制文件不需要时,Conan 能够避免下载它们。例如,如果包含可执行文件的 package_type = "application" 包依赖于 (requires) 另一个 package_type = "static-library" 包(或者一个常规库,但选项为 shared=False),那么安装应用程序包的二进制文件不需要静态库依赖项的二进制文件即可工作。Conan 将“跳过”这些二进制文件的下载,节省下载和安装的时间和传输成本。这些二进制文件在 Conan 命令输出中被标记为“跳过的二进制文件 (Skipped binaries)”。

tools.graph:skip_binaries 配置可以改变默认行为,如果设置为 False,它将避免跳过二进制文件,这在某些场景下可能有用。

no_skip=True 特性可以在依赖项中定义,例如:

name = "mypkg"

def requirements(self):
  self.requires("mydep/0.1", no_skip=True)

这将强制下载 mydep/0.1 的二进制文件,当 mypkg 的二进制文件需要时。

注意

最佳实践

no_skip=True 的使用应该是例外情况,适用于非常有限和特殊的用例,Conan 默认的“跳过二进制文件”行为应适用于绝大多数情况。通常,单独使用它没有意义,除非与其他特性(例如 visible=False)一起使用。除非绝对必要,否则应避免使用它,并且它应该只用于非常特殊的 recipes 中。如果用于许多 recipes,很可能属于滥用。

package_type 特性推断

如果 recipe 没有显式设置,某些特性会根据 package_type 的值自动推断。

  • application: headers=False, libs=False, run=True

  • shared-library: run=True

  • static-library: run=False

  • header-library: headers=True, libs=False, run=False

  • build-scripts: headers=False, libs=False, run=True, visible=False

此外,根据依赖方的 package_type,在上述基础上还会推断出一些额外的特性。

  • header-library: transitive_headers=True, transitive_libs=True

每种 requires 的默认特性

每种 requires 在上一节所述特性的基础上默认设置了一些额外的特性。它们是:

  • requires: build=False

  • build_requires: headers=False, libs=False, build=True, visible=False

  • tool_requires: headers=False, libs=False, build=True, run=True, visible=False

  • test_requires: headers=True, libs=True, build=False, visible=False, test=True