mirror of
				https://github.com/TheLartians/ModernCppStarter.git
				synced 2025-10-31 02:01:33 +01:00 
			
		
		
		
	do it my way, modernize cmake
build dynamic lib use makefile wrapper to test all use cases include clang-tidy config file prevent clang-tidy warnings
This commit is contained in:
		
							parent
							
								
									eedcb6f24e
								
							
						
					
					
						commit
						79060d4af6
					
				
					 10 changed files with 128 additions and 50 deletions
				
			
		
							
								
								
									
										26
									
								
								.clang-tidy
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								.clang-tidy
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,26 @@ | |||
| --- | ||||
| Checks: "-*,\ | ||||
| boost-*,\ | ||||
| cert-*,\ | ||||
| clang-analyzer-*,\ | ||||
| cppcoreguidelines-*,\ | ||||
| -cppcoreguidelines-macro-usage,\ | ||||
| -cppcoreguidelines-owning-memory,\ | ||||
| -hicpp-*,\ | ||||
| misc-*,\ | ||||
| -misc-non-private-member-variables-in-classes,\ | ||||
| -modernize-*,\ | ||||
| -modernize-use-trailing-return-type,\ | ||||
| performance-*,\ | ||||
| portability-*,\ | ||||
| readability-*,\ | ||||
| -*magic-numbers,\ | ||||
| -*avoid-c-arrays,\ | ||||
| " | ||||
| WarningsAsErrors: '' | ||||
| HeaderFilterRegex: '.*' | ||||
| AnalyzeTemporaryDtors: false | ||||
| FormatStyle:     file | ||||
| User:            clausklein | ||||
| ... | ||||
| 
 | ||||
|  | @ -1,4 +1,4 @@ | |||
| cmake_minimum_required(VERSION 3.14 FATAL_ERROR) | ||||
| cmake_minimum_required(VERSION 3.14...3.19) | ||||
| 
 | ||||
| # ---- Project ---- | ||||
| 
 | ||||
|  | @ -21,15 +21,16 @@ endif() | |||
| # ---- Project settings ---- | ||||
| 
 | ||||
| if(NOT DEFINED CMAKE_CXX_STANDARD) | ||||
|   set(CMAKE_CXX_STANDARD 17) | ||||
|   set(CMAKE_CXX_STANDARD 20) | ||||
|   set(CMAKE_CXX_STANDARD_REQUIRED ON) | ||||
|   set(CMAKE_CXX_EXTENSIONS NO) | ||||
| endif() | ||||
| 
 | ||||
| # ---- Add dependencies via CPM ---- | ||||
| # see https://github.com/TheLartians/CPM.cmake for more info | ||||
| # see https://github.com/cpm-cmake/CPM.cmake for more info | ||||
| 
 | ||||
| include(cmake/CPM.cmake) | ||||
| cpmusepackagelock(package-lock.cmake) | ||||
| 
 | ||||
