Using CMake#
Note
This documentation is the same documentation that would be generated for your project when using
new_cxx_project. The terms ${project_name} and ${PROJECT_NAME} will be replaced
with your project’s designated name.
${project_name} has a robust set of configuration options and a library that allows for faster C++ development. This page documents how everything fits together.
Config options#
Default config options#
new_cxx_project.py provides the following config options for all C++ projects.
Project-specific config options#
Project-specific config options should be added to config/cmake/install_options.cmake, and
documented here.
Packages#
Project-specific package dependencies should be added to config/cmake/import_packages.cmake, and
documented here.
Toolchain files#
${project_name} has two toolchain files to config/cmake/toolchain. Both toolchains enable a
variety of warnings, security mechanisms, and optimisations (release-only).
LLVM toolchain
- Path:
config/cmake/toolchain/x86_64-unknown-linux-gnu-clang-with-llvm-toolchain.cmake- Compiler:
Clang
- Linker:
lld
- Standard library:
libc++
- Compiler runtime:
compiler-rt
- Unwind library:
libunwind
GNU toolchain
- Path:
config/cmake/toolchain/x86_64-unknown-linux-gnu-gcc.cmake- Compiler:
GCC
- Linker:
gold
- Standard library:
libstdc++
- Compiler runtime:
libgcc
- Unwind library:
libgcc_eh
Creating binaries#
To ensure that simple binaries are built with as few CMake errors as possible, this project provides
a set of rules that can build executables, libraries, and tests. The primary advantage of using these
rules over the default CMake rules is that they handle some desirable defaults for everything, and
also bundle all of your rules into a single rule (as opposed to needing to repeat yourself, a la
add_executable(target sources...), add_compile_options(target options...),
add_compile_definitions(target definitions...), etc., which can be error-prone).
All rules must be provided with a TARGET (the name of the binary to be built), and at
least one source file needs to be listed using either the SOURCES named parameter,
the HEADER_INTERFACE named parameter (cxx_library() only), or the
MODULE_INTERFACE named parameter (cxx_library() only).
# A standalone executable.
cxx_executable(
TARGET hello
SOURCES hello.cpp
)
# A greeter using conventional C++ headers.
cxx_library(
TARGET greeter
LIBRARY_TYPE OBJECT
SOURCES greeter.cpp
HEADER_INTERFACE greeter.hpp
)
cxx_test(
TARGET test_greeter
SOURCES test_greeter.cpp
DEPENDS_ON greeter
)
# A header-only version.
cxx_library(
TARGET greeter_header_only
LIBRARY_TYPE HEADER_ONLY
HEADER_INTERFACE greeter_header_only.hpp
)
cxx_test(
TARGET test_greeter_header_only
SOURCES test_greeter.cpp
DEPENDS_ON greeter_header_only
)
# A greeter using C++20 modules.
cxx_library(
TARGET module_based_greeter
MODULE_INTERFACE module_based_greeter.cpp
)
cxx_test(
TARGET test_module_based_greeter
SOURCES test_module_based_greeter.cpp
DEPENDS_ON module_based_greeter
)
- cxx_executable(TARGET target_name SOURCES source_files... COMPILE_OPTIONS options... DEFINE macros... HEADERS headers... INDCLUDE directories... LINK_OPTIONS linker_options... DEPENDS_ON dependencies... INSTALL_WITH install_target INSTALL_PERMISSIONS install_permissions...)#
Builds an executable program. Accepts the following parameters:
- TARGET:STRING#
The name of the executable.
- SOURCES:LIST[STRING]#
Paths to each source file.
cxx_executable( TARGET hello SOURCES hello.cpp greeter.cpp )
- COMPILE_OPTIONS:LIST[STRING]#
Provides the compiler with a set of options that are only be applicable to the current target.
cxx_executable( TARGET hello SOURCES hello.cpp COMPILE_OPTIONS -Wno-float-conversion -Wno-literal-conversion )
- DEFINE:LIST[STRING]#
Tells the compiler to define these macros for every source file.
cxx_executable( TARGET hello SOURCES hello.cpp DEFINE ${PROJECT_NAME}_USE_ASAN ${PROJECT_NAME}_RETURN_VALUE=1 )
- HEADERS:LIST[STRING]#
Tells the compiler the set of headers that the target depends on.
cxx_executable( TARGET hello SOURCES hello.cpp HEADERS "${PROJECT_SOURCE_DIR}/include/greeting.hpp" )
- LINK_OPTIONS:LIST[STRING]#
Provides the linker with a set of options that are only be applicable to the current target.
cxx_executable( TARGET hello SOURCES hello.cpp LINK_OPTIONS -fuse-ld=mold )
- DEPENDS_ON:LIST[STRING]#
Tells CMake which targets this one depends on.
cxx_executable( TARGET hello_triangle SOURCES hello_triangle.cpp DEPENDS_ON Vulkan GLFW3 )
- INSTALL_WITH:STRING#
Installs the executable to
${CMAKE_INSTALL_PREFIX}/binwheninstall_targetis invoked as an install step.install_targetmust be defined inconfig/cmake/install_targets.cmake.This executable will be installed to${CMAKE_INSTALL_PREFIX}/binwheninstall-targetsis executed as an install step.#cxx_executable( TARGET hello_moon SOURCES hello_moon.cpp INSTALL_WITH install-targets )
- INSTALL_PERMISSIONS:LIST[STRING]#
Determines the permissions that the executable will have when installed. Valid values include
OWNER_READ,OWNER_WRITE,OWNER_EXECUTE,GROUP_READ,GROUP_WRITE,GROUP_EXECUTE,WORLD_READ,WORLD_WRITE, andWORLD_EXECUTE.Defaults to
OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE.The previous case installedhello_moonwith the default permissions. We install with some more restricted permissions this time.#cxx_executable( TARGET hello_moon SOURCES hello_moon.cpp INSTALL_WITH install-targets INSTALL_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE )
- cxx_library(TARGET target_name LIBRARY_TYPE library_type SOURCES sources... MODULE_INTERFACE export_module_sources... HEADERS headers HEADER_INTERFACE headers_to_export DEFINE macros... DEPENDS_ON_INTERFACE public_dependencies... DEPENDS_ON private_dependencies... INSTALL_WITH install_target INSTALL_PREFIX_INCLUDE directory INSTALL_PREFIX_LIBRARY directory INSTALL_PERMISSIONS install_permissions...)#
Builds a library.
cxx_library()supports the following named arguments.- TARGET:STRING#
The name of the library.
- SOURCES:LIST[STRING]#
- MODULE_INTERFACE:LIST[STRING]#
Both are used to indicate which source files are built for this target.
MODULE_INTERFACErefers to any file containingexport module.cxx_library( TARGET greeter MODULE_INTERFACE greeter.cpp SOURCES strings.cpp )
- LIBRARY_TYPE:STRING#
Determines how the library should be produced. Valid values include:
STATICbuilds the target as a static library. Static libraries are typically shipped as a deliverable for other projects to consume.The executablehellowill have all ofgreeter’s code linked at build time. The project does not need to shipgreeterforhelloto be usable.#cxx_library( TARGET greeter LIBRARY_TYPE STATIC HEADER_INTERFACE "${PROJECT_SOURCE_DIR}/include/greeter.hpp" "${PROJECT_SOURCE_DIR}/include/strings.hpp" SOURCES greeter.cpp strings.cpp ) cxx_binary( TARGET hello DEPENDS_ON greeter )
SHAREDbuilds the target as a shared library. Shared libraries are typically shipped as a deliverable for other projects to consume.The executablehellowill not contain any ofgreeter’s code, and requires the project to shipgreeterin order forhelloto be usable.#cxx_library( TARGET greeter LIBRARY_TYPE SHARED HEADER_INTERFACE "${PROJECT_SOURCE_DIR}/include/greeter.hpp" "${PROJECT_SOURCE_DIR}/include/strings.hpp" SOURCES greeter.cpp strings.cpp ) cxx_binary( TARGET hello DEPENDS_ON greeter )
PLUGINbuilds the target as a shared object that must be loaded at runtime, and cannot be linked using the compiler or linker.cxx_library( TARGET greeter LIBRARY_TYPE PLUGIN SOURCES greeter.cpp strings.cpp ) # Error: attempting to link greeter cxx_binary( TARGET hello DEPENDS_ON greeter )
Note
The official CMake term for this is
MODULE. We usePLUGINto avoid confusion with C++20 modules.OBJECTbuilds the target as an intermediary object file. Object files are project-local targets that are used to modularise a build. Unlike all other library types, object files cannot be exported by the project.cxx_library( TARGET greeter LIBRARY_TYPE OBJECT HEADER_INTERFACE "${PROJECT_SOURCE_DIR}/include/greeter.hpp" "${PROJECT_SOURCE_DIR}/include/strings.hpp" SOURCES greeter.cpp strings.cpp ) cxx_binary( TARGET hello DEPENDS_ON greeter )
HEADER_ONLYbuilds the target as a header-only library. Since header-only libraries only consist of headers, it isn’t possible to useSOURCES,MODULE_INTERFACE, orHEADERS.cxx_library( TARGET greeter LIBRARY_TYPE HEADER_ONLY HEADER_INTERFACE strings.hpp greeter.hpp ) cxx_binary( TARGET hello DEPENDS_ON greeter )
- HEADERS:LIST[STRING]#
- HEADER_INTERFACE:LIST[STRING]#
Tells the build system the set of headers that the target depends on. Headers listed under
HEADER_INTERFACEare installed, while headers listed underHEADERSare not.cxx_library( TARGET hello LIBRARY_TYPE OBJECT HEADER_INTERFACE "${PROJECT_SOURCE_DIR}/include/greeter.hpp" HEADERS "${PROJECT_SOURCE_DIR}/source/strings.hpp" SOURCES greeter.cpp strings.cpp )
- DEFINE:LIST[STRING]#
As above, but for macros.
- DEPENDS_ON_INTERFACE:LIST[STRING]#
- DEPENDS_ON:LIST[STRING]#
Tells CMake which targets this one depends on.
DEPENDS_ON_INTERFACEdependencies are propagated; dependencies listed underDEPENDS_ONare not.cxx_executable( TARGET hello_triangle SOURCES hello_triangle.cpp DEPENDS_ON Vulkan GLFW3 )
- INSTALL_WITH:STRING#
Installs header interfaces to
${CMAKE_INSTALL_PREFIX}/include, and static archives, shared objects, and plugins to${CMAKE_INSTALL_PREFIX}/libwheninstall-targetsis executed as an install step.Note
Module interfaces can’t be installed at the moment due to technical limitations.
The precompiled binary component of this library will be installed to${CMAKE_INSTALL_PREFIX}/lib, and the headers will be installed to${CMAKE_INSTALL_PREFIX}/includewheninstall-targetsis executed as an install step.#cxx_library( TARGET greeter LIBRARY_TYPE STATIC HEADERS greeter.hpp SOURCES greeter.cpp INSTALL_WITH install-targets )
- INSTALL_PREFIX_INCLUDE:STRING#
Tells the build system to install headers to the path in
${CMAKE_INSTALL_PREFIX}/include/${INSTALL_PREFIX_INCLUDE}.The precompiled binary component of this library will be installed to${CMAKE_INSTALL_PREFIX}/lib, and the headers will be installed to :code:`${CMAKE_INSTALL_PREFIX}/include/greeter` wheninstall-targetsis executed as an install step.#cxx_library( TARGET greeter LIBRARY_TYPE STATIC HEADERS greeter.hpp SOURCES greeter.cpp INSTALL_WITH install-targets INSTALL_PREFIX_INCLUDE greeter )
- INSTALL_PREFIX_LIBRARY:STRING#
Tells the build system to install static archives, shared objects, and plugins to the path in
${CMAKE_INSTALL_PREFIX}/include/${INSTALL_PREFIX_LIBRARY}.The precompiled binary component of this library will be installed to :code:`${CMAKE_INSTALL_PREFIX}/lib/greeter`, and the headers will be installed to${CMAKE_INSTALL_PREFIX}/include/greeterwheninstall-targetsis executed as an install step.#cxx_library( TARGET greeter LIBRARY_TYPE STATIC HEADERS greeter.hpp SOURCES greeter.cpp INSTALL_WITH install-targets INSTALL_PREFIX_INCLUDE greeter )
- INSTALL_PERMISSIONS:LIST[STRING]#
Determines the permissions that the library will have when installed. Valid values include
OWNER_READ,OWNER_WRITE,OWNER_EXECUTE,GROUP_READ,GROUP_WRITE,GROUP_EXECUTE,WORLD_READ,WORLD_WRITE, andWORLD_EXECUTE.Defaults to
OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ.The previous case installedgreeterwith the default permissions. We install with some more restricted permissions this time.#cxx_library( TARGET greeter LIBRARY_TYPE shared HEADERS greeter.hpp SOURCES greeter.cpp INSTALL_WITH install-targets INSTALL_PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ )
- cxx_test()#
A wrapper around
cxx_executable()to register the executable with CTest. The parameters are identical, excluding install options.The test will be named
test.$TARGET_NAME, where$TARGET_NAMEis a placeholder for what you passed toTARGET.
Installing binaries#
The named parameter INSTALL_WITH install-targets indicates to a cxx_executable() or
cxx_library() that you intend to install this target. In order to do so, you’ll first need to
define install-targets as something to install. You do this by adding an install(EXPORT)
to config/cmake/install_targets.cmake, like the one that’s below.
install(
EXPORT ${project_name}-install
FILE ${project_name}-config.cmake
NAMESPACE ${project_name}::
DESTINATION lib/cmake/${project_name}
)
Your project will automatically warn that an installation target hasn’t been created so that you don’t forget to do this.