我正在尝试编写一个 FindFoo.cmake 脚本来定位一个名为 libfoo.so 的外部库,我想使用它,但问题是 libfoo.so 还链接了 2 个外部库(我们称它们为 libbar.so 和 libbaz.so )所以当我尝试链接时我总是有未定义的引用。
这是我尝试过的:
查找Foo.cmake
find_path(Foo_INCLUDE_DIR NAMES foo.h)
mark_as_advanced(Foo_INCLUDE_DIR)
find_library(Foo_LIBRARY NAMES foo)
mark_as_advanced(Foo_LIBRARY)
if(Foo_INCLUDE_DIR AND Foo_LIBRARY)
set(Foo_FOUND TRUE)
if(Foo_FOUND)
add_library(Foo UNKNOWN IMPORTED)
set_target_properties(Foo PROPERTIES
IMPORTED_LOCATION "${Foo_LIBRARIES}"
INTERFACE_INCLUDE_DIRECTORIES "${Foo_INCLUDE_DIR}"
INTERFACE_LINK_LIBRARIES "${Foo_LIBRARIES};bar;baz"
)
endif()
然后我链接到:
CMakeLists.txt
find_package(Foo REQUIRED)
add_executable(Test test.cxx)
target_link_libraries(Test PUBLIC Foo)
问题是它仅链接到Foo,不还链接到bar和baz(尽管有
INTERFACE_LINK_LIBRARIES
属性),因此生成了很多未定义的引用。
这是唯一的问题,因为手动更改链接到以下内容可以使可执行文件正确链接:
target_link_libraries(Test
PUBLIC Foo
PUBLIC bar
PUBLIC baz
)
但是既然我不应该手动执行此操作,我做错了什么?
编辑:根据评论中的建议,我也尝试过
target_link_libraries(Foo INTERFACE bar baz)
但是问题仍然存在,当任何链接到 Foo 时,它都会忽略 foo 的链接依赖关系。
也许 Foo 定义是错误的,所以 cmake 忽略了它的属性?或者我应该将 bar 和 baz 声明为外部,以便 cmake 也考虑它们?
还尝试将外部库设置为:
add_library(Foo SHARED IMPORTED)
CMake版本:3.30.5
感谢@Tsyvarev 的评论,我发现了问题并得到了我在这里分享的解决方案,以防有人发现类似的错误:
问题:
Foo_LIBRARY
var 为空,因此目标库未正确创建GLOBAL
所以目标库的范围只是当前文件最后,导入库并设置其依赖项的解决方案是:
查找Foo.cmake
# Look for the necessary header
find_path(Foo_INCLUDE_DIR NAMES foo.h)
mark_as_advanced(Foo_INCLUDE_DIR)
# Look for the necessary library
find_library(Foo_LIBRARY NAMES foo)
mark_as_advanced(Foo_LIBRARY)
# Extract version information from the header file
if(Foo_INCLUDE_DIR AND Foo_LIBRARY)
set(Foo_FOUND TRUE)
set(Foo_LIBRARIES bar baz)
endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Foo
REQUIRED_VARS Foo_INCLUDE_DIR Foo_LIBRARY Foo_LIBRARIES
)
# Create the imported target
if(Foo_FOUND)
set(Foo_INCLUDE_DIRS ${StormByte_INCLUDE_DIR})
if(NOT TARGET Foo)
add_library(Foo UNKNOWN IMPORTED GLOBAL)
set_target_properties(Foo PROPERTIES
IMPORTED_LOCATION "${Foo_LIBRARY}"
INTERFACE_INCLUDE_DIRECTORIES "${Foo_INCLUDE_DIRS}"
INTERFACE_LINK_LIBRARIES "${Foo_LIBRARIES}"
)
endif()
endif()
因此,从现在开始,使用此配置,目标是
GLOBAL
每个 other CMakeFiles.txt
都可以通过以下方式将 Foo 库及其依赖项定位为: target_link_libraries(TARGET Foo)
如果 find_package(Foo)
已在某处执行。
注意:无需在最终目标之前或之后执行
find_package(Foo)
,无论如何它都会起作用。