属性

包引用

Recipe 属性,用于定义主 pkg/version@user/channel 包引用。

name

包的名称。有效名称是全小写,并且

  • 最少 2 个字符,最多 101 个字符(但建议使用更短的名称)。

  • 匹配以下正则表达式 ^[a-z0-9_][a-z0-9_+.-]{1,100}$:因此,它以字母数字字符或 _ 开头,

    然后是 1 到 100 个字母数字字符、_+.-

只有在将 recipe 导出到本地缓存时(exportexport-pkg

create 命令),如果它们没有在命令行中使用 --name=<pkgname> 定义,则名称是必需的。

version

包的版本。有效版本遵循与 name 属性相同的规则。如果版本遵循 X.Y.Z-pre1+build2 形式的语义版本化,则该值可能用于通过版本范围而不是精确版本来要求此包。

只有在将 recipe 导出到本地缓存时(exportexport-pkgcreate 命令)才严格需要 version,如果它们没有在命令行中使用 --version=<pkgversion> 定义。

version 可以在命令行中动态定义,也可以在 recipe 中通过 set_version() 方法 以编程方式定义。

user

user 字段的有效字符串遵循与 name 属性相同的规则。这是一个可选属性。它可用于使用 pkg/version@user/channel 标识您的自有包,其中 user 可以是您的团队、组织或公司的名称。ConanCenter recipe 没有 user/channel,因此它们仅采用 pkg/version 的形式。您还可以不带 user 和 channel 地命名您的包,或者仅使用 user 作为 pkg/version@user

可以使用命令行 --user=<myuser> 指定 user

channel

channel 字段的有效字符串遵循与 name 属性相同的规则。这是一个可选属性。有时用于标识包的成熟度(“stable”、“testing”……),但通常来说这是不必要的,包的成熟度最好通过将它们放在不同的服务器存储库来管理。

可以使用命令行 --channel=<mychannel> 指定 channel。如果指定了 channel,则必须同时指定 user,以便包引用始终是完整的,即 pkg/version@user/channel

Metadata

可选的元数据,例如 license、description、author 等。大多数情况下不是必需的,但可能有用。

description

这是一个可选但推荐的文本字段,包含包的描述以及对消费者有用的任何信息。第一行可以用作包的简短描述。

class HelloConan(ConanFile):
    name = "hello"
    version = "0.1"
    description = """This is a Hello World library.
                    A fully featured, portable, C++ library to say Hello World in the stdout,
                    with incredible iostreams performance"""

license

目标源代码和二进制文件的许可证,即正在打包的代码,而不是 conanfile.py 本身。可以包含多个逗号分隔的许可证。它是一个文本字符串,因此可以包含任何文本,但强烈建议开源项目的 recipe 使用 SPDX 标识符,来自 SPDX 许可证列表

这将有助于那些希望自动化许可证兼容性检查的人,例如您的包的消费者,或者如果您自己的包有开源依赖项。

class Pkg(ConanFile):
    license = "MIT"

author

包的主要维护者/负责人,格式不限。这是一个可选属性。

class HelloConan(ConanFile):
    author = "John J. Smith (john.smith@company.com)"

topics

用于将相关包分组在一起并描述代码含义的标签。在 ConanCenter 中用作搜索过滤器。可选属性。它应该是一个字符串元组。

class ProtocInstallerConan(ConanFile):
    name = "protoc_installer"
    version = "0.1"
    topics = ("protocol-buffers", "protocol-compiler", "serialization", "rpc")

homepage

正在打包的库的主页。

用于将 recipe 链接到有关库本身的其他解释,例如其功能概述、文档、常见问题解答以及其他相关信息。

class EigenConan(ConanFile):
    name = "eigen"
    version = "3.3.4"
    homepage = "http://eigen.tuxfamily.org"

url

包存储库的 URL,即不一定是原始源代码的 URL。推荐的属性,但非强制。

class HelloConan(ConanFile):
    name = "hello"
    version = "0.1"
    url = "https://github.com/conan-io/libhello.git"

Requirements

依赖项简单声明的属性形式,例如 requirestool_requires。对于定义依赖项的高级方法,请改用 requirements()build_requirements() 方法。

requires

主机上下文中常规依赖项的列表或元组,例如库。

class MyLibConan(ConanFile):
    requires = "hello/1.0", "otherlib/2.1@otheruser/testing"

您可以指定版本范围,语法是使用方括号

class HelloConan(ConanFile):
    requires = "pkg/[>1.0 <1.8]"

可接受的表达式为

Expression

Versions in range

Versions outside of range

[>=1.0 <2]

1.0.0, 1.0.1, 1.1, 1.2.3

0.2, 2.0, 2.1, 3.0

[<3.2.1]

0.1, 1.2, 2.4, 3.1.1

3.2.2

[>2.0]

2.1, 2.2, 3.1, 14.2

1.1, 1.2, 2.0

插入符号 ^ 和波浪线 ~ 运算符基本上是下限和上限的紧凑表示。

  • 范围 [~2.5.1] 可以写成 [>=2.5.1 <2.6.0]

  • 范围 [^1.2.3] 可以写成 [>=1.2.3 <2.0.0]

通常,建议使用完整的表达式 [>=lower <upper] 而不是插入符号或波浪线快捷方式,因为它对所有读者来说更明确,更容易理解该范围内的有效版本。

如果启用了预发行版,例如定义配置 core.version_ranges:resolve_prereleases=True

Expression

Versions in range

Versions outside of range

[>=1.0 <2]

1.0.0-pre.1, 1.0.0, 1.0.1, 1.1, 1.2.3

0.2, 2.0-pre.1, 2.0, 2.1, 3.0

[<3.2.1]

