相信很多编程初学者,对以上这些常见名词都很熟悉,但都分不清楚,今天写这篇文章,一次性说清楚这些东西的作用。
GNU
首先参考wiki:https://zh.wikipedia.org/zh-cn/GNU
GNU就是GNU’s Not Unix!的缩写,GNU是一个自由的操作系统,其内容完全以GPL协议发布,由理查德·斯托曼(Richard Stallman)于1983年创立。GNU项目的目标是创建一个完全自由的操作系统,用户可以自由使用、修改和分发其软件。
作为操作系统,GNU的发展仍未完成,其中最大的问题是具有完备功能的内核尚未被开发成功。GNU的内核,称为Hurd,是自由软件基金会发展的重点,但是其发展尚未成熟。在实际使用上,多半使用Linux内核、FreeBSD等替代方案,作为系统核心,其中主要的操作系统是Linux的发行版。Linux操作系统包涵了Linux内核与其他自由软件项目中的GNU组件和软件,可以被称为GNU/Linux(见GNU/Linux命名争议)。
可以简单理解,GNU就是一个平台,这个平台上开发了操作系统、编译工具、库文件等一系列东西。但主要由以下几个部分组成:
- GNU工具链:包括GCC(GNU Compiler Collection),GDB(GNU Debugger)等开发工具。
- GNU核心库:如GLibc(GNU C Library)。
- GNU核心工具:如Bash(GNU Bourne Again Shell)和其他基本命令行工具。关于SHELL的相关内容可以参考我的另一篇文章终端和Shell是什么?
所以,可以认为,GNU是一个旨在提供自由软件的项目,它包含了各种开发工具、库和程序。
GCC
介绍完了GNU,那么一定要介绍GCC,GCC(GNU Compiler Collection)是一个开源的编译器套件,由GNU项目开发和维护。它支持多种编程语言,并且在许多操作系统和硬件平台上运行。GCC是一个功能强大且灵活的工具,广泛应用于软件开发和操作系统内核的编译。以下是GCC的一些主要特点和组成部分:
支持的编程语言:C、C++、Go、Objective等,如果大家学过C、C++,那么一定会对GCC非常熟悉。
主要组成部分:
- 前端(Front End):负责将高级编程语言(如C或C++)的源代码转换为中间表示(Intermediate Representation,IR)。每种编程语言都有自己的前端。
- 中间表示(IR):一种通用的代码表示形式,用于在编译过程中进行优化和转换。
- 优化器(Optimizer):在中间表示阶段,GCC对代码进行各种优化,以提高运行效率和减少资源消耗。例如做算法题时经常会说
O2、O3
优化有没有开。 - 后端(Back End):负责将中间表示转换为特定目标平台的机器代码。GCC的后端支持多种硬件架构,如x86、ARM、MIPS等。
- 链接器(Linker):负责将多个目标文件和库文件链接在一起,生成最终的可执行文件或库。
GCC最强大的地方在于,跨平台,开源且遵循GPL(GNU General Public License),高性能。因此GCC广泛运用在多种操作系统平台上,同时在Linux和其他类Unix操作系统上也将GCC作为默认编译器。
GCC和G++有什么区别?
GCC和G++是GNU编译器套件中的两个不同组件,用于编译不同的编程语言。虽然它们都属于GCC(GNU Compiler Collection),但它们在用途和默认处理的编程语言方面有所不同。
GCC是一个通用的编译器驱动程序,可以编译多种编程语言,如C、C++、Fortran、Ada、Go等。它通过文件扩展名自动选择适当的前端编译器。例如,.c
文件使用C编译器,.cpp
文件使用C++编译器。在控制台中使用如下命令编译代码:
gcc -o myprogram myprogram.c
G++是GCC的一个专用驱动程序,专门用于编译C++代码。它不仅能够编译C++源代码,还会自动链接C++标准库。简单来说,G++就是GCC的一个分支,隶属于GCC。
g++ -o myprogram myprogram.cpp
关键区别,
- gcc默认处理C语言文件,如果需要编译C++代码,需要明确指定,而G++默认处理c++文件。
- 使用GCC编译C++代码,需要手动链接C++标准库,这也是为什么大家都说编译c语言用GCC、编译C++用G++。
gcc -o myprogram myprogram.cpp -lstdc++
g++ -o myprogram myprogram.cpp # 使用g++无需额外指定链接库文件
为什么有时候使用gcc也可以编译C++代码?
当你在C++程序中没有使用STL库(关于STL相关可以参考文章C++ STL详细介绍和底层原理讲解)、以及一些C++面向对象相关的代码时,此时可以认为C++代码就是C语言代码,因此也能编译通过。
MinGW
MinGW(Minimalist GNU for Windows)是一个开发工具集,旨在将GNU编译器套件(GCC)和GNU工具链带到Windows平台上。它提供了开发和构建Windows应用程序所需的编译器和工具,同时保留了GNU工具链的特性和功能。
MinGW的组成部分
- GCC编译器:包括
gcc
、g++
等,用于编译C、C++代码。 - Binutils:包括汇编器、链接器等工具。
- MSYS(Minimal SYStem):提供一个轻量级的Unix风格的环境,包含基本的Unix命令(如
bash
、make
、awk
等),方便在Windows下使用GNU工具链。 - Windows API库:提供与Windows操作系统交互的必要库和头文件,允许编译生成的程序运行在Windows平台上。
MinGW的特点
- 跨平台:尽管MinGW运行在Windows上,它使用的编译器和工具与Linux、Unix系统上的GNU工具链一致。
- 轻量级:MinGW相对轻量,易于安装和配置,不需要依赖其他庞大的软件包或环境。
- 开放源代码:MinGW是开源的,用户可以自由使用、修改和分发。
- 兼容性:提供与Windows原生API的兼容性,允许开发者使用标准的Windows库和功能。
MinGW说白了,就是将GNU编译器和工具链带到了Windows平台,并且和linux下的GNU工具保持一致,这使得项目移植开发变得简单。
LLVM
简单理解:LLVM = GCC,是另外一帮人开发的工具,和GCC有很多相识之处。下面来看详细介绍。
来自wiki百科:https://zh.wikipedia.org/wiki/LLVM
LLVM项目的发展起源于2000年伊利诺伊大学厄巴纳-香槟分校维克拉姆·艾夫(Vikram Adve)与克里斯·拉特纳(Chris Lattner)的研究,他们想要为所有静态及动态语言创造出动态的编译技术。LLVM是以BSD许可来发展的开源软件。2005年,苹果电脑雇用了克里斯·拉特纳及他的团队为苹果电脑开发应用程序系统[4],LLVM为现今macOS及iOS开发工具的一部分。
LLVM的命名最早源自于底层虚拟机(Low Level Virtual Machine)的首字母缩写[5],由于这个项目的范围并不局限于建立一个虚拟机,这个缩写导致了广泛的疑惑。LLVM开始成长之后,成为众多编译工具及低端工具技术的统称,使得这个名字变得更不贴切,开发者因而决定放弃这个缩写的意涵[6],现今LLVM已单纯成为一个系统,适用于LLVM下的所有项目,包含LLVM中介码(LLVM IR)、LLVM调试工具、LLVM C++标准函式库等。
以下是一些关于LLVM的关键点:
- 模块化设计:LLVM由多个模块组成,这些模块可以独立使用或组合在一起,以支持不同的编译和优化任务。
- 中间表示(IR):LLVM使用一种称为LLVM中间表示(LLVM IR)的中间代码,这种IR是高度优化的,并且设计成能够跨越不同的硬件和软件平台进行高效的代码生成和优化。
- 前端和后端:LLVM支持多种前端和后端。前端将高层语言(如C、C++、Rust等)编译成LLVM IR,而后端则将LLVM IR编译成目标机器代码(如x86、ARM等)。
- 优化:LLVM具有强大的优化能力,可以在不同的编译阶段(如编译时、链接时、运行时)进行代码优化,从而提高程序的性能和效率。
- 工具链:除了编译器,LLVM还提供了一整套相关的工具和库,如Clang(一个基于LLVM的C语言家族的编译器前端)、LLD(一个高效的链接器)、libc++(一个C++标准库实现)等。
LLVM项目被广泛应用于学术研究、工业编译器开发和各种软件工程项目中。其模块化和灵活的设计使其成为编译器技术领域中的一个重要工具。
Clang、Clang++
Clang和Clang++是LLVM项目的一部分,它们是基于LLVM的编译器前端,分别用于C语言和C++语言的编译。你可以将Clang类比为GCC,因为他们都是编译器前端,负责将高级编程语言(如C、C++等)编译成目标机器代码或中间表示(IR)。
然而,尽管它们具有相似的目标和功能,但在设计和实现上有一些重要的区别和特点:
共同点
- 编译器前端:Clang和GCC都包含前端,负责解析和编译高级语言(如C、C++、Objective-C等)。
- 支持多种语言:两者都支持多种编程语言,包括C、C++、Objective-C等。
- 优化和代码生成:都包含各种优化技术,以生成高效的目标代码。
- 跨平台支持:Clang和GCC都支持在多个操作系统和硬件平台上运行。
不同点
- 架构设计:
- Clang:基于LLVM架构,具有模块化和现代化的设计。它将高级语言编译成LLVM中间表示(IR),然后由LLVM进行优化和代码生成。
- GCC:传统的单体编译器,包含自己的前端、优化和代码生成阶段。GCC的架构较为一体化,但近年来也进行了模块化改进。
- 诊断信息:
- Clang:以生成清晰且详细的诊断信息而闻名,错误和警告信息易于理解,有助于开发者快速定位和修复问题。
- GCC:虽然也提供详细的诊断信息,但在用户友好性和可读性上通常不如Clang。
- 编译速度:
- Clang:通常编译速度较快,尤其是在增量编译和处理大型代码库时表现优异。
- GCC:在某些情况下可能较慢,但通过优化和配置可以提升编译性能。
- 扩展性和工具链:
- Clang:由于基于LLVM的模块化设计,易于扩展和集成。它还支持多种工具,如Clang Static Analyzer、Clang-Tidy、Clang-Format等。
- GCC:虽然也有许多扩展和工具,但其扩展性通常不如Clang灵活。
- 标准支持和兼容性:
- Clang:快速跟进最新的语言标准和特性,尤其是C++标准。与其他编译器(如MSVC)兼容性较好。
- GCC:也支持最新的语言标准,但更新速度可能稍慢,特别是在新特性方面。
Clang和GCC都是功能强大的编译器前端,各有优缺点。Clang以其现代化设计、快速编译、详细诊断和扩展性而受到欢迎,而GCC则以其成熟稳定、广泛使用和丰富的功能著称。在实际应用中,选择Clang或GCC通常取决于具体需求和项目环境。
GDB、LLDB
GDB和LDB都是Debugger工具,区别在于GDB来自GNU,LDB来自LLVM。都广泛用于调试C、C++、Objective-C等编程语言编写的程序。
GDB(GNU Debugger)
主要特点
- 多语言支持:支持C、C++、Fortran、Ada等多种编程语言。
- 广泛平台支持:可以在各种操作系统(如Linux、Windows、macOS等)和硬件平台上运行。
- 强大的功能:支持断点设置、单步执行、检查和修改变量、调用栈追踪、多线程和多进程调试等。
- 脚本化支持:可以使用Python、Guile等脚本语言进行扩展和自动化调试任务。
- 远程调试:可以通过网络进行远程调试,适用于嵌入式系统和分布式应用程序。
常用命令
break [location]
:在指定位置设置断点。run [args]
:运行程序并传递参数。continue
:继续执行程序直到下一个断点。step
:单步执行程序(进入函数)。next
:单步执行程序(跳过函数)。print [expression]
:打印表达式的值。
LLDB(LLVM Debugger)
主要特点
- 基于LLVM架构:与LLVM紧密集成,使用LLVM的模块化设计和优化技术。
- 快速启动和响应:由于模块化设计和现代实现,启动和响应速度较快。
- 广泛语言支持:支持C、C++、Objective-C、Swift等多种语言,并不断扩展支持的语言种类。
- 强大的调试功能:支持断点、单步执行、检查和修改变量、调用栈追踪、多线程和多进程调试等。
- 脚本化支持:可以使用Python脚本进行扩展和自动化调试任务。
- 集成开发环境(IDE)支持:与Xcode、Visual Studio Code等IDE无缝集成,提供良好的用户体验。
常用命令
breakpoint set -n [function]
:在指定函数设置断点。run
:运行程序。continue
:继续执行程序直到下一个断点。step
:单步执行程序(进入函数)。next
:单步执行程序(跳过函数)。frame variable [variable]
:打印变量的值。
cmake
来自wiki百科:https://zh.wikipedia.org/wiki/CMake
CMake是个一个开源的跨平台自动化建构系统,用来管理软件建置的程序,并不依赖于某特定编译器,并可支持多层目录、多个应用程序与多个函式库。 它用配置文件控制建构过程(build process)的方式和Unix的make相似,只是CMake的配置文件取名为CMakeLists.txt。CMake并不直接建构出最终的软件,而是产生标准的建构档(如Unix的Makefile或Windows Visual C++的projects/workspaces),然后再依一般的建构方式使用。这使得熟悉某个集成开发环境(IDE)的开发者可以用标准的方式建构他的软件,这种可以使用各平台的原生建构系统的能力是CMake和SCons等其他类似系统的区别之处。 CMake配置文件(CMakeLists.txt)可设置源代码或目标程序库的路径、产生适配器(wrapper)、还可以用任意的顺序建构可执行文件。CMake支持in-place建构(二进档和源代码在同一个目录树中)和out-of-place建构(二进档在别的目录里),因此可以很容易从同一个源代码目录树中建构出多个二进档。CMake也支持静态与动态程序库的建构。
“CMake”这个名字是“Cross platform Make”的缩写。虽然名字中含有“make”,但是CMake和Unix上常见的make系统是分开的,而且更为高阶。它可与原生建置环境结合使用,例如:make、ninja、苹果公司的Xcode与微软的Microsoft Visual Studio。
简单来说,cmake管理软件源代码不同文件之间如何编译、链接并合成,cmake不是编译器,它不编译代码,它可以和GCC或LLVM共同工作,在一些大型项目中,使用cmake管理可以加快编译速度,它只会编译哪些发生修改过的文件,而不像gcc等,完整的编译整个项目。
主要特点
- 跨平台:CMake支持多种操作系统和编译器,包括Windows、Linux、macOS、Unix,以及Visual Studio、GCC、Clang等编译器。
- 生成本机构建文件:CMake能够生成特定平台的构建文件,如Makefile、Visual Studio项目、Xcode项目等。
- 模块化和扩展性:CMake支持模块化设计,可以通过CMake脚本和自定义模块进行扩展。
- 自动化依赖管理:自动处理项目依赖关系,简化项目配置和编译过程。
- 支持外部项目:能够轻松集成和管理第三方库和项目。
cmake和GCC的区别
- CMake 编译过程:
- CMake 生成的构建系统文件会记录项目中每个源文件的依赖关系。当你运行生成的构建系统(比如使用
make
命令)时,构建系统会检查哪些源文件发生了修改。 - 构建系统会只重新编译发生了修改的源文件,然后重新链接这些文件,以更新最终的可执行文件。这样可以节省重新编译整个项目的时间,特别是在大型项目中。
- CMake 生成的构建系统文件会记录项目中每个源文件的依赖关系。当你运行生成的构建系统(比如使用
- 直接使用 GCC 编译:
- 如果直接使用 GCC 编译整个项目,GCC 将会编译所有的源文件,而不管它们是否已经存在目标文件(即是否已经被编译过)。
- 这种方式可能会导致整体的编译时间较长,尤其是在只有部分文件发生了变化的情况下。