注:本文为 "GCC 编译" 相关合辑。
图片清晰度受引文原图所限。
略作重排,未整理去重。
如有内容异常,请看原文。
GCC 的使用简介与命令行参数说明
delphiwcdj 原创于 2011-06-19 20:29:00 发布
本文阐述 GCC 编译器的基础用法与拓展功能,涵盖编译配置项、告警输出、库文件调用、调试配置、交叉编译等内容,适用于学习 GCC 编译流程、规范代码编写的开发人员。
参考资料:《GNU gcc嵌入式系统开发》,作者:董文军
1. GCC 的基本用法
调用 GCC 编译器时,需要指定对应参数与待处理文件名称。不同类型编译参数的先后顺序不会改变执行结果,同类参数的顺序会影响执行逻辑 。若使用多个 -L 参数指定库文件检索目录,GCC 会依照参数书写顺序依次检索对应目录。
GCC 多数参数由多字符构成,不支持单字符参数合并写法 ,该类参数在 Linux 系统中称作短参数。例如 -dr 与分开书写的 -d -r 具备不同语义。GCC 内置编译参数数量超过 100 个,下文仅介绍日常使用频次较高的参数。
GCC 标准调用格式:gcc [options] [filenames]
options 代表编译参数,filenames 代表待处理文件名称。常用参数说明如下:
1.1 -c
仅执行编译操作,不执行链接流程。编译器读取 .c 等源码文件,生成后缀为 .o 的目标文件。该参数多用于编译不含程序入口的子程序文件。
1.2 -o output_filename
指定输出文件名称为 output_filename,输出文件名称不可与源文件名称一致。未配置该参数时,GCC 默认生成可执行文件 a.out。
1.3 -g
生成 GNU 调试工具 gdb 所需的符号信息。对源码进行调试操作时,必须添加该参数。
1.4 -O
开启编译与链接阶段的代码优化。经过优化处理的可执行文件运行效率会提升,但编译、链接耗时会相应增加。同时优化操作会对调试工作造成干扰,可能出现运行表现与源码逻辑不一致的情况。该参数一般用于软件正式版本的编译打包。
1.5 -O2
执行强度高于 -O 的编译与链接优化,整体编译、链接流程耗时更长。
1.6 -Idirname
将 dirname 指向的目录加入头文件检索路径,该参数作用于预处理阶段。
C 语言头文件引入分为两种形式:
c
#include <stdio.h>
#include "stdio.h"
- 尖括号
<>形式:预处理程序cpp优先在系统默认头文件目录(如/usr/include)中检索文件; - 双引号
""形式:预处理程序cpp首先在当前工作目录检索文件,检索失败后再检索-I指定的目录。
若项目头文件分散在多个目录中,需要多次使用 -I 参数依次配置检索路径。
1.7 -Ldirname
将 dirname 指向的目录加入库文件检索路径,该参数作用于链接阶段。默认状态下,链接程序 ld 在系统默认目录(如 /usr/lib)中检索库文件。配置该参数后,链接程序会优先检索 -L 指定目录,再检索系统默认目录。库文件存放于多个目录时,需多次使用该参数配置路径。
1.8 -lname
链接名称为 libname.a 的函数库,库文件取自系统默认目录或 -L 参数指定的目录。示例:-lm 表示链接数学函数库 libm.a。
1.9 基础使用示例
现有 C 语言源码文件 test.c,代码内容如下:
c
#include <stdio.h>
int main(void)
{
printf("Hello world\n");
return 0;
}
生成可执行文件的基础指令:
shell
gcc test.c -o test
完整编译流程分为三步:
- 调用预处理程序
cpp,完成宏展开、头文件内容嵌入等预处理操作; - 调用编译程序
ccl与汇编程序as,将预处理后的源码转换为目标代码; - 调用链接程序
ld,将目标代码整合为可执行文件。
默认配置下,预处理、编译、链接流程会一次性执行。
1.10 分步执行编译流程
GCC 支持在编译的四个阶段中断执行,对应参数如下:
-E:执行预处理后终止流程,生成后缀为.i的预处理文件;-c:执行编译后终止流程,生成后缀为.o的目标文件;-S:执行汇编后终止流程,生成后缀为.s的汇编文件。
分步执行指令示例:
shell
# 预处理
gcc -E test.c -o test.i
# 编译生成目标文件
gcc -c test.c -o test.o
# 汇编生成汇编文件
gcc -S test.c -o test.s
# 链接生成可执行文件
gcc test.o -o test
1.11 多文件与库链接示例
项目包含 testmain.c、testsub.c 两个源码文件,程序调用系统数学库,编译指令如下:
shell
gcc testmain.c testsub.c -lm -o test
其中 -lm 用于链接系统数学库 libm.a。
1.12 工程编译说明
源码数量较多的工程,单次使用一条 GCC 指令完成全量编译会造成资源损耗。若仅修改单个文件,该方式会重复编译所有未变更文件。针对该场景,可搭配 make 工具完成增量编译。
2. 告警提示配置项
GCC 集成完备的错误检测与告警输出能力,可辅助开发人员规范代码编写。
2.1 -pedantic
编译不符合 ANSI/ISO C 语言标准的源码时,输出对应告警信息。
c
#include <stdio.h>
void main(void)
{
long long int var = 1;
printf("It is not standard C code!/n");
}