| # PackageProject.cmake will be used to make our target installable | ||||
| CPMAddPackage( | ||||
|  | @ -59,8 +60,9 @@ file(GLOB_RECURSE sources CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/source/ | |||
| 
 | ||||
| # Note: for header-only libraries change all PUBLIC flags to INTERFACE and create an interface | ||||
| # target! EITHER: add_library(Greeter INTERFACE) OR: | ||||
| add_library(Greeter ${headers} ${sources}) | ||||
| add_library(Greeter SHARED ${headers} ${sources}) | ||||
| 
 | ||||
| # EITHER: | ||||
| set_target_properties(Greeter PROPERTIES CXX_STANDARD ${CMAKE_CXX_STANDARD}) | ||||
| # OR target_compile_features(Greeter PUBLIC cxx_std_17) | ||||
| 
 | ||||
|  | @ -69,9 +71,9 @@ if(MSVC) | |||
|   target_compile_options(Greeter PUBLIC /permissive) | ||||
| endif() | ||||
| 
 | ||||
| # Link dependencies (if required) | ||||
| # Link dependencies EITHER: | ||||
| target_link_libraries(Greeter PRIVATE $<BUILD_INTERFACE:fmt::fmt-header-only>) | ||||
| # XXX target_link_libraries(Greeter PUBLIC fmt::fmt) | ||||
| # OR: target_link_libraries(Greeter PUBLIC fmt::fmt) | ||||
| 
 | ||||
| target_include_directories( | ||||
|   Greeter PUBLIC $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include> | ||||
|  | @ -93,6 +95,6 @@ packageProject( | |||
|   INCLUDE_DIR ${PROJECT_SOURCE_DIR}/include | ||||
|   INCLUDE_DESTINATION include/${PROJECT_NAME}-${PROJECT_VERSION} | ||||
|   VERSION_HEADER "${VERSION_HEADER_LOCATION}" | ||||
|   # TODO COMPATIBILITY SameMajorVersion | ||||
|   DEPENDENCIES "fmt 7.1.3" | ||||
|   COMPATIBILITY SameMajorVersion | ||||
|   # NOTE: not needed DEPENDENCIES "fmt 7.1.3" | ||||
| ) | ||||
|  |  | |||
							
								
								
									
										58
									
								
								GNUmakefile
									
										
									
									
									
										Executable file
									
								
							
							
						
						
									
										58
									
								
								GNUmakefile
									
										
									
									
									
										Executable file
									
								
							|  | @ -0,0 +1,58 @@ | |||
| # | ||||
| # CURDIR=$(/bin/pwd) | ||||
| # | ||||
| # GENERATOR="Unix Makefiles" | ||||
| GENERATOR=Ninja | ||||
| 
 | ||||
| export CPM_SOURCE_CACHE=${HOME}/.cache/CPM | ||||
| export CPM_USE_LOCAL_PACKAGES=1 | ||||
| 
 | ||||
| .PHONY: update format all test check clean distclean lock | ||||
| 
 | ||||
| # the default target does just all | ||||
| check: all | ||||
| 
 | ||||
| all: test | ||||
| 
 | ||||
| test: install | ||||
| 
 | ||||
| 
 | ||||
| distclean: | ||||
| 	rm -rf build root | ||||
| 
 | ||||
| # update CPM.cmake | ||||
| update: | ||||
| 	wget -q -O cmake/CPM.cmake https://github.com/cpm-cmake/CPM.cmake/releases/latest/download/get_cpm.cmake | ||||
| 
 | ||||
| lock: install | ||||
| 	cmake --build build/install --target cpm-update-package-lock | ||||
| 
 | ||||
| # install the library | ||||
| install: | ||||
| 	cmake -S . -B build/install -G "${GENERATOR}" -DCMAKE_PREFIX_PATH=${CURDIR}/root -DCMAKE_INSTALL_PREFIX=${CURDIR}/root -DCMAKE_CXX_STANDARD=20 # --trace-expand | ||||
| 	cmake --build build/install --target install | ||||
| 
 | ||||
| # test the library | ||||
| test: | ||||
| 	cmake -S test -B build/test -G "${GENERATOR}" -DCMAKE_PREFIX_PATH=${CURDIR}/root -DTEST_INSTALLED_VERSION=1 | ||||
| 	cmake --build build/test | ||||
| 	cmake --build build/test --target test | ||||
| 
 | ||||
| # all together | ||||
| all: | ||||
| 	cmake -S all -B build/all -G "${GENERATOR}" -DCMAKE_PREFIX_PATH=${CURDIR}/root -DTEST_INSTALLED_VERSION=1 -DENABLE_TEST_COVERAGE=1 | ||||
| 	cmake --build build/all | ||||
| 	cmake --build build/all --target test | ||||
| 	cmake --build build/all --target GenerateDocs | ||||
| 	cmake --build build/all --target check-format | ||||
| 
 | ||||
| format: distclean | ||||
| 	find . -name CMakeLists.txt | xargs cmake-format -i | ||||
| 	find . -name '*.cpp' | xargs clang-format -i | ||||
| 	find . -name '*.h' | xargs clang-format -i | ||||
| 
 | ||||
| # check the library | ||||
| check: | ||||
| 	cmake -S standalone -B build/standalone -G "${GENERATOR}" -DCMAKE_PREFIX_PATH=${CURDIR}/root -DCMAKE_EXPORT_COMPILE_COMMANDS=1 | ||||
| 	cmake --build build/standalone --target all | ||||
| 	run-clang-tidy.py -p build/standalone -checks='-*,modernize-*,misc-*,hicpp-*,cert-*,readability-*,portability-*,performance-*,google-*' standalone | ||||
|  | @ -1,4 +1,4 @@ | |||
| cmake_minimum_required(VERSION 3.14 FATAL_ERROR) | ||||
| cmake_minimum_required(VERSION 3.14...3.19) | ||||
| 
 | ||||
| project(GreeterDocs) | ||||
| 
 | ||||
|  |  | |||
|  | @ -18,17 +18,14 @@ namespace greeter { | |||
|      * @brief Creates a new greeter | ||||
|      * @param name the name to greet | ||||
|      */ | ||||
|     Greeter(std::string name); | ||||
|     explicit Greeter(std::string name); | ||||
| 
 | ||||
|     /**
 | ||||
|      * @brief Creates a localized string containing the greeting | ||||
|      * @param lang the language to greet in | ||||
|      * @return a string containing the greeting | ||||
|      */ | ||||
|     std::string greet(LanguageCode lang = LanguageCode::EN) const; | ||||
| 
 | ||||
|     /// @brief Return an iso date string
 | ||||
|     std::string getIsoDate() const; | ||||
|     [[nodiscard]] std::string greet(LanguageCode lang = LanguageCode::EN) const; | ||||
|   }; | ||||
| 
 | ||||
| }  // namespace greeter
 | ||||
|  |  | |||
|  | @ -1,4 +1,4 @@ | |||
| #include <fmt/chrono.h> | ||||
| #include <fmt/format.h> | ||||
| #include <greeter/greeter.h> | ||||
| 
 | ||||
| using namespace greeter; | ||||
|  | @ -9,17 +9,12 @@ std::string Greeter::greet(LanguageCode lang) const { | |||
|   switch (lang) { | ||||
|     default: | ||||
|     case LanguageCode::EN: | ||||
|       return "Hello, " + name + "!"; | ||||
|       return fmt::format("Hello, {}!", name); | ||||
|     case LanguageCode::DE: | ||||
|       return "Hallo " + name + "!"; | ||||
|       return fmt::format("Hallo {}!", name); | ||||
|     case LanguageCode::ES: | ||||
|       return "¡Hola " + name + "!"; | ||||
|       return fmt::format("¡Hola {}!", name); | ||||
|     case LanguageCode::FR: | ||||
|       return "Bonjour " + name + "!"; | ||||
|       return fmt::format("Bonjour {}!", name); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| std::string Greeter::getIsoDate() const { | ||||
|   using namespace std::literals::chrono_literals; | ||||
|   return fmt::format("{:%H:%M:%S}", 3h + 15min + 30s); | ||||
| } | ||||
|  |  | |||
|  | @ -1,4 +1,4 @@ | |||
| cmake_minimum_required(VERSION 3.14 FATAL_ERROR) | ||||
| cmake_minimum_required(VERSION 3.14...3.19) | ||||
| 
 | ||||
| project(GreeterStandalone LANGUAGES CXX) | ||||
| 
 | ||||
|  | @ -27,4 +27,8 @@ add_executable(GreeterStandalone ${sources}) | |||
| 
 | ||||
| set_target_properties(GreeterStandalone PROPERTIES CXX_STANDARD 17 OUTPUT_NAME "Greeter") | ||||
| 
 | ||||
| target_link_libraries(GreeterStandalone Greeter::Greeter cxxopts) | ||||
| # WORKAROUND for ALIAS target is missing error! CK | ||||
| if(NOT TARGET cxxopts::cxxopts) | ||||
|   add_library(cxxopts::cxxopts ALIAS cxxopts) | ||||
| endif() | ||||
| target_link_libraries(GreeterStandalone Greeter::Greeter cxxopts::cxxopts) | ||||
|  |  | |||
|  | @ -6,15 +6,20 @@ | |||
| #include <string> | ||||
| #include <unordered_map> | ||||
| 
 | ||||
| const std::unordered_map<std::string, greeter::LanguageCode> languages{ | ||||
|     {"en", greeter::LanguageCode::EN}, | ||||
|     {"de", greeter::LanguageCode::DE}, | ||||
|     {"es", greeter::LanguageCode::ES}, | ||||
|     {"fr", greeter::LanguageCode::FR}, | ||||
| }; | ||||
| 
 | ||||
| // NOLINTNEXTLINE(modernize-use-trailing-return-type)
 | ||||
| int main(int argc, char** argv) { | ||||
|   cxxopts::Options options(argv[0], "A program to welcome the world!"); | ||||
|   // prevent warning: initialization of 'languages' with static storage duration may throw an
 | ||||
|   // exception that cannot be caught [cert-err58-cpp]
 | ||||
|   const std::unordered_map<std::string, greeter::LanguageCode> languages{ | ||||
|       {"en", greeter::LanguageCode::EN}, | ||||
|       {"de", greeter::LanguageCode::DE}, | ||||
|       {"es", greeter::LanguageCode::ES}, | ||||
|       {"fr", greeter::LanguageCode::FR}, | ||||
|   }; | ||||
| 
 | ||||
|   // prevent warning: do not use pointer arithmetic
 | ||||
|   // [cppcoreguidelines-pro-bounds-pointer-arithmetic]
 | ||||
|   cxxopts::Options options(*argv, "A program to welcome the world!"); | ||||
| 
 | ||||
|   std::string language; | ||||
|   std::string name; | ||||
|  | @ -33,7 +38,10 @@ int main(int argc, char** argv) { | |||
|   if (result["help"].as<bool>()) { | ||||
|     std::cout << options.help() << std::endl; | ||||
|     return 0; | ||||
|   } else if (result["version"].as<bool>()) { | ||||
|   } | ||||
| 
 | ||||
|   // prevent warning: do not use 'else' after 'return' [readability-else-after-return]
 | ||||
|   if (result["version"].as<bool>()) { | ||||
|     std::cout << "Greeter, version " << GREETER_VERSION << std::endl; | ||||
|     return 0; | ||||
|   } | ||||
|  |  | |||
|  | @ -1,4 +1,4 @@ | |||
| cmake_minimum_required(VERSION 3.14 FATAL_ERROR) | ||||
| cmake_minimum_required(VERSION 3.14...3.19) | ||||
| 
 | ||||
| project(GreeterTests LANGUAGES CXX) | ||||
| 
 | ||||
|  | @ -57,18 +57,11 @@ endif() | |||
| 
 | ||||
| enable_testing() | ||||
| 
 | ||||
| # Note: doctest and similar testing frameworks can automatically configure CMake tests For other | ||||
| # testing frameworks add the tests target instead: | ||||
| if(DEFINED doctest_SOURCE_DIR) | ||||
|   include(${doctest_SOURCE_DIR}/scripts/cmake/doctest.cmake) | ||||
|   doctest_discover_tests(GreeterTests) | ||||
| else() | ||||
|   add_test(greeterTests GreeterTests) | ||||
| endif() | ||||
| add_test(greeterTests GreeterTests) | ||||
| 
 | ||||
| # ---- code coverage ---- | ||||
| 
 | ||||
| if(ENABLE_TEST_COVERAGE) | ||||
| if(ENABLE_TEST_COVERAGE AND NOT Greeter_FOUND) | ||||
|   target_compile_options(Greeter PUBLIC -O0 -g -fprofile-arcs -ftest-coverage) | ||||
|   target_link_options(Greeter PUBLIC -fprofile-arcs -ftest-coverage) | ||||
| endif() | ||||
|  |  | |||
|  | @ -24,8 +24,3 @@ TEST_CASE("Greeter version") { | |||
|   CHECK(std::string(GREETER_VERSION) == std::string("1.0")); | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| TEST_CASE("Greeter date") { | ||||
|   const greeter::Greeter greeter("Tests"); | ||||
|   CHECK(greeter.getIsoDate() == std::string("03:15:30")); | ||||
| } | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue