簡體   English   中英

如何構建具有多個相互依賴的子目錄的 C++ 項目?

[英]How can I build a C++ project with multiple interdependent subdirectories?

我有一個 C++ 項目,我在其中使用目錄作為更多的組織元素——人們可能使用 Java 中的包或 PHP 中的目錄的方式。 目錄並不是自給自足的元素,而只是一種組織整個項目並防止我被來源淹沒的方式。 如何構建我的 CMakeLists.txt 文件來處理這個問題? 制作目錄庫似乎不適合這里,因為它們都是相互依賴的,不打算以這種方式使用。

作為一個相關問題,我在 CMake 中看到的多個子目錄的大多數示例(並且這些子目錄不是很多)都忽略或掩蓋了設置include_directories的問題,這是我一直遇到的問題. 沒有組合我的源文件來確定哪個文件依賴於哪個目錄以及在哪個目錄中,無論如何將/src/下的所有目錄設置為潛在的包含目錄並讓 CMake 計算出哪些實際上是依賴的?

這是一個示例結構:

--src
  --top1
    --mid1
      --bot1
        --src1.cpp
        --hdr1.h
      --bot2
        --src2.cpp
        --hdr2.h
    --mid2
      --bot3
        --src3.cpp
        --src4.cpp
        --hdr3.h
  --top2
    --mid3
      --src5.cpp
      --hdr4.h

等等等等。 如何構建我的CMakeLists.txt文件來處理這種結構?

由於項目中的目錄結構只是為了讓文件井井有條,一種方法是使用CMakeLists.txt自動查找src目錄中的所有源文件,並將所有目錄添加為包含頭文件的目錄. 以下 CMake 文件可以作為起點:

cmake_minimum_required(VERSION 3.12)

project (Foo)

file (GLOB_RECURSE Foo_SOURCES CONFIGURE_DEPENDS "src/*.cpp")
file (GLOB_RECURSE Foo_HEADERS CONFIGURE_DEPENDS "src/*.h")

set (Foo_INCLUDE_DIRS "")
foreach (_headerFile ${Foo_HEADERS})
    get_filename_component(_dir ${_headerFile} PATH)
    list (APPEND Foo_INCLUDE_DIRS ${_dir})
endforeach()
list (REMOVE_DUPLICATES Foo_INCLUDE_DIRS)

add_executable(FooExe ${Foo_SOURCES})
target_include_directories(FooExe PRIVATE ${Foo_INCLUDE_DIRS})

這兩個file(GLOB_RECURSE ...命令確定一套源文件和頭文件。該foreach循環計算一組包含所有頭文件的列表目錄,其中的CONFIGURE_DEPENDS國旗在編譯的時候告訴CMake的重新運行該命令的glob .

計算源文件集的一個缺點是 CMake 不會自動檢測何時將新文件添加到您的源代碼樹中。 然后您必須手動重新創建構建文件。

雖然@sakra 對這個問題給出了很好的答案,但我認為更深入地研究它更合適。

出於多種原因,我們希望將代碼分成模塊和庫。 像代碼封裝、可重用性、更容易調試等。這個想法也會在編譯過程中傳播。

換句話說,我們想把編譯過程分成幾個小的編譯步驟,每個步驟都屬於一個模塊。 所以每個模塊都必須有自己的編譯過程。 這就是我們為每個目錄使用一個CMakeLists.txt文件的原因。 因此,每個目錄都有自己的編譯命令,並且在項目的根目錄中會有一個主CMakeLists.txt文件。

這是一個例子。 考慮以下項目結構:

src/
|
- main.cpp
|
_sum/
    |
    - sum.h
    |
    - sum.cpp

我們將有一個CmakeLists.txt每個目錄。 第一個目錄是src/文件夾所在項目的根目錄。 這是該文件的內容:

cmake_minimum_required(VERSION 3.4)
project(multi_file)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_FLAGS "-Wall")

add_subdirectory(src) 

接下來CMakeLists.txt將位於src/目錄中:

add_subdirectory("sum")

add_executable(out main.cpp)
target_link_libraries(out sum)

最后一個將在sum/目錄中:

add_library(sum SHARED sum.cpp)

我希望這有幫助。 我創建了一個github 存儲庫,以防您覺得需要查看代碼或需要進一步解釋。

我不是 CMake 的專家,但由於沒有其他答案,我將查看文檔並試一試。 在不同目錄中組織源文件和包含文件幾乎是常態。

看起來 CMake 允許您提供包含目錄的列表: http : //www.cmake.org/cmake/help/cmake-2-8-docs.html#command : include_directories

所以像:

include_directories("src/top1/mid1/bot1" "src/top1/mid1/bot2/" ... )

這些被傳遞給編譯器,以便它可以找到頭文件,並將為每個源文件傳遞。 所以你的任何源文件都應該能夠包含任何頭文件(我認為這就是你所要求的)。

與此類似,您應該能夠在add_executable命令中列出所有源文件:

add_executable(name "src/top1/mid1/bot1/src1.cpp" "src/top1/id1/bot2/src2.cpp" ...)

所以這將是一種讓一切都構建起來的幼稚方式。 每個源文件都將被編譯並在所有這些目錄中查找頭文件,然后將目標文件鏈接在一起。 考慮是否有任何方法可以簡化這一點,這樣您就不需要這么多包含文件夾,也許只有幾個公共頭文件需要被所有源文件引用。 如果事情變得更復雜,您可以將子層次結構構建到庫等中。還可以考慮將源文件和頭文件分開(例如在 src 和 include 中)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM