我当前正在开发一个软件包,我想为其提供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"
)
库的标头包含在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(...)
命令中弄乱了一些目录,所以目录是错误的,因此在我的其他项目中找不到。感谢您的帮助!
答案 0 :(得分:2)
为什么要设置FOO_INCLUDE_DIR
或FOO_LIBRARIES
?这可能是旧的查找模块的工作方式,而不是配置文件的工作方式。甚至更新的查找模块都公开目标而不是目录变量。
生成XYZConfig.cmake
文件时,将导出有关 targets 的信息,而不是目录中的信息。
具有这样的出口:
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
之类的导出目标时,其公共接口将被传递给其用户。在上面的示例中,bar
将继承链接目标的属性。
因此INTERFACE_INCLUDE_DIRECTORIES
和Foo::FooLib1
中的Foo::FooLib2
将附加到bar
的{{1}}中。与INCLUDE_DIRECTORIES
相同。
对于LINK_LIBRARIES
,不仅其baz
将包含INCLUDE_DIRECTORIES
条目,而且其自身的Foo::FooLib2
将传递INTERFACE_INCLUDE_DIRECTORIES
的使用要求>