CMake导出包依赖于外部库

时间:2014-12-17 02:06:05

标签: 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.libd,而set_target_properties不喜欢关键字。

现在我正在使用

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

但我还必须检测是否指定了调试库...这是可行的,但对我来说似乎是牦牛。

所以,堆栈的圣人......有什么建议吗?我忽略了一些明显的模块或巧妙的方法吗? (并且感谢你一路走来!


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

1 个答案:

答案 0 :(得分:0)

我最后得到了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}>

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