离线安装GCC全攻略:RPM与源码编译避坑指南
简介面向在隔离网络或离线环境中部署GCC的Linux运维工程师与开发者这套离线安装资源将GCC完整编译工具链及其全部依赖打包为可直接安装的RPM集合与自动化脚本解决无网络时无法通过yum安装的难题。压缩包共12个文件包含11个rpm与1个sh脚本覆盖gcc、gcc-c、cpp、glibc-devel、mpfr、cloog-ppl等核心组件其中头文件与依赖库均已齐备整体大小仅24.09MB。安装脚本会先检查系统版本与rpm工具再利用rpm2cpio解压RPM、按依赖顺序安装并自动清理临时文件整个过程无需外网。已有556人浏览学习适合CentOS/RHEL等基于RPM的Linux发行版尤其适用于远程服务器、教育机房等受限网络场景。通过这套资源可以一次获取完整依赖链免去逐一下载RPM的繁复工作显著提升离线部署效率。1. 离线装 GCC难点永远不在 GCC 本身做了几年系统环境搭建GitHub 上随手拉个开源项目来编译本地却报gcc: command not found这种事情碰到的次数两只手数不过来。更麻烦的环境是那些不允许外网访问的服务器Yum 源配了三天三夜都连不上最后只能选择离线安装 GCC。真正的问题在于GCC 不像普通工具那样一个 RPM 包就完事它有一堆依赖包要一起装上那才是让人崩溃的地方。很多人以为离线安装 GCC 就是找个gcc.rpm拷过去rpm -ivh就好结果装到一半发现缺libmpfr.so.4、缺cpp、缺gcc-c然后开始孤独地在网上找依赖包找到一个装一个装完报错再找下一个。这种打地鼠式的安装过程GCC 没装好心态先崩了。这篇笔记讲的就是怎么把 GCC 离线安装需要的所有 RPM 包装齐、怎么用脚本一键处理依赖顺序以及装坏了怎么救回来。适合那些给内网服务器搭编译环境、被 GCC 依赖折磨过的开发者照着操作就能把 C/C 编译环境跑起来。2. 版本选择与环境确认先把最关键的三个点摸清楚2.1 查系统版本和架构这是后面所有步骤的地基拿到一台离线服务器先不要急着找安装包花三分钟确认系统的版本和架构。同样的 GCC 包在 CentOS 7 和 CentOS 8 上完全不通用x86_64 和 aarch64 也不通用版本选错了后面所有动作都是白费。# 查看操作系统版本 cat /etc/redhat-release # 查看内核版本必要时 uname -r # 查看系统架构 uname -m这一步决定了后面在联网机器上下载 RPM 包时该选哪个版本的源、哪个架构的目录。比如cat /etc/redhat-release显示CentOS Linux release 7.9.2009 (Core)那么下载依赖时就要找 el7 的源uname -m返回x86_64就只下载 x86_64 的包千万不要下载 i686 的包来凑数。整个离线安装流程中只要架构和系统版本对不上后边的 rpm 安装阶段就会出现各种奇怪的依赖冲突。2.2 确认 glibc 版本最容易忽略的隐藏依赖GCC 本身不是孤立运行的它编译出来的程序要链接 glibc而 GCC 的运行也依赖 glibc 的某些版本特性。在高版本的 CentOS 8 / Rocky Linux 上装老 GCC通常问题不大但在 CentOS 7 上强行安装从 CentOS 8 仓库里拉下来的高版本 GCC就极大概率会因为 glibc 版本过旧而报GLIBC_2.18 not found之类的错误。# 查看 glibc 版本 ldd --version | head -1常见做法是glibc 版本决定了 GCC 版本的上限。CentOS 7.9 自带的 glibc 是 2.17装 GCC 9.x 或 10.x 问题不大但想从源码编译 GCC 12某些特性就会遇到问题。选择 GCC 版本时先看一下目标服务器上的 glibc 版本这能帮你避开后面五分之一的坑。2.3 选 GCC 版本RPM 方式还是源码编译方式离线安装 GCC 有两种主流路线选择哪种取决于你目标服务器的系统版本和你的耐心。RPM 方式适合系统自带的软件源里能凑齐依赖的场景比如 CentOS 7 装 GCC 4.8.5CentOS 8 装 GCC 8.5.0这些官方源里都有现成的包离线时只需要把依赖包全部下载好按顺序安装即可。源码编译方式适合需要更高版本 GCC 的场景比如在 CentOS 7 上装 GCC 10.3.0就得下载 GCC 源码包然后在有网环境里把 gmp、mpfr、mpc 这三个依赖库的源码也准备好到目标机器上一股脑编译。但源码编译耗时很长一台 2 核 4G 的机器编译 GCC 10 可能需要四五十分钟而且对内存有要求如果内存不够 2G编译过程很容易被 OOM killer 干掉。一般我的做法是系统自带的 GCC 版本满足需求就直接用 RPM 方式省时省力开发项目要求支持 C17 / C20比如要装 GCC 8 以上才能编译的软件那就老老实实走源码编译路线。3. 在有网机器上准备离线安装包把所有依赖一次捞干净3.1 用 yumdownloader 下载依赖包列表准备离线包需要在另一台同版本、同架构、能联网的机器上进行。假设目标服务器是 CentOS 7.9 x86_64那就找一台同样是 CentOS 7.9 x86_64 的联网机器配好 yum 源后执行下面的操作。先安装yumdownloader工具它属于yum-utils包# 在有网机器上安装 yum-utils 工具包 yum install -y yum-utils然后先模拟一次安装把依赖关系弄清楚。yum deplist会列出指定包的依赖关系虽然不一定拿到完整的递归依赖但至少可以让你心里有个底。3.2 用 yumdownloader 配合 --resolve 一次性拉全依赖包yumdownloader的--resolve参数会自动下载所有依赖包这是最省事的方式远比手工查依赖列表再逐个 wget 靠谱。# 创建存放 RPM 的目录 mkdir -p /data/gcc-rpms cd /data/gcc-rpms # 下载 gcc、gcc-c 以及所有依赖不安装 yumdownloader --resolve --destdir/data/gcc-rpms gcc gcc-c make命令执行完以后/data/gcc-rpms目录下会有一堆 RPM 文件包括gcc-4.8.5、gcc-c-4.8.5、libstdc-devel、cpp、glibc-devel、libgomp等。其中make是编译时必需的如果目标机器上连 make 也没有一定要让它一起下载进来。有一个坑要注意yumdownloader --resolve只会下载目标包的依赖但如果 target 包本身已经被安装在当前联网机器上它就不会重复下载。遇到这种情况需要先确认这台机器上确实没有装过 gcc或者在命令里加--downloadonly并配合临时清空本地安装状态否则你会发现下载出来的 RPM 目录里少了一半东西。最保险的检查方式是在下载之后逐个确认 RPM 文件名里是否都带上了版本号并且手动核对目录里是否有libmpc、libmpfr这几个关键库没有的话就得手动补下载# 如果缺 gcc 的核心数学依赖库单独补下载 yumdownloader --destdir/data/gcc-rpms gmp gmp-devel mpfr mpfr-devel libmpc libmpc-devel这几个库是 GCC 源码编译和运行时的数学运算基础RPM 安装方式同样需要它们。3.3 用 createrepo 生成本地 yum 源目录把所有 RPM 下载到服务器后直接把这一堆 RPM 拿去rpm -ivh是可以装的但顺序必须严格正确一旦顺序错了依赖检查就会中断。这里我推荐先在有网机器上把这一堆 RPM 制作成本地 yum 源这样到目标机器上后用yum install就能自动处理依赖顺序彻底告别手动调顺序的苦日子。# 安装 createrepo 工具 yum install -y createrepo # 在 RPM 目录下生成 repodata 元数据 createrepo /data/gcc-rpms执行完后/data/gcc-rpms目录下除了 RPM 文件还会多出一个repodata目录这个目录记录了这个 yum 源里所有包的元数据和依赖关系。之后把这整个目录打包拷贝到离线服务器上通过配置本地 yum 源文件就可以像在线 yum 一样直接安装 GCC 了。3.4 打包拷贝到离线服务器# 打包整个 RPM 目录包含 repodata tar czf gcc-offline-rpms.tar.gz /data/gcc-rpms拷贝 tar 包到离线目标服务器后解压目标服务器上不需要安装 createrepo只需要配置 yum 源指向这个解压出来的目录即可。如果是选择源码编译路线那么在有网机器上下载的是源码包而不是 RPM# GCC 官方源码包按需选 10.3.0 / 9.5.0 等版本 wget https://ftp.gnu.org/gnu/gcc/gcc-10.3.0/gcc-10.3.0.tar.gz # 下载 gcc 自带的依赖库源码包 wget https://ftp.gnu.org/gnu/gmp/gmp-6.2.1.tar.xz wget https://ftp.gnu.org/gnu/mpfr/mpfr-4.1.0.tar.xz wget https://ftp.gnu.org/gnu/mpc/mpc-1.2.1.tar.gz注意GCC 源码包解压后有个contrib/download_prerequisites脚本它会自动帮你下载 gmp、mpfr、mpc 三个依赖库但那是针对联网环境的。离线环境下只能手动把这几个源码包一起拷过去。4. 离线安装实践本地 yum 源方式与源码编译两条路都走通4.1 配置本地 yum 源三步搞定在离线服务器上解压 RPM 包后要做的是配置 yum 源。假设我们把 tar 包解压到了/opt/gcc-rpms# 解压 RPM 包 tar xzf gcc-offline-rpms.tar.gz -C /opt/配置文件写在/etc/yum.repos.d/local.repo[gcc-local] nameGCC Local Repository baseurlfile:///opt/gcc-rpms enabled1 gpgcheck0这里gpgcheck0是必须的因为离线 RPM 包没有经过 GPG 签名校验如果保留gpgcheck1可能会因为找不到签名信息而拒绝安装。另外要注意baseurl必须指向包含repodata的那一层目录。配置完成后先清理 yum 缓存再检查源是否可用yum clean all yum repolist如果输出里出现了gcc-local说明本地源已经生效。4.2 用 yum 自动安装 GCC依赖顺序交给 yum 处理这一步就很简单了直接像在线安装一样执行yum install -y gcc gcc-c makeyum 会扫描/opt/gcc-rpms里的所有 RPM自动识别依赖关系按照依赖顺序安装。整个过程不需要手动指定任何 RPM 包顺序之前用rpm -ivh各种报错的场景彻底消失了。如果是安装完成后想确认 gcc 版本用gcc --version查看应该会得到 4.8.5 之类的系统版本号。4.3 源码编译 GCC配置三步和参数取舍如果目标场景要求 GCC 10 或更高版本RPM 方式就搞不定了这时要走源码编译。先把源码包解压好然后统一编译安装 gmp、mpfr、mpc 三个依赖库。# 创建统一的安装前缀目录方便后面配置环境变量和清理 mkdir -p /usr/local/gcc-10.3.0 # 分别编译三个依赖库指定安装到同样的前缀目录 tar xf gmp-6.2.1.tar.xz cd gmp-6.2.1 ./configure --prefix/usr/local/gcc-10.3.0 make -j4 make install cd .. tar xf mpfr-4.1.0.tar.xz cd mpfr-4.1.0 ./configure --prefix/usr/local/gcc-10.3.0 --with-gmp/usr/local/gcc-10.3.0 make -j4 make install cd .. tar xf mpc-1.2.1.tar.gz cd mpc-1.2.1 ./configure --prefix/usr/local/gcc-10.3.0 --with-gmp/usr/local/gcc-10.3.0 --with-mpfr/usr/local/gcc-10.3.0 make -j4 make install cd ..关于make -j4-j4表示用 4 个并行任务编译理论上能显著缩短编译时间。但这里有个取舍如果目标服务器是 2 核 CPU用-j4反而会拖慢速度甚至把内存吃满一般按核数减一比较合适2 核机器用-j2即可。mpfr 和 mpc 的 configure 必须显式指定依赖库的安装路径不指定的话它们会去/usr/local/lib下找 gmp找不到就报错后退出。依赖库装完后接着编译 GCC 本体tar xf gcc-10.3.0.tar.gz cd gcc-10.3.0 # 创建独立的编译目录GCC 官方推荐不要直接在源码目录里编译 mkdir build cd build # 配置 GCC指定依赖库路径和安装位置 ../configure \ --prefix/usr/local/gcc-10.3.0 \ --with-gmp/usr/local/gcc-10.3.0 \ --with-mpfr/usr/local/gcc-10.3.0 \ --with-mpc/usr/local/gcc-10.3.0 \ --enable-languagesc,c \ --disable-multilib make -j4 make install这里--enable-languagesc,c指定了只编译 C 和 C 编译器如果省略这个参数GCC 默认会把所有支持的语言都编译一遍包括 Fortran、Go 等时间翻倍还不一定用得上。--disable-multilib是告诉 GCC 只生成 64 位版本不生成 32 位兼容库如果没有 32 位需求加上这个参数能省不少编译时间。整个编译过程耗时的确很长。CentOS 7 的 2 核 4G 机器编译 GCC 10普遍要跑四五十分钟中间如果内存不足会被系统直接杀进程。一般做法是编译之前free -h看一眼内存低于 2G 就考虑加 swap。4.4 脚本化整个源码编译过程把上面所有步骤串成一个脚本离线环境下一键执行#!/bin/bash # 一键离线编译安装 GCC 10.3.0 # 适用CentOS 7 x86_64 离线服务器 # 用法先把源码包放到 /opt/gcc-src 下再执行脚本 set -e GCC_VERSION10.3.0 PREFIX/usr/local/gcc-10.3.0 SRC_DIR/opt/gcc-src CPU_NUM$(nproc) # 减去 1 避免把 CPU 完全占满 if [ $CPU_NUM -gt 1 ]; then MAKE_JOBS$((CPU_NUM - 1)) else MAKE_JOBS1 fi mkdir -p $PREFIX cd $SRC_DIR # 解压 gmp mpfr mpc 并编译安装 for pkg in gmp-6.2.1 mpfr-4.1.0 mpc-1.2.1; do tar xf $pkg.tar.* 2/dev/null || true done脚本写到这里有一个细节tar xf $pkg.tar.*这行用了通配符来兼容.tar.xz和.tar.gz两种格式但如果目录里同时存在多个匹配文件tar 可能无法正确处理。更稳妥的做法是用ls拿到具体的文件名再解压或者直接用tar xf时明确指定完整文件名不要偷懒依赖通配符。编译安装三个依赖库后再解压 GCC 源码包并编译安装最后把export PATH/usr/local/gcc-10.3.0/bin:$PATH写入/etc/profile.d/gcc.sh保证新开的 shell 里能直接找到新版 gcc。4.5 环境变量与动态库配置源码编译的 GCC 安装完成后如果不做环境变量配置直接执行gcc --version看到的仍然是系统自带的旧版 gcc。这时候必须显式把新版的路径放到 PATH 前面。# 写入系统环境变量配置 cat /etc/profile.d/gcc.sh EOF export PATH/usr/local/gcc-10.3.0/bin:$PATH export LD_LIBRARY_PATH/usr/local/gcc-10.3.0/lib64:/usr/local/gcc-10.3.0/lib:$LD_LIBRARY_PATH EOF # 立即生效 source /etc/profile.d/gcc.shLD_LIBRARY_PATH很关键。新版 GCC 编译出来的程序运行时需要找到新版 libstdc.so.6如果你不在LD_LIBRARY_PATH里加入新版本 lib 目录编译出来的程序在别的机器上跑会报libstdc.so.6: version GLIBCXX_3.4.26 not found。这个坑非常典型解决方案就是让运行环境能提前找到新版动态库。5. 离线安装避坑指南三个真实的踩坑记录5.1 用 rpm -ivh 手动安装导致依赖地狱现象把下载下来的 RPM 包直接拿到服务器上rpm -ivh gcc-*.rpm结果报错libmpfr.so.4()(64bit) is needed by gcc-...于是手动装 libmpfr装完又报libmpc.so.3()(64bit) is needed by...陷入无限循环。原因RPM 包之间的依赖是链式的rpm -ivh不会自动解析依赖关系只会检查当前系统里是否已经存在依赖项。一次性把几十个 RPM 全塞给 rpm 命令时它虽然会尝试按顺序安装但依赖链一旦出现环状或顺序错误就直接卡死。解决不要跟 rpm 命令的依赖解析硬碰硬。把 RPM 目录配置成本地 yum 源后用yum install gcc一条命令让 yum 自己处理依赖顺序。yum 是基于 RPM 的更高层工具它能根据 rpmdb 的依赖关系计算出合理的安装顺序这是最省心的路径。5.2 源里缺少 gcc-c 导致 C 程序无法编译现象离线安装完 gcc 后C 代码能正常编译可g或者编译.cpp文件时报g: command not found。原因yumdownloader --resolve gcc只下载了gcc包及其依赖而 gcc 包里并不含 GG 属于gcc-c包。gcc-c不是gcc的依赖所以不会被 yumdownloader 自动拉下来。解决下载 RPM 包时命令写成yumdownloader --resolve gcc gcc-c make把 gcc-c 和 make 一起放进列表。同样的道理如果之后要编译 Fortran还要单独下载gcc-gfortran。别指望 gcc 一个包覆盖所有语言这是新手最容易漏掉的地方。5.3 源码编译 GCC 中途被 OOM killer 杀死现象编译 GCC 源码时终端突然输出Killed没有任何错误信息dmesg | tail里看到Out of memory: Kill process。原因GCC 编译过程中尤其是 C 编译器编译自身时内存占用非常恐怖。一台 1G 内存的机器编译 GCC 10稍不注意内存就耗尽系统会强制杀掉最占内存的进程。解决先看内存再决定是否编译。free -h如果 total 少于 2G建议先增加 swapdd if/dev/zero of/swapfile bs1M count4096 mkswap /swapfile swapon /swapfile临时加 4G swap或者干脆换 RPM 安装路线源码编译等升级硬件后再做。5.4 新 GCC 编译出来的程序在旧系统上报 GLIBCXX 版本错误现象在 CentOS 7 上用新编译的 GCC 10 编译了一个程序拷贝到另一台 CentOS 7 机器运行时报./a.out: /usr/lib64/libstdc.so.6: version GLIBCXX_3.4.26 not found。原因新 GCC 编译的程序链接的是新版 libstdc.so.6 里的符号而目标机器的系统库路径里只有旧版本的 libstdc.so.6缺少新符号表所以报错。解决两个办法任选其一。一是静态链接编译时加-static-libstdc -static-libgcc把 C 标准库打进可执行文件二是把新版的libstdc.so.6拷贝到目标机器上用LD_LIBRARY_PATH指向新 lib 目录。第一种方式更干净省得在目标机器上折腾环境。6. 装完怎么验证跑通从版本检查到真实编译实测6.1 验证 GCC 本体安装状态装完 GCC 后第一件事是验证版本号和你预期的是否一致同时确认相关工具链是否都齐了。# 检查 gcc 版本和 g 版本 gcc --version g --version # 检查编译相关的几个核心辅助工具是否就位 whereis make whereis ld whereis as预期输出里 gcc 和 g 的版本号应该完全一致比如都是 10.3.0 或者都是 4.8.5。如果 gcc 有版本而 g 提示找不到命令说明 gcc-c 没有装成功需要回头检查安装过程。然后编译一个最简单的 Hello World 验证基本编译链路# 写一个 3 行的测试代码 cat /tmp/hello.c EOF #include stdio.h int main() { printf(GCC offline install test passed!\n); return 0; } EOF gcc /tmp/hello.c -o /tmp/hello /tmp/hello如果输出GCC offline install test passed!说明编译器本体、汇编器、链接器、C 标准库的头文件路径和动态库路径都配置正确了。这一步能排除 90% 的环境问题。6.2 验证 C 编译能力与标准库运行C 能编译不代表 C 也能编译所以单独再测一次cat /tmp/hello.cpp EOF #include iostream int main() { std::cout C compiler works. std::endl; return 0; } EOF g /tmp/hello.cpp -o /tmp/hello_cpp /tmp/hello_cpp这里有一个值得知道的细节如果/tmp/hello_cpp运行时报libstdc.so.6: version GLIBCXX_3.4.x not found说明新 g 编译出的二进制运行时找到了旧的 libstdc需要回到第 4 章配置LD_LIBRARY_PATH或者用-static-libstdc重新编译。然后再验证一下 GCC 10 的 C17 特性支持情况这是很多人装新 GCC 的真实原因cat /tmp/check_cpp17.cpp EOF #include string_view #include iostream int main() { std::string_view sv(GCC17); std::cout sv std::endl; return 0; } EOF g -stdc17 /tmp/check_cpp17.cpp -o /tmp/check_cpp17 /tmp/check_cpp17能输出GCC17说明 C17 标准库头文件和运行时都具备可以放心交给开发者去编译项目了。从那次把离线 GCC 环境反复装坏又救回来之后我每配置完一套编译环境都会强制自己走一遍这几条验证命令尤其是 C 和 C 分开测、再测一次高版本特性确认没问题才交付出去。一套环境跑不通后面所有基于它的项目都会白白浪费精力提前花三分钟验证省下的是后面一整天的排查时间。希望这篇笔记里的流程和踩坑记录能帮到你少走几段弯路。拿到资料照着装装完跑一遍验证就能确定这套环境能不能收了。本文还有配套的精品资源点击获取