2011-12-21 62 views
9

我有一個大型的代碼庫,它可以編譯幾十個庫文件和幾個可執行文件。什麼是CMake「項目」指令的正確使用

代碼庫按層次分解,並在幾乎每個級別都構建庫。

我已經通過並在每個目錄中放置一個CMakeLists.txt文件來構建每個庫。

在每個CMakeLists.txt中,我都使用了「project(xxx)」指令。這爲我定義了我明智使用的PROJECT_NAME,PROJECT_SOURCE_DIR和PROJECT_BINARY_DIR變量。

但是,其中一個團隊對這種方法感到不滿,因爲他找不到任何其他人做過這件事的真實世界的例子。他經常引用KitWare的例子不使用這種方法,因此我們也不應該這樣做。

他所倡導的另一種方法是在每個makefile中設置這些變量,這看起來很像「項目」給你的東西。

我真的不明白他的觀點,並且在說服他的時候沒有什麼進展。任何人都可以通過這種方式闡明使用項目指令的缺點。

我把自己放在你的集體智慧上嗎?

+0

你如何使用'PROJECT_NAME','PROJECT_SOURCE_DIR'和'PROJECT_BINARY_DIR'變量?這些庫是獨立的還是它們只是主庫/應用程序的一部分? – 2011-12-21 09:19:33

+0

我在生成源代碼的宏內部使用這些變量。我創建了一個稱爲$ {PROJECT_NAME} _SPDEF的頂級目標,其他項目可以依靠這些目標來強制生成這些目標。我還使用_DIR變量將生成的代碼放置在適當的位置。 – ScaryAardvark 2011-12-21 09:53:58

回答

12

首先,它使您能夠使用<projectName>_BINARY_DIR<projectName>_SOURCE_DIR,但這不是主要優點。如果您給CMake一個項目名稱,那麼它會爲他們自己的目錄中的每個子項目生成構建目標。這意味着無論您使用的是GNU Make,Eclipse CDT,XCode還是任何其他支持的生成器,都可以單獨構建子項目。例如GNU Make的每個子項目都有它自己的完整版本系統。

您可以通過PROJECT_NAME和根項目名稱CMAKE_PROJECT_NAME訪問當前項目名稱。

編輯:我剛剛意識到下面將是任何構建目標的標準CMake行爲,無論他們是否是項目。我將在這裏保留一般信息,但它與回答無關:

假設我有一個C++庫,並且可以生成三個二進制可執行文件; Maintests/test1examples/ex1。我可以使用ALL目標在我稱爲CMake的目錄中運行make,運行make ex1,或者我可以將目錄更改爲examples/,並使用該目錄中的make構建示例。這將構建所有依賴項目和庫,即使它們位於目錄結構中的其他位置,但不會構建Maintests/test1或它們依賴的任何庫,而這些庫不包含在examples/ex1中。如果我然後從主目錄運行make,它將不會重建examples/ex1所依賴的任何庫,除非它們的源已更改。

+1

能夠「cd」到構建層次結構的任何級別並「做到全部」,並從這個級別構建所有人工製品對我來說是一個巨大的勝利。謝謝。 – ScaryAardvark 2011-12-21 10:28:39

+0

@ScaryAardvark能夠爲不同的編譯器運行不同的命令,並且自動將不同的代碼與不同的操作系統包含在一起非常好,再加上使用幾行代碼很容易就可以完成相當高級的操作。我用CMake的'zip'壓縮資產,它可以在任何平臺/ IDE /工具鏈上正常工作。它還使得ARM等交叉編譯非常容易。您還應該查看CMake的內置測試系統[CTest](http://www.vtk.org/Wiki/CMake_Testing_With_CTest)。還有像詹金斯這樣的CI系統的CMake插件。 – 2011-12-21 10:40:08

+0

是的,我對此很熟悉。我遇到的一個問題是,cmake如何處理同一個編譯器的不同版本......即我們的項目樹只有一部分只能在sunstudio11下編譯,而且大部分都需要sunstudio12。我想我會提出另一個問題,但謝謝:) – ScaryAardvark 2011-12-21 12:11:44

0

如果庫是真正獨立的項目,那麼使用project命令是有意義的。但是,如果他們不是,我會將它們作爲子目錄添加到您的根目錄CmakeLists.txt。如果您需要知道當前正在處理的目錄,則可以使用變量CMAKE_CURRENT_SOURCE_DIRCMAKE_CURRENT_BINARY_DIR

+0

是否有CMAKE_CURRENT_PROJECT。如果有,那麼我可以看到你的觀點,但是如果我必須使用set()來創建這個變量(或類似的東西),那麼爲什麼不使用「project」並且爲我創建了所有的變量。 – ScaryAardvark 2011-12-21 09:54:56

0

我今天發現了一個很好的使用例子:添加Doxygen文檔。

我使用CMake(和Ninja)來構建我的個人C++項目。我決定隨心所欲地將一些Doxygen文檔添加到我非常完整但沒有記錄的工作中。我還認爲將它添加到其他項目中並且只要我研究如何使其儘可能通用就行了。

首先,我生成了一個標準的Doxygen模板並重新命名了它。

cd my_projects/projectx 
doxygen -g Doxyfile 
mv Doxyfile Doxyfile.in 

請注意.in擴展名。如果我理解正確,可能不必要,但是常規。

接下來,我在我的CMakeLists.txt文件中添加了下面的代碼塊,就在定義我的目標之前(不知道這是否重要,但CMake有時候對某些命令的順序很挑剔)。

FIND_PACKAGE(Doxygen) 
IF("${DOXYGEN_FOUND}" MATCHES "^YES$") 
    CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in 
        ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile 
        @ONLY) 
    ADD_CUSTOM_TARGET( doc ALL 
         COMMAND ${DOXYGEN_EXECUTABLE} 
         ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile 
         WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} 
         COMMENT "Doxygenating..." 
         VERBATIM) 
ENDIF() 

這創建了一個名爲doc的新目標。指定ALL將其添加到默認的「all」目標,但這是可選的。指定@ONLY確保任何「$ {variable}」類型的變量不會被CONFIGURE_FILE擴展,只會被「@ variable @」類型擴展。有點令人困惑的是(至少對我來說),CMAKE_CURRENT_SOURCE_DIR似乎是指項目目錄,而CMAKE_CURRENT_BINARY_DIR是指編譯目錄。

最後,這是PROJECT_NAME等進來的地方,我編輯了Doxyfile.in。

這是我的新Doxyfile.in的開頭:

DOXYFILE_ENCODING  = UTF-8 
PROJECT_NAME   = "@[email protected]" 
PROJECT_NUMBER   = @[email protected] 
PROJECT_BRIEF   = 
PROJECT_LOGO   = @[email protected]/res/doc_logo-200x55.png 
OUTPUT_DIRECTORY  = @[email protected]/doc 

你的想法,我想。一旦這是完全通用的(這是一個詞?)我可以將它複製到我的其他項目,只要我標記我的代碼,我將有很好的文檔到處。

注意PROJECT_BRIEF未指定。我還沒有完成這個,還有幾個空白讓我思考。例如PROJECT_VERSION_TWEAK實際上並未包含任何內容。我將不得不找到一種方法讓我的內部編號在那裏。