ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

GCC 9.3.0源码编译安装全指南:从解压到动态库配置

GCC 9.3.0源码编译安装全指南:从解压到动态库配置 简介gcc-9.3.0.tar.gz 是 GNU 编译器套件 9.3.0 版本的完整源码压缩包面向 Linux/UNIX 开发者、嵌入式工程师及需要从源码定制编译工具链的中高级用户。该版本在 GCC 9 系列中兼具新语言特性支持与稳定性改进适用于 C/C、Fortran、Go 等主流语言的编译与优化场景。压缩包共 2000 个文件包含 1520 个 C 源文件、344 个头文件以及少量 C、Python、Shell 辅助脚本和 PDF/TXT 文档整体体积约 118.39MB目录结构符合 GNU 官方发布布局便于定位核心源码与构建脚本。包内代码覆盖编译器前端解析、GIMPLE 中间表示、后端代码生成及 libbacktrace 等基础库同时附带 lex/yacc 相关处理文件和多语言运行时支持适合深入阅读源码或进行二次开发。已有 350 人学习下载对希望研究编译原理、调试 GCC 内部实现或构建定制化工具链的开发者具有直接参考价值。1. 拿到 gcc-9.3.0.tar.gz 之后一条从解压到生效的完整闭环把 gcc-9.3.0.tar.gz 下载到本地只算走完第一步。这个包解压后是一整套编译器源码从它到系统里出现一个能用的gcc -v中间隔着依赖库、configure 参数、几十分钟编译、动态库路径和 PATH 优先级任何一环断了都会让你觉得「明明装了怎么还是旧版本」。这篇文章就按我自己的安装链路来写从解压 tar.gz 开始到验证 C17 程序能跑为止把每一步命令为什么这么写、失败时看什么日志讲清楚。适合在 CentOS 7、Ubuntu 或同类 Linux 发行版上需要独立工具链的开发者也适合刚接触 GCC 源码编译、照着帖子抄命令却总在最后一步翻车的人。2. 解压 gcc-9.3.0.tar.gz 之前依赖库和工具链得先齐2.1 为什么 GCC 源码编译前要盯住 GMP、MPFR、MPC 三个库GCC 9.3.0 的源码包本身只包含编译器主体它的数学运算优化、浮点精度控制和多项式处理分别依赖 GMP、MPFR、MPC 三个外部库。configure 阶段会检查这三个库的头文件和符号缺任何一个就会在检查步骤直接中断报错往往很隐晦比如提示找不到gmp.h或libmpc.so。这里有个容易搞混的地方GCC 源码树里其实带了这三个库的「贡献版本」放在gmp、mpfr、mpc子目录里但它们默认不会被自动编译。常见做法是去官网下载对应的源码包解压后做软链接让名字变成源码树根目录下的gmp、mpfr、mpcconfigure 会自动去同名目录里找并一起构建。另一种做法是用发行版自带的开发包比如 CentOS 7 上的gmp-devel、mpfr-devel、libmpc-devel然后通过--with-gmp、--with-mpfr、--with-mpc指向安装前缀。我一般推荐软链接方案理由是发行版仓库里的这三个库往往版本偏老CentOS 7 默认源尤其明显。老版本不是不能用但 GCC 9 的某些优化路径会在运行时探测新接口版本太低时会让生成的二进制在特定 CPU 指令下表现异常。这种问题最麻烦——编译不报错跑起来结果不对属于典型的黑匣子问题。用源码树内置的方式构建三个库与 GCC 本身版本匹配后续排查也少一个变量。2.2 tar.gz 解压命令与系统依赖安装CentOS 7 与 Ubuntu 对照先做解压。GCC 9.3.0 的官方包有 tar.gz 和 tar.xz 两种格式你拿到的是 tar.gz 就直接用tar -xf新版 GNU tar 会自动识别压缩格式不需要在意后缀# 解压到当前目录-x 解包 -f 指定文件-C 可以换目录 tar -xf gcc-9.3.0.tar.gz cd gcc-9.3.0 # 查看解压结果确认目录结构完整 ls -la | head -20tar -xf是解压 tar.gz 和 tar.xz 的通用写法GNU tar 1.27 及以上版本都能自动识别 gzip 和 xz不用像老教程那样先gunzip再tar -xvf。解压后第一件事不是急着 configure而是先检查系统里有没有基础编译工具。GCC 是 C 语言写的编译它需要一个能工作的 C/C 编译器这是典型的先有鸡还是先有蛋问题。# CentOS 7 / Rocky Linux / 国产同类发行版 yum groupinstall -y Development Tools yum install -y gcc gcc-c gmp-devel mpfr-devel libmpc-devel bison flex texinfo # Ubuntu / Debian apt install -y build-essential libgmp-dev libmpfr-dev libmpc-devDevelopment Tools这个包组会装好 make、binutils、gcc 等基础工具但这些通常版本偏旧只能拿来「生」新编译器。bison和flex是生成 GCC 解析器代码时用的texinfo用于生成文档装齐可以避免 configure 阶段半路报错。装完之后用gcc --version确认一下系统里至少有一个能跑的旧编译器版本不论新旧够用就行。2.3 下载 gcc 网速过慢怎么办断点续传和镜像源很多人卡在第一步其实是下载阶段。gcc-9.3.0.tar.gz 体积不小官方源在国外国内网络环境下一个多小时下不完是常事。处理办法分两层下载阶段用wget -c支持断点续传中断了不用从头再来如果源实在慢就换国内镜像站下载路径和官方保持一致。# 先让下载在后台跑-c 断点续传日志写到文件里 nohup wget -c https://mirrors.example.com/gcc/releases/gcc-9.3.0/gcc-9.3.0.tar.gz \ gcc-download.log 21 # 隔几分钟看一眼下载进度确认没有卡死 tail -n 5 gcc-download.lognohup配合把下载放到后台关闭终端也不会中断。下载完成后用ls -lh看一眼文件大小和页面标注的字节数比对对不上就说明下载不完整解压时会出现莫名的 CRC 错误。用sha256sum gcc-9.3.0.tar.gz再和官方校验和对比一次更稳这一步能省掉后面解压到一半报错的后悔药。3. 执行 configure参数怎么设决定后面几十分钟值不值3.1 最小可用的一组 configure 参数与含义准备工作做完进入真正的编译安装流程。GCC 官方推荐在源码目录外单独建一个 build 目录不要把构建产物混进源码树。原因很实际GCC 支持同一套源码在不同配置下构建多次分开目录后想换个参数重编直接清空 build 目录就行源码保持干净。# 回到 gcc-9.3.0 源码根目录创建独立构建目录 cd gcc-9.3.0 mkdir -p build cd build # configure 参数只编 C/C装到独立目录关闭 multilib ../configure \ --prefix/usr/local/gcc-9.3.0 \ --enable-languagesc,c \ --disable-multilib \ --enable-checkingrelease \ 21 | tee ../configure.log # 确认没有 error 再继续 tail -n 30 ../configure.log | grep -i error--prefix指定安装目录这步很关键。把 GCC 9.3.0 装到/usr/local/gcc-9.3.0而不是默认的/usr/local是为了和系统自带的 GCC 完全隔离之后想切回旧版本只要改 PATH卸载也只要删目录。--enable-languagesc,c限定只编 C 和 C 编译器不编 Fortran、Ada、Go 这些用不到的前端能省不少编译时间。--disable-multilib告诉 GCC 不需要生成 32 位库否则 configure 会检查 32 位版本的 glibc 头文件缺失就直接报错。--enable-checkingrelease让编译器在发布模式下做最小限度的自检既能保留一点内部错误检测能力又不会拖慢生成的代码。21 | tee ../configure.log的作用是把 configure 的所有输出同时写到屏幕和日志文件。GCC 的 configure 脚本输出很啰嗦滚动速度快到肉眼根本来不及看报错信息把日志落盘后可以随时回头查。这也是后面排查问题的主要依据我在这一行上的经验和教训最深。3.2 configure 和 make 的日志输出到文件tee 与 grep 的配合编译 GCC 的输出量比 configure 还大一个量级几千行编译告警会淹没真正的错误。把日志写到文件不是可选操作是必须操作。# 在 build 目录下执行 make-j 指定并行度日志双写并保存 make -j$(nproc) 21 | tee ../build.log # 出错中断后快速定位第一个真正的错误位置 grep -in error: ../build.log | head -20 # 看错误发生前后的上下文方便理解失败原因 grep -n error: ../build.log | head -1 | cut -d: -f1 | xargs -I{} sed -n {},$(({}15))p ../build.logtee命令把 stdout 和 stderr 合并后一边送终端一边写文件这样既能看到实时进度又能在编译跑了半小时后中断时用 grep 在日志里搜error:。注意搜的时候不要搜全部先head -20看前 20 条。GCC 编译过程中的很多错误是连锁反应第一个错误引发后面几十条报错只有最上面那条才是根因。我刚才用的sed组合命令就是从第一个 error 行开始打印 15 行上下文看它到底是在编哪个文件、调用了什么命令这在排查 header 路径错误时特别好用。3.3 configure 检查失败时先看 config.log 而不是重跑configure 中断时新手的第一反应是换个参数重跑但更高效的做法是看 build 目录下的config.log文件。这个文件记录了 configure 做的每一项检查、执行了什么测试命令、得到了什么输出是诊断配置问题的第一手资料。# 在 build 目录下查看 config.log 末尾记录的最后一次失败 tail -n 80 config.log | grep -B5 error\|failed # 常见原因系统里没有 c 编译器 # configure: error: C preprocessor /lib/cpp fails sanity check yum install -y gcc-c最常见的两个 configure 失败原因一是系统缺gcc-cconfigure 测试 C 编译器时直接失败报错信息里会出现/lib/cpp或cannot compute suffix二是环境变量里残留了CC、CXX指向不存在的编译器路径这是之前手动装过其他版本留下的坑。解决办法很简单安装缺失的包或者unset CC CXX清掉残留变量再重跑 configure。按我的经验百分之八十的 configure 失败都能在 config.log 末尾 50 行内找到直接原因比盲目换参数省时间得多。4. make 与 make install把新版 GCC 装进独立目录4.1 make 时长与 -j 参数选择小心内存把编译中断configure 顺利通过后进入编译阶段。GCC 9.3.0 默认会做 bootstrap也就是用刚编译出来的编译器再编译一遍自己整个过程相当于完整编译三遍目的是验证新编译器能正确编译自身代码并优化出更高性能的编译器。默认make会跑完整 bootstrap总时长按机器性能在 20 分钟到一小时不等。# 查看 CPU 核心数-j 参数一般用核心数减一 nproc # 内存充足8G 以上可以用满核 make -j$(($(nproc) - 1)) 21 | tee ../build.log # 内存紧张2G 左右强制降到双线程避免 cc1plus 被 OOM 杀掉 make -j2 21 | tee ../build.log-j参数不是越大越好。GCC 编译过程中单个编译进程峰值内存能到几百 MBmake -j8并发 8 个编译任务时内存占用可能冲到 4G 以上。小内存机器直接 OOM内核杀掉 cc1plus 进程后 make 报一个莫名其妙的Killed这时候去翻 build.log 往往找不到 error 记录。我吃过这个亏后来养成习惯先free -h看内存再决定开几个线程。如果只追求尽快拿到编译器不追求自举验证可以用make -j2 bootstrap-lean或者直接make -j2配合--disable-bootstrap省掉后两遍编译。代价是新编译器没有经过「自己编自己」这层检验可靠性略低。我的建议是这个环节别省GCC 这种基础工具多花二十分钟换来自检通过的编译器值。4.2 安装与动态库路径libstdc 的位置决定程序能不能跑make顺利结束后执行安装GCC 会按 configure 时指定的--prefix把编译器、头文件、库文件分别放到对应目录。安装完成后先别急着用还有一步动态库路径要配。# 安装到 /usr/local/gcc-9.3.0需要 root 权限 make install 21 | tee ../install.log # 确认编译器已经落在目标目录 ls -l /usr/local/gcc-9.3.0/bin/gcc /usr/local/gcc-9.3.0/bin/gcc --version # 让系统找到新的 libstdc.so.6写入 ld.so.conf.d 后刷新缓存 echo /usr/local/gcc-9.3.0/lib64 /etc/ld.so.conf.d/gcc-9.3.0.conf ldconfig # 检查动态库是否指向新版本 ldconfig -p | grep libstdc这里最大的坑是 32 位库和 64 位库目录名不同。64 位系统的 GCC 库装在lib6432 位系统装在lib如果机器上装了 32 位兼容环境两条路径都要加进配置文件。ldconfig刷新后用ldconfig -p | grep libstdc确认系统里有一个libstdc.so.6指向/usr/local/gcc-9.3.0/lib64这一步没做后面编译出来的程序运行时百分之百会报version GLIBCXX_3.4.28 not found。这就是前面说的动态链接器优先从/etc/ld.so.conf.d下的路径里找库找不到才回退到系统默认路径的机制。4.3 升级后为啥还是旧版本PATH 优先级与 shell 缓存安装完成后打开新终端输入gcc -v发现版本还是老版本这是 GCC 手动安装后最常见的问题本质是 PATH 里/usr/local/gcc-9.3.0/bin排在/usr/bin后面shell 先找到了系统自带的旧 gcc。# 看看当前 gcc 实际是从哪来的 which gcc which -a gcc # 当前会话临时生效的方式注意路径要放在最前面 export PATH/usr/local/gcc-9.3.0/bin:$PATH hash -r gcc -v # 永久生效写入 profile.d 下的脚本新登录终端自动加载 echo export PATH/usr/local/gcc-9.3.0/bin:$PATH /etc/profile.d/gcc-9.3.0.sh chmod x /etc/profile.d/gcc-9.3.0.shexport PATH新路径:$PATH的顺序不能反新路径放在最前面才能被优先找到。hash -r是清空 bash 的命令路径缓存这个细节很容易被忽略——bash 会把用过的命令路径存起来PATH 改了之后它可能还在用旧缓存导致你明明改了 PATH 却感觉没生效这是典型的玄学问题实际就是缓存作祟。我的习惯是系统自带 GCC 不要卸载。CentOS 7 的 yum、内核编译、部分系统工具依赖特定版本的 GCC强制替换会带来一堆连锁问题。让新版 GCC 走 PATH 前缀需要时随时用不需要时把/etc/profile.d/gcc-9.3.0.sh改名就恢复原样这是最安全也最省心的双版本共存方案。5. 避坑GCC 9.3.0 编译安装中的 5 个典型翻车现场5.1 configure 报错 cannot compute suffix of object files现象configure 执行到检查 C 编译器那一项时中断日志末尾出现cannot compute suffix of object files: cannot compile或类似信息。原因系统里没有可用的 C 编译器或者环境变量CXX指向了一个不存在的路径。CentOS 7 最小化安装时默认没有gcc-cGCC 9.3.0 的 configure 脚本需要靠现有 C 编译器来完成一系列语言特性探测找不到就直接失败。解决先yum install -y gcc-c补上基础编译器再用env | grep -E ^CXX|^CC检查环境变量如果有残留就unset CC CXX。然后删除 build 目录重新 configure注意不要在原目录上继续跑configure 失败后的中间状态不可靠。5.2 make 中断在 fatal error: gmp.h No such file or directory现象编译进行到一半报fatal error: gmp.h: No such file or directory同时伴随一堆mpfr.h、mpc.h相关的头文件找不到。原因configure 时用了--with-gmp之类的参数指向系统路径但系统里的开发包没装全或者头文件路径与 GCC 期望的版本不匹配。还有一种情况是用了源码软链接方案但软链接名写错比如起了gmp-6.2.0而不是gmp。解决优先用同级目录软链接方案。具体做法是把三个依赖库的源码解压到和gcc-9.3.0平级的位置然后分别做软链接链接名必须是gmp、mpfr、mpc三个不带版本号的名字GCC 的 configure 默认去找这三个目录。检查无误后重新 configure这一步不再需要--with参数。5.3 装完后 gcc -v 还是 4.8.5 或旧版本号现象make install成功/usr/local/gcc-9.3.0/bin/gcc --version也显示 9.3.0但新开的终端里gcc -v输出的还是旧版本。原因PATH 环境变量里新路径排在旧路径后面或者 bash 缓存了旧命令路径。which gcc能直接告诉你 shell 当前找到的是哪个文件如果输出/usr/bin/gcc问题就出在路径顺序上。解决把export PATH/usr/local/gcc-9.3.0/bin:$PATH写进/etc/profile.d/并确认写法是新路径在最前。如果改了 PATH 还不行执行hash -r清空哈希表再试。验证方式用which gcc确认目标路径不要只看gcc -v因为 -v 输出可能来自被 PATH 命中的旧文件。5.4 程序运行时报 version GLIBCXX_3.4.28 not found现象用新 GCC 编译出来的程序放到本机或另一台机器上运行时报./a.out: /usr/lib64/libstdc.so.6: version GLIBCXX_3.4.28 not found。原因程序编译时链接的是新版 libstdc.so.6但运行时动态链接器加载的是系统自带的旧版。这是 GCC 手动安装最常见的连锁坑——编译阶段用新头文件和新库生成二进制运行阶段却找不到对应的动态库。解决按前面 4.2 节的步骤检查/etc/ld.so.conf.d/gcc-9.3.0.conf是否存在、内容是否正确、是否执行过ldconfig。用ldd ./a.out | grep libstdc看程序实际加载的库路径确认它指向/usr/local/gcc-9.3.0/lib64。如果是临时的快速验证也可以用LD_LIBRARY_PATH/usr/local/gcc-9.3.0/lib64 ./a.out先跑起来但长久方案一定是写 ld.so.conf.d。5.5 磁盘空间不足导致 make 中断在编译中段现象编译进行到大约三分之二的位置日志里没有任何 error但 make 进程被杀死终端提示No space left on device。原因GCC 的 build 目录在中途会占掉 8G 以上磁盘空间bootstrap 模式更翻倍。很多人习惯把 build 目录放在 /root 或 /home 下这两个分区往往没留够空间或者根分区本身就不大。解决编译前先df -h看一眼分区可用空间确保 build 所在分区至少有 15G 空间。空间紧张就把 build 目录放到空间大的分区configure 时进入那个目录执行。如果只是想快速看一下新版 GCC 能否用可以用make -j2 bootstrap-lean减少中间产物体积但正经安装还是建议留足空间跑完整 bootstrap。提示以上五条基本覆盖了 gcc 9.3.0 从 configure 到运行验证的绝大多数失败场景。遇到问题时先看日志再对照本条目的「现象 → 原因 → 解决」逐项排查不要盲目重跑 configure。6. 验证安装并让新版编译器日常生效一个可抄的收尾脚本装完编译器不算完我习惯用一个脚本做整链路验证从gcc -v确认版本到编译一个带 C17 特性的小程序再到确认动态库加载无误全部通过才算这台机器上的 GCC 9.3.0 真正可用。#!/bin/bash # verify-gcc-9.3.0.sh 安装后的完整验证脚本 echo 1. 检查编译器版本 /usr/local/gcc-9.3.0/bin/gcc -v 21 | grep gcc version echo 2. 检查 gcc 实际路径 which gcc echo 3. 编译 C17 的 std::filesystem 测试程序 cat /tmp/test_fs.cpp EOF #include filesystem #include iostream int main() { std::filesystem::path p(/tmp); std::cout exists: std::filesystem::exists(p) std::endl; return 0; } EOF /usr/local/gcc-9.3.0/bin/g -stdc17 /tmp/test_fs.cpp -o /tmp/test_fs /tmp/test_fs echo 4. 检查动态库指向 ldd /tmp/test_fs | grep libstdc手动安装 GCC 后我吃过不少亏现在养成的习惯是configure.log、build.log、install.log 三个日志文件和这段验证脚本一起留在 /root 下下次升级 GCC 版本时直接对照上次的 configure 参数diff 一下就知道自己改了什么。最重要的是永远保留系统自带的 GCC新版走 PATH 前缀的方式共存编译项目时缺哪个版本就临时把 PATH 顺序换一下互不干扰。这套流程我已经在 CentOS 7、Ubuntu 和几个国产 Linux 发行版上各跑过一遍坑基本都在这篇文章里了希望帮到你。本文还有配套的精品资源点击获取
返回列表