Let us first look at CMakeLists.txt in the root folder:
- We declare a C++11 project, with a minimum required CMake version:
cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
project(recipe-01 LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
- We set the EP_BASE directory property for the current and any underlying directories. This will be discussed shortly:
set_property(DIRECTORY PROPERTY EP_BASE ${CMAKE_BINARY_DIR}/subprojects)
- We include the ExternalProject.cmake standard module. This module provides the ExternalProject_Add function:
include(ExternalProject)
- The source code for our "Hello, World" example is added as an external project by invoking the ExternalProject_Add function. The name of the external project is recipe-01_core:
ExternalProject_Add(${PROJECT_NAME}_core
- We set the source directory for the external project using the SOURCE_DIR option:
SOURCE_DIR
${CMAKE_CURRENT_LIST_DIR}/src
- The src subdirectory contains a full-fledged CMake project. To configure and build it, we pass the appropriate CMake options to the external project via the CMAKE_ARGS option. In our case, we only need to pass the C++ compiler and the requirements for the C++ standard:
CMAKE_ARGS
-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}
-DCMAKE_CXX_STANDARD=${CMAKE_CXX_STANDARD}
-DCMAKE_CXX_EXTENSIONS=${CMAKE_CXX_EXTENSIONS}
-DCMAKE_CXX_STANDARD_REQUIRED=${CMAKE_CXX_STANDARD_REQUIRED}
- We also set the C++ compiler flags. These are passed using the CMAKE_CACHE_ARGS option to the ExternalProject_Add command:
CMAKE_CACHE_ARGS
-DCMAKE_CXX_FLAGS:STRING=${CMAKE_CXX_FLAGS}
- We configure the external project so that it is always built:
BUILD_ALWAYS
1
- The install step will not execute any actions (we will revisit installation in Recipe 4, Installing a superbuild, in Chapter 10, Writing an Installer):
INSTALL_COMMAND
""
)
Let us now move on to src/CMakeLists.txt. Since we are adding our "Hello, World" sources as an external project, this is a full-fledged CMakeLists.txt file for a standalone project:
- Also, here we declare a minimum required CMake version:
cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
- We declare a C++ project:
project(recipe-01_core LANGUAGES CXX)
- Finally, we add an executable target, hello-world, from the hello-world.cpp source file:
add_executable(hello-world hello-world.cpp)
Configuring and building our project is done as usual:
$ mkdir -p build
$ cmake ..
$ cmake --build .
The structure of the build directory is now slightly more complex. In particular, we notice the subprojects folder with the following contents:
build/subprojects/
├── Build
│ └── recipe-01_core
│ ├── CMakeCache.txt
│ ├── CMakeFiles
│ ├── cmake_install.cmake
│ ├── hello-world
│ └── Makefile
├── Download
│ └── recipe-01_core
├── Install
│ └── recipe-01_core
├── Stamp
│ └── recipe-01_core
│ ├── recipe-01_core-configure
│ ├── recipe-01_core-done
│ ├── recipe-01_core-download
│ ├── recipe-01_core-install
│ ├── recipe-01_core-mkdir
│ ├── recipe-01_core-patch
│ └── recipe-01_core-update
└── tmp
└── recipe-01_core
├── recipe-01_core-cache-.cmake
├── recipe-01_core-cfgcmd.txt
└── recipe-01_core-cfgcmd.txt.in
recipe-01_core has been built into a subdirectory of build/subprojects, called Build/recipe-01_core, which is the EP_BASE we have set.
The hello-world executable has been created under Build/recipe-01_core. The additional subfolders tmp/recipe-01_core and Stamp/recipe-01_core contain temporary files, such as the CMake cache script recipe-01_core-cache-.cmake, and the stamp files for the various steps CMake has performed to build the external project.