2015-06-22 8 views
8

ho projectA, in cui sto importazione di una biblioteca con:Esportazione di una libreria importata

add_library(foo STATIC IMPORTED) 
set_property(TARGET foo PROPERTY IMPORTED_LOCATION /path/to/foo.a) 

Ho quindi utilizzare foo in più punti all'interno del progetto, e tutto funziona bene.

Un paio di livelli di directory in basso Voglio esportare una libreria creata all'interno di questo progetto per l'utilizzo in un altro progetto con una configurazione CMake completamente disconnessa. Ho:

... 
target_link_libraries(thislib foo) 
export(TARGETS thislib FILE /path/to/thislib.cmake) 

L'importazione ProjectB deve anche foo però (perché la libreria importata ne ha bisogno), e si lamenta che cannot find -lfoo. Ho provato ad aggiungere al comando export, ma poi ottengo:

CMake Error at thislib/CMakeLists.txt:37 (export): 
    export given target "foo" which is not built by this project. 

voglio solo esportare la stessa configurazione che uso a livello locale per il progetto altro (importazione). Non voglio dover dire esplicitamente al progetto B circa foo. C'è un modo per realizzare questo?

risposta

1

Non ho trovato una soluzione reale per il problema come indicato, ma sto postando la mia soluzione alternativa per riferimento futuro.

Mi sono reso conto che la dipendenza fooera stata emessa nell'export; semplicemente non aveva un percorso con esso. E poiché non ho ancora capito come ottenere cmake per esportare il percorso insieme a esso, ho ripristinato il mio comando export a quello mostrato nella domanda sopra (senza foo).

Poi sono tornato al luogo originario in cui foo veniva importato e rimosso il add_library e set_property, la loro sostituzione con questo:

set(foo /path/to/foo.a) 

poi cambiato il target_link_libraries a:

target_link_libraries(thislib ${foo}) 

In altre parole, piuttosto che renderla una vera "libreria importata", è solo un percorso di libreria grezza. Questo viene scritto correttamente nel file di esportazione e consente al link B di collegarsi.

+1

Un problema è che non consente di impostare proprietà di destinazione come INTERFACE_INCLUDE_DIRECTORIES – RiaD

0

È necessario

  1. Esporta foo da dove si è costruito (a, diciamo, foolibs.cmake)
  2. Invece di utilizzare /path/to/thislib.cmake direttamente (il file di esportazione generato da export(TARGETS thislib... crearne un'altra, thislib-and-deps.cmake che comprende entrambi:

    include(<...>/foolibs.cmake) 
    include(${CMAKE_CURRENT_LIST_DIR}/thislib.cmake) 
    
+0

Esiste una soluzione facile per implementare questo in modo riutilizzabile senza implementare un sacco di codice CMake per progetto? Questo non sembra essere il * CMake-way-to-go *. Attualmente ripeto la chiamata 'find_package ( CONFIG)' per ogni dipendenza transitiva, che fa schifo, poiché rompe il concetto di dipendenza transitiva. –

0

Anche io non riesco a trovare un modo ideale per farlo. Ma ecco la soluzione che sto usando per ora. È un lavoro extra, e non ASCIUTTO, ma penso che raggiunga la cosa giusta.

Imagine lib B dipende da lib di terze parti A. A ha un modulo di ricerca definito oppure possiamo implementare un modulo di ricerca personalizzato per questo. Entrambi sono fattibili. Supponiamo di aver già scritto FindA.cmake e memorizzato in ${CMAKE_SOURCE_DIR}/cmake.Inoltre, supponiamo che quando si esegue cmake per generare il sistema di generazione di B, si fornisce A_ROOT per aiutare a trovare ccake A.

Poi nel di B di livello superiore CMakeLists.txt abbiamo bisogno:

# Use FindA.cmake, defined in the cmake/ directory. 
list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") 
find_package(A REQUIRED) 

# ... (define the B target here)... 

# Copy the config file to the build dir 
configure_file(cmake/BConfig.cmake cmake/BConfig.cmake @ONLY) 

# Copy A's find module (skip this step if FindA is not custom). 
configure_file(cmake/FindA.cmake cmake/FindA.cmake COPYONLY) 

# Create the target export. 
export(EXPORT BTargets 
    FILE ${CMAKE_BINARY_DIR}/cmake/BTargets.cmake 
    NAMESPACE B:: 
    ) 

# Register B so cmake can find B's config file. 
export(PACKAGE B) 

Ora in cmake/BConfig.cmake:

# Get the exported find module onto the module path. 
# This step is unnecessary if the find module is part of cmake. 
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}") 

# Store the root so that find_package will work. 
# You may have to store other variables here, too, but 
# the principle is just more of the same. 
set(A_ROOT @[email protected]) # **Could optionally cache this. 
find_package(A MODULE REQUIRED) 

# The usual one-liner for a config file. 
include("${CMAKE_CURRENT_LIST_DIR}/BTargets.cmake") 

giusto per guidare la casa di soluzione, diamo un'occhiata a un secondo esempio, Rocket questa volta usando Boost, che ha già definito un modulo di ricerca.

CMakeLists.txt:

option(Boost_USE_MULTITHREADED ON) 
option(Boost_USE_STATIC_LIBS OFF) 
find_package(Boost REQUIRED COMPONENTS filesystem program_options) 

add_library(Rocket rocket.cpp) 
target_link_libraries(Rocket 
    PUBLIC Boost::filesystem 
    PRIVATE Boost::program_options 
    ) 

configure_file(cmake/BConfig.cmake cmake/BConfig.cmake @ONLY) 

export(EXPORT RocketTargets 
    FILE ${CMAKE_BINARY_DIR}/RocketTargets.cmake 
    NAMESPACE Rocket:: 
    ) 
export(PACKAGE Rocket) 

Poi cmake/RocketConfig.cmake avrebbe:

set(BOOST_ROOT @[email protected] CACHE PATH "In case boost was relocated.") 
set(Boost_USE_MULTITHREADED @[email protected]) 
set(Boost_USE_STATIC LIBS @[email protected]) 
find_package(Boost REQUIRED COMPONENTS filesystem program_options) 

include("${CMAKE_CURRENT_LIST_DIR}/RocketTargets.cmake") 

Quindi sì. Sembra digitare troppo. Sembra che cmake dovrebbe essere in grado di generare tutto il codice da una dichiarazione export in CMakeLists.txt. Ma questa strategia sembra raggiungere l'obiettivo.

Inoltre, non ho ancora testato, ma ho il sospetto che, se la vostra dipendenza transitiva utilizza una CONFIG invece di un MODULE per find_package, dovrebbe essere molto facile solo per aggiungere al CMAKE_PREFIX_PATH nel file di configurazione pure.