2016-04-20 30 views
8

E 'possibile dire CMake per collegare contro una libreria statica invece di condiviso?cmake: target_link_libraries usano libreria statica non condiviso

Nella parte superiore della mia CMakeLists.txt Ho la seguente configurazione:

set(CMAKE_FIND_LIBRARY_SUFFIXES .a ${CMAKE_FIND_LIBRARY_SUFFIXES}) 

Più tardi, aggiungo un binario, e dirgli di collegarsi contro tcmalloc nella modalità di rilascio:

target_link_libraries(${BIN_NAME} optimized tcmalloc_minimal) 

La risultante makefile links nella versione condivisa di tcmalloc:

$ make VERBOSE=1 | grep tcmalloc 
/usr/bin/c++ ... -Wl,-Bdynamic ltcmalloc_minimal 

Un'ulteriore prova:

$ ldd app 
    ... 
    libtcmalloc_minimal.so.4 => /usr/local/lib/libtcmalloc_minimal.so.4 (0x00007eff89733000) 
    ... 

Entrambe le versioni statiche e condivise di tcmalloc esiste:

$ ls -1 /usr/local/lib/libtcmalloc_minimal* 
/usr/local/lib/libtcmalloc_minimal.a 
/usr/local/lib/libtcmalloc_minimal_debug.a 
/usr/local/lib/libtcmalloc_minimal_debug.la 
/usr/local/lib/libtcmalloc_minimal_debug.so 
/usr/local/lib/libtcmalloc_minimal_debug.so.4 
/usr/local/lib/libtcmalloc_minimal_debug.so.4.2.6 
/usr/local/lib/libtcmalloc_minimal.la 
/usr/local/lib/libtcmalloc_minimal.so 
/usr/local/lib/libtcmalloc_minimal.so.4 
/usr/local/lib/libtcmalloc_minimal.so.4.2.6 

Domanda:

Come posso configurare CMake a collegare con la versione statica di tcmalloc?

risposta

0

È possibile creare una funzione di supporto che definisce CMAKE_FIND_LIBRARY_SUFFIXES a perimetro funzione (so therefore doesn't affect the parent scope), che cerca la libreria in questione e imposta una variabile di uscita con il risultato

function(find_static_library LIB_NAME OUT) 

    if (WIN32 OR MSVC) 
     set(CMAKE_FIND_LIBRARY_SUFFIXES ".lib") 
    elseif (UNIX) 
     set(CMAKE_FIND_LIBRARY_SUFFIXES ".a") 
    endif()  

    find_library(
     FOUND_${LIB_NAME}_STATIC 
     ${LIB_NAME} 
     ) 

    if (FOUND_${LIB_NAME}_STATIC) 
     get_filename_component(ABS_FILE ${FOUND_${LIB_NAME}_STATIC} ABSOLUTE) 
    else() 
     message(SEND_ERROR "Unable to find library ${LIB_NAME}") 
    endif() 

    set(${OUT} ${ABS_FILE} PARENT_SCOPE) 

endfunction() 

È quindi possibile chiamare questa funzione da qualche parte il tuo CMakeLists.txt per popolare una variabile con il percorso della libreria.

fallimento nel trovare il risultato e 'un guasto del disco

find_static_library(tcmalloc_minimal TCMALLOC) 

è possibile utilizzare questa variabile nella chiamata a target_link_libraries ed essere sicuri che stai collegando contro la versione statica

target_link_libraries(${BIN_NAME} optimized ${TCMALLOC}) 

Qui è possibile visualizzare il risultato:

$ make VERBOSE=1 | grep tcmalloc 
/usr/bin/c++ ... /usr/local/lib/libtcmalloc_minimal.a ... 
+1

è necessario aggiungere 'unset (FOUND CACHE)' prima della chiamata find_library altrimenti la seconda find_static_library non funzionerà. –

-1

è necessario impostare la variabile CMAKE_FIND_LIBRARY_SUFFIXES in questo modo:

set(CMAKE_FIND_LIBRARY_SUFFIXES .a) 

perché in CMAKE_FIND_LIBRARY_SUFFIXES di default c'è anche il suffisso .so (e non sembra cercare in ordine di inserimento). Per consentire la portabilità, è necessario aggiungere altri suffissi (vedere here per i valori predefiniti di CMAKE_FIND_LIBRARY_SUFFIXES su piattaforme diverse).

+1

Che non ha funzionato - Ho fatto solo quello che hai suggerito, e si collega ancora alla lib condivisa. Secondo [documenti] (https://cmake.org/cmake/help/v3.0/variable/CMAKE_FIND_LIBRARY_SUFFIXES.html) quell'impostazione è solo per 'find_library' non per' target_link_libraries' –

+0

Sì, richiede l'uso di find_library. Di solito utilizzo find_library per trovare librerie esterne e archiviarle in variabili CMake; poi li aggiungo alle librerie di destinazione usando le variabili. –

+0

Per favore, potresti mostrare come farlo? –

1

Se è necessario solo supportare piattaforme non Windows, quindi this old email dalla mailing list di CMake da uno degli sviluppatori di Kitware fornisce il metodo più semplice.In pratica, usa find_library() per trovare la posizione della libreria attuale, favorendo le librerie statiche su quelle condivise elencandole prima nei nomi da cercare. cioè

find_library(TCMALLOC_LIB NAMES libtcmalloc_minimal.a tcmalloc_minimal) 

Si potrebbe quindi collegare alla libreria trovato nel solito modo:

target_link_libraries(${BIN_NAME} ${TCMALLOC_LIB}) 

Si potrebbe ottenere più intelligente su come si definisce il nome della libreria statico se è necessario supportare le piattaforme in cui una libreria statica è chiamato qualcosa di diverso da lib???.a. Dovresti utilizzare le variabili CMAKE_STATIC_LIBRARY_PREFIX e CMAKE_STATIC_LIBRARY_SUFFIX per quello.

Su Windows, il problema è che non è possibile distinguere tra una libreria statica e la libreria di importazione per una DLL, come discusso in this old issue nel bug tracker di Kitware. Entrambi hanno l'estensione file .lib, quindi non è possibile utilizzare l'estensione per capire se un determinato file è una libreria statica o meno, a differenza delle piattaforme basate su Unix dove è possibile.