0.1, 1.2, 1.8-beta.1, 2.0-alpha.2, 2.4, 3.1.1

3.2.1-pre.1, 3.2.1, 3.2.2, 3.3

[>2.0]

2.1-pre.1, 2.1, 2.2, 3.1, 14.2

1.1, 1.2, 2.0-pre.1, 2.0

另请参阅

tool_requires

依赖项的列表或元组。代表一个构建工具,如“cmake”。如果当前包存在预编译的二进制文件,则不会检索工具依赖项的二进制文件。它们不能冲突。

class MyPkg(ConanFile):
    tool_requires = "tool_a/0.2", "tool_b/0.2@user/testing"

这是添加 tool_requires 的声明式方法。请查阅 tool_requires() conanfile.py 方法,了解更灵活的添加方式。

build_requires

build_requires 在 Conan 2 中用于提供与 Conan 1.X 语法的兼容性,但在 Conan 2 中不推荐使用 build_requires,并且在未来的 2.X 版本中将被弃用。请在您的 Conan 2 recipe 中使用 tool_requires 而不是 build_requires

test_requires

仅在主机上下文中用于依赖项的列表或元组。代表一个测试工具,如“gtest”。当当前包从源代码构建时使用。它们不会将信息传播给下游消费者。如果当前包存在预编译的二进制文件,则不会检索测试依赖项的二进制文件。它们不能冲突。

class MyPkg(ConanFile):
    test_requires = "gtest/1.17.0", "other_test_tool/0.2@user/testing"

这是添加 test_requires 的声明式方法。请查阅 test_requires() 方法,了解更灵活的添加方式。

python_requires

此类属性允许定义对另一个 Conan recipe 的依赖并重用其代码。其基本语法为

from conan import ConanFile

class Pkg(ConanFile):
    python_requires = "pyreq/0.1@user/channel"  # recipe to reuse code from

    def build(self):
        self.python_requires["pyreq"].module # access to the whole conanfile.py module
        self.python_requires["pyreq"].module.myvar  # access to a variable
        self.python_requires["pyreq"].module.myfunct()  # access to a global function
        self.python_requires["pyreq"].path # access to the folder where the reused file is

Python requires 中阅读有关此属性的更多信息

python_requires_extend

此类属性定义一个或多个类,这些类将在运行时作为 recipe 类的基类注入。这些类的语法应为字符串,例如 pyreq.MyConanfileBase,其中 pyreqpython_requires 的名称,而 MyConanfileBase 是要使用的类的名称。

from conan import ConanFile

class Pkg(ConanFile):
    python_requires = "pyreq/0.1@user/channel", "utils/0.1@user/channel"
    python_requires_extend = "pyreq.MyConanfileBase", "utils.UtilsBase"  # class/es to inject

Sources

exports

包含要导出并与 conanfile.py 文件并排放置以使 recipe 正常工作的 文件名fnmatch 模式的列表或元组:其他 recipe 将导入的 Python 文件,要读取的一些文本文件……

例如,如果我们有一些 Python 代码希望 recipe 在 helpers.py 文件中使用,并且有一个文本文件 info.txt 我们希望在 recipe 求值期间读取和显示,我们会这样做

exports = "helpers.py", "info.txt"

排除模式也是可能的,带有 ! 前缀

exports = "*.py", "!*tmp.py"

exports_sources

包含要导出并可用于生成包的文件名或 fnmatch 模式的列表或元组。与 exports 属性不同,这些文件不应由 conanfile.py Python 代码使用,而应用于编译库或生成最终包。并且,由于其目的,只有当请求的二进制文件不可用或用户强制 Conan 从源代码编译时,才会检索这些文件。

这是获取 source() 方法中的源代码的替代方法。当我们在打包第三方库时,并且我们有 recipe 和 C/C++ 项目在一起时使用。

exports_sources = "include*", "src*"

排除模式也是可能的,带有 ! 前缀

exports_sources = "include*", "src*", "!src/build/*"

注意,如果 recipe 定义了 layout() 方法并指定了 self.folders.source = "src",这不会影响 exports_sources 中的文件被复制到的位置。它们将被复制到基础源文件夹。因此,如果您想替换已进入 source() 方法的某个文件,您需要显式地从父文件夹复制它,甚至更好的是,从 self.export_sources_folder 复制。

import os, shutil
from conan import ConanFile
from conan.tools.files import save, load

class Pkg(ConanFile):
    ...
    exports_sources = "CMakeLists.txt"

    def layout(self):
        self.folders.source = "src"
        self.folders.build = "build"

    def source(self):
        # emulate a download from web site
        save(self, "CMakeLists.txt", "MISTAKE: Very old CMakeLists to be replaced")
        # Now I fix it with one of the exported files
        shutil.copy("../CMakeLists.txt", ".")
        shutil.copy(os.path.join(self.export_sources_folder, "CMakeLists.txt"), ".")

conan_data

只读属性,包含一个字典,其键和值来自与 conanfile.py 旁边的 conandata.yml 文件格式。此 YAML 文件会自动与 recipe 一起导出,并自动加载。

您可以在 conandata.yml 文件中声明信息,然后在 recipe 的任何方法中访问它。例如,一个包含源代码信息的 conandata.yml 文件如下所示

sources:
  "1.1.0":
    url: "https://www.url.org/source/mylib-1.0.0.tar.gz"
    sha256: "8c48baf3babe0d505d16cfc0cf272589c66d3624264098213db0fb00034728e9"
  "1.1.1":
    url: "https://www.url.org/source/mylib-1.0.1.tar.gz"
    sha256: "15b6393c20030aab02c8e2fe0243cb1d1d18062f6c095d67bca91871dc7f324a"
def source(self):
    get(self, **self.conan_data["sources"][self.version])

source_buildenv

