Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/64.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 使用Makefile和CMake编译代码的区别_C++_C_Makefile_Cmake - Fatal编程技术网

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

C++ 使用Makefile和CMake编译代码的区别,c++,c,makefile,cmake,C++,C,Makefile,Cmake,我在C/C++上编写代码,并使用(GNU)Makefile编译代码。我可以用CMake做同样的事情,并得到一个MakeFile。但是,使用Makefile和CMake编译代码有什么区别?Make(或者更确切地说是Makefile)是一个构建系统-它驱动编译器和其他构建工具来构建代码 CMake是构建系统的生成器。它可以生成makefile,它可以生成Ninja构建文件,它可以生成KDEvelop或Xcode项目,它可以生成visualstudio解决方案。从相同的起点,创建相同的CMakeLis

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

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

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

如果Windows开发人员习惯于Visual Studio和Unix开发人员对GNU Make信誓旦旦,那么CMake就是一个不错的选择

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


使用buildsystem生成器可以使您的项目更加经得起未来的考验。即使您现在是GNU Make,但如果您后来决定扩展到其他平台(无论是Windows还是嵌入式平台),或者只是想使用IDE呢?

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

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

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

那么,真正的区别是什么

  • CMake更高级。它是专门编译C++的,你可以编写更少的编译代码,但也可以用于通用的构建。code>make也有一些内置的C/C++规则,但它们充其量是无用的

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

  • CMake
    的语法更易于支持外部工具

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

  • 现代
    CMake
    (从版本3.something开始)根据“目标”之间的依赖关系工作。目标仍然是单个输出文件,但它可以具有可传递的(“公共”/“接口”在CMake术语中)依赖关系。 这些可传递的依赖项可以向依赖包公开或隐藏
    CMake
    将为您管理目录。使用
    make
    ,您只能一个文件接一个文件,手动管理目录

您可以使用中间文件在
make
中编写一些代码来填补最后两个空白,但这是您自己的事情<代码>制作包含一个(偶数两个,有时三个);前两个是可怕的,而且诡计几乎从未使用过

老实说,这就是
CMake
make
的共同点——它们的语言非常可怕。我想到的是:

  • 它们没有用户定义的类型
  • CMake
    有三种数据类型:字符串、列表和具有属性的目标
    make
    有一个:字符串
  • 通常通过设置全局变量将参数传递给函数。
    • 这在现代CMake中得到了部分处理-您可以设置目标的属性:
      set_属性(目标helloworld附加属性包括_目录“${CMake_CURRENT_SOURCE_DIR}”)
  • 默认情况下,引用未定义的变量会被静默忽略
谢谢!我要确认的是,如果我只在Linux环境下编写程序,而不是只在makefile上编写程序就足够了,但是如果我想让Linux上的程序在Mac上运行,而不是在cmake上运行,这是更好的选择,据我所知,我们不需要在Mac上编写新的makefile,只需要运行cmake即可。这就是重点吗?是的,这就是要点。然而,请注意,在Linux上编程的方法比Makefiles更多——例如,请参见QtCreator、KDEvelop、Ninja。对于其中的每一个,要么“创建一个项目并使其与Makefile保持同步”,要么“重新运行CMake”。而且,正如答案所提到的,CMake还有其他功能,比如依赖项发现(例如)或测试/打包支持。我读到CMake不能创建非递归的makefiles。这仍然是真的吗?@Angew Non recursive是指使用完整的项目依赖关系树调用make一次。与顶级makefile以特定顺序调用子项目makefiles时的递归相反,这是CMake的一个重要缺点-GNU make有它的缺点,但是如果你花时间学习它,它是非常强大和通用的,并且可以在大量的平台上工作。没有一个完整的依赖树来分析是一个主要的缺陷,谷歌的“递归使被认为是有害的”。这里有一些很好的信息,但有一句话是完全错误的:cmake有一个列表类型,因为它具有正确的列表函数,这对于许多构建系统任务来说是至关重要的,有一点不同:我不会称之为“完全”错误,但是谢谢你的更正。@VictorSergienko,在OP的问题中没有被问到,但我一直在等待妙语……你觉得哪种用法比这两种用法都好?我使用make是出于历史原因,而我