🎉 init(cmake): init modern cmake template

This commit is contained in:
clzhao20 2024-04-08 15:22:45 +08:00
commit 120ef25b84
18 changed files with 285 additions and 0 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
*build*

78
CMakeLists.txt Normal file
View File

@ -0,0 +1,78 @@
# Works with 3.14 and tested through 3.29
cmake_minimum_required(VERSION 3.14...3.29)
# Project name and a few useful settings. Other commands can pick up the results
project(
ModernCMakeExample
VERSION 0.1
DESCRIPTION "An example project with CMake"
LANGUAGES CXX)
# Only do these if this is the main project, and not if it is included through add_subdirectory
if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)
# Optionally set things like CMAKE_CXX_STANDARD, CMAKE_POSITION_INDEPENDENT_CODE here
set(CMAKE_CXX_STANDARD 17)
# set(CMAKE_CXX_STANDARD_REQUIRED 17)
set(default_build_type "Release")
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
message(STATUS "Setting build type to '${default_build_type}' as none was specified.")
set(CMAKE_BUILD_TYPE "${default_build_type}" CACHE
STRING "Choose the type of build." FORCE)
# Set the possible values of build type for cmake-gui
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS
"Debug" "Release" "MinSizeRel" "RelWithDebInfo")
endif()
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
# Let's ensure -std=c++xx instead of -std=g++xx
set(CMAKE_CXX_EXTENSIONS OFF)
# Let's nicely support folders in IDEs
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
# Testing only available if this is the main app
# Note this needs to be done in the main CMakeLists
# since it calls enable_testing, which must be in the
# main CMakeLists.
include(CTest)
# Docs only available if this is the main app
find_package(Doxygen)
if(Doxygen_FOUND)
add_subdirectory(docs)
else()
message(STATUS "Doxygen not found, not building docs")
endif()
endif()
# FetchContent added in CMake 3.11, downloads during the configure step
# FetchContent_MakeAvailable was added in CMake 3.14; simpler usage
include(FetchContent)
# Accumulator library
# This is header only, so could be replaced with git submodules or FetchContent
find_package(Boost REQUIRED)
# Adds Boost::boost
# Formatting library
FetchContent_Declare(
fmtlib
GIT_REPOSITORY https://github.com/fmtlib/fmt.git
GIT_TAG 5.3.0)
FetchContent_MakeAvailable(fmtlib)
# Adds fmt::fmt
# The compiled library code is here
add_subdirectory(src)
# The executable code is here
add_subdirectory(apps)
# Testing only available if this is the main app
# Emergency override MODERN_CMAKE_BUILD_TESTING provided as well
if((CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME OR MODERN_CMAKE_BUILD_TESTING)
AND BUILD_TESTING)
add_subdirectory(tests)
endif()

34
Makefile Normal file
View File

@ -0,0 +1,34 @@
## 定义基本编译命令到变量中
# CC=gcc
# CXX=g++
default:
cmake -S . -B build -GNinja
release:
cmake -S . -B build -GNinja -DCMAKE_BUILD_TYPE=Release
cmake --build build
debug:
cmake -S . -B build -GNinja -DCMAKE_BUILD_TYPE=Debug
cmake --build build
docs:
cmake --build build --target docs
test:
cmake --build build --target test
clean:
rm build -rf
.PHONY: help clean
help:
@echo "Usage: make [target]"
@echo " default: build the project"
@echo " release: build the project with release mode"
@echo " debug: build the project with debug mode"
@echo " docs: build the project documentation"
@echo " clean: clean the project"
@echo " help: show this help message"

46
README.md Normal file
View File

@ -0,0 +1,46 @@
# CMake Template
This is an example project using CMake.
The requirements are:
- CMake 3.11 or better; 3.14+ highly recommended.
- A C++17 compatible compiler
- The Boost libararies (header only part is fine)
- Git
- Doxygen (optional)
To configure:
```bash
cmake -S . -B build
```
Add `-GNinja` if you have Ninja.
To build:
```bash
cmake --build build
```
To test (`--target` can be written as `-t` in CMake 3.15+):
```bash
cmake --build build --target test
```
To build docs (requires Doxygen, output in `build/docs/html`):
```bash
cmake --build build --target docs
```
To use an IDE, such as Xcode:
```bash
cmake -S . -B xbuild -GXcode
cmake --open xbuild
```
The CMakeLists show off several useful design patterns for CMake.

4
apps/CMakeLists.txt Normal file
View File

@ -0,0 +1,4 @@
add_executable(app app.cpp)
target_compile_features(app PRIVATE cxx_std_17)
target_link_libraries(app PRIVATE modern_library fmt::fmt)

17
apps/app.cpp Normal file
View File

