From c0252b42235409dc5701ccfa1f6fbb96831d5f6b Mon Sep 17 00:00:00 2001 From: ClausKlein Date: Thu, 10 Oct 2024 22:55:42 +0200 Subject: [PATCH 01/13] Modernize cmake files --- CMakeLists.txt | 43 +++++++++++++++++++++++++++++-------------- CMakePresets.json | 8 ++++++-- tests/CMakeLists.txt | 9 +++++++-- 3 files changed, 42 insertions(+), 18 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9e7f909..c1b661b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.14) +cmake_minimum_required(VERSION 3.25...3.30) project(mylib VERSION 1.0.0 DESCRIPTION "Template for C++ library built with CMake" @@ -14,8 +14,8 @@ include(GNUInstallDirs) string(COMPARE EQUAL "${CMAKE_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}" is_top_level) # MYLIB_SHARED_LIBS option (undefined by default) can be used to force shared/static build -option(MYLIB_BUILD_TESTS "Build mylib tests" OFF) -option(MYLIB_BUILD_EXAMPLES "Build mylib examples" OFF) +option(MYLIB_BUILD_TESTS "Build mylib tests" ${is_top_level}) +option(MYLIB_BUILD_EXAMPLES "Build mylib examples" ${is_top_level}) option(MYLIB_BUILD_DOCS "Build mylib documentation" OFF) option(MYLIB_INSTALL "Generate target for installing mylib" ${is_top_level}) set_if_undefined(MYLIB_INSTALL_CMAKEDIR "${CMAKE_INSTALL_LIBDIR}/cmake/mylib" CACHE STRING @@ -30,6 +30,10 @@ if(NOT DEFINED CMAKE_BUILD_TYPE AND NOT DEFINED CMAKE_CONFIGURATION_TYPES) set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo") endif() +# Neither of these two are technically needed, but they make the expectation clear +set_if_undefined(CMAKE_CXX_STANDARD 20) +set_if_undefined(CMAKE_CXX_EXTENSIONS FALSE) + set_if_undefined(CMAKE_CXX_VISIBILITY_PRESET hidden) set_if_undefined(CMAKE_VISIBILITY_INLINES_HIDDEN ON) @@ -67,13 +71,22 @@ source_group(TREE "${CMAKE_CURRENT_SOURCE_DIR}" FILES ${sources}) include(CMakePackageConfigHelpers) -target_sources(mylib PRIVATE ${sources}) + +target_sources(mylib PRIVATE src/mylib.cpp) +target_sources(mylib PUBLIC FILE_SET HEADERS + BASE_DIRS + ${CMAKE_CURRENT_SOURCE_DIR}/include + ${CMAKE_CURRENT_BINARY_DIR}/include + FILES + ${CMAKE_CURRENT_SOURCE_DIR}/include/mylib/mylib.h + ${CMAKE_CURRENT_SOURCE_DIR}/include/mylib/export.h + ${CMAKE_CURRENT_BINARY_DIR}/include/mylib/${export_file_name}) target_compile_definitions(mylib PUBLIC "$<$>:MYLIB_STATIC_DEFINE>") -target_include_directories(mylib - PUBLIC - "$" - "$") +# target_include_directories(mylib +# PUBLIC +# "$" +# "$") set_target_properties(mylib PROPERTIES SOVERSION ${PROJECT_VERSION_MAJOR} @@ -90,13 +103,15 @@ if(MYLIB_INSTALL AND NOT CMAKE_SKIP_INSTALL_RULES) RUNTIME COMPONENT mylib LIBRARY COMPONENT mylib NAMELINK_COMPONENT mylib-dev ARCHIVE COMPONENT mylib-dev + FILE_SET HEADERS INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}") - install(DIRECTORY include/ - TYPE INCLUDE - COMPONENT mylib-dev) - install(FILES "${CMAKE_CURRENT_BINARY_DIR}/include/mylib/${export_file_name}" - COMPONENT mylib-dev - DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/mylib") + + # install(DIRECTORY include/ + # TYPE INCLUDE + # COMPONENT mylib-dev) + # install(FILES "${CMAKE_CURRENT_BINARY_DIR}/include/mylib/${export_file_name}" + # COMPONENT mylib-dev + # DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/mylib") set(targets_file "mylib-shared-targets.cmake") diff --git a/CMakePresets.json b/CMakePresets.json index a8adc4e..38d2bce 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -11,9 +11,13 @@ "description": "Base preset for library developers", "binaryDir": "${sourceDir}/build", "hidden": true, + "generator": "Ninja", "cacheVariables": { - "MYLIB_BUILD_TESTS": "ON", - "MYLIB_BUILD_EXAMPLES": "ON" + "CMAKE_BUILD_TYPE": "Release", + "CMAKE_EXPORT_COMPILE_COMMANDS": true, + "MYLIB_SHARED_LIBS": true, + "MYLIB_BUILD_TESTS": true, + "MYLIB_BUILD_EXAMPLES": true } }, { diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 1492052..6343a84 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.14) +cmake_minimum_required(VERSION 3.25...3.30) project(mylib-tests) #---------------------------------------------------------------------------------------------------------------------- @@ -10,6 +10,10 @@ string(COMPARE EQUAL "${CMAKE_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}" is_top_ if(is_top_level) enable_testing() + + # Neither of these two are technically needed, but they make the expectation clear + set_if_undefined(CMAKE_CXX_STANDARD 20) + set_if_undefined(CMAKE_CXX_EXTENSIONS FALSE) endif() #---------------------------------------------------------------------------------------------------------------------- @@ -17,7 +21,8 @@ endif() #---------------------------------------------------------------------------------------------------------------------- include(FetchContent) -FetchContent_Declare(googletest URL https://github.com/google/googletest/archive/refs/tags/release-1.12.1.tar.gz) +FetchContent_Declare(googletest URL https://github.com/google/googletest/archive/refs/tags/v1.15.2.tar.gz + DOWNLOAD_EXTRACT_TIMESTAMP ON) set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) # do not override parent project's runtime settings on Windows set(INSTALL_GTEST OFF) From dc67259646121c78f3900eb56013b546416ba657 Mon Sep 17 00:00:00 2001 From: ClausKlein Date: Fri, 11 Oct 2024 00:02:05 +0200 Subject: [PATCH 02/13] Formate cmake files --- .cmake-format.yaml | 16 ++++++ CMakeLists.txt | 106 ++++++++++++++++++++++------------------ cmake/silent_copy.cmake | 2 +- cmake/utils.cmake | 27 +++++----- tests/CMakeLists.txt | 13 ++--- 5 files changed, 95 insertions(+), 69 deletions(-) create mode 100644 .cmake-format.yaml diff --git a/.cmake-format.yaml b/.cmake-format.yaml new file mode 100644 index 0000000..c15f2ba --- /dev/null +++ b/.cmake-format.yaml @@ -0,0 +1,16 @@ +format: + line_width: 123 + tab_size: 4 + max_subgroups_hwrap: 4 + max_pargs_hwrap: 4 + max_rows_cmdline: 8 + separate_ctrl_name_with_space: false + separate_fn_name_with_space: false + dangle_parens: true + min_prefix_chars: 8 + max_lines_hwrap: 3 + line_ending: unix +markup: + bullet_char: '*' + enum_char: . + enable_markup: false diff --git a/CMakeLists.txt b/CMakeLists.txt index c1b661b..3f30cbd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,8 +1,5 @@ cmake_minimum_required(VERSION 3.25...3.30) -project(mylib - VERSION 1.0.0 - DESCRIPTION "Template for C++ library built with CMake" - LANGUAGES CXX) +project(mylib VERSION 1.0.0 DESCRIPTION "Template for C++ library built with CMake" LANGUAGES CXX) #---------------------------------------------------------------------------------------------------------------------- # general settings and options @@ -18,8 +15,13 @@ option(MYLIB_BUILD_TESTS "Build mylib tests" ${is_top_level}) option(MYLIB_BUILD_EXAMPLES "Build mylib examples" ${is_top_level}) option(MYLIB_BUILD_DOCS "Build mylib documentation" OFF) option(MYLIB_INSTALL "Generate target for installing mylib" ${is_top_level}) -set_if_undefined(MYLIB_INSTALL_CMAKEDIR "${CMAKE_INSTALL_LIBDIR}/cmake/mylib" CACHE STRING - "Install path for mylib package-related CMake files") +set_if_undefined( + MYLIB_INSTALL_CMAKEDIR + "${CMAKE_INSTALL_LIBDIR}/cmake/mylib" + CACHE + STRING + "Install path for mylib package-related CMake files" +) if(DEFINED MYLIB_SHARED_LIBS) set(BUILD_SHARED_LIBS ${MYLIB_SHARED_LIBS}) @@ -27,7 +29,14 @@ endif() if(NOT DEFINED CMAKE_BUILD_TYPE AND NOT DEFINED CMAKE_CONFIGURATION_TYPES) set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type" FORCE) - set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo") + set_property( + CACHE CMAKE_BUILD_TYPE + PROPERTY STRINGS + "Debug" + "Release" + "MinSizeRel" + "RelWithDebInfo" + ) endif() # Neither of these two are technically needed, but they make the expectation clear @@ -59,10 +68,7 @@ endif() generate_export_header(mylib EXPORT_FILE_NAME include/mylib/${export_file_name}) -set(sources - include/mylib/export.h - include/mylib/mylib.h - src/mylib.cpp) +set(sources include/mylib/export.h include/mylib/mylib.h src/mylib.cpp) source_group(TREE "${CMAKE_CURRENT_SOURCE_DIR}" FILES ${sources}) #---------------------------------------------------------------------------------------------------------------------- @@ -71,16 +77,19 @@ source_group(TREE "${CMAKE_CURRENT_SOURCE_DIR}" FILES ${sources}) include(CMakePackageConfigHelpers) - target_sources(mylib PRIVATE src/mylib.cpp) -target_sources(mylib PUBLIC FILE_SET HEADERS - BASE_DIRS - ${CMAKE_CURRENT_SOURCE_DIR}/include - ${CMAKE_CURRENT_BINARY_DIR}/include - FILES - ${CMAKE_CURRENT_SOURCE_DIR}/include/mylib/mylib.h - ${CMAKE_CURRENT_SOURCE_DIR}/include/mylib/export.h - ${CMAKE_CURRENT_BINARY_DIR}/include/mylib/${export_file_name}) +target_sources( + mylib + PUBLIC FILE_SET + HEADERS + BASE_DIRS + ${CMAKE_CURRENT_SOURCE_DIR}/include + ${CMAKE_CURRENT_BINARY_DIR}/include + FILES + ${CMAKE_CURRENT_SOURCE_DIR}/include/mylib/mylib.h + ${CMAKE_CURRENT_SOURCE_DIR}/include/mylib/export.h + ${CMAKE_CURRENT_BINARY_DIR}/include/mylib/${export_file_name} +) target_compile_definitions(mylib PUBLIC "$<$>:MYLIB_STATIC_DEFINE>") # target_include_directories(mylib @@ -88,23 +97,24 @@ target_compile_definitions(mylib PUBLIC "$<$>:M # "$" # "$") -set_target_properties(mylib PROPERTIES - SOVERSION ${PROJECT_VERSION_MAJOR} - VERSION ${PROJECT_VERSION}) +set_target_properties(mylib PROPERTIES SOVERSION ${PROJECT_VERSION_MAJOR} VERSION ${PROJECT_VERSION}) if(MYLIB_INSTALL AND NOT CMAKE_SKIP_INSTALL_RULES) - configure_package_config_file(cmake/mylib-config.cmake.in mylib-config.cmake - INSTALL_DESTINATION "${MYLIB_INSTALL_CMAKEDIR}") - - write_basic_package_version_file(mylib-config-version.cmake - COMPATIBILITY SameMajorVersion) - - install(TARGETS mylib EXPORT mylib_export - RUNTIME COMPONENT mylib - LIBRARY COMPONENT mylib NAMELINK_COMPONENT mylib-dev - ARCHIVE COMPONENT mylib-dev - FILE_SET HEADERS - INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}") + configure_package_config_file( + cmake/mylib-config.cmake.in mylib-config.cmake INSTALL_DESTINATION "${MYLIB_INSTALL_CMAKEDIR}" + ) + + write_basic_package_version_file(mylib-config-version.cmake COMPATIBILITY SameMajorVersion) + + install(TARGETS mylib + EXPORT mylib_export + RUNTIME COMPONENT mylib + LIBRARY COMPONENT mylib NAMELINK_COMPONENT mylib-dev + ARCHIVE COMPONENT mylib-dev FILE_SET HEADERS COMPONENT mylib-dev + INCLUDES + COMPONENT mylib-dev + DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" + ) # install(DIRECTORY include/ # TYPE INCLUDE @@ -120,16 +130,15 @@ if(MYLIB_INSTALL AND NOT CMAKE_SKIP_INSTALL_RULES) endif() install(EXPORT mylib_export - COMPONENT mylib-dev - FILE "${targets_file}" - DESTINATION "${MYLIB_INSTALL_CMAKEDIR}" - NAMESPACE mylib::) + COMPONENT mylib-dev + FILE "${targets_file}" + DESTINATION "${MYLIB_INSTALL_CMAKEDIR}" + NAMESPACE mylib:: + ) - install(FILES - "${CMAKE_CURRENT_BINARY_DIR}/mylib-config.cmake" - "${CMAKE_CURRENT_BINARY_DIR}/mylib-config-version.cmake" - COMPONENT mylib-dev - DESTINATION "${MYLIB_INSTALL_CMAKEDIR}") + install(FILES "${CMAKE_CURRENT_BINARY_DIR}/mylib-config.cmake" "${CMAKE_CURRENT_BINARY_DIR}/mylib-config-version.cmake" + COMPONENT mylib-dev DESTINATION "${MYLIB_INSTALL_CMAKEDIR}" + ) if(MSVC) set(pdb_file "") @@ -145,10 +154,11 @@ if(MYLIB_INSTALL AND NOT CMAKE_SKIP_INSTALL_RULES) endif() install(FILES "${pdb_file}" - COMPONENT mylib-dev - CONFIGURATIONS Debug RelWithDebInfo - DESTINATION "${pdb_file_destination}" - OPTIONAL) + COMPONENT mylib-dev + CONFIGURATIONS Debug RelWithDebInfo + DESTINATION "${pdb_file_destination}" + OPTIONAL + ) endif() endif() diff --git a/cmake/silent_copy.cmake b/cmake/silent_copy.cmake index 1e3b52b..e296d31 100644 --- a/cmake/silent_copy.cmake +++ b/cmake/silent_copy.cmake @@ -6,7 +6,7 @@ math(EXPR dir_idx "${CMAKE_ARGC} - 1") set(first_file_idx ${dir_idx}) foreach(i RANGE ${dir_idx}) - if ("${CMAKE_ARGV${i}}" STREQUAL "-P") + if("${CMAKE_ARGV${i}}" STREQUAL "-P") math(EXPR first_file_idx "${i} + 2") break() endif() diff --git a/cmake/utils.cmake b/cmake/utils.cmake index b3d36d4..5988aa5 100644 --- a/cmake/utils.cmake +++ b/cmake/utils.cmake @@ -23,10 +23,11 @@ function(win_copy_deps_to_target_dir target) if(CMAKE_MAJOR_VERSION GREATER 3 OR CMAKE_MINOR_VERSION GREATER_EQUAL 21) set(has_runtime_dll_genex YES) - add_custom_command(TARGET ${target} POST_BUILD - COMMAND ${CMAKE_COMMAND} -P "${mylib_SOURCE_DIR}/cmake/silent_copy.cmake" - "$" "$" - COMMAND_EXPAND_LISTS) + add_custom_command( + TARGET ${target} POST_BUILD COMMAND ${CMAKE_COMMAND} -P "${mylib_SOURCE_DIR}/cmake/silent_copy.cmake" + "$" "$" + COMMAND_EXPAND_LISTS + ) endif() foreach(dep ${ARGN}) @@ -34,15 +35,17 @@ function(win_copy_deps_to_target_dir target) if(dep_type STREQUAL "SHARED_LIBRARY") if(NOT has_runtime_dll_genex) - add_custom_command(TARGET ${target} POST_BUILD - COMMAND ${CMAKE_COMMAND} -P "${mylib_SOURCE_DIR}/cmake/silent_copy.cmake" - "$" "$" "$" - COMMAND_EXPAND_LISTS) + add_custom_command( + TARGET ${target} POST_BUILD + COMMAND ${CMAKE_COMMAND} -P "${mylib_SOURCE_DIR}/cmake/silent_copy.cmake" "$" + "$" "$" COMMAND_EXPAND_LISTS + ) else() - add_custom_command(TARGET ${target} POST_BUILD - COMMAND ${CMAKE_COMMAND} -P "${mylib_SOURCE_DIR}/cmake/silent_copy.cmake" - "$" "$" - COMMAND_EXPAND_LISTS) + add_custom_command( + TARGET ${target} POST_BUILD COMMAND ${CMAKE_COMMAND} -P "${mylib_SOURCE_DIR}/cmake/silent_copy.cmake" + "$" "$" + COMMAND_EXPAND_LISTS + ) endif() endif() endforeach() diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 6343a84..1be6be8 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -21,8 +21,9 @@ endif() #---------------------------------------------------------------------------------------------------------------------- include(FetchContent) -FetchContent_Declare(googletest URL https://github.com/google/googletest/archive/refs/tags/v1.15.2.tar.gz - DOWNLOAD_EXTRACT_TIMESTAMP ON) +FetchContent_Declare( + googletest URL https://github.com/google/googletest/archive/refs/tags/v1.15.2.tar.gz DOWNLOAD_EXTRACT_TIMESTAMP ON +) set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) # do not override parent project's runtime settings on Windows set(INSTALL_GTEST OFF) @@ -45,8 +46,7 @@ endif() # tests sources #---------------------------------------------------------------------------------------------------------------------- -set(sources - add_test.cpp) +set(sources add_test.cpp) source_group(TREE "${CMAKE_CURRENT_SOURCE_DIR}" FILES ${sources}) #---------------------------------------------------------------------------------------------------------------------- @@ -56,10 +56,7 @@ source_group(TREE "${CMAKE_CURRENT_SOURCE_DIR}" FILES ${sources}) add_executable(mylib-tests) target_sources(mylib-tests PRIVATE ${sources}) -target_link_libraries(mylib-tests - PRIVATE - mylib::mylib - gtest_main) +target_link_libraries(mylib-tests PRIVATE mylib::mylib gtest_main) if(NOT is_top_level) win_copy_deps_to_target_dir(mylib-tests mylib::mylib) From 7bf4c3e95276990c17844650bedcba8915f0850a Mon Sep 17 00:00:00 2001 From: ClausKlein Date: Fri, 11 Oct 2024 14:57:41 +0200 Subject: [PATCH 03/13] Add cmake workflow preset --- .clang-format | 7 ++++ CMakeLists.txt | 1 + CMakePresets.json | 82 ++++++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 85 insertions(+), 5 deletions(-) diff --git a/.clang-format b/.clang-format index 1fdaf20..78f8042 100644 --- a/.clang-format +++ b/.clang-format @@ -1,4 +1,11 @@ --- +BasedOnStyle: Google +ConstructorInitializerIndentWidth: 2 +ContinuationIndentWidth: 2 +IndentWidth: 2 +TabWidth: 2 +UseTab: Never +--- Language: Cpp Standard: c++17 UseTab: Never diff --git a/CMakeLists.txt b/CMakeLists.txt index 3f30cbd..7940763 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -160,6 +160,7 @@ if(MYLIB_INSTALL AND NOT CMAKE_SKIP_INSTALL_RULES) OPTIONAL ) endif() + include(CPack) endif() #---------------------------------------------------------------------------------------------------------------------- diff --git a/CMakePresets.json b/CMakePresets.json index 38d2bce..14a4379 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -1,8 +1,8 @@ { - "version": 3, + "version": 6, "cmakeMinimumRequired": { "major": 3, - "minor": 14, + "minor": 25, "patch": 0 }, "configurePresets": [ @@ -24,19 +24,91 @@ "name": "dev-win", "description": "Windows preset for library developers", "hidden": false, - "inherits": ["dev"], + "inherits": [ + "dev" + ], "cacheVariables": { "CMAKE_CXX_FLAGS": "/W4 /EHsc /w14242 /w14254 /w14263 /w14265 /w14287 /w14289 /w14296 /w14311 /w14545 /w14546 /w14547 /w14549 /w14555 /w14640 /w14826 /w14928 /WX" + }, + "condition": { + "type": "equals", + "lhs": "${hostSystemName}", + "rhs": "Windows" } }, { - "name": "dev-linux", + "name": "Release", "description": "Linux preset for library developers", "hidden": false, - "inherits": ["dev"], + "inherits": [ + "dev" + ], "cacheVariables": { "CMAKE_CXX_FLAGS": "-Wall -Wextra -Wpedantic -Wshadow -Wconversion -Wsign-conversion -Wcast-align -Wcast-qual -Wnull-dereference -Woverloaded-virtual -Wformat=2 -Werror" + }, + "condition": { + "type": "notEquals", + "lhs": "${hostSystemName}", + "rhs": "Windows" } } + ], + "buildPresets": [ + { + "name": "Release", + "configurePreset": "Release" + }, + { + "name": "install", + "configurePreset": "Release", + "targets": [ + "install" + ] + } + ], + "testPresets": [ + { + "name": "Release", + "configurePreset": "Release", + "output": { + "outputOnFailure": true + }, + "execution": { + "noTestsAction": "error", + "stopOnFailure": true + } + } + ], + "packagePresets": [ + { + "name": "Release", + "configurePreset": "Release", + "generators": [ + "TGZ" + ] + } + ], + "workflowPresets": [ + { + "name": "Release", + "steps": [ + { + "type": "configure", + "name": "Release" + }, + { + "type": "build", + "name": "Release" + }, + { + "type": "test", + "name": "Release" + }, + { + "type": "package", + "name": "Release" + } + ] + } ] } From c3d704359fc0eb6c45f64535d69f81d6c115bd3c Mon Sep 17 00:00:00 2001 From: ClausKlein Date: Fri, 11 Oct 2024 20:07:51 +0200 Subject: [PATCH 04/13] Restucture cmake presets --- .gitignore | 1 + CMakeDarwinPresets.json | 11 +++++ CMakeGenericPresets.json | 86 +++++++++++++++++++++++++++++++++ CMakeLinuxPresets.json | 38 +++++++++++++++ CMakePresets.json | 102 +++++++++++++++++++-------------------- CMakeWindowsPresets.json | 36 ++++++++++++++ 6 files changed, 222 insertions(+), 52 deletions(-) create mode 100644 CMakeDarwinPresets.json create mode 100644 CMakeGenericPresets.json create mode 100644 CMakeLinuxPresets.json create mode 100644 CMakeWindowsPresets.json diff --git a/.gitignore b/.gitignore index d484323..a0fd4da 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ build*/ _build*/ cmake-build*/ +/stagedir/ # CMake CMakeUserPresets.json diff --git a/CMakeDarwinPresets.json b/CMakeDarwinPresets.json new file mode 100644 index 0000000..7efefcd --- /dev/null +++ b/CMakeDarwinPresets.json @@ -0,0 +1,11 @@ +{ + "version": 4, + "cmakeMinimumRequired": { + "major": 3, + "minor": 23, + "patch": 0 + }, + "include": [ + "CMakeLinuxPresets.json" + ] +} diff --git a/CMakeGenericPresets.json b/CMakeGenericPresets.json new file mode 100644 index 0000000..83b4b1f --- /dev/null +++ b/CMakeGenericPresets.json @@ -0,0 +1,86 @@ +{ + "version": 9, + "cmakeMinimumRequired": { + "major": 3, + "minor": 30, + "patch": 0 + }, + "configurePresets": [ + { + "name": "default", + "description": "Base preset for library developers", + "binaryDir": "${sourceDir}/build", + "hidden": true, + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Debug", + "CMAKE_EXPORT_COMPILE_COMMANDS": true, + "MYLIB_SHARED_LIBS": true, + "MYLIB_BUILD_TESTS": true, + "MYLIB_BUILD_EXAMPLES": true + } + }, + { + "name": "cmake-pedantic", + "hidden": true, + "inherits": "default", + "warnings": { + "dev": true, + "deprecated": true, + "uninitialized": true, + "unusedCli": true, + "systemVars": false + }, + "errors": { + "dev": true, + "deprecated": true + } + }, + { + "name": "dev-mode", + "hidden": true, + "inherits": "cmake-pedantic", + "installDir": "${sourceDir}/stagedir", + "cacheVariables": { + "CMAKE_PREFIX_PATH": { + "type": "path", + "value": "${sourceDir}/stagedir" + }, + "BUILD_SHARED_LIBS": false, + "BUILD_TESTING": true + } + }, + { + "name": "cppcheck", + "hidden": true, + "cacheVariables": { + "CMAKE_CXX_CPPCHECK": "cppcheck;--inline-suppr" + } + }, + { + "name": "clang-tidy", + "hidden": true, + "cacheVariables": { + "CMAKE_CXX_CLANG_TIDY": "clang-tidy;--header-filter=^${sourceDir}/" + } + }, + { + "name": "ci-std", + "description": "This preset makes sure the project actually builds with at least the specified standard", + "hidden": true, + "cacheVariables": { + "CMAKE_CXX_EXTENSIONS": false, + "CMAKE_CXX_STANDARD": "20", + "CMAKE_CXX_STANDARD_REQUIRED": true + } + }, + { + "name": "ci-build", + "binaryDir": "${sourceDir}/build", + "generator": "Ninja", + "hidden": true, + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Release" + } + } + ] +} diff --git a/CMakeLinuxPresets.json b/CMakeLinuxPresets.json new file mode 100644 index 0000000..59f12af --- /dev/null +++ b/CMakeLinuxPresets.json @@ -0,0 +1,38 @@ +{ + "version": 9, + "cmakeMinimumRequired": { + "major": 3, + "minor": 30, + "patch": 0 + }, + "include": [ + "CMakeGenericPresets.json" + ], + "configurePresets": [ + { + "name": "Release", + "description": "Possix preset for library developers", + "inherits": [ + "ci-build", + "ci-std" + ], + "cacheVariables": { + "CMAKE_CXX_FLAGS": "-Wall -Wextra -Wpedantic -Wshadow -Wconversion -Wsign-conversion -Wcast-align -Wcast-qual -Wnull-dereference -Woverloaded-virtual -Wformat=2 -Werror" + }, + "condition": { + "type": "notEquals", + "lhs": "${hostSystemName}", + "rhs": "Windows" + } + }, + { + "name": "Debug", + "description": "Possix preset for library developers", + "inherits": [ + "ci-std", + "dev-mode", + "clang-tidy" + ] + } + ] +} diff --git a/CMakePresets.json b/CMakePresets.json index 14a4379..805bd8d 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -1,72 +1,42 @@ { - "version": 6, + "version": 9, "cmakeMinimumRequired": { "major": 3, - "minor": 25, + "minor": 30, "patch": 0 }, - "configurePresets": [ - { - "name": "dev", - "description": "Base preset for library developers", - "binaryDir": "${sourceDir}/build", - "hidden": true, - "generator": "Ninja", - "cacheVariables": { - "CMAKE_BUILD_TYPE": "Release", - "CMAKE_EXPORT_COMPILE_COMMANDS": true, - "MYLIB_SHARED_LIBS": true, - "MYLIB_BUILD_TESTS": true, - "MYLIB_BUILD_EXAMPLES": true - } - }, - { - "name": "dev-win", - "description": "Windows preset for library developers", - "hidden": false, - "inherits": [ - "dev" - ], - "cacheVariables": { - "CMAKE_CXX_FLAGS": "/W4 /EHsc /w14242 /w14254 /w14263 /w14265 /w14287 /w14289 /w14296 /w14311 /w14545 /w14546 /w14547 /w14549 /w14555 /w14640 /w14826 /w14928 /WX" - }, - "condition": { - "type": "equals", - "lhs": "${hostSystemName}", - "rhs": "Windows" - } - }, - { - "name": "Release", - "description": "Linux preset for library developers", - "hidden": false, - "inherits": [ - "dev" - ], - "cacheVariables": { - "CMAKE_CXX_FLAGS": "-Wall -Wextra -Wpedantic -Wshadow -Wconversion -Wsign-conversion -Wcast-align -Wcast-qual -Wnull-dereference -Woverloaded-virtual -Wformat=2 -Werror" - }, - "condition": { - "type": "notEquals", - "lhs": "${hostSystemName}", - "rhs": "Windows" - } - } + "include": [ + "CMake${hostSystemName}Presets.json" ], "buildPresets": [ + { + "name": "Debug", + "configurePreset": "Debug" + }, { "name": "Release", "configurePreset": "Release" }, { - "name": "install", - "configurePreset": "Release", + "name": "install-Debug", + "configurePreset": "Debug", "targets": [ "install" ] } ], "testPresets": [ + { + "name": "Debug", + "configurePreset": "Debug", + "output": { + "outputOnFailure": true + }, + "execution": { + "noTestsAction": "ignore", + "stopOnFailure": true + } + }, { "name": "Release", "configurePreset": "Release", @@ -75,11 +45,18 @@ }, "execution": { "noTestsAction": "error", - "stopOnFailure": true + "stopOnFailure": false } } ], "packagePresets": [ + { + "name": "Debug", + "configurePreset": "Debug", + "generators": [ + "TGZ" + ] + }, { "name": "Release", "configurePreset": "Release", @@ -89,6 +66,27 @@ } ], "workflowPresets": [ + { + "name": "Debug", + "steps": [ + { + "type": "configure", + "name": "Debug" + }, + { + "type": "build", + "name": "Debug" + }, + { + "type": "test", + "name": "Debug" + }, + { + "type": "build", + "name": "install-Debug" + } + ] + }, { "name": "Release", "steps": [ diff --git a/CMakeWindowsPresets.json b/CMakeWindowsPresets.json new file mode 100644 index 0000000..c917934 --- /dev/null +++ b/CMakeWindowsPresets.json @@ -0,0 +1,36 @@ +{ + "version": 9, + "cmakeMinimumRequired": { + "major": 3, + "minor": 30, + "patch": 0 + }, + "include": [ + "CMakeGenericPresets.json" + ], + "configurePresets": [ + { + "name": "Release", + "description": "Windows preset for library developers", + "inherits": [ + "ci-build", + "ci-std" + ], + "cacheVariables": { + "CMAKE_CXX_FLAGS": "/W4 /EHsc /w14242 /w14254 /w14263 /w14265 /w14287 /w14289 /w14296 /w14311 /w14545 /w14546 /w14547 /w14549 /w14555 /w14640 /w14826 /w14928 /WX" + }, + "condition": { + "type": "equals", + "lhs": "${hostSystemName}", + "rhs": "Windows" + } + }, + { + "name": "Debug", + "description": "Windows preset for library developers", + "inherits": [ + "ci-std", + "dev-mode" + } + ] +} From f5e49376760565aa6ceabda98e06f47ab77ab1ae Mon Sep 17 00:00:00 2001 From: ClausKlein Date: Fri, 11 Oct 2024 20:31:52 +0200 Subject: [PATCH 05/13] Be less verbose --- CMakeGenericPresets.json | 3 +++ tests/CMakeLists.txt | 1 + 2 files changed, 4 insertions(+) diff --git a/CMakeGenericPresets.json b/CMakeGenericPresets.json index 83b4b1f..56f204b 100644 --- a/CMakeGenericPresets.json +++ b/CMakeGenericPresets.json @@ -14,6 +14,7 @@ "cacheVariables": { "CMAKE_BUILD_TYPE": "Debug", "CMAKE_EXPORT_COMPILE_COMMANDS": true, + "CMAKE_MESSAGE_LOG_LEVEL": "WARNING", "MYLIB_SHARED_LIBS": true, "MYLIB_BUILD_TESTS": true, "MYLIB_BUILD_EXAMPLES": true @@ -45,6 +46,7 @@ "type": "path", "value": "${sourceDir}/stagedir" }, + "CMAKE_MESSAGE_LOG_LEVEL": "STATUS", "BUILD_SHARED_LIBS": false, "BUILD_TESTING": true } @@ -78,6 +80,7 @@ "binaryDir": "${sourceDir}/build", "generator": "Ninja", "hidden": true, + "inherits": "default", "cacheVariables": { "CMAKE_BUILD_TYPE": "Release" } diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 1be6be8..6e26799 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -23,6 +23,7 @@ endif() include(FetchContent) FetchContent_Declare( googletest URL https://github.com/google/googletest/archive/refs/tags/v1.15.2.tar.gz DOWNLOAD_EXTRACT_TIMESTAMP ON + DOWNLOAD_NO_PROGRESS ON ) set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) # do not override parent project's runtime settings on Windows From 933e43cf885a20ca0ac3f2c996e40eeccc49e8ff Mon Sep 17 00:00:00 2001 From: ClausKlein Date: Fri, 11 Oct 2024 21:25:44 +0200 Subject: [PATCH 06/13] Add github CI workflow --- .github/workflows/ci.yml | 69 ++++++++++++++++++++++++++++++++++++++++ CMakeGenericPresets.json | 4 +-- CMakeLinuxPresets.json | 2 +- CMakeWindowsPresets.json | 1 + 4 files changed, 73 insertions(+), 3 deletions(-) create mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..650b857 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,69 @@ +--- +name: Continuous Integration + +on: + push: + branches: + - master + - develop + + pull_request: + branches: + - develop + +jobs: + test: + strategy: + fail-fast: false + + matrix: + os: [macos-15, ubuntu-24.04, windows-2022] + + # type: [shared, static] + + # include: + # - {type: shared, shared: YES} + # - {type: static, shared: NO} + + runs-on: ${{ matrix.os }} + + steps: + - uses: actions/checkout@v4 + + - name: Install static analyzers + if: matrix.os == 'macos-15' + run: >- + brew install llvm@18 cmake ninja + + - name: Install static analyzers + if: matrix.os == 'ubuntu-24.04' + run: >- + sudo apt-get install clang-tidy-18 ninja-build -y -q + + sudo update-alternatives --install + /usr/bin/clang-tidy clang-tidy + /usr/bin/clang-tidy-18 140 + + - name: Setup MultiToolTask + if: matrix.os == 'windows-2022' + run: | + Add-Content "$env:GITHUB_ENV" 'UseMultiToolTask=true' + Add-Content "$env:GITHUB_ENV" 'EnforceProcessCountAcrossBuilds=true' + + - name: Configure + shell: pwsh + run: cmake --preset=Debug # -D BUILD_SHARED_LIBS=${{ matrix.shared }} + + - name: Setup PATH + if: matrix.os == 'windows-2022' && matrix.type == 'shared' + run: Add-Content "$env:GITHUB_PATH" "$(Get-Location)\build\Debug" + + - name: Build + run: cmake --build build --config Debug -j 2 + + - name: Test + working-directory: build + run: ctest --output-on-failure --no-tests=error -C Debug -j 2 + + - name: Install + run: cmake --install build --config Debug --prefix prefix diff --git a/CMakeGenericPresets.json b/CMakeGenericPresets.json index 56f204b..675389a 100644 --- a/CMakeGenericPresets.json +++ b/CMakeGenericPresets.json @@ -27,8 +27,8 @@ "warnings": { "dev": true, "deprecated": true, - "uninitialized": true, - "unusedCli": true, + "uninitialized": false, + "unusedCli": false, "systemVars": false }, "errors": { diff --git a/CMakeLinuxPresets.json b/CMakeLinuxPresets.json index 59f12af..d22e4f4 100644 --- a/CMakeLinuxPresets.json +++ b/CMakeLinuxPresets.json @@ -17,7 +17,7 @@ "ci-std" ], "cacheVariables": { - "CMAKE_CXX_FLAGS": "-Wall -Wextra -Wpedantic -Wshadow -Wconversion -Wsign-conversion -Wcast-align -Wcast-qual -Wnull-dereference -Woverloaded-virtual -Wformat=2 -Werror" + "CMAKE_CXX_FLAGS": "-Wall -Wextra -Wpedantic -Wshadow -Wconversion -Wsign-conversion -Wcast-align -Wcast-qual -Wno-null-dereference -Woverloaded-virtual -Wformat=2 -Werror" }, "condition": { "type": "notEquals", diff --git a/CMakeWindowsPresets.json b/CMakeWindowsPresets.json index c917934..f662365 100644 --- a/CMakeWindowsPresets.json +++ b/CMakeWindowsPresets.json @@ -31,6 +31,7 @@ "inherits": [ "ci-std", "dev-mode" + ] } ] } From afda4ed2c135d0b58944d5da9eafb410b0678e3e Mon Sep 17 00:00:00 2001 From: ClausKlein Date: Fri, 11 Oct 2024 21:57:35 +0200 Subject: [PATCH 07/13] Use setup-cpp github action --- .github/workflows/ci.yml | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 650b857..4a325af 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -30,10 +30,14 @@ jobs: steps: - uses: actions/checkout@v4 - - name: Install static analyzers - if: matrix.os == 'macos-15' - run: >- - brew install llvm@18 cmake ninja + - name: Setup Cpp + if: startsWith(matrix.os, 'macos') + uses: aminya/setup-cpp@v1 + with: + compiler: llvm-18 + clangtidy: true + cmake: true + ninja: true - name: Install static analyzers if: matrix.os == 'ubuntu-24.04' From 16cf2ddb105245ace17da276851643808d296bdd Mon Sep 17 00:00:00 2001 From: ClausKlein Date: Fri, 11 Oct 2024 22:09:19 +0200 Subject: [PATCH 08/13] Build Debug and Release on CI --- .github/workflows/ci.yml | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4a325af..e33a40e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,11 +19,12 @@ jobs: matrix: os: [macos-15, ubuntu-24.04, windows-2022] - # type: [shared, static] + type: [Debug, Release] + # link: [shared, static] # include: - # - {type: shared, shared: YES} - # - {type: static, shared: NO} + # - {link: shared, shared: YES} + # - {link: static, shared: NO} runs-on: ${{ matrix.os }} @@ -34,7 +35,7 @@ jobs: if: startsWith(matrix.os, 'macos') uses: aminya/setup-cpp@v1 with: - compiler: llvm-18 + # compiler: llvm-18 clangtidy: true cmake: true ninja: true @@ -56,18 +57,18 @@ jobs: - name: Configure shell: pwsh - run: cmake --preset=Debug # -D BUILD_SHARED_LIBS=${{ matrix.shared }} + run: cmake --preset=${{ matrix.type }} - name: Setup PATH if: matrix.os == 'windows-2022' && matrix.type == 'shared' - run: Add-Content "$env:GITHUB_PATH" "$(Get-Location)\build\Debug" + run: Add-Content "$env:GITHUB_PATH" "$(Get-Location)\build\${{ matrix.type }}" - name: Build - run: cmake --build build --config Debug -j 2 + run: cmake --build build --config ${{ matrix.type }} -j 2 - name: Test working-directory: build - run: ctest --output-on-failure --no-tests=error -C Debug -j 2 + run: ctest --output-on-failure --no-tests=error -C ${{ matrix.type }} - name: Install - run: cmake --install build --config Debug --prefix prefix + run: cmake --install build --prefix prefix --config ${{ matrix.type }} From 6d6508e6b93b3f66bfac7f0943091b66dc809322 Mon Sep 17 00:00:00 2001 From: ClausKlein Date: Fri, 11 Oct 2024 22:24:20 +0200 Subject: [PATCH 09/13] Use Visual Studio 17 2022 on windows CI --- CMakeGenericPresets.json | 3 ++- CMakeLinuxPresets.json | 2 +- CMakeWindowsPresets.json | 6 ++++-- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/CMakeGenericPresets.json b/CMakeGenericPresets.json index 675389a..dc0c43c 100644 --- a/CMakeGenericPresets.json +++ b/CMakeGenericPresets.json @@ -10,6 +10,7 @@ "name": "default", "description": "Base preset for library developers", "binaryDir": "${sourceDir}/build", + "generator": "Ninja", "hidden": true, "cacheVariables": { "CMAKE_BUILD_TYPE": "Debug", @@ -77,9 +78,9 @@ }, { "name": "ci-build", + "hidden": true, "binaryDir": "${sourceDir}/build", "generator": "Ninja", - "hidden": true, "inherits": "default", "cacheVariables": { "CMAKE_BUILD_TYPE": "Release" diff --git a/CMakeLinuxPresets.json b/CMakeLinuxPresets.json index d22e4f4..f61874b 100644 --- a/CMakeLinuxPresets.json +++ b/CMakeLinuxPresets.json @@ -29,7 +29,7 @@ "name": "Debug", "description": "Possix preset for library developers", "inherits": [ - "ci-std", + "Release", "dev-mode", "clang-tidy" ] diff --git a/CMakeWindowsPresets.json b/CMakeWindowsPresets.json index f662365..89145f8 100644 --- a/CMakeWindowsPresets.json +++ b/CMakeWindowsPresets.json @@ -16,6 +16,7 @@ "ci-build", "ci-std" ], + "generator": "Visual Studio 17 2022", "cacheVariables": { "CMAKE_CXX_FLAGS": "/W4 /EHsc /w14242 /w14254 /w14263 /w14265 /w14287 /w14289 /w14296 /w14311 /w14545 /w14546 /w14547 /w14549 /w14555 /w14640 /w14826 /w14928 /WX" }, @@ -29,9 +30,10 @@ "name": "Debug", "description": "Windows preset for library developers", "inherits": [ - "ci-std", + "Release", "dev-mode" - ] + ], + "generator": "Visual Studio 17 2022" } ] } From 9d446d15f15826044f33afa939947061daab8e20 Mon Sep 17 00:00:00 2001 From: ClausKlein Date: Sat, 12 Oct 2024 14:28:58 +0200 Subject: [PATCH 10/13] Update Readme and Debug preset --- CMakeGenericPresets.json | 5 ++--- CMakeLists.txt | 12 ----------- README.md | 45 +++++++++++++++++++++++++++++++++------- 3 files changed, 39 insertions(+), 23 deletions(-) diff --git a/CMakeGenericPresets.json b/CMakeGenericPresets.json index dc0c43c..20481ff 100644 --- a/CMakeGenericPresets.json +++ b/CMakeGenericPresets.json @@ -13,10 +13,8 @@ "generator": "Ninja", "hidden": true, "cacheVariables": { - "CMAKE_BUILD_TYPE": "Debug", "CMAKE_EXPORT_COMPILE_COMMANDS": true, "CMAKE_MESSAGE_LOG_LEVEL": "WARNING", - "MYLIB_SHARED_LIBS": true, "MYLIB_BUILD_TESTS": true, "MYLIB_BUILD_EXAMPLES": true } @@ -47,6 +45,7 @@ "type": "path", "value": "${sourceDir}/stagedir" }, + "CMAKE_BUILD_TYPE": "Debug", "CMAKE_MESSAGE_LOG_LEVEL": "STATUS", "BUILD_SHARED_LIBS": false, "BUILD_TESTING": true @@ -63,7 +62,7 @@ "name": "clang-tidy", "hidden": true, "cacheVariables": { - "CMAKE_CXX_CLANG_TIDY": "clang-tidy;--header-filter=^${sourceDir}/" + "CMAKE_CXX_CLANG_TIDY": "clang-tidy;--header-filter=^${sourceDir}/include" } }, { diff --git a/CMakeLists.txt b/CMakeLists.txt index 7940763..c610f28 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -92,11 +92,6 @@ target_sources( ) target_compile_definitions(mylib PUBLIC "$<$>:MYLIB_STATIC_DEFINE>") -# target_include_directories(mylib -# PUBLIC -# "$" -# "$") - set_target_properties(mylib PROPERTIES SOVERSION ${PROJECT_VERSION_MAJOR} VERSION ${PROJECT_VERSION}) if(MYLIB_INSTALL AND NOT CMAKE_SKIP_INSTALL_RULES) @@ -116,13 +111,6 @@ if(MYLIB_INSTALL AND NOT CMAKE_SKIP_INSTALL_RULES) DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" ) - # install(DIRECTORY include/ - # TYPE INCLUDE - # COMPONENT mylib-dev) - # install(FILES "${CMAKE_CURRENT_BINARY_DIR}/include/mylib/${export_file_name}" - # COMPONENT mylib-dev - # DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/mylib") - set(targets_file "mylib-shared-targets.cmake") if(NOT BUILD_SHARED_LIBS) diff --git a/README.md b/README.md index 8987554..7463450 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,42 @@ # Overview -Template repository to be used as a base for creating C++ libraries built with CMake. This repository provides: -* Commonly accepted directory layout: `cmake` for CMake utilities and package config, `include/` for public headers, `src` for library sources and private headers, `examples` and `tests` for library examples and tests correspondingly. +Template repository to be used as a base for creating C++ libraries built with CMake. + +## This repository provides: + +* Commonly accepted directory layout: + + - `cmake` for CMake utilities and package config + - `include/` for public headers + - `src` for library sources and private headers + - `examples` + - `tests` for library examples and tests correspondingly + * `CMakeLists.txt` files thoroughly implemented with the following ideas in mind: - * user should be able to build library both as subproject (probably fetched with CMake's [FetchContent_MakeAvailable](https://cmake.org/cmake/help/latest/module/FetchContent.html)) and as a stand-alone project - * user should be able to build examples/tests as part of the library build or as a stand-alone projects - * multi-configuration CMake generators should be supported - * package systems (conan, vcpkg and others) should be respected, which means that library `CMakeLists.txt` file should contain only **build requirements**, i.e. should not hardcode any compiler/linker flags unless they are absolutely required to build the library -* Basic [preset](https://cmake.org/cmake/help/latest/manual/cmake-presets.7.html) file `CMakePresets.json` which is a modern way (since CMake 3.19) for specifying build options (instead of hardcoding them in the `CMakeLists.txt` or setting on the command line) + + - user should be able to build library both as subproject (probably fetched with CMake's + [FetchContent_MakeAvailable](https://cmake.org/cmake/help/latest/module/FetchContent.html)) and as a stand-alone project + - user should be able to build examples/tests as part of the library build or as a stand-alone projects + - multi-configuration CMake generators should be supported + - package systems (conan, vcpkg and others) should be respected, which means that library `CMakeLists.txt` file should contain + only **build requirements**, i.e. should not hardcode any compiler/linker flags unless they are absolutely required to build + the library + +* [CMake Workflow preset](https://cmake.org/cmake/help/latest/manual/cmake-presets.7.html) file `CMakePresets.json` which is a + modern way (since CMake 3.25) for specifying build options (instead of hardcoding them in the `CMakeLists.txt` or setting + on the command line) + * My personal `.clang-format` for code-style worth trying -Note, that I prefer [googletest](https://github.com/google/googletest) as a testing framework so it's the one used in this repository. Still it's not a big deal to replace it with any other of your choice. +* And too `.cmake-format.yml` to format the CMake files + +Note, that I prefer [googletest](https://github.com/google/googletest) as a testing framework so it's the one used in this +repository. Still it's not a big deal to replace it with any other of your choice. + + +## Links + +* Anton Pantyukhin - [Modern CMake tutorial for C++ library developers](https://medium.com/@pananton/modern-cmake-tutorial-for-c-library-developers-12f3bf57dc87) +* Dominik Berner - [Organizing CMake presets](https://dominikberner.ch/cmake-presets-best-practices/) +* Craig Scott -[C++20 Modules, CMake, And Shared Libraries](https://crascit.com/category/cmake/) +* [cmake-init - CMake project generator](https://github.com/friendlyanon/cmake-init) that creates good `CMakeLists.tx` files From 20e6a1e9631b6debc1e07248851c85325de93563 Mon Sep 17 00:00:00 2001 From: ClausKlein Date: Sat, 12 Oct 2024 14:44:10 +0200 Subject: [PATCH 11/13] Release build shared libs too --- CMakeGenericPresets.json | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/CMakeGenericPresets.json b/CMakeGenericPresets.json index 20481ff..89abee1 100644 --- a/CMakeGenericPresets.json +++ b/CMakeGenericPresets.json @@ -14,9 +14,7 @@ "hidden": true, "cacheVariables": { "CMAKE_EXPORT_COMPILE_COMMANDS": true, - "CMAKE_MESSAGE_LOG_LEVEL": "WARNING", - "MYLIB_BUILD_TESTS": true, - "MYLIB_BUILD_EXAMPLES": true + "CMAKE_MESSAGE_LOG_LEVEL": "WARNING" } }, { @@ -45,10 +43,10 @@ "type": "path", "value": "${sourceDir}/stagedir" }, - "CMAKE_BUILD_TYPE": "Debug", - "CMAKE_MESSAGE_LOG_LEVEL": "STATUS", "BUILD_SHARED_LIBS": false, - "BUILD_TESTING": true + "BUILD_TESTING": true, + "CMAKE_BUILD_TYPE": "Debug", + "CMAKE_MESSAGE_LOG_LEVEL": "STATUS" } }, { @@ -82,6 +80,7 @@ "generator": "Ninja", "inherits": "default", "cacheVariables": { + "BUILD_SHARED_LIBS": true, "CMAKE_BUILD_TYPE": "Release" } } From c45f20ecb55f8cc22ddce38ff3a2fabb54bf09bc Mon Sep 17 00:00:00 2001 From: Claus Klein Date: Sun, 13 Oct 2024 13:58:54 +0200 Subject: [PATCH 12/13] Use ctest --build-and-test (#1) * Use ctest --build-and-test * Move sub presets to cmake/presets * Final cleanup --- .cmake-format.yaml | 2 +- CMakeLists.txt | 24 +++++----- CMakePresets.json | 2 +- .../presets/CMakeDarwinPresets.json | 0 .../presets/CMakeGenericPresets.json | 0 .../presets/CMakeLinuxPresets.json | 2 +- .../presets/CMakeWindowsPresets.json | 4 +- examples/add/CMakeLists.txt | 9 ++-- tests/CMakeLists.txt | 44 +++++++++++++------ 9 files changed, 52 insertions(+), 35 deletions(-) rename CMakeDarwinPresets.json => cmake/presets/CMakeDarwinPresets.json (100%) rename CMakeGenericPresets.json => cmake/presets/CMakeGenericPresets.json (100%) rename CMakeLinuxPresets.json => cmake/presets/CMakeLinuxPresets.json (100%) rename CMakeWindowsPresets.json => cmake/presets/CMakeWindowsPresets.json (95%) diff --git a/.cmake-format.yaml b/.cmake-format.yaml index c15f2ba..988038f 100644 --- a/.cmake-format.yaml +++ b/.cmake-format.yaml @@ -1,5 +1,5 @@ format: - line_width: 123 + line_width: 120 tab_size: 4 max_subgroups_hwrap: 4 max_pargs_hwrap: 4 diff --git a/CMakeLists.txt b/CMakeLists.txt index c610f28..1768b68 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,13 +8,11 @@ project(mylib VERSION 1.0.0 DESCRIPTION "Template for C++ library built with CMa include(cmake/utils.cmake) include(GNUInstallDirs) -string(COMPARE EQUAL "${CMAKE_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}" is_top_level) - # MYLIB_SHARED_LIBS option (undefined by default) can be used to force shared/static build -option(MYLIB_BUILD_TESTS "Build mylib tests" ${is_top_level}) -option(MYLIB_BUILD_EXAMPLES "Build mylib examples" ${is_top_level}) +option(MYLIB_BUILD_TESTS "Build mylib tests" ${PROJECT_IS_TOP_LEVEL}) +option(MYLIB_BUILD_EXAMPLES "Build mylib examples" ${PROJECT_IS_TOP_LEVEL}) option(MYLIB_BUILD_DOCS "Build mylib documentation" OFF) -option(MYLIB_INSTALL "Generate target for installing mylib" ${is_top_level}) +option(MYLIB_INSTALL "Generate target for installing mylib" ${PROJECT_IS_TOP_LEVEL}) set_if_undefined( MYLIB_INSTALL_CMAKEDIR "${CMAKE_INSTALL_LIBDIR}/cmake/mylib" @@ -40,7 +38,7 @@ if(NOT DEFINED CMAKE_BUILD_TYPE AND NOT DEFINED CMAKE_CONFIGURATION_TYPES) endif() # Neither of these two are technically needed, but they make the expectation clear -set_if_undefined(CMAKE_CXX_STANDARD 20) +set_if_undefined(CMAKE_CXX_STANDARD 17) set_if_undefined(CMAKE_CXX_EXTENSIONS FALSE) set_if_undefined(CMAKE_CXX_VISIBILITY_PRESET hidden) @@ -101,15 +99,16 @@ if(MYLIB_INSTALL AND NOT CMAKE_SKIP_INSTALL_RULES) write_basic_package_version_file(mylib-config-version.cmake COMPATIBILITY SameMajorVersion) + # cmake-format: off install(TARGETS mylib EXPORT mylib_export RUNTIME COMPONENT mylib LIBRARY COMPONENT mylib NAMELINK_COMPONENT mylib-dev - ARCHIVE COMPONENT mylib-dev FILE_SET HEADERS COMPONENT mylib-dev - INCLUDES - COMPONENT mylib-dev - DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" + ARCHIVE COMPONENT mylib-dev + INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" + FILE_SET HEADERS COMPONENT mylib-dev ) + # cmake-format: on set(targets_file "mylib-shared-targets.cmake") @@ -124,8 +123,9 @@ if(MYLIB_INSTALL AND NOT CMAKE_SKIP_INSTALL_RULES) NAMESPACE mylib:: ) - install(FILES "${CMAKE_CURRENT_BINARY_DIR}/mylib-config.cmake" "${CMAKE_CURRENT_BINARY_DIR}/mylib-config-version.cmake" - COMPONENT mylib-dev DESTINATION "${MYLIB_INSTALL_CMAKEDIR}" + install(FILES "${CMAKE_CURRENT_BINARY_DIR}/mylib-config.cmake" + "${CMAKE_CURRENT_BINARY_DIR}/mylib-config-version.cmake" COMPONENT mylib-dev + DESTINATION "${MYLIB_INSTALL_CMAKEDIR}" ) if(MSVC) diff --git a/CMakePresets.json b/CMakePresets.json index 805bd8d..31ed414 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -6,7 +6,7 @@ "patch": 0 }, "include": [ - "CMake${hostSystemName}Presets.json" + "cmake/presets/CMake${hostSystemName}Presets.json" ], "buildPresets": [ { diff --git a/CMakeDarwinPresets.json b/cmake/presets/CMakeDarwinPresets.json similarity index 100% rename from CMakeDarwinPresets.json rename to cmake/presets/CMakeDarwinPresets.json diff --git a/CMakeGenericPresets.json b/cmake/presets/CMakeGenericPresets.json similarity index 100% rename from CMakeGenericPresets.json rename to cmake/presets/CMakeGenericPresets.json diff --git a/CMakeLinuxPresets.json b/cmake/presets/CMakeLinuxPresets.json similarity index 100% rename from CMakeLinuxPresets.json rename to cmake/presets/CMakeLinuxPresets.json index f61874b..82e4f3f 100644 --- a/CMakeLinuxPresets.json +++ b/cmake/presets/CMakeLinuxPresets.json @@ -29,8 +29,8 @@ "name": "Debug", "description": "Possix preset for library developers", "inherits": [ - "Release", "dev-mode", + "Release", "clang-tidy" ] } diff --git a/CMakeWindowsPresets.json b/cmake/presets/CMakeWindowsPresets.json similarity index 95% rename from CMakeWindowsPresets.json rename to cmake/presets/CMakeWindowsPresets.json index 89145f8..9996eec 100644 --- a/CMakeWindowsPresets.json +++ b/cmake/presets/CMakeWindowsPresets.json @@ -30,8 +30,8 @@ "name": "Debug", "description": "Windows preset for library developers", "inherits": [ - "Release", - "dev-mode" + "dev-mode", + "Release" ], "generator": "Visual Studio 17 2022" } diff --git a/examples/add/CMakeLists.txt b/examples/add/CMakeLists.txt index 66dde79..2cb4c55 100644 --- a/examples/add/CMakeLists.txt +++ b/examples/add/CMakeLists.txt @@ -1,11 +1,10 @@ -cmake_minimum_required(VERSION 3.14) +cmake_minimum_required(VERSION 3.25...3.30) project(mylib-add LANGUAGES CXX) include("../../cmake/utils.cmake") -string(COMPARE EQUAL "${CMAKE_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}" is_top_level) -if(is_top_level) - find_package(mylib REQUIRED) +if(PROJECT_IS_TOP_LEVEL) + find_package(mylib 1.0.0 REQUIRED) endif() set(sources main.cpp) @@ -15,6 +14,6 @@ add_executable(mylib-add) target_sources(mylib-add PRIVATE ${sources}) target_link_libraries(mylib-add PRIVATE mylib::mylib) -if(NOT is_top_level) +if(NOT PROJECT_IS_TOP_LEVEL) win_copy_deps_to_target_dir(mylib-add mylib::mylib) endif() diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 6e26799..a363f26 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,18 +1,17 @@ cmake_minimum_required(VERSION 3.25...3.30) -project(mylib-tests) +project(mylib-tests LANGUAGES CXX) #---------------------------------------------------------------------------------------------------------------------- # general settings and options #---------------------------------------------------------------------------------------------------------------------- include("../cmake/utils.cmake") -string(COMPARE EQUAL "${CMAKE_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}" is_top_level) -if(is_top_level) +if(PROJECT_IS_TOP_LEVEL) enable_testing() # Neither of these two are technically needed, but they make the expectation clear - set_if_undefined(CMAKE_CXX_STANDARD 20) + set_if_undefined(CMAKE_CXX_STANDARD 17) set_if_undefined(CMAKE_CXX_EXTENSIONS FALSE) endif() @@ -23,15 +22,12 @@ endif() include(FetchContent) FetchContent_Declare( googletest URL https://github.com/google/googletest/archive/refs/tags/v1.15.2.tar.gz DOWNLOAD_EXTRACT_TIMESTAMP ON - DOWNLOAD_NO_PROGRESS ON + DOWNLOAD_NO_PROGRESS ON FIND_PACKAGE_ARGS NAMES GTest ) set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) # do not override parent project's runtime settings on Windows set(INSTALL_GTEST OFF) - -# For simplicity, always build googletest as static library. This prevents mylib-tests executable from -# complaining about missing googletest DLLs on Windows. -set(BUILD_SHARED_LIBS OFF) +set(BUILD_GMOCK OFF) FetchContent_MakeAvailable(googletest) @@ -39,8 +35,13 @@ FetchContent_MakeAvailable(googletest) # tests dependencies #---------------------------------------------------------------------------------------------------------------------- -if(is_top_level) - find_package(mylib REQUIRED) +if(PROJECT_IS_TOP_LEVEL) + find_package(mylib 1.0.0 QUIET) + if(NOT mylib_FOUND) + message(STATUS "find_package(mylib) was NOT found, use as subproject ...") + # test if the targets are usable if used as subproject + add_subdirectory(.. mylib EXCLUDE_FROM_ALL) + endif() endif() #---------------------------------------------------------------------------------------------------------------------- @@ -57,9 +58,26 @@ source_group(TREE "${CMAKE_CURRENT_SOURCE_DIR}" FILES ${sources}) add_executable(mylib-tests) target_sources(mylib-tests PRIVATE ${sources}) -target_link_libraries(mylib-tests PRIVATE mylib::mylib gtest_main) +target_link_libraries(mylib-tests PRIVATE mylib::mylib GTest::gtest_main) + +if(NOT PROJECT_IS_TOP_LEVEL) + # test if the targets are findable from the build directory + # cmake-format: off + add_test(find-package-test + ${CMAKE_CTEST_COMMAND} + -C ${CMAKE_BUILD_TYPE} + --build-and-test + "${CMAKE_CURRENT_SOURCE_DIR}" + "${CMAKE_CURRENT_BINARY_DIR}/find-package-test" + --build-generator ${CMAKE_GENERATOR} + --build-makeprogram ${CMAKE_MAKE_PROGRAM} + --build-options + "-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}" + "-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}" + "-DCMAKE_PREFIX_PATH=${CMAKE_PREFIX_PATH}" + ) + # cmake-format: on -if(NOT is_top_level) win_copy_deps_to_target_dir(mylib-tests mylib::mylib) endif() From 1fca6de82c883898301066a29ce4f6ab9bb6d2c3 Mon Sep 17 00:00:00 2001 From: ClausKlein Date: Sun, 13 Oct 2024 23:09:43 +0200 Subject: [PATCH 13/13] Use CMAKE_VERIFY_INTERFACE_HEADER_SETS too --- CMakeLists.txt | 23 +++++++++++++---------- CMakePresets.json | 11 +++++++++++ cmake/presets/CMakeGenericPresets.json | 3 ++- 3 files changed, 26 insertions(+), 11 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1768b68..2ef93a5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -76,18 +76,21 @@ source_group(TREE "${CMAKE_CURRENT_SOURCE_DIR}" FILES ${sources}) include(CMakePackageConfigHelpers) target_sources(mylib PRIVATE src/mylib.cpp) -target_sources( - mylib - PUBLIC FILE_SET - HEADERS - BASE_DIRS - ${CMAKE_CURRENT_SOURCE_DIR}/include + +# cmake-format: off +target_sources(mylib + PUBLIC + FILE_SET HEADERS + BASE_DIRS + include ${CMAKE_CURRENT_BINARY_DIR}/include - FILES - ${CMAKE_CURRENT_SOURCE_DIR}/include/mylib/mylib.h - ${CMAKE_CURRENT_SOURCE_DIR}/include/mylib/export.h + FILES + include/mylib/mylib.h + include/mylib/export.h ${CMAKE_CURRENT_BINARY_DIR}/include/mylib/${export_file_name} ) +# cmake-format: on + target_compile_definitions(mylib PUBLIC "$<$>:MYLIB_STATIC_DEFINE>") set_target_properties(mylib PROPERTIES SOVERSION ${PROJECT_VERSION_MAJOR} VERSION ${PROJECT_VERSION}) @@ -105,7 +108,6 @@ if(MYLIB_INSTALL AND NOT CMAKE_SKIP_INSTALL_RULES) RUNTIME COMPONENT mylib LIBRARY COMPONENT mylib NAMELINK_COMPONENT mylib-dev ARCHIVE COMPONENT mylib-dev - INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" FILE_SET HEADERS COMPONENT mylib-dev ) # cmake-format: on @@ -148,6 +150,7 @@ if(MYLIB_INSTALL AND NOT CMAKE_SKIP_INSTALL_RULES) OPTIONAL ) endif() + include(CPack) endif() diff --git a/CMakePresets.json b/CMakePresets.json index 31ed414..1eac1e0 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -23,6 +23,13 @@ "targets": [ "install" ] + }, + { + "name": "verify_interface_header-Debug", + "configurePreset": "Debug", + "targets": [ + "all_verify_interface_header_sets" + ] } ], "testPresets": [ @@ -81,6 +88,10 @@ "type": "test", "name": "Debug" }, + { + "type": "build", + "name": "verify_interface_header-Debug" + }, { "type": "build", "name": "install-Debug" diff --git a/cmake/presets/CMakeGenericPresets.json b/cmake/presets/CMakeGenericPresets.json index 89abee1..1f8725a 100644 --- a/cmake/presets/CMakeGenericPresets.json +++ b/cmake/presets/CMakeGenericPresets.json @@ -14,7 +14,8 @@ "hidden": true, "cacheVariables": { "CMAKE_EXPORT_COMPILE_COMMANDS": true, - "CMAKE_MESSAGE_LOG_LEVEL": "WARNING" + "CMAKE_MESSAGE_LOG_LEVEL": "WARNING", + "CMAKE_VERIFY_INTERFACE_HEADER_SETS": true } }, {