Как правильно передать зависимость от одной цели к другой? - PullRequest
0 голосов
/ 27 января 2020

После переключения цели cwd_r с (в проекте root 's CMakeLists.txt)

pkg_check_modules(libcwd_r libcwd_r IMPORTED_TARGET GLOBAL)

на

find_package(libcwd_r CONFIG)

У меня неожиданно появляется ошибка для ранее работавший код (в events/CMakeLists.txt):

add_executable(test1 test1.cxx)
target_link_libraries(test1 PRIVATE AICxx::events AICxx::utils AICxx::cwds)

раньше это работало нормально, и я хотел бы, чтобы он работал снова без того, чтобы мне пришлось изменить events/CMakeLists.txt, что эти две строки являются часть.

Ошибка:

CMake Error at events/CMakeLists.txt:59 (add_executable):
  Target "test1" links to target "Threads::Threads" but the target was not
  found.  Perhaps a find_package() call is missing for an IMPORTED target, or
  an ALIAS target is missing?

Способ, которым сюда втягивается Threads::Threads, заключается в том, что это зависимость PUBLI C от AICxx::cwds.

Чтобы сузить круг, давайте сначала изменим вторую строку на

target_link_libraries(test1 PRIVATE AICxx::cwds)

, просто пропуская AICxx::events AICxx::utils. Как и ожидалось, это дает точно такую ​​же ошибку, потому что связывание еще не происходит.

Цель AICxx::cwds определена в cwds/CMakeLists.txt с

find_package(Threads REQUIRED)
[...snip...]
add_library(cwds_ObjLib OBJECT)
[...snip...]
# Add dependencies.
target_link_libraries(cwds_ObjLib
  PUBLIC
    Boost::boost
    Threads::Threads
)

if (OptionEnableLibcwd)
  target_link_libraries(cwds_ObjLib
    PUBLIC
      ${libcwd_r_TARGET}
   )
endif ()

# Create an ALIAS target.
add_library(AICxx::cwds ALIAS cwds_ObjLib)

, где OptionEnableLibcwd истинно libcwd_r_TARGET установлено на правильное целевое имя (Libcwd::cwd_r) libcwd_r.

Обратите внимание, как cwds добавляет зависимость от Threads::Threads (и Boost). Но так как я изменил только то, как libcwd_r найдено, что не может быть причиной проблемы, верно?

Чтобы проверить эту гипотезу - я также удалил Threads::Threads из target_link_libraries в этом cwds/CMakeLists.txt и действительно все та же ошибка. Следовательно (как и ожидалось) он жалуется на что-то, что он унаследовал от Libcwd::cwd_r.

Мой вопрос сейчас: если (найденная) цель Libcwd::cwd_r задает зависимость Threads::Threads, то почему я получаю эта ошибка? Разве это не должно быть скрыто от конечного пользователя (test1), который даже не знает, что используется Threads::Threads (он просто связывается с AICxx::cwds)? Ответ на это - Да! Потому что раньше, когда я использовал pkg_check_modules, это работало!

Так что же изменилось? Что не так? Как я могу это исправить? И самое главное, что cmake ожидает от передачи таких зависимостей? Кажется, ошибка указывает на то, что я должен добавить find_package(Threads) везде?!

1 Ответ

0 голосов
/ 27 января 2020

Непосредственная причина разницы между ними заключается в том, что pkg_check_modules не добавляет цель Threads::Threads (или любую цель) к свойству INTERFACE_LINK_LIBRARIES возвращенной цели PkgConfig::libcwd_r. В частности, последний имеет свойство

INTERFACE_LINK_LIBRARIES = /usr/local/lib/libcwd_r.so;/usr/lib/libdl.so

(слегка изменено, чтобы пути здесь были короче). Это извлекается из файла .pc:

prefix=/usr/local
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
datadir=${prefix}/share
includedir=${prefix}/include

Name: libcwd_r
Description: C++ Debugging Support Library for threaded applications
Version: 1.1.2
Libs: -L${libdir} -lcwd_r -ldl
Cflags: -DCWDEBUG -DLIBCWD_THREAD_SAFE -I${includedir}

В то время как пакет cmake из libcwd устанавливает эту цель. А именно, у него есть свойство

INTERFACE_LINK_LIBRARIES = Threads::Threads;dl

, которое установлено в установленном файле libcwd_rTargets.cmake (один из четырех файлов пакета cmake):

set_target_properties(Libcwd::cwd_r PROPERTIES
  COMPATIBLE_INTERFACE_STRING "cwd_r_MAJOR_VERSION"
  INTERFACE_COMPILE_DEFINITIONS "CWDEBUG;LIBCWD_THREAD_SAFE;VERSION=\"1.1.2\""
  INTERFACE_INCLUDE_DIRECTORIES "${_IMPORT_PREFIX}/include"
  INTERFACE_LINK_LIBRARIES "Threads::Threads;dl"
  INTERFACE_cwd_r_MAJOR_VERSION "5"
)

С этим "новым msgstr "зависимость, ошибка возникает из-за того, что эта зависимость не сопровождается find_package.

А именно, такая импортируемая цель имеет область действия своего (под) каталога и должна иметь find_package где он вводится в том же объеме. Ака, где у вас есть Threads::Threads буквально в вашем CMakeLists.txt, что CMakeLists.txt также должно иметь find_package(Threads).

В этом случае, однако, Threads::Threads используется в libcwd_rTargets.cmake файл. Правильный способ добавить find_package для таких зависимостей, как это, с помощью find_dependency , добавив это в файл пакета *Config.cmake:

include(CMakeFindDependencyMacro)
find_dependency(Threads)
include("${CMAKE_CURRENT_LIST_DIR}/libcwd_rTargets.cmake")

, где отсутствовали первые две строки ; отсюда и ошибка, которую я получил. См., Например, ответ разработчика cmake Мэтью Вёльке в конце этой темы .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...