布尔属性,用于选择在运行 source() 方法时注入 VirtualBuildEnv 生成的环境。

将此属性设置为 True(默认值 False)将在执行 source() 方法时注入来自工具依赖项的 VirtualBuildEnv 生成的环境。

 class MyConan:
    name = "mylib"
    version = "1.0.0"
    source_buildenv = True
    tool_requires = "7zip/1.2.0"

    def source(self):
        get(self, **self.conan_data["sources"][self.version])
        self.run("7z x *.zip -o*")  ## Can run 7z in the source method

Binary model

定义包二进制模型的关键属性,例如哪些设置、选项、包类型等会影响最终打包的二进制文件。

package_type

可选。声明 package_type 将有助于 Conan

  • 为每个依赖项选择更好的默认 package_id_mode,即依赖项的更改应如何影响当前包的 package_id

  • 从依赖项传播给消费者的信息,例如头文件、库、运行时信息。请参阅 此处,了解基于 package_type 信息传播哪些特征。

有效值为

  • application: 该包是一个应用程序。

  • library: 该包是一个通用库。它将尝试确定库的类型(来自 shared-librarystatic-libraryheader-library),读取 self.options.shared(如果已声明)和 self.options.header_only

  • shared-library: 该包是一个共享库。

  • static-library: 该包是一个静态库。

  • header-library: 该包是一个仅头文件库。

  • build-scripts: 该包仅包含构建脚本。

  • python-require: 该包是一个 Python require。

  • unknown: 包的类型未知。

请注意,包之间的关系可能并不总是定义明确,并可能导致错误,例如,build-scripts 不能有常规的 requires 依赖项来编译库,并且不知道如何通过旨在用作 tool_requires 的内容来传播这些依赖项。如果某个包想同时使用构建脚本并链接到某个库,它应该定义一个到 build-scripts 包的 tool_requires(),并定义一个到编译库的常规 requires()

settings

字符串列表,包含 recipe 所需的第一级设置(来自 settings.yml),因为:- 它们用于构建(例如:if self.settings.compiler == “gcc”)- 它们会影响 package_id。如果声明的设置值发生更改,则 package_id 必须不同。

最常见的是声明

settings = "os", "compiler", "build_type", "arch"

一旦 recipe 被 Conan 加载,settings 就会被处理,并且可以在 recipe 中读取它们,也可以读取子设置。

settings = "os", "arch"

def build(self):
    if self.settings.compiler == "gcc":
        if self.settings.compiler.cppstd == "gnu20":
            # do some special build commands

如果您尝试访问不存在的设置,例如 msvc 设置的 self.settings.compiler.libcxx,Conan 会失败并提示 libcxx 对该编译器不存在。

如果要安全地检查设置值,可以使用 get_safe() 方法。

def build(self):
    # Will be None if doesn't exist (not declared)
    arch = self.settings.get_safe("arch")
    # Will be None if doesn't exist (doesn't exist for the current compiler)
    compiler_version = self.settings.get_safe("compiler.version")
    # Will be the default version if the return is None
    build_type = self.settings.get_safe("build_type", default="Release")

如果该设置或子设置不存在且没有默认值,get_safe() 方法将返回 None

也可以使用 possible_values() 方法检查 settings.yml 中定义的可能值。

def generate(self):
    # Print if Android exists as OS in the whole settings.yml
    is_android = "Android" in self.settings.possible_values()["os"]
    self.output.info(f"Android in settings.yml: {is_android}")
    # Print the available versions for the compiler used by the HOST profile
    compiler_versions = self.settings.compiler.version.possible_values()
    self.output.info(f"[HOST] Versions for {str(self.settings.compiler)}:  {', '.join(compiler_versions)}")
    # Print the available versions for the compiler used by the BUILD profile
    compiler_versions = self.settings_build.compiler.version.possible_values()
    self.output.info(f"[BUILD] Versions for {str(self.settings_build.compiler)}:  {', '.join(compiler_versions)}")

如上所示,self.settings.possible_values() 返回整个 settings.yml 作为类似 Python dict 的对象,而例如 self.settings.compiler.version.possible_values() 返回消费者使用的编译器的可用版本。

如果要安全地删除设置,可以使用 rm_safe() 方法。例如,在 configure() 方法中,C 库的典型模式是

def configure(self):
    self.settings.rm_safe("compiler.libcxx")
    self.settings.rm_safe("compiler.cppstd")

options

具有仅影响当前 recipe 的特性的字典,其中键是选项名称,值是选项可以具有的不同值列表。默认情况下,选项中的任何值更改都会更改 package_id。请检查 default_optionsdefault_build_options 字段以定义选项的默认值。

每个选项的值可以是类型化的,也可以是纯字符串("value"True42……)。

有两个特殊值

  • None: 允许选项具有 None 值(未指定)而不会出错。

  • "ANY": 对于可以接受任何值的选项,不限于某个集合。

class MyPkg(ConanFile):
    ...
    options = {
        "shared": [True, False],
        "option1": ["value1", "value2"],
        "option2": ["ANY"],
        "option3": [None, "value1", "value2"],
        "option4": [True, False, "value"],
}

一旦 recipe 被 Conan 加载,options 就会被处理,并且可以在 recipe 中读取它们。您还可以使用 .get_safe() 方法(请参阅 settings 属性)来避免 Conan 在选项不存在时引发异常。

class MyPkg(ConanFile):
    options = {"shared": [True, False]}

    def build(self):
        if self.options.shared:
            # build the shared library
        if self.options.get_safe("foo", True):
            pass

在布尔表达式中,例如 if self.options.shared

  • 对于值 True"True""true",等于 True,以及任何其他在 Python 代码中具有相同求值方式的值。

  • 对于值 False"False""false",等于 False,也如预期的那样,对于空字符串和 0"0"

