不同的编译工具

编译过程概述

cmake/makefile/make 理解

make 工具可以看成是一个智能的批处理工具,它本身并没有编译和链接的功能,而是用类似于批处理的方式:通过调用 makefile 文件中用户指定的命令来进行编译和链接的。

  • CMake 是一个跨平台的、开源的构建工具。cmake 是 makefile 的上层工具,它们的目的正是为了产生可移植的 makefile,并简化自己动手写 makefile时的巨大工作量;
  • make 命令写在文件中,构成一系列构建规则的文件叫做 Makefile 文件。Makefile 文件有一套自己专门的语法,包括 echoing、通配符、模式匹配、变量和赋值符、自动变量等内容。
  • Linux 中 make 是用来编译的,它从 Makefile 中读取指令,然后编译。make 的作用是开始进行源代码编译,以及由 Makefile 设置文件提供的一些功能;比如 make install 表示进行安装(一般需要有 root 权限),make uninstall 是卸载,不加参数就是默认的进行源代码编译。

CMake 编译过程

CMake 是针对跨平台编译问题,所设计的工具:它首先允许开发者编写一种平台无关的 CMakeList.txt 文件来定制整个编译流程,然后再根据目标用户的平台进一步自动生成所需的本地化 Makefile 和工程文件,如 Unix 的 Makefile 或 Windows 的 Visual Studio 工程。

Linux 平台下使用 CMake 生成 Makefile 并编译的流程如下:

  1. 编写 CMake 配置文件 CMakeLists.txt
  2. 执行命令 cmake PATH 或者 ccmake PATH 生成 Makefile (ccmake 和 cmake 的区别在于前者提供了一个交互式的界面)。其中, PATHCMakeLists.txt 所在的目录。
  3. 使用 make 命令进行编译得到项目可执行文件。make “-j []” 指同时运行命令的个数。如果没有这个参数,make 运行命令时能运行多少就运行多少。

GCC 是什么

GNU(Gnu’s Not Unix)编译器套装(GNU Compiler Collection,GCC),指一套编程语言编译器,以 GPL 及 LGPL 许可证所发行的自由软件,也是 GNU 项目的关键部分,也是 GNU 工具链的主要组成部分之一。GCC(特别是其中的 C 语言编译器)也常被认为是跨平台编译器的事实标准。1985 年由理查德·马修·斯托曼开始发展,现在由自由软件基金会负责维护工作。GCC 原本用 C 开发,后来因为 LLVM、Clang 的崛起,它更快地将开发语言转换为 C++。GCC 在发布后很快地得到扩展,变得可处理 C++。之后也变得可处理 Fortran、Pascal、Objective-C、Java、Ada,Go 与其他语言。

许多操作系统,包括许多类 Unix 系统,如 Linux 及 BSD 家族都采用 GCC 作为标准编译器。苹果电脑预装的 Mac OS X 操作系统也采用这个编译器。GCC 目前由世界各地不同的数个程序员小组维护。它是移植到最多中央处理器架构以及最多操作系统的编译器。由于 GCC 已成为 GNU 系统的官方编译器(包括 GNU/Linux 家族),它也成为编译与创建其他操作系统的主要编译器,包括 BSD 家族、Mac OS X、NeXTSTEP 与 BeOS。GCC 通常是跨平台软件的编译器首选。有别于一般局限于特定系统与运行环境的编译器,GCC 在所有平台上都使用同一个前端处理程序,产生一样的中介码,因此此中介码在各个其他平台上使用 GCC 编译,有很大的机会可得到正确无误的输出程序。

GCC 原本用 C 开发,后来因为 LLVM、Clang 的崛起,它更快地将开发语言转换为 C++。许多 C 的爱好者在对 C++一知半解的情况下主观认定 C++的性能一定会输给 C,但是 Ian Lance Taylor 给出了不同的意见,并表明 C++不但性能不输给 C,而且能设计出更好,更容易维护的程序。

gcc 与 g++ 的区别

