CMake 导出依赖于外部库的包
CMake export package that relies on external library
我有一个使用 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}>
一点也不漂亮,但这是我能想到的最好的。就这样过去了。
- VS 2015 链接错误 无法构建依赖于 libcurl 的项目
- 为什么内存屏障依赖于变量?
- 反转依赖于 end() 的迭代器
- 使用 Git 处理 C++ Visual Studio 2019 解决方案的外部依赖项源代码管理的最佳方法是什么?
- 编译依赖于 QTCore 库的 WASM
- 如何添加依赖于类本身的模板成员变量
- 初始化依赖于子类的继承类的常量类成员
- Makefile 创建两个库 - 一个依赖于另一个
- 如何将外部依赖引入跨平台CMake项目?
- 对于BTreeMap和其他依赖于Ord的东西,是否有等效于C++比较器对象?
- 类成员函数参数列表是否可以依赖于模板参数?
- 依赖于类成员属性的类实例成员
- 使用 cmake 获取外部依赖关系
- 如何定义依赖于参数包转换的函数的返回类型
- 依赖于模板的错误
- 如何在bazel中同时处理外部依赖项和我的项目
- 如果 copts 不允许系统路径,如何引用外部依赖项使用的系统库?
- 依赖于特定类类型的C++模板方法
- 如何测试从依赖于外部系统的外部基类派生的类
- CMake 导出依赖于外部库的包