# [`cmake-common`][] A [CMake][]\>=3.14 [C++][] common project helper. [CMake][] has many useful features but requires verbose per-project configuration to enable them. This helper allows you to just place your files where everyone expects them to be anyway, install the tools you want to use, and things like downloading dependencies, linting, building, testing, sanitizing, packaging (build artifacts, assets, documentation), and installing will automatically be enabled. [`cmake-common`]: https://git.rcrnstn.net/rcrnstn/cmake-common [CMake]: https://cmake.org [C++]: https://en.wikipedia.org/wiki/C++ ## Usage This work is licensed in such a way that you may use it however you please, including relicensing, without attribution. As such, the encouraged way to use this work is to simply copy the required files or content into your project, optionally(!) mentioning where it came from in the readme or other documentation. See [License][]. Copy the file [`common.cmake`][] into your project and [`include`][] it from (e.g.) the main [`CMakeLists.txt`][]. This will define a `common` function that takes a number of arguments to configure the project. [License]: #license [`include`]: https://cmake.org/cmake/help/v3.14/command/include.html [`common.cmake`]: common.cmake [`CMakeLists.txt`]: https://cmake.org/cmake/help/v3.14/manual/cmake-language.7.html#directories ### Overview ```cmake ## CMake cmake_minimum_required(VERSION 3.14) if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE Debug) endif() ## Project project(project-name VERSION 1.0.0 LANGUAGES CXX ) ## Main target add_library(${PROJECT_NAME}) ## Common include(common.cmake) common( CXX_STANDARD 11 DISABLE_INCLUDE_WHAT_YOU_USE PACKAGES Package EXTERNAL external_project FETCHCONTENT "https://example.com/user/online_project GIT_TAG v1.2.3" DEPENDENCIES_PUBLIC Package::Package DEPENDENCIES_PRIVATE external_project DEPENDENCIES_TESTS online_project DEFINITIONS PROJECT_FEATURE ) ``` ### Main target If there are files in the `src` and/or `include` directories, they are added as sources to a single "main" target, which is assumed to already be declared with the name `${`[`PROJECT_NAME`][]`}` (which is automatically set by CMake when calling [`project`][]). The "main" target may be of any type, such as [normal executable][], [normal library][], [interface library][], or [custom target][] (the latter probably with the `ALL` specifier, so that it is added to the default build target so that it will be run every time). [`PUBLIC`][] dependencies are taken from `DEPENDENCIES_PUBLIC` and [`PRIVATE`][] dependencies are taken from `DEPENDENCIES_PRIVATE`, see [Dependencies][]. For [top level project][]s, `*Config.cmake` and `*ConfigVersion.cmake` files that can be used by [`find_package`][] to find this project are [`install`][]ed, see [Packaging][]. [`PROJECT_NAME`]: https://cmake.org/cmake/help/v3.14/variable/PROJECT_NAME.html [`project`]: https://cmake.org/cmake/help/v3.14/command/project.html [normal executable]: https://cmake.org/cmake/help/v3.14/command/add_executable.html#normal-executables [normal library]: https://cmake.org/cmake/help/v3.14/command/add_library.html#normal-libraries [interface library]: https://cmake.org/cmake/help/v3.14/command/add_library.html#interface-libraries [custom target]: https://cmake.org/cmake/help/v3.14/command/add_custom_target.html [`PUBLIC`]: https://cmake.org/cmake/help/v3.14/manual/cmake-buildsystem.7.html#target-usage-requirements [`PRIVATE`]: https://cmake.org/cmake/help/v3.14/manual/cmake-buildsystem.7.html#target-usage-requirements [Dependencies]: #dependencies [top level project]: https://cmake.org/cmake/help/v3.14/variable/CMAKE_PROJECT_NAME.html [`find_package`]: https://cmake.org/cmake/help/v3.14/command/find_package.html [`install`]: https://cmake.org/cmake/help/v3.14/command/install.html [Packaging]: #packaging ### Test targets For [top level project][]s, every file directly under the `tests` directory is individually added as a source to a separate executable "test" target, which is automatically declared with the name `${PROJECT_NAME}-test-${TEST_NAME}` and passed to [`add_test`][]. All files in the `tests/common` directory are also added as sources to all "test" targets. A ([`PRIVATE`][]) dependency on the "main" target is declared and further ([`PRIVATE`][]) dependencies are taken from `DEPENDENCIES_TESTS`, see [Dependencies][]. CMake can be run with the standard `-D`[`BUILD_TESTING`][]`=OFF` to disable testing. See [Testing][]. [`add_test`]: https://cmake.org/cmake/help/v3.14/command/add_test.html [`BUILD_TESTING`]: https://cmake.org/cmake/help/v3.14/module/CTest.html [Testing]: #testing ### Assets If there are files in the `assets` directory, a target named `${PROJECT_NAME}-assets` that runs by default and [symlink][]s them to `${`[`CMAKE_BINARY_DIR`][]`}/assets` is automatically declared. If the path does not include `/tests/`, the asset is [`install`][]ed into `${`[`CMAKE_INSTALL_DATADIR`][]`}/${CMAKE_PROJECT_NAME}/assets` (note that `CMAKE_PROJECT_NAME` is the name of the [top level project][]), see [Packaging][]. [symlink]: https://en.wikipedia.org/wiki/Symbolic_link [`CMAKE_BINARY_DIR`]: https://cmake.org/cmake/help/v3.14/variable/CMAKE_BINARY_DIR.html [`CMAKE_INSTALL_DATADIR`]: https://cmake.org/cmake/help/v3.14/module/GNUInstallDirs.html ### Documentation For [top level project][]s, documentation from the `doc` directory and repository root is automatically [`install`][]ed, see [Packaging][]. ### Man pages For [top level project][]s, [man page][]s from the `man` directory is automatically [`install`][]ed, see [Packaging][]. [man page]: https://en.wikipedia.org/wiki/Man_page ### Dependencies Dependencies on other targets are declared with `DEPENDENCIES_PUBLIC`, `DEPENDENCIES_PRIVATE`, and `DEPENDENCIES_TESTS`, see [Main target][] and [Test targets][]. Three mechanisms to make these dependencies available are provided, given as arguments to the `common` function: - `PACKAGES`: Packages passed to [`find_package`][]`(...)` in order to find system packages. - `EXTERNAL`: Subdirectories of `external` that is passed to [`add_subdirectory`][]. - `FETCHCONTENT`: [Git][] [URL][]s passed to [`FetchContent_Declare`][]'s `GIT_REPOSITORY`. If a specific [Git tag][] is wanted, specify it in the same (quoted) argument, delimited with `GIT_TAG`, see [Usage][]. (`GIT_SHALLOW` and `GIT_PROGRESS` are always set to `TRUE`). [`FetchContent_MakeAvailable`][] is automatically called in order to download and make targets available during the CMake configure step. If more involved steps are required to make targets available, perform them manually before calling the `common` function. [Main target]: #main-target [Test targets]: #test-targets [`add_subdirectory`]: https://cmake.org/cmake/help/v3.14/command/add_subdirectory.html [Git]: https://git-scm.com [URL]: https://en.wikipedia.org/wiki/URL [`FetchContent_Declare`]: https://cmake.org/cmake/help/v3.14/module/FetchContent.html#command:fetchcontent_declare [`FetchContent_MakeAvailable`]: https://cmake.org/cmake/help/v3.14/module/FetchContent.html#command:fetchcontent_makeavailable [Git tag]: https://git-scm.com/book/en/v2/Git-Basics-Tagging [Usage]: #usage ### Preprocessor definitions [Preprocessor definitions][] can be specified with the `DEFINITIONS` argument to the `common` function. Both `NAME` and `NAME=EXPANSION` forms are supported. [preprocessor definitions]: https://en.cppreference.com/w/cpp/preprocessor/replace#.23define_directives ### Language version For [top level project][]s, the `CXX_STANDARD` argument to the `common` function sets the [`CXX_STANDARD`][] property applied to configured targets ([`CXX_STANDARD_REQUIRED`][] is always set to `ON`, [`CXX_EXTENSIONS`][] is always set to `OFF`). [`CXX_STANDARD`]: https://cmake.org/cmake/help/v3.14/prop_tgt/CXX_STANDARD.html [`CXX_STANDARD_REQUIRED`]: https://cmake.org/cmake/help/v3.14/prop_tgt/CXX_STANDARD_REQUIRED.html [`CXX_EXTENSIONS`]: https://cmake.org/cmake/help/v3.14/prop_tgt/CXX_EXTENSIONS.html ### Build options For [top level project][]s, aggressive warnings are enabled and treated as errors. For projects compiled with [GCC][] or [Clang][], [`-Wshadow`][] is enabled by default, but can be disabled by passing `DISABLE_WSHADOW` to the `common` function. For projects compiled with [MSVC][], [`/Zc:__cplusplus`][] is enabled. If supported, [interprocedural optimization][] (also known as link-time optimization) is enabled. For projects compiled with the `Debug` [build type][] with [GCC][] or [Clang][], [address sanitizer][] ([wiki][address sanitizer wiki]), [leak sanitizer][] ([wiki][leak sanitizer wiki]), and [undefined behavior sanitizer][] are linked into all targets. The sanitizers can be disabled by passing `DISABLE_SANITIZERS` to the `common` function. Suppression files that match the [glob][]s `*.asan.supp`, `*.lsan.supp`, and `*.ubsan.supp` respectively in the repository root are automatically used. [GCC]: https://gcc.gnu.org [Clang]: https://clang.llvm.org [`-Wshadow=`]: https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html#index-Wshadow [MSVC]: https://visualstudio.microsoft.com/vs/ [`/Zc:__cplusplus`]: https://learn.microsoft.com/en-us/cpp/build/reference/zc-cplusplus [interprocedural optimization]: https://en.wikipedia.org/wiki/Interprocedural_optimization [build type]: https://cmake.org/cmake/help/v3.14/variable/CMAKE_BUILD_TYPE.html [address sanitizer]: https://clang.llvm.org/docs/AddressSanitizer.html [address sanitizer wiki]: https://github.com/google/sanitizers/wiki/AddressSanitizer [leak sanitizer]: https://clang.llvm.org/docs/LeakSanitizer.html [leak sanitizer wiki]: https://github.com/google/sanitizers/wiki/AddressSanitizerLeakSanitizer [undefined behavior sanitizer]: https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html [glob]: https://en.wikipedia.org/wiki/Glob_(programming) ### Tools For [top level project][]s compiled with the `Debug` [build type][], [Cppcheck][], [Clang-Tidy][], and [Include What You Use][] are automatically configured if present on the system. The tools can be disabled by passing the `DISABLE_CPPCHECK`, `DISABLE_CLANG_TIDY`, and/or `DISABLE_INCLUDE_WHAT_YOU_USE` options, respectively, to the `common` function. CppCheck suppressions list files that match the [glob][] `.cppcheck.supp`, a Clang-Tidy configuration file named `.clang-tidy`, and Include What You Use [mapping files][] that match the [glob][] `*.iwyu.imp`, in the repository root, are automatically used. [Cppcheck]: https://cppcheck.sourceforge.io [Clang-Tidy]: https://clang.llvm.org/extra/clang-tidy [Include What You Use]: https://include-what-you-use.org [mapping files]: https://github.com/include-what-you-use/include-what-you-use/blob/0.20/docs/IWYUMappings.md ### Testing For [top level project][]s, [CTest][] is automatically configured and can be run with [`ctest`][], see the [`BUILDING.md`][] auxiliary file. [CTest]: https://cmake.org/cmake/help/v3.14/module/CTest.html [`ctest`]: https://cmake.org/cmake/help/v3.14/manual/ctest.1.html [`BUILDING.md`]: BUILDING.md ### Packaging For [top level project][]s, [CPack][] is automatically configured and can be run with [`cpack`][], see the [`BUILDING.md`][] auxiliary file. [CPack]: https://cmake.org/cmake/help/v3.14/module/Pack.html [`cpack`]: ttps://cmake.org/cmake/help/v3.14/manual/cpack.1.html ## Auxiliary files This repository includes some files besides [`common.cmake`][] that may be of use: - [`BUILDING.md`][]: Instructions to build a project that uses [`cmake-common`][]. - [`.gitignore`][]: A configuration file for [Git][] that makes it ignore the created `_build` directory created when following the instructions in [`BUILDING.md`][]. - [`.cppcheck.supp`][]: A suppressions list for [CppCheck][] with a set of suppressed warnings. - [`.clang-tidy`][]: A configuration file for [Clang-Tidy][] with a set of enabled and disabled warnings. [`.gitignore`]: .gitignore [`.cppcheck.supp`]: .cppcheck.supp [`.clang-tidy`]: .clang-tidy ## License Licensed under the [BSD 0-Clause License][] unless otherwise noted, see the [`LICENSE`][] file. [BSD 0-Clause License]: https://choosealicense.com/licenses/0bsd/ [`LICENSE`]: LICENSE