Skip to content
This repository was archived by the owner on Jul 7, 2022. It is now read-only.

Repository files navigation

cmake-utils

A set of utility scripts and functions to ease the setup of complex CMake build pipelines.

Current utilities:

cmake-bootstrap

A CMake function to bootstrap other CMake projects. Allows for complex build pipelines that, for example, require projects to be built pre-configure-time.

Setup

The setup process is identical to the process described for cmake-download, save for the file to include: substitute cmake-bootstrap.cmake for cmake-download.cmake.

Usage

Invoke the bootstrap_build function with the required and any one, or more, of the optional arguments:

ArgumentRequired?Description
BOOTSTRAP_NAMEREQUIREDThe name of the bootstrapped project
BUILD_CMAKE_ROOTREQUIREDThe directory containing the 'CMakeLists.txt' of the bootstrapped project
TARGET_NAMEOPTIONALCommon target name prefix for all bootstrap build targets, defaults to '${BOOTSTRAP_NAME}'
GENERATOROPTIONALThe CMake generator to use for the bootstrapped project, defaults to 'Ninja'
BUILD_COMMANDOPTIONALThe build command to use for the bootstrapped porject, defaults to the generator's build command
ENVIRONMENTOPTIONALA list of environment variables [VAR1=1 VAR2=2 ...] to use for the bootstrapped configure and build tasks
EXTRA_CMAKE_FLAGSOPTIONALA list of CMake flags [FLAG1=1 FLAG2=2 ...] to set when configuring the bootstrapped project
DEPENDSOPTIONALA list of configure dependencies

The function will add two new targets that you can use in your project:

Target NameDescription
${BOOTSTRAP_NAME}_configureThe configure task for the bootstrapped project
${BOOTSTRAP_NAME}_buildThe build task for the bootstrapped project

Example

cmake_minimum_required(VERSION3.8)
include(cmake-utils/cmake-bootstrap.cmake)
bootstrap_build(
BOOTSTRAP_NAME"example"BUILD_CMAKE_ROOT"path/to/example"ENVIRONMENTCC=clangCXX=clang++
)
#Some downstream command that depends on configure artifacts from "example"add_custom_command(
OUTPUTstuffCOMMAND${CMAKE_COMMAND}-Eecho"Configured!"DEPENDSexample_configure
)
#Another downstream command that depends on build artifacts from "example"add_custom_command(
OUTPUTthingsCOMMAND${CMAKE_COMMAND}-Eecho"Built!"DEPENDSexample_build
)
#The target for this project add_custom_target(my_custom_targetALLDEPENDSstuffthings)

cmake-download

A simple CMake function to download a cmake-based project without all the fuss of ExternalProject_Add.

Setup

Submodule

Add this repository as a submodule to you CMake-based repository:

git submodule add git@github.com:Matthewacon/cmake-download.git

then include the download file in your in your top-level CMakeLists.txt:

include(cmake-download/download.cmake)

Single file download

Download the cmake-download.cmake file into the root of your repository:

curl https://raw.githubusercontent.com/Matthewacon/cmake-utils/master/cmake-download.cmake -o cmake-download.cmake -s

then include the file in your top-level CMakeLists.txt:

include(cmake-download.cmake)

Usage

Invoke the find_or_download function with the required and any one, or more, of the optional arguments:

ArgumentRequired?Description
PACKAGE_NAMEREQUIREDThe name of the package to find
VERSIONOPTIONALThe version of the package to find
GIT_REPOREQUIREDThe repository to download if the package is not found
GIT_TAGOPTIONALA branch, tag or commit hash, defaults to 'master'
STATUS_VAROPTIONALThe variable to store the download status on, set to TRUE if downloaded
DEPS_DIROPTIONALDownload destination, defaults to ${CMAKE_SOURCE_DIR}/dependencies
DOWNLOAD_OVERRIDEOPTIONALForce downloading of sources

The function will add one target that you can use in your project:

Target NameDescription
download_${PACKAGE_NAME}The download task

Example

cmake_minimum_required(VERSION3.8)
include(cmake-utils/cmake-download.cmake)
find_or_download(
PACKAGE_NAMEgtestGIT_REPOhttps://github.com/google/googletestGIT_TAGv1.10.0STATUS_VARgtest_downloaded
)
if(${gtest_downloaded})
message(STATUS"Building gtest from source")
include(dependencies/googletest)
#...else()
message(STATUS"Using system gtest installation")
#...endif()

cmake-fetch

cmake-fetch is an alternative to cmake-download, that allows fetching and adding dependencies at configure time within a single build. It has less granularity than cmake-download, but should be suitable for most applications. If your build requires pre-configuration-time building of dependencies, a combination of cmake-download and cmake-bootstrap should suffice.

