GCC、CMake、CMakelist、Make、Makefile、Ninja啥关系?一图讲透!

一、GCC的诞生!

1985年,一个伸手不见五指的黑夜,一位满脸胡须、五短身材、头发长乱的怪人开始编写一套C语言编译器。这个怪人后来被称作“最伟大的程序员”、“自由软件之父”,他就是 Richard Stallman。经过2年时间没日没夜的苦练,胡须更长、头发更乱的Richard Stallman完成了C语言编译器初版,称之为GNU C Complier,也就是现在大名鼎鼎GCC的来源。后来GCC快速发展,现在GCC除了能编译C语言,还能编译C++、Fortran、Pascal、Objective-C、Java以及Ada 等语言。上世纪80、90年代,个人计算机CPU频率、硬盘大小、内存大小都是以MB为单位,甚至KB为单位,需要编译的程序文件个数较少,用GCC命令也足以应对。

二、新的麻烦出现了! (make & makefile)

随着计算机的性能提升和普及,一个软件工程包含的源文件越来越多,比如linux,采用gcc命令逐个手动去编译,很容易混乱而且工作量大,会让人抓狂。 于是乎,Richard Stallman和 Roland McGrath 共同开发了make 和makefile来解决这个问题。make工具可以看成是一个智能的批处理工具,它本身并没有编译和链接的功能,而是用类似于批处理的方式—通过调用makefile文件中用户指定的命令来进行编译和链接的。makefile是什么?makefile就是一个脚本文件,简单的说就像一首歌的乐谱,make工具就像指挥家,指挥家根据乐谱指挥整个乐团怎么样演奏,make工具就根据makefile中的命令进行编译和链接的。makefile命令中就包含了调用gcc(也可以是别的编译器)去编译某个源文件的命令。

三、新的麻烦又出现了!(Cmake & CMakelist)

makefile在一些简单的工程下,完全可以人工手写,但是当工程非常大的时候,手写makefile也是非常麻烦。而且陆陆续续出现了各种不同平台的makefile,有GNU make、QT 的 qmake,微软的 MSnmake,BSD Make(pmake),Makepp等等。这些 Make 工具遵循着不同的规范和标准,所执行的 Makefile 格式也千差万别。这样就带来了一个严峻的问题:如果软件想跨平台,必须要保证能够在不同平台编译。而如果使用上面的 Make 工具,就得为每一种标准写一次 Makefile ,这将是一件让人抓狂的工作,如果换了个平台makefile又要重新修改。

于是乎,这时候就出现了Cmake这个工具,Cmake就可以更加简单地生成makefile文件给上面那个make用。当然cmake还有其他功能,就是可以跨平台生成对应平台能用的makefile,你不用再自己去修改了。cmake正是makefile的上层工具,它们的目的正是为了产生可移植的makefile,并简化自己动手写makefile时的巨大工作量。可是cmake根据什么生成makefile呢?它又要根据一个叫CMakeLists.txt文件(学名:组态档)去生成makefile。到最后CMakeLists.txt文件谁写啊?当然是你自己手写的。

四、新的麻烦又又又出现了!(Ninja)

随着软件工程越来越大,越来越复杂,make的执行速度慢的问题越来越严重了。

于是乎,Google的一名程序员推出的注重速度的构建工具Ninja。Ninja 舍弃了各种高级功能,语法和用法非常简单,给它指定好了具体详细要做什么,所以启动编译的速度非常快。根据实际测试:在超过30,000个源文件的情况下,也能够在1秒钟内开始进行真正的构建。与之相比,通过资深工程师进行编写的Makefiles文件也需要10-20秒才能开始构建。

五、目前完美的结局!

Cmake可以生成 .ninja 和.makefile 的工具。因为担心很多人不熟悉makefile文件和ninja文件的写法,所以cmake只需要用户通过对源码文件的简单描述(就是CMakeLists.txt文件),就能自动生成一个project的makefile文件或者ninja文件,然后就可以通过ninja或者make进行启动编译了。

GCC、CMake、CMakelist、Make、Makefile、Ninja啥关系?一图讲透! - 知乎