请注意,使用 is 进行比较始终为 False,因为类型会不同,因为它被封装在一个 Python 类中。

如果要安全地删除选项,可以使用 rm_safe() 方法。例如,在 config_options() 方法中,Windows 库的典型模式是

def config_options(self):
    if self.settings.os == "Windows":
        self.options.rm_safe("fPIC")

另请参阅

default_options

属性 default_options 定义了当前 recipe 和任何依赖项的选项的默认值。此属性应定义为 Python 字典。

class MyPkg(ConanFile):
    ...
    requires = "zlib/1.2.8", "zwave/2.0"
    options = {"build_tests": [True, False],
                "option2": "ANY"}
    default_options = {"build_tests": True,
                        "option1": 42,
                        "z*:shared": True}

您还可以使用“<reference_pattern>: option_name”为依赖项的选项分配默认值,其中 reference_pattern 是有效的 name/version 或任何带有 * 的模式,如上面的示例所示。

警告

在 recipe 中定义选项值没有严格的保证,请参阅 关于依赖项选项值的 FAQ。定义选项值的推荐方法是在 profile 文件中。

您也可以在 configure() 方法中将选项条件性地设置为最终值,而不是使用 default_options

class OtherPkg(ConanFile):
    settings = "os", "arch", "compiler", "build_type"
    options = {"some_option": [True, False]}
    # Do NOT declare 'default_options', use 'config_options()'

    def configure(self):
        if self.options.some_option == None:
            if self.settings.os == 'Android':
                self.options.some_option = True
            else:
                self.options.some_option = False

请注意,如果在 configure() 方法中分配了值,则无法覆盖它。

另请参阅

Recipe 可以通过 2 种不同的方式尝试为其实例定义选项值。使用 default_options = {"mypkg/*:myoption", 123},当前 recipe 可以将 123 值分配给依赖项 mypkgmyoption。此方式为依赖项定义选项存在一些限制。

  • 任何其他下游用户,如果为 mypkg 定义了相同的选项,都将具有优先权,覆盖当前 recipe 的 123 值。此外,profile 或命令行中的任何定义也将具有优先权。recipe 的 default_options 具有最低的优先权。如果某个 recipe 根本无法与某些依赖项选项一起工作,那么 recipe 可以进行检查并引发 ConanInvalidConfiguration 错误。

  • 任何依赖于 mypkg同级包也将定义其选项,并且它将是唯一被考虑的。换句话说,第一次由任何其他包要求 mypkg 时,它将“冻结”其当前分配的选项值。任何后来(关闭依赖图中的菱形结构)依赖于 mypkg 的其他包将不对 mypkg 的选项产生任何影响。只有第一个要求它的包才会。

定义选项值的第二种方法是将其定义为 important!

警告

important! 语法是实验性的,可能会随时更改或移除。

Recipe 可以使用 default_options = {"mypkg/*:myoption!", 123} 语法将其依赖项选项定义为 important!。这意味着 mypkgmyoption 不会被其他下游包、profile 或命令行以常规方式定义选项(例如 -o *:myoption=234)覆盖。

但在 2 种情况下,这仍不会定义依赖项的最终值

  • 如果任何下游 recipe、命令行或 profile 也使用 myoption! 语法,那也将具有优先权并覆盖上游值。

  • 如果存在任何其他包首先要求 mypkg,那么此时定义的将仍然具有优先权。

总的来说,定义选项值的建议是在 profile 文件中而不是在 recipe 中,因为在 recipe 中定义可能更复杂,尤其是在复杂的依赖项图中。

default_build_options

属性 default_build_options 定义了构建上下文中选项的默认值,通常用于定义 tool_requires 的选项。

from conan import ConanFile
class Consumer(ConanFile):
    default_options = {"protobuf/*:shared": True}
    default_build_options = {"protobuf/*:shared": False}
    def requirements(self):
        self.requires("protobuf/1.0")
    def build_requirements(self):
        self.tool_requires("protobuf/1.0")

options_description

属性 options_description 是一个可选属性,可以定义为字典形式,其中键是选项名称,值是选项的文本描述。此属性对于提供关于每个选项的功能和目的的附加信息非常有用,尤其是在选项不直观或具有复杂或特殊行为时。

每个字典条目的格式应为

  • Key: 选项名称。必须是字符串,并且必须与 options 字典中的某个键匹配。

  • Value: 选项的描述。必须是字符串,长度可以任意。

例如

class MyPkg(ConanFile):
    ...
    options = {"option1": [True, False],
               "option2": "ANY"}

    options_description = {
        "option1": "Describe the purpose and functionality of 'option1'. ",
        "option2": "Describe the purpose and functionality of 'option2'. ",
    }

languages

警告

此功能是实验性的,可能会发生重大更改。有关更多信息,请参阅 Conan 稳定性 部分。

从 Conan 2.4 开始,conanfile.py recipe 属性 languages 可用于定义此包所涉及的编程语言。目前 CC++ 是可能的值。例如,纯 C 包将定义如下

class ZLib(ConanFile):
    languages = "C"

可以定义多种语言,例如 languages = "C", "C++" 是当包从 C 和 C++ 源代码构建时正确的定义。

关于 languages 的定义,将发生以下情况

  • 如果未定义 languages 或未声明 C 语言,则 compiler.cstd 子设置将在包 configure() 时自动删除(以实现向后兼容)。

  • 如果定义了 languages,但它不包含 C++,则 compiler.cppstdcompiler.libcxx 子设置将在包 configure() 时自动删除。

info

仅在 package_id() 方法中使用的对象

  • package_id 方法,用于控制包的唯一 ID。

    def package_id(self):
        self.info.clear()
    

