Cmake命令之a(chǎn)dd_subdirectory介紹

  • 命令格式

    add_subdirectory (source_dir [binary_dir] [EXCLUDE_FROM_ALL])
    添加一個子目錄并構建該子目錄。

  • 命令解析

    • source_dir
      必選參數(shù)。該參數(shù)指定一個子目錄,子目錄下應該包含CMakeLists.txt文件和代碼文件。子目錄可以是相對路徑也可以是絕對路徑,如果是相對路徑,則是相對當前目錄的一個相對路徑。
    • binary_dir
      可選參數(shù)。該參數(shù)指定一個目錄,用于存放輸出文件??梢允窍鄬β窂揭部梢允墙^對路徑,如果是相對路徑,則是相對當前輸出目錄的一個相對路徑。如果該參數(shù)沒有指定,則默認的輸出目錄使用source_dir。
    • EXCLUDE_FROM_ALL
      可選參數(shù)。當指定了該參數(shù),則子目錄下的目標不會被父目錄下的目標文件包含進去,父目錄的CMakeLists.txt不會構建子目錄的目標文件,必須在子目錄下顯式去構建。例外情況:當父目錄的目標依賴于子目錄的目標,則子目錄的目標仍然會被構建出來以滿足依賴關系(例如使用了target_link_libraries)

??此外需要注意的是,因為add_subdirectory增加的構建子目錄,CMake構建工程會自動將該子目錄添加到編譯和鏈接的搜索目錄中,以保證整個構建工程能滿足依賴,這也是為什么使用add_subdirectory后不需要將子文件夾加入到頭文件或庫文件搜索目錄也能搜索到子目錄的頭文件或庫文件。

  • 舉例說明

    目錄結構及說明如下:

    ├── CMakeLists.txt????#父目錄的CMakeList.txt
    ├── main.cpp????#源文件,包含main函數(shù)
    ├── sub????#子目錄
    ?└── CMakeLists.txt????#子目錄的CMakeLists.txt
    ?└── test.h????#子目錄頭文件
    ?└── test.cpp????#子目錄源文件
    ?

    子目錄sub 下的test.cpp定義了一個函數(shù)test(),將輸入?yún)?shù)打印出來,相應的頭文件test.h則對test()進行聲明,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.txtadd_subdirectory 只指定了source_dir。
    # 父目錄下的CMakeLists.txt
    cmake_minimum_required(VERSION 3.10.2)
    project(test)
    
    add_subdirectory(sub) 
    

    在父目錄下調(diào)用cmake .構建之后,在sub目錄下會出現(xiàn)libsub.a庫,說明當不指定binary_dir,輸出目標文件就會放到source_dir目錄下。

    • 場景2:父目錄CMakeLists.txtadd_subdirectory 指定了source_dirbinary_dir。
    # 父目錄下的CMakeLists.txt
    cmake_minimum_required(VERSION 3.10.2)
    project(test)
    
    add_subdirectory(sub output) 
    

    在父目錄下調(diào)用cmake .構建之后,在output目錄下會出現(xiàn)libsub.a庫,sub目錄下則沒有libsub.a。說明當指定binary_dir,輸出目標文件就會放到binary_dir目錄下。

    • 場景3:父目錄CMakeLists.txtadd_subdirectory 指定了EXCLUDE_FROM_ALL選項。
    # 父目錄下的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 .構建之后,在output目錄或sub目錄下不會出現(xiàn)libsub.a庫,說明當指定EXCLUDE_FROM_ALL選項,子目錄的目標文件不會生成。

    • 場景4:父目錄CMakeLists.txtadd_subdirectory 指定了EXCLUDE_FROM_ALL選項,且父目錄的目標文件依賴子目錄的目標文件。
    # 父目錄下的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 .構建之后,在output目錄出現(xiàn)libsub.a庫,說明即使指定EXCLUDE_FROM_ALL選項,當父目錄目標文件對子目錄目標文件存在依賴關系時,子目錄的目標文件仍然會生成以滿足依賴關系。

?
?最后,以一個完整的例子來結束本文(sub目錄下的CMakeList.txt、test.h、test.cpp等文件內(nèi)容如上文所示,沒有變化),父目錄下的main.cppCMakeList.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!

附錄:參考資料

  1. https://cmake.org/cmake/help/latest/command/add_subdirectory.html
最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內(nèi)容