从(在项目根目录的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::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_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
?!
答案 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::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")
缺少前两行;因此,我得到的错误。参见thread末尾的cmake开发人员Matthew Woehlke的答案。