明朗北街七万号·数研工坊|扎根雄安新区中关村科技园,专注受限环境下软件搭建与数据平台落地
适用场景#
如果你属于以下任一种情况,这篇对你有用:
- 内网环境需要编译 C/C++ 源码,但系统自带的 gcc 版本太低
- 需要在新版本编译器下编译大数据组件(如 ClickHouse、DuckDB、部分机器学习库)
- 系统自带的 yum 源里找不到新版 gcc(第 3 篇镜像源里只有基础包)
- 需要交叉编译 ARM 架构的软件(飞腾、鲲鹏平台)
应用范围: 一切需要从源码编译的场景。很多开源软件的官方文档要求 gcc 9+,而内网系统自带的多是 gcc 4.8(CentOS 7 经典问题)或 gcc 8.x(openEuler)。编译新版 GCC 是绕不开的一步。
一、问题#
内网环境,需要编译一个依赖新特性的 C++ 库,但:
gcc --version
# gcc (GCC) 4.8.5 ← CentOS 7 标配plaintext代码一编译就报错:
error: 'std::filesystem' has not been declaredplaintext需要 gcc 9+。yum 源里没有(第 3 篇说过,ISO 里的包是固定的)。怎么办?——从源码编译 GCC。
二、约束#
- 无公网,无法直接下载
- 编译 GCC 需要前置依赖(GMP、MPFR、MPC 三个库),它们不在 ISO 里
- 编译 GCC 耗时较长(1-3 小时,取决于机器性能)
- 编译失败排查难度大
三、准备工作:在联网机器上打包依赖#
3.1 获取源码包#
在有外网的机器上下载以下源码包:
# GCC 源码(以 9.3.0 为例)
wget https://mirrors.aliyun.com/gnu/gcc/gcc-9.3.0/gcc-9.3.0.tar.gz
# GCC 依赖的三个库(GMP、MPFR、MPC)
wget https://mirrors.aliyun.com/gnu/gmp/gmp-6.1.2.tar.bz2
wget https://mirrors.aliyun.com/gnu/mpfr/mpfr-4.0.2.tar.bz2
wget https://mirrors.aliyun.com/gnu/mpc/mpc-1.1.0.tar.gzplaintext3.2 国内镜像源#
上面用的是阿里云镜像。其他选择:
- 清华 TUNA:
https://mirrors.tuna.tsinghua.edu.cn/gnu/gcc/ - 中科大 USTC:
https://mirrors.ustc.edu.cn/gnu/gcc/
3.3 打包上传#
tar czf gcc-offline.tar.gz gcc-9.3.0.tar.gz gmp-6.1.2.tar.bz2 mpfr-4.0.2.tar.bz2 mpc-1.1.0.tar.gz
# 传到内网服务器(用第 2 篇的 rsync/scp)plaintext四、内网编译#
4.1 解压#
tar xzf gcc-offline.tar.gz
cd gcc-9.3.0plaintext4.2 一键下载依赖?——不行#
GCC 源码目录里有个 contrib/download_prerequisites 脚本,它会自动下载 GMP/MPFR/MPC。但在内网环境用不了(它从外网下载)。
替代方案:手动把三个依赖包放进源码目录,让编译系统自动识别:
# 把三个依赖包复制到 gcc 源码目录
cp ../gmp-6.1.2.tar.bz2 ./
cp ../mpfr-4.0.2.tar.bz2 ./
cp ../mpc-1.1.0.tar.gz ./
# 解压并创建软链接(GCC 编译脚本会按名字找)
tar xjf gmp-6.1.2.tar.bz2
tar xjf mpfr-4.0.2.tar.bz2
tar xzf mpc-1.1.0.tar.gz
ln -sf gmp-6.1.2 gmp
ln -sf mpfr-4.0.2 mpfr
ln -sf mpc-1.1.0 mpcplaintext关键点:GCC 源码根目录下的 build 脚本会检测
gmp/、mpfr/、mpc/这三个软链接目录,存在就跳过下载。
4.3 创建独立编译目录#
不要直接在源码目录里 make,这是 GCC 编译的经典规范:
mkdir build && cd buildplaintext4.4 配置编译参数#
../configure \
--prefix=/usr/local/gcc-9.3.0 \
--enable-languages=c,c++ \
--disable-multilib \
--disable-bootstrapplaintext参数说明:
| 参数 | 作用 | 建议 |
|---|---|---|
--prefix | 安装路径 | 装到独立目录,方便多版本共存 |
--enable-languages=c,c++ | 只要 C/C++ | 数据平台场景够用,别全开 |
--disable-multilib | 不编译多架构库 | 省一半编译时间 |
--disable-bootstrap | 不用三步自举编译 | 大幅缩短编译时间(首次编译没必要) |
⚠️ 如果嫌编译慢,
--disable-bootstrap是最大的省时开关。三步 bootstrap 会让编译时间翻倍甚至三倍,首次编译完全没必要。
4.5 编译安装#
make -j$(nproc)
# -j 用满所有核,nproc 返回 CPU 核数plaintext编译耗时取决于机器:8 核机器大约 40-60 分钟,4 核要 1.5-2 小时。
make installplaintext4.6 验证#
/usr/local/gcc-9.3.0/bin/gcc --version
# gcc (GCC) 9.3.0plaintext写个简单的 C++17 测试:
cat > test.cpp << 'EOF'
#include <iostream>
#include <filesystem>
int main() {
std::cout << "GCC OK: " << std::filesystem::current_path() << std::endl;
return 0;
}
EOF
/usr/local/gcc-9.3.0/bin/g++ -std=c++17 test.cpp -o test && ./testplaintext能输出路径就说明 std::filesystem 可用,编译成功。
五、让系统默认使用新 GCC#
编译完只是第一步,要让后续编译命令默认用新版:
# 加入 PATH(写入 /etc/profile.d/gcc.sh)
cat > /etc/profile.d/gcc.sh << 'EOF'
export PATH=/usr/local/gcc-9.3.0/bin:$PATH
export LD_LIBRARY_PATH=/usr/local/gcc-9.3.0/lib64:$LD_LIBRARY_PATH
EOF
source /etc/profile.d/gcc.sh
gcc --version
# 现在默认就是 9.3.0plaintext六、踩坑记录#
坑 1:编译报 cannot find -lgmp#
依赖库没被识别。确认 gmp/、mpfr/、mpc/ 软链接在 GCC 源码根目录下,且在 build 目录配置前建立。
坑 2:make 卡在某一步特别久#
GCC 编译 libstdc++ 时会有一次比较久的过程,属正常。如果超过 30 分钟无输出,检查 make -j 的核数是不是超过了实际核数导致内存溢出(-j$(nproc) 一般没问题,但如果是虚拟机建议 -j2)。
坑 3:编译期内存不足#
make -j8 在 4G 内存的机器上容易 OOM。降核数:make -j2。或者配置时加 --disable-libsanitizer 减少内存占用。
坑 4:装完 gcc 却找不到 g++#
检查 configure 是否带了 --enable-languages=c,c++。只写 c 就不会编 g++。
坑 5:磁盘空间不足#
GCC 源码 + build 目录 + 安装结果,总共需要约 6-8GB。提前 df -h 确认。
七、总结#
离线编译 GCC 的完整流程:
外网下载源码+依赖 → 打包 → 上传内网
→ 解压+软链接依赖 → 建 build 目录 → configure → make → make install
→ 配置 PATH → 验证编译plaintext核心就三个字:依赖全、别图快、验证过。
| 环节 | 关键动作 |
|---|---|
| 依赖 | GMP/MPFR/MPC 必须手动放进源码目录并建软链接 |
| 编译 | 独立 build 目录 + --disable-bootstrap 省时间 |
| 安装 | 独立 prefix,方便多版本共存 |
| 验证 | 编译一个实际用的 C++17 程序,别只看 gcc —version |
本文首发于掘金 · 作者:七万号 扎根雄安新区中关村科技园,专注受限环境下软件搭建与数据平台落地