commit 120ef25b84ab19f97de092673b0e6ba11766bf2c Author: clzhao20 Date: Mon Apr 8 15:22:45 2024 +0800 🎉 init(cmake): init modern cmake template diff --git a/.cache/clangd/index/app.cpp.585A27E459A42788.idx b/.cache/clangd/index/app.cpp.585A27E459A42788.idx new file mode 100644 index 0000000..cc2d528 Binary files /dev/null and b/.cache/clangd/index/app.cpp.585A27E459A42788.idx differ diff --git a/.cache/clangd/index/lib.cpp.3E5A22867B4F266E.idx b/.cache/clangd/index/lib.cpp.3E5A22867B4F266E.idx new file mode 100644 index 0000000..926ed71 Binary files /dev/null and b/.cache/clangd/index/lib.cpp.3E5A22867B4F266E.idx differ diff --git a/.cache/clangd/index/lib.hpp.C6091EB14F97B140.idx b/.cache/clangd/index/lib.hpp.C6091EB14F97B140.idx new file mode 100644 index 0000000..f7529bc Binary files /dev/null and b/.cache/clangd/index/lib.hpp.C6091EB14F97B140.idx differ diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f35e3c0 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*build* diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..4edcd82 --- /dev/null +++ b/CMakeLists.txt @@ -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() diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..189bcc9 --- /dev/null +++ b/Makefile @@ -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" diff --git a/README.md b/README.md new file mode 100644 index 0000000..027107a --- /dev/null +++ b/README.md @@ -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. diff --git a/apps/CMakeLists.txt b/apps/CMakeLists.txt new file mode 100644 index 0000000..cbaa521 --- /dev/null +++ b/apps/CMakeLists.txt @@ -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) diff --git a/apps/app.cpp b/apps/app.cpp new file mode 100644 index 0000000..26a92ee --- /dev/null +++ b/apps/app.cpp @@ -0,0 +1,17 @@ +#include + +#include + +#include +#include +#include + +int main() { + std::vector input = {1.2, 2.3, 3.4, 4.5}; + + auto [mean, moment] = accumulate_vector(input); + + fmt::print("Mean: {}, Moment: {}\n", mean, moment); + + return 0; +} diff --git a/cmake/FindSomeLib.cmake b/cmake/FindSomeLib.cmake new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/cmake/FindSomeLib.cmake @@ -0,0 +1 @@ + diff --git a/docs/CMakeLists.txt b/docs/CMakeLists.txt new file mode 100644 index 0000000..f833062 --- /dev/null +++ b/docs/CMakeLists.txt @@ -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") diff --git a/docs/mainpage.md b/docs/mainpage.md new file mode 100644 index 0000000..6f29cd9 --- /dev/null +++ b/docs/mainpage.md @@ -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`. diff --git a/externals/.git-keep b/externals/.git-keep new file mode 100644 index 0000000..e69de29 diff --git a/include/modern/lib.hpp b/include/modern/lib.hpp new file mode 100644 index 0000000..a058e69 --- /dev/null +++ b/include/modern/lib.hpp @@ -0,0 +1,12 @@ +#pragma once + +#include +#include + +/// \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 accumulate_vector( + const std::vector& values ///< The vector of values +); diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 0000000..e3c614d --- /dev/null +++ b/src/CMakeLists.txt @@ -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}) diff --git a/src/lib.cpp b/src/lib.cpp new file mode 100644 index 0000000..dc20885 --- /dev/null +++ b/src/lib.cpp @@ -0,0 +1,21 @@ +#include + +#include +#include +#include + +#include +#include +#include +#include + +namespace ba = boost::accumulators; + +std::tuple accumulate_vector(const std::vector& values) { + + ba::accumulator_set>> acc; + + std::for_each(std::begin(values), std::end(values), std::ref(acc)); + + return {ba::mean(acc), ba::moment<2>(acc)}; +} diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt new file mode 100644 index 0000000..917e23d --- /dev/null +++ b/tests/CMakeLists.txt @@ -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 diff --git a/tests/testlib.cpp b/tests/testlib.cpp new file mode 100644 index 0000000..e4becee --- /dev/null +++ b/tests/testlib.cpp @@ -0,0 +1,11 @@ +#define CATCH_CONFIG_MAIN +#include +#include + +TEST_CASE( "Quick check", "[main]" ) { + std::vector values {1, 2., 3.}; + auto [mean, moment] = accumulate_vector(values); + + REQUIRE( mean == 2.0 ); + REQUIRE( moment == Approx(4.666666) ); +}