The ExternalProject_Add command can be used to add sources from third parties. Our first example, however, shows how to manage our own project as an assembly of different CMake projects. In this example, both the root and the leaf CMakeLists.txt declared a CMake project, that is, both of them used the project command.
ExternalProject_Add has many options that can be used to fine-tune all aspects of the configuration and compilation of external projects. These options can be classified into the following:
- Directory options: These are used to tune the structure of the source and build directories for the external project. In our case, we used the SOURCE_DIR option to let CMake know that the sources are available in the ${CMAKE_CURRENT_LIST_DIR}/src folder and thus should not be fetched from somewhere else. The directories for building the project and storing temporary files can also be specified in this class of options or as directory properties. We have followed the latter route by setting the EP_BASE directory property. CMake will set up all directories for the various subprojects with the following layout:
TMP_DIR = <EP_BASE>/tmp/<name> STAMP_DIR = <EP_BASE>/Stamp/<name> DOWNLOAD_DIR = <EP_BASE>/Download/<name> SOURCE_DIR = <EP_BASE>/Source/<name> BINARY_DIR = <EP_BASE>/Build/<name> INSTALL_DIR = <EP_BASE>/Install/<name>
- Download options: The code for the external project might have to be downloaded from an online repository or resource. Options in this class let you control all aspects of this step.
- Update and Patch options: This class of options can be used to define how to update the sources for the external project or how to apply patches.
- Configure options: By default, CMake assumes that the external project is itself configured using CMake. As the following recipes will show, we are however not limited to this case. If the external project is a CMake project, ExternalProject_Add will call the CMake executable and pass options to it. For our current example, we passed configuration arguments via the CMAKE_ARGS and CMAKE_CACHE_ARGS options. The former are passed directly as a command line argument, whereas the latter are passed via a CMake script file. In our example, the script file is in build/subprojects/tmp/recipe-01_core/recipe-01_core-cache-.cmake. The configuration would then look like this example:
$ cmake -DCMAKE_CXX_COMPILER=g++ -DCMAKE_CXX_STANDARD=11
-DCMAKE_CXX_EXTENSIONS=OFF -DCMAKE_CXX_STANDARD_REQUIRED=ON
-C/home/roberto/Workspace/robertodr/cmake-cookbook/chapter-08/recipe-01/cxx-example/build/subprojects/tmp/recipe-01_core/recipe-01_core-cache-.cmake "-GUnix Makefiles" /home/roberto/Workspace/robertodr/cmake-cookbook/chapter-08/recipe-01/cxx-example/src
- Build options: This class of options can be used to tweak the actual compilation of the external project. Our example used the BUILD_ALWAYS option to ensure that the external project is always freshly built.
- Install options: These are options to configure how the external project should be installed. Our example left INSTALL_COMMAND empty and we will discuss installation with CMake in more detail in Chapter 10, Writing an Installer.
- Test options: It is always a good idea to run tests for any piece of software that is built from sources. This class of options to ExternalProject_Add is here for this purpose. Our example did not use these options, as the "Hello, World" example didn't have any tests, but in Recipe 5, Managing your project as a superbuild, we will trigger a test step.
ExternalProject.cmake defines the command ExternalProject_Get_Property which, as the name suggests, is useful to retrieve properties of external projects. The properties on external projects are set when first invoking the ExternalProject_Add command. For example, retrieving the arguments to be passed to CMake when configuring recipe-01_core can be achieved with:
ExternalProject_Get_Property(${PROJECT_NAME}_core CMAKE_ARGS)
message(STATUS "CMAKE_ARGS of ${PROJECT_NAME}_core ${CMAKE_ARGS}")