Create custom targets to build projects in external trees


The ExternalProject_Add function creates a custom target to drive download, update/patch, configure, build, install and test steps of an external project:

ExternalProject_Add(<name> [<option>...])

General options are:

DEPENDS <projects>...
Targets on which the project depends
PREFIX <dir>
Root dir for entire project
Sep to be replaced by ; in cmd lines
TMP_DIR <dir>
Directory to store temporary files
Directory to store step timestamps
The “all” target does not depend on this

Download step options are:

File name to store (if not end of URL)
Directory to store downloaded files
Command to download source tree
Disable download progress reports
CVSROOT of CVS repository
Module to checkout from CVS repo
CVS_TAG <tag>
Tag to checkout from CVS repo
URL of Subversion repo
Revision to checkout from Subversion repo
SVN_USERNAME <username>
Username for Subversion checkout and update
SVN_PASSWORD <password>
Password for Subversion checkout and update
Trust the Subversion server site certificate
URL of git repo
GIT_TAG <tag>
Git branch name, commit id or tag
GIT_SUBMODULES <module>...
Git submodules that shall be updated, all if empty
URL of mercurial repo
HG_TAG <tag>
Mercurial branch name, commit id or tag
URL /.../src.tgz
Full path or URL of source
Hash of file at URL
URL_MD5 md5
Equivalent to URL_HASH MD5=md5
Should certificate for https be checked
Path to a certificate authority file
TIMEOUT <seconds>
Time allowed for file download operations

Update/Patch step options are:

Source work-tree update command
Never update automatically from the remote repository
Command to patch downloaded source

Configure step options are:

Source dir to be used for build
Build tree configuration command
CMAKE_COMMAND /.../cmake
Specify alternative cmake executable
Specify generator for native build
Generator-specific platform name
Generator-specific toolset name
CMAKE_ARGS <arg>...
Arguments to CMake command line. These arguments are passed to CMake command line, and can contain arguments other than cache values, see also CMake Options. Arguments in the form -Dvar:string=on are always passed to the command line, and therefore cannot be changed by the user.
Initial cache arguments, of the form -Dvar:string=on. These arguments are written in a pre-load a script that populates CMake cache, see also cmake -C. This allows to overcome command line length limits. These arguments are set() using the FORCE argument, and therefore cannot be changed by the user.
Initial default cache arguments, of the form -Dvar:string=on. These arguments are written in a pre-load a script that populates CMake cache, see also cmake -C. This allows to overcome command line length limits. These arguments can be used as default value that will be set if no previous value is found in the cache, and that the user can change later.

Build step options are:

Specify build dir location
Command to drive the native build
Use source dir for build dir
No stamp file, build step always runs
Files that will be generated by the build command but may or may not have their modification time updated by subsequent builds.

Install step options are:

Installation prefix
Command to drive install after build

Test step options are:

Add test step executed before install step
Add test step executed after install step
Main target does not depend on the test step
Command to drive test

Output logging options are:

Wrap download in script to log output
Wrap update in script to log output
Wrap configure in script to log output
Wrap build in script to log output
Wrap test in script to log output
Wrap install in script to log output

Other options are:

STEP_TARGETS <step-target>...
Generate custom targets for these steps
Generate custom targets for these steps that do not depend on other external projects even if a dependency is set

The *_DIR options specify directories for the project, with default directories computed as follows. If the PREFIX option is given to ExternalProject_Add() or the EP_PREFIX directory property is set, then an external project is built and installed under the specified prefix:

TMP_DIR      = <prefix>/tmp
STAMP_DIR    = <prefix>/src/<name>-stamp
DOWNLOAD_DIR = <prefix>/src
SOURCE_DIR   = <prefix>/src/<name>
BINARY_DIR   = <prefix>/src/<name>-build
INSTALL_DIR  = <prefix>

Otherwise, if the EP_BASE directory property is set then components of an external project are stored under the specified base:

TMP_DIR      = <base>/tmp/<name>
STAMP_DIR    = <base>/Stamp/<name>
DOWNLOAD_DIR = <base>/Download/<name>
SOURCE_DIR   = <base>/Source/<name>
BINARY_DIR   = <base>/Build/<name>
INSTALL_DIR  = <base>/Install/<name>

If no PREFIX, EP_PREFIX, or EP_BASE is specified then the default is to set PREFIX to <name>-prefix. Relative paths are interpreted with respect to the build directory corresponding to the source directory in which ExternalProject_Add is invoked.

