├── .gitignore ├── CMakeLists.txt ├── README.md ├── packaging └── CMakeLists.txt ├── readme ├── CMake 变量.md ├── CMake 逻辑判断及循环.md └── CMake 项目目录结构组织.md ├── src ├── CMakeLists.txt ├── example │ └── header_only │ │ ├── CMakeLists.txt │ │ ├── cmake │ │ └── pkg-config.pc.in │ │ ├── include │ │ └── header_only │ │ │ └── header_only.h │ │ ├── open_source │ │ └── README.md │ │ ├── packaging │ │ └── CMakeLists.txt │ │ └── tests │ │ └── CMakeLists.txt └── main.cpp └── tests └── CMakeLists.txt /.gitignore: -------------------------------------------------------------------------------- 1 | CMakeUserPresets.json 2 | # Generated and user files 3 | **/CMakeCache.txt 4 | **/CMakeUserPresets.json 5 | **/CTestTestfile.cmake 6 | **/CPackConfig.cmake 7 | **/cmake_install.cmake 8 | **/install_manifest.txt 9 | **/compile_commands.json 10 | 11 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 4.0 FATAL_ERROR) 2 | 3 | project(study_cmake 4 | VERSION 1.0.0 5 | DESCRIPTION "Study CMake 4.0" 6 | HOMEPAGE_URL "https://github.com/eglinuxer/study_cmake" 7 | LANGUAGES CXX 8 | ) 9 | 10 | set(CMAKE_EXPORT_COMPILE_COMMANDS ON) 11 | 12 | # cmake --log-context 13 | list(APPEND CMAKE_MESSAGE_CONTEXT "${PROJECT_NAME}") 14 | 15 | if(NOT PROJECT_IS_TOP_LEVEL) 16 | message(FATAL_ERROR "The ${CMAKE_PROJECT_NAME} project is intended to be a standalone, top-level project. Do not vendor this directory.") 17 | endif() 18 | 19 | if(PROJECT_SOURCE_DIR STREQUAL PROJECT_BINARY_DIR) 20 | message(FATAL_ERROR "In-source builds are not allowed") 21 | endif() 22 | 23 | include(GNUInstallDirs) 24 | include (TestBigEndian) 25 | test_big_endian(IS_BIG_ENDIAN) 26 | 27 | if(IS_BIG_ENDIAN) 28 | message(STATUS "BIG_ENDIAN") 29 | else() 30 | message(STATUS "LITTLE_ENDIAN") 31 | endif() 32 | 33 | # Check if the current generator is a multi-configuration generator or not 34 | get_property(IsMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) 35 | 36 | if(IsMultiConfig) 37 | message(STATUS "Configuring for [${CMAKE_CONFIGURATION_TYPES}]") 38 | else() 39 | set(AllowedBuildTypes Debug Release RelWithDebugInfo MinSizeRel) 40 | set_property( 41 | CACHE CMAKE_BUILD_TYPE 42 | PROPERTY STRINGS "${AllowedBuildTypes}" 43 | ) 44 | 45 | # if the build type is not set force it to debug 46 | if(NOT CMAKE_BUILD_TYPE) 47 | set(CMAKE_BUILD_TYPE Debug CACHE STRING "" FORCE) 48 | elseif(NOT CMAKE_BUILD_TYPE IN_LIST AllowedBuildTypes) 49 | message(FATAL_ERROR "Unknown build type: ${CMAKE_BUILD_TYPE}") 50 | endif() 51 | endif() 52 | 53 | message(STATUS "Configuring on/for [${CMAKE_SYSTEM_NAME}]") 54 | message(STATUS "Current build type is [${CMAKE_BUILD_TYPE}]") 55 | 56 | set(CMAKE_CXX_STANDARD 20) 57 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 58 | set(CMAKE_CXX_EXTENSIONS OFF) 59 | 60 | add_subdirectory(src) 61 | 62 | if(PROJECT_IS_TOP_LEVEL) 63 | add_subdirectory(tests) 64 | add_subdirectory(packaging) 65 | endif() 66 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # study_cmake 2 | CMake 已经来到了 4.0 时代,让我们重学 CMake 吧! 3 | 4 | ## 开始使用 CMake 5 | 6 | 在这个部分,主要展示一些常用的 cmake 命令。 7 | 8 | ### cmake 9 | 10 | - 配置和构建项目 11 | 12 | ```bash 13 | # 先进入项目顶级目录 14 | cmake -S -B 15 | cmake --build 16 | ``` 17 | 18 | - -S 指定源码目录 19 | - -B 指定构建目录 20 | 21 | ### ctest 22 | 23 | ### cpack 24 | 25 | ## CMake 基础语法 26 | 27 | - 一个最小项目所必须的三个命令 28 | 29 | - 指定 CMake 最小版本 30 | - [cmake_minimum_required()](https://cmake.org/cmake/help/latest/command/cmake_minimum_required.html) 31 | - 定义项目 32 | - [project()](https://cmake.org/cmake/help/latest/command/project.html) 33 | 34 | - 定义目标 35 | - [add_executable()](https://cmake.org/cmake/help/latest/command/add_executable.html) 36 | - [add_library()](https://cmake.org/cmake/help/latest/command/add_library.html) 37 | - [add_custom_target()](https://cmake.org/cmake/help/latest/command/add_custom_target.html) 38 | 39 | - [CMake 变量](<./readme/CMake 变量.md>) 40 | 41 | - [CMake 逻辑判断及循环](<./readme/CMake 逻辑判断及循环.md>) 42 | 43 | - [CMake 项目目录结构组织](<./readme/CMake 项目目录结构组织.md>) 44 | 45 | ## CMake 进阶 46 | -------------------------------------------------------------------------------- /packaging/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(CPACK_THREADS 0) 2 | set(CPACK_PACKAGE_VENDOR "Eglinux") 3 | set(CPACK_GENERATOR "TGZ;STGZ") 4 | 5 | include(CPack) 6 | 7 | -------------------------------------------------------------------------------- /readme/CMake 变量.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eglinuxer/study_cmake/cbfba3ff0e6bbf3b1eeffbce7b7d038a345f4d1e/readme/CMake 变量.md -------------------------------------------------------------------------------- /readme/CMake 逻辑判断及循环.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eglinuxer/study_cmake/cbfba3ff0e6bbf3b1eeffbce7b7d038a345f4d1e/readme/CMake 逻辑判断及循环.md -------------------------------------------------------------------------------- /readme/CMake 项目目录结构组织.md: -------------------------------------------------------------------------------- 1 | # CMake 项目目录结构组织 2 | 3 | 随着项目越来越大,越来越复杂,就需要考虑好好的组织项目的目录结构,CMake 提供了一些命令来支持项目保持良好的目录结构。 4 | 5 | ## [include()](https://cmake.org/cmake/help/latest/command/include.html) 6 | 7 | ## [include_guard()](https://cmake.org/cmake/help/latest/command/include_guard.html) 8 | 9 | ## [add_subdirectory()](https://cmake.org/cmake/help/latest/command/add_subdirectory.html) 10 | 11 | ## [aux_source_directory()](https://cmake.org/cmake/help/latest/command/aux_source_directory.html) 12 | 13 | ## [source_group()](https://cmake.org/cmake/help/latest/command/source_group.html) -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(main main.cpp) 2 | -------------------------------------------------------------------------------- /src/example/header_only/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 4.0 FATAL_ERROR) 2 | 3 | project(header_only 4 | VERSION 1.0.0 5 | DESCRIPTION "A header only CMake project example" 6 | HOMEPAGE_URL "https://github.com/eglinuxer/study_cmake/src/example/header_only" 7 | LANGUAGES CXX 8 | ) 9 | 10 | set(CMAKE_EXPORT_COMPILE_COMMANDS ON) 11 | 12 | # cmake --log-context 13 | list(APPEND CMAKE_MESSAGE_CONTEXT "${CMAKE_PROJECT_NAME}") 14 | 15 | if(PROJECT_SOURCE_DIR STREQUAL PROJECT_BINARY_DIR) 16 | message(FATAL_ERROR "In-source builds are not allowed") 17 | endif() 18 | 19 | include(GNUInstallDirs) 20 | include (TestBigEndian) 21 | test_big_endian(IS_BIG_ENDIAN) 22 | 23 | if(IS_BIG_ENDIAN) 24 | message(STATUS "BIG_ENDIAN") 25 | else() 26 | message(STATUS "LITTLE_ENDIAN") 27 | endif() 28 | 29 | # Check if the current generator is a multi-configuration generator or not 30 | get_property(IsMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) 31 | 32 | if(IsMultiConfig) 33 | message(STATUS "Configuring for [${CMAKE_CONFIGURATION_TYPES}]") 34 | else() 35 | set(AllowedBuildTypes Debug Release RelWithDebugInfo MinSizeRel) 36 | set_property( 37 | CACHE CMAKE_BUILD_TYPE 38 | PROPERTY STRINGS "${AllowedBuildTypes}" 39 | ) 40 | 41 | # if the build type is not set force it to debug 42 | if(NOT CMAKE_BUILD_TYPE) 43 | set(CMAKE_BUILD_TYPE Debug CACHE STRING "" FORCE) 44 | elseif(NOT CMAKE_BUILD_TYPE IN_LIST AllowedBuildTypes) 45 | message(FATAL_ERROR "Unknown build type: ${CMAKE_BUILD_TYPE}") 46 | endif() 47 | endif() 48 | 49 | message(STATUS "Configuring on/for [${CMAKE_SYSTEM_NAME}]") 50 | message(STATUS "Current build type is [${CMAKE_BUILD_TYPE}]") 51 | 52 | set(CMAKE_CXX_STANDARD 20) 53 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 54 | set(CMAKE_CXX_EXTENSIONS OFF) 55 | 56 | option(header_only_SystemInclude "Include as system headers (skip for clang-tidy)." OFF) 57 | 58 | if (header_only_SystemInclude) 59 | set(EGLINUX_HEADER_ONLY_SYSTEM_INCLUDE "SYSTEM") 60 | endif() 61 | 62 | add_library(header_only INTERFACE) 63 | add_library(eglinux::header_only ALIAS header_only) 64 | 65 | target_include_directories(header_only ${EGLINUX_HEADER_ONLY_SYSTEM_INCLUDE} 66 | INTERFACE 67 | $ 68 | $ 69 | ) 70 | 71 | # Install a pkg-config file, so other tools can find this. 72 | CONFIGURE_FILE( 73 | "${CMAKE_CURRENT_SOURCE_DIR}/cmake/pkg-config.pc.in" 74 | "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc" 75 | @ONLY 76 | ) 77 | 78 | include(CMakePackageConfigHelpers) 79 | 80 | write_basic_package_version_file( 81 | "header_only-config-version.cmake" 82 | COMPATIBILITY SameMajorVersion 83 | ) 84 | 85 | install( 86 | DIRECTORY 87 | ${CMAKE_CURRENT_SOURCE_DIR}/include/ 88 | DESTINATION 89 | ${CMAKE_INSTALL_INCLUDEDIR} 90 | ) 91 | 92 | install( 93 | FILES 94 | ${CMAKE_CURRENT_BINARY_DIR}/header_only-config-version.cmake 95 | DESTINATION 96 | ${CMAKE_INSTALL_DATADIR}/cmake/${PROJECT_NAME} 97 | ) 98 | 99 | install( 100 | TARGETS 101 | header_only 102 | EXPORT 103 | header_only_export 104 | INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} 105 | ) 106 | 107 | install( 108 | EXPORT 109 | header_only_export 110 | FILE 111 | header_only-config.cmake 112 | NAMESPACE 113 | eglinux:: 114 | DESTINATION 115 | ${CMAKE_INSTALL_DATADIR}/cmake/${PROJECT_NAME} 116 | ) 117 | 118 | install( 119 | FILES 120 | ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc 121 | DESTINATION 122 | ${CMAKE_INSTALL_DATADIR}/pkgconfig 123 | ) 124 | 125 | if(PROJECT_IS_TOP_LEVEL) 126 | add_subdirectory(tests) 127 | add_subdirectory(packaging) 128 | endif() 129 | -------------------------------------------------------------------------------- /src/example/header_only/cmake/pkg-config.pc.in: -------------------------------------------------------------------------------- 1 | prefix=@CMAKE_INSTALL_PREFIX@ 2 | includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@ 3 | 4 | Name: @PROJECT_NAME@ 5 | Description: Eglinux header_only example. 6 | Version: @PROJECT_VERSION@ 7 | Cflags: -I${includedir} 8 | -------------------------------------------------------------------------------- /src/example/header_only/include/header_only/header_only.h: -------------------------------------------------------------------------------- 1 | #ifndef __HEADER_ONLY_H__ 2 | #define __HEADER_ONLY_H__ 3 | 4 | #include 5 | #include 6 | 7 | namespace header_only 8 | { 9 | inline void print_hello(const std::string& name) { 10 | std::cout << "Hello " << name << " from a header only library" << std::endl; 11 | } 12 | } 13 | 14 | #endif // !__HEADER_ONLY_H__ 15 | 16 | -------------------------------------------------------------------------------- /src/example/header_only/open_source/README.md: -------------------------------------------------------------------------------- 1 | # 仅头文件 2 | 3 | 下面是一些开源的使用 CMake 管理的仅头文件项目,可以供学习 CMake 使用 4 | 5 | - [nlohmann/json](https://github.com/nlohmann/json.git) 6 | -------------------------------------------------------------------------------- /src/example/header_only/packaging/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(CPACK_THREADS 0) 2 | set(CPACK_PACKAGE_VENDOR "Eglinux") 3 | set(CPACK_GENERATOR "TGZ;STGZ") 4 | 5 | include(CPack) 6 | 7 | -------------------------------------------------------------------------------- /src/example/header_only/tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | enable_testing() 2 | 3 | -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(int argc, const char* argv[]) 4 | { 5 | std::cout << "Hello All, welcome to study CMake 4.0 with eglinux." << std::endl; 6 | std::cout << "Hello cpp " << __cplusplus << std::endl; 7 | } 8 | -------------------------------------------------------------------------------- /tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | enable_testing() 2 | 3 | --------------------------------------------------------------------------------