使用Makefile和CMake编译代码的区别是什么?

我用C/ c++编写代码,并使用(GNU) Makefile编译代码。我可以用CMake做同样的事情,并获得一个Makefile。但是,使用Makefile和CMake来编译代码之间有什么区别呢?

226981 次浏览

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

CMake是一个构建系统的生成器。它可以生成makefile,可以生成Ninja构建文件,可以生成KDEvelop或Xcode项目,也可以生成Visual Studio解决方案。同样的起点,同样的CMakeLists.txt文件。因此,如果你有一个平台无关的项目,CMake是一种使它与构建系统无关的方法。

如果你有使用Visual Studio的Windows开发人员和使用GNU Make的Unix开发人员,CMake是你可以选择的方法之一。

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

使用构建系统生成器使您的项目更加经得起考验。即使您现在只使用gnu - make,但如果稍后决定扩展到其他平台(无论是Windows还是嵌入式平台),或者只想使用IDE,该怎么办?

关于CMake是一个“构建生成器”的声明;是一种常见的误解。

从技术上讲,这并没有错;它只是描述了它是如何工作的,而不是它是做什么的。

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

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

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

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

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

  • 一旦make构建了一个工件,它就会忘记它是如何构建的。它是从什么来源构建的,什么编译器标志?CMake跟踪它,make把它留给你。如果自Makefile的上一个版本以来删除了一个库源,make将不会重新构建它。

  • 现代CMake(从版本3.something开始)根据“目标”之间的依赖关系工作。一个目标仍然是一个单一的输出文件,但是它可以有可传递的(“公开”/“接口”)。在CMake术语中)依赖项。 这些可传递依赖关系可以向依赖包公开,也可以向依赖包隐藏。CMake将为你管理目录。对于make,你将停留在逐个文件和逐个手动管理目录的级别

你可以在make中编写一些代码,使用中间文件来覆盖最后两个空白,但这是你自己的。make确实包含一个图灵完备语言(甚至是两个,有时是三个,包括诡计);前两个是可怕的,Guile几乎从未使用过。

老实说,这就是CMakemake的共同之处——他们的语言非常糟糕。我想到的是:

  • 它们没有用户定义的类型;
  • CMake有三种数据类型:字符串、列表和带有属性的目标。make有一个:string;
  • 通常通过设置全局变量将参数传递给函数。
    • 这在现代CMake中得到了部分解决——你可以设置目标的属性:set_property(TARGET helloworld APPEND PROPERTY INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}");
  • 默认情况下,引用未定义的变量会被静默忽略;

正如在其他答案中提到的,CMake可以生成其他项目文件。它将这些项目引用为发电机

这允许用户使用特定于领域的语言编写/描述他们的构建,并使用生成器编译项目。与直接写入这些项目文件相比,它通常会产生更简单/更好的代码。

最大的优势是用户可以使用他们最熟悉的工具(Makefiles, Visual Studio, XCode, Ninja等)。这很好,但有争议会带来复杂性。为什么不直接使用Ninja?

答案是历史。(这是C/ c++的标准)

像Visual Studio这样的构建系统拥有只接受这些项目文件的工具。

例如,微软有一个叫做“静态驱动程序验证器”的功能。一个分析内核模式windows驱动程序代码的工具。然而,这个工具只适用于Visual Studio项目,因为它与msbuild一起工作。

msbuild /t:sdv /p:Inputs="Parameters" ProjectFile /p:Configuration=configuration /p:Platform=platform

如果您的构建系统不能生成Visual Studio项目文件,那么您就不能使用该工具。对于某些项目/公司,这可以是非常重要