我有一个使用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 ...)
文档包含有用的行“如果导出中包含库目标,但未包含其链接的目标,则行为未指定。”是的,基本上,我正在寻找一种解决方法。
答案 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}>
一点也不漂亮,但这是我能想到的最好的。它就是这样。