以违规代码为例,该参数可检测出以下问题:
main函数返回值声明为void,标准规范要求声明为int;- 使用
long long定义 64 位整数,属于 GNU 语法扩展,不符合 ANSI/ISO C 标准; main函数执行结束前未编写return语句。
2.2 -Wall
GCC 多数告警类参数以 -W 为前缀,-Wall 可启用绝大多数告警检测规则,输出全面的告警信息。

编译输出的告警不属于程序错误,但会提升故障出现概率。建议编译源码时固定添加 -Wall 参数,便于排查隐性代码问题。
2.3 -Werror
将所有告警信息判定为错误,触发告警时编译流程立即终止。该参数适用于自动化编译场景,强制对存在问题的代码进行修正。

2.4 -Wcast-align
检测指针地址对齐异常。若无需地址对齐的指针指向要求地址对齐的变量,编译器会输出告警。例如 char * 类型指针指向 int * 类型地址,int 类型数据通常要求地址可被 2 或 4 整除。
2.5 其他常用参数
-v:输出 GCC 完整执行流程;--target-help:展示当前 GCC 支持的 CPU 架构;-Q:输出编译统计信息与所有函数名称。
3. 库文件操作配置项
Linux 平台下的软件开发,通常需要调用第三方库文件。从代码开发角度,库文件由头文件(.h)与库文件(.so / .a)组成。系统默认头文件存放于 /usr/include/,库文件存放于 /usr/lib/,文件路径自定义时,需要通过编译参数配置检索规则。
3.1 -I
向头文件检索路径中新增自定义目录。
3.2 -L
向库文件检索路径中新增自定义目录,适用于库文件未存放在系统默认路径的场景。
3.3 -l
Linux 平台库文件命名遵循统一规则,文件名以 lib 作为前缀。使用 -l 参数时可省略该前缀,例如 -lfoo 会自动链接 libfoo.so 文件。
3.4 -static
Linux 库文件分为静态链接库(后缀 .a)与动态链接库(后缀 .so)。二者区别在于代码加载时机:静态库代码在编译阶段载入程序,动态库代码在程序运行阶段载入程序。
GCC 默认优先使用动态链接库,动态库缺失时才会检索静态库。添加 -static 参数可强制使用静态链接库。
3.5 -shared
生成共享目标文件,该文件可与其他目标文件链接整合为可执行文件。
4. 调试配置项
gdb(GNU Debugger)与 GCC 配合使用,可在 Linux 平台搭建完整的程序调试环境。
4.1 -g 与 -ggdb
默认编译模式下,GCC 不会向二进制文件写入调试符号信息,以此控制文件体积。需要调试时,可使用 -g 或 -ggdb 参数生成调试符号。
-g 支持分级配置调试信息粒度,格式为 -g[数字],共分为三个等级:
-g1:仅保留函数调用回溯、堆栈转储相关信息,不包含局部变量、行号信息;-g2:默认等级,包含符号表、代码行号、局部变量与外部变量信息;-g3:在-g2基础上,额外保留源码宏定义信息。
补充说明:
- 函数调用回溯:追踪程序运行过程中的函数调用链路;
- 堆栈转储:以十六进制格式保存程序运行现场。
调试参数会增大二进制文件体积,同时增加程序运行开销,仅建议在开发、测试阶段使用。
4.2 -p 与 -pg
向二进制文件植入性能剖析数据,用于定位程序性能瓶颈。
4.3 -save-temps
保留编译流程产生的中间文件。示例指令:
shell
gcc test.c -o test -save-temps
执行后除可执行文件 test 外,还会保留预处理文件 test.i、汇编文件 test.s 等中间文件。
5. 交叉编译配置项
常规编译场景中,GCC 生成的目标代码适配当前运行主机的硬件架构。GCC 支持交叉编译,可生成适配其他 CPU 架构的目标代码。
嵌入式系统开发常以 X86 架构 PC 作为宿主机,借助 GCC 交叉编译功能完成嵌入式设备的程序开发。本文不展开详述具体参数配置。
GCC 的基本使用
Balaaam 原创于 2022-03-26 17:18:23 发布
1. GCC 概述
- GCC(GNU Compiler Collection)由 Richard Stallman 开发,是 GNU 项目的核心工具之一;
- 该工具最初为 C 语言编译器(GNU C Compiler),现阶段支持 C、C++、Java、Ada、COBOL 等多种编程语言;
- GCC 具备跨平台特性,支持主流硬件架构,同时兼容 MMIX 等小众架构;
- 软件采用模块化设计,可扩展新增编程语言与 CPU 架构支持;
- GCC 属于自由软件。
2. GCC 编译流程
完整编译分为四个阶段:预处理、编译、汇编、链接。

