我有一个使用 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 ...)
文档包含有用的行“如果库目标包含在导出中但未包含它链接到的目标,则行为未指定”是的,基本上,我正在寻找解决方法。
最佳答案
我得到了最后一个 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/