Hooks

Warning

This is an experimental feature subject to breaking changes in future releases.

The Conan hooks are Python functions that are intended to extend the Conan functionalities and let users customize the client behavior at determined execution points. Check the hooks section in extending Conan to see some examples of how to use them and already available ones providing useful functionality.

Hook interface

Here you can see a complete example of all the hook functions available and the different parameters for each of them depending on the context:

def pre_export(output, conanfile, conanfile_path, reference, **kwargs):
    assert conanfile
    output.info("conanfile_path={}".format(conanfile_path))
    output.info("reference={}".format(reference.full_str()))

def post_export(output, conanfile, conanfile_path, reference, **kwargs):
    assert conanfile
    output.info("conanfile_path={}".format(conanfile_path))
    output.info("reference={}".format(reference.full_str()))

def pre_source(output, conanfile, conanfile_path, **kwargs):
    assert conanfile
    output.info("conanfile_path={}".format(conanfile_path))
    if conanfile.in_local_cache:
        output.info("reference={}".format(kwargs["reference"].full_str()))

def post_source(output, conanfile, conanfile_path, **kwargs):
    assert conanfile
    output.info("conanfile_path={}".format(conanfile_path))
    if conanfile.in_local_cache:
        output.info("reference={}".format(kwargs["reference"].full_str()))

def pre_build(output, conanfile, **kwargs):
    assert conanfile
    if conanfile.in_local_cache:
        output.info("reference={}".format(kwargs["reference"].full_str()))
        output.info("package_id={}".format(kwargs["package_id"]))
    else:
        output.info("conanfile_path={}".format(kwargs["conanfile_path"]))

def post_build(output, conanfile, **kwargs):
    assert conanfile
    if conanfile.in_local_cache:
        output.info("reference={}".format(kwargs["reference"].full_str()))
        output.info("package_id={}".format(kwargs["package_id"]))
    else:
        output.info("conanfile_path={}".format(kwargs["conanfile_path"]))

def pre_package(output, conanfile, conanfile_path, **kwargs):
    assert conanfile
    output.info("conanfile_path={}".format(conanfile_path))
    if conanfile.in_local_cache:
        output.info("reference={}".format(kwargs["reference"].full_str()))
        output.info("package_id={}".format(kwargs["package_id"]))

def post_package(output, conanfile, conanfile_path, **kwargs):
    assert conanfile
    output.info("conanfile_path={}".format(conanfile_path))
    if conanfile.in_local_cache:
        output.info("reference={}".format(kwargs["reference"].full_str()))
        output.info("package_id={}".format(kwargs["package_id"]))

def pre_upload(output, conanfile_path, reference, remote, **kwargs):
    output.info("conanfile_path={}".format(conanfile_path))
    output.info("reference={}".format(reference.full_str()))
    output.info("remote.name={}".format(remote.name))

def post_upload(output, conanfile_path, reference, remote, **kwargs):
    output.info("conanfile_path={}".format(conanfile_path))
    output.info("reference={}".format(reference.full_str()))
    output.info("remote.name={}".format(remote.name))

def pre_upload_recipe(output, conanfile_path, reference, remote, **kwargs):
    output.info("conanfile_path={}".format(conanfile_path))
    output.info("reference={}".format(reference.full_str()))
    output.info("remote.name={}".format(remote.name))

def post_upload_recipe(output, conanfile_path, reference, remote, **kwargs):
    output.info("conanfile_path={}".format(conanfile_path))
    output.info("reference={}".format(reference.full_str()))
    output.info("remote.name={}".format(remote.name))

def pre_upload_package(output, conanfile_path, reference, package_id, remote, **kwargs):
    output.info("conanfile_path={}".format(conanfile_path))
    output.info("reference={}".format(reference.full_str()))
    output.info("package_id={}".format(package_id))
    output.info("remote.name={}".format(remote.name))

def post_upload_package(output, conanfile_path, reference, package_id, remote, **kwargs):
    output.info("conanfile_path={}".format(conanfile_path))
    output.info("reference={}".format(reference.full_str()))
    output.info("package_id={}".format(package_id))
    output.info("remote.name={}".format(remote.name))

def pre_download(output, reference, remote, **kwargs):
    output.info("reference={}".format(reference.full_str()))
    output.info("remote.name={}".format(remote.name))