@ -0,0 +1,17 @@
#include <modern/lib.hpp>
#include <fmt/format.h>
#include <iostream>
#include <vector>
#include <tuple>
int main() {
std::vector<double> input = {1.2, 2.3, 3.4, 4.5};
auto [mean, moment] = accumulate_vector(input);
fmt::print("Mean: {}, Moment: {}\n", mean, moment);
return 0;
}

1
cmake/FindSomeLib.cmake Normal file
View File

@ -0,0 +1 @@

5
docs/CMakeLists.txt Normal file
View File

@ -0,0 +1,5 @@
set(DOXYGEN_EXTRACT_ALL YES)
set(DOXYGEN_BUILTIN_STL_SUPPORT YES)
doxygen_add_docs(docs modern/lib.hpp "${CMAKE_CURRENT_SOURCE_DIR}/mainpage.md"
WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}/include")

11
docs/mainpage.md Normal file
View File

@ -0,0 +1,11 @@
# Documentation for Modern Library {#mainpage}
This is the documentation for my simple example library.
It is good documentation because:
1. It exists.
2. I wrote it.
3. Everything is documented (pretty easy since there's only one function)
The single provided function is `::accumulate_vector`.

0
externals/.git-keep vendored Normal file
View File

12
include/modern/lib.hpp Normal file
View File

@ -0,0 +1,12 @@
#pragma once
#include <vector>
#include <tuple>
/// \brief Accumulate a vector to produce the mean and the first moment of the distribution.
///
/// This computes the mean and the first moment of a vector of double values.
///
std::tuple<double, double> accumulate_vector(
const std::vector<double>& values ///< The vector of values
);

24
src/CMakeLists.txt Normal file
View File

@ -0,0 +1,24 @@
# Note that headers are optional, and do not affect add_library, but they will not
# show up in IDEs unless they are listed in add_library.
# Optionally glob, but only for CMake 3.12 or later:
# file(GLOB HEADER_LIST CONFIGURE_DEPENDS "${ModernCMakeExample_SOURCE_DIR}/include/modern/*.hpp")
set(HEADER_LIST "${ModernCMakeExample_SOURCE_DIR}/include/modern/lib.hpp")
# Make an automatic library - will be static or dynamic based on user setting
add_library(modern_library lib.cpp ${HEADER_LIST})
# We need this directory, and users of our library will need it too
target_include_directories(modern_library PUBLIC ../include)
# This depends on (header only) boost
target_link_libraries(modern_library PRIVATE Boost::boost)
# All users of this library will need at least C++11
target_compile_features(modern_library PUBLIC cxx_std_11)
# IDEs should put the headers in a nice place
source_group(
TREE "${PROJECT_SOURCE_DIR}/include"
PREFIX "Header Files"
FILES ${HEADER_LIST})

21
src/lib.cpp Normal file
View File

@ -0,0 +1,21 @@
#include <modern/lib.hpp>
#include <tuple>
#include <vector>
#include <algorithm>
#include <boost/accumulators/accumulators.hpp>
#include <boost/accumulators/statistics/stats.hpp>
#include <boost/accumulators/statistics/mean.hpp>
#include <boost/accumulators/statistics/moment.hpp>
namespace ba = boost::accumulators;
std::tuple<double, double> accumulate_vector(const std::vector<double>& values) {
ba::accumulator_set<double, ba::stats<ba::tag::mean, ba::tag::moment<2>>> acc;
std::for_each(std::begin(values), std::end(values), std::ref(acc));
return {ba::mean(acc), ba::moment<2>(acc)};
}

20
tests/CMakeLists.txt Normal file
View File

@ -0,0 +1,20 @@
# Testing library
FetchContent_Declare(
catch
GIT_REPOSITORY https://github.com/catchorg/Catch2.git
GIT_TAG v2.13.6)
FetchContent_MakeAvailable(catch)
# Adds Catch2::Catch2
# Tests need to be added as executables first
add_executable(testlib testlib.cpp)
# I'm using C++17 in the test
target_compile_features(testlib PRIVATE cxx_std_17)
# Should be linked to the main library, as well as the Catch2 testing library
target_link_libraries(testlib PRIVATE modern_library Catch2::Catch2)
# If you register a test, then ctest and make test will run it.
# You can also run examples and check the output, as well.
add_test(NAME testlibtest COMMAND testlib) # Command can be a target

11
tests/testlib.cpp Normal file
View File

@ -0,0 +1,11 @@
#define CATCH_CONFIG_MAIN
#include <catch2/catch.hpp>
#include <modern/lib.hpp>
TEST_CASE( "Quick check", "[main]" ) {
std::vector<double> values {1, 2., 3.};
auto [mean, moment] = accumulate_vector(values);
REQUIRE( mean == 2.0 );
REQUIRE( moment == Approx(4.666666) );
}