七万号·数据平台实战手记

Back

明朗北街七万号·数研工坊|扎根雄安新区中关村科技园,专注受限环境下软件搭建与数据平台落地


适用场景#

如果你属于以下任一种情况,这篇对你有用:

  • 内网环境需要编译 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 declared
plaintext

需要 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.gz
plaintext

3.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.0
plaintext

4.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 mpc
plaintext

关键点:GCC 源码根目录下的 build 脚本会检测 gmp/mpfr/mpc/ 这三个软链接目录,存在就跳过下载。

4.3 创建独立编译目录#

不要直接在源码目录里 make,这是 GCC 编译的经典规范:

mkdir build && cd build
plaintext

4.4 配置编译参数#

../configure \
    --prefix=/usr/local/gcc-9.3.0 \
    --enable-languages=c,c++ \
    --disable-multilib \
    --disable-bootstrap
plaintext

参数说明:

参数作用建议
--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 install
plaintext

4.6 验证#

/usr/local/gcc-9.3.0/bin/gcc --version
# gcc (GCC) 9.3.0
plaintext

写个简单的 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 && ./test
plaintext

能输出路径就说明 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.0
plaintext

六、踩坑记录#

坑 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

本文首发于掘金 · 作者:七万号 扎根雄安新区中关村科技园,专注受限环境下软件搭建与数据平台落地

离线编译 GCC——一个看似简单实则劝退的操作
https://realcpf.tech/blog/airgapped-gcc-build
Author 刘佳成
Published at 2026年8月1日