C 语言源码为人类可读格式,运行前需要转换为机器指令,并按照可执行文件格式打包存储至磁盘。
3. GCC 常用参数与示例

编译指令示例:
shell
# 预处理
gcc -E hello.c -o hello.i
# 编译生成汇编文件
gcc -S hello.i -o hello.s
# 汇编生成目标文件
gcc -c hello.s -o hello.o
# 链接生成可执行文件
gcc hello.o -o hello
# 一次性完成编译与链接
gcc hello.c -o hello
# 编译生成目标文件
gcc -c hello.c
gcc -c hello.c -o hello.o
4. 多文件编译
项目文件:hello_fn.h、hello_fn.c、main.c
shell
# 一次性编译链接
gcc hello_fn.c main.c -o newhello
# 分步独立编译
gcc -Wall -c main.c -o main.o
gcc -Wall -c hello_fn.c -o hello_fn.o
gcc -Wall main.o hello_fn.o -o newhello
5. 头文件与库文件作用
- 头文件(
.h):定义常量、声明系统函数与库函数调用接口; - 库文件:预编译完成的函数集合,由一组关联函数组成,用于实现通用功能。例如 ncurses 库用于界面绘制,dbm 库用于数据库访问。
6. 系统默认检索路径
头文件路径
/usr/include及其子目录/usr/local/include及其子目录
库文件路径
/usr/lib/usr/local/lib
7. 外部库调用示例
源码文件 calc.c:
c
#include <math.h>
#include <stdio.h>
int main()
{
double x = pow(2.0, 3.0);
printf("The cubed if %f\n", x);
return 0;
}
编译指令:
shell
gcc -Wall calc.c -o calc -lm
-lm 用于链接 libm.so 或 libm.a 数学库。
8. 静态库与共享库
- 静态库(后缀
.a):编译链接阶段,库代码完整嵌入可执行文件。程序运行时不再依赖原静态库文件; - 共享库(后缀
.so):仅在可执行文件中记录函数入口地址,库代码在程序运行时动态加载。多个程序可共用同一份共享库文件; - 共享库优势:减小可执行文件体积,借助操作系统虚拟内存机制,实现内存资源复用。
9. 静态库生成与使用
项目文件:hello_fn.h、hello_fn.c、main.c
shell
# 编译生成目标文件
gcc -Wall hello_fn.c -o hello_fn.o
# 打包为静态库,ar 为 GNU 归档工具
ar rcs libhello.a hello_fn.o
# 链接静态库生成可执行文件
gcc -Wall main.c libhello.a -o main
# 通过 -L、-l 参数调用静态库
gcc -Wall -L . main.c -o main -lhello
10. 库文件检索优先级
-I、-L参数指定的目录(从左至右检索);- 环境变量
C_INCLUDE_PATH、LIBRARY_PATH指定的目录; - 系统默认目录。
11. 共享库生成与使用
编译参数说明
-shared:指定生成共享库格式;-fPIC:生成位置无关代码,适配共享库运行特性;- 共享库命名规则:
libXXX.so。
示例指令
shell
# 生成共享库
gcc -shared -fPIC hello.o -o libhello.so
# 链接共享库
gcc main.o -o main -L . -lhello
12. 共享库运行配置
程序运行时加载共享库,可选择以下三种配置方式:
- 将
.so文件复制至系统共享库目录/usr/lib; - 配置环境变量
LD_LIBRARY_PATH; - 修改配置文件
ld.so.conf,执行ldconfig更新缓存。
GCC 简介和命令行参数说明
KuoGavin 于 2021-05-12 14:01:15 发布
本文介绍 GCC 编译器基础用法、告警配置、库文件操作、调试配置、交叉编译,并区分 GCC 与 G++ 的使用差异。

