GCC工具链简介

1. 介绍

1.1. 简介

GNU Compiler Collection(GCC)是一套开源编译器,它可以对C、C++、Objective-C、Fortran、Java和Ada等多种程序设计语言进行编译。GCC项目始于1987年,目标是为GNU操作系统开发免费软件和开源编译器。

从最初仅支持C语言,到后来支持更多平台和语言,GCC经历了长时间的发展。它为GNU/Linux及其他开源操作系统的流行做出了重要贡献。到今天,GCC已经成为最广泛使用的开源编译系统之一。

1.2. 主要内容

工具链是一套完整的编译代码的工具,gcc工具链主要包括下面内容:

  1. 编译器、链接器、预处理器、调试器等工具。

  2. 头文件,如C/C++的的标准库头文件。

  3. 标准库,C/C++的标准运行库。

  4. 文档,示例等。

1.3. 发展历程

GCC 1.0版本(1989年)支持C语言编译。

GCC 2.0版本(1992年)开始支持更多平台,支持C++语言编译。

GCC 2.5版本(1994年)开始支持PowerPC。

GCC 2.7版本(1995年)开始支持Sparc。

GCC 2.95版本(1997年)开始支持IA-64。

GCC 3.0版本(2000年)开始支持x86-64。

GCC 4.0版本(2004年)引入模拟汇编和图形后端,开始支持C99。

GCC 4.2版本(2007年)开始支持ARM。

GCC 4.6版本(2011年)开始支持OpenMP并行编译。

GCC 4.9版本(2014年)开始支持大部分C++11标准特性。

GCC 6.1版本(2016年)开始支持C++14标准,支持C11标准。

GCC 8.0版本(2018年)开始支持RISC-V。

GCC 8.1版本(2018年)开始支持C++17标准特性。

GCC 10版本(2020年)开始支持C++20标准特性。

2. 分类

不同的CPU对应不同的gcc,然后不同的运行系统,也对应着不同的gcc。CPU框架和运行系统交叉,导致有非常多版本的gcc。编译运行于不同于开发电脑的CPU架构或运行系统的C/C++,都需要使用相应的gcc来编译,这种编译叫做交叉编译。因为gcc的版本非常多,所以gcc官方组织并不负责发布具体的预编译二进制版本,只是提供标准的源码,下载地址:http://ftp.gnu.org/gnu/gcc/gcc-13.2.0/

2.1. 目标系统

2.1.1. Windows

gcc生成的可执行文件默认是运行在Unix-like下的,所以构建运行于Mac、Linux构建gcc的预编译版本,比较容易。Windows的API接口与Unix-like不同,与通用的gcc差异较大。所以专门有一个基于gcc扩展的框架来实现此功能。

MinGW(Minimalist GNU for Windows的缩写)。它是一个可自由使用和自由发布的Windows特定头文件和使用GNU工具集导入库的集合,允许你在GNU/Linux和Windows平台生成本地的Windows程序而不需要第三方C运行时(C Runtime)库。MinGw只支持32位Widnows系统,MinGW-w64 支持32位和64位。所以现在说MinGW时,一般默认指的MinGW-w64。

  1. MinGW可以运行在Windows和Linux上,官方网站提供各平台的下载地址:MinGW官网

  2. Windows下的Cygwin和MSYS2都有自己特有预编译版本,可以直接通过命令下载。

pacman -Syu

pacman -S mingw-w64-x86_64-toolchain

  1. Linux下的包管理软件,也有提供专门的MinGW版本。

yum install mingw64-gcc

sudo apt install mingw-w64

2.1.2. Linux

要编译运行Linux下的程序,必须在Linux环境下编译。Windows下可以通过虚拟机或WSL来实现Linux环境。

  1. 编译安装,见官方介绍:https://gcc.gnu.org/install/

  2. 包安装

    1. Ubuntu 或 Debian:

sudo apt install gcc

// 或指定版本

sudo apt install gcc9

// ARM32交叉编译工具链

sudo apt install gcc-arm-linux-gnueabi

// ARM64交叉编译工具链,也支持ARM32

sudo apt install gcc-aarch64-linux-gnu

  1. CentOS 或 Fedora:

sudo yum install gcc

// 或指定版本

sudo apt install gcc-9