If SOURCE_DIR is explicitly set to an existing directory the project will be built from it. Otherwise a download step must be specified using one of the DOWNLOAD_COMMAND, CVS_*, SVN_*, or URL options. The URL option may refer locally to a directory or source tarball, or refer to a remote tarball (e.g. http://.../src.tgz).

If UPDATE_DISCONNECTED is set, the update step is not executed automatically when building the main target. The update step can still be added as a step target and called manually. This is useful if you want to allow to build the project when you are disconnected from the network (you might still need the network for the download step). This is disabled by default. The directory property EP_UPDATE_DISCONNECTED can be used to change the default value for all the external projects in the current directory and its subdirectories.


The ExternalProject_Add_Step function adds a custom step to an external project:

ExternalProject_Add_Step(<name> <step> [<option>...])

Options are:

COMMAND <cmd>...
Command line invoked by this step
COMMENT "<text>..."
Text printed when step executes
DEPENDEES <step>...
Steps on which this step depends
DEPENDERS <step>...
Steps that depend on this step
DEPENDS <file>...
Files on which this step depends
BYPRODUCTS <file>...
Files that will be generated by this step but may or may not have their modification time updated by subsequent builds.
No stamp file, step always runs
Main target does not depend on this step
Working directory for command
Wrap step in script to log output

The command line, comment, and working directory of every standard and custom step is processed to replace tokens <SOURCE_DIR>, <BINARY_DIR>, <INSTALL_DIR>, and <TMP_DIR> with corresponding property values.

Any builtin step that specifies a <step>_COMMAND cmd... or custom step that specifies a COMMAND cmd... may specify additional command lines using the form COMMAND cmd.... At build time the commands will be executed in order and aborted if any one fails. For example:

... BUILD_COMMAND make COMMAND echo done ...

specifies to run make and then echo done during the build step. Whether the current working directory is preserved between commands is not defined. Behavior of shell operators like && is not defined.


The ExternalProject_Get_Property function retrieves external project target properties:

ExternalProject_Get_Property(<name> [prop1 [prop2 [...]]])

It stores property values in variables of the same name. Property names correspond to the keyword argument names of ExternalProject_Add.


The ExternalProject_Add_StepTargets function generates custom targets for the steps listed:

ExternalProject_Add_StepTargets(<name> [NO_DEPENDS] [step1 [step2 [...]]])

If NO_DEPENDS is set, the target will not depend on the dependencies of the complete project. This is usually safe to use for the download, update, and patch steps that do not require that all the dependencies are updated and built. Using NO_DEPENDS for other of the default steps might break parallel builds, so you should avoid, it. For custom steps, you should consider whether or not the custom commands requires that the dependencies are configured, built and installed.

If STEP_TARGETS or INDEPENDENT_STEP_TARGETS is set then ExternalProject_Add_StepTargets is automatically called at the end of matching calls to ExternalProject_Add_Step. Pass STEP_TARGETS or INDEPENDENT_STEP_TARGETS explicitly to individual ExternalProject_Add calls, or implicitly to all ExternalProject_Add calls by setting the directory properties EP_STEP_TARGETS and EP_INDEPENDENT_STEP_TARGETS. The INDEPENDENT version of the argument and of the property will call ExternalProject_Add_StepTargets with the NO_DEPENDS argument.

If STEP_TARGETS and INDEPENDENT_STEP_TARGETS are not set, clients may still manually call ExternalProject_Add_StepTargets after calling ExternalProject_Add or ExternalProject_Add_Step.

This functionality is provided to make it easy to drive the steps independently of each other by specifying targets on build command lines. For example, you may be submitting to a sub-project based dashboard, where you want to drive the configure portion of the build, then submit to the dashboard, followed by the build portion, followed by tests. If you invoke a custom target that depends on a step halfway through the step dependency chain, then all the previous steps will also run to ensure everything is up to date.

For example, to drive configure, build and test steps independently for each ExternalProject_Add call in your project, write the following line prior to any ExternalProject_Add calls in your CMakeLists.txt file:

set_property(DIRECTORY PROPERTY EP_STEP_TARGETS configure build test)

The ExternalProject_Add_StepDependencies function add some dependencies for some external project step:

ExternalProject_Add_StepDependencies(<name> <step> [target1 [target2 [...]]])

This function takes care to set both target and file level dependencies, and will ensure that parallel builds will not break. It should be used instead of add_dependencies() when adding a dependency for some of the step targets generated by ExternalProject.