链接阶段会完成数据段合并(合并只读数据以节省内存)与地址回填,对应符号解析、地址重定位两大流程。

内存布局说明:栈区域向低地址扩展,堆区域向高地址扩展,共享库占用中间地址空间。
1. GCC 基本用法
调用规则与前文一致,基础调用格式:
gcc options filenames \text{gcc options filenames} gcc options filenames
| 参数 | 说明 |
|---|---|
-c |
仅编译不链接,由 .c 源码生成 .o 目标文件,多用于子程序编译 |
-o output_filename |
自定义输出文件名称,未配置时默认生成 a.out |
-g |
生成 gdb 调试所需符号信息 |
-O |
开启编译与链接优化,提升程序运行效率,增加编译耗时,干扰调试工作 |
-O2 |
高阶代码优化,编译、链接耗时进一步增加 |
-Idirname |
新增头文件检索目录,区分两类头文件引入规则 |
-Ldirname |
新增库文件检索目录,链接阶段优先检索该目录 |
-lname |
链接库文件,省略库文件前缀 lib,示例:-lm 对应 libm.a / libm.so |
编译示例
源码文件 test.c:
c
#include <stdio.h>
int main(void)
{
printf("Hello world\n");
return 0;
}
基础编译指令:
shell
gcc test.c -o test
分步编译指令:
shell
# 预处理
gcc -E test.c -o test.i
# 汇编
gcc -S test.c -o test.s
# 编译生成目标文件
gcc -c test.c -o test.o
# 链接
gcc test.o -o test
多文件+库链接示例:
shell
gcc testmain.c testsub.c -lm -o test
大型工程建议搭配 make 工具实现增量编译。
2. 告警提示配置项
| 参数 | 说明 |
|---|---|
-v |
输出 GCC 完整执行流程 |
--target-help |
展示支持的 CPU 架构 |
-Q |
输出编译统计信息与函数名称 |
-pedantic |
检测不符合 ANSI/ISO C 标准的代码并输出告警 |
-Wall |
启用全量告警检测规则 |
-Werror |
告警升级为错误,触发告警则终止编译 |
-Wcast-align |
检测指针地址对齐异常 |
测试代码:
c
#include <stdio.h>
void main(void)
{
long long int var = 1;
printf("It is not standard C code!\n");
}
该代码存在多处语法规范问题,对应不同参数的运行效果参考下图:

-pedantic 参数运行效果

-Wall 参数运行效果