2.1.3. Android

Android中的gcc一般在NDK中,所以安装对应内核的NDK即可。如运行在x86_64平台上编译arm的NDK:

#下载NDK

wget https://dl.google.com/android/repository/android-ndk-r17b-linux-x86_64.zip

#解压 unzip后面跟着的是刚刚下载的文件

unzip android-ndk-r17b-linux-x86_64.zip

export ANDROID_64_ARM_GCC=/linux/android-ndk-r17b/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-gcc

2.1.4. Mac

Mac上一般是通过Homebrew来安装软件。

brew install gcc

// 安装指定版本

brew install gcc @11

// 安装支持arm64的gcc的交叉工具链

brew install crosstool-ng

2.1.5. 裸机系统

裸机系统主要是针对嵌入式的。目前的嵌入式系统主要为ARM和RISC-V两种内核。

2.1.5.1. ARM

arm-none-eabi,即 ARM architecture,no vendor,not target an operaTIng system,complies with the ARM EABI 是不支持操作系统的,自然无法使用那些跟操作系统关系密切的函数,比如 fork(2)。该工具链使用的是 newlib 这个专用于嵌入式系统的 C 库。

主要用于编译 ARM 架构的裸机系统(包括 ARM Linux 的 boot,kernel,不适用编译 Linux Kernel和App),一般适合 ARM7,Cortex-M 和 Cortex-R 内核架构的芯片开发使用,不支持与操作系统关系密切的函数。

arm-none-eabi-gcc由arm官方负责维护,下载地址:https://developer.arm.com/downloads/-/gnu-rm

2.1.5.2. RISC-V

Windows下安装,通过MSYS2命令进行:

pacman -S mingw-w64-x86_64-toolchain riscv64-unknown-elf-gcc

pacman -S mingw-w64-i686-toolchain riscv32-unknown-elf-gcc

Windows下代码编译,见:https://www.emdalo.com/posts/risc-v-gnu-compiler-toolchain-howto-compile-on-windows/

Linux下,通过命令安装:

sudo apt update

sudo apt install gcc-riscv32-linux-gnu

sudo apt install gcc-riscv64-linux-gnu

Linux下也可以gcc源代码或直接下载二进制:

https://github.com/riscv-collab/riscv-gnu-toolchain/

2.2. 目标架构

2.2.1. x86-64

主要应用于操作系统编译应用程序的。详细内容见上节。

2.2.2. ARM

2.2.2.1. 下载
  1. Linaro是一个非营利性开源软件工程组织,旨在为嵌入式设备领域提供合作和创新的基础。它由多个半导体公司共同发起和支持,包括ARM、IBM、Freescale、Samsung等。Linaro致力于提供针对ARM架构的Linux操作系统、工具链以及其他相关软件的开发和优化。针对ARM架构的Linux操作系统最新的gcc工具链由Linaro发布,下载地址:https://snapshots.linaro.org/gnu-toolchain/

  2. ARM公司发布的gcc版本有一些是在linaro上做了进一步优化。下载地址:https://developer.arm.com/downloads/-/arm-gnu-toolchain-downloads

2.2.2.2. 分类
  1. AArch32 bare-metal target (arm-none-eabi)

arm-none-eabi,即 ARM architecture,no vendor,not target an operaTIng system,complies with the ARM EABI 是不支持操作系统的,自然无法使用那些跟操作系统关系密切的函数,比如 fork(2)。该工具链使用的是 newlib 这个专用于嵌入式系统的 C 库。

主要用于编译 ARM 架构的裸机系统(包括 ARM Linux 的 boot,kernel,不适用编译 Linux Kernel和App),一般适合 ARM7,Cortex-M 和 Cortex-R 内核架构的芯片开发使用,不支持与操作系统关系密切的函数。

arm-none-eabi-gcc由arm官方负责维护,下载地址:https://developer.arm.com/downloads/-/gnu-rm

  1. AArch32 GNU/Linux target with hard float (arm-none-linux-gnueabihf)

(ARM architecture, no vendor, creates binaries that run on the Linux operating system, and uses the GNU EABI),主要用于基于ARM架构的Linux系统,可用于编译 ARM 架构的 u-boot、Linux内核、linux应用等。一般ARM9、ARM11、Cortex-A 内核,带有 Linux 操作系统的会用到。hf 表示硬浮点(Hard-Float)。

  1. AArch64 bare-metal target (aarch64-none-elf)