self.info.clear() 方法会从 package_id 计算中删除所有设置、选项、依赖项(requirestool_requirespython_requires)和配置(conf),因此 package_id 始终会产生相同的二进制文件,而与所有这些因素无关。这通常是仅头文件库的情况,其中打包的工件(文件)始终相同。

package_id_{embed,non_embed,python,unknown}_mode, build_mode

package_id_embed_mode, package_id_non_embed_mode, package_id_python_mode, package_id_unknown_mode 是可以在 recipe 中定义的类属性,用于定义它们对消费者 package_id 的影响,当它们被用作 requires 时。

build_mode(实验性)是一个类属性,它影响消费者使用此包作为 tool_requires 时的行为。可以声明为

from conan import ConanFile

class Pkg(ConanFile):
    name = "pkg"
    version = "1.0.0"
    # They are not mandatory, and it is not necessary to define all
    package_id_embed_mode = "full_mode"
    package_id_non_embed_mode = "patch_mode"
    package_id_unknown_mode = "minor_mode"
    package_id_python_mode = "major_mode"
    build_mode = "patch_mode"  # (experimental) when used as tool_requires

通常,Conan 的默认值是好的,并且允许用户很好地控制何时需要从源代码重新构建消费者。此外,Conan 的默认值可以通过 global.conf 文件(应全局更改,适用于所有用户、CI 等)通过 core.package_id:xxxx 配置进行更改。在 recipe 中定义属性对于定义与默认值不同的行为很有用。

可能的值是(遵循 semver 的 MAJOR.MINOR.PATCH 定义)

  • patch_mode: 该包的新补丁、次要版本和主要版本将要求消费者的新二进制文件(新的 package_id)。新的 recipe 修订版将不会要求消费者的新二进制文件。例如,如果我们创建一个新的 pkg/1.0.1 版本,并且某个消费者有 requires = "pkg/[>=1.0 <2.0]",那么该消费者将针对这个新的 1.0.1 版本构建新的二进制文件。但是,如果我们只是更改了 recipe,生成了新的 recipe_revision,那么消费者将不需要构建新的二进制文件。

  • minor_mode: 该包的新次要版本和主要版本将要求消费者的新二进制文件。新补丁和新修订版将不会要求消费者的新二进制文件。这是“non-embed-mode”的默认值,因为它允许用户精细控制何时重新构建内容。

  • major_mode: 只有新主要版本才会要求新二进制文件。任何其他修改和新版本都不会要求消费者的新二进制文件。

  • full_mode: 此包的完整标识符,包括 pkgname/version@user/channel#recipe_revision:package_id 将在消费者的 package_id 中使用,因此对于此包的每次更改(无论是源代码还是配置更改都会产生不同的 recipe_revisionpackage_id),都会要求消费者构建新的二进制文件。这是“embed-mode”的默认值。

  • unrelated_mode: 此包的任何更改都不会在消费者中生成新的二进制文件。

  • revision_mode: 在消费者 package_id 中使用此包的 pkgname/version@user/channel#recipe_revision,即依赖项的 package_id 之外的完整引用。

  • semver_mode: 如果版本是 >=1.0,则相当于 major_mode;如果版本是 <1.0,则相当于 patch_mode(或具有 3 位以上数字的完整版本)。

这 4 个不同的属性是

  • package_id_embed_mode: 定义“嵌入”情况的模式,即共享库链接静态库,应用程序链接静态库,应用程序或库链接仅头文件库。此模式的默认值为 full_mode

  • package_id_non_embed_mode。定义“非嵌入”情况的模式,即共享库链接另一个共享库,静态库链接另一个静态库,应用程序可执行文件链接共享库。此模式的默认值为 minor_mode

  • package_id_unknown_mode: 定义包之间关系未知时的模式。如果无法推断包类型,因为没有定义 sharedheader_only 选项,或者因为未定义 package_type,则将使用此模式。此模式的默认值为 semver_mode(类似于 Conan 1.X 的行为)。

  • package_id_python_mode: 定义 python_requires 消费者使用的模式。默认值为 minor_mode,并且强烈建议使用此默认值,不要定义 package_id_python_mode。此属性是为了完整性和例外情况(如临时迁移)而提供的。

  • build_mode:(实验性)定义消费者将此依赖项用作 tool_requires 时的模式。默认值为 None,这意味着 tool_requires 不直接影响其消费者的 package_id。启用此 build_mode 会为 tool_requires 引入更强的依赖关系,以便在更多情况下解析消费者的 package_id

另请参阅

有关 Conan 二进制模型的完整视图,请阅读 二进制模型参考

Build

generators

生成器名称的列表或元组。

class MyLibConan(ConanFile):
    generators = "CMakeDeps", "CMakeToolchain"

生成器也可以在 generate() 方法 中显式实例化。

from conan.tools.cmake import CMakeToolchain

class MyLibConan(ConanFile):
    ...

    def generate(self):
        tc = CMakeToolchain(self)
        tc.generate()

build_policy

控制在 conan install 期间何时构建当前包。允许的值为

  • "missing": 如果没有可用的二进制文件,Conan 将从源代码构建它。

  • "never": 此包不能从源代码构建,它始终使用 conan export-pkg 创建。

  • None (默认值): 除非在命令行中指定了策略(例如 --build=foo*),否则此包不会被构建。

     class PocoTimerConan(ConanFile):
         build_policy = "missing"
    

win_bash

True 时,它启用 Windows 子系统 bash 中的新运行机制。

from conan import ConanFile

class FooRecipe(ConanFile):
    ...
    win_bash = True

它也可以声明为基于任何条件的 property

from conan import ConanFile

class FooRecipe(ConanFile):
    ...


    @property
    def win_bash(self):
        return self.settings.arch == "armv8"