这里的 gcc (小写)与前文的 GCC 含义是不同的。简单来说,gcc 指的是 GCC 中的 GNU C Compiler(C 编译器);g++ 是 G++ 中的 GNU C++ Compiler(C++ 编译器),但实际上 gcc 和 g++ 都不是编译器,也不是编译器的集合,它们只是一种驱动器,根据参数中的文件类型,调用对应的 GNU 编译器,所以更准确的说法是:gcc 调用了 C compiler, g++ 调用了 C++ compiler。gcc 和 g++ 的主要区别如下:

  • 使用 gcc 编译 cpp 文件可能会报错,因为 gcc 编译文件时不会自动链接标准库 STL,而 g++ 会,为了能够使用 STL,需要添加参数 -lstdc++gcc -lstdc++g++ 不等价。
  • 对于 *.c*.cpp 文件,gcc 分别当做 c 和 cpp 文件编译(c 和 cpp 的语法强度是不一样的)。
  • 对于 *.c*.cpp 文件,g++ 则统一当做 cpp 文件编译。
  • gcc 在编译 c 文件时,可使用的预定义宏是比较少的。

Clang 是什么

Clang 是一个 C、C++、Objective-C 和 Objective-C++ 编程语言的编译器前端。它采用了底层虚拟机(LLVM)作为其后端。它的目标是提供一个 GNU 编译器套装(GCC)的替代品。作者是克里斯·拉特纳(Chris Lattner),在苹果公司的赞助支持下进行开发,而源代码授权是使用类 BSD 的伊利诺伊大学厄巴纳-香槟分校开源码许可。Clang 主要由 C++编写。Clang 项目包括 Clang 前端和 Clang 静态分析器等。这个软件项目在 2005 年由苹果电脑发起,是 LLVM(Low Level Virtual Machine)编译器工具集的前端(front-end),目的是输出代码对应的抽象语法树(Abstract Syntax Tree, AST),并将代码编译成 LLVM Bitcode。接着在后端(back-end)使用 LLVM 编译成平台相关的机器语言。Clang 本身性能优异,其生成的 AST 所耗用掉的内存仅仅是 GCC 的 20%左右。2014 年 1 月发行的 FreeBSD10.0 版将 Clang/LLVM 作为默认编译器。

Clang 与 GCC 对比

二者的优劣对比如下:

  • GCC 特性:除支持 C/C++/ Objective-C/Objective-C++语言外,还是支持 Java/Ada/Fortran/Go 等;当前的 Clang 的 C++支持落后于 GCC;支持更多平台;更流行,广泛使用,支持完备。
  • Clang 特性:编译速度快;内存占用小;兼容 GCC;设计清晰简单、容易理解,易于扩展增强;基于库的模块化设计,易于 IDE 集成;出错提示更友好。

MinGW 是什么

MinGW(Minimalist GNU for Windows),又称 mingw32,是将 GCC 编译器和 GNU Binutils 移植到 Win32 平台下的产物,包括一系列头文件(Win32API)、库和可执行文件。另有可用于产生 32 位及 64 位 Windows 可执行文件的 MinGW-w64 项目,是从原本 MinGW 产生的分支。如今已经独立发展。MinGW 是从 Cygwin(1.3.3 版)基础上发展而来。

GCC 支持的语言大多在 MinGW 也受支持,其中涵盖 C、C++、Objective-C、Fortran 及 Ada。对于 C 语言之外的语言,MinGW 使用标准的 GNU 运行库,如 C++ 使用 GNU libstdc++。但是 MinGW 使用 Windows 中的 C 运行库。因此用 MinGW 开发的程序不需要额外的第三方 DLL 支持就可以直接在 Windows 下运行,而且也不一定必须遵从 GPL 许可证。这同时造成了 MinGW 开发的程序只能使用 Win32API 和跨平台的第三方库,而缺少 POSIX 支持[3],大多数 GNU 软件无法在不修改源代码的情况下用 MinGW 编译。