2013-10-13 38 views
9

我有一個cmake項目,我有一些模塊,我用Find - *。cmake在應用程序中包含共享模塊。 對於帳戶每次我添加模塊不服用,我已經定義了一種全球LIB變量TOR鏈接器:cmake,丟失在全局變量的概念(和PARENT_SCOPE或add_subdirectory的替代品)

# inside a Find-*.cmake or in the CMakeLists.txt of the modules: 
set(LIB ${LIB} ...) 

所以在最終的應用之一是使用了一些模塊,我可以這樣做:

target_link_libraries(${APP_NAME} ${LIB}) 

然後,我想要在/project_path/modules/foo/build編譯模塊,以便如果一個模塊真的很大,編譯它可以爲所有使用它的應用程序編譯一次。我實現這一目標的方式是從查找加載模塊的CMakeLists.txt - 這樣的cmake *:

# Inside FindFoo.cmake, for loading /project_path/modules/foo/CMakeLists.txt 
# and compile it in /project_path/modules/foo/build 
add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/../modules/${PACKAGE_NAME} 
       ${CMAKE_CURRENT_LIST_DIR}/../modules/${PACKAGE_NAME}/build 
) 
include_directories(${CMAKE_CURRENT_LIST_DIR}/../modules/${PACKAGE_NAME}/include) 

但有時發生一些模塊需要另一個模塊,這樣的add_subdirectory創建新的示波器,並且可以正確加載LIB但不能寫入(當我使用set時,它在更深的範圍內並且不會更改上方的範圍)。爲了繞過此我要補充PARENT_SCOPEset)..所以我試圖將它添加一些模塊,我認爲可以嵌套,並隱藏在一些依賴,但編譯所有我突然面臨着應用程序:

CMake Warning (dev) at /path_to_repo/cmake/FindFooX.cmake:6 (set): 
    Cannot set "LIB": current scope has no parent. 
Call Stack (most recent call first): 
    CMakeLists.txt:14 (find_package) 
This warning is for project developers. Use -Wno-dev to suppress it. 

恐怕這可以從應用程序更改爲我需要哪個模塊或在模塊本身的依賴性樹方面,所以我正在尋找一個更乾淨的解決方案。

回答

20

默認情況下,CMake中的所有變量都是本地的。儘管您可以使用PARENT_SCOPE參數來將局部變量的範圍增加一層,但對於返回值functions而言,這通常是有意義的。

另一方面,爲了查找腳本,您通常需要全局變量的行爲:一旦查找腳本被任何人調用,就希望結果在任何地方都可用。特別是,對同一查找腳本的第二次調用應該重用第一次調用的結果。在CMake中,這是通過將變量存儲到緩存中來實現的。各種find_*調用已自動執行此操作,因此您應該更喜歡使用適用的那些調用。對於任何額外的自定義變量,set提供的功能可存儲到緩存以及:

set(MY_GLOBAL_VARIABLE "Some value" CACHE STRING "Description") 

注意局部變量可以隱藏在其範圍的同名緩存變量。

+0

抱歉,但我一直搞不明白到底如何使用這個緩存的全局變量..我試圖用'set(LIB $ {LIB} $ {PACKAGE_NAME} CACHE STRING'包描述替換'set(LIB $ {LIB} $ {PACKAGE_NAME})'的所有實例「),但最後如果我的消息(」 - $ {LIB}「)'只有我調用的第一個包被包含在$ {LIB}裏面.. – nkint

+0

@nkint查看'set'的文檔I上面鏈接。 CMake假定緩存的值一旦創建後通常不會更新,因此在以後更改時需要額外的'FORCE'參數。 – ComicSansMS

+1

所以我用'set(LIB $ {LIB} $ {PACKAGE_NAME} CACHE STRING「描述FORCE)'替換了任何地方,也嘗試過'INTERNAL',但無論如何不起作用:沒有錯誤,但是在子包中添加了lib 'add_subdirectories'不在上面的範圍內 – nkint

25

可以 '模擬' 的全局變量問題,通過與全球範圍內的屬性:使用

GET_PROPERTY(MyLocalVariable GLOBAL PROPERTY MyGlobalProperty) 

然後,MyLocalVariable包含

SET_PROPERTY(GLOBAL PROPERTY MyGlobalProperty "MyGlobalPropertyValue") 

然後你就可以提取您的全局屬性「 MyGlobalPropertyValue」。

因爲PARENT_SCOPE擴展變量定義的唯一父目錄(而不是其父母),有時它是不夠的,例如,如果您有很深的源代碼樹...