def post_download(output, conanfile_path, reference, remote, **kwargs):
    output.info("conanfile_path={}".format(conanfile_path))
    output.info("reference={}".format(reference.full_str()))
    output.info("remote.name={}".format(remote.name))

def pre_download_recipe(output, reference, remote, **kwargs):
    output.info("reference={}".format(reference.full_str()))
    output.info("remote.name={}".format(remote.name))

def post_download_recipe(output, conanfile_path, reference, remote, **kwargs):
    output.info("conanfile_path={}".format(conanfile_path))
    output.info("reference={}".format(reference.full_str()))
    output.info("remote.name={}".format(remote.name))

def pre_download_package(output, conanfile, conanfile_path, reference, package_id, remote, **kwargs):
    output.info("conanfile.name={}".format(conanfile.name))
    output.info("conanfile_path={}".format(conanfile_path))
    output.info("reference={}".format(reference.full_str()))
    output.info("package_id={}".format(package_id))
    output.info("remote.name={}".format(remote.name))

def post_download_package(output, conanfile, conanfile_path, reference, package_id, remote, **kwargs):
    output.info("conanfile.name={}".format(conanfile.name))
    output.info("conanfile_path={}".format(conanfile_path))
    output.info("reference={}".format(reference.full_str()))
    output.info("package_id={}".format(package_id))
    output.info("remote.name={}".format(remote.name))

def pre_package_info(output, conanfile, reference, **kwargs):
    output.info("reference={}".format(reference.full_str()))
    output.info("conanfile.cpp_info.defines={}".format(conanfile.cpp_info.defines))

def post_package_info(output, conanfile, reference, **kwargs):
    output.info("reference={}".format(reference.full_str()))
    output.info("conanfile.cpp_info.defines={}".format(conanfile.cpp_info.defines))

Functions of the hooks are intended to be self-descriptive regarding to the execution of them. For example, the pre_package() function is called just before the package() method of the recipe is executed.

For download/upload functions, the pre_download()/pre_upload() function is executed first in an conan download/conan upload command. Then pre and post download_recipe()/upload_recipe() and its subsequent pre/post download_package()/upload_package() if that is the case. Finally the general post_download()/post_upload() function is called to wrap up the whole execution.

Important

Pre and post download_recipe()/download_package() are also executed when installing new recipes/packages from remotes using conan create or conan install.

Function parameters

Here you can find the description for each parameter:

  • output: Output object to print formatted messages during execution with the name of the hook and the function executed, e.g., [HOOK - complete_hook] post_download_package(): This is the remote name: default.

  • conanfile: It is a regular ConanFile object loaded from the recipe that received the Conan command. It has its normal attributes and dynamic objects such as build_folder, package_folder

  • conanfile_path: Path to the conanfile.py file whether it is in local cache or in user space.

  • reference: Named tuple with attributes name, version, user, and channel. Its representation will be a reference like: box2d/2.1.0@user/channel

  • package_id: String with the computed package ID.

  • remote: Named tuple with attributes name, url and verify_ssl.

Hook function*

Parameters

conanfile

conanfile_path

reference

package_id

remote

export()

Yes

pre/post

Yes

No

No

source()

Yes

Yes

cache

No

No

build()

Yes

user space

cache

cache

No

package()

Yes

pre/post

cache

Yes

No

upload()
upload_recipe()
upload_package()

No

Yes

Yes

Yes

Yes

download()
download_recipe()

Yes

post

Yes

Yes

Yes

download_package()

Yes

Yes

Yes

Yes

Yes

package_info()

Yes

No

Yes

No

No

*Hook functions are indicated without pre and post prefixes for simplicity.

Table legend:
  • Yes: Availability in pre and post functions in any context.

  • No: Not available.

  • pre / post: Availability in both pre and post functions with different values. e.g. conanfile_path pointing to user space in pre and to local cache in post.

  • post: Only available in post function.

  • cache: Only available when the context of the command executed is the local cache. e.g. conan create, conan install

  • user space: Only available when the context of the command executed is the user space. e.g. conan build

Note

Path to the different folders of the Conan execution flow may be accessible as usual through the conanfile object. See source_folder to learn more.

Some of this parameters does not appear in the signature of the function as they may not be always available (Mostly depending on the recipe living in the local cache or in user space). However, they can be checked with the kwargs parameter.

Important

Hook functions should have a **kwargs parameter to keep compatibility of new parameters that may be introduced in future versions of Conan.