win_bash_run

True 时,它启用在 "run" 作用域中运行命令,以便在 bash shell 中运行它们。

from conan import ConanFile

class FooRecipe(ConanFile):

    ...

    win_bash_run = True
    def build(self):
        self.run(cmd, scope="run")  # will run <cmd> inside bash

Folders and layout

source_folder

源代码所在的文件夹。路径通过连接基本目录(在缓存目录中运行时为缓存目录,在本地运行时为 output folder)和 layout() 方法中声明的 folders.source 值来构建。

请注意,当在缓存中运行时,source_folder 的基本目录将指向构建的基本目录,除非 no_copy_source 设置为 True。但无论如何,它将始终指向源代码所在的正确文件夹。

export_sources_folder

该值取决于您访问它的方法。

  • source(self) 中:指向基础源文件夹(这意味着 self.source_folder,但不考虑 layout() 方法中声明的 folders.source)。声明的 exports_sources 始终被复制到该基础源文件夹。

  • exports_sources(self) 中:指向缓存中需要复制导出源的文件夹。

build_folder

用于构建源代码的文件夹。路径通过连接基本目录(在缓存目录中运行时为缓存目录,在本地运行时为 output folder)和 layout() 方法中声明的 folders.build 值来构建。

generators_folder

generate() 方法中的文件应该生成到的文件夹。路径由布局的 self.folders.generators 属性构建。

package_folder

用于将最终工件复制到二进制包的文件夹。在本地缓存中,为每个不同的包 ID 创建一个包文件夹。

self.package_folder 最常见的用法是在 package() 方法copy 文件。

import os
from conan import ConanFile
from conan.tools.files import copy

class MyRecipe(ConanFile):
    ...

    def package(self):
        copy(self, "*.so", self.build_folder, os.path.join(self.package_folder, "lib"))
        ...

recipe_folder

recipe conanfile.py 存储的文件夹,无论是在本地文件夹还是在缓存中。这对于访问与 recipe 一起导出的文件,或者在 export(self)export_sources(self) 方法中导出文件时的源文件夹很有用。

self.recipe_folder 最常见的用法是在 export(self)export_sources(self) 方法中,作为我们复制文件的源文件夹。

from conan import ConanFile
from conan.tools.files import copy

class MethodConan(ConanFile):
    exports = "file.txt"
    def export(self):
        copy(self, "LICENSE.md", self.recipe_folder, self.export_folder)

recipe_metadata_folder

self.recipe_metadata_folder实验性)可以在 export()export_sources()source() 方法中使用,以保存或复制recipe 元数据文件。有关更多信息,请参阅 metadata 部分

package_metadata_folder

self.package_metadata_folder实验性)可以在 generate()build()package() 方法中使用,以保存或复制package 元数据文件。有关更多信息,请参阅 metadata 部分

no_copy_source

属性 no_copy_source 告知 recipe 源文件不会从 source_folder 复制到 build_folder。这主要是为了优化具有大型源代码库或仅头文件库的包,以避免额外的复制。

如果激活 no_copy_source=True,则必须源文件不能被 configure 或 build 脚本修改,因为源文件将在所有构建之间共享。

Recipe 应始终使用 self.source_folder 属性,该属性在 no_copy_source=False 时指向 build 文件夹,在 no_copy_source=True 时指向 source 文件夹。

另请参阅

请阅读 header-only packages 部分 以获取使用 no_copy_source 属性的示例。

test_package_folder

类属性 test_package_folder 允许在 recipe 中为 conan create 命令定义不同的默认 test_package 文件夹。当运行 conan create 时,在包在缓存中创建后,它会查找 test_package 文件夹,或 --test-folder=xxx 参数指定的文件夹,并启动包测试。

此属性允许更改默认名称

import os
from conan import ConanFile

class Pkg(ConanFile):
    test_package_folder = "my/test/folder"

它允许定义任何文件夹,始终相对于 conanfile.py 的位置。

Layout

folders

属性 folders 只能在 layout() 方法中设置。请查阅 layout() 方法文档 以了解有关此属性的更多信息。

cpp

存储包消费者所需的所有信息的对象:包含目录、库名、库路径……适用于缓存中的可编辑包和常规包。它仅在 layout() 方法中可用。

  • self.cpp.package: 对于从 Conan 缓存使用的常规包。与在 package_info() 方法中声明 self.cpp_info 相同。

  • self.cpp.source: 对于“可编辑”包,用于描述 self.source_folder 下的工件。

  • self.cpp.build: 对于“可编辑”包,用于描述 self.build_folder 下的工件。

属性 cpp 只能在 layout() 方法中设置。请查阅 layout() 方法文档 以了解有关此属性的更多信息。

layouts

属性 layouts 只能在 layout() 方法中设置。请查阅 layout() 方法文档 以了解有关此属性的更多信息。

layouts 属性包含有关环境和 conf 的信息,这些信息将是路径相关的,因此当包处于可编辑模式或在缓存中时,它将包含不同的值。 layouts 的子属性是

  • self.layouts.build: 与相对 self.folders.build 相关的信息。

  • self.layouts.source: 与相对 self.folders.source 相关的信息。

  • self.layouts.package: 与最终 package_folder 相关的信息。

上述每个属性都将包含

  • buildenv_info: 消费者用于构建的环境变量信息(等同于 package_info() 方法中的 self.buildenv_info)。

  • runenv_info: 消费者用于运行的环境变量信息(等同于 package_info() 方法中的 self.runenv_info)。

  • conf_info: 传递给消费者依赖项的配置信息(等同于 package_info() 方法中的 self.conf_info)。注意,只有当该包是直接 tool_require 时,此信息才会自动传播给消费者的 self.conf