<think>嗯,用户想了解CMakeMakefile之间的区别,我需要整理下这两者的不同点。首先,根据引用的资料,CMakeMakefile都是构建工具,但CMake更像是个构建生成器,而Makefile是直接指导构建过程的脚本。 我记得引用中提到,Makefile需要手动编写所有的编译规则,特别是当项目变得庞大时,管理起来会比较复杂。而CMake通过更高级的脚本语言生成Makefile或者其他构建系统的文件,比如Ninja,这样能简化项目配置,特别是在跨平台的时候。比如,用户如果需要在Windows、macOS和Linux上构建项目,CMake可以自动适配不同平台的Makefile,而手动编写Makefile的话,每个平台都要维护不同的版本,很麻烦。 另外,跨平台支持是个关键点。引用4提到,CMake适合需要跨平台的项目,而Makefile主要适用于GNU环境。比如,如果项目要用到Visual Studio的编译器,CMake可以生成对应的解决方案文件,而Makefile可能需要借助其他工具或者手动调整,这增加了维护的难度。 还有语法层面,Makefile使用自己的语法,规则比较繁琐,尤其是处理依赖关系的时候。而CMake的语法更简洁,支持模块化和函数式编程,比如find_package这样的命令可以方便地查找依赖库,这在Makefile中可能需要写很多shell命令或者手动指定路径。 生成过程方面,引用3和5指出,CMake需要先运行生成Makefile,然后再用make来编译。而Makefile直接使用make命令执行。这也意味着使用CMake多了个步骤,但对于大型项目来说,这个步骤能带来更好的可维护性和扩展性。 另外,用户可能关心选择标准。比如项目规模,小项目用Makefile简单,大项目用CMake更高效。还有自动化构建和可维护性,CMake在这方面更有优势。比如,如果项目需要频繁添加新的源文件或依赖库,CMake可以通过变量和循环结构来简化配置,而Makefile可能需要逐个添加,容易出错。 不过,用户可能也会疑惑,既然CMake这么好,为什么还有人用Makefile?可能是因为小型项目或者对构建过程有特殊需求的情况下,直接写Makefile更直接,不需要额外的生成步骤,也减少工具链的依赖。 最后,需要确保回答覆盖了主要区别,比如定位与功能、语法与配置、生成过程、跨平台能力、适用场景等,并结合引用中的例子,让回答更有依据。可能还需要提醒用户根据项目需求选择,比如跨平台选CMake,小项目用Makefile。</think>### CMake vs Makefile: 核心区别与对比 #### 1. **定位与功能** - **Makefile**:直接定义编译规则和依赖关系的脚本文件,需手动编写所有构建细节(如编译器选项、文件依赖链)。例如: ```makefile main: main.c utils.c gcc -o main main.c utils.c ``` - **CMake**:通过高级配置语言(`CMakeLists.txt`)**生成**底层构建文件(如MakefileNinja文件)。例如: ```cmake cmake_minimum_required(VERSION 3.10) project(MyProject) add_executable(main main.c utils.c) ``` 优势在于自动处理依赖关系和跨平台兼容性[^3][^5]。 #### 2. **语法与配置** - **Makefile**:使用基于规则的语法,需显式指定编译命令和目标依赖: ```makefile object_files = main.o utils.o main: $(object_files) gcc -o main $(object_files) ``` 复杂项目需大量手动维护依赖链,易出错。 - **CMake**:提供声明式语法,内置函数简化配置。例如: ```cmake find_package(OpenMP REQUIRED) target_link_libraries(main PRIVATE OpenMP::OpenMP_C) ``` 支持模块化配置(如`find_package`自动查找依赖库)[^2][^4]。 #### 3. **生成过程** - **Makefile**:直接执行`make`命令触发构建。 - **CMake**:需先运行`cmake`生成构建文件,再调用`make`(或其他工具): ```bash mkdir build && cd build cmake .. # 生成Makefile make # 执行编译 ``` 支持生成多种构建系统文件(如Xcode工程、Visual Studio项目)[^5]。 #### 4. **跨平台能力** - **Makefile**:依赖GNU工具链,在Windows等非Unix环境需额外工具(如MinGW或Cygwin)[^4]。 - **CMake**:原生支持多平台,自动适配本地编译器(如Windows的MSVC、macOS的Clang)[^1][^4]。 #### 5. **适用场景** | **场景** | **推荐工具** | **原因** | |----------------|------------|------------------------------------------| | 小型单平台项目 | Makefile | 配置简单,无需生成步骤 | | 大型跨平台项目 | CMake | 自动管理依赖,减少平台适配成本 | | 依赖复杂库的项目 | CMake | `find_package`等函数简化第三方库集成 | #### 示例对比 - **Makefile编译OpenMP程序**: ```makefile CC = gcc CFLAGS = -fopenmp main: main.c $(CC) $(CFLAGS) -o main main.c ``` - **CMake实现同等功能**: ```cmake cmake_minimum_required(VERSION 3.12) project(OpenMPDemo) find_package(OpenMP REQUIRED) add_executable(main main.c) target_link_libraries(main PRIVATE OpenMP::OpenMP_C) ``` CMake自动处理编译器差异(如MSVC需`-openmp`而非`-fopenmp`)[^4]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值