requirements()

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

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

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

依赖特性

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

Conan 2.0 的高级依赖模型 演示文稿 提供了对特性的良好介绍。

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

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

headers

表示该包包含将在编译时 #included 的头文件。该依赖项将处于 host 上下文中。

libs

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

build

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

警告

定义了 build=True 的构建时依赖项(tool_requiresbuild_requires)旨在与它们的默认 visible=False 一起工作,目前强烈建议将它们保留为 visible=False。如果您认为您可能有使用场景,最好先在 https://github.com/conan-io/conan/issues 上讨论并询问,而不是尝试启用 visible=True

对于一些非常特殊的例外情况,我们有针对 build=True 的构建/工具依赖项的**实验性**支持,这些依赖项也定义了 visible=True,但这是实验性的,并可能在未来的 Conan 版本中发生破坏性更改。它也被认为并且设计为不传播所有特性,例如 headers/libs 将不会被传播,因为来自“build”上下文的头文件和库无法在 host 上下文中链接。

run

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

visible

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

警告

当一个传递性依赖项对当前配方声明为 visible=False 的同一包具有 visible=True 的依赖项时,visible 特性可能会产生冲突。在这些不同的可见性规则达到同一包的情况下,将使用并向下游传播可见的传递性依赖项。

transitive_headers

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

transitive_libs

如果为 True,则与依赖项链接的库将对下游可见。

test

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

package_id_mode

如果配方想指定依赖项版本如何影响当前包的 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

如果依赖项是直接依赖项,即它由当前配方显式声明,或者它是传递性依赖项。

options

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

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

警告

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

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)

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

注意

最佳实践

no_skip=True 的使用应该是例外情况,对于非常有限和不寻常的用例,默认的 Conan “跳过二进制文件”行为对绝大多数情况来说应该足够好了。通常,它不会单独有意义,但如果与 visible=False 等其他特性一起使用。除非绝对必要,否则避免使用它,并且它应该只在非常特殊的配方中使用。如果它在许多配方中使用,那很可能是滥用。

package_type 特性推断

一些特性是根据依赖项的 package_type 值自动推断的,如果配方没有显式设置。

注意

除非在下面的列表中另有说明,或者用户手动将其设置为 False,否则 libsheadersvisible 特性默认设置为 True

推断规则是

  • 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

这意味着,如果您的配方中有 self.requires("mypkg/1.0"),并且 mypkg/1.0package_type="application",那么该 requires 的有效特性将是 headers=False, libs=False, run=True。然后可以通过在 requires 中显式设置来覆盖这些特性。

此外,基于您的配方的 package_type,还会推断出一些额外的特性。

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

这意味着,如果您的包是一个 header-library,那么它所有的依赖项将默认具有 transitive_headers=Truetransitive_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

例如,考虑到所有显示逻辑,这意味着如果您的 package_type="header-library" 的库中有一个 self.requires("mypkg/1.0") 形式的依赖项,并且 mypkg/1.0package_type="shared-library",那么该 requires 的有效特性将是:

  • mypkgpackage_type 推断:run=True

  • 从您的包的 package_type 推断:transitive_headers=True, transitive_libs=True

  • 根据 requires 类型:build=False

  • 默认:headers=True, libs=True