# [`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