{"id":25658452,"url":"https://github.com/abin-z/cmakeprotemplate","last_synced_at":"2026-04-24T12:33:37.203Z","repository":{"id":272314233,"uuid":"915703904","full_name":"abin-z/CMakeProTemplate","owner":"abin-z","description":"C++复杂项目推荐的目录组织方式","archived":false,"fork":false,"pushed_at":"2025-02-23T14:00:07.000Z","size":20,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-02-23T15:18:37.112Z","etag":null,"topics":["c","cpp","cpp17","modern-cmake","project-management","template"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/abin-z.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2025-01-12T15:31:41.000Z","updated_at":"2025-02-23T14:34:02.000Z","dependencies_parsed_at":null,"dependency_job_id":"edb635e6-0e10-4e5e-a834-89d45cf3b933","html_url":"https://github.com/abin-z/CMakeProTemplate","commit_stats":null,"previous_names":["abin-z/cmakeprotemplate"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/abin-z%2FCMakeProTemplate","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/abin-z%2FCMakeProTemplate/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/abin-z%2FCMakeProTemplate/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/abin-z%2FCMakeProTemplate/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/abin-z","download_url":"https://codeload.github.com/abin-z/CMakeProTemplate/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":240396800,"owners_count":19794731,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["c","cpp","cpp17","modern-cmake","project-management","template"],"created_at":"2025-02-24T00:21:31.568Z","updated_at":"2026-04-24T12:33:37.198Z","avatar_url":"https://github.com/abin-z.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# 现代CMake模块化项目管理指南\n\n出发点: 基于CMake的C/C++项目, 如何优雅地、模块化地组织大量源文件?\n\n#### 一. CMake项目推荐的目录组织方式\n\n- 项目名/include/项目名/模块名.h\n- 项目名/src/模块名.cpp\n\n  ```sh\n  [user@ubuntu CMakeProTemplate]$ tree 项目名/\n  项目名/\n  ├── CMakeLists.txt\n  ├── include\n  │   └── 项目名\n  │       └── 模块名.h\n  └── src\n      └── 模块名.cpp\n  ```\n\n- CMakeLists.txt中写:\n\n  ```cmake\n  target_include_directories(项目名 PUBLIC include)\n  ```\n\n- 在头文件中(`项目名/include/项目名/模块名.h`)写:\n\n  ```cpp\n  #pragma once\n  \n  namespace 项目名\n  {\n  void 函数名();\n  }\n  ```\n\n- 在实现文件中(`项目名/src/模块名.cpp`)写:\n\n  ```cpp\n  #include \u003c项目名/模块名.h\u003e\n  \n  namespace 项目名\n  {\n  void 函数名()\n  {\n      // 函数实现\n  }\n  }\n  ```\n  \n- 使用该模块的源文件`main.cpp`:\n\n  ```cpp\n  #include \u003c项目名/模块名.h\u003e\n  \n  int main(int argc, char **argv)\n  {\n  \t项目名::函数名();\n  }\n  ```\n\n  \n\n#### 二. 划分子项目\n\n- 大型的项目，往往会划分为几个子项目, 子项目有的是库的形式.\n\n- 一个主要的可执行文件, 类似\"前台接待员\"的功能, 真正的功能是在其他几个lib库项目中实现的.\n\n- 下图的案例中,  在根目录下, 主项目为`mainproject`, 有两个子项目`biology`和`network`库. 它们分别在各自的目录下都有专属的CMakeLists.txt文件. 在根目录下用主CMakeLists.txt 进行组织.\n\n  ```sh\n  .\n  ├── biology\n  │   ├── CMakeLists.txt\n  │   ├── include\n  │   │   └── biology\n  │   │       ├── Animal.h\n  │   │       ├── Cat.h\n  │   │       ├── Dog.h\n  │   │       └── Mammal.h\n  │   └── src\n  │       ├── Cat.cpp\n  │       ├── Dog.cpp\n  │       └── Mammal.cpp\n  ├── CMakeLists.txt\n  ├── mainproject\n  │   ├── CMakeLists.txt\n  │   ├── include\n  │   │   └── mainproject\n  │   │       └── utils.hpp\n  │   └── src\n  │       └── main.cpp\n  ├── network\n  │   ├── CMakeLists.txt\n  │   ├── include\n  │   │   └── network\n  │   │       └── socket.h\n  │   └── src\n  │       └── socket.cpp\n  └── README.md\n  \n  12 directories, 16 files\n  ```\n\n#### 三. 根目录的CMakeLists.txt配置\n\n- 在根目录中的CMakeLists.txt中, 设置了默认的构建模式, 设置了C++版本等各种选项, 然后通过project命令初始化根项目.\n- 设置静态库/动态库/可执行文件的输出目录.\n- 通过`add_subdirectory`把各个子项目添加进来(顺序无关紧要的), 这会调用各个子项目中的CMakeLists.txt.\n\n  ```cmake\n  # 设置 CMake 的最低版本要求\n  cmake_minimum_required(VERSION 3.20)\n  \n  # 设置默认构建类型为Release，如果未指定构建类型\n  if(NOT CMAKE_CONFIGURATION_TYPES AND NOT CMAKE_BUILD_TYPE)\n    set(CMAKE_BUILD_TYPE Release CACHE STRING \"Build type\")\n  endif()\n  \n  # 设置 C++ 标准为 C++17，并强制要求支持 C++17\n  set(CMAKE_CXX_STANDARD 17)\n  set(CMAKE_CXX_STANDARD_REQUIRED ON) # 强制要求支持指定的 C++ 标准\n  set(CMAKE_CXX_EXTENSIONS OFF)       # 禁用编译器特定扩展，确保代码更具可移植性\n  \n  # 定义项目名称及支持的语言\n  project(SmallDemo LANGUAGES C CXX)\n  \n  # 设置所有库生成位置无关代码 (Position Independent Code) 对应GCC/Clang的-fPIC\n  set(CMAKE_POSITION_INDEPENDENT_CODE ON)\n  \n  # 设置输出目录\n  # 静态库输出目录\n  set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/build_output/lib)\n  # 动态库输出目录\n  set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/build_output/bin)\n  # 可执行文件输出目录\n  set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/build_output/bin)\n  \n  # 添加子目录\n  # 每个子目录对应一个模块\n  add_subdirectory(mainproject)\n  add_subdirectory(network)\n  add_subdirectory(biology)\n  ```\n\n### 三. 子项目的CMakeLists.txt配置\n\n- 子项目的CMakeLists.txt就干净许多，只是创建了network这个静态库对象，并通过`GLOB_RECRUSE`分别批量添加了所有位于`include`的头文件和`src`的实现文件。\n\n  ```cmake\n  # 设置目标名称为 network\n  set(tgt_name network)\n  \n  # 递归查找头文件，存储在变量 headers 中\n  # CONFIGURE_DEPENDS 用于确保当文件系统中匹配的文件发生变化时，会触发重新配置\n  file(GLOB_RECURSE headers CONFIGURE_DEPENDS include/*.h include/*.hpp)\n  \n  # 递归查找源文件，存储在变量 sources 中\n  file(GLOB_RECURSE sources CONFIGURE_DEPENDS src/*.c src/*.cpp src/*.cc src/*.cxx)\n  \n  # 创建一个名为 ${tgt_name} 的目标库（默认是静态库）\n  add_library(${tgt_name})\n  \n  # 将头文件添加到目标的 PUBLIC 源文件列表中\n  # PUBLIC 意味着头文件将对目标的用户可见\n  target_sources(${tgt_name} PUBLIC ${headers})\n  \n  # 将源文件添加到目标的 PRIVATE 源文件列表中\n  # PRIVATE 意味着这些文件仅对目标本身可见\n  target_sources(${tgt_name} PRIVATE ${sources})\n  \n  # 指定 include 目录，让目标及其用户能够访问 include 下的头文件\n  # PUBLIC 意味着 include 目录会被传播给目标的依赖者\n  target_include_directories(${tgt_name} PUBLIC\n      $\u003cBUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include\u003e\n  )\n  ```\n\n- 根项目的CMakeLists.txt负责处理全局有效的设定。而子项目的CMakeLists.txt则仅考虑该子项目自身的设定，比如他的头文件目录，要链接的库等等。\n\n  ```cmake\n  # 设置目标名称为 mainproject\n  set(tgt_name mainproject)\n  \n  # 递归查找头文件，存储在变量 headers 中\n  # CONFIGURE_DEPENDS 用于确保当文件系统中匹配的文件发生变化时，会触发重新配置\n  file(GLOB_RECURSE headers CONFIGURE_DEPENDS include/*.h include/*.hpp)\n  \n  # 递归查找源文件，存储在变量 sources 中\n  file(GLOB_RECURSE sources CONFIGURE_DEPENDS src/*.c src/*.cpp src/*.cc src/*.cxx)\n  \n  # 创建一个名为 ${tgt_name} 的目标库（默认是静态库）\n  add_library(${tgt_name})\n  \n  # 将头文件添加到目标的 PUBLIC 源文件列表中\n  # PUBLIC 意味着头文件将对目标的用户可见\n  target_sources(${tgt_name} PUBLIC ${headers})\n  \n  # 将源文件添加到目标的 PRIVATE 源文件列表中\n  # PRIVATE 意味着这些文件仅对目标本身可见\n  target_sources(${tgt_name} PRIVATE ${sources})\n  \n  # 指定 include 目录，让目标及其用户能够访问 include 下的头文件\n  # PUBLIC 意味着 include 目录会被传播给目标的依赖者\n  target_include_directories(${tgt_name} PUBLIC\n      $\u003cBUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include\u003e\n  )\n  \n  # 链接biology和network库, 面向目标target\n  target_link_libraries(${tgt_name} PRIVATE biology network)\n  ```\n\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fabin-z%2Fcmakeprotemplate","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fabin-z%2Fcmakeprotemplate","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fabin-z%2Fcmakeprotemplate/lists"}