如何正确地将依赖关系从一个目标传递到下一个目标?

时间:2020-01-27 16:36:35

标签: cmake

从(在项目根目录的cwd_r中切换目标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被拖入此处的方式是因为 AICxx::cwds的PUBLIC依赖项。

要缩小范围,首先将第二行更改为

target_link_libraries(test1 PRIVATE AICxx::cwds)

只需放弃AICxx::events AICxx::utils。正如预期的那样,这会产生完全相同的错误,因为尚未发生链接。

目标AICxx::cwdscwds/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_r的正确目标名称(Libcwd::cwd_r)。

请注意cwds如何添加对Threads::Threads(和Boost)的依赖。但是因为我只有 更改了libcwd_r的查找方式,但这不能解决问题,对吧?

要检验该假设-我还从Threads::Threads的{​​{1}}中删除了target_link_libraries,实际上仍然是完全相同的错误。因此(如预期的那样),它抱怨它是从cwds/CMakeLists.txt继承来的。

我现在的问题是:如果(找到的)目标Libcwd::cwd_r指定了依赖项Libcwd::cwd_r,那么为什么会出现此错误?难道不应该向最终用户(test1)隐藏该用户,而最终用户(test1)甚至都不知道正在使用Threads::Threads(它只是与Threads::Threads链接)? 的答案是是的!因为以前,当我使用AICxx::cwds时它起作用了!

那么什么改变了?怎么了?我怎样才能解决这个问题? 最重要的是,cmake对于传递这样的依赖关系有什么期望?错误似乎表明我必须在各处添加pkg_check_modules?!

1 个答案:

答案 0 :(得分:0)

两者之间存在差异的直接原因是pkg_check_modules没有将目标Threads::Threads(或任何目标)添加到返回目标{{1}的INTERFACE_LINK_LIBRARIES属性中}}。具体来说,后者具有属性

PkgConfig::libcwd_r

(在此处稍作更改以使路径更短)。这是从其INTERFACE_LINK_LIBRARIES = /usr/local/lib/libcwd_r.so;/usr/lib/libdl.so 文件中提取的:

.pc

尽管libcwd的cmake package 设置了此目标。即具有属性

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}

它在已安装的INTERFACE_LINK_LIBRARIES = Threads::Threads;dl 文件(cmake软件包的四个文件之一)中设置:

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

就是说,这样的导入目标具有其(子)目录的范围,并且在同一范围内需要在其引入位置使用find_package。也就是find_package字面上的Threads::ThreadsCMakeLists.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")

缺少前两行;因此,我得到的错误。参见thread末尾的cmake开发人员Matthew Woehlke的答案。

相关问题