属性

包引用

可以定义主要pkg/version@user/channel包引用的配方属性。

名称

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

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

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

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

名称仅在将配方导出到本地缓存(exportexport-pkg

create命令)时才需要,如果它们未在命令行中使用--name=<pkgname>定义。

版本

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

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

可以在命令行中动态定义version,也可以在配方中使用set_version() 方法以编程方式定义。

用户

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

可以在命令行中使用--user=<myuser>指定用户。

通道

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

可以在命令行中使用--channel=<mychannel>指定通道。

元数据

可选元数据,如许可证、描述、作者等。在大多数情况下不需要,但可能会有用。

描述

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

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"""

许可证

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

这将有助于希望自动执行许可证兼容性检查的人员,例如您的包的使用者,或者如果您是包具有开源依赖项。

class Pkg(ConanFile):
    license = "MIT"

作者

包的主要维护人员/负责人,任何格式。这是一个可选属性。

class HelloConan(ConanFile):
    author = "John J. Smith ([email protected])"

主题

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

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

主页

正在打包的库的主页。

用于将配方链接到库本身的进一步说明,例如其功能概述、文档、常见问题解答以及其他相关信息。

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

URL

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

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

需求

依赖项简单声明的属性形式,如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]"

可接受的表达式为

表达式

范围内的版本

范围外的版本

[>=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

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

表达式

范围内的版本

范围外的版本

[>=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”。如果当前包存在预编译的二进制文件,则不会检索 tool_require 的二进制文件。它们不能冲突。

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 中不鼓励使用,并且将在未来的 2.X 版本中弃用。请在您的 Conan 2 配方中使用tool_requires 而不是build_requires

test_requires

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

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

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

python_requires

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

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 依赖项

python_requires_extend

此类属性定义一个或多个类,这些类将在运行时作为配方类的基类注入。每个类的语法应类似于字符串 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

源代码

导出

字符串列表或元组,包含应导出并与 conanfile.py 文件并排存储的 文件名fnmatch 模式,以使配方正常工作:配方将导入的其他 Python 文件,一些包含要读取数据的文本文件等。

例如,如果我们有一些 Python 代码希望配方在 helpers.py 文件中使用,并且有一些文本文件 info.txt 我们希望在配方评估期间读取并显示,我们会执行以下操作

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

也支持排除模式,使用 ! 前缀

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

导出源代码

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

这是一种使用 source() 方法获取源代码的替代方法。当我们不打包第三方库并且同时拥有配方和 C/C++ 项目时使用。

exports_sources = "include*", "src*"

也支持排除模式,使用 ! 前缀

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

请注意,如果配方定义了 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 文件会自动与配方一起导出,并自动加载。

您可以在 conandata.yml 文件中声明信息,然后在配方的任何方法内部访问它。例如,一个包含源代码信息的 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

二进制模型

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

包类型

可选。声明 package_type 将帮助 Conan

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

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

有效值为

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

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

  • **共享库**:该包是一个共享库。

  • **静态库**:该包是一个静态库。

  • **头文件库**:该包是一个仅包含头文件的库。

  • **构建脚本**:该包仅包含构建脚本。

  • **python 依赖项**:该包是一个 Python 依赖项。

  • **未知**:包的类型未知。

设置

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

最常见的是声明

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

Conan 加载配方后,将处理 settings 并可以在配方中读取它们,还可以读取子设置

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.compiler)}:  {', '.join(compiler_versions)}")

如上所示,执行 self.settings.possible_values() 会将整个 settings.yml 作为 Python 类字典对象返回,例如执行 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")

选项

包含影响当前配方的特征的字典,其中键是选项名称,值是选项可以采用的不同值的列表。默认情况下,选项中的任何值更改都会更改 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"],
}

Conan 加载配方后,将处理 options 并可以在配方中读取它们。您还可以使用 .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")

另请参阅

  • 阅读入门,创建包以了解如何声明选项以及如何为选项定义值。

  • package_id()方法中删除选项。<缺少页面>

  • 关于 package_type 及其在声明shared选项时的作用。<缺少页面>

default_options

属性default_options定义了选项的默认值,包括当前配方和任何需求。此属性应定义为 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或任何包含*的模式,如上例所示。

警告

在配方中定义选项值没有强保证,请查看关于依赖项选项值的此常见问题解答。定义选项值的推荐方法是在配置文件中。

您还可以使用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()方法中分配了值,则无法覆盖它。

另请参阅

配方有两种不同的方法可以尝试为其依赖项定义选项值。使用default_options = {"mypkg/*:myoption", 123},当前配方可以将值123定义为依赖项mypkgmyoption。这种为依赖项定义选项的方式有一些限制

  • 当前配方的任何其他下游用户如果为mypkg定义了相同的选项,则将具有优先级,覆盖当前配方的123值。配置文件或命令行中的任何定义也将具有优先级。配方default_options具有最低优先级。如果配方根本无法与某些依赖项选项一起工作,则配方可以相应地检查并引发ConanInvalidConfiguration错误。

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

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

警告

语法important!处于实验阶段,可能会随时更改或删除。

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

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

  • 如果任何下游配方、命令行或配置文件也使用myoption!语法,则它也将具有优先级并覆盖上游的值

  • 如果任何其他包首先需要mypkg,则此时定义的值仍将具有优先级。

通常,定义选项值的建议是在profile文件中进行,而不是在配方中,因为在配方中定义对于复杂的依赖关系图来说可能更复杂。

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是一个可选属性,可以以字典的形式定义,其中键是选项名称,值是选项的文本格式描述。此属性对于提供有关每个选项的功能和用途的其他信息非常有用,尤其是在选项本身不明确或具有复杂或特殊行为时。

每个字典条目的格式应为

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

  • 值:选项的描述。必须是字符串,并且可以根据需要任意长。

例如

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配方属性languages可用于定义此包中涉及的编程语言。目前,CC++语言是可能的值。例如,纯 C 包将定义如下内容

class ZLib(ConanFile):
    languages = "C"

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

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

  • 如果未定义languagesC不是声明的语言,则在包configure()时将自动删除compiler.cstd子集(以实现向后兼容性)。

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

info

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

  • 用于控制包唯一 ID 的:ref:package_id 方法<reference_conanfile_methods_package_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

package_id_embed_mode, package_id_non_embed_mode, package_id_python_mode, package_id_unknown_mode是可以在配方中定义的类属性,用于定义它们对其使用者package_id的影响。可以声明为

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"

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

可能的值为(遵循 MAJOR.MINOR.PATCH 的语义版本控制定义)

  • patch_mode:包的新补丁、次要版本和主要版本发布将需要消费者使用新的二进制文件(新的 package_id)。新的配方修订版本不需要消费者使用新的二进制文件。例如,如果我们创建一个新的 pkg/1.0.1 版本,并且某些消费者具有 requires = "pkg/[>=1.0 <2.0]",则此类消费者将针对此特定新的 1.0.1 版本构建新的二进制文件。但是,如果我们只是更改配方,生成新的 recipe_revision,则消费者将不需要构建新的二进制文件。

  • minor_mode:此包的新次要版本和主要版本发布将需要消费者使用新的二进制文件。新的补丁和新的修订版本不需要消费者使用新的二进制文件。这是“非嵌入模式”的默认设置,因为它允许用户精细控制何时重建内容。

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

  • full_mode:此包的完整标识符,包括 pkgname/version@user/channel#recipe_revision:package_id 将用于消费者 package_id 中,然后需要为每次更改此包(因为源代码或配置中的任何更改都会分别产生不同的 recipe_revisionpackage_id)构建消费者的新二进制文件。这是“嵌入模式”的默认设置。

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

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

这四个不同的属性是

  • 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。此属性是为了完整性和诸如临时迁移之类的特殊情况而提供的。

另请参阅

阅读 二进制模型参考 以全面了解 Conan 二进制模型。

构建

生成器

包含生成器名称的字符串列表或元组。

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

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

from conan.tools.cmake import CMakeToolchain

class MyLibConan(ConanFile):
    ...

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

构建策略

控制在 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

文件夹和布局

source_folder

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

请注意,在缓存中运行时 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)与 folders.build 的值(如果在 layout() 方法中声明)连接起来构建。

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

存储配方 *conanfile.py* 的文件夹,位于本地文件夹或缓存中。这对于访问与配方一起导出的文件或导出 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() 方法中用于保存或复制**配方**元数据文件。有关更多信息,请参见 元数据部分

package_metadata_folder

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

no_copy_source

属性 no_copy_source 告诉配方不会将源代码从 source_folder 复制到 build_folder。这主要针对具有大型源代码库或仅头文件的包进行优化,以避免额外的复制操作。

如果激活了no_copy_source=True,则**必须**确保源代码在配置或构建脚本中完全不会被修改,因为源代码将在所有构建之间共享。

配方应始终使用self.source_folder属性,当no_copy_source=False时,它将指向build文件夹,当no_copy_source=True时,它将指向source文件夹。

另请参阅

阅读仅包含头文件的包部分,了解使用no_copy_source属性的示例。

test_package_folder

test_package_folder类属性允许在配方中为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的位置。

布局

文件夹

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属性只能在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的androidndk配方,并且我们希望该配方处于“可编辑”模式,则需要知道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"))

使用者包信息

cpp_info

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

另请参阅

重要

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

buildenv_info

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

重要

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

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

另请参阅

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

runenv_info

对于依赖的配方,声明的环境变量将在运行时存在。应仅在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

要传递给依赖配方的配置变量。应仅在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 的完整参考

generators_info

警告

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

要传递给依赖配方的生成器。应仅在package_info()方法中填充。

已弃用

此属性声明配方已弃用,导致在每次使用时发出用户友好的警告消息。

例如,以下代码

from conan import ConanFile

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

可能会发出类似以下的警告:

cpp-taskflow/1.0: WARN: Recipe 'cpp-taskflow/1.0' is deprecated. Please, consider changing your requirements.

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

from conan import ConanFile

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

这将发出类似以下的警告:

cpp-taskflow/1.0: WARN: Recipe 'cpp-taskflow/1.0' is deprecated in favor of 'taskflow'. Please, consider changing your requirements.

如果属性的值计算结果为False,则不会打印任何警告。

提供

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

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

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

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

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

from conan import ConanFile

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

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

from conan import ConanFile

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

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

其他

依赖项

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 的完整参考

conf

self.conf属性中,我们可以找到在配置文件的[conf]部分声明的所有conf条目。此外,还包括来自一级工具需求中声明的self.conf_info条目。配置文件条目具有优先级。

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属性是**只读**属性。它只能在配置文件和命令行中定义,但绝不应该由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声明如何计算其自身的版本号。它可以取三个不同的值

  • "hash"(默认):Conan将使用recipe清单的校验和哈希来计算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,它定义了可以加载和理解当前conanfile.py的Conan版本的有效版本范围。语法如下

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中没有明确定义时。

警告

这是一个仅限2.0的功能,它在1.X中不起作用。

alias

警告

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

在Conan 2中,alias属性仍然是recipe的一部分,允许用户为包版本定义别名。通常,您将使用带有alias模板的conan new命令创建一个别名,并使用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属性是一个字典,旨在定义和传递recipe到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}