Copy sources from all your dependencies¶
Please, first clone the sources to recreate this project. You can find them in the examples2 repository in GitHub:
$ 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 Deployers reference.
Locate the deployer¶
In this case, the deployer is located in the same directory as our example conanfile, but as shown in 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/deployers
folderBuilt-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:
$ conan graph info . -c tools.build:download_source=True --deployer=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.
Note that you can pass the --deployer-folder
argument to change the base folder output path for the deployer.
Code tour¶
The source_deploy.py file has the following code:
from conan.tools.files import copy
import os
def deploy(graph, output_folder, **kwargs):
# Note the kwargs argument is mandatory to be robust against future changes.
for name, dep in graph.root.conanfile.dependencies.items():
if dep.folders is None or dep.folders.source_folder is None:
raise ConanException(f"Sources missing for {name} dependency.\n"
"This deployer needs the sources of every dependency present to work, either building from source, "
"or by using the 'tools.build:download_source' conf.")
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 conan.tools.copy.
Note
If you’re using this deployer as an example for your own, remember that
tools.build:download_source=True
is necessary so that dep.folders.source_folder
is defined for the dependencies.
Without the conf, said variable will not be defined for those dependencies that do not need to be built from sources
nor in those commands that do not require building, such as conan graph.
Note
If your custom deployer needs access to the full dependency graph, including those libraries that might be skipped,
use the tools.graph:skip_binaries=False
conf. This is useful for collecting, for example, all the licenses in your graph.