C++ 使用 Makefile 和 CMake 编译代码的区别

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25789644/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 11:25:59  来源:igfitidea点击:

Difference between using Makefile and CMake to compile the code

c++cmakefilecmake

提问by rish

I code on C/C++ and use a (GNU) Makefile to compile the code. I can do the same with CMake and get a MakeFile. However, what is the difference between using Makefile and CMake to compile the code?

我在 C/C++ 上编码并使用(GNU)Makefile 来编译代码。我可以用 CMake 做同样的事情并得到一个 MakeFile。但是,使用 Makefile 和 CMake 编译代码有什么区别?

回答by Angew is no longer proud of SO

Make (or rather a Makefile) is a buildsystem - it drives the compiler and other build tools to build your code.

Make(或者更确切地说是一个 Makefile)是一个构建系统——它驱动编译器和其他构建工具来构建你的代码。

CMake is a generator of buildsystems. It can produce Makefiles, it can produce Ninja build files, it can produce KDEvelop or Xcode projects, it can produce Visual Studio solutions. From the same starting point, the same CMakeLists.txt file. So if you have a platform-independent project, CMake is a way to make it buildsystem-independent as well.

CMake 是构建系统的生成器。它可以生成 Makefile,可以生成 Ninja 构建文件,可以生成 KDEvelop 或 Xcode 项目,可以生成 Visual Studio 解决方案。从相同的起点,相同的 CMakeLists.txt 文件。因此,如果您有一个独立于平台的项目,CMake 也是一种使其独立于构建系统的方法。

If you have Windows developers used to Visual Studio and Unix developers who swear by GNU Make, CMake is (one of) the way(s) to go.

如果您的 Windows 开发人员习惯于使用 GNU Make 的 Visual Studio 和 Unix 开发人员,那么 CMake 是(一种)要走的路。

I would always recommend using CMake (or another buildsystem generator, but CMake is my personal preference) if you intend your project to be multi-platform or widely usable. CMake itself also provides some nice features like dependency detection, library interface management, or integration with CTest, CDash and CPack.

如果您希望您的项目是多平台或广泛使用的,我总是建议使用 CMake(或其他构建系统生成器,但 CMake 是我个人的偏好)。CMake 本身也提供了一些不错的功能,比如依赖项检测、库接口管理或与 CTest、CDash 和 CPack 的集成。

Using a buildsystem generator makes your project more future-proof. Even if you're GNU-Make-only now, what if you later decide to expand to other platforms (be it Windows or something embedded), or just want to use an IDE?

使用构建系统生成器可以使您的项目更加面向未来。即使您现在只使用 GNU-Make,如果您以后决定扩展到其他平台(无论是 Windows 还是嵌入式平台),或者只想使用 IDE,该怎么办?

回答by Victor Sergienko

The statement about CMake being a "build generator" is a common misconception.

关于 CMake 是“构建生成器”的说法是一种常见的误解。

It's not technically wrong; it just describes HOW it works, but not WHAT it does.

这在技术上没有错。它只是描述了它的工作原理,而不是它的作用。

In the context of the question, they do the same thing: take a bunch of C/C++ files and turn them into a binary.

在问题的上下文中,他们做同样的事情:获取一堆 C/C++ 文件并将它们转换为二进制文件。

So, what is the real difference?

那么,真正的区别是什么?

  • CMake is much more high-level. It's tailored to compile C++, for which you write much less build code, but can be also used for general purpose build. makehas some built-in C/C++ rules as well, but they are mostly useless.

  • CMakedoes a two-step build: it generates a low-level build script in ninjaor makeor many other generators, and then you run it. All the shell script pieces that are normally piled into Makefileare only executed at the generation stage. Thus, CMakebuild can be orders of magnitude faster.

  • The grammar of CMakeis much easier to support for external tools than make's.

  • Once makebuilds an artifact, it forgets how it was built. What sources it was built from, what compiler flags? CMaketracks it, makeleaves it up to you. If one of library sources was removed since the previous version of Makefile, makewon't rebuild it.

  • Modern CMake(starting with version 3.something) works in terms of dependencies between "targets". A target is still a single otput file (sadly), but can have transitive ("public"/"interface" in CMake terms) dependencies. These transitive dependencies can be exposed to or hidden from the dependent packages. CMakewill manage directories for you too. With make, you're stuck on a file-by-file and manage-directories-by-hand level.

  • CMake 更高级。它是为编译 C++ 量身定制的,为此您编写的构建代码要少得多,但也可用于通用构建。make也有一些内置的 C/C++ 规则,但它们大多没用。

  • CMake执行两步构建:它在ninjamake或许多其他生成器中生成低级构建脚本,然后您运行它。平时堆进去的所有shell脚本片段Makefile都只在生成阶段执行。因此,CMake构建速度可以快几个数量级。

  • 的语法比 make 的CMake更容易支持外部工具。

  • 一旦make构建了工件,它就会忘记它是如何构建的。它是从什么来源构建的,什么编译器标志?CMake跟踪它,make由你决定。如果自 的先前版本以来删除了一个库源Makefilemake则不会重建它。

  • 现代CMake(从版本 3.something 开始)在“目标”之间的依赖关系方面起作用。目标仍然是单个 otput 文件(遗憾的是),但可以具有传递性(CMake 术语中的“公共”/“接口”)依赖项。这些可传递依赖项可以向依赖包公开或隐藏。CMake也会为您管理目录。使用make,您会被困在逐个文件和逐个管理目录的级别。

You could code up something in makeusing flag files to cover the last two gaps, but you're on your own. makedoes contain a Turing complete language(even two, sometimes three counting Guile), and all of them are horrible.

您可以make使用标志文件编写一些代码来弥补最后两个空白,但您必须靠自己。make确实包含一个图灵完备的语言(甚至两个,有时三个计算Guile),而且它们都很可怕。

To be honest, this is what CMakeand makehave in common -- their languages are pretty horrible:

说实话,这是什么CMake,并make有共同的-他们的语言是相当可怕:

  • They have no types;
  • no arrays, only space-separated strings, thus escaping hell;
  • you normally pass arguments to functions by setting global variables; (this is being tackled in modern CMake - variables can have a namespaces now; a target is a namespace for its properties)
  • referring to an undefined variable is silently ignored by default;
  • 他们没有类型;
  • 没有数组,只有空格分隔的字符串,从而逃离地狱;
  • 您通常通过设置全局变量将参数传递给函数;(这在现代 CMake 中得到解决 - 变量现在可以有一个命名空间;目标是其属性的命名空间)
  • 默认情况下,对未定义变量的引用会被静默忽略;

to start with.

开始。

But in CMakeyou write much fewer lines of code.

但是CMake你编写的代码行要少得多。