-Werror 参数运行效果
告警信息可辅助排查隐性故障,推荐常态化使用 -Wall 参数。
3. 库文件操作配置项
| 参数 | 说明 |
|---|---|
-I |
新增头文件检索目录 |
-L |
新增库文件检索目录 |
-l |
链接指定库文件,省略前缀 lib |
-static |
强制使用静态链接库 |
-shared |
生成共享目标文件 |
4. 调试配置项
| 参数 | 说明 |
|---|---|
-g / -ggdb |
生成调试符号,支持三级调试信息粒度划分 |
-p / -pg |
植入性能剖析数据,用于性能调优 |
-save-temps |
保留编译中间文件 |
调试参数会增大文件体积与运行开销,仅用于开发调试阶段。
5. 交叉编译配置项
GCC 支持生成跨架构目标代码,嵌入式开发场景常使用该功能,具体参数不作展开。
6. GCC 与 G++ 对比
6.1 统一编译流程
- 预处理,生成
.i文件; - 编译转换为汇编代码,生成
.s文件; - 汇编生成
.o目标文件; - 链接生成可执行文件。
6.2 支持的文件后缀
- 源码类:
.c、.C(C 语言);.cxx、.cc(C++ 语言);.m(Objective-C);.i(预处理 C 文件);.ii(预处理 C++ 文件);.s、.S(汇编文件); - 头文件:
.h; - 目标/库文件:
.o(目标文件);.a(库文件)。
6.3 常见认知误区纠正
| 误区 | 说明 |
|---|---|
| GCC 仅编译 C 代码,G++ 仅编译 C++ 代码 | 二者均可编译 C/C++ 代码。 后缀为 .c 的文件,GCC 按 C 语法解析,G++ 按 C++ 语法解析; 后缀为 .cpp 的文件,二者均按 C++ 语法解析。 编译阶段 G++ 会调用 GCC,C++ 项目通常使用 G++ 完成链接操作。 |
GCC 不会定义 __cplusplus 宏,G++ 一定会定义 |
该宏用于标识代码解析语法。 .c 文件使用 GCC 编译时,宏不生效;其余场景宏生效。 |
| 编译使用 GCC,链接必须使用 G++ | 编译可任选 GCC / G++; 链接可使用 G++,或使用 gcc -lstdc++。 C++ 标准库不会由 GCC 自动链接,因此 C++ 项目多选用 G++ 完成链接。 |
链接器、链接过程及相关概念解析
KuoGavin 于 2021-05-15 22:54:45 发布
链接是将代码、数据片段整合为单一文件的过程,生成的文件可加载至内存并运行。该流程由链接器执行,按照执行时机分为三类:
- 编译时链接:源代码转换为机器码阶段,适用于静态库、动态库、可重定位目标文件;
- 加载时链接:程序载入内存运行阶段,适用于静态库、动态库、可重定位目标文件;
- 运行时链接:程序运行过程中由应用主动触发,仅适用于动态库。
1. 编译器驱动程序
编译器驱动程序会按需调用预处理器、编译器、汇编器、链接器。
示例:存在 main.c、sum.c 两个文件,main.c 调用 sum.c 内函数,编译指令:
shell
gcc -Og -o prog main.c sum.c
源文件至可执行文件的编译流程

静态链接流程
生成可执行文件 prog 后,执行指令 ./prog。Shell 识别该文件为可执行文件,调用操作系统加载器完成程序运行。
2. 目标文件
目标文件分为三类:
- 可重定位目标文件 :包含二进制代码与数据,可与其他同类文件合并,Linux 后缀
.o; - 可执行目标文件:包含二进制代码与数据,可直接载入内存运行,无固定后缀;
- 共享目标文件 :特殊可重定位文件,支持加载时、运行时动态链接,Linux 后缀
.so,Windows 后缀.dll。
文件转换流程:
文本源文件 ⟶ ccl & as 可重定位文件 ⟶ ld 可执行目标文件 \text{文本源文件} \stackrel{\text{ccl \& as}}{\longrightarrow} \text{可重定位文件} \stackrel{\text{ld}}{\longrightarrow} \text{可执行目标文件} 文本源文件⟶ccl & as可重定位文件⟶ld可执行目标文件
目标模块为二进制字节序列,目标文件是存储在磁盘中的目标模块,单个目标文件可包含多个目标模块。
主流系统文件格式:Linux 与 Unix(x86-64)使用 ELF 格式,Windows 使用 PE 格式,MacOS 使用 Mach-O 格式。下文基于 ELF 格式展开说明。
2.1 可重定位目标文件(.o)
2.2 可执行目标文件
ELF 可执行文件设计为适配内存加载,程序头部表记录文件片段与内存段的映射关系。
加载器将文件内容从磁盘复制至内存,并跳转到程序入口地址执行,该过程称为加载。Linux 程序可通过 execve 函数调用加载器。
程序运行内存映像
2.3 共享目标文件(.so / .dll)
静态库存在维护成本高、内存占用大的问题,共享库可解决上述问题。共享库又称共享目标文件,支持多进程共用同一份库代码。
共享库共享特性:
- 文件系统中,单个库文件可被多个可执行文件引用;
- 内存中,库的代码段仅保留一份副本,供所有调用进程共用。
共享库编译与调用
生成共享库指令:
shell
gcc -shared -fpic -o libvector.so addvec.c multvec.c
参数说明:
-fpic:生成位置无关代码,是共享库的必备配置;-shared:指定输出为共享库格式。
链接共享库生成可执行文件:
shell
gcc -o prog21 main2.c ./libvector.so

