【问题标题】:How to use find_package in CMake? (Example: GMP library)如何在 CMake 中使用 find_package? (例如:GMP 库)
【发布时间】:2023-03-31 02:27:01
【问题描述】:

我正在尝试使用 find_package 在 CMake 中包含库。

This question 讨论如何告诉 CMake 链接到 GMP library (external)。我正在尝试按照那里的答案步骤进行操作,但没有任何 <name>Config.cmake<name>-config.cmake 文件,正如一些 cmets 所提到的,这似乎是默认设置。当您不知道如何获取/查找这些文件时,答案没有提及任何解决方案。该答案的 cmets 链接到一个旧的website (external),其中有很多断开的链接,它描述了一个加载模块列表。我不清楚这些模块来自哪里以及如何获得它们。

根据官方 CMake documentation (external),如果找不到配置文件,find_package 从“模块模式”回退到“配置模式”。我不明白这意味着什么以及在什么情况下这会相关,尤其是因为文档不鼓励阅读“配置模式”。

文档说

文件首先在 CMAKE_MODULE_PATH 中搜索,然后在 CMake 安装提供的 Find Modules 中搜索。

我仍然对这些配置文件是否应该随 CMake 或相关库一起提供以及它们应该位于何处感到困惑。可能两者都有可能,但在特定情况下如何知道?

示例代码,尝试遵循现代最佳实践:

# CMakeLists.txt (not working)
cmake_minimum_required(VERSION 3.2)  # I have no idea what version I actually need

project (GMP_demo_project)

# Enable C++17 standard
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

find_package(GMP REQUIRED)

# Create the executable from sources
add_executable(GMP_demo GMP_demo.cpp)
target_link_libraries(GMP_demo gmp gmpxx)

代码输出错误消息

 CMake Error at CMakeLists.txt:10 (find_package):
  By not providing "FindGMP.cmake" in CMAKE_MODULE_PATH this project has
  asked CMake to find a package configuration file provided by "GMP", but
  CMake did not find one.
  Could not find a package configuration file provided by "GMP" with any of
  the following names:
    GMPConfig.cmake
    gmp-config.cmake
  Add the installation prefix of "GMP" to CMAKE_PREFIX_PATH or set "GMP_DIR"
  to a directory containing one of the above files.  If "GMP" provides a
  separate development package or SDK, be sure it has been installed.

问题:一般来说,如何获取和组织这些配置文件(CMake 加载模块)?怎么能指望其他用户在他的系统上拥有这些文件?我的问题是一般性的,仅以 GMP 为例(尽管我实际上对能够使用它感兴趣)。

顺便说一句,在按照库文档的建议安装 GMP 后,我可以使用 gcc GMP_demo.cpp -lstdc++ -lgmp 编译、链接和执行我的演示代码。问题只是让 CMake 去做。我也可以只为 CMake 提供库的绝对路径,这当然会更容易但不可移植(假设可以让 find_package 实际工作并通过合理的工作量进行移植)。

【问题讨论】:

  • gcc -lstdc++ 为什么不直接使用g++

标签: cmake gmp


【解决方案1】:

一般来说,如何获取和组织这些配置文件(CMake 加载模块)?

从广义上讲,它们分为三个类别:

  1. 包直接提供的文件。这是理想的解决方案,也就是 CMake 所称的配置模式。将有一个名为GMPConfig.cmake 的文件,cmake 可以通过搜索预配置路径或通过在配置时提供特定路径(cmake -DGMP_Dir=/path/to/GMP/install/root)来找到该文件。这种方法的优点是 GMPConfig.cmake 的生成大部分是自动的,并且库可以包含安装路径和编译标志等内容。缺点是库的开发实际上必须努力利用现代 CMake,而不是每个人都这样做。
  2. 由 CMake 直接提供的文件。对于常见的包(例如 boost),CMake 提供 FindXXX.cmake 文件,这些文件会搜索众所周知的路径并为您处理这些问题。从最终用户的角度来看,它们的工作方式与上述相同,但可用的 Find 模块取决于您安装的 CMake 版本。
  3. 一些随机人提供的文件被复制/粘贴到项目中。这些工作方式取决于编写它的人,因此您必须阅读他们的文档。使用您最喜欢的搜索引擎并尝试找到 FindGMP.cmake,然后将其放入某个模块文件夹中并适当地更新 CMAKE_MODULE_PATH

如何期望其他用户在他的系统上拥有这些文件?

安装包所需的任何依赖项是您的工作。任何使用现代 CMake(上面列出的项目符号 1)的东西都应该安装 XXXConfig.cmake 文件作为其安装的一部分。如果一个库不是由 CMake 构建的,你要么希望得到第 2 条,要么找到/编写你自己的 FindXXX.cmake 文件(第 3 条)。

对于您的具体情况,使用find_library 可能会更好,因为您的示例编译行看起来只需要链接。

【讨论】:

  • 1.图书馆作者必须为地球上的每个构建系统(不仅仅是 cmake)都这样做,这是不现实的。 CMake 实际上可以使用 pkg-config 来检测包(如果问得好的话),碰巧最新版本的 GMP 有 pkg​​-config 的配置文件。
  • 非常感谢您的回答!抱歉,我花了一段时间才回复,直到现在没有时间继续处理这个问题。无论如何,虽然您所说的确实很有帮助,但我仍然不确定如何为 GMP 库实现这一点,这是有问题的示例。我怎么知道从哪里获取配置?如果有可用的?我提到的另一个答案听起来很容易。不是这样吗?
最近更新 更多