c++ - 依赖外部库的CMake导出包

标签 c++ cmake

我有一个使用 C++ 和 CMake 编写的项目,使用 Boost,我正在尝试制作一个独立的二进制/头文件包,以允许其他人链接到我的工作。我正在为此使用 cmake 安装程序。但是,当我的库链接到外部库时,我遇到了 install(EXPORTS ...) 问题。特别是,Boost 库和头目录位置被硬编码到导出的文件中,我不知道如何让它更好地工作。

举个例子。 (未经测试;如果不清楚,我可以详细说明或修复它。)

CMakeLists.txt:

package(MyLibrary)
set(MyLibrary_VERSION 1.0)

find_component(BOOST 1.55.0 REQUIRED COMPONENTS serialization)

set(INSTALL_INCLUDE_DIR "C:/MyLibrary/include")
set(INSTALL_SRC_DIR "C:/MyLibrary/include")
set(INSTALL_BIN_DIR "C:/MyLibrary/bin")
set(INSTALL_LIB_DIR "C:/MyLibrary/lib")
set(INSTALL_CMAKE_DIR "C:/MyLibrary/cmake")

set(HEADERS myfile.hpp)
set(SOURCES myfile.cpp)

install(FILES ${HEADERS} DESTINATION ${INSTALL_INCLUDE_DIR} COMPONENT headers)
install(FILES ${SOURCES} DESTINATION ${INSTALL_SRC_DIR} COMPONENT sources)

add_library(MyLibrary STATIC
    ${HEADERS} ${SOURCES})

target_link_libraries(MyLibrary
    ${Boost_SERIALIZATION_LIBRARY})

target_include_directories(MyLibrary
    PUBLIC "$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR};${Boost_INCLUDE_DIRS}>"
    PUBLIC "$<INSTALL_INTERFACE:include;${Boost_INCLUDE_DIRS}>")


install(TARGETS MyLibrary EXPORT MyLibrary-depends
    DESTINATION ${INSTALL_LIB_DIR} COMPONENT libraries)

configure_package_config_file(MyLibraryConfig.cmake.in
    "${CMAKE_CURRENT_BINARY_DIR}/MyLibraryConfig.cmake" 
    INSTALL_DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
write_basic_package_version_file("${CMAKE_CURRENT_BINARY_DIR}/MyLibraryConfigVersion.cmake" 
    VERSION ${MyLibrary_VERSION}
    COMPATIBILITY AnyNewerVersion)

install(FILES
    "${CMAKE_CURRENT_BINARY_DIR}/MyLibraryConfig.cmake"
    "${CMAKE_CURRENT_BINARY_DIR}/MyLibraryConfigVersion.cmake"
    DESTINATION "${INSTALL_CMAKE_DIR}")

install(EXPORT MyLibrary-depends
    FILE MyLibrary-depends.cmake
    DESTINATION "${INSTALL_CMAKE_DIR}")

MyLibraryConfig.cmake.in

@PACKAGE_INIT@

if (NOT MyLibrary_FOUND)
    set(MyLibrary_FOUND 1)

    find_package(Boost 1.55.0 COMPONENTS SERIALIZATION)

    include(MyLibrary-depends.cmake)

    # random directory stuff, etc.
endif()

问题是 MyProject-depends.cmake${Boost_INCLUDE_DIRS}${Boost_SERIALIZATION_LIBRARY} 的值结束>,它们都是绝对路径,破坏了安装的可移植性。


我尝试了一些方法,但似乎都无法解决我所有的问题。

target_include_directories:

我尝试转义 $,希望 MyProject-depends.cmake 会在包含时获取 Boost_INCLUDE_DIRS 变量的值-时间:

target_include_directories(MyProject
    PUBLIC "$<INSTALL_INTERFACE:include;\${Boost_INCLUDE_DIRS}>"
    ...)

当然,INSTALL_INTERFACE 认为 ${Boost_INCLUDE_DIRS} 是一个相对路径,并在其前面加上 {$_IMPORT_DIR} 前缀,这会中断一切。

我可以完全放弃 MyProject-depends.cmake 路由,并将其添加到 MyProjectConfig.cmake.in 中:

CMakeLists.txt:

target_include_directories(MyProject
    PUBLIC "$<INSTALL_INTERFACE:include>"
    PUBLIC "$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR};${Boost_INCLUDE_DIRS>")

和 MyProjectConfig.cmake.in:

include(MyProject-depends.cmake)
set_target_properties(MyProject
    INTERFACE_INCLUDE_DIRECTORIES "${Boost_INCLUDE_DIRS}")

该选项似乎有效但很痛苦。


target_link_libraries:

我在库链接方面遇到了更多麻烦。我尝试了同样的技巧,将内容移动到 MyProjectConfig.cmake.in 文件中以获得更多控制,但是

target_link_libraries(MyProject ${Boost_SERIALIZATION_LIBRARIES})

不适用于导入的库,并且

set_target_properties(MyProject INTERFACE_LINK_LIBRARIES ${Boost_SERIALIZATION_LIBRARY})

失败,因为 ${Boost_SERIALIZATION_LIBRARY} 扩展为类似 optimized;C:/boost/stage/lib/boost_serialization.lib;debug;C:/boost/stage/lib/boost_serialization .libdset_target_properties 不喜欢关键字。

现在我只剩下使用

的某种重新映射
"$<$<CONFIG:DEBUG>:${Boost_SERIALIZATION_LIBRARY_DEBUG}>$;<$<CONFIG:RELEASE>:${Boost_SERIALIZATION_LIBRARY_RELEASE}>"

但我还必须检测是否指定了调试库...这是可行的,但对我来说就像剃牦牛毛一样。

那么,堆栈中的圣人……有什么建议吗?我忽略了一些明显的模块或聪明的方法吗? (感谢您一路走来!


此外:cmake install(EXPORTS ...) 文档包含有用的行“如果库目标包含在导出中但未包含它链接到的目标,则行为未指定”是的,基本上,我正在寻找解决方法。

最佳答案

我得到了最后一个 target_link_libraries 答案,完全放弃了内置导入结构并编写了 CMake 模块来重新映射

optimized;C:/boost/stage/lib/boost_serialization.lib;debug;C:/boost/stage/lib/boost_serialization.libd

进入

$<$<CONFIG:DEBUG>:${Boost_SERIALIZATION_LIBRARY_DEBUG}>$;<$<CONFIG:RELEASE>:${Boost_SERIALIZATION_LIBRARY_RELEASE}>

一点也不漂亮,但这是我能想到的最好的。就这样吧。

关于c++ - 依赖外部库的CMake导出包,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27517257/

相关文章:

c++ - 我可以在 C++ 中声明一个非成员函数 const 吗?

c++ - 使用 CMake 编译 CUDA 时出现错误 "undefined reference to ` __cudaRegisterLinkedBinary"

java - Android 上的 FreeRDP - 如何让此代码在 android 和 windows 中工作?

linux - 使用 -fPIC 重新编译 makefile

C++调试返回0返回变量

c++ - 为C++字符串转义一些字符的函数

c++ - 我想在运行 C++ .exe 时停止 CMD

c++ - CMake:从 ExternalProject 链接共享 C++ 对象生成具有相对路径而非绝对路径的二进制文件

c++ - 使用CMake构建Qt项目并从QMainWindow继承导致未引用的vtable错误

c++ - 在 C++ 中分配回调函数