Ubuntu 22.04 GCC 安装与命令参数详解
Ubuntu 22.04 下 GCC 11.4.0 的在线/离线安装步骤与全部常用命令参数实测详解。
Ubuntu 22.04 GCC 安装与命令参数详解
目标:在 Ubuntu 22.04 x86_64 环境下,完成 GCC 编译器从在线安装、离线安装到全部常用命令参数的真实回显验证。本文所有命令与输出均已在 Ubuntu 22.04 x86_64 环境实测通过。
一、环境信息
| 项目 | 值 |
|---|---|
| 操作系统 | Ubuntu 22.04 LTS(jammy) |
| 内核版本 | 5.15.x(x86_64) |
| 系统架构 | x86_64 |
| 包管理器 | apt(底层 dpkg) |
| 软件源 | archive.ubuntu.com 官方源(jammy / jammy-updates / jammy-backports) |
| GCC 版本 | 11.4.0(Ubuntu 11.4.0-1ubuntu1~22.04.3) |
| 默认 C 标准 | GNU C17 |
| 当前用户 | root(文档中普通用户场景以 sudo 前缀演示) |
💡 说明:Ubuntu 的
gcc是一个“元包”,apt 中显示的版本为4:11.2.0-1ubuntu1,其真正负责编译的底层编译器是gcc-11包(11.4.0)。两者关系详见“七、常见问题(FAQ)”。
二、工具概述
GCC(GNU Compiler Collection,GNU 编译器套件)是 GNU 项目发布的开源编译器集合,支持 C、C++、Objective-C、Fortran、Ada、Go 等多种语言。本文聚焦其中的 C 编译器 gcc。
GCC 的编译过程本质上是一条“驱动器”流水线:它按照输入文件的类型自动调用内部各子工具完成工作:
| 阶段 | 子工具 | 产物 | 作用 |
|---|---|---|---|
| 预处理 | cpp(cc1 内嵌) | .i | 展开宏、处理 #include、条件编译 |
| 编译 | cc1 | .s | 将 C 源码翻译为汇编代码 |
| 汇编 | as | .o | 将汇编代码翻译为机器码(可重定位目标文件) |
| 链接 | collect2 / ld | 可执行文件 | 合并目标文件与库,解析符号引用 |
GCC 在整个 Linux 开发生态中处于核心位置:内核、glibc、各类基础库与上层应用几乎都由它编译产出。它与 make(构建调度)、gdb(调试)、valgrind(内存检测)等工具配合,构成完整的 C/C++ 开发工具链。
💡 说明:Ubuntu 22.04 的
gcc默认开启 PIE(位置无关可执行文件)与栈保护(-fstack-protector-strong)等安全特性,编译出的可执行文件默认就是 PIE 格式,见后续file命令回显。
三、在线安装方案
3.1 检查软件源配置
Ubuntu 22.04 的 apt 软件源定义在 /etc/apt/sources.list 与 /etc/apt/sources.list.d/ 目录下。执行 apt update 刷新软件包索引:
sudo apt update
回显(节选):
Hit:4 http://archive.ubuntu.com/ubuntu jammy-backports InRelease
Reading package lists...
Building dependency tree...
Reading state information...
8 packages can be upgraded. Run 'apt list --upgradable' to see them.
💡 说明:
apt update只刷新软件包索引,不安装任何软件。若输出中出现Err或Failed to fetch,说明软件源不可达或配置有误,需先修复软件源。
3.2 安装 gcc
sudo apt install -y gcc
回显:
WARNING: apt does not have a stable CLI interface. Use with caution in scripts.
Reading package lists...
Building dependency tree...
Reading state information...
gcc is already the newest version (4:11.2.0-1ubuntu1).
gcc set to manually installed.
0 upgraded, 0 newly installed, 0 to remove and 8 not upgraded.
💡 说明:本次环境中 gcc 已是最新版本,故显示
already the newest version。若是在全新系统上首次安装,回显中会列出Need to get ...、Get:1 ...下载行,并提示Setting up gcc ...完成安装。
3.3 验证安装
gcc --version
回显:
gcc (Ubuntu 11.4.0-1ubuntu1~22.04.3) 11.4.0
Copyright (C) 2021 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
四、离线安装方案
离线安装的思路:在一台能联网的 Ubuntu 22.04 机器上用 apt 将软件包下载为 .deb 文件,拷贝到离线机器,再用 dpkg -i 安装。
4.1 下载软件包(不安装)
对尚未安装的软件包,直接执行:
sudo apt install --download-only --no-install-recommends -y gcc
⚠️ 注意:
--download-only表示只下载不安装;--no-install-recommends表示不拉取“推荐”级别的依赖,减小下载体积。
由于本次环境中 gcc 已安装,直接执行该命令不会重复下载,回显:
WARNING: apt does not have a stable CLI interface. Use with caution in scripts.
Reading package lists...
Building dependency tree...
Reading state information...
gcc is already the newest version (4:11.2.0-1ubuntu1).
0 upgraded, 0 newly installed, 0 to remove and 8 not upgraded.
💡 说明:
--download-only对已安装且缓存中已有.deb的软件包不会重复下载。若需要强制重新下载(例如补全缓存),可追加--reinstall参数。
4.2 强制重新下载核心包
为了让离线安装演示完整,这里使用 --reinstall 强制重新下载 gcc 及其核心组成包(gcc 元包、gcc-11 编译器、cpp-11 预处理器、libgcc-11-dev 开发头文件):
sudo apt install --reinstall --download-only --no-install-recommends -y gcc gcc-11 cpp-11 libgcc-11-dev
回显:
Reading package lists...
Building dependency tree...
Reading state information...
0 upgraded, 0 newly installed, 4 reinstalled, 0 to remove and 8 not upgraded.
Need to get 32.7 MB of archives.
After this operation, 0 B of additional disk space will be used.
Get:1 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 cpp-11 amd64 11.4.0-1ubuntu1~22.04.3 [10.0 MB]
Get:2 http://archive.ubuntu.com/ubuntu jammy/main amd64 gcc amd64 4:11.2.0-1ubuntu1 [5112 B]
Get:3 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 gcc-11 amd64 11.4.0-1ubuntu1~22.04.3 [20.1 MB]
Get:4 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 libgcc-11-dev amd64 11.4.0-1ubuntu1~22.04.3 [2517 kB]
Fetched 32.7 MB in 4s (8765 kB/s)
Download complete and in download only mode
下载的 .deb 默认存放在 /var/cache/apt/archives/ 目录:
ls -lh /var/cache/apt/archives/*.deb
回显:
-rw-r--r-- 1 root root 9.6M Feb 12 2026 /var/cache/apt/archives/cpp-11_11.4.0-1ubuntu1~22.04.3_amd64.deb
-rw-r--r-- 1 root root 20M Feb 12 2026 /var/cache/apt/archives/gcc-11_11.4.0-1ubuntu1~22.04.3_amd64.deb
-rw-r--r-- 1 root root 5.0K Aug 5 2021 /var/cache/apt/archives/gcc_4%3a11.2.0-1ubuntu1_amd64.deb
-rw-r--r-- 1 root root 2.5M Feb 12 2026 /var/cache/apt/archives/libgcc-11-dev_11.4.0-1ubuntu1~22.04.3_amd64.deb
4.3 拷贝到离线目录
sudo mkdir -p /opt/devchain-demo/gcc-ubuntu-test/offline
sudo cp /var/cache/apt/archives/*.deb /opt/devchain-demo/gcc-ubuntu-test/offline/
ls -lh /opt/devchain-demo/gcc-ubuntu-test/offline/
回显:
total 32M
-rw-r--r-- 1 root root 9.6M Oct 6 06:23 cpp-11_11.4.0-1ubuntu1~22.04.3_amd64.deb
-rw-r--r-- 1 root root 20M Oct 6 06:23 gcc-11_11.4.0-1ubuntu1~22.04.3_amd64.deb
-rw-r--r-- 1 root root 5.0K Oct 6 06:23 gcc_4%3a11.2.0-1ubuntu1_amd64.deb
-rw-r--r-- 1 root root 2.5M Oct 6 06:23 libgcc-11-dev_11.4.0-1ubuntu1~22.04.3_amd64.deb
4.4 查看 deb 包元信息
dpkg-deb -I 查看软件包的控制信息(包名、版本、依赖关系等):
dpkg-deb -I /opt/devchain-demo/gcc-ubuntu-test/offline/gcc-11_*.deb
回显:
new Debian package, version 2.0.
size 20143406 bytes: control archive=1666 bytes.
942 bytes, 16 lines control
2804 bytes, 36 lines md5sums
Package: gcc-11
Version: 11.4.0-1ubuntu1~22.04.3
Architecture: amd64
Maintainer: Ubuntu Core developers <ubuntu-devel-discuss@lists.ubuntu.com>
Installed-Size: 52747
Depends: cpp-11 (= 11.4.0-1ubuntu1~22.04.3), gcc-11-base (= 11.4.0-1ubuntu1~22.04.3), libcc1-0 (>= 11.4.0-1ubuntu1~22.04.3), binutils (>= 2.38), libgcc-11-dev (= 11.4.0-1ubuntu1~22.04.3), libc6 (>= 2.34), libgcc-s1 (>= 3.0), libgmp10 (>= 2:6.2.1+dfsg), libisl23 (>= 0.15), libmpc3 (>= 1.1.0), libmpfr6 (>= 3.1.3), libstdc++6 (>= 5), libzstd1 (>= 1.4.0), zlib1g (>= 1:1.1.4)
Recommends: libc6-dev (>= 2.13-0ubuntu6)
Suggests: gcc-11-multilib, gcc-11-doc (>= 11), gcc-11-locales (>= 11)
Replaces: cpp-11 (<< 7.1.1-8)
Provides: c-compiler
Section: devel
Priority: optional
Homepage: http://gcc.gnu.org/
Description: GNU C compiler
This is the GNU C compiler, a fairly portable optimizing compiler for C.
Original-Maintainer: Debian GCC Maintainers <debian-gcc@lists.debian.org>
💡 说明:
Depends行列出的就是安装本包所需的全部依赖,离线环境下需要把 gcc-11 及其所有依赖包一起拷贝过去(例如 cpp-11、gcc-11-base、libgcc-11-dev、binutils、libmpc3、libisl23 等),安装顺序为“依赖在前、被依赖在后”。
4.5 查看 deb 包内容列表
dpkg-deb -c 列出软件包将要释放到系统里的所有文件:
dpkg-deb -c /opt/devchain-demo/gcc-ubuntu-test/offline/gcc-11_*.deb | head -15
回显:
drwxr-xr-x root/root 0 2025-12-18 07:31 ./
drwxr-xr-x root/root 0 2025-12-18 07:31 ./usr/
drwxr-xr-x root/root 0 2025-12-18 07:31 ./usr/bin/
-rwxr-xr-x root/root 928584 2025-12-18 07:31 ./usr/bin/x86_64-linux-gnu-gcc-11
-rwxr-xr-x root/root 27176 2025-12-18 07:31 ./usr/bin/x86_64-linux-gnu-gcc-ar-11
-rwxr-xr-x root/root 27176 2025-12-18 07:31 ./usr/bin/x86_64-linux-gnu-gcc-nm-11
-rwxr-xr-x root/root 27176 2025-12-18 07:31 ./usr/bin/x86_64-linux-gnu-gcc-ranlib-11
-rwxr-xr-x root/root 409608 2025-12-18 07:31 ./usr/bin/x86_64-linux-gnu-gcov-11
-rwxr-xr-x root/root 257880 2025-12-18 07:31 ./usr/bin/x86_64-linux-gnu-gcov-dump-11
-rwxr-xr-x root/root 282552 2025-12-18 07:31 ./usr/bin/x86_64-linux-gnu-gcov-tool-11
-rwxr-xr-x root/root 24887264 2025-12-18 07:31 ./usr/bin/x86_64-linux-gnu-lto-dump-11
drwxr-xr-x root/root 0 2025-12-18 07:31 ./usr/lib/
drwxr-xr-x root/root 0 2025-12-18 07:31 ./usr/lib/gcc/
drwxr-xr-x root/root 0 2025-12-18 07:31 ./usr/lib/gcc/x86_64-linux-gnu/
drwxr-xr-x root/root 0 2025-12-18 07:31 ./usr/lib/gcc/x86_64-linux-gnu/11/
dpkg-deb: error: tar subprocess was killed by signal (Broken pipe)
💡 说明:回显末尾的
Broken pipe是head -15提前关闭管道、dpkg-deb仍在继续解包读取导致的正常现象,并非安装失败。可以看到 gcc-11 包主要向/usr/bin/释放x86_64-linux-gnu-gcc-11等编译驱动及配套工具。
4.6 在离线机器上安装
将整个 offline 目录拷贝到离线机器后,用 dpkg -i 安装(依赖按顺序先装):
sudo dpkg -i /opt/devchain-demo/gcc-ubuntu-test/offline/*.deb
⚠️ 注意:
dpkg -i不会自动解决依赖。若缺少依赖包,会提示dpkg: dependency problems。生产实践中更推荐在有网机器上把依赖一并下载(如apt-rdepends分析或直接--download-only整组下载),或使用apt install ./xxx.deb借助本机软件源自动补依赖。
安装完成后同样用 gcc --version 验证。
五、命令与参数详解
💡 说明:本章命令默认在测试目录
/opt/devchain-demo/gcc-ubuntu-test下执行。测试文件包括:
hello.c:主程序,调用add()并打印结果,引用了自定义头文件mymath.hinclude/mymath.h:自定义头文件,声明int add(int a, int b);lib/mymath.c:add()函数实现warn.c:含未使用变量,用于警告演示macro.c:含条件编译宏,用于-D/-U演示foo.c、main.c:共享库演示math_var.c、sqrt_demo.c:数学库链接演示
5.1 版本与平台信息类
5.1.1 --version:查看完整版本信息
gcc --version
回显:
gcc (Ubuntu 11.4.0-1ubuntu1~22.04.3) 11.4.0
Copyright (C) 2021 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5.1.2 -dumpversion:输出主版本号
gcc -dumpversion
回显:
11
5.1.3 -dumpfullversion:输出完整版本号
gcc -dumpfullversion
回显:
11.4.0
💡 说明:
-dumpversion只输出主版本号11,-dumpfullversion输出完整的三段式版本号11.4.0。脚本中判断编译器大版本时常用-dumpversion。
5.1.4 -dumpmachine:输出目标平台三元组
gcc -dumpmachine
回显:
x86_64-linux-gnu
💡 说明:
x86_64-linux-gnu即 Ubuntu 的 multiarch 三元组,它决定了默认的库与头文件搜索路径(如/usr/lib/x86_64-linux-gnu/)。
5.1.5 --help:查看帮助
gcc --help
回显(节选,头部):
Usage: gcc [options] file...
Options:
-pass-exit-codes Exit with highest error code from a phase.
--help Display this information.
--target-help Display target specific command line options.
--help={common|optimizers|params|target|warnings|[^]{joined|separate|undocumented}}[,...].
Display specific types of command line options.
(Use '-v --help' to display command line options of sub-processes).
--version Display compiler version information.
-dumpspecs Display all of the built in spec strings.
-dumpversion Display the version of the compiler.
-dumpmachine Display the compiler's target processor.
-print-search-dirs Display the directories in the compiler's search path.
-print-libgcc-file-name Display the name of the compiler's companion library.
-print-file-name=<lib> Display the full path to library <lib>.
-print-prog-name=<prog> Display the full path to compiler component <prog>.
-print-multiarch Display the target's normalized GNU triplet, used as
a component in the library path.
-print-multi-directory Display the root directory for versions of libgcc.
-print-multi-lib Display the mapping between command line options and
回显(节选,尾部):
-shared Create a shared library.
-x <language> Specify the language of the following input files.
Permissible languages include: c c++ assembler none
'none' means revert to the default behavior of
guessing the language based on the file's extension.
Options starting with -g, -f, -m, -O, -W, or --param are automatically
passed on to the various sub-processes invoked by gcc. In order to pass
other options on to these processes the -W<letter> options must be used.
For bug reporting instructions, please see:
<file:///usr/share/doc/gcc-11/README.Bugs>.
5.2 编译四阶段:-E、-S、-c、-o
GCC 把从源码到可执行文件的完整过程拆成预处理、编译、汇编、链接四个阶段,可以用参数在任意阶段停下。
5.2.1 -E:只做预处理
-E 让 gcc 只运行预处理器,展开宏、包含头文件,输出 .i 文件:
gcc -I./include -E hello.c -o hello.i
💡 说明:
-I./include告知编译器去include/目录搜索自定义头文件(hello.c 中#include "mymath.h"),详见 5.9 节。
查看产物类型与内容:
file hello.i
head -5 hello.i
回显:
hello.i: C source, ASCII text
# 0 "hello.c"
# 0 "<built-in>"
# 0 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 0 "<command-line>" 2
💡 说明:
# 行号 "文件名"形式的行是预处理器添加的“行标记”(linemarkers),供后续编译与调试定位源码位置使用。
5.2.2 -S:只做编译,输出汇编
-S 把(预处理后的)源码翻译为汇编代码,输出 .s 文件:
gcc -S hello.i -o hello.s
file hello.s
回显:
hello.s: assembler source, ASCII text
5.2.3 -c:只做汇编,输出目标文件
-c 把汇编代码翻译为机器码,输出可重定位目标文件 .o:
gcc -c hello.s -o hello.o
file hello.o
回显:
hello.o: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), not stripped
💡 说明:
.o是 ELF 可重定位文件(relocatable),尚未链接,不能直接执行。
5.2.4 链接生成可执行文件并运行
链接阶段把目标文件与库合并。由于 hello.c 引用了 add() 函数而其实现在 lib/mymath.c,链接时需要一并参与编译链接:
gcc hello.o lib/mymath.c -o hello
./hello
回显:
Hello, GCC on Ubuntu 22.04!
add(3, 5) = 8
查看四个阶段的产物:
ls -l hello.i hello.s hello.o hello
回显:
-rwxr-xr-x 1 root root 16064 Oct 6 06:24 hello
-rw-r--r-- 1 root root 18106 Oct 6 06:24 hello.i
-rw-r--r-- 1 root root 1696 Oct 6 06:24 hello.o
-rw-r--r-- 1 root root 849 Oct 6 06:24 hello.s
用 file 查看最终可执行文件:
file hello
回显:
hello: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=0e8db20d74fc60d737baa2a6ebd2d9964df85413, for GNU/Linux 3.2.0, not stripped
💡 说明:
pie executable表示 Ubuntu 22.04 默认开启 PIE(位置无关可执行文件);dynamically linked表示动态链接;not stripped表示符号表未被剥离,可用于调试。
5.3 输出文件控制:-o
-o 指定输出文件名:
gcc -I./include hello.c lib/mymath.c -o hello2
./hello2
回显:
Hello, GCC on Ubuntu 22.04!
add(3, 5) = 8
⚠️ 注意:
-o后面必须紧跟输出文件名。若省略-o,gcc 默认输出到当前目录的a.out:
gcc -I./include hello.c lib/mymath.c
ls -l a.out
./a.out
回显:
-rwxr-xr-x 1 root root 16064 Oct 6 06:24 a.out
Hello, GCC on Ubuntu 22.04!
add(3, 5) = 8
5.4 优化级别:-O0、-O1、-O2、-O3
-O 系列参数控制编译器的优化强度。数字越大优化越激进,编译时间与代码体积通常随之增加,运行效率提升:
gcc -O0 -I./include hello.c lib/mymath.c -o hello_O0
gcc -O1 -I./include hello.c lib/mymath.c -o hello_O1
gcc -O2 -I./include hello.c lib/mymath.c -o hello_O2
gcc -O3 -I./include hello.c lib/mymath.c -o hello_O3
ls -l hello_O0 hello_O1 hello_O2 hello_O3
回显:
-rwxr-xr-x 1 root root 16064 Oct 6 06:24 hello_O0
-rwxr-xr-x 1 root root 16072 Oct 6 06:24 hello_O1
-rwxr-xr-x 1 root root 16072 Oct 6 06:24 hello_O2
-rwxr-xr-x 1 root root 16072 Oct 6 06:24 hello_O3
💡 说明:
-O0不做优化,编译最快,最利于调试;-O1做基本优化;-O2是发布版本的常用级别;-O3进一步激进优化。小程序在体积上差异不大,可借助size查看各段实际大小:
size hello_O0 hello_O3
回显:
text data bss dec hex filename
1596 608 8 2212 8a4 hello_O0
1598 608 8 2214 8a6 hello_O3
💡 说明:
text是代码段字节数,-O3优化后 text 段略大(1598 > 1596);data是已初始化数据段,bss是未初始化数据段。
5.5 警告选项:-Wall、-Wextra、-Werror
5.5.1 -Wall -Wextra:开启常用警告
-Wall 开启一组常用警告(如未使用变量、隐式类型转换等),-Wextra 开启更多额外警告。以 warn.c(含未使用变量)为例:
gcc -Wall -Wextra warn.c -o warn
回显:
warn.c: In function 'main':
warn.c:5:9: warning: unused variable 'unused_var' [-Wunused-variable]
5 | int unused_var = 42;
| ^~~~~~~~~~
💡 说明:警告不影响编译结果,
warn可执行文件照常生成,但强烈建议消除所有警告。
5.5.2 -Werror:把警告升级为错误
-Werror 将一切警告视为错误,导致编译失败。
⚠️ 注意:
-Werror本身不会主动开启警告,必须配合-Wall等警告选项才有意义。单独使用gcc -Werror warn.c时,未使用变量警告默认未开启,编译会正常通过。
正确用法:
gcc -Wall -Werror warn.c -o warn_err
echo "exit=$?"
回显:
warn.c: In function 'main':
warn.c:5:9: error: unused variable 'unused_var' [-Werror=unused-variable]
5 | int unused_var = 42;
| ^~~~~~~~~~
cc1: all warnings being treated as errors
exit=1
⚠️ 注意:
cc1: all warnings being treated as errors表明所有警告被当作错误,编译以非零状态退出(exit=1),且不会生成warn_err文件。CI(持续集成)构建中常用-Wall -Werror强制代码零警告。
5.6 语言标准:-std=c11、-std=c17、-std=gnu17
-std= 指定遵循的 C 语言标准。c11/c17 为纯 ISO 标准模式,gnu17 为带 GNU 扩展的标准模式(Ubuntu 22.04 默认):
gcc -std=c11 -I./include hello.c lib/mymath.c -o hello_c11
./hello_c11
回显:
Hello, GCC on Ubuntu 22.04!
add(3, 5) = 8
gcc -std=c17 -I./include hello.c lib/mymath.c -o hello_c17
./hello_c17
回显:
Hello, GCC on Ubuntu 22.04!
add(3, 5) = 8
gcc -std=gnu17 -I./include hello.c lib/mymath.c -o hello_gnu17
./hello_gnu17
回显:
Hello, GCC on Ubuntu 22.04!
add(3, 5) = 8
💡 说明:
-v输出中的GNU C17表明本机默认标准为 GNU C17(等价于-std=gnu17)。常见的还有c99、c2x(C23 草案)等取值。
5.7 调试与剖析:-g、-pg
5.7.1 -g:生成调试信息
-g 让编译器在产物中写入 DWARF 调试信息,供 gdb 断点、查看变量等使用:
gcc -g -I./include hello.c lib/mymath.c -o hello_g
file hello_g
回显:
hello_g: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=31c7bb076583bafa86200314ff4b732be4809b7f, for GNU/Linux 3.2.0, with debug_info, not stripped
💡 说明:
file输出中的with debug_info即表明带调试信息。调试版体积明显更大(hello_g 17672 字节,普通版 16064 字节)。发布版本应去掉-g(或使用-g0)。
5.7.2 -pg:生成剖析(profiling)支持
-pg 在生成的可执行文件中加入 gprof 剖析支持,运行程序会生成 gmon.out 剖析数据:
gcc -pg -I./include hello.c lib/mymath.c -o hello_pg
ls -l hello_pg
回显:
-rwxr-xr-x 1 root root 16536 Oct 6 06:25 hello_pg
💡 说明:运行
./hello_pg后会在当前目录生成gmon.out,再用gprof hello_pg gmon.out即可输出各函数耗时统计,用于性能瓶颈分析。
5.8 宏定义:-D、-U、-dM -E
5.8.1 -D:定义宏
-DDEBUG=1 等价于在源码最前面写 #define DEBUG 1。以 macro.c 为例(含 #ifdef DEBUG 条件编译):
gcc -DDEBUG=1 -o macro macro.c
./macro
回显:
DEBUG mode: macro DEBUG is defined
不定义 DEBUG 时编译则走 else 分支:
gcc -o macro_none macro.c
./macro_none
回显:
normal mode
5.8.2 -U:取消宏定义
-UDEBUG 等价于 #undef DEBUG,可取消命令行或头文件中已定义的宏:
gcc -DDEBUG=1 -UDEBUG -o macro_u macro.c
./macro_u
回显:
normal mode
💡 说明:先用
-DDEBUG=1定义,再用-UDEBUG取消,最终#ifdef DEBUG不成立,输出normal mode。
5.8.3 -dM -E:列出预定义宏
-dM 让预处理器把所有宏定义(含编译器内置宏)以 #define 形式打印,-E 表示只做预处理,- 表示从标准输入读取空文件:
gcc -dM -E - </dev/null | head -20
回显:
#define __SSP_STRONG__ 3
#define __DBL_MIN_EXP__ (-1021)
#define __UINT_LEAST16_MAX__ 0xffff
#define __ATOMIC_ACQUIRE 2
#define __FLT128_MAX_10_EXP__ 4932
#define __FLT_MIN__ 1.17549435082228750796873653722224568e-38F
#define __GCC_IEC_559_COMPLEX 2
#define __UINT_LEAST8_TYPE__ unsigned char
#define __SIZEOF_FLOAT80__ 16
#define __INTMAX_C(c) c ## L
#define __CHAR_BIT__ 8
#define __UINT8_MAX__ 0xff
#define __SCHAR_WIDTH__ 8
#define __WINT_MAX__ 0xffffffffU
#define __FLT32_MIN_EXP__ (-125)
#define __ORDER_LITTLE_ENDIAN__ 1234
#define __SIZE_MAX__ 0xffffffffffffffffUL
#define __WCHAR_MAX__ 0x7fffffff
#define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 1
#define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 1
💡 说明:这些是编译器根据目标平台自动预定义的宏,可用于源码中判断编译器与平台特性,例如
__SIZE_MAX__表示size_t最大值。
5.9 依赖列表与头文件搜索:-MM、-M、-I
5.9.1 -MM:输出用户头文件依赖
-MM 只输出源文件对用户头文件(非系统头文件)的依赖,供 Makefile 自动生成依赖规则:
gcc -I./include -MM hello.c
回显:
hello.o: hello.c include/mymath.h
5.9.2 -M:输出全部依赖
-M 输出包括系统头文件在内的全部依赖:
gcc -I./include -M hello.c
回显(节选,输出很长):
hello.o: hello.c /usr/include/stdc-predef.h /usr/include/stdio.h \
/usr/include/x86_64-linux-gnu/bits/libc-header-start.h \
/usr/include/features.h /usr/include/features-time64.h \
/usr/include/x86_64-linux-gnu/bits/wordsize.h \
/usr/include/x86_64-linux-gnu/bits/timesize.h \
/usr/include/x86_64-linux-gnu/sys/cdefs.h \
💡 说明:
-M输出可用gcc -M hello.c > hello.d重定向到文件,由 Makefile 以-include hello.d引入,实现头文件变更自动重编译。
5.9.3 -I:指定头文件搜索目录
-I<目录> 向编译器追加头文件搜索路径。hello.c 中 #include "mymath.h" 位于 include/ 目录,不加 -I 会报错 fatal error: mymath.h: No such file or directory:
gcc -I./include -c hello.c -o hello.o
回显:无输出(成功)
💡 说明:
-c只编译不链接,用于验证头文件能被正确找到。-I可多次使用(-I dir1 -I dir2),搜索顺序按命令行先后排列,系统头文件目录在最后。
5.10 库链接:-L、-l、-lm
5.10.1 -lm:链接数学库 libm
sqrt()、sin() 等数学函数位于 libm 数学库中。以 math_var.c(运行时变量参数,阻止常量折叠)为例,不加 -lm 链接失败:
gcc math_var.c -o math_var
回显:
/usr/bin/ld: /tmp/cc1K8TKE.o: in function `main':
math_var.c:(.text+0x3a): undefined reference to `sqrt'
collect2: error: ld returned 1 exit status
加上 -lm 后链接成功:
gcc math_var.c -lm -o math_var
./math_var
回显:
sqrt(9) = 3.0
💡 说明:
-l<名字>表示链接名为lib<名字>.so(或.a)的库,-lm即链接libm。若源码中对sqrt()传的是编译期常量,GCC 会内建优化为常量结果(gcc sqrt_demo.c -o sqrt_demo也能成功),因此演示用变量参数确保真实触发链接需求。
5.10.2 -L:指定库文件搜索目录
链接自定义库时,用 -L<目录> 告知链接器去哪个目录找库文件,配合 -l<名字> 使用:
gcc main.c -L. -lfoo -o app
回显:无输出(成功)
💡 说明:
-L.表示在当前目录(.)搜索库文件,-lfoo表示链接libfoo.so。详见 5.12 节完整演示。
5.11 工具链信息:-v、-print-search-dirs、-print-file-name
5.11.1 -v:输出详细编译过程
-v(verbose)让 gcc 打印其配置信息与每个内部子工具的调用细节:
gcc -v -I./include hello.c lib/mymath.c -o hello_v
回显(节选):
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/11/lto-wrapper
OFFLOAD_TARGET_NAMES=nvptx-none:amdgcn-amdhsa
OFFLOAD_TARGET_DEFAULT=1
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 11.4.0-1ubuntu1~22.04.3' --with-bugurl=file:///usr/share/doc/gcc-11/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++,m2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-11 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-bootstrap --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --enable-libphobos-checking=release --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --enable-cet --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=...,amdgcn-amdhsa=... --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu --with-build-config=bootstrap-lto-lean --enable-link-serialization=2
Thread model: posix
Supported LTO compression algorithms: zlib zstd
gcc version 11.4.0 (Ubuntu 11.4.0-1ubuntu1~22.04.3)
继续输出内部子工具调用与头文件搜索路径:
/usr/lib/gcc/x86_64-linux-gnu/11/cc1 -quiet -v -I ./include -imultiarch x86_64-linux-gnu hello.c -quiet -dumpdir hello_v- -dumpbase hello.c -dumpbase-ext .c -mtune=generic -march=x86-64 -version -fasynchronous-unwind-tables -fstack-protector-strong -Wformat -Wformat-security -fstack-clash-protection -fcf-protection -o /tmp/ccc3FNGg.s
GNU C17 (Ubuntu 11.4.0-1ubuntu1~22.04.3) version 11.4.0 (x86_64-linux-gnu)
compiled by GNU C version 11.4.0, GMP version 6.2.1, MPFR version 4.1.0, MPC version 1.2.1, isl version isl-0.24-GMP
#include "..." search starts here:
💡 说明:从
-v可以看到:默认标准是GNU C17;--enable-default-pie解释了为何可执行文件是 PIE 格式;-fstack-protector-strong等安全选项由发行版默认注入。
5.11.2 -print-search-dirs:打印搜索目录
gcc -print-search-dirs
回显:
install: /usr/lib/gcc/x86_64-linux-gnu/11/
programs: =/usr/lib/gcc/x86_64-linux-gnu/11/:/usr/lib/gcc/x86_64-linux-gnu/11/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/11/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/11/../../../../x86_64-linux-gnu/bin/x86_64-linux-gnu/11/:/usr/lib/gcc/x86_64-linux-gnu/11/../../../../x86_64-linux-gnu/bin/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/11/../../../../x86_64-linux-gnu/bin/
libraries: =/usr/lib/gcc/x86_64-linux-gnu/11/:/usr/lib/gcc/x86_64-linux-gnu/11/../../../../x86_64-linux-gnu/lib/x86_64-linux-gnu/11/:/usr/lib/gcc/x86_64-linux-gnu/11/../../../../x86_64-linux-gnu/lib/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/11/../../../../x86_64-linux-gnu/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/11/../../../x86_64-linux-gnu/11/:/usr/lib/gcc/x86_64-linux-gnu/11/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/11/../../../../lib/:/lib/x86_64-linux-gnu/11/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/11/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/11/../../../../x86_64-linux-gnu/lib/:/usr/lib/gcc/x86_64-linux-gnu/11/../../../:/lib/:/usr/lib/
💡 说明:
programs是 gcc 查找 cc1、as、ld 等子工具的目录列表,libraries是查找库文件的目录列表。
5.11.3 -print-file-name:打印库/头文件完整路径
gcc -print-file-name=include
gcc -print-file-name=libgcc.a
回显:
/usr/lib/gcc/x86_64-linux-gnu/11/include
/usr/lib/gcc/x86_64-linux-gnu/11/libgcc.a
💡 说明:
-print-file-name=<名字>输出指定库或文件的完整路径,脚本中常用它动态获取路径,避免硬编码。
5.12 共享库编译:-shared、-fPIC
5.12.1 编译共享库 libfoo.so
-fPIC 生成位置无关代码(Position Independent Code),-shared 生成共享库:
gcc -shared -fPIC -o libfoo.so foo.c
file libfoo.so
回显:
libfoo.so: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, BuildID[sha1]=9691b5e25065705ea521fd67d96d2412271e173c, not stripped
💡 说明:
shared object即共享库类型。查看其动态导出符号:
nm -D libfoo.so | head -12
回显:
w _ITM_deregisterTMCloneTable
w _ITM_registerTMCloneTable
w __cxa_finalize@GLIBC_2.2.5
w __gmon_start__
0000000000001119 T foo
U puts@GLIBC_2.2.5
💡 说明:
T foo表示foo是已定义的导出符号(可被外部调用),U puts@GLIBC_2.2.5表示puts是未定义的导入符号,来自 glibc。
5.12.2 链接并使用共享库
gcc main.c -L. -lfoo -o app
回显:无输出(成功)
💡 说明:
-L.指定库搜索目录为当前目录,-lfoo链接libfoo(自动匹配libfoo.so)。
查看动态链接依赖:
ldd app
回显(相关行):
libfoo.so => not found
⚠️ 注意:运行时动态链接器默认不搜索当前目录,
libfoo.so显示not found。需通过LD_LIBRARY_PATH指定运行期库路径:
LD_LIBRARY_PATH=. ./app
回显:
hello from libfoo.so
💡 说明:
LD_LIBRARY_PATH=.告诉动态链接器去当前目录找共享库。生产环境更推荐把库安装到系统目录(如/usr/local/lib)并执行ldconfig更新缓存。
六、配置说明
6.1 默认编译标准
Ubuntu 22.04 的 gcc-11 默认标准为 GNU C17(-std=gnu17),-v 输出中 GNU C17 ... 即为证明。需要严格 ISO 标准时显式传 -std=c17 或 -std=c11。
6.2 多版本共存与默认 gcc
Ubuntu 通过符号链接管理默认编译器版本。查看 /usr/bin 下的 gcc 符号链接:
ls -l /usr/bin/gcc*
回显:
lrwxrwxrwx 1 root root 6 Aug 5 2021 /usr/bin/gcc -> gcc-11
lrwxrwxrwx 1 root root 23 Dec 18 2025 /usr/bin/gcc-11 -> x86_64-linux-gnu-gcc-11
lrwxrwxrwx 1 root root 9 Aug 5 2021 /usr/bin/gcc-ar -> gcc-ar-11
lrwxrwxrwx 1 root root 26 Dec 18 2025 /usr/bin/gcc-ar-11 -> x86_64-linux-gnu-gcc-ar-11
lrwxrwxrwx 1 root root 9 Aug 5 2021 /usr/bin/gcc-nm -> gcc-nm-11
lrwxrwxrwx 1 root root 26 Dec 18 2025 /usr/bin/gcc-nm-11 -> x86_64-linux-gnu-gcc-nm-11
lrwxrwxrwx 1 root root 13 Aug 5 2021 /usr/bin/gcc-ranlib -> gcc-ranlib-11
lrwxrwxrwx 1 root root 30 Dec 18 2025 /usr/bin/gcc-ranlib-11 -> x86_64-linux-gnu-gcc-ranlib-11
💡 说明:
/usr/bin/gcc是一个符号链接,指向gcc-11。系统中可以同时安装多个 GCC 大版本(如 gcc-10、gcc-11、gcc-12),通过gcc-11、gcc-12直接调用指定版本。
直接调用指定大版本:
gcc-11 --version
回显:
gcc-11 (Ubuntu 11.4.0-1ubuntu1~22.04.3) 11.4.0
Copyright (C) 2021 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
若需要让 gcc 在多个版本间切换,可配置 update-alternatives 机制。本机尚未配置,执行查询会报错:
update-alternatives --list gcc
回显:
update-alternatives: error: no alternatives for gcc
💡 说明:Ubuntu 官方源的 gcc 默认不注册 alternatives(避免破坏符号链接链)。如需切换默认版本,可手工注册,例如:
update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-11 110。
6.3 相关环境变量
| 环境变量 | 作用 |
|---|---|
LD_LIBRARY_PATH | 指定动态链接器运行时搜索共享库的额外目录(见 5.12) |
CPATH | 指定编译器搜索头文件的额外目录(等效于全局 -I) |
LIBRARY_PATH | 指定链接器搜索库文件的额外目录(等效于全局 -L) |
CFLAGS | 供 make 等构建工具读取的 C 编译选项 |
七、常见问题(FAQ)
7.1 为什么 apt show gcc 显示 4:11.2.0-1ubuntu1,而 gcc --version 显示 11.4.0?
因为 Ubuntu 的 gcc 是元包,只负责把真正的编译器 gcc-11 拉进来。元包版本号与底层编译器版本可以不同:
apt-cache show gcc | head -14
回显:
Package: gcc
Architecture: amd64
Version: 4:11.2.0-1ubuntu1
Priority: optional
Section: devel
Source: gcc-defaults (1.193ubuntu1)
Origin: Ubuntu
Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
Original-Maintainer: Debian GCC Maintainers <debian-gcc@lists.debian.org>
Bugs: https://bugs.launchpad.net/ubuntu/+filebug
Installed-Size: 50
Provides: c-compiler, gcc-x86-64-linux-gnu (= 4:11.2.0-1ubuntu1)
Depends: cpp (= 4:11.2.0-1ubuntu1), gcc-11 (>= 11.2.0-1~)
Recommends: libc6-dev | libc-dev
💡 说明:
Depends: gcc-11 (>= 11.2.0-1~)表明元包依赖 gcc-11。以gcc --version输出为准(11.4.0),4:11.2.0-1ubuntu1中的4:是 Debian/Ubuntu 的 epoch(版本优先级前缀)。
7.2 -Werror 为什么没有报错?
-Werror 只负责“把警告当错误”,不负责“开启警告”。未使用变量等警告默认关闭,必须配合 -Wall 等选项:
gcc -Wall -Werror warn.c -o warn_err
7.3 undefined reference to 'sqrt' 是什么原因?
sqrt 等数学函数在 libm 库中,链接时需显式加 -lm:
gcc math_var.c -lm -o math_var
7.4 libfoo.so => not found 怎么办?
运行时动态链接器不搜索当前目录。两种做法:其一,运行前设置环境变量 LD_LIBRARY_PATH=.;其二,将库安装到系统目录并执行 sudo ldconfig。
7.5 提示 file: command not found?
最小化系统可能未安装 file 工具:
sudo apt install -y file
7.6 头文件报 No such file or directory?
源码引用的自定义头文件不在默认搜索路径中,用 -I 指定目录,例如:
gcc -I./include hello.c lib/mymath.c -o hello
八、卸载与清理
8.1 查看 gcc 包的安装状态
dpkg -l 列出包的期望/实际状态(ii 表示已正确安装):
dpkg -l gcc
回显:
Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
|/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)
||/ Name Version Architecture Description
+++-==============-=================-============-=================================
ii gcc 4:11.2.0-1ubuntu1 amd64 GNU C compiler
💡 说明:第一列
ii:第一位i(Desired=Install)第二位i(Status=Inst),即“期望安装且已安装”。
8.2 卸载 gcc
仅卸载元包(保留依赖与配置):
sudo apt remove gcc
连同配置与自动安装的依赖一起清理(生产环境谨慎使用,可能移除其他依赖 gcc 的工具):
sudo apt purge gcc
sudo apt autoremove
⚠️ 注意:卸载会连带影响依赖 gcc 的软件(如内核模块编译、部分 SDK),卸载前先确认无其他软件需要它。
8.3 清理下载缓存
sudo apt clean
💡 说明:
apt clean清空/var/cache/apt/archives/下的.deb缓存,释放磁盘空间(本机缓存约 32 MB)。
九、参考链接
- GCC 官方文档:https://gcc.gnu.org/onlinedocs/
- GCC 11 变更说明:https://gcc.gnu.org/gcc-11/changes.html
- Ubuntu 软件包 gcc:https://packages.ubuntu.com/jammy/gcc
- Ubuntu 软件包 gcc-11:https://packages.ubuntu.com/jammy-updates/gcc-11
- GNU C 手册:https://gcc.gnu.org/onlinedocs/gcc-11.4.0/gcc/
- apt 用户手册:https://manpages.ubuntu.com/manpages/jammy/man8/apt.8.html