CMake软件包支持-找不到包含和库

时间:2020-05-28 17:35:49

标签: c++ cmake

我当前正在开发一个软件包,我想为其提供cmake软件包支持(以便用户可以通过find_package(...)找到它)。问题是找到了该程序包,但是FOO_INCLUDE_DIRFOO_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_DIRECTORIESINTERFACE_LINK_LIBRARIES是否不是要设置的正确标志?

感谢您的帮助和问候,

亚历克斯

编辑:

@Guillaume Racicot已经解决了大多数问题,我只知道“非目标”向项目添加标头的方法,即include_directories(Foo_INCLUDE_DIRS)。但是,在目标世界中,与我的库Foo链接就足够了。另一件事是我在target_include_directories(...)命令中弄乱了一些目录,所以目录是错误的,因此在我的其他项目中找不到。感谢您的帮助!

1 个答案:

答案 0 :(得分:2)

为什么要设置FOO_INCLUDE_DIRFOO_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_DIRECTORIESFoo::FooLib1中的Foo::FooLib2将附加到bar的{​​{1}}中。与INCLUDE_DIRECTORIES相同。

对于LINK_LIBRARIES,不仅其baz将包含INCLUDE_DIRECTORIES条目,而且其自身的Foo::FooLib2将传递INTERFACE_INCLUDE_DIRECTORIES的使用要求

相关问题