2015-06-22 3 views
8

У меня есть Projecta, в который я импортируя библиотеку с:Экспорт импортированной библиотеки

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

я затем использовать foo в нескольких местах, в рамках проекта, и все это прекрасно работает.

Несколько уровней каталогов вниз Я хочу экспортировать библиотеку, построенную в этом проекте, для использования в еще одном проекте с полностью отключенной конфигурацией CMake. У меня есть:

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

Импортирующая projectB также нуждается в Foo, хотя (потому что импортируемая библиотека нуждается в нем), и жалуется, что cannot find -lfoo. Я пытался добавить его в команду export, но затем я получаю:

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

Я просто хочу экспортировать ту же конфигурацию, которую я использую локально на другой (импортера) проекта. Я не хочу явно указывать проектуB около foo. Есть ли способ сделать это?

ответ

1

Я не нашел фактического решения проблемы, как указано, но я отправляю свое собственное обходное решение для дальнейшего использования.

Я понял, что зависимость fooбыла испускаемой в экспорте; у него просто не было пути. И так как я до сих пор не понял, как получить cmake, чтобы экспортировать путь вместе с ним, я вернул команду export на то, что показано в вопросе выше (без foo).

Затем я вернулся на прежнее место, где foo был импортируемого и извлекал add_library и set_property, заменив их следующим образом:

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

Затем изменил target_link_libraries к:

target_link_libraries(thislib ${foo}) 

В другими словами, вместо того, чтобы превращать его в настоящую «импортированную библиотеку», это просто путь к библиотеке. Это правильно записывается в файл экспорта и позволяет проектуB связываться.

+1

Одна из проблем заключается в том, что он не позволяет устанавливать целевые свойства, такие как INTERFACE_INCLUDE_DIRECTORIES – RiaD

0

Вы должны

  1. Экспорт foo, откуда он построен (к, скажем, foolibs.cmake)
  2. Вместо использования /path/to/thislib.cmake непосредственно (экспортный файл, генерируемый export(TARGETS thislib... создать еще один, thislib-and-deps.cmake, который включает в себя как:

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

Существует ли простое решение для реализации этого в многоразовом режиме без реализации большого количества кода CMake для каждого проекта? Это не похоже на * CMake-way-to-go *. В настоящее время я повторяю 'find_package ( CONFIG)' вызов для каждой транзитивной зависимости, который также отстой, поскольку он нарушает концепцию транзитивных зависимостей. –

0

Я также не могу найти идеальный способ сделать это. Но вот обходной путь, который я использую сейчас. Это дополнительная работа, а не СУХОЙ, но я думаю, что она правильная.

Imagine lib B зависит от стороннего пользователя A. A либо имеет определенный модуль поиска, либо мы можем реализовать для него настраиваемый модуль поиска. Оба выполнимы. Предположим, что мы уже написали FindA.cmake и занесены в ${CMAKE_SOURCE_DIR}/cmake.Кроме того, предположим, что когда вы запускаете cmake для создания системы сборки B, вы предоставляете A_ROOT, чтобы помочь cmake найти A.

Затем в верхнем уровне Б CMakeLists.txt нам нужно:

# 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) 

Сейчас в 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") 

Просто ехать домой решение, давайте посмотрим на второй пример, Rocket на этот раз с помощью Boost, у которого уже определен модуль поиска.

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) 

Тогда cmake/RocketConfig.cmake бы:

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") 

Так что да. Похоже, слишком много печатается. Кажется, что cmake должен иметь возможность генерировать весь этот код из инструкции export в CMakeLists.txt. Но эта стратегия, похоже, достигает цели.

Кроме того, я еще не проверял, но я подозреваю, что, если транзитивной зависимостью использует CONFIG вместо MODULE для find_package, это должно быть очень легко просто добавить в CMAKE_PREFIX_PATH в файле конфигурации, а также.

Смежные вопросы