2012-02-26 74 views
2

我正在從現有的GNU makefile重寫cmake構建腳本。這是我試圖寫的第一個cmake腳本。什麼cmake命令與GNU make的vpath相匹配?

GNU make提供vpaths命令,但我找不到一個corrsponding命令。

我已經實現了一個宏來解決它,但我發現它很難涵蓋所有的異常情況。

您有任何解決方案嗎?


在許多來源和目錄下需要一些時間。

宏(VPATH resultSource NumOfSource NumOfDir SOURCELIST DirList) 數學(EXPR startDirIndex 「3 + $ {NumOfSource}」) 數學(EXPR endIndex的 「2 + $ {NumOfSource} + $ {NumOfDir}」)

message(STATUS "startDirIndex: ${startDirIndex}") 
message(STATUS "endIndex: ${endIndex}") 

set(__SRC_LIST__) 
set(__SRC_DIR__) 

set(pos 0) 
foreach(item ${ARGV}) 
    if(${pos} EQUAL ${startDirIndex} 
     OR ${pos} GREATER ${startDirIndex}) 

     list(APPEND __SRC_DIR__ ${item}) 
     #message(STATUS "DIR:${item}") 

    elseif(${pos} GREATER 2) 

     list(APPEND __SRC_LIST__ ${item}) 
     #message(STATUS "SRC:${item}") 

    endif(${pos} EQUAL ${startDirIndex} 
     OR ${pos} GREATER ${startDirIndex}) 

    math(EXPR pos "${pos}+1") 
endforeach(item ${ARGV}) 

#message(STATUS "__SRC_LIST__: ${__SRC_LIST__}") 
#message(STATUS "__SRC_DIR__: ${__SRC_DIR__}") 

#set(SOURCE_EXTENTION cpp c C CPP) 
set(SOURCE_EXTENTION cpp) 
#list(APPEND SOURCE_EXTENTION ${CMAKE_CXX_SOURCE_FILE_EXTENSIONS} ${CMAKE_C_SOURCE_FILE_EXTENSIONS}) 

#message(STATUS "SOURCE_EXTENTION: ${SOURCE_EXTENTION}") 

set(temp_list "") 

foreach(dir ${__SRC_DIR__}) 
    foreach(src ${__SRC_LIST__}) 
     set(cand_src) 
     foreach(postfix ${SOURCE_EXTENTION}) 
      set(cand_src "${dir}/${src}.${postfix}") 
      file(GLOB result ${cand_src}) 
      if(NOT ${result} STREQUAL "") 
       list(APPEND temp_list ${result})      
      endif(NOT ${result} STREQUAL "")        
     endforeach(postfix ${SOURCE_EXTENTION}) 
    endforeach(src ${__SRC_LIST__}) 
endforeach(dir ${__SRC_DIR__}) 

set(${resultSource} ${temp_list}) 

#message(STATUS "temp_list: ${temp_list}") 

endmacro(vpath resultSource NumOfSource NumOfDir sourceList DirList)

+0

嗯,你爲什麼需要它?你能顯示這個宏的代碼嗎? – arrowd 2012-02-26 11:54:44

回答

3

這就是我的想法。完全免責聲明:我不是一個真正的cmake古茹,這個答案完全是基於我的研究後,看完這個問題。我沒有一個項目來測試這個,我從來沒有在我寫的Makefile中使用過vpath

此外,這個問題沒有發佈示例Makefile,也沒有發佈OP使用的宏,這讓我猶豫是否給出了「使用這個」答案,但是在這裏。

首先:爲什麼是我們用我們的Makefilevpath 因爲我不知道vpath是什麼,所以我查了一下。從GNU Make Manual,第4.5節:

化妝的目錄搜索功能促進這種通過自動搜索幾個目錄找到一個前提...... 類似於VPATH變量,但更多的選擇性,是vpath指令(注小寫),它允許您爲特定類別的文件名稱指定搜索路徑:匹配特定模式的搜索路徑。因此,您可以爲一類文件名和其他目錄(或無其他文件名)提供某些搜索目錄。

因此,您使用vpath來查找分佈在多個目錄中的文件。這些文件,我進一步假設,是源文件或在構建過程中創建的中間文件。

我發現了幾個vpath的例子,它們似乎表明它的用法 - this StackOverflow question,this one,最後是Managing Projects with GNU make, 3rd Edition第2.3節。