例如,如果我们有一个 androidndk recipe,它包含 AndroidNDK,并且我们希望该 recipe 处于“可编辑”模式,那么在打包到包中之前,有必要知道 androidndk 在本地的位置。

import os
from conan import ConanFile
from conan.tools.files import copy

class AndroidNDK(ConanFile):

    def layout(self):
        # When developing in user space it is in a "mybuild" folder (relative to current dir)
        self.layouts.build.conf_info.define_path("tools.android:ndk_path", "mybuild")
        # but when packaged it will be in a "mypkg" folder (inside the cache package folder)
        self.layouts.package.conf_info.define_path("tools.android:ndk_path", "mypkg")

    def package(self):
        copy(self, "*", src=os.path.join(self.build_folder, "mybuild"),
             dst=os.path.join(self.package_folder, "mypkg"))

Package information for consumers

cpp_info

与在 layout() 方法中使用 self.cpp.package 相同。如果您需要读取 package_folder 来定位已定位的工件,则使用它。

另请参阅

重要

此属性仅在 package_info() 方法中定义,在其他地方为 None

buildenv_info

对于依赖的 recipe,声明的环境变量将在构建过程中存在。应仅在 package_info() 方法中填写。

重要

此属性仅在 package_info() 方法中定义,在其他地方为 None

def package_info(self):
    self.buildenv_info.append_path("PATH", self.package_folder)

另请参阅

请查看 Environment 对象的参考,了解如何填充 self.buildenv_info

runenv_info

对于依赖的 recipe,声明的环境变量将在运行时存在。应仅在 package_info() 方法中填写。

重要

此属性仅在 package_info() 方法中定义,在其他地方为 None

def package_info(self):
    self.runenv_info.define_path("RUNTIME_VAR", "c:/path/to/exe")

另请参阅

请查看 Environment 对象的参考,了解如何填充 self.runenv_info

conf_info

要传递给依赖的 recipe 的配置变量。应仅在 package_info() 方法中填写。

class Pkg(ConanFile):
    name = "pkg"

    def package_info(self):
        self.conf_info.define("tools.build:verbosity", "debug")
        self.conf_info.get("tools.build:verbosity")  # == "debug"
        self.conf_info.append("user.myconf.build:ldflags", "--flag3")  # == ["--flag1", "--flag2", "--flag3"]
        self.conf_info.update("tools.microsoft.msbuildtoolchain:compile_options", {"ExpandAttributedSource": "false"})
        self.conf_info.unset("tools.microsoft.msbuildtoolchain:compile_options")
        self.conf_info.remove("user.myconf.build:ldflags", "--flag1")  # == ["--flag0", "--flag2", "--flag3"]
        self.conf_info.pop("tools.system.package_manager:sudo")

另请参阅

在此处阅读 self.conf_info 的完整参考。

generator_info

警告

此功能是实验性的,可能会发生重大更改。有关更多信息,请参阅 Conan 稳定性 部分。

要传递给依赖的 recipe 的生成器。应仅在 package_info() 方法中填写,默认值为 None

另请参阅

在此处查看 示例用法,并在此处查看 self.generator_info 的完整参考。

deprecated

此属性声明 recipe 已弃用,这会在每次使用它时发出用户友好的警告消息。

例如,以下代码

from conan import ConanFile

class Pkg(ConanFile):
    name = "cpp-taskflow"
    version = "1.0"
    deprecated = True

可能会发出 risk 警告,例如

Deprecated
    cpp-taskflow/1.0

WARN: risk: There are deprecated packages in the graph

可选地,该属性可以指定建议替换的名称。

from conan import ConanFile

class Pkg(ConanFile):
    name = "cpp-taskflow"
    version = "1.0"
    deprecated = "Not secure, use better taskflow>1.2.3"

这将发出 risk 警告,例如

Deprecated
    cpp-taskflow/1.0: Not secure, use better taskflow>1.2.3

WARN: risk: There are deprecated packages in the graph

如果属性的值求值为 False,则不显示警告。

provides

此属性声明该 recipe 提供与其他 recipe 相同的 [功能]。通常需要此属性,因为两个或多个库实现了相同的 API,以防止链接时和运行时冲突(ODR 违规)。一种典型情况是分叉的库。例如

如果 Conan 在单个图中遇到两个或更多提供相同功能的库,它将引发错误。

At least two recipes provides the same functionality:
- 'libjpeg' provided by 'libjpeg/9d', 'libjpeg-turbo/2.0.5'

属性值应为包含 recipe 名称的字符串或此类 recipe 名称的元组。

例如,要声明 libjpeg-turbo recipe 提供与 libjpeg recipe 相同的功能,可以使用以下代码

from conan import ConanFile

class LibJpegTurbo(ConanFile):
    name = "libjpeg-turbo"
    version = "1.0"
    provides = "libjpeg"

要声明一个 recipe 同时提供多个不同 recipe 的功能,可以使用以下代码

from conan import ConanFile

class OpenBLAS(ConanFile):
    name = "openblas"
    version = "1.0"
    provides = "cblas", "lapack"

如果省略该属性,则该属性的值假定等于当前包的名称。因此,对于 libjpeg recipe 来说,声明它提供了 libjpeg 是多余的,Conan 已经隐式地假设了这一点。

Other

dependencies

Conan recipes 通过 self.dependencies 属性提供对其依赖项的访问。

class Pkg(ConanFile):
    requires = "openssl/0.1"

    def generate(self):
        openssl = self.dependencies["openssl"]
        # access to members
        openssl.ref.version
        openssl.ref.revision # recipe revision
        openssl.options
        openssl.settings

另请参阅

在此处阅读 self.dependencies 的完整参考。

subgraph

