CMake究竟是如何运作的?

Nav*_*Nav 137 cmake

我不是只问自己这个问题.我希望这个问题可以作为许多喜欢我的新手的参考,发现它对于这样一个小CMakeLists.txt文件 后幕后到底发生了什么感到非常困惑.

cmake_minimum_required (VERSION 2.6)
project(Tutorial)
add_executable(Tutorial tutorial.cpp)
Run Code Online (Sandbox Code Playgroud)

这么小 tutorial.cpp

int main() { return 0; } 
Run Code Online (Sandbox Code Playgroud)

生成的文件太多了

CMakeCache.txt  cmake_install.cmake  Makefile
CMakeLists.txt  tutorial.cpp
Run Code Online (Sandbox Code Playgroud)

和一个CMakeFiles包含这么多文件和文件夹的文件夹

CMakeCCompiler.cmake               CMakeOutput.log    Makefile.cmake
cmake.check_cache                  CMakeSystem.cmake  progress.marks
CMakeCXXCompiler.cmake             CMakeTmp           TargetDirectories.txt
CMakeDetermineCompilerABI_C.bin    CompilerIdC        Tutorial.dir
CMakeDetermineCompilerABI_CXX.bin  CompilerIdCXX
CMakeDirectoryInformation.cmake    Makefile2
Run Code Online (Sandbox Code Playgroud)

不了解幕后发生的事情(即:为什么文件必须生成以及它们的目的是什么),是能够学习CMake的最大障碍.

如果有人知道,你可以为了后代而解释它吗?这些文件的目的是什么,当我输入时cmake .,在构建项目之前cmake配置和生成究竟是什么?

Com*_*sMS 81

秘诀是您不必了解生成的文件的作用.

CMake在构建系统中引入了很多复杂性,如果你用它来构建复杂的软件项目,它们中的大部分都会得到回报.

好消息是,CMake很好地保持了很多这种混乱:使用源外构建,你甚至不必查看生成的文件.如果你到目前为止没有这样做(我猜你自己就是这样cmake .),请在继续之前检查它们.混合构建和源目录对于CMake来说真的很痛苦,而不是系统应该如何使用.

简而言之:而不是

cd <source_dir>
cmake .
Run Code Online (Sandbox Code Playgroud)

总是用

cd <build_dir_different_from_source_dir>
cmake <source_dir>
Run Code Online (Sandbox Code Playgroud)

代替.我通常build在源目录中使用一个空的子文件夹作为构建目录.

为了减轻您的痛苦,让我快速概述一下CMake生成的相关文件:

  • 项目文件/ Makefile - 您真正感兴趣的内容:在所选生成器下构建项目所需的文件.这可以是从Unix Makefile到Visual Studio解决方案的任何内容.
  • CMakeCache.txt - 这是一个持久的键/值字符串存储,用于在运行之间缓存值.存储在此处的值可以是库依赖项的路径,也可以是是否构建可选组件.变量列表几乎等于你看到运行时,一个ccmakecmake-gui.这对于不时查看可能很有用,但我建议使用上述工具来更改任何值(如果可能).
  • 生成的文件 - 这可以是从自动生成的源文件到导出宏的任何内容,可帮助您将构建的项目与其他CMake项目重新集成.其中大部分只是按需生成,不会出现在一个简单的项目中,例如问题中的项目.
  • 任何其他东西都是噪音,以保持构建系统的快乐.特别是,我从不需要关心CMakeFiles子目录中发生的任何事情.

一般来说,你不应该搞乱CMake为你生成的任何文件.所有问题都可以通过CMakeLists.txt一种方式或另一种方式从内部解决.只要结果按预期构建您的项目,您可能就好了.不要过分担心血腥的细节 - 因为这是CMake首先试图饶恕你的东西.

  • `CMakeFiles` 目录包含 `CMakeError.log` 和 `CMakeOutput.log`,对于排除 CMake 构建的故障很重要。 (3认同)
  • 有时您需要在“CMakeFiles/target_name.dir”目录中检查的两个内容是“flags.make”和“link.txt”文件。我必须在复杂的项目中检查这些,该项目从上游项目继承了标志/链接的东西。例如:我遇到了一些错误,因为 TPL A 依赖于 TPL B。此外,我的项目依赖于我在本地安装的 B;但是 A 使用了我系统中的 B 版本(而不是我的本地安装),它具有不同的启用选项,并且它先出现,导致我的项目出现错误。仅查看 link.txt 我就能发现发生了这种情况。 (3认同)

Pat*_*ryk 13

如其网站上所述:

Cmake是一个跨平台的开源构建系统,用于使用独立于编译器的方法管理软件的构建过程

在大多数情况下,它用于生成项目/生成文件 - 在您的示例中,它已生成Makefile用于构建软件的文件(主要在Linux/Unix平台上).

Cmake允许提供跨平台构建文件,这些文件将为特定编译/平台生成特定于平台的项目/ make文件.

例如,您可以尝试使用Visual Studio在Windows上编译软件,然后在您CMakeLists.txt可以启动的文件中使用适当的语法

cmake .
Run Code Online (Sandbox Code Playgroud)

在Windows平台上的项目目录中,Cmake将生成所有必要的项目/解决方案文件(.sln等).

如果您想在Linux/Unix平台上构建您的软件,您只需转到您拥有CMakeLists.txt文件的源目录并触发cmake .它,它将生成您通过简单make或者构建软件所需的所有文件 make all.

这里有一些关于关键Cmake功能的非常好的演示http://www.elpauer.org/stuff/learning_cmake.pdf

编辑

如果您想制作与平台相关的库包含/变量定义等,则可以在CMakeLists.txt文件中使用此语法

IF(WIN32)
   ...do something...
 ELSE(WIN32)
   ...do something else...
 ENDIF(WIN32)
Run Code Online (Sandbox Code Playgroud)

还有很多命令可以防止构建失败,Cmake会通知您,例如您没有升级库filesystemregex安装在您的系统上.为此,您可以使用以下语法:

find_package(Boost 1.45.0 COMPONENTS filesystem regex)
Run Code Online (Sandbox Code Playgroud)

检查它是否会为适当的系统/ IDE /编译器生成makefile.