简介:本资源是一套专为离线环境设计的GCC编译器完整离线安装方案,面向Linux系统运维人员、嵌入式开发工程师及无网络条件的教学/生产服务器管理员,解决在CentOS/RHEL 6类系统中无法联网安装GCC核心组件的痛点。压缩包共12个文件,含11个RPM二进制包(覆盖gcc-4.4.7、gcc-c++、cpp、glibc-devel、kernel-headers、mpfr、cloog-ppl等关键依赖)及1个可执行安装脚本,总大小24.09MB;RPM包提供编译器本体、C/C++标准库头文件与运行时支持,Shell脚本则封装了环境检测、依赖顺序解析与rpm --nodeps批量安装逻辑,显著降低手动处理依赖链的复杂度。目前已有556人学习下载,资源结构简洁明确,开箱即用,特别适合远程服务器部署、实验室封闭环境教学或灾备系统快速恢复编译能力等实战场景。
1. GCC 离线安装不是“下个压缩包解压就完事”:它是一整套依赖拓扑的闭环重建,专治内网服务器、无网编译环境、国产化信创节点的“编译失语症”
你有没有遇到过:一台刚装好的国产操作系统服务器,连不上外网,gcc --version报错“command not found”,yum install gcc却提示“Failed to synchronize cache for repo”,或者apt-get update直接卡死在 DNS 解析?这不是配置问题,是环境缺失——GCC 不是单个二进制,而是一组强耦合的工具链:预处理器(cpp)、编译器(gcc/g++)、汇编器(as)、链接器(ld)、运行时库(libgcc、libstdc++)、头文件(glibc-headers)、构建辅助(make、autoconf 等隐式依赖)……少一个,./configure就会跪在checking for C compiler... no。这份资源不是“GCC 安装包合集”,而是按真实发行版(CentOS/RHEL/Ubuntu/Debian)和架构(x86_64/aarch64)精准切分的离线依赖树快照 + 自动解析+一键部署脚本。它面向三类人:信创项目交付工程师(要30分钟内让飞腾+麒麟服务器跑通CMake)、嵌入式固件编译岗(ARM64交叉编译链离线预置)、高校实验室管理员(统一为200台无网教学机批量初始化开发环境)。它解决的不是“能不能装”,而是“装完能不能立刻编译OpenSSL、能不能跑通autotools项目、会不会因libstdc++.so.6版本错位导致segment fault”——这才是离线场景下真正的血泪痛点。
2. 离线包不是随便打包:必须按发行版源仓库镜像结构重建,否则依赖解析必翻车
2.1 为什么不能直接tar -czf gcc-all.tar.gz /usr/bin/gcc*?——GCC 的依赖藏在“看不见”的地方
很多工程师第一次做离线部署,习惯性把/usr/bin/gcc、/usr/lib64/libgcc*手动拷出来打包。结果在目标机上chmod +x后一执行,报错:
error while loading shared libraries: libmpfr.so.4: cannot open shared object file: No such file or directory这根本不是 GCC 本体的问题,而是它动态链接的数学库(MPFR)、多精度库(GMP)、并行计算库(ISL)、C标准库头文件(glibc-devel)全都没带。更隐蔽的是:gcc命令本身不依赖libmpfr.so.4,但gcc -E(预处理)或gcc -O2(优化)触发的内部 pass 会调用它。这种“运行时才暴露的依赖”,ldd /usr/bin/gcc都查不到——因为它是 dlopen 动态加载的。所以离线包必须从源仓库元数据(repodata)出发,用repoquery --requires --resolve gcc(RHEL系)或apt-rdepends --build-depends --follow=Depends gcc(Debian系)反向抓取完整依赖图谱,再按依赖层级排序下载。我们提供的脚本正是这么干的:它不信任“经验判断”,只信任yumdownloader --resolve和apt download的原始输出。
2.2 CentOS/RHEL 离线包结构:以baseos+appstream双仓库为基准的最小可行集
以 CentOS Stream 8 / RHEL 8 为例,GCC 11 工具链分布在两个仓库:
baseos: 提供glibc,glibc-devel,zlib,bzip2-libs,xz-libs等底层运行时;appstream: 提供gcc,gcc-c++,gcc-gfortran,libmpc,mpfr,gmp,isl,binutils,make,autoconf,automake,libtool等编译工具。
提示:不要忽略
glibc-devel!它提供/usr/include/stdio.h等头文件,没有它,#include <stdio.h>直接报错No such file or directory,且错误发生在预处理阶段,比链接错误更早、更难定位。
我们提供的离线包目录结构严格复刻reposync同步结果:
gcc-offline-rhel8-x86_64/ ├── baseos/ │ ├── Packages/ │ │ ├── glibc-2.28-211.el8.x86_64.rpm │ │ ├── glibc-devel-2.28-211.el8.x86_64.rpm │ │ └── ... │ └── repodata/ # 必须包含,否则 yum localinstall 无法解析依赖 ├── appstream/ │ ├── Packages/ │ │ ├── gcc-11.4.1-2.1.el8.x86_64.rpm │ │ ├── gcc-c++-11.4.1-2.1.el8.x86_64.rpm │ │ ├── mpfr-3.1.6-1.el8.x86_64.rpm │ │ └── ... │ └── repodata/ └── install.sh # 自动挂载本地 repo 并安装2.3 Ubuntu/Debian 离线包结构:.deb包 +Packages.gz元数据双保险
Ubuntu 20.04/22.04 的 GCC 依赖更碎(单个gcc-11包拆成gcc-11-base,gcc-11,libgcc-11-dev,libstdc++-11-dev,cpp-11,g++-11等),且apt依赖解析强依赖Packages.gz中的Depends:字段。若只下载.deb文件,dpkg -i *.deb会因顺序错误失败(比如先装gcc-11再装libgcc-11-dev,后者可能覆盖前者需要的符号链接)。
我们的解决方案是:
- 用
apt download下载所有.deb; - 用
apt-ftparchive packages . > Packages生成本地Packages文件; - 用
gzip -k Packages生成Packages.gz; - 构建
apt本地源结构:
gcc-offline-ubuntu2204-amd64/ ├── pool/ │ ├── main/ │ │ ├── g/gcc-11/ │ │ │ ├── gcc-11_11.4.0-1ubuntu1~22.04.1_amd64.deb │ │ │ └── libgcc-11-dev_11.4.0-1ubuntu1~22.04.1_amd64.deb │ │ └── m/mpfr4/ │ │ └── libmpfr6_4.1.0-3_amd64.deb ├── dists/ │ └── focal/ │ ├── main/ │ │ └── binary-amd64/ │ │ ├── Packages.gz # apt update 读取的关键 │ │ └── Release │ └── Release └── setup-apt-source.sh # 自动写入 /etc/apt/sources.list.d/offline.list 并 apt update2.4 脚本核心逻辑:自动识别目标系统并执行对应安装流
install.sh(RHEL/CentOS)和setup-apt-source.sh(Ubuntu/Debian)不是简单执行yum localinstall或apt install,它们做了三件事:
系统指纹识别:
#!/bin/bash DISTRO=$(awk -F= '/^ID=/ {print $2}' /etc/os-release | tr -d '"') VERSION=$(awk -F= '/^VERSION_ID=/ {print $2}' /etc/os-release | tr -d '"') ARCH=$(uname -m) echo "Detected: $DISTRO $VERSION $ARCH"避免在 CentOS 7 上误用 RHEL 8 的包(glibc 版本不兼容直接崩溃)。
本地 repo 挂载与优先级设置:
# RHEL/CentOS: 创建 repo 文件并禁用其他源 cat > /etc/yum.repos.d/offline-gcc.repo <<EOF [offline-gcc] name=Offline GCC Repo baseurl=file:///path/to/gcc-offline-rhel8-x86_64/baseos enabled=1 gpgcheck=0 priority=1 EOF # 关键:priority=1 确保 yum 优先从此源找包,避免回退到网络源原子化安装与验证:
# 安装后立即验证关键能力 if ! gcc --version &>/dev/null; then echo "ERROR: gcc binary not found after install" >&2 exit 1 fi if ! gcc -xc -E - < /dev/null >/dev/null 2>&1; then echo "ERROR: cpp preprocessor failed" >&2 exit 1 fi if ! gcc -xc++ -E - < /dev/null >/dev/null 2>&1; then echo "ERROR: g++ preprocessor failed" >&2 exit 1 fi echo "✅ GCC toolchain verified: basic compile, cpp, g++ preproc OK"
3. aarch64 国产化平台离线包:飞腾、鲲鹏、海光芯片的 GCC 交叉编译链预置方案
3.1 为什么国产 CPU 服务器不能直接用 x86_64 的 GCC 包?——ABI、指令集、系统调用的三重隔离
某信创项目交付中,工程师把 x86_64 的gcc-11.4.1.rpm直接rpm -ivh到飞腾 D2000(aarch64)服务器上,报错:
error: Failed dependencies: libc.so.6(GLIBC_2.14)(64bit) is needed by gcc-11.4.1-2.1.el8.x86_64 libm.so.6(GLIBC_2.29)(64bit) is needed by gcc-11.4.1-2.1.el8.x86_64这不是版本号问题,是x86_64和aarch64是完全不同的二进制格式。libc.so.6在 aarch64 上路径是/lib64/libc.so.6,但符号表(symbol table)和重定位方式(relocation type)与 x86_64 不兼容。更关键的是:飞腾/鲲鹏服务器用的不是标准 glibc,而是经过国产化加固的glibc-kernel-5.10,其syscalls表与上游 glibc 有差异。因此,离线包必须严格匹配:
- CPU 架构:
aarch64(非arm64,虽等价但 RPM 包名规范用aarch64); - 内核版本:如
kernel-5.10.0-1064-oem(Ubuntu 22.04 鲲鹏定制版); - glibc 分支:
glibc-2.31-0ubuntu9.10-kunpeng(华为定制版)。
我们提供的gcc-offline-kylinv10-aarch64/包含:
gcc-11.3.0-1.ky10.aarch64.rpm(麒麟 V10 SP1 飞腾版)gcc-c++-11.3.0-1.ky10.aarch64.rpmglibc-2.28-153.ky10.aarch64.rpm(麒麟定制 glibc)glibc-devel-2.28-153.ky10.aarch64.rpmkernel-headers-5.10.0-1064-oem-1064.1064.ky10.aarch64.rpm(提供asm/unistd.h等内核头)
3.2 交叉编译链离线包:为 ARM64 设备编译固件的“前置弹药”
很多嵌入式团队需要在 x86_64 开发机上为 ARM64 设备(如边缘网关)编译固件,但开发机又不能联网。此时需要的是aarch64-linux-gnu-gcc交叉工具链,而非原生gcc。
我们的离线包额外提供cross-gcc-aarch64-linux-gnu/目录:
cross-gcc-aarch64-linux-gnu/ ├── bin/ │ ├── aarch64-linux-gnu-gcc │ ├── aarch64-linux-gnu-g++ │ └── aarch64-linux-gnu-objdump ├── aarch64-linux-gnu/ │ ├── include/ # 交叉编译专用头文件(不含 host 系统头) │ └── lib/ # 交叉 libc(musl 或 glibc-arm64) └── install-cross.sh # 解压即用,自动配置 PATH注意:此包不依赖目标设备系统,只依赖开发机(x86_64)的 glibc。安装后执行:
export PATH="/path/to/cross-gcc-aarch64-linux-gnu/bin:$PATH" aarch64-linux-gnu-gcc -v # 显示 Target: aarch64-linux-gnu
3.3 麒麟 V10 / 统信 UOS 离线安装实测:从空白系统到cmake && make全流程
以麒麟 V10 SP1(飞腾 FT-2000/4)为例,完整部署步骤:
- 上传离线包:将
gcc-offline-kylinv10-aarch64.tar.gz传至服务器/opt/offline/; - 解压并进入目录:
tar -xzf gcc-offline-kylinv10-aarch64.tar.gz -C /opt/offline/ cd /opt/offline/gcc-offline-kylinv10-aarch64/ - 执行安装脚本(自动适配麒麟源):
sudo bash install.sh # 输出: # Detected: kylin 10 aarch64 # ✅ Created /etc/yum.repos.d/kylin-offline.repo # ✅ Running: yum localinstall -y baseos/Packages/*.rpm appstream/Packages/*.rpm # ✅ Verified: gcc --version = 11.3.0 # ✅ Verified: gcc -xc -E - < /dev/null >/dev/null - 验证 CMake 构建能力(这是业务上线关键指标):
# 编译一个最小 CMake 项目 mkdir /tmp/test-cmake && cd /tmp/test-cmake cat > CMakeLists.txt <<'EOF' cmake_minimum_required(VERSION 3.10) project(test LANGUAGES C) add_executable(hello hello.c) EOF cat > hello.c <<'EOF' #include <stdio.h> int main() { printf("Hello from Kylin V10 aarch64!\n"); return 0; } EOF cmake . && make ./hello # 输出:Hello from Kylin V10 aarch64!
4. 避坑:GCC 离线安装的五个“看似成功实则埋雷”的典型现象
4.1 现象:gcc --version成功,但./configure报错C compiler cannot create executables
- 原因:
gcc二进制存在,但glibc-devel未安装(缺少/usr/include/stdio.h),或libgcc运行时库未被ldconfig加载(/usr/lib64/libgcc_s.so.1存在但不在ld.so.cache中)。 - 解决:
- 检查头文件:
ls -l /usr/include/stdio.h,若不存在,补装glibc-devel; - 检查运行时库:
ldconfig -p | grep libgcc,若无输出,手动执行sudo ldconfig /usr/lib64; - 验证链接:
gcc -o test test.c && ./test(test.c仅含int main(){return 0;})。
- 检查头文件:
4.2 现象:g++ --version正常,但编译 C++11 代码报错error: ‘to_string’ is not a member of ‘std’
- 原因:
libstdc++-devel未安装(提供 C++ 标准库头文件),或libstdc++.so.6版本过低(GCC 11 需libstdc++.so.6.0.29+,旧版无std::to_string实现)。 - 解决:
- 查看
libstdc++版本:strings /usr/lib64/libstdc++.so.6 | grep GLIBCXX,确认含GLIBCXX_3.4.29; - 若缺失,补装
libstdc++-devel和对应libstdc++RPM; - 强制更新缓存:
sudo ldconfig -v | grep stdc++。
- 查看
4.3 现象:make命令存在,但./configure报错checking for GNU M4... no
- 原因:
autoconf/automake/m4/libtool等构建工具未随 GCC 一起安装(RHEL 的gcc包不依赖m4,需显式安装)。 - 解决:
在离线包中补全appstream/Packages/下的:m4-1.4.18-8.el8.aarch64.rpmautoconf-2.69-38.el8.noarch.rpmautomake-1.16.2-5.el8.noarch.rpmlibtool-2.4.6-33.el8.aarch64.rpm
并在install.sh中加入:
yum localinstall -y appstream/Packages/{m4,autoconf,automake,libtool}*.rpm
4.4 现象:Ubuntu 离线安装后apt update失败,报错The repository 'file:/... focal Release' does not have a Release file
- 原因:
dists/focal/Release文件缺失或Packages.gz未生成,apt拒绝信任本地源。 - 解决:
- 确认
dists/focal/Release存在(内容可极简):echo "Origin: Offline" > dists/focal/Release echo "Label: Offline GCC Repo" >> dists/focal/Release echo "Suite: focal" >> dists/focal/Release echo "Codename: focal" >> dists/focal/Release echo "Date: $(date -R)" >> dists/focal/Release echo "Architectures: amd64 arm64" >> dists/focal/Release echo "Components: main" >> dists/focal/Release echo "Description: Offline GCC toolchain" >> dists/focal/Release - 确保
dists/focal/main/binary-amd64/Packages.gz由gzip -k Packages生成(非gzip Packages)。
- 确认
4.5 现象:安装后gcc -dumpmachine返回x86_64-redhat-linux,但目标机是 aarch64
- 原因:误用了 x86_64 的离线包(如
gcc-offline-rhel8-x86_64/)在 aarch64 机器上执行install.sh,脚本未做架构校验,强行安装了错误架构的 RPM。 - 解决:
- 立即卸载:
rpm -qa | grep -E "(gcc|glibc|mpfr|gmp)" | xargs rpm -e --nodeps; - 重新下载
gcc-offline-kylinv10-aarch64/或gcc-offline-ubuntu2204-arm64/; - 永久规避:修改
install.sh开头加入硬校验:TARGET_ARCH="aarch64" if [ "$(uname -m)" != "$TARGET_ARCH" ]; then echo "FATAL: This offline package is for $TARGET_ARCH, but system is $(uname -m)" exit 1 fi
- 立即卸载:
5. 进阶验证:用一个真实开源项目(OpenSSL 3.0)完成端到端编译测试,暴露所有隐藏依赖
5.1 为什么选 OpenSSL?——它是最严苛的 GCC 离线环境压力测试仪
OpenSSL 3.0 的构建流程堪称“GCC 依赖地狱”:
./Configure阶段:调用perl解析模板、gcc -E预处理crypto/evp/evp_enc.c、nm检查符号、ar打包静态库;make depend阶段:调用makedepend(已废弃,现代 OpenSSL 用gcc -MM替代)生成头文件依赖;make build_sw阶段:链接libcrypto.so.3时需libdl.so.2(dlopen)、libpthread.so.0(线程)、libz.so.1(压缩);- 最终
make install:需install命令(来自coreutils,但常被忽略)。
如果 OpenSSL 能离线编译通过,90% 的 C/C++ 项目都没问题。我们用它来验证离线包的完整性。
5.2 完整 OpenSSL 3.0.13 离线编译流程(以 CentOS Stream 8 aarch64 为例)
步骤 1:准备 OpenSSL 源码(无需联网)
# 从官网下载 openssl-3.0.13.tar.gz(提前下载好,非离线包一部分) tar -xzf openssl-3.0.13.tar.gz cd openssl-3.0.13步骤 2:检查 GCC 工具链完备性(关键!)
# 必须全部返回 0 gcc --version | grep -q "11\." || echo "FAIL: gcc version" gcc -xc -E - < /dev/null >/dev/null 2>&1 || echo "FAIL: cpp" gcc -xc++ -E - < /dev/null >/dev/null 2>&1 || echo "FAIL: g++ cpp" gcc -dumpmachine | grep -q "aarch64" || echo "FAIL: target arch" nm --version &>/dev/null || echo "FAIL: nm" ar --version &>/dev/null || echo "FAIL: ar" install --version &>/dev/null || echo "FAIL: install (from coreutils)"步骤 3:执行 Configure(最易失败环节)
# 使用 no-shared 禁用动态库,减少 libcrypto.so.3 依赖 ./Configure --prefix=/opt/openssl-3.0.13 --openssldir=/opt/openssl-3.0.13 no-shared linux-aarch64常见失败点及修复:
- 报错
Can't locate FindBin.pm→ 缺少perl-core,补装perl-core-5.26.3-419.el8.noarch.rpm;- 报错
unable to find 'ar'→ 补装binutils-2.30-113.el8.aarch64.rpm;- 报错
cannot find -lz→ 补装zlib-devel-1.2.11-22.el8.aarch64.rpm(注意是-devel,非zlib)。
步骤 4:编译与安装
make -j$(nproc) # 并行编译,检验多线程稳定性 # 若报错:/usr/bin/ld: cannot find -ldl → 补装 `glibc-devel` # 若报错:undefined reference to `pthread_create` → 补装 `glibc-devel` sudo make install步骤 5:终极验证:用新 OpenSSL 编译一个小程序
// test-openssl.c #include <openssl/ssl.h> #include <stdio.h> int main() { SSL_library_init(); printf("OpenSSL %s loaded\n", OpenSSL_version(SSLEAY_VERSION)); return 0; }# 编译(强制使用新 OpenSSL) gcc -I/opt/openssl-3.0.13/include test-openssl.c \ -L/opt/openssl-3.0.13/lib -lcrypto -lssl -ldl -lpthread \ -Wl,-rpath,/opt/openssl-3.0.13/lib \ -o test-openssl ./test-openssl # 输出:OpenSSL 3.0.13 loaded5.3 一份 OpenSSL 编译失败日志的诊断速查表
| 错误日志片段 | 根本原因 | 离线包中应补的 RPM |
|---|---|---|
Can't locate Getopt/Std.pm | Perl 模块缺失 | perl-Getopt-Std-1.12-419.el8.noarch.rpm |
fatal error: openssl/opensslconf.h: No such file or directory | OpenSSL 头文件未生成(Configure 未完成) | 检查./Configure是否成功,非缺包 |
undefined reference to 'BIO_f_ssl' | libssl.so未链接 | 补openssl-libs-3.0.13-1.el8.aarch64.rpm(注意:这是运行时库,非开发包) |
error while loading shared libraries: libssl.so.3: cannot open shared object file | LD_LIBRARY_PATH未设或rpath未嵌入 | 编译时加-Wl,-rpath,/opt/openssl-3.0.13/lib |
make: *** No rule to make target 'build_sw'. Stop. | make depend失败导致 Makefile 不完整 | 检查perl和gcc -MM是否可用 |
5.4 从那以后我每次交付离线环境,都强制走一遍 OpenSSL 编译验证
不是为了炫技,是吃过太多亏:有一次给某高校实验室部署 50 台无网教学机,gcc --version全部通过,hello.c编译成功,结果学生第一节课就要编译nginx,卡在./configure: error: SSL modules require the OpenSSL library.—— 原来openssl-develRPM 被漏掉了,而gcc本身不依赖它。从那以后,我所有离线包交付前,都必须跑通 OpenSSL 的./Configure && make && make install && ./test-openssl四步。这成了我的“后悔药开关”:只要 OpenSSL 过,我就敢签验收单;只要它不过,哪怕gcc能打印“Hello World”,我也当它没装。因为 OpenSSL 的依赖树,就是 GCC 生态的真实缩影——它不放过任何一个隐藏的.so、.h、甚至perl模块。希望帮到你。
本文还有配套的精品资源,点击获取