2013-10-13 29 views
9

Bazı modüllere sahip olduğum bir cmake projem var ve uygulamada paylaşılan modülleri dahil etmek için Find - *. Cmake kullanıyorum. hesapta ben eklemek her modül almayan, ben bağlayıcı tor küresel LIB değişkenlerin bir tür tanımlamış: Nihai uygulamaların birinde öylesinecmake, global değişkenler kavramında kayboldu (ve PARENT_SCOPE veya add_subdirectory alternatifleri)

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

elimden gelen sadece bazı modülleri kullanır:

target_link_libraries(${APP_NAME} ${LIB}) 

Daha sonra, bir modülün gerçekten büyük olması durumunda, onu kullanan tüm uygulamalar için bir kez derlenebilmesi için, /project_path/modules/foo/build numaralı derlenmiş modüllere sahip olmak isterim. . Bunu elde ediyorum yolu Bul gelen modülün CMakeLists.txt yüklemek için - bu şekilde * 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) 

Ama add_subdirectory oluşturur, böylece bazı modül başka modülleri gerektirdiğini bazen oldu Yeni kapsamlar ve doğru LIB yükleyebilir, ancak yazamazsınız (set kullandığınızda, daha geniş bir kapsamdadır ve üst kapsamı değiştirmez). bypass için bu ben ..) set içinde PARENT_SCOPE eklemek zorunda yüzden ben bazı bağımlılıkları iç içe ve gizlenebilir düşünüyorum bazı modülde eklemek için çalıştı ama aniden karşı karşıya tüm uygulamayı derleme var:

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. 

Bu modülün ihtiyaç duyduğum modül veya modüllerdeki bağımlılık ağacına göre uygulamadan uygulamaya geçebileceğinden korkuyorum, bu yüzden daha temiz bir çözüm arıyorum.

cevap

20

CMake'deki tüm değişkenler varsayılan olarak yereldir. Yerel bir değişkenin kapsamını tek bir katmanla artırmak için PARENT_SCOPE parametresini kullanabilmenize rağmen, çoğunlukla functions döndürme değerleri için anlamlıdır.

Diğer yandan komut dosyalarını bulmak için genellikle genel değişkenin davranışını istersiniz: Bulma komut dosyası herkes tarafından çağrıldıktan sonra, sonuçların her yerde kullanılabilir olmasını istersiniz. Özellikle, aynı bulma betiğine yapılan ikinci bir çağrı, ilk aramanın sonuçlarını yeniden kullanmalıdır. CMake'de bu, değişkenleri önbelleğe kaydederek elde edilir. Çeşitli find_* çağrıları zaten bunu otomatik olarak yapar, bu nedenle geçerli olanları kullanmayı tercih etmelisiniz. ek özel değişkenler için, set yanı önbelleğe saklamak için yeteneği sunar: Yerel değişkenler kendi kapsamına aynı adı önbelleğe değişkenleri gizleyebileceğinizi

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

Not.

+0

üzgünüm ama anlamadım var Bu önbelleğe alınmış global değişkenleri tam olarak nasıl kullanacağım .. 'set (LIB $ {LIB} $ {PACKAGE_NAME})' nin tüm örneklerini 'set (LIB $ {LIB} $ {PACKAGE_NAME} CACHE STRING" paket açıklaması ile değiştirmeye çalıştım) ")' ama sonunda mesajım ("- $ {LIB}") 'sadece aradığım ilk paket $ {LIB} içinde yer almaktadır. – nkint

+0

@ nkint' set' için belgelere göz atın yukarıda bağlantılı. CMake, önbelleğe alınan değerlerin genellikle oluşturulduktan sonra güncellenmeyeceğini varsayar, bu nedenle daha sonra değiştirirken ek bir "FORCE" parametresine ihtiyacınız vardır. – ComicSansMS

+1

bu yüzden her yerde "set" (LIB $ {LIB} $ {PACKAGE_NAME} CACHE STRING "Açıklama" FORCE) ile de, "INTERNAL" ile de denedim, ancak yine de çalışmıyor: Hata yok, ancak alt paketin içinde eklenen lib eklendi 'add_subdirectories' ile üst kapsamda artık mevcut değil – nkint

25
Sen KÜRESEL kapsamı ile özelliklerini kullanarak, KÜRESEL değişken davranışlar 'taklit' olabilir

: Sonra

GET_PROPERTY(MyLocalVariable GLOBAL PROPERTY MyGlobalProperty) 

, MyLocalVariable içeren kullanarak

SET_PROPERTY(GLOBAL PROPERTY MyGlobalProperty "MyGlobalPropertyValue") 

Ardından global özelliğini çıkarabilir " MyGlobalPropertyValue".

PARENT_SCOPE durumlar vardır derin bir kaynak ağacını varsa, örneğin yeterli değil olan değişken sadece üst dizine tanımları (ve onun velilere), uzanır Çünkü ...