CMake:配置文件包依赖查找模块包的推荐方法

时间:2015-05-28 11:14:17

标签: build cmake

我刚刚阅读了有关CMake的配置文件包"概念"这听起来很有希望。我非常喜欢它的是,如果我自己创建一个Config-File包,我可以指定它依赖的其他包。我的问题是:我如何创建一个可重定位的#Conf;-34;并取决于Find-Module Package(例如boost)?

更详细:假设我想创建一个名为HyDi的包。 cmake documentation非常好地解释了如何自动创建相应的HydiConfig.cmake和HydiTargets.cmake文件。执行此操作的CMakeLists.txt的一个非常简单的版本是:

project(HyDi)

find_package(Boost COMPONENTS program_options)
add_library(HyDi foo.cpp foo.hpp)
target_include_directories(HyDi PUBLIC INTERFACE ${Boost_INCLUDE_DIRS})
target_link_libraries(HyDi ${Boost_LIBRARIES})
target_compile_options(HyDi INTERFACE PUBLIC "-std=c++11")


install(TARGETS HyDi EXPORT HyDiTarget
  LIBRARY DESTINATION lib
  ARCHIVE DESTINATION lib
  RUNTIME DESTINATION bin
  INCLUDES DESTINATION include
)

install(FILES foo.hpp DESTINATION include)

configure_file(cmake/HyDiConfig.cmake
  "${CMAKE_CURRENT_BINARY_DIR}/HyDi/HyDiConfig.cmake"
  COPYONLY
)

set(ConfigPackageLocation lib/cmake/HyDi)
install(EXPORT HyDiTarget FILE HyDiTargets.cmake 
    NAMESPACE Upstream:: DESTINATION ${ConfigPackageLocation} )
install(FILES cmake/HyDiConfig.cmake DESTINATION ${ConfigPackageLocation})

相应的HydiConfig.cmake是:

include(CMakeFindDependencyMacro)
find_dependency(Boost COMPONENTS program_options)

include("${CMAKE_CURRENT_LIST_DIR}/HyDiTargets.cmake")

但是,如果我安装此库,HyDiTargets.cmake文件将包含硬编码的Boost库的包含路径,因此无法重定位。

请注意,cmake documentation给出了一个如何不包含基本上是我的版本的boost库的示例。但遗憾的是,他们没有解释如何做得更好。

我知道我可以使用cmake构建boost,然后可以将boost作为Config文件包导入,以便我的HydiTargets.cmake可以重定位。但是这种方法并不适用于提供Findxxx.cmake文件的每个其他库。

1 个答案:

答案 0 :(得分:-2)

实际上,当注入"硬编码的"提升库的路径(你做错了)。因为在您的库被编译和安装之后,它应该"链接" w /非常特别的boost版本(当你的库编译时) - 即它的头文件和静态/动态库。

考虑场景:在成功安装库之后,有人会并行安装新版本的boost库(或您依赖的任何其他第三方库)(是的,boost和其他一些库可以在相同的安装前缀中共存) 。为了使事情看起来像一个真实世界的例子,假设它与先前版本的ABI不兼容。现在,如果那"幸运"开发人员想要使用您的(已经编译和安装的)库(使用导出的目标并提供HyDiConfig.cmake),他会遇到麻烦:

  • 您的图书馆已经链接到"之前的"提升版本(记住ABI与新版本不兼容);
  • 所以当你以某种方式取代"硬编码"路径,并会找到一个更新的版本(正如你在HyDiConfig.cmake尝试做的那样)你的"幸运"顾客会因为那个烂摊子而生气!

这不仅仅是针对所有第三方库的提升...相同的策略:它们应该保持与编译时相同(或者至少ABI兼容,如果我们在运行时讨论动态链接,但这是一个单独的故事。)

此外,您的用户甚至可能不会在他的应用程序中使用boost(但安装了多个版本) - 为什么你应该找到smth?您已经知道(感谢CMake和硬编码路径)促进版本"所需"为你的图书馆!因此,在这种情况下找到smth new是完全错误的!这太晚了...... 你的图书馆已经编译,链接和安装了!

另一个案例:他想使用其他(更新)版本的提升......根据find_package(boost)find_package(yourLib)的顺序,结果可能会有所不同......但他还是会对你生气!