属性¶
包引用¶
Recipe 属性,可以定义主要的 pkg/version@user/channel
包引用。
name¶
包的名称。一个有效的名称必须是全小写,且具备:
最少 2 个字符,最多 101 个字符(建议使用较短的名称)。
- 匹配以下正则表达式
^[a-z0-9_][a-z0-9_+.-]{1,100}$
:以字母数字或_
开头, 后面是 1 到 100 个字符,可以是字母数字、
_
、+
、.
或-
。
- 匹配以下正则表达式
- 只有在将 recipe
export
到本地缓存时才需要名称(export
、export-pkg
和
create
命令),如果在命令行中未使用--name=<pkgname>
定义名称,则需要此属性。
version¶
包的版本。有效的版本遵循与 name
属性相同的规则。如果版本遵循语义版本控制,形式为 X.Y.Z-pre1+build2
,该值可用于通过版本范围而非精确版本来要求此包。
只有在将 recipe export
到本地缓存时才严格需要版本(export
、export-pkg
和 create
命令),如果在命令行中未使用 --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>
指定。
channel¶
channel
字段的有效字符串遵循与 name
属性相同的规则。这是一个可选属性。有时用于标识包的成熟度(如“stable”、“testing”……),但通常情况下这并非必需,包的成熟度通过将它们放在不同的服务器仓库中可以更好地管理。
Channel 可以在命令行中通过 --channel=<mychannel>
指定。
元数据¶
可选的元数据,如许可证、描述、作者等。在大多数情况下不是必需的,但拥有它们可能会很有用。
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"
topics¶
用于将相关包分组并描述代码主题的标签。在 ConanCenter 中用作搜索过滤器。可选属性。应为字符串元组。
class ProtocInstallerConan(ConanFile):
name = "protoc_installer"
version = "0.1"
topics = ("protocol-buffers", "protocol-compiler", "serialization", "rpc")
homepage¶
正在打包的库的主页。
用于将 recipe 链接到对库本身的进一步解释,如其特性概述、文档、FAQ 以及其他相关信息。
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"
依赖关系¶
依赖项简单声明的属性形式,如 requires
, tool_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 |
另请参阅
查看 范围表达式 version_ranges 教程部分
查看 requirements() 方法文档
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 recipe 中使用 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 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
,其中 pyreq
是 python_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
源代码¶
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 一起导出,也会自动随 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() 方法时注入由 tool requires 生成的 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¶
可选。声明 package_type
将有助于 Conan:
为每个依赖项更好地选择默认的
package_id_mode
,即依赖项的更改应如何影响当前包的package_id
。依赖项中的哪些信息应该传播给消费者,例如头文件、库、运行时信息。请参阅此处,了解根据
package_type
信息传播的特性。
有效值包括:
application: 该包是一个应用程序。
library: 该包是一个通用库。它会尝试通过读取
self.options.shared
(如果已声明)和self.options.header_only
来确定库的类型(从shared-library
、static-library
、header-library
中选择)。shared-library: 该包是一个共享库。
static-library: 该包是一个静态库。
header-library: 该包是一个仅头文件库。
build-scripts: 该包只包含构建脚本。
python-require: 该包是一个 python require。
unknown: 包的类型未知。
settings¶
字符串列表,包含 recipe 需要的第一级设置(来自 settings.yml),因为:- 它们用于构建时读取(例如:if self.settings.compiler == “gcc”) - 它们会影响 package_id
。如果声明的设置值发生变化,则 package_id
必须不同。
最常见的是声明:
settings = "os", "compiler", "build_type", "arch"
Conan 加载 recipe 后,会处理 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.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")
options¶
影响当前 recipe 的特性字典,其中键是选项名称,值是选项可以采用的不同值列表。默认情况下,选项中的任何值更改都会更改 package_id
。请查看 default_options
和 default_build_options
字段以定义选项的默认值。
每个选项的值可以是带类型的或普通字符串("value"
, True
, 42
等)。
有两个特殊值:
None
: 允许选项具有None
值(未指定),且不报错。"ANY"
: 对于可以接受任何值的选项,不受集合限制。
class MyPkg(ConanFile):
...
options = {
"shared": [True, False],
"option1": ["value1", "value2"],
"option2": ["ANY"],
"option3": [None, "value1", "value2"],
"option4": [True, False, "value"],
}
Conan 加载 recipe 后,会处理 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 中定义选项值没有强有力的保证,请查看 关于依赖项选项值的常见问题解答。建议在 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 可以尝试为其依赖项定义选项值,有两种不同方式。使用 default_options = {"mypkg/*:myoption", 123}
,当前 recipe 可以为依赖项 mypkg
的 myoption
定义值 123
。这种为依赖项定义选项的方式存在一些限制:
当前 recipe 的任何其他下游用户,如果为
mypkg
定义了相同的选项,将具有优先权,覆盖当前 recipe 定义的123
值。同样,profile 或命令行中的任何定义也将具有优先权。recipe 的default_options
优先级最低。如果 recipe 在某些依赖项选项下根本无法工作,则 recipe 可以进行检查并相应地引发ConanInvalidConfiguration
错误。任何依赖
mypkg
的 *同级* 包也会定义其选项,并且只有它的定义会被考虑在内。换句话说,任何其他包第一次要求mypkg
时,将“冻结”其当前分配的选项值。任何之后依赖mypkg
的包,即使在依赖图中形成菱形结构,也不会对mypkg
的选项产生任何影响。只有第一个要求它的包会起作用。
定义选项值的第二种方式是将其定义为 important!
。
警告
important!
语法是实验性的,随时可能更改或移除。
recipe 可以使用语法 default_options = {"mypkg/*:myoption!", 123}
将其依赖项选项定义为 important!
。这意味着 mypkg
的 myoption
不会被其他下游包、profile 或命令行进行的常规选项定义(例如 -o *:myoption=234
)覆盖。
但在两种情况下,这仍然不会定义依赖项的最终值:
如果任何下游 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
属性是一个可选属性,可以定义为字典形式,其中键是选项名称,值是选项的文本描述。此属性对于提供有关每个选项功能和目的的附加信息非常有用,特别是当选项不是自解释的或具有复杂或特殊行为时。
每个字典条目的格式应为:
键:选项名称。必须是字符串,并且必须与
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
recipe 属性 languages
可用于定义此包涉及的编程语言。目前 C
和 C++
语言是可能的取值。例如,一个纯 C 包可以定义为:
class ZLib(ConanFile):
languages = "C"
可以定义多种语言,例如当包由 C 和 C++ 源代码构建时,languages = "C", "C++"
是正确的定义。
关于 languages
定义,将发生以下情况:
如果未定义
languages
或C
不是声明的语言,则在包的configure()
时将自动移除compiler.cstd
子设置(以实现向后兼容)。如果定义了
languages
,但其中不包含C++
,则在包的configure()
时将自动移除compiler.cppstd
和compiler.libcxx
子设置。
info¶
仅在 package_id()
方法中使用的对象
:ref:package_id 方法<reference_conanfile_methods_package_id> 用于控制包的唯一 ID。
def package_id(self): self.info.clear()
self.info.clear()
方法从 package_id
计算中移除所有设置、选项、依赖项(requires
、tool_requires
、python_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 中定义,用于定义它们作为 requires
被消费时,对其消费者 package_id
的影响。
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 中的属性定义对于定义偏离默认值的行为非常有用。
可能的值包括(遵循 MAJOR.MINOR.PATCH 的 semver 定义):
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_revision
或package_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
: 定义包之间关系未知时的模式。如果无法推断包类型,因为没有定义shared
或header_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 二进制模型。
构建¶
generators¶
包含 generator 名称的字符串列表或元组。
class MyLibConan(ConanFile):
generators = "CMakeDeps", "CMakeToolchain"
generator 也可以在 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
文件夹和布局¶
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
值来构建的。
package_folder¶
用于复制二进制包最终工件的文件夹。在本地缓存中,会为每个不同的 package ID 创建一个 package 文件夹。
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 元数据文件。更多信息请参阅 元数据部分。
package_metadata_folder¶
self.package_metadata_folder
(实验性)可在 generate()
、build()
和 package()
方法中使用,用于保存或复制 包 元数据文件。更多信息请参阅 元数据部分。
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
文件夹。
另请参阅
阅读 仅头文件包部分 查看使用 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
的位置。
布局¶
folders¶
folders
属性只能在 layout()
方法中设置。请查看 layout() 方法文档 了解更多关于此属性的信息。
cpp¶
存储包消费者所需所有信息的对象:include 目录、库名称、库路径等。对于可编辑包和缓存中的常规包都适用。它仅在 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 的 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"))
供消费者使用的包信息¶
cpp_info¶
与在 layout()
方法中使用 self.cpp.package
相同。如果您需要读取 package_folder
以定位已找到的工件,请使用它。
另请参阅
CppInfo 模型。
重要
此属性仅在 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 的 generator。应仅在 package_info()
方法中填充。
另请参阅
请参阅 此处的使用示例 和 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'
属性值应该是一个食谱名称的字符串,或者此类食谱名称的元组。
例如,要声明食谱 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 食谱通过 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 的完整参考。
子图¶
(实验性) 食谱的只读依赖关系图。应使用 dependencies
属性访问食谱的依赖项,因为此属性旨在传递给其他 Conan API,并用于高级用途,例如 SBOM 生成。
配置¶
在 self.conf
属性中,我们可以找到 profiles 的 [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 和命令行中定义,但绝不应由食谱设置。食谱只能通过 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")
提供了额外的输出方法,您可以使用不同的颜色生成不同的输出。请参阅输出文档以获取可用输出方法的列表。
修订模式¶
此属性允许每个食谱声明如何计算食谱自身的修订版本。它可以采用三个不同的值
"hash"
(默认): Conan 将使用食谱清单的校验和哈希来计算食谱的修订版本。"scm"
: 如果项目位于 Git 仓库中,将使用提交 ID 作为食谱修订版本。如果没有仓库,将引发错误。"scm_folder"
: 当您拥有一个单仓库项目,但仍想使用 scm 修订版本时,此配置适用。在这种情况下,导出的 conanfile.py 的修订版本将对应于其所在文件夹的提交 ID。这种方法允许在同一个 Git 仓库中存在多个 conanfile.py 文件,每个文件都以其独特的修订版本导出。
当选择 scm
或 scm_folder
时,将使用 Git 提交,但默认情况下仓库必须是干净的,否则很可能存在未提交的更改,并且构建将不可重现。因此,如果存在脏文件,Conan 将引发错误。如果仓库中存在可能脏污但完全不属于食谱或包的文件,则可以使用 core.scm:excluded
配置将它们排除在检查之外,该配置是一个要排除的模式列表 (fnmatch)。
上传策略¶
控制当前包构建的二进制文件是否上传
"skip"
: 预编译的二进制文件不会上传。这对于仅下载和解压大型文件(例如 android-ndk)的“安装程序”包非常有用,并且与build_policy = "missing"
一起使用时也很方便。class Pkg(ConanFile): upload_policy = "skip"
所需 Conan 版本¶
食谱可以定义模块级别的 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 机器使用所需的版本范围非常方便。
实现¶
使用列表来定义一系列选项配置,Conan 将自动处理这些配置。这对于避免在大多数食谱中重复出现的样板代码特别有用。语法如下
from conan import ConanFile
class Pkg(ConanFile):
implements = ["auto_shared_fpic", "auto_header_only", ...]
Conan 目前提供的自动实现如下
"auto_shared_fpic"
: 自动管理fPIC
和shared
选项。当食谱中未显式定义 configure 和 config_options 方法时,添加此实现将在这些步骤中产生效果。"auto_header_only"
: 自动管理包 ID 清除设置。当食谱中未显式定义 package_id 方法时,添加此实现将在 package_id 步骤中产生效果。
警告
这是 2.0 版本的独有功能,在 1.X 版本中无法工作。
别名¶
警告
虽然别名在 Conan 2 中技术上仍然可以使用,但其使用不推荐,并且在未来的版本中可能会被完全移除。鼓励用户采用较新的版本控制功能,以获得更标准化、更高效的包管理体验。
在 Conan 2 中,alias 属性仍然是食谱的一部分,允许用户为包版本定义别名。通常,您可以使用 conan new
命令和 alias
模板创建别名,然后使用 conan export 导出食谱。
$ conan new alias -d name=mypkg -d version=latest -d target=1.0
$ conan export .
请注意,在要求别名时,必须将版本放在括号 ()
中,以显式声明将别名用作依赖项。
class Consumer(ConanFile):
...
requires = "mypkg/(latest)"
...
扩展属性¶
extensions_properties
属性是一个字典,用于定义并将信息从食谱传递给 Conan 扩展。
目前,唯一定义的属性是 compatibility_cppstd
和 compatibility_cstd
,它们允许禁用默认 compatibility.py 扩展的行为,该扩展认为使用不同 compiler.cppstd
和 compiler.cstd
值构建的二进制文件之间 ABI 兼容。要禁用当前包的此行为,可以使用以下方法
class Pkg(ConanFile):
extension_properties = {"compatibility_cppstd": False}
如果需要有条件地执行此操作,也可以在食谱的 compatibility()
方法内部定义其值。
class Pkg(ConanFile):
def compatibility(self):
self.extension_properties = {"compatibility_cppstd": False}
注意
extension_properties
的值默认情况下不会从依赖项传递到消费者,但可以通过遍历 self.dependencies
并检查其 extension_properties
的所需值来手动传播。