This recipe shows how the superbuild pattern can be harnessed to muster the dependencies of your project. Let us take another look at the layout of the project:
.
├── CMakeLists.txt
├── external
│ └── upstream
│ ├── boost
│ │ └── CMakeLists.txt
│ └── CMakeLists.txt
└── src
├── CMakeLists.txt
└── path-info.cpp
We have introduced four CMakeLists.txt files in the project source tree:
- The root CMakeLists.txt will coordinate the superbuild.
- The file in external/upstream will lead us to the boost leaf directory.
- external/upstream/boost/CMakeLists.txt will take care of the Boost dependency.
- Finally, the CMakeLists.txt under src will build our example code, which depends on Boost.
Let us start start the discussion with the external/upstream/boost/CMakeLists.txt file. Boost uses its own build system and hence we need to be slightly more verbose in our ExternalProject_Add to get everything set up correctly:
- We keep the default values for the Directory options.
- The Download step will download an archive of the desired version of Boost from their online server. We therefore set up the URL and the URL_HASH. The latter is needed to check the integrity of the downloaded archive. Since we do not wish to see a progress report of the download, we also set the DOWNLOAD_NO_PROGRESS option to true.
- The Update step is left blank. If anything needs rebuilding, we do not want to download Boost once again.
- The Configure step will use the native configuration tool provided by Boost in CONFIGURE_COMMAND. Since we want the superbuild to be cross-platform, we use the <SOURCE_DIR> variable to refer to the location for the unpacked sources:
CONFIGURE_COMMAND
<SOURCE_DIR>/bootstrap.sh
--with-toolset=${_toolset}
--prefix=${STAGED_INSTALL_PREFIX}/boost
${_bootstrap_select_libraries}
- The Build options declare an in-source build, by setting the BUILD_IN_SOURCE option to true. BUILD_COMMAND uses the Boost native build tool, b2. Since we will be doing an in-source build, we use again the <SOURCE_DIR> variable to refer to the location of the unpacked sources.
- We then move on to the Install options. Boost manages installation using the same native build tool. In fact, the build and installation commands could easily be collapsed into one.
- The Output logging options LOG_BUILD and LOG_INSTALL direct ExternalProject_Add to write log files for the build and installation operations, instead of outputting to screen.
- Finally, the BUILD_BYPRODUCTS option lets ExternalProject_Add keep track of the freshly built Boost libraries in subsequent builds, even though their modification times might not get updated.
Once Boost has been built, the ${STAGED_INSTALL_PREFIX}/boost folder in the build directory will contain our desired libraries. We need to pass this information down to our project, whose build system is generated in src/CMakeLists.txt. To achieve this goal, we pass two additional CMAKE_CACHE_ARGS in the ExternalProject_Add in the root CMakeLists.txt:
- CMAKE_INCLUDE_PATH: The path where CMake will look for C/C++ headers
- CMAKE_LIBRARY_PATH: The path where CMake will look for libraries
By setting these variables to our freshly built installation of Boost, we ensure that the dependency will be properly picked up.