我目前正在开发一个软件包,我想为此提供 cmake 软件包支持(以便用户可以通过 find_package(...)
找到它)。问题是,找到了包,但是 FOO_INCLUDE_DIR
和 FOO_LIBRARIES
是空的。
在我的包中,我有几个模块,每个模块都有一个 CMakeLists 文件,该文件安装相应的库和头文件:
install(TARGETS ${LIBRARY_NAME} EXPORT FooTargets
RUNTIME DESTINATION ${Foo_RUNTIME_INSTALL_DIR}
LIBRARY DESTINATION ${Foo_LIBRARY_INSTALL_DIR}
ARCHIVE DESTINATION ${Foo_ARCHIVE_INSTALL_DIR}
FRAMEWORK DESTINATION ${Foo_FRAMEWORK_INSTALL_DIR})
# Headers
install(
DIRECTORY include/${LIBRARY_NAME}
DESTINATION include/${PROJECT_NAME}
FILES_MATCHING
PATTERN "*.h"
PATTERN "*.hpp"
)
库的 header 包含在 target_include_directories 中,如下所示:
target_include_directories(${LIBRARY_NAME} PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> # for headers when building
$<INSTALL_INTERFACE:${Foo_INC_INSTALL_DIR}> # for client in install mode
)
我检查了文件夹,所有库和头文件都已正确安装。在我的顶级 CMakeLists 中,我使用以下命令导出目标:
install(
EXPORT FooTargets
DESTINATION ${Foo_CMAKE_CONFIG_INSTALL_DIR}
FILE FooConfig.cmake
)
配置是我假设的位置(
usr/local/lib/cmake/Foo
)。所以一切似乎都是正确的。当我查看我的 FooConfig.cmake
它说:# Create imported target realm_densifier_base
add_library(FooLib1 SHARED IMPORTED)
set_target_properties(FooLib1 PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "/usr/local/include/Foo"
INTERFACE_LINK_LIBRARIES "...several libraries..."
)
...这是绝对正确的,正是我所期望的。谜题的哪一部分缺失了?是
INTERFACE_INCLUDE_DIRECTORIES
和 INTERFACE_LINK_LIBRARIES
不是要设置的正确标志?感谢您的帮助和最好的问候,
亚历克斯
编辑:
@Guillaume Racicot 已经清理了大部分事情,我只知道向我的项目添加标题的“非目标”方式,即使用 include_directories(Foo_INCLUDE_DIRS)。但是,在目标世界中,链接到我的库 Foo 就足够了。另一件事是我弄乱了
target_include_directories(...)
中的一些目录。命令,所以目录错误,因此在我的其他项目中找不到。谢谢您的帮助!
最佳答案
为什么会FOO_INCLUDE_DIR
或 FOO_LIBRARIES
设置?这可能是查找模块的工作方式,但不是配置文件的工作方式。甚至较新的 find 模块会公开目标而不是目录变量。
生成 XYZConfig.cmake
时文件,有关目标的信息将被导出,而不是目录信息。
有了这样的导出:
install(
EXPORT FooTargets
NAMESPACE Foo::
DESTINATION ${Foo_CMAKE_CONFIG_INSTALL_DIR}
FILE FooConfig.cmake
)
您会期望该软件包的用户像这样使用它:
find_package(Foo REQUIRED)
# or PUBLIC ------v
target_link_libraries(bar PRIVATE Foo::FooLib1)
如果您的包在导出集中有多个目标,那么您可以链接到两个或仅一个
target_link_libraries(bar PRIVATE Foo::FooLib1 Foo::FooLib2)
target_link_libraries(baz PUBLIC Foo::FooLib2) # link to lib2 only
当您链接到导出的目标时,如
Foo::FooLib1
,它的公共(public)接口(interface)将传递给它的用户。在上面的示例中,bar
将从链接目标继承属性。所以
INTERFACE_INCLUDE_DIRECTORIES
的 Foo::FooLib1
和 Foo::FooLib2
将附加到 bar
的INCLUDE_DIRECTORIES
. LINK_LIBRARIES
相同.对于
baz
,不仅是它的INCLUDE_DIRECTORIES
将包含 Foo::FooLib2
条目,还有它自己的INTERFACE_INCLUDE_DIRECTORIES
将传递 Foo::FooLib2
的使用要求
关于c++ - CMake 包支持 - 未找到包含和库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62070997/