那麼這就是爲什麼你會使用vpath。所以,繼續:

其次,你如何使用cmake實現相同的事情。這是來自OP的進一步意見會有所幫助的地方。

如果你有多個目標你是從一個目錄結構建築是這樣的:

|- library1/ 
|-- {C++ Source} 
|- Tool/ 
|-- {C++ Source} 
|- Project/ 
|-- src/ 
|---- {C++ Source} 

你應該使用多個CMakeLists.txt,一個在每個子目錄中。在library1中,您將構建庫(ADD_LIBRARY(libNAME src1.cxx src2.cxx src3.cxx)),在Tool中您將添加一個可執行文件(ADD_EXECUTABLE(theTOOL src1.cxx src2.cxx))。最後,在Project/src/中,您可以使用ADD_EXECUTABLE構建項目可執行文件,將其鏈接到您在library1中構建的libNAME

在這種情況下,你永遠需要尋找,因爲你的來源是明確放在CMakeLists.txt

如果做類似上面的,你的源只是分散在許多許多的目錄,這樣的事情:

|-Project/ 
|--src/ 
|----maths/ 
|------ { SOURCE FILES } 
|----sound/ 
|------ { SOURCE FILES } 
|----imagegeneration/ 
|------ { SOURCE FILES } 

在這種情況下,你只建設一件事,並且您只是將您的資源分散到易用性中。在這種情況下,您有幾種選擇。

  1. 您可以使用發佈的答案here自動添加一個類型的所有文件到目標。這是不是應該完成!從cmake --help-command file(重點是我的):

    GLOB將生成一個與globbing表達式匹配的所有文件的列表,並將其存儲到變量中...我們做 不建議使用GLOB從源樹中收集源文件列表
    [請參閱下面的原因]

  2. 您可以使用add_subdirectory指令添加多個子目錄,每個子目錄對應一個源子目錄。這也不理想。 (一些支持文檔:一個link其中討論以這種方式使用的add_subdirectory

  3. 可以使用aux_source_directory從在變量中指定的目錄和存儲收集的源文件。 (如果您對此感興趣,請閱讀cmake --help-command aux_source_directory)。但是,這也是推薦的而不是

那麼爲什麼你不應該使用(1),(2)或(3)? cmake不是替代對於makeMakefiles。相反,cmake生成 a build system,然後您可以使用它來構建您的項目。這是一個值得注意的區別。雖然您可以自動輕鬆地將多個來源添加到您的CMakeLists.txt,但是您會對cmake造成歧義:cmake將無法​​創建知道源文件的構建系統,以確定發生了什麼變化!

這是上述所有三種方法的問題。從cmake --help-command aux_source_directory

雖然這似乎工作, 沒有辦法對CMake的生成時使用已加入 新的源文件,知道構建系統。通常生成的構建系統 知道何時需要重新運行CMake,因爲修改了CMakeLists.txt文件 以添加新源。當源文件剛被添加到 目錄而沒有修改該文件時,必須手動運行 重新運行CMake以生成包含新文件的生成系統。

總結:如何將源文件添加到cmake

使用cmake,你應該明確地加入源文件到您的每個CMakeLists.txt的。如果您正在使用多個目錄分開的代碼邏輯塊,應該在CMakeLists.txt明確地設置,類似下面的東西:

set (MyApplication_SRC_FILES 
    maths/a.cpp 
    maths/b.cpp 
    sound/c.cpp 
    sound/d.cpp 
    imagegeneration/e.cpp 
    imagegeneration/f.cpp 
) 
ADD_EXECUTABLE (MyApplication ${MyApplication_SRC_FILES}) 

這就允許cmake產生構造系統,該系統可以建立你的代碼。在上面的(1),(2)和(3)中列出的構建系統中,有許多方法可以在目錄中添加大量文件;但他們應該謹慎對待,而不是僅僅因爲「這就是我用我的Makefile做到的」。你不寫這個構建系統本身;這是從Makefile退一步,因此應該稍微區別對待。

+0

謝謝。遺留的makefile有太多的源,所以我不能重寫你的建議選項 - 1,2,3 - 我寫了一些宏。它有一些奇怪的。我寫在下面。 – 2012-03-01 04:26:10