CMake指令: add_sub_directory以及工作流程

目錄

1.簡介

2.工作流程

3.示例場景

4.最佳實踐

5.注意事項

6.總結

相關鏈接


1.簡介

? ?add_subdirectory?是 CMake 中用于添加子目錄參與構建的命令,允許將項目拆分為多個模塊或子項目,實現代碼的模塊化管理。

? ? ? ? 基本語法:

add_subdirectory(source_dir [binary_dir] [EXCLUDE_FROM_ALL])
  • source_dir:子目錄的源代碼路徑(相對于當前 CMakeLists.txt 的路徑)。
  • binary_dir(可選):指定子目錄的編譯輸出路徑(默認與?source_dir?同級的?build?目錄)。
  • EXCLUDE_FROM_ALL(可選):子目錄不會被默認構建,需顯式調用?add_subdirectory?或指定目標依賴。

? ? ? ? 核心作用:

  1. 模塊化構建:將項目拆分為多個子目錄(如?srcteststhird_party),每個子目錄包含獨立的?CMakeLists.txt
  2. 依賴管理:子目錄可定義庫或可執行文件,供父目錄或其他子目錄鏈接。
  3. 遞歸構建:子目錄中的?add_subdirectory?會被遞歸處理,實現多層級項目結構。

2.工作流程

1.目錄解析

  • CMake 解析?add_subdirectory()?中的?source_dir?參數(如?src),確定子目錄的路徑。
  • 若指定?binary_dir(如?build/src),則將子目錄的構建輸出定向到該路徑。
# 父目錄 CMakeLists.txt
add_subdirectory(src)  # 無 binary_dir,輸出到 build/src

2.變量傳遞:

  • 父→子傳遞:父目錄中的變量(如?CMAKE_CXX_FLAGSPROJECT_NAME)自動傳遞給子目錄。
  • 子→父傳遞:子目錄可通過?set(... PARENT_SCOPE)?將變量回傳給父目錄。
# 父目錄定義
set(COMMON_FLAGS "-Wall")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${COMMON_FLAGS}")# 子目錄自動繼承 COMMON_FLAGS 和 CMAKE_CXX_FLAGS# 子目錄
set(MY_VERSION "1.0.0" PARENT_SCOPE)  # 傳遞到父目錄# 父目錄
message("Version from subdir: ${MY_VERSION}")  # 輸出 1.0.0

3.子目錄處理

  • CMake 遞歸執行子目錄中的?CMakeLists.txt?文件,生成目標(如?add_libraryadd_executable)。
  • 子目錄中的?add_subdirectory()?會被遞歸處理,形成構建樹。
# src/CMakeLists.txt
add_library(my_lib STATIC src/file.cpp)
target_include_directories(my_lib PUBLIC include)

4.依賴關系建立

  • 子目錄中定義的目標(如?lib)可被父目錄或其他子目錄鏈接(如?target_link_libraries)。
  • CMake 自動處理目標間的依賴關系,確保正確的構建順序。
# 父目錄 CMakeLists.txt
add_subdirectory(src)  # 先處理子目錄,生成 my_libadd_executable(main main.cpp)
target_link_libraries(main PRIVATE my_lib)  # 鏈接子目錄的庫

3.示例場景

假設你的項目結構如下:

MyProject/
├── CMakeLists.txt
├── src/
│   ├── CMakeLists.txt
│   ├── main.cpp
│   ├── utils.cpp
│   └── app.cpp
├── lib/
│   ├── CMakeLists.txt
│   ├── lib1.cpp
│   └── lib2.cpp
└── include/├── utils.h└── app.h

主目錄的?CMakeLists.txt

cmake_minimum_required(VERSION 3.10)
project(MyProject)# 設置C++標準
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED True)# 添加包含目錄
include_directories(${PROJECT_SOURCE_DIR}/include)# 添加子目錄
add_subdirectory(lib)
add_subdirectory(src)# 定義最終的可執行文件,并鏈接子目錄生成的庫
add_executable(MyApp ${SRC_FILES})
target_link_libraries(MyApp PRIVATE mylib)# 輸出配置信息
message(STATUS "Source files: ${SRC_FILES}")
message(STATUS "Library files: ${LIB_SOURCES}")

lib?子目錄的?CMakeLists.txt

# lib/CMakeLists.txt# 定義庫的源文件列表
set(LIB_SOURCESlib1.cpplib2.cpp
)# 創建靜態庫或動態庫
add_library(mylib STATIC ${LIB_SOURCES})
# 或者創建動態庫
# add_library(mylib SHARED ${LIB_SOURCES})# 指定庫的包含目錄
target_include_directories(mylib PUBLIC ${PROJECT_SOURCE_DIR}/include)# 將庫源文件傳遞到父作用域
set(LIB_SOURCES ${LIB_SOURCES} PARENT_SCOPE)

src?子目錄的?CMakeLists.txt

# src/CMakeLists.txt# 定義源文件列表,包含當前目錄的源文件
set(SRC_FILESmain.cpputils.cppapp.cpp
)# 將源文件傳遞到父作用域
set(SRC_FILES ${SRC_FILES} PARENT_SCOPE)

4.最佳實踐

1.項目結構建議

project/
├─ CMakeLists.txt          # 根目錄:設置全局變量、添加子目錄
├─ include/                # 公共頭文件
├─ src/
│  ├─ CMakeLists.txt       # 定義庫或可執行文件
│  └─ ...                  # 源代碼
├─ tests/
│  ├─ CMakeLists.txt       # 測試相關目標
│  └─ ...                  # 測試代碼
└─ third_party/            # 第三方依賴(可選)

2.模塊化管理

在子目錄中封裝功能模塊(如?add_library),通過?target_*?命令暴露接口,避免全局變量污染。

# 子目錄 src/CMakeLists.txt
add_library(utils STATIC utils.cpp)
target_include_directories(utils PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)

3.條件編譯與選項

使用?option?或?if?控制子目錄是否參與構建,提升靈活性:

# 根據選項決定是否添加測試子目錄
option(BUILD_TESTS "Build tests" ON)
if(BUILD_TESTS)add_subdirectory(tests)
endif()

4.排除默認構建(EXCLUDE_FROM_ALL)

# 子目錄不會被默認構建,需顯式依賴(如通過 add_dependencies)
add_subdirectory(third_party EXCLUDE_FROM_ALL)

5.注意事項

1.變量作用域問題

  • 子目錄無法直接修改父目錄的變量,需通過?PARENT_SCOPE?回傳。
  • 避免在子目錄中使用全局變量(如?include_directories),改用?target_*?命令。
set(VERSION "1.0" PARENT_SCOPE)  # 子目錄回傳變量到父目錄

2.多級子目錄

如果項目中有多級子目錄,例如?src/module1?和?src/module2,可以在?src/CMakeLists.txt?中進一步使用?add_subdirectory(module1)?和?add_subdirectory(module2)?來遞歸處理這些子目錄。

# src/CMakeLists.txtadd_subdirectory(module1)
add_subdirectory(module2)# 定義 src 目錄下的源文件
set(SRC_FILESmain.cpputils.cppapp.cpp
)# 將源文件傳遞到父作用域
set(SRC_FILES ${SRC_FILES} PARENT_SCOPE)

3.構建順序

  • add_subdirectory?的調用順序決定子目錄的處理順序,但目標的構建順序需通過?target_link_libraries?或?add_dependencies?顯式指定。

4.使用相對路徑和全局變量

????????在子目錄的 CMakeLists.txt 中,路徑通常是相對于子目錄本身的。例如,lib/CMakeLists.txt 中的 lib1.cpp 實際上指的是 lib/lib1.cpp。

????????如果需要在多個子目錄中共享變量或路徑,可以在主目錄中定義全局變量或使用 CMake 的全局范圍選項(如 CACHE 變量)來傳遞信息。

5.錯誤處理

????????如果?add_subdirectory()?指定的子目錄不存在或沒有?CMakeLists.txt?文件,CMake 會報錯并中止配置過程。因此,確保所有子目錄中都存在有效的?CMakeLists.txt?文件。

6.總結

? ? ?add_subdirectory()的優點:

  • 結構清晰:項目目錄層次分明,便于導航和理解。
  • 模塊化:每個模塊或組件可以獨立開發和測試。
  • 靈活性:每個子目錄可以有不同的編譯選項和依賴關系。
  • 可擴展性:輕松添加新的模塊或組件,無需修改主?CMakeLists.txt

