-
命令格式
add_subdirectory
(source_dir [binary_dir] [EXCLUDE_FROM_ALL
])
添加一個(gè)子目錄并構(gòu)建該子目錄。 -
命令解析
-
source_dir
必選參數(shù)。該參數(shù)指定一個(gè)子目錄,子目錄下應(yīng)該包含CMakeLists.txt
文件和代碼文件。子目錄可以是相對路徑也可以是絕對路徑,如果是相對路徑,則是相對當(dāng)前目錄的一個(gè)相對路徑。 -
binary_dir
可選參數(shù)。該參數(shù)指定一個(gè)目錄,用于存放輸出文件。可以是相對路徑也可以是絕對路徑,如果是相對路徑,則是相對當(dāng)前輸出目錄的一個(gè)相對路徑。如果該參數(shù)沒有指定,則默認(rèn)的輸出目錄使用source_dir
。 -
EXCLUDE_FROM_ALL
可選參數(shù)。當(dāng)指定了該參數(shù),則子目錄下的目標(biāo)不會被父目錄下的目標(biāo)文件包含進(jìn)去,父目錄的CMakeLists.txt
不會構(gòu)建子目錄的目標(biāo)文件,必須在子目錄下顯式去構(gòu)建。例外情況:當(dāng)父目錄的目標(biāo)依賴于子目錄的目標(biāo),則子目錄的目標(biāo)仍然會被構(gòu)建出來以滿足依賴關(guān)系(例如使用了target_link_libraries)
。
-
??此外需要注意的是,因?yàn)閍dd_subdirectory增加的構(gòu)建子目錄,CMake構(gòu)建工程會自動將該子目錄添加到編譯和鏈接的搜索目錄中,以保證整個(gè)構(gòu)建工程能滿足依賴,這也是為什么使用add_subdirectory后不需要將子文件夾加入到頭文件或庫文件搜索目錄也能搜索到子目錄的頭文件或庫文件。
-
舉例說明
目錄結(jié)構(gòu)及說明如下:
├── CMakeLists.txt????#父目錄的CMakeList.txt
├── main.cpp????#源文件,包含main函數(shù)
├── sub????#子目錄
?└── CMakeLists.txt????#子目錄的CMakeLists.txt
?└── test.h????#子目錄頭文件
?└── test.cpp????#子目錄源文件
?子目錄
sub
下的test.cpp
定義了一個(gè)函數(shù)test()
,將輸入?yún)?shù)打印出來,相應(yīng)的頭文件test.h
則對test()
進(jìn)行聲明,CMakelists.txt
則將sub
下的源文件編譯成庫文件。// sub/test.cpp #include "test.h" #include <iostream> void test(std::string str) { std::cout << str << std::endl; }
// sub/test.h #include <string> void test(std::string str);
# sub/CMakeLists.txt cmake_minimum_required(VERSION 3.10.2) project(sub) add_library(sub test.cpp)
-
場景1:父目錄
CMakeLists.txt
的add_subdirectory
只指定了source_dir
。
# 父目錄下的CMakeLists.txt cmake_minimum_required(VERSION 3.10.2) project(test) add_subdirectory(sub)
在父目錄下調(diào)用
cmake .
構(gòu)建之后,在sub
目錄下會出現(xiàn)libsub.a
庫,說明當(dāng)不指定binary_dir
,輸出目標(biāo)文件就會放到source_dir
目錄下。-
場景2:父目錄
CMakeLists.txt
的add_subdirectory
指定了source_dir
和binary_dir
。
# 父目錄下的CMakeLists.txt cmake_minimum_required(VERSION 3.10.2) project(test) add_subdirectory(sub output)
在父目錄下調(diào)用
cmake .
構(gòu)建之后,在output
目錄下會出現(xiàn)libsub.a
庫,sub
目錄下則沒有libsub.a
。說明當(dāng)指定binary_dir
,輸出目標(biāo)文件就會放到binary_dir
目錄下。-
場景3:父目錄
CMakeLists.txt
的add_subdirectory
指定了EXCLUDE_FROM_ALL
選項(xiàng)。
# 父目錄下的CMakeLists.txt cmake_minimum_required(VERSION 3.10.2) project(test) add_subdirectory(sub output EXCLUDE_FROM_ALL) add_executable(test main.cpp)
在父目錄下調(diào)用
cmake .
構(gòu)建之后,在output
目錄或sub
目錄下不會
出現(xiàn)libsub.a
庫,說明當(dāng)指定EXCLUDE_FROM_ALL
選項(xiàng),子目錄的目標(biāo)文件不會生成。-
場景4:父目錄
CMakeLists.txt
的add_subdirectory
指定了EXCLUDE_FROM_ALL
選項(xiàng),且父目錄的目標(biāo)文件依賴子目錄的目標(biāo)文件。
# 父目錄下的CMakeLists.txt cmake_minimum_required(VERSION 3.10.2) project(test) add_subdirectory(sub output EXCLUDE_FROM_ALL) add_executable(test main.cpp) target_link_libraries(test sub)
在父目錄下調(diào)用
cmake .
構(gòu)建之后,在output
目錄會
出現(xiàn)libsub.a
庫,說明即使指定EXCLUDE_FROM_ALL
選項(xiàng),當(dāng)父目錄目標(biāo)文件對子目錄目標(biāo)文件存在依賴關(guān)系時(shí),子目錄的目標(biāo)文件仍然會生成以滿足依賴關(guān)系。 -
場景1:父目錄
?
?最后,以一個(gè)完整的例子來結(jié)束本文(sub
目錄下的CMakeList.txt
、test.h
、test.cpp
等文件內(nèi)容如上文所示,沒有變化),父目錄下的main.cpp
和CMakeList.txt
如下:
# 父目錄下的CMakeLists.txt
cmake_minimum_required(VERSION 3.10.2)
project(test)
include_directories(sub)
add_subdirectory(sub output)
add_executable(test main.cpp)
target_link_libraries(test sub)
# 父目錄下的main.cpp
#include "test.h"
#include <iostream>
int main(int argc, char** argv)
{
std::cout << "In main..." << std::endl;
test("hello, world!");
return 0;
}
# 輸出
> cmake --build .
Scanning dependencies of target sub
[ 25%] Building CXX object output/CMakeFiles/sub.dir/test.cpp.o
[ 50%] Linking CXX static library libsub.a
[ 50%] Built target sub
Scanning dependencies of target test
[ 75%] Building CXX object CMakeFiles/test.dir/main.cpp.o
[100%] Linking CXX executable test
[100%] Built target test
>./test
In main...
hello, world!