-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Multiple .cmake files were condensed into single
cpp-init.cmake
- Loading branch information
Showing
17 changed files
with
295 additions
and
691 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,113 +1,105 @@ | ||
# cpp-init | ||
|
||
This repo hosts configuration files for my C++ projects. In addition to `.clang-format`/`.clang-tidy` files, several CMake scripts exist for easy project setup and maintenance. | ||
|
||
# Table of Contents | ||
|
||
- [Quickstart example](#quickstart-example) | ||
- [CPM Packages](#cpm-packages) | ||
- [bootstrap.cmake](#bootstrapcmake) | ||
- [bootstrap_cpm](#bootstrap_cpm) | ||
- [glob_headers_and_sources](#glob_headers_and_sources) | ||
- [get_git_version](#get_git_version) | ||
- [fetch_prebuilt_dependency](#fetch_prebuilt_dependency) | ||
- [fetch_headeronly_dependency](#fetch_headeronly_dependency) | ||
- [cpp.cmake](#cppcmake) | ||
- [apply_compile_options](#apply_compile_options) | ||
- [enable_autoformatter](#enable_autoformatter) | ||
- [enable_linter](#enable_linter) | ||
- [macros.cmake](#macroscmake) | ||
- [make_static_library](#make_static_library) | ||
- [make_executable](#make_executable) | ||
|
||
## Quickstart example | ||
|
||
First, get the `get_cpp_init.cmake` script from the Releases page. Then you can include it in your project and it will fetch the rest of the scripts for you: | ||
This repo hosts common configuration files I use in my C++ projects, namely: | ||
|
||
```cmake | ||
cmake_minimum_required ( VERSION 3.26 ) | ||
* `.clang-format` | ||
* `.clang-tidy` | ||
* `cmake/cpp-init.cmake` | ||
|
||
# Use the script from releases to fetch everything | ||
include ( "${PATH_TO}/get_cpp_init.cmake" ) | ||
The `cpp-init.cmake` is an opinionated CMake helper that makes CMake much simpler by enforcing a bunch of rules on project structure. | ||
|
||
# Read git tags for version | ||
get_git_version ( PROJECT_VERSION_VARIABLE GIT_FULL_VERSION ) | ||
## Table of Contents | ||
|
||
# Enable dependency management with CPM | ||
bootstrap_cpm() | ||
* [Project Structure](#project-structure) | ||
* [Quickstart Example](#quickstart-example) | ||
* [Documentation](#documentation) | ||
* [CMake Package Manager](#cmake-package-manager) | ||
|
||
project ( demo VERSION ${GIT_PROJECT_VERSION} ) | ||
## Project Structure | ||
|
||
CPMAddPackage( "gh:nlohmann/[email protected]" ) | ||
For each compilable target, the recommended folder structure is this: | ||
|
||
``` | ||
\root | ||
- \include | ||
- File.hpp | ||
- \src | ||
- File.cpp | ||
- CMakeLists.txt | ||
``` | ||
|
||
# globs all .hpp files from "${CMAKE_CURRENT_SOURCE_DIR}/include" | ||
# and all .cpp files from "${CMAKE_CURRENT_SOURCE_DIR}/src" | ||
# including subfolders | ||
glob_headers_and_sources ( HEADERS SOURCES ) | ||
Scripts present in this repo are conditioned to follow this structure, with a little bit of leevay. The `src` folder can also be called `source`. Allowed extensions for header files are `hpp` and `h`. Header files must always be in a folder `include` or `private_include` (the latter is for headers that should not be accessible by dependent targets). | ||
|
||
add_executable ( ${PROJECT_NAME} | ||
${HEADERS} | ||
${SOURCES} | ||
) | ||
These scripts also rely on globbing (recursively scanning) for source files, instead of you having to manually specify them in CMakeLists.txt. This makes project maintenance much easier, but if you delete a file, `cmake --build` command will not detect it automatically and will fail compilation. | ||
|
||
target_link_libraries ( ${PROJECT_NAME} | ||
PRIVATE_LINK nlohmann::json | ||
) | ||
If you delete a source file, you always need to manually reconfigure. Lastly, scripts here are tailored towards MSVC. PRs for your favorite platforms are welcomed. | ||
|
||
### Semantic versioning | ||
|
||
# Applies compiler switches and options I commonly use | ||
apply_compile_options ( ${PROJECT_NAME} ) | ||
This project also promotes [semantic versioning](https://semver.org/). You can easily read the current version from the git tags, insert it into your project declaration and it will propagate further into packaging, etc. | ||
|
||
If you're new to git, you can mark the current commit with version like this: | ||
|
||
```sh | ||
git tag v0.1.0 | ||
git push --tags | ||
``` | ||
|
||
## Quickstart Example | ||
|
||
Suppose you want to make a simple executable with a bunch of header and source files. Follow this folder structure: | ||
|
||
# Applies .clang-format | ||
enable_autoformatter ( ${PROJECT_NAME} ) | ||
``` | ||
\root | ||
- \cmake | ||
- cpp-init.cmake | ||
- \include | ||
- HeaderA.hpp | ||
- HeaderB.hpp | ||
- \src | ||
- ImplA.cpp | ||
- ImplB.cpp | ||
- Main.cpp | ||
- CMakeLists.txt | ||
``` | ||
|
||
Obtain the `cpp-init.cmake` by downloading the latest version from the [Releases](https://github.com/nerudaj/cpp-init/releases/latest) page. | ||
|
||
With macros, this can get even shorter: | ||
Put the following code in the `CMakeLists.txt`: | ||
|
||
```cmake | ||
cmake_minimum_required ( VERSION 3.26 ) | ||
# Use the script from releases to fetch everything | ||
include ( "${PATH_TO}/get_cpp_init.cmake" ) | ||
include ( "cmake/cpp-init.cmake" ) | ||
# Read git tags for version | ||
get_git_version ( PROJECT_VERSION_VARIABLE GIT_FULL_VERSION ) | ||
cpp_init() | ||
get_version_from_git ( PROJECT_VERSION_VARIABLE GIT_FULL_VERSION ) | ||
# Enable dependency management with CPM | ||
bootstrap_cpm() | ||
project ( Example VERSION ${PROJECT_VERSION_VARIABLE} ) | ||
project ( demo VERSION ${GIT_PROJECT_VERSION} ) | ||
CPMAddPackage ( "gh:nlohmann/[email protected]" ) | ||
# Convenience macro for CPMAddPackage call | ||
cpm_add_nlohmann_json () | ||
# Assumes there is at least `src` directory in the current one (also looks for `include`) | ||
# It globs them, adds them as sources, enables autoformatter and applies compile options. | ||
make_executable ( ${PROJECT_NAME} DEPS nlohmann::json ) | ||
make_executable ( ${PROJECT_NAME} DEPS nlohmann_json::nlohmann_json ) | ||
``` | ||
|
||
Assuming you're placing all `.cmake` files into a `cmake` subfolder, you can set a variable `CPP_INIT_ROOT_DIR` to `${CMAKE_CURRENT_SOURCE_DIR}/cmake` prior to including `get_cpp_init.cmake`. This will copy all related CMake scripts into your `cmake` folder so you can add them to your version control. | ||
The `cpp_init()`, `get_version_from_git()`, and `make_executable()` are all from the `cpp-init.cmake` and are documented below. | ||
|
||
## CPM Packages | ||
This example autodetects header and source files in the appropriate folders, creates an executable target called `${PROJECT_NAME}` and links nlohmann JSON library to it. It also reads project semantic version from git tags and applies it to the project. | ||
|
||
There are a few macros that make it easier to add certain well known (well known to me) C++ packages. Here's an overview: | ||
## Documentation | ||
|
||
| Library name | Version | Macro | Linkable target | | ||
| --- | --- | --- | --- | | ||
| base64 | master | cpm_add_base64 | base64 | | ||
| Catch2 | 3.7.1 | cpm_add_catch2 | Catch2::Catch2 | | ||
| cxxopts | 3.11.3 | cpm_add_cxxopts | cxxopts | | ||
| dgm-lib | 2.3.1 | cpm_add_dgmlib | dgm-lib | | ||
| Eigen | master | cpm_add_eigen | Eigen3::Eigen | | ||
| EnTT | 3.14.0 | cpm_add_entt | EnTT::EnTT | | ||
| FakeIt | 2.4.1 | cpm_add_fakeit | FakeIt::FakeIt | | ||
| fsm-lib | 2.1.0 | cpm_add_fsmlib | fsm-lib | | ||
| nlohmann json | 3.0.0 | cpm_add_nlohmann_json | nlohmann::json | | ||
| SFML | 2.6.1 | cpm_add_sfml | sfml-main sfml-audio sfml-graphics sfml-window sfml-network | | ||
| SFML 3 | 3.0.0 | cpm_add_sfml3 | SFML::Main SFML::Audio SFML::Graphics SFML::Window SFML::Network | | ||
|
||
## bootstrap.cmake | ||
|
||
This is a script full of useful utility functions: | ||
This section describes utility functions present in the `cpp-init.cmake` file. | ||
|
||
### download_file_if_not_there | ||
|
||
If a file with a TARGET name is not yet present, this function attepts to download it from a given URL. If not successful, empty file is created instead. | ||
|
||
```cmake | ||
download_file_if_not_there ( | ||
"http://myurl.com/file.txt" | ||
"${CMAKE_BINARY_DIR}/file.txt" | ||
) | ||
``` | ||
|
||
### bootstrap_cpm | ||
|
||
|
@@ -122,8 +114,20 @@ bootstrap_cpm ( 0.30.2 ) # version number is optional | |
CPMAddPackage( "gh:nlohmann/[email protected]" ) | ||
``` | ||
|
||
### set_cpp23_x64 | ||
|
||
Sets the required C++ standard to 23 and sets the target platform to x64. | ||
|
||
### cpp_init | ||
|
||
Shorthand for calling `bootstrap_cpm` and `set_cpp23_x64`. | ||
|
||
### glob_headers_and_sources | ||
|
||
In current source directory, recursively looks for .h/.hpp files in folders `include` and `private_include`, adds them to IDE through `source_group` call and saves them in `HEADERS_OUTVARNAME` variable. | ||
|
||
Also looks for .cpp files in `source` and `src` folders, adds them to IDE and saves them in `SOURCES_OUTVARNAME`. | ||
|
||
If the `${CMAKE_CURRENT_SOURCE_DIR}` contains subfolders `include` and `src`, this will recursively glob all `.hpp` files in the `include` folder and all `.cpp` files in the `src` folder. It will add them to your IDE filters through `source_group` call and it will populate the output variables. | ||
|
||
```cmake | ||
|
@@ -163,32 +167,33 @@ CPM is great, but you pay with long build times. Many libraries on GitHub come p | |
fetch_prebuilt_dependency ( | ||
SFML | ||
URL https://github.com/SFML/SFML/releases/download/2.6.1/SFML-2.6.1-windows-vc17-64-bit.zip | ||
CACHE_DIR "C:/deps" # can download to outside location | ||
CACHE_DIR "C:/deps" # optional: can download to given location | ||
) | ||
# unpacked archive contents are in ${SFML_FOLDER} | ||
``` | ||
|
||
Unlike `FetchContent_MakeAvailable`, this only downloads and unpacks the archive. It does not look for `CMakeLists.txt` inside the archive, nor it calls `add_subdirectory`. | ||
|
||
### fetch_headeronly_dependency | ||
|
||
For headeronly libraries, it is even easier (the `CACHE_DIR` parameter can still be used). | ||
Downloads a single file, presumably a headeronly library. | ||
|
||
```cmake | ||
fetch_headeronly_dependency ( | ||
NLOHMANN_JSON | ||
JSON | ||
URL https://github.com/nlohmann/json/releases/download/v3.11.3/json.hpp | ||
CACHE_DIR "C:/deps" # optional: can download to given location | ||
) | ||
# json.hpp is located in ${NLOHMANN_JSON_FOLDER} | ||
# json.hpp is located in ${JSON_FOLDER} | ||
``` | ||
|
||
## cpp.cmake | ||
|
||
### apply_compile_options | ||
|
||
**NOTE:** Currently only supported with MSVC generator. | ||
|
||
Applies a set of useful compiler diagnostics and settings. | ||
Applies a set of useful compiler diagnostics and settings. For MSVC, postfixes all artifacts compiled under Debug with `-d` postfix. | ||
|
||
```cmake | ||
apply_compile_options ( ${TARGET} ) | ||
|
@@ -204,14 +209,12 @@ enable_autoformatter ( ${TARGET} ) | |
|
||
### enable_linter | ||
|
||
Copies `.clang-tidy` to `${CMAKE_CURRENT_SOURCE_DIR}` and adds them to the specified target sources. For MSVC, it turns on static code analysis with Clang tidy. | ||
Copies `.clang-tidy` to `${CMAKE_CURRENT_SOURCE_DIR}` and adds them to the specified target sources. For MSVC, it turns on static code analysis with clang-tidy. Note that MSVC ships with some old clang-tidy implementation so you likely need to install newer one yourself. | ||
|
||
```cmake | ||
enable_linter ( ${TARGET} ) | ||
``` | ||
|
||
## macros.cmake | ||
|
||
### make_static_library | ||
|
||
A shorthand for calling `glob_headers_and_sources`, `apply_compile_options` and bunch of other options. Declares `include` folder as public include directory. | ||
|
@@ -232,3 +235,22 @@ make_static_library ( myLib DEPS nlohmann_json::nlohmann_json ) | |
### make_executable | ||
|
||
Similar as `make_static_library`, just for executables. | ||
|
||
## CMake Package Manager | ||
|
||
CPM is great, but I can never remember the author nor the CMake target I can link against. Here's a list of bunch of libraries I frequently use, might be useful for you as well: | ||
|
||
| Library name | Version | CPM expression | Linkable target | | ||
| --- | --- | --- | --- | | ||
| base64 | master | `gh:tobiaslocker/base64#master` | base64 | | ||
| Catch2 | 3.7.1 | `gh:catchorg/Catch2#v3.7.1` | Catch2::Catch2 | | ||
| cxxopts | 3.2.1 | `jarro2783/cxxopts#3.2.1` | cxxopts | | ||
| dgm-lib | 2.5.0 | `gh:nerudaj/dgm-lib#v2.5.0` | dgm-lib | | ||
| dgm-lib 3 | 3.0.0-rc1 | `gh:nerudaj/dgm-lib#v3.0.0-rc1` | dgm::dgm | | ||
| Eigen | master | `gl:libeigen/eigen#master` | Eigen3::Eigen | | ||
| EnTT | 3.14.0 | `gh:skypjack/entt#v3.14.0` | EnTT::EnTT | | ||
| FakeIt | 2.4.1 | `gh:eranpeer/FakeIt#2.4.1` | FakeIt::FakeIt | | ||
| fsm-lib | 2.1.0 | `gh:nerudaj/fsm-lib#v2.1.0` | fsm-lib | | ||
| nlohmann json | 3.11.3 | `gh:nlohmann/json#v3.11.3` | nlohmann::json | | ||
| SFML | 2.6.1 | `gh:SFML/SFML#2.6.1` | sfml-main sfml-audio sfml-graphics sfml-window sfml-network | | ||
| SFML 3 | 3.0.0 | `gh:SFML/SFML#3.0.0` | SFML::Main SFML::Audio SFML::Graphics SFML::Window SFML::Network | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.