? ?add_subdirectory()?的核心價值在于實現項目的模塊化構建,通過合理拆分代碼和分層管理?CMakeLists.txt,可顯著提升大型項目的可維護性。充分利用 CMake 提供的命令和功能,如?target_include_directories()target_link_libraries()?等,來管理依賴關系和編譯選項。

相關鏈接

  • CMake 官網?CMake - Upgrade Your Software Build System
  • CMake 官方文檔:CMake Tutorial — CMake 4.0.2 Documentation
  • CMake 源碼:https://github.com/Kitware/CMake
  • CMake 源碼:CMake · GitLab
  • 中文版基礎介紹:?CMake 入門實戰 | HaHack
  • wiki:?Home · Wiki · CMake / Community · GitLab

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/84518.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/84518.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/84518.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【C++ 】智能指針:內存管理的 “自動導航儀”

目錄 一、引入 二、智能指針的兩大特性: 1、RAII 特點: 好處: 2、行為像指針 三、智能指針起初的缺陷:拷貝問題 四、幾種智能指針的介紹。 1、C98出現的智能指針——auto_ptr auto_ptr解決上述拷貝構造的問題&#xff1a…

Java多線程實現之線程池詳解

Java多線程實現之線程池詳解 一、線程池的基本概念1.1 為什么需要線程池1.2 線程池的核心思想 二、Java線程池的實現2.1 Executor框架2.2 ThreadPoolExecutor構造參數 三、常見線程池類型3.1 FixedThreadPool3.2 CachedThreadPool3.3 SingleThreadExecutor3.4 ScheduledThreadP…

解碼美元-黃金負相關:LSTM-Attention因果發現與黃金反彈推演

摘要:本文采用時間序列分析框架與自然語言處理(NLP)技術,對黃金與美元指數的負相關關系進行量化拆解。通過構建包含宏觀經濟因子、市場情緒指標及地緣風險的三維分析模型,揭示當前貴金屬市場的核心驅動邏輯&#xff0c…

Asp.Net Core SignalR導入數據

文章目錄 前言一、安裝包二、使用步驟1.實現SignalR Hub服務:2.實現CSV文件解析及數據導入服務3.控制器4.前端實現(vue) 三、關鍵技術點說明總結 前言 導入CSV文件中的數據到數據庫,使用CsvHelper解析CSV文件,SqlBulk…

Modern C++(四)聲明

4、聲明 聲明是將名字引入到cpp程序中,不是每條聲明都聲明實際的東西。定義是足以使該名字所標識的實體被使用的聲明。聲明包含以下幾種: 函數定義模板聲明模板顯式實例化模板顯式特化命名空間定義鏈接說明屬性聲明(C11)空聲明&…

目標檢測yolo算法

yolov5s: 從github官網下載yolov5的算法之后,配置好環境(pycharm安裝包-CSDN博客),再下載權重文件,比如默認的yolov5s.pt; 運行當前文件(detect.py),就能看…

一個超強的推理增強大模型,開源了,本地部署

大家好,我是 Ai 學習的老章 前幾天介紹了MOE 模型先驅 Mistral 開源的代碼 Agent 大模型——mistralai/Devstral-Small-2505 今天一起看看 Mistral 最新開源的推理大模型——Magistral Magistral 簡介 Mistral 公司推出了首個推理模型 Magistral 及自研可擴展強…

MySQL體系架構解析(五):讀懂MySQL日志文件是優化與故障排查的關鍵

MySQL文件 日志文件 在服務器運行過程中,會產生各種各樣的日志,比如常規的查詢日志,錯誤日志、二進制日志、 redo 日志和 Undo 日志等,日志文件記錄了影響 MySQL 數據庫的各種類型活動。 常見的日志文件有:錯誤日志…

湖南省網絡建設與運維賽項競賽規程及樣題