Setup

The setup process is identical to the process described for cmake-download, save for the file to include: substitute cmake-fetch.cmake for cmake-download.cmake.

Usage

cmake-fetch provides two functions for declaring latent dependencies and fetching them later on:

add_latent_dependency:

The add_latent_dependency function accepts all of the same arguments as the FetchContent_Declare function, as well as a few named arguments that are specific to itself, and are removed from the argument list when invoking FetchContent_Declare:

ArgumentRequired?Description
SCOPE_IDOPTIONALA unique prefix for the parent-scope latent dependency list
NAMEREQUIREDThe designated name of the dependency; added to parent-scope list of dependencies
TARGET_NAMESOPTIONALA list of targets defined by the dependency; added to parent-scope list of link targets
SHALLOWOPTIONALWhether or not the dependency should be shallow cloned; defaults to 'FALSE'

The function will invoke FetchContent_Declare, forwarding any arguments that are not specific to add_latent_dependency, and define two variables in the parent scope:

VARIABLEDESCRIPTION
${SCOPE_ID}_latent_dependenciesA list of dependency names; used internally when invoking fetch_latent_dependencies
${SCOPE_ID}_latent_targetsA list of targets to link against later in the build lifecycle (see TARGETS_VAR)

Note: If the SCOPE_ID named variable is not specified, it defaults to adl.

fetch_latent_dependencies:

The fetch_latent_dependencies function does exactly as it says; when invoked it will populate all of the projects defined in the list ${SCOPE_ID}_latent_dependencies and add include them in the build.

ArgumentRequired?Description
SCOPE_IDOPTIONALA unique prefix for the parent-scope latent dependency list
TARGETS_VAROPTIONALThe name of the result var for the parent-scope list of latent dependency targets
NO_FAILOPTIONALFlag to silence error when invoking fetch_latent_dependencies without having declared any dependencies

Example

Simple configuration:

cmake_minimum_required(VERSION3.19)
project(cmake-fetch-example VERSION 0.0.1)
include(cmake-utils/cmake-fetch.cmake)
#Add googletest as a dependencyadd_latent_dependency(
NAMEgtestGIT_REPOSITORYhttps://github.com/google/googletest.gitGIT_TAGrelease-1.10.0TARGET_NAMESgtest
)
#Add google benchmark as a dependencyadd_latent_dependency(
NAMEgbenchmarkGIT_REPOSITORYhttps://github.com/google/benchmark.gitGIT_TAGv1.5.2TARGET_NAMESbenchmark::benchmark
)
#Configure executableadd_executable(example_binaryexample.cpp)
#Fetch all declared dependencies and get list of link targetsfetch_latent_dependencies(TARGETS_VARto_link_against)
target_include_directories(
example_binaryPRIVATE${gtest_SOURCE_DIR}/include#gtest headers${gbenchmark_SOURCE_DIR}/include#gbenchmark headers
)
target_link_libraries(example_binary${to_link_against})

Configuration with multiple dependency scopes:

cmake_minimum_required(VERSION3.19)
project(multiscope-cmake-fetch-example VERSION 0.0.1)
#Add fmt as a main dependencyadd_latent_dependency(
NAMEfmtSCOPE_IDmainGIT_REPOSITORYhttps://github.com/fmtlib/fmt.gitGIT_TAG7.1.3
)
#Add gtest as a test dependencyadd_latent_dependency(
NAMEgtestSCOPE_IDtestGIT_REPOSITORYhttps://github.com/google/googletest.gitGIT_TAGrelease-1.10.0TARGET_NAMESgtest
)
#Add google benchmark as test dependencyadd_latent_dependency(
NAMEgbenchmarkSCOPE_IDtestGIT_REPOSITORYhttps://github.com/google/benchmark.gitGIT_TAGv1.5.2TARGET_NAMESbenchmark::benchmark
)
#Configure test executableadd_executable(example_testtest.cpp)
#Fetch test dependenciesfetch_latent_dependencies(
SCOPE_IDtestTARGETS_VARtest_libraries
)
target_include_directories(
example_test${gtest_SOURCE_DIR}/include${gbenchmark_SOURCE_DIR}/include
)
target_link_libraries(example_test${test_libraries})
#Configure main executableadd_executable(mainmain.cpp)
#Fetch main dependenciesfetch_latent_dependencies(
SCOPE_IDmainTARGETS_VARmain_libraries )
target_include_directories(mainPRIVATE${fmt_SOURCE_DIR}/include)
target_link_libraries(main${main_libraries})

License

M.I.T.

About

A set of utility scripts and functions to ease the setup of complex CMake build pipelines.

Topics

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages