diff --git a/examples.rst b/examples.rst index 8f9d7ec6d0d8..76a2124b8ac1 100644 --- a/examples.rst +++ b/examples.rst @@ -9,6 +9,7 @@ Examples examples/conanfile/conanfile examples/extensions/commands/custom_commands + examples/extensions/deployers/custom_deployers examples/tools/cmake/cmake examples/tools/files/files examples/tools/meson/meson diff --git a/examples/extensions/deployers/custom_deployers.rst b/examples/extensions/deployers/custom_deployers.rst new file mode 100644 index 000000000000..1e3a1ccb37b5 --- /dev/null +++ b/examples/extensions/deployers/custom_deployers.rst @@ -0,0 +1,14 @@ +.. _examples_extensions_deployers: + + + + +Custom deployers +================ + + +.. toctree:: + :maxdepth: 2 + + + sources/custom_deployer_sources diff --git a/examples/extensions/deployers/sources/custom_deployer_sources.rst b/examples/extensions/deployers/sources/custom_deployer_sources.rst new file mode 100644 index 000000000000..ebc5defa2b75 --- /dev/null +++ b/examples/extensions/deployers/sources/custom_deployer_sources.rst @@ -0,0 +1,80 @@ +.. examples_extensions_deployers_sources: + +Copy sources from all your dependencies +======================================= + + + +Please, first of all, clone the sources to recreate this project. You can find them in the +`examples2.0 repository `_ in GitHub: + +.. code-block:: bash + + $ git clone https://github.com/conan-io/examples2.git + $ cd examples2/examples/extensions/deployers/sources + + +In this example we are going to see how to create and use a custom deployer. +This deployer copies all the source files from your dependencies and puts them into a specific output folder + +.. note:: + + To better understand this example, it is highly recommended to have previously read the :ref:`Deployers ` reference. + + +Locate the deployer +------------------- + +In this case, the deployer is located in the same directory as our example conanfile, +but as shown in :ref:`Deployers ` reference, +Conan will look for the specified deployer in a few extra places in order, namely: + +#. Absolute paths +#. Relative to cwd +#. In the ``[CONAN_HOME]/extensions/deploy`` folder +#. Built-in deployers + + +Run it +------ + +For our example, we have a simple recipe that lists both ``zlib`` and ``mcap`` as requirements. +With the help of the ``tools.build:download_source=True`` conf, we can force the invocation of its ``source()`` method, +which will ensure that sources are available even if no build needs to be carried out. + +Now, you should be able to use the new deployer in both ``conan install`` and ``conan graph`` commands for any given recipe: + +.. code-block:: bash + + $ conan graph info . -c tools.build:download_source=True --deploy=sources_deploy + + +Inspecting the command output we can see that it copied the sources of our direct dependencies ``zlib`` and ``mcap``, +**plus** the sources of our transitive dependencies, ``zstd``and ``lz4`` to a ``dependencies_sources`` folder. +After this is done, extra preprocessing could be done to accomplish more specific needs. + +Code tour +--------- + +The **source_deploy.py** file has the following code: + + + +.. code-block:: python + :caption: **sources_deploy.py** + + from conan.tools.files import copy + import os + + + def deploy(graph, output_folder): + for name, dep in graph.root.conanfile.dependencies.items(): + copy(graph.root.conanfile, "*", dep.folders.source_folder, os.path.join(output_folder, "dependency_sources", str(dep))) + + +deploy() +++++++++ + +The ``deploy()`` method is called by Conan, and gets both a dependency graph and an output folder path as arguments. +It iterates all the dependencies of our recipe and copies every source file to their respective folders +under ``dependencies_sources`` using :ref:`conan.tools.copy`. diff --git a/reference/extensions/deployers.rst b/reference/extensions/deployers.rst index db0cee572b0a..bba1e298df83 100644 --- a/reference/extensions/deployers.rst +++ b/reference/extensions/deployers.rst @@ -1,5 +1,76 @@ .. _reference_extensions_deployers: Deployers ---------- +========= +Deployers are a mechanism to facilitate copying files form one folder, usually the Conan cache, to user folders. +While Conan provides two built-in ones (``full_deploy`` and ``direct_deploy``), users can easily manage their own +with ``conan config install``. + +Deployers run before generators, and they can change the target folders. +For example, if the ``--deploy=full_deploy`` deployer runs before ``CMakeDeps``, +the files generated by ``CMakeDeps`` will point to the local copy in the user folder done by the ``full_deploy`` deployer, +and not to the Conan cache. Multiple deployers can be specified by supplying more than one ``--deploy=`` argument, +and they will be ran in order of appearance. + +Deployers can be multi-configuration. Running ``conan install . --deploy=full_deploy`` repeatedly for different profiles +can achieve a fully self-contained project, including all the artifacts, binaries, and build files. +This project will be completely independent of Conan and no longer require it at all to build. + + +Built-in deployers +------------------ + +.. _reference_extensions_deployer_full_deploy: + +full_deploy +^^^^^^^^^^^ + +Deploys each package folder of every dependency to your recipe's ``output_folder`` in a subfolder tree based on: + +#. The build context +#. The dependency name and version +#. The build type +#. The build arch + +Then every dependency will end up in a folder such as: + +``[OUTPUT_FOLDER]/host/dep/0.1/Release/x86_64`` + + +.. _reference_extensions_deployer_direct_deploy: + +direct_deploy +^^^^^^^^^^^^^ + +Same as ``full_deploy``, but only processes your recipe's *direct* dependencies. + + +Custom deployers +---------------- + +Custom deployers can be managed via ``conan config install``. When looking for a specific deployer, +Conan will look in these locations for the deployer in the following order: + +#. Absolute paths +#. Relative to cwd +#. In the ``[CONAN_HOME]/extensions/deploy`` folder +#. As built-in deployers + +Conan will look for a ``deploy()`` method to call for each installed file. +The function signature of your custom deployers should be as follows: + + +.. code-block:: python + :caption: **my_custom_deployer.py** + + def deploy(graph, output_folder: str): + +(Note that the arguments are passed as named parameters, so both the ``graph`` and ``output_folder`` names are mandatory) + +You can access your conanfile object with ``graph.root.conanfile``. +See :ref:`ConanFile.dependencies` for information on how to iterate over its dependencies. +Your custom deployer can now be invoked as if it were a built-in deployer using the filename in which it's found, +in this case ``conan install . --deploy=my_custom_deployer``. Note that supplying the **.py** extension is optional. + +See the :ref:`custom deployers` section for examples on how to implement your own deployers.