aarch64-none-elf是一个用于交叉编译AArch64(也称为ARM64)架构的工具链,专门用于在嵌入式裸机系统中开发和构建针对AArch64处理器的应用程序。一般为Cortex-A53、Cortex-A57、Cortex-A72、Cortex-R82等。

  1. AArch64 GNU/Linux target (aarch64-none-linux-gnu)

aarch64-none-linux-gnu是一个用于交叉编译适用于AArch64架构的应用程序的工具链,专为在Linux操作系统上运行的AArch64设备而设计。一般为Cortex-A53、Cortex-A57、Cortex-A72等。

2.2.3. RISC-V

RISC-V主要用于嵌入式裸机和Linux,其主要安装见:https://github.com/riscv-collab/riscv-gnu-toolchain

3. gcc常用工具

3.1. 简介

  1. gcc:gcc是GCC的主要编译器,用于将源代码编译为可执行文件或库。它支持多种语言(如C、C++、Fortran等),并提供丰富的编译选项来控制编译过程。

  2. g++:g++是GCC的C++编译器,用于将C++源代码编译为可执行文件或库。它与gcc共享许多相同的编译选项,同时还支持针对C++的特定选项。

  3. gdb:gdb是GCC附带的调试器,用于调试程序。它允许您在程序运行时设置断点、单步执行代码、查看变量值等。gdb支持多种编程语言,并提供强大的调试功能。

  4. objdump:objdump用于反汇编目标文件或可执行文件,可以显示二进制文件的汇编代码。它还可以显示符号表信息、重定位表等相关信息。

  5. nm:nm用于列出目标文件或可执行文件中的符号表。它可以显示函数、变量以及其他符号的名称和地址。

  6. ar:ar用于创建、修改和提取静态库文件。它允许将多个目标文件打包成一个库文件,以便在编译时链接使用。

  7. size:size用于查看目标文件或可执行文件的大小信息。它可以显示代码段、数据段和符号表等各部分的大小统计。

  8. readelf:readelf用于显示ELF(Executable and Linkable Format)格式的二进制文件的详细信息。它可以显示段表、符号表、动态链接信息等。

3.2. gdb-mutiarch

不同的CPU架构,对应不同的gdb,使用起来麻烦。针对不同架构CPU,gdb的原理上基本类似,并且用法都是一样的,是否可以有一个通用的gdb,可以应用于所有CPU架构呢?gdb-multiarch应运而生,解决了此问题。

Windows安装,通过MSYS2安装:

pacman -S mingw-w64-x86_64-gdb

Linux安装,通过apt安装:

sudo apt install gdb-multiarch

4. 其他

4.1. 扩展

很多基于Arm或RISC-V的内核IP商,他们会在标准的指令集上进行一些扩展,所以同样需要对编译器gcc进行扩展,所以官方会提供特有GCC工具链。

如RISC-V IP商NUCLEI: https://www.nucleisys.com/download.php

除了指令上的扩展会修改编译器之外,另外也有一些厂商会优化头文件等,也会有专门的gcc,如Android。

4.2. 兼容

  1. 头文件兼容性:GCC的头文件包含了编译器和标准库的声明和定义。通常情况下,较新版本的GCC会向后兼容旧版本的头文件,这意味着您可以使用较新版本的GCC编译旧版本的代码,并期望其能够正常工作。但是,有时候较新版本的GCC可能会引入一些改变,导致旧版本的头文件与新版本的GCC不兼容。在这种情况下,您可能需要更新您的代码以适应新版本的头文件。

  2. 二进制兼容性:GCC生成的二进制文件(可执行文件、共享库等)在某种程度上具有跨版本的兼容性。较新版本的GCC通常可以正确地编译和链接由较旧版本的GCC编译生成的二进制文件。这意味着您可以使用新版本的GCC来更新现有的二进制文件,而无需重新编译源代码。然而,需要注意的是,如果新版本的GCC引入了一些二进制接口上的更改,那么旧版本的二进制文件可能无法与新版本的GCC完全兼容。在这种情况下,您可能需要重新编译或重新链接您的代码以确保兼容性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值