对于cmake“include”命令,文件和模块有啥区别?

Posted

技术标签:

【中文标题】对于cmake“include”命令,文件和模块有啥区别?【英文标题】:For the cmake "include" command, what is the difference between a file and a module?对于cmake“include”命令,文件和模块有什么区别? 【发布时间】:2021-10-06 00:32:49 【问题描述】:

我使用了一些我不想在每个使用它们的项目中构建的库。一个非常容易理解的例子是 LLVM,它有 78 个静态库。即使在每个 cmakefile 中都有 cmake 代码来查找和导入这些代码也是多余的。

显而易见的解决方案似乎是使用“include”命令,并将相关的 cmake 脚本块分解到 *.cmake 文件中,并设置一个 CMAKE_MODULE_PATH 环境变量。

除非它只是简单地不起作用。 Cmake 没有找到我在 include 命令中指定的文件。

在偶然的情况下,我什至尝试用几种方法在环境变量中指定路径 - 一次使用反斜杠,一次使用正斜杠... - 我每次都重新启动命令提示符并检查环境变量是否存在并正确。

在 cmake 手册中,它有点暗示“文件”与“模块”不同——只有模块获得自动添加扩展和搜索路径处理。但是没有解释有什么区别。我猜想缺少的扩展可能就足够了(与标准模块一样),但显然不是。

在手册中搜索“模块”并没有太大帮助,因为这个词似乎已经超载。例如,模块也是使用 LoadLibrary/dl_open 加载的动态库。

谁能解释一下在这种情况下文件和模块之间有什么区别,以及我如何创建自己的模块以便 cmake include 命令可以找到并使用它?

我在 Windows 上使用 cmake 2.8.1。

编辑

我非常确信这里的问题是不了解 cmake 应该如何工作。我认为我应该做的是写一些find_package 可以使用的东西。

尽管如此,我离回答自己的问题还有一段距离。

【问题讨论】:

【参考方案1】:

我相信 CMake 的“模块”只是一个可以与find_package 指令一起使用的文件。也就是说,当您运行 find_package(Module) 时,它会在 MODULE_PATH 中搜索名为 FindModule.cmake 的文件。

也就是说,如果你 include 一个没有扩展名的文件,它也会在你的 MODULE_PATH 中搜索那个 file.cmake。在我正在处理的 CMake 项目中,我的目录结构与您的建议非常相似。

+ root/
  + CMakeLists.txt
  + cmake/
  | + FindMatlab.cmake
  | + TestInline.cmake
  | + stdint.cmake
  + src/
  + include/

在 CMakeLists.txt 我有:

set (CMAKE_MODULE_PATH "$CMAKE_MODULE_PATH;$CMAKE_CURRENT_SOURCE_DIR/cmake")
find_package (Matlab) # runs FindMatlab.cmake
include(TestInline) # defines a macro:
test_inline (CONFIG_C_INLINE)
include(stdint) # simply executes flat CMake code

也许您的问题是您试图从环境中定义模块路径。相反,尝试简单地将您尝试访问模块/文件的 CMakeList 附加到它

【讨论】:

现在回头看那个代码,我注意到我没有附加到CMAKE_MODULE_PATH;我完全破坏了它。您可能想做更多类似的事情:set (CMAKE_MODULE_PATH "$CMAKE_MODULE_PATH;$CMAKE_CURRENT_SOURCE_DIR/cmake") 我现在没有时间检查,但这看起来不错。谢谢。 我不知道为什么我现在认为该变量是环境变量。我猜是看到我正在寻找的东西,而不是那里的东西。我最近刚刚在 YouTube 上观看了 Google techtalk 视频,其中指出环境变量大多是故意避免的。无论如何 - 接受并感谢。 FindPackage,顾名思义,就是找Gtk、Qt等包,就是你项目所依赖的包。 更好的是:list(APPEND CMAKE_MODULE_PATH "$CMAKE_CURRENT_SOURCE_DIR/cmake").【参考方案2】:

在阅读了 CMake include() 命令文档后,我也遇到了同样的问题。它指出:

从给定的文件中加载并运行 CMake 代码。 [...为简洁起见...] 如果指定的是模块而不是文件,则首先在 CMAKE_MODULE_PATH 中搜索名为 .cmake 的文件,然后在 CMake 模块目录中搜索。

这留下了很多关于 CMake 认为模块与文件的解释,因为 CMake 模块毕竟是文件系统上的文件。那么有什么区别呢?

CMake 源代码是我唯一能找到答案的地方。基本上,如果 include() 的参数看起来像绝对路径,CMake 会将其视为文件。这意味着:

在 Linux/Unix 上 参数以“/”或“~”开头 在 Windows 上 参数的第二个字符是 ':'(如 C:) 参数以'\'开头

CMake 假定任何其他不符合上述条件的都是模块。在这种情况下,它将“.cmake”附加到参数并在 CMAKE_MODULE_PATH 中搜索它。

【讨论】:

【参考方案3】:

文件是 CMake 列表文件,例如 CMakeLists.txt。使用以下命令获取

中使用的命令列表
cmake --help-command-list 

Module 是一个包含 cmake 命令的 cmake 文件 (*.cmake)。

正如 Matt B. 所说,CMAKE_MODULE_PATH 不是 shell 的环境变量,而是 cmake 变量。

将你的模块路径附加到 CMAKE_MODULE_PATH

LIST(APPEND CMAKE_MODULE_PATH $YourPath)

或者,如果您希望首先使用您的模块

LIST(INSERT CMAKE_MODULE_PATH 0 $Yourpath)

【讨论】:

以上是关于对于cmake“include”命令,文件和模块有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章

CMake中include的使用

cmake 语法

CMake基础教程(26)find_package搜索包完成库链接和头文件添加(module模式)

Cmake中find_package命令的搜索模式之模块模式(Module mode)

CMAKE将动态库链接到模块,但不显示为链接依赖

Cmake中find_package命令的搜索模式之配置模式(Config mode)