我正在更新一个(非常旧的)库的查找模块。所以情况是一个现有的共享库,它使用 CMake 本身。用户可能已经将它安装在某个地方,在包 repos 或其他地方。
现在他们想用这个。好的方法是
find_package(Foo REQUIRED)
target_link_libraries(MyProject Foo::Foo)
所以这就是目标。
问题是:一个好的 find_package-Config 或 -Module 看起来如何允许这个 2-liner 工作?它应该满足这两个要求:
- 允许 CMake 版本使用比用于构建它的库更旧的库
- 强制执行例如 C++11 模式。在 Find-Module 中,可以根据版本(
cxx_std_11
(CMake 3.8+)、cxx_alias_templates
(CMake 3.1+),check_cxx_source_compiles
使用 C++11 代码和对旧 CMake 的警告)设置 C++11 要求
有两种方法可以做到这一点:
- 更新 find-module 以定义一个导入的库
Foo::Foo
并正确设置它(使用属性)并且很高兴也为旧的 CMake w/o 目标设置FOO_INCLUDE_DIR
和设置。 这很简单:只需使用and ,设置导入的目标即可。向前和向后兼容,因此即使是旧版本也能找到。FOO_LIBRARIES
find_path
find_library
用法:
用户将其项目复制(最新)FindFoo.cmake
到 egcmake/Modules
并指向CMAKE_MODULE_PATH
它,或复制FindFoo.cmake
到某些 CMake 默认路径。
听Daniel Pfeiffer和Modern CMake说
If you are the library author, don't make a Find<mypackage>.cmake script!
所以我们导出和安装目标。
这有点乱。需要进行以下更改:- Add
EXPORTS FooTargets
andINCLUDES DESTINATION include
toinstall(TARGETS
(参见 Pfeiffer #24),它基本上只是定义了一个导出。(我真的不明白,为什么我要为已经有名字的东西创建一个额外的名字。为什么下面的命令不能简单地引用一个目标?) - 添加
install(EXPORT FooTargets NAMESPACE Foo:: DESTINATION lib/cmake/Foo)
它会创建一个FooTargets.cmake
in<CMAKE_INSTALL_PREFIX>/lib/cmake/Foo
定义一个Foo::Foo
具有(希望)其所有依赖项的目标 - 根据我的理解,
FooConfigVersion.cmake
可能通过使用它来添加“某物” ,将版本硬编码到该文件write_basic_package_version_file
- 创建一个
FooConfig.cmake
可用于find_dependency
搜索 Foo 依赖并包含的库的FooTargets.cmake
- 安装
FooConfig.cmake
和FooConfigVersion.cmake
_lib/cmake/Foo
- 修改
target_include_directories
为使用单独的BUILD_INTERFACE
和INSTALL_INTERFACE
路径
- Add
用法:
find_package
自动查找FooConfig.cmake
和FooConfigVersion.cmake
何时Foo
搜索。
所以应该首选配置模块,但我看到的问题是:
- 过程看起来更复杂
- 它不能用于使用户能够找到旧版本的库(没有使用这种方法)
- 它不包括所有使用旧 CMake 的(库)用户(2.8.11 可能是这里所需的最低要求)
- 它需要更新的 CMake 版本来构建库本身
- C++11 的要求似乎很难编码
那么我们可以用 CMake-Config 解决需求吗?答案应该提供一个解决方案,或者至少是一个有充分根据的“不可能”。它还应该解决最后概述的问题。
最后说明:如果它不存在,我想这是一个很好的 wiki 条目。