设置和选项如何影响配方包 ID¶
在 Conan 中,包 ID 是一个用于识别包二进制文件的唯一标识符,它会考虑所有影响其二进制兼容性的因素。这些因素包括配方选项和设置,以及依赖项或工具要求。
让我们看看设置和选项如何影响包 ID,以及在哪些情况下它们不应该影响包 ID。
设置如何影响包 ID¶
设置是项目范围内的变量,例如编译器、其版本或操作系统本身。这些变量值必须定义,应该与我们的开发环境的值匹配,并且不能像选项那样具有默认值。
例如,让我们定义一个仅依赖于操作系统的配方
from conan import ConanFile
class Pkg(ConanFile):
name = "pkg"
version = "1.0.0"
settings = "os" # Only OS setting affects the package ID
如果从这个配方为 Linux 生成一个包,我们将得到以下包 ID
$ conan create . --settings os=Linux
...
pkg/1.0.0: Package '9a4eb3c8701508aa9458b1a73d0633783ecc2270' created
$ conan list pkg/1.0.0:*
Local Cache
pkg
pkg/1.0.0
revisions
476929a74c859bb5f646363a4900f7cf (2024-03-07 09:13:43 UTC)
packages
9a4eb3c8701508aa9458b1a73d0633783ecc2270
info
settings
os: Linux
如果我们对 Windows 执行同样的操作,那么包 ID 将会不同
$ conan create . --settings os=Windows
...
pkg/1.0.0: Package 'ebec3dc6d7f6b907b3ada0c3d3cdc83613a2b715' created
$ conan list pkg/1.0.0:*
Local Cache
pkg
pkg/1.0.0
revisions
476929a74c859bb5f646363a4900f7cf (2024-03-07 09:13:43 UTC)
packages
9a4eb3c8701508aa9458b1a73d0633783ecc2270
info
settings
os: Linux
ebec3dc6d7f6b907b3ada0c3d3cdc83613a2b715
info
settings
os: Windows
每当设置或子设置的值发生变化时,包 ID 都会不同,以反映这一点。
设置最常见的用途是模拟可能影响包 ID 的不同项目范围内的方面。一个这样做配方将会是
from conan import ConanFile
class Pkg(ConanFile):
name = "pkg"
version = "1.0.0"
settings = "os", "arch", "compiler", "build_type"
现在,使用不同的编译器版本编译包将导致不同的包 ID
$ conan create . --settings compiler.version=192
...
pkg/1.0.0: Package '4f267380690f99b3ef385199826c268f63147457' created
$ conan create . --settings compiler.version=193
...
pkg/1.0.0: Package 'c13a22a41ecd72caf9e556f68b406569547e0861' created
$ conan list pkg/1.0.0:*
Local Cache
pkg
pkg/1.0.0
revisions
f1f48830ecb04f3b328429b390fc5de8 (2024-03-07 09:21:07 UTC)
packages
4f267380690f99b3ef385199826c268f63147457
info
settings
arch: x86_64
build_type: Release
compiler: msvc
compiler.cppstd: 14
compiler.runtime: dynamic
compiler.runtime_type: Release
compiler.version: 192
os: Windows
c13a22a41ecd72caf9e556f68b406569547e0861
info
settings
arch: x86_64
build_type: Release
compiler: msvc
compiler.cppstd: 14
compiler.runtime: dynamic
compiler.runtime_type: Release
compiler.version: 193
os: Windows
移除用于作为 tool_require 的包的设置¶
在某些情况下,一个设置不应该影响生成的包 ID。一个例子是当一个配方打包一个将通过 tool_requires 用于构建其他包的工具时
在这种情况下,编译器值对于工具的编译是必需的,但对于使用者来说并不重要,因为我们只想执行该工具来构建其他项目。因此,我们可以最终从包 ID 中移除编译器的影响
from conan import ConanFile
class CMake(ConanFile):
name = "cmake"
version = "1.0.0"
settings = "os", "arch", "compiler", "build_type" # Only OS and architecture influence the resulting package
def build(self):
# self.settings.compiler value will be used here to compile cmake
def package_id(self):
# Remove compiler setting from package ID
del self.info.settings.compiler
为什么不从 settings 属性中移除设置?因为编译器值仍然需要在 build() 方法中用于执行可执行文件的编译。
注意
在生成我们自己的可执行文件(我们自己的应用程序,而不是 tool_require)的情况下,不建议从包 ID 中移除编译器设置,因为我们总是希望知道该包是用特定的编译器生成的。
但是,如果我们要打包一个甚至不需要编译器输入进行构建的工具(例如 Python 脚本),我们也可以直接移除设置属性
from conan import ConanFile
class MyPythonScripts(ConanFile):
name = "my-python-scripts"
version = "1.0.0"
# No settings this time
或者,如果该工具是平台特定的,我们可以只保留操作系统和体系结构信息
from conan import ConanFile
class MyScripts(ConanFile):
name = "my-scripts"
version = "1.0.0"
settings = "os", "arch"
选项如何影响包 ID¶
选项用于指定单个配方特有的特征,与通常在项目内的配方中保持一致的设置形成对比。它们通常是库可执行文件或 conan 包可能具有的一组特定特征。
例如,shared 选项是用于可以生成共享库的配方的常用选项。但是,它不能是一个设置,因为并非所有配方都生成共享库。
from conan import ConanFile
class Pkg(ConanFile):
name = "pkg"
version = "1.0.0"
options = {"shared": [True, False]}
default_options = {"shared": True}
与设置类似,选项的不同值会影响包 ID,因此,根据选项的不同,将生成不同的包。
$ conan create . --options shared=True
...
pkg/1.0.0: Package '1744785cb24e3bdca70e27041dc5abd20476f947' created
$ conan create . --options shared=False
...
pkg/1.0.0: Package '55c609fe8808aa5308134cb5989d23d3caffccf2' created
同样,可能存在作为配方输入所需的“选项”,但不应将其计入包 ID 中。一个例子是在构建阶段控制某些内容,但不影响包结果的选项,例如编译的详细程度。在这种情况下,配方应该在 package_id() 方法 中移除该选项
但是,通常的建议是 选项应该始终影响包 ID,并且如果我们需要一个配方的输入,但不应该影响它,应该通过配置文件的 conf 部分 来完成。然后,在配方中,我们应该只添加
from conan import ConanFile
class MyPkg(ConanFile):
name = "my-pkg"
version = "1.0.0"
def build(self):
verbosity = self.conf.get("user.my-pkg:verbosity")
self.output.info(f"Using verbosity level: {verbosity})
...
[conf]
user.my-pkg:verbosity=silent
这样包 ID 将不会受到影响,配方会更简洁(没有与包 ID 无关的选项),并且可以通过配置文件的 conf 部分轻松管理输入。