湖南省職業院校技能競賽樣題 賽題說明 一、競賽內容 “網絡建設與運維”競賽共分三個部分,其中: 第一部分:職業規范與素養 ( 5 分) 第二部分:網絡搭建及安全部署項目 ( 50 分&#xff09…

華為云Flexus+DeepSeek征文 | 基于華為云ModelArts Studio搭建AnythingLLM聊天助手

華為云FlexusDeepSeek征文 | 基于華為云ModelArts Studio搭建AnythingLLM聊天助手 引言一、ModelArts Studio平臺介紹華為云ModelArts Studio簡介ModelArts Studio主要特點 二、AnythingLLM介紹AnythingLLM 簡介AnythingLLM主要特點AnythingLLM地址 三、安裝AnythingLLM應用下載…

板凳-------Mysql cookbook學習 (十--5)

6.11 計算年齡 2025年6月11日星期三 --創建表、初始化數據 drop table if exists sibling; create table sibling (name char(20),birth date );insert into sibling (name,birth) values(Gretchen,1942-04-14); insert into sibling (name,birth) values(Wilbur,1946-11-28)…

SAP RESTFUL接口方式發布SICF實現全路徑

其他相關資料帖可參考: https://blog.csdn.net/woniu_maggie/article/details/146210752 https://blog.csdn.net/SAPmatinal/article/details/134349125 https://blog.csdn.net/weixin_44382089/article/details/128283417 【業務場景】 外部系統不想通過RFC (需…

在windows中安裝或卸載nginx

首先在nginx的安裝目錄下cmd查看nginx的版本: 在看windows的服務中是否nginx注冊為服務了 如果注冊了服務就先將服務卸載了 在nginx的安裝目錄cmd執行命令 NginxService.exe uninstall “NginxService”是對應的注冊的服務名稱 關閉所有的相關nginx的服務這個也…

FaceFusion 技術深度剖析:核心算法與實現機制揭秘

在 AI 換臉技術蓬勃發展的浪潮中,FaceFusion 憑借其出色的換臉效果和便捷的操作,成為眾多用戶的首選工具。從短視頻平臺上的創意惡搞視頻,到影視制作中的特效合成,FaceFusion 都展現出強大的實用性。而這一切的背后,是…

2. Web網絡基礎 - 協議端口

深入解析協議端口與netstat命令:網絡工程師的實戰指南 在網絡通信中,協議端口是服務訪問的門戶。本文將全面解析端口概念,并通過netstat命令實戰演示如何監控網絡連接狀態。 一、協議端口核心知識解析 1. 端口號的本質與分類 端口范圍類型說…

嵌入式學習筆記 - freeRTOS vTaskPlaceOnEventList()函數解析

vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait ); 函數第一個參數為消息隊列等待插入鏈表, void vTaskPlaceOnEventList( List_t * const pxEventList, const TickType_t xTicksToWait ) { configASSERT( pxEventList ); /…

Ubuntu 配置使用 zsh + 插件配置 + oh-my-zsh 美化過程

Ubuntu 配置使用 zsh 插件配置 oh-my-zsh 美化過程 引言zsh 安裝及基礎配置oh-my-zsh 安裝及美化配置oh-my-zsh 安裝主題美化配置主題自定義主題 插件安裝及配置官方插件查看及啟用插件安裝 主題文件備份.zshrcre5et_self.zsh-theme 同步發布在個人筆記Ubuntu 配置使用 zsh …

Xilinx FPGA 重構Multiboot ICAPE2和ICAPE3使用

一、FPGA Multiboot 本文主要介紹基于IPROG命令的FPGA多版本重構,用ICAP原語實現在線多版本切換。需要了解MultiBoot Fallback點擊鏈接。 如下圖所示,ICAP原語可實現flash中n1各版本的動態切換,在工作過程中,可以通過IPROG命令切…

springMVC-11 中文亂碼處理

前言 本文介紹了springMVC中文亂碼的解決方案,同時也貼出了本人遇到過的其他亂碼情況,可以根據自身情況選擇合適的解決方案。 其他-jdbc、前端、后端、jsp亂碼的解決 Tomcat導致的亂碼解決 自定義中文亂碼過濾器 老方法,通過javaW…

mysql-innoDB存儲引擎事務的原理

InnoDB 存儲引擎支持 ACID 事務,其事務機制是通過 Redo Log(重做日志)、Undo Log(回滾日志) 和 事務日志系統 來實現的。下面詳細解析 InnoDB 事務的工作原理。 1.事務的基本特性(ACID) 特性描…