finalize()¶
警告
此特性为实验性功能,可能会有不兼容的更改。有关更多信息,请参阅 Conan 稳定性 部分。
包的不可变性是 Conan 中的一个重要概念。它确保包在构建和打包后不会被修改,从而使得包 ID 一致,并且可以在不同的机器上复用该包。
此方法旨在用于在使用包的机器上对包进行定制,允许修改将由包消费者使用的包,但不修改 Conan 缓存中的原始包。此方法在包安装到本地缓存后调用,且修改不会上传到任何远程服务器,它们仅是本地的。
此方法的主要用例包括
在使用时会被修改的不同包(例如在执行时会生成 pycache 文件的 Python 工具)
修改将在本地机器上使用的包(例如创建一个包含包在本地机器上使用所需的环境变量的
conf
文件)
这些修改对包的消费者是透明的,他们将使用定制后的包,就像在使用原始包一样,因此在此方法中进行的修改应该能正常工作。
finalize() 示例用法¶
此方法最常见的用例是避免破坏包的不可变性。
例如,如果一个包在执行过程中生成了一些文件,例如一个生成 pycache 文件的 Python 包,你可以使用此方法在本地机器上生成这些文件,而不会影响原始包。Meson 等工具就是这种情况。
from conan import ConanFile, conan_version
from conan.tools.files import copy
class MesonPackage(ConanFile):
...
def package(self):
copy(self, "*", src=self.source_folder, dst=os.path.join(self.package_folder, "bin"))
...
def finalize(self):
copy(self, "*", src=self.immutable_package_folder, dst=self.package_folder)
这里我们将文件从不可变包文件夹复制到最终包文件夹,在 finalize 方法内部(以及此后的任何地方),这将是新的包文件夹,这样包所做的任何修改都将发生在本地的最终化文件夹中,而不会影响原始包。
对于需要访问原始包的情况,可以通过 immutable_package_folder
属性来实现。该属性在同一个 recipe 中为 self.immutable_package_folder
,在依赖方的 recipe 中为 self.dependencies[<package_name>].immutable_package_folder
。此信息也会作为图信息的一部分被序列化,例如在使用 conan graph info 等命令时。
由于此方法必须与生成的 package id 一一对应,在 finalize()
方法内部禁止访问 self.settings
、self.options
和 self.cpp_info
,且必须通过 self.info
属性进行访问。
注意
如果不使用此方法,包会在包文件夹中生成 pycache 文件,因此需要设置 PYTHONDONTWRITEBYTECODE
以避免修改包,但这会影响性能。此外,如果对修改后的包进行缓存完整性检查(无论是通过 conan cache check-integrity 还是作为 conan upload ... --check 上传过程的一部分),都将引发错误。
警告
这并非 post_package 钩子的替代品。该钩子在包创建后运行,提供在计算 package_id 之前修改包的机会,但它并非用于修改特定运行机器上的包。