(实验性)recipe 的只读依赖图。应使用 dependencies 属性来访问 recipe 的依赖项,因为此属性旨在传递给其他 Conan API,并为高级用法(如 SBOM 生成)公开。

conf

self.conf 属性中,我们可以找到在 profiles 的 [conf] 部分声明的所有 conf 条目。此外,还有来自第一级工具依赖项声明的 self.conf_info 条目。profile 条目具有更高的优先级。

from conan import ConanFile

class MyConsumer(ConanFile):

  tool_requires = "my_android_ndk/1.0"

  def generate(self):
      # This is declared in the tool_requires
      self.output.info("NDK host: %s" % self.conf.get("tools.android:ndk_path"))
      # This is declared in the profile at [conf] section
      self.output.info("Custom var1: %s" % self.conf.get("user.custom.var1"))

注意

conf 属性是只读属性。它只能在 profiles 和命令行中定义,但不应由 recipes 设置。Recipes 只能通过 self.conf.get() 方法读取其值。

输出

输出内容

使用 self.output 属性将内容打印到输出。

self.output.success("This is good, should be green")
self.output.info("This is neutral, should be white")
self.output.warning("This is a warning, should be yellow")
self.output.error("Error, should be red")

还提供了其他输出方法,您可以使用不同的颜色产生不同的输出。有关可用输出方法的列表,请参阅 输出文档

revision_mode

此属性允许每个 recipe 声明如何计算 recipe 本身的修订版本。它可以接受三个不同的值:

  • "hash"(默认):Conan 将使用 recipe manifest 的校验和哈希来计算 recipe 的修订版本。

  • "scm":如果项目位于 Git 存储库中,则提交 ID 将用作 recipe 的修订版本。如果没有存储库,则会引发错误。

  • "scm_folder":此配置适用于您拥有单体存储库项目,但仍希望使用scm修订版本的情况。在这种场景下,导出的 conanfile.py 的修订版本将对应于其所在文件夹的提交 ID。这种方法允许同一个 Git 存储库中存在多个 conanfile.py 文件,每个文件在各自的修订版本下导出。

当选择 scmscm_folder 时,将使用 Git 提交,但默认情况下存储库必须是干净的,否则很可能存在未提交的更改,并且构建将无法重现。因此,如果存在脏文件,Conan 将引发错误。如果存储库中存在不属于 recipe 或包的脏文件,则可以使用 core.scm:excluded 配置将它们排除在检查之外,该配置是一个模式列表 (fnmatch) 以供排除。

upload_policy

控制当前构建的包的二进制文件何时上传或不上传。

  • "skip":不上传预编译的二进制文件。这对于仅下载和解压大型内容的“安装程序”包很有用(例如 android-ndk),并且与 build_policy = "missing" 一起使用很有用。

    class Pkg(ConanFile):
        upload_policy = "skip"
    

required_conan_version

Recipes 可以定义一个模块级别的 required_conan_version,它定义了一个有效的 Conan 版本范围,可以加载和理解当前的 conanfile.py。语法如下:

from conan import ConanFile

required_conan_version = ">=2.0"

class Pkg(ConanFile):
    pass

版本范围(如 requires 中所示)是允许的。此外,还有一个 global.conf 文件 core:required_conan_version 配置,它可以定义一个全局的 Conan 运行最低、最高或精确版本,这对于维护开发团队和 CI 机器使用所需版本范围非常方便。

implements

列表用于定义一系列 Conan 将自动处理的选项配置。这对于避免大多数 recipes 中容易重复的样板代码特别有用。语法如下:

from conan import ConanFile

class Pkg(ConanFile):
    implements = ["auto_shared_fpic", "auto_header_only", ...]

目前,Conan 提供了以下自动实现:

  • "auto_shared_fpic":自动管理 fPICshared 选项。添加此实现将在 configureconfig_options 步骤中生效,前提是这些方法未在 recipe 中明确定义。

  • "auto_header_only":自动管理包 ID 清除设置。添加此实现将在 package_id 步骤中生效,前提是该方法未在 recipe 中明确定义。

警告

这是 Conan 2.0 特有的功能,在 1.X 中将不起作用。

alias

警告

虽然别名在 Conan 2 中技术上仍然可以使用,但不建议使用它们,并且它们可能会在未来版本中被完全移除。鼓励用户适应 更新的版本控制功能,以获得更标准化和高效的包管理体验。

在 Conan 2 中,alias 属性仍然是 recipe 的一部分,允许用户为包版本定义一个别名。通常,您可以使用 conan new 命令和 alias 模板创建它,然后使用 conan export 导出 recipe。

$ conan new alias -d name=mypkg -d version=latest -d target=1.0
$ conan export .

请注意,在要求别名时,您必须将版本放在括号 () 中,以明确声明将别名作为依赖项使用。

class Consumer(ConanFile):

    ...
    requires = "mypkg/(latest)"
    ...

extension_properties

extensions_properties 属性是一个字典,用于定义并将信息从 recipes 传递给 Conan 扩展。

目前,已定义的属性有 compatibility_cppstdcompatibility_cstd,它们允许禁用 默认的 compatibility.py 扩展 的行为,该扩展将使用不同 compiler.cppstdcompiler.cstd 值构建的二进制文件视为 ABI 兼容。要为当前包禁用此行为,可以通过以下方式实现:

class Pkg(ConanFile):
    extension_properties = {"compatibility_cppstd": False}

如果需要有条件地执行此操作,也可以在 recipe 的 compatibility() 方法中定义其值:

class Pkg(ConanFile):

    def compatibility(self):
        self.extension_properties = {"compatibility_cppstd": False}

注意

extension_properties 的值默认不会从依赖项传播到使用者,但可以通过迭代 self.dependencies 并检查其 extension_properties 的所需值来手动传播。