扩展二进制模型¶
有一些机制可以扩展默认的 Conan 二进制模型
自定义设置 (Settings)¶
可以在 *settings.yml* 文件中添加新的设置或子设置,例如:
os:
Windows:
new_subsetting: [null, "subvalue1", "subvalue2"]
new_root_setting: [null, "value1", "value2"]
其中 null
值允许在 profile 中保留未定义的设置。 如果不包含,则 profile 必须为它们定义一个值。
自定义设置将在 recipe 和 package 中显式或隐式使用
class Pkg(ConanFile):
# If we explicilty want this package binaries to vary according to 'new_root_setting'
settings = "os", "compiler", "build_type", "arch", "new_root_setting"
# While all packages with 'os=Windows' will implicitly vary according to 'new_subsetting'
另请参阅
有关如何自定义 settings.yml
文件的完整参考,请访问 settings 部分。 实际上,没有必要修改 settings.yml
文件,而是可以提供 settings_user.yml
文件来扩展现有设置。 请参阅settings_user.yml 文档。
自定义选项 (Options)¶
Options
对于每个 recipe 都是自定义的,没有像 settings.yml
那样的全局 options 定义。
Package conanfile.py
recipe 定义了自己的 options,具有自己的有效值范围和默认值
class MyPkg(ConanFile):
...
options = {"build_tests": [True, False],
"option2": ["ANY"]}
default_options = {"build_tests": True,
"option1": 42,
"z*:shared": True}
对于 Conan 来说, options shared
、fPIC
和 header_only
具有特殊的含义,并且大多数内置构建系统集成都会自动考虑它们。 它们也是表示库是共享、静态还是仅标头的推荐默认值。
Settings vs Options vs Conf¶
何时使用 settings、options 或 configuration?
Settings 是项目范围的配置,通常会影响正在构建的整个项目并影响生成的 package 二进制文件。 例如,操作系统或架构对于依赖关系图中的所有 package 自然是相同的,将 Linux 库链接到构建 Windows 应用程序,或混合架构是不可能的。 Settings 无法在 package recipe 中默认设置。 给定库的 recipe 不能说其默认值为
os=Windows
。os
将由处理该 recipe 的环境给出。 它是输入 profile 中定义的强制性输入。另一方面, Options 是影响生成的 package 二进制文件的 package 特有配置。 静态或共享库不是适用于所有 package 的 settings。 有些可以是仅标头的库,而其他 package 可以只是数据或 package 可执行文件。 例如,
shared
是一个常见的 option(用于指定库可以是静态的还是共享的默认值),但 package 可以定义和使用他们想要的任何 option。 Options 在 packageconanfile.py
recipe 中定义,包括其支持的和默认值,使用options
和default_options
。通过
conf
进行配置旨在用于通常不影响生成的 package 二进制文件的配置。 例如,使用tools.cmake.cmaketoolchain:generator=Ninja
构建一个库不应导致与使用 Visual Studio 构建的二进制文件不同(通常只是由于 Ninja 带来了更快的构建速度)。
以上情况存在一些例外。 例如,可以使用 <pattern:>setting=value
在 profile 和命令行中为每个 package 定义 settings
$ conan install . -s mypkg/*:compiler=gcc -s compiler=clang ..
这将对 "mypkg" 使用 gcc
,对其余依赖项使用 clang
(在大多数情况下,建议对整个依赖关系图使用相同的编译器,但在保证强二进制兼容性的某些情况下,可以混合使用用不同编译器构建的库)。
在许多 package 使用相同的 option 值的情况下,允许您使用 pattern 设置其值一次,例如:
$ conan install . -o *:shared=True
自定义配置¶
如上所述,Conan conf
配置系统旨在调整某些工具和行为,但实际上并不影响生成的 package 二进制文件。 一些典型的 conf
项是激活并行构建、配置上传到服务器时的“重试”或更改 CMake 生成器。 阅读更多关于本节中的 Conan 配置系统。
也可以为用户定义的配置定义 user.xxxx:conf=value
,它与核心和工具内置配置的精神相同,不会影响二进制文件的 package_id
。
但是,在某些特殊情况下,确实希望某些 conf
定义不同的 package_ids
,从而创建不同的 package 二进制文件。 可以在两个不同的地方执行此操作
在本地,在 recipe 的
package_id
方法中,通过self.info.conf
属性def package_id(self): # We can get the value from the actual current conf value, or define a new value value = self.conf.get("user.myconf:myitem") # This ``self.info.conf`` will become part of the ``package_id`` self.info.conf.define("user.myconf:myitem", value)
全局地,使用
tools.info.package_id:confs
配置,接收一个现有配置的列表作为参数,该配置将成为 package ID 的一部分,因此您可以在 profile 中定义tools.info.package_id:confs=["tools.build:cxxflags", ...]
package_id
的值将包含在tools.build:cxxflags
和其他配置中提供的值。 请注意,此值作为字符串进行管理,更改字符串将产生不同的结果和不同的package_id
,因此如果使用此方法,则必须与tools.build:cxxflags
之类的不同配置的提供的值保持一致。也可以使用正则表达式来匹配多个
confs
,而不是列出所有confs
,例如.*cmake
可以匹配其名称中包含 "cmake" 的任何配置(不建议这样做,请参阅下面的最佳实践)。
注意
最佳实践
通常,通过 conf
定义二进制文件 package_id
的可变性应保留给特殊情况,并始终谨慎管理。 将许多不同的 confs
传递给 tools.info.package_id:confs
很容易导致诸如缺少二进制文件或不必要地构建过多二进制文件之类的问题。 如果是这种情况,请考虑使用新的自定义 settings 或 options 在您的二进制文件上构建更高级别的抽象。
交叉构建目标 settings¶
self.settings_target
是 conanfile.py
属性,在“构建”上下文中 tool_requires
工具的交叉编译场景中变得相关。 当我们有像 CMake 这样的 tool_requires
时,假设 cmake/3.25.3
,package 二进制文件独立于交叉编译可能针对的平台,对于所有不同的目标平台,它是相同的 cmake
可执行文件。 对于从 Windows-X64 到 Linux-armv8 场景的交叉构建,cmake
conanfile recipe 的 settings
将是
self.settings
: 当前cmake/3.25.3
运行的设置。 由于它是一个工具需求,它将在 Windows 机器上运行,因此self.settings.os = Windows
且self.settings.arch = x86_64
。self.settings_build
: 当前构建机器的设置,如有必要,它将构建此包。 这也是 Windows-x64 机器,因此self.settings_build.os = Windows
且self.settings_build.arch = x86_64
。self.settings_target
: 当前应用程序输出将面向的设置。 在这种情况下,它将是self.settings_target.os = Linux
且self.settings_target.arch = armv8
在 cmake
包方案中,正如我们指出的那样,目标是不相关的。 它根本没有在 cmake
conanfile recipe 中使用,并且它不会影响 cmake
二进制包的 package_id
。
但是在某些情况下,二进制包可能因目标平台而异。 例如,一个交叉编译器 gcc
,它有一个不同的 gcc
可执行文件,具体取决于它将编译的目标。 这在 GNU 生态系统中很典型,我们可以在其中找到 arm-gcc
工具链,例如,专门用于给定的架构。 Conan 可以通过使用这些 settings_target
的值扩展 package_id
来反映这种情况。
def package_id(self):
self.info.settings_target = self.settings_target
# If we only want the ``os`` and ``arch`` settings, then we remove the other:
self.info.settings_target.rm_safe("compiler")
self.info.settings_target.rm_safe("build_type")