2015-04-30 22 views
9

I documenti per lo stato di CMake 3.2.2, che è possibile utilizzare le espressioni del generatore per la firma install(<FILES|PROGRAMS> ...). Stavo cercando di utilizzare le espressioni del generatore in altre firme di install(), ma a quanto pare non funziona. Mi piacerebbe fare qualcosa di simile:Espressione generatore per comandi di installazione()

install(TARGETS foo EXPORT fooConfig 
     RUNTIME DESTINATION "Bin/$<CONFIG>" 
     LIBRARY DESTINATION "Lib/$<CONFIG>" 
     ARCHIVE DESTINATION "Lib/$<CONFIG>" 

Ho anche provato a chiamare install() più volte come questo:

install(TARGETS foo EXPORT fooConfig 
     RUNTIME DESTINATION "Bin/Debug" CONFIGURATIONS Debug 
     LIBRARY DESTINATION "Lib/Debug" CONFIGURATIONS Debug 
     ARCHIVE DESTINATION "Lib/Debug" CONFIGURATIONS Debug 
install(TARGETS foo EXPORT fooConfig 
     RUNTIME DESTINATION "Bin/Release" CONFIGURATIONS Release 
     LIBRARY DESTINATION "Lib/Release" CONFIGURATIONS Release 
     ARCHIVE DESTINATION "Lib/Release" CONFIGURATIONS Release 
install(TARGETS foo EXPORT fooConfig 
     RUNTIME DESTINATION "Bin/MinSizeRel" CONFIGURATIONS MinSizeRel 
     LIBRARY DESTINATION "Lib/MinSizeRel" CONFIGURATIONS MinSizeRel 
     ARCHIVE DESTINATION "Lib/MinSizeRel" CONFIGURATIONS MinSizeRel 
install(TARGETS foo EXPORT fooConfig 
     RUNTIME DESTINATION "Bin/RelWithDebInfo" CONFIGURATIONS RelWithDebInfo 
     LIBRARY DESTINATION "Lib/RelWithDebInfo" CONFIGURATIONS RelWithDebInfo 
     ARCHIVE DESTINATION "Lib/RelWithDebInfo" CONFIGURATIONS RelWithDebInfo 

Questo fa sì che CMake per emettere un errore sulla falsariga di target 'pippo' esportati più di una volta in "fooConfig".

Non riesco a utilizzare CMAKE_BUILD_TYPE qui senza aggiornare la cache di CMake e rieseguire la compilazione. Piuttosto, voglio utilizzare la funzione di compilazione batch di Visual Studio, che crea per me configurazioni multiple.

C'è stato un piccolo trucco che ho provato anche io. Ho notato che il progetto INSTALL generato da CMake sta semplicemente richiamando uno script CMake ${CMAKE_BINARY_DIR}/cmake_install.cmake con l'argomento -DBUILD_TYPE=$(Configuration). Così ho provato il seguente:

install(TARGETS foo EXPORT fooConfig 
     RUNTIME DESTINATION "Bin/\${BUILD_TYPE}" 
     LIBRARY DESTINATION "Lib/\${BUILD_TYPE}" 
     ARCHIVE DESTINATION "Lib/\${BUILD_TYPE}" 

Questo ha funzionato bene per l'installazione. Tuttavia, lo script di esportazione installato, ovvero l'output di install(EXPORT fooConfig DESTINATION .) ora tenta anche di utilizzare ${BUILD_TYPE}, che non è impostato nel momento in cui l'utente include quello script ...

Se qualcuno conosce un altro modo per raggiungere i miei obiettivi, si prega di lasciare conoscermi.

risposta

6

Sfortunatamente il comando install supporta solo espressioni generatore per l'elenco di file da installare, ma non per la directory di destinazione.

lo consiglio a attaccare con il vostro piccolo hack, ma utilizzare CMAKE_INSTALL_CONFIG_NAME invece di CMAKE_BUILD_TYPE, cioè .:

install(TARGETS foo EXPORT fooConfig 
     RUNTIME DESTINATION "Bin/\${CMAKE_INSTALL_CONFIG_NAME}" 
     LIBRARY DESTINATION "Lib/\${CMAKE_INSTALL_CONFIG_NAME}" 
     ARCHIVE DESTINATION "Lib/\${CMAKE_INSTALL_CONFIG_NAME}" 

CMAKE_INSTALL_CONFIG_NAME è impostato per la configurazione di generazione effettivamente utilizzato per l'installazione nel cmake_install.cmake script generato.

Gli script di esportazione generati (ad es., fooConfig-debug.cmake) può essere risolto automaticamente aggiungendo uno script di patch al processo di installazione. Generare un file patch_export_files.cmake con il seguente contenuto nella directory di origine:

file(GLOB_RECURSE _configFiles "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/fooConfig-*.cmake") 
foreach(_configFile ${_configFiles}) 
    file (READ "${_configFile}" _contents) 
    string (REGEX MATCH "configuration \"[A-Za-z]+\"" _configName "${_contents}") 
    if (_configName MATCHES "\"([A-Za-z]+)\"") 
     message(STATUS "Patching: ${_configFile}") 
     string (REPLACE "\${CMAKE_INSTALL_CONFIG_NAME}" "${CMAKE_MATCH_1}" _patchedContents "${_contents}") 
     file (WRITE "${_configFile}" "${_patchedContents}") 
    endif() 
endforeach() 

Lo script cerotto deve essere eseguito al momento dell'installazione con l'aggiunta di un install(SCRIPT ... chiamata dopo il install(EXPORT ...:

install(EXPORT fooConfig DESTINATION .) 
... 
install(SCRIPT patch_export_files.cmake) 

Lo script di patch prima analizza la configurazione per cui lo script di esportazione generato è valido dal suo commento di intestazione e quindi sostituisce ogni utilizzo di ${CMAKE_INSTALL_CONFIG_NAME} con il nome di configurazione.

+0

Mi aspettavo di dover fare qualcosa di simile ... È un peccato che CMake non supporti qualcosa del genere. Nel loro sistema di tracciamento dei problemi ho visto che hanno implementato espressioni generatrici per gli argomenti DESTINATION di tutte le firme install() di recente, ma non esiste ancora alcuna versione ufficiale con questa funzionalità. Quindi per gli utenti futuri: le versioni recenti di CMake (> 3.2.2) probabilmente già supportano le espressioni del generatore per altre firme che installano (FILES). – Manuzor

2

Sto lavorando a un progetto che richiede build con diverse configurazioni. Il modo in cui ho raggiunto questo è l'utilizzo di "ExternalProject".

ho creato un repository di esempio per mostrare l'idea: https://github.com/mpaluru/cmake_multiple_build_configs_example

(Linux è l'ambiente che per lo più usare e non hanno accesso a Visual Studio.) Se si passa sulla bandiera -G nel livello superiore CMakeLists.txt, dovresti essere in grado di generare i tuoi file VS. Ho testato questo su Linux e "make -j" funziona bene. Entrambe le configurazioni di debug e release si sviluppano in parallelo.

Riepilogo: Si crea un nuovo progetto di superbuild che chiama il progetto usando ExternalProject_Add con diversi CMAKE_BUILD_TYPE.

E in base al tipo di build, si passano definizioni diverse o si installa in modo diverso.

+0

ExternalProject è una buona idea, ma ciò richiederebbe la modifica di un albero di sorgenti esistente, giusto? – Manuzor

+0

NO e SÌ. Dipende da come è configurato il tuo progetto attuale. Se hai già avuto cura di fare cose diverse in base alla variabile CMAKE_BUILD_TYPE, non devi assolutamente modificare il progetto esistente. Tutto ciò che fai è creare un nuovo progetto wrapper come ho indicato nel codice di esempio. –

+0

Ma questo progetto wrapper dovrebbe vivere al di fuori del codice esistente, almeno un livello al di sopra della radice di origine originale. O c'è un modo per incorporare questo wrapper direttamente nella root? Forse tramite inclusione multipla? – Manuzor

Problemi correlati