This is a set of CMake scripts aimed at easing the development of CMake based projects. The main goal is ease of use both for the developer and for the end user.
They provide:
- Dependency management
- Dependencies are installed through CMake, making their insallation portable
- Support for dependency graphs (each dependency can itself have other dependencies)
- Bundling of dependencies in the installation package
- Installation scripts for a set of dependency packages is already provided, but other dependencies can be added without having to modify this project
- Proper installation, complete with CMake modules needed to use this project in other projects
Include this project somewhere in your source tree. If you are using git you can add this repository as a git submodule.
First you need to include SetUpProject.cmake
. Assuming the contents of this repository are availabe at ${CMAKE_CURRENT_SOURCE_DIR}/cmake
:
cmake_minimum_required(VERSION 3.0)
set(PROJECT_NAME YourProjectName)
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/SetUpProject.cmake)
You can then add dependencies by calling:
add_project_dependency(<dependency_name>
[COMPONENTS <component_name> [component_name [...]]]
[OPTIONAL_COMPONENTS <component_name> [component_name [...]]]
)
The first argument of this function should be the dependency name (capitalization is important and should be the same used in Find<package_name>.cmake module). For example:
add_project_dependency(EIGEN3)
add_project_dependency(Boost COMPONENTS regex filesystem)
Once you have added all the dependencies you need to install them and/or find them.
install_project_dependencies()
find_project_dependencies()
Note that dependencies are installed only if DEPENDENCY_INSTALL_<dependency_name>
is set to ON (which it is by default).
find_project_dependencies()
defines the following variables:
${PROJECT_NAME}_DEPENDENCIES_INCLUDE_DIRS
, ${PROJECT_NAME}_DEPENDENCIES_LIBRARY_DIRS
and ${PROJECT_NAME}_DEPENDENCIES_LIBRARIES
You don't then need to make explicit use of these variables (i.e. include_directories
and link_directories
is already called)
After providing instructions to compile your project, you can use the following script to properly install it
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/InstallProject.cmake)
When configuring a project that uses CUPID, you can set the following (optional) CMake variables to manage dependencies:
DEPENDENCIES_ENABLE_INSTALLATION
:BOOL
if set to OFF dependencies are not installedDEPENDENCIES_INSTALL_<dependency_name>
:BOOL
if set to OFF the given dependency won't be installed. It must be already installed. CMake will try to find it in the default system paths, but its location can optionally be set via theDEPENDENCIES_<dependency_name>_DIR
variableDEPENDENCIES_<dependency_name>_DIR
:PATH
where the given dependency can be found if its installation is disabled (either by settingDEPENDENCIES_INSTALL_<dependency_name>
to OFF or by disabling all installations byDEPENDENCIES_ENABLE_INSTALLATION
ot OFF)DEPENDENCIES_ARCHIVE_DIR
:PATH
where dependencies source archives can be found. Each dependency should have a subdirectory with the same name containing its archive. If the archives are found here they won't be downloaded again. Defaults to${CUPID_DIR}/dependencies/src
DEPENDENCIES_INSTALL_DIR
:PATH
where dependencies will be installed. Defaults to${CMAKE_BINARY_DIR}/dependencies
These variables can be set either when invoking cmake via the command line (e.g.: cmake -D DEPENDENCIES_INSTALL_DIR=/where/you/want/them/installed path/to/source/dir
) or by using its GUI.
In order to add support for a custom dependency, you should provide 3 files: Add<dependency_name>Dependencies.cmake
, Install<dependency_name>.cmake
and Bundle<dependency_name>.cmake
.
Additionally, if this dependency does not provide its own '<dependency_name>Config.cmake' file and it is not supported by any of the cmake 'Find<dependency_name>.cmake' modules, you should provide a 'Find<dependency_name>.cmake' script.
You can specify where these files are located by adding directories to the cache variable DEPENDENCIES_INSTALL_SCRIPTS_DIRS
. e.g.:
set(DEPENDENCIES_INSTALL_SCRIPTS_DIRS "${CMAKE_SOURCE_DIR}/dependency_install_scripts" CACHE INTERNAL "")
This file should simply add other dependency needed by this dependency by calling add_project_dependency()
, as shown above.
If there are no other dependencies, this file is not needed.
This script should actually install the dependency, most likely by using ExternalProject_Add()
.
The installation can rely on the following variables (and assume they are already properly set):
DEPENDENCY_ARCHIVE_DIR
: directory where the source package should be downloaded. This defaults to a subdirectory of this scripts:dependencies/src
DEPENDENCY_BASE_DIR
: directory used for the build. IfExternalProject_Add
is used, thePREFIX
argument should be set to this value. Defaults to${CMAKE_BINARY_DIR}/dependencies/<dependency_name>
.DEPENDENCY_INSTALL_DIR
: directory where the project should be installed. This defaults to${DEPENDENCY_BASE_DIR}/install
This script should install any file that needs to be bundled with the project (e.g. dynamic libraries). If nothing needs to be bundled, this file is not needed.
This script is only needed if the dependency does not provide its own '<dependency_name>Config.cmake' file and it is not supported by any of the cmake 'Find<dependency_name>.cmake' modules.
This script should rely on ${DEPENDENCIES_${DEPENDENCY_NAME}_DIR}
and can assume that ${CMAKE_PREFIX_PATH}
has already been set to that path.
It can also rely on the variables DEPENDENCY_COMPONENTS
and DEPENDENCY_OPTIONAL_COMPONENTS
to know thich components it has to find.
If the package is found, it should set the variable ${DEPENDENCY_NAME}_FOUND
to ON
and should set ${DEPENDENCY_NAME}_INCLUDE_DIRS
, ${DEPENDENCY_NAME}_LIBRARY_DIRS
and ${DEPENDENCY_NAME}_LIBRARIES
appropriately.