finalize()

Warning

This feature is experimental and subject to breaking changes. See the Conan stability section for more information.

Package immutability is an important concept in Conan. It ensures that the package is not modified after it has been built and packaged, so that the package id is consistent and the package can be reused in different machines.

This method is intended for customization of the package in the running machine, allowing modifications to the package that will be used by the consumers of the package, but not modifying the original package inside the Conan cache. This method is called after the package has been installed in the local cache and the modifications are not uploaded to any remote server, they are only local.

The main use-cases of this method include:

  • Having different packages that get modified when they are run (Like python tools that generate pycache files as part of their execution)

  • Modifying the package to be used in the local machine (Like creating a conf file with the necessary environment variables for the package to be used in the local machine)

These changes are transparent to the consumers of the package, they will use the customized package as if they were dealing with the original package, so changes made in this method should work.

finalize() example usage

The most common use-case of this method is to avoid corrupting the immutability of the package.

For example, if a package generates some files during its execution, like a python package that generates pycache files, you can use this method to generate those files in the local machine, without affecting the original package. This is the case for tools like 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)

Here we are copying the files from the immutable package folder to the finalized package folder, which inside the finalize method (and everywhere after that point) will be the new package folder, so that any modifications done by the package are done in the local finalized folder, without affecting the original package.

For cases where it’s necessary to access the original package, the immutable_package_folder attribute is available both in the same recipe’s self.immutable_package_folder and thru the self.dependencies[<package_name>].immutable_package_folder attribute in the dependants’ recipe. This info is also serialized as part of the graph information in conan graph info etc.

As this method must have a 1 to 1 correspondence to the generated package id, access to self.settings, self.options and self.cpp_info is forbidden inside the finalize() method, and _must_ be done thru the self.info attribute.

Note

Without using this approach, the package would generate the pycache files in the package folder, and thus there would be a need to set PYTHONDONTWRITEBYTECODE to avoid mutating the package, but this would affect performance, and performing cache integrity checks either thru conan cache check-integrity or as part of the upload processes in conan upload ... --check would raise errors if the modified package was ever checked.

Warning

This is not a replacement for the post_package hook. The hook runs after the creation of the package for a chance to modify it before the package_id is computed, but it is not intended for modifications of the package for a particular running machine.