可执行文件运行流程:
- 加载器载入程序文件,识别
.interp节,启动动态链接器; - 动态链接器完成共享库重定位、符号引用解析;
- 移交程序控制权,程序正常运行。
运行时动态加载接口
Linux 提供专用接口支持程序运行时加载共享库:
dlopen:加载并链接指定共享库;dlsym:根据符号名称获取函数地址;dlerror:获取接口调用的错误信息。
Java JNI 技术基于该套接口实现本地 C/C++ 函数调用。
3. 链接器的核心任务
3.1 符号解析
符号分为函数、全局变量、静态变量三类。符号解析的作用是将每一处符号引用,匹配到唯一的符号定义。
符号与符号表
每个可重定位目标文件包含符号表 .symtab,记录文件内定义与引用的符号,局部非静态变量不记录在符号表中。目标模块内的符号分为三类:
- 全局定义符号:本模块定义,其他模块可引用,对应非静态 C 函数、全局变量;
- 外部符号:本模块引用,其他模块定义;
- 局部符号:仅本模块可见,对应带
static修饰的函数、全局变量。
符号表包含节索引、符号类型等字段,存在三类伪节标识:
ABS:不可重定位符号;UNDEF:未定义符号;COMMON:未初始化全局变量。
多重全局符号解析规则
按照定义形式区分强符号、弱符号:函数、已初始化全局变量为强符号;未初始化全局变量为弱符号。解析规则:
- 不允许存在多个同名强符号,出现则编译报错;
- 同名符号包含一个强符号与多个弱符号时,选用强符号;
- 存在多个同名弱符号时,随机选择其中一个。
上述规则易引发隐性逻辑错误,编写代码时需规避全局符号重定义。
静态库符号解析
静态库(后缀 .a)通过 ar 工具打包生成,链接器仅复制程序实际引用的目标模块。
静态库创建指令:
shell
ar rcs libvector.a addvec.o multvec.o
链接指令:
shell
gcc -static -o prog2c main2.o ./libvector.a
gcc -static -o prog2c main2.o -L . -lvector
链接器维护三个集合:待合并目标文件集合 E、未解析符号集合 U、已定义符号集合 D。按照命令行顺序扫描文件:
- 扫描目标文件:将文件加入集合
E,同步更新U、D; - 扫描静态库:匹配
U中的未解析符号,将匹配成功的模块加入E,更新U、D; - 扫描结束后,若
U非空则链接报错。
命令行中目标文件与库文件的顺序需要匹配依赖关系。
3.2 重定位
编译器、汇编器默认从地址 0 开始生成代码与数据。符号解析完成后,链接器明确各代码段、数据段的大小,重定位环节会为所有符号分配运行时内存地址,并修改符号引用地址。
重定位条目
汇编器生成目标文件时,针对外部符号、全局变量生成重定位条目,指导链接器修改地址引用。代码段重定位条目存放于 .rel.text,数据段重定位条目存放于 .rel.data。
ELF 格式定义多种重定位类型,两类基础类型:
R_X86_64_PC32:32 位 PC 相对地址重定位;R_X86_64_32:32 位绝对地址重定位。
重定位执行步骤
- 节与符号重定位:合并同类数据段、代码段,为所有节、符号分配运行时内存地址;
- 引用重定位:遍历所有重定位条目,按照寻址类型修改符号引用地址,指向最终内存位置。
4. 总结
- 链接分为编译时、加载时、运行时三种形式,目标文件包含可重定位、可执行、共享三类;
- 符号解析、重定位是链接器的两项核心工作;
- 静态库会完整复制引用模块,库文件与目标文件的顺序会影响链接结果;
- 动态库基于位置无关代码实现多进程共享,支持加载时链接与运行时动态加载;
- 加载器负责将可执行文件载入内存,动态链接器完成共享库的地址解析与绑定。
reference
- gcc 的使用简介与命令行参数说明_gcc -l -share -fpic -g-CSDN 博客
https://blog.csdn.net/delphiwcdj/article/details/6555073 - GCC 编译器详解-CSDN 博客
https://blog.csdn.net/weixin_50697073/article/details/123759516 - gcc 简介和命令行参数说明_gcc -t-CSDN 博客
https://blog.csdn.net/yueguangmuyu/article/details/116703618 - 链接器、链接过程及相关概念解析-CSDN 博客
https://blog.csdn.net/yueguangmuyu/article/details/116710102