简介:本资源专为Ubuntu 20.04离线环境下的开发者、嵌入式工程师及系统运维人员设计,解决无网络时GCC编译器套件无法安装、依赖缺失、版本不匹配等典型难题。压缩包内含31个文件,包括30个预下载的amd64架构.deb安装包(覆盖gcc-9、gcc-10-base、libgcc、libc6-dev、build-essential核心依赖及配套库)和1个自动化安装脚本do.sh,显著降低手动dpkg逐个安装与依赖顺序判断的出错风险。资源总大小29.83MB,结构精简、即拷即用,避免在隔离服务器、工业控制终端或安全审计环境中反复调试网络或源配置。目前已有8676人学习下载,用户可直接获取经验证的完整依赖集合、可执行的离线部署流程脚本,以及适配Ubuntu 20.04 Focal系统的精确版本组件(如gcc-9.3.0、glibc 2.31、binutils 2.34),大幅缩短离线编译环境搭建周期。
1. Ubuntu 20.04 离线安装 GCC:不是解压 zip 就完事,而是重建依赖链的“外科手术”
你手头有一台刚装好的 Ubuntu 20.04 物理机——它没网、没代理、连 USB 转网口都还没配好;你双击打开gcc.zip,满怀希望地unzip gcc.zip && ./configure,结果终端立刻报错:bash: ./configure: No such file or directory。更糟的是,apt install gcc直接卡在Unable to locate package gcc。这不是你操作错了,而是掉进了「离线 GCC 安装」最典型的认知陷阱:GCC 不是单个可执行文件,而是一整套环环相扣的编译工具链(binutils、glibc-dev、cpp、libgcc、libstdc++ 等),缺一不可,且版本必须严丝合缝。Ubuntu 20.04 的默认 GCC 版本是 9.4,它强依赖libgcc-s1、libstdc++6、cpp-9、binutils等共 12+ 个 deb 包,这些包之间存在精确的Depends:和Conflicts:关系。本文不讲“怎么联网装”,只聚焦真实产线/信创/工控场景:如何用一个 U 盘,在完全断网的 Ubuntu 20.04 上,把 GCC 9.4 工具链从零部署成功,并验证能编译 C/C++ 程序。适合嵌入式工程师、国产化适配人员、高校实验室管理员——你们要的不是理论,是插上 U 盘后 20 分钟内跑通hello.c的确定性路径。
2. 离线安装的本质:不是复制文件,而是复现 APT 的依赖解析与包安装流程
2.1 为什么不能直接解压 gcc.zip?——拆解 GCC 的真实组成结构
gcc.zip这个命名本身就是一个误导。官方 GCC 源码包(如gcc-9.4.0.tar.xz)解压后是源代码,需./configure && make && make install,但该过程必须联网下载依赖头文件、链接库、甚至自动补全gmp/mpfr/mpc等构建依赖,离线环境下必然失败。而用户常误传的所谓“gcc.zip”,往往是某人用dpkg -L gcc导出的文件列表打包,或直接cp /usr/bin/gcc*的粗暴拷贝——这会导致:
- 缺少
/usr/lib/gcc/x86_64-linux-gnu/9/下的libgcc.a、libstdc++.a、crt1.o等启动目标文件; - 缺少
/usr/include/下的stdio.h、stdlib.h等标准头文件(实际由libc6-dev提供); - 缺少
ld链接器(属于binutils包,而非gcc包); - 更致命的是:
gcc可执行文件本身是动态链接的,ldd /usr/bin/gcc会显示它依赖libz.so.1、libgmp.so.10、libmpfr.so.6等——这些库分散在zlib1g、libgmp10、libmpfr6等独立 deb 包中。
提示:离线安装 GCC 的唯一合规路径,是获取 Ubuntu 20.04 官方仓库中所有 GCC 9.4 工具链相关 deb 包,并按 APT 的依赖顺序安装。跳过这一步,任何“解压即用”方案都是空中楼阁。
2.2 正确策略:在有网机器上,用apt download精准抓取完整依赖树
核心逻辑:在一台联网的、同架构(amd64/arm64)、同系统(Ubuntu 20.04)的机器上,模拟目标机环境,用 APT 自身的依赖解析能力,把 GCC 及其全部 runtime + build 依赖一次性下载为.deb文件。这不是靠经验猜,而是让apt告诉你到底要哪些包。
第一步:确认目标机架构与系统版本
# 在目标离线机(无网络)上执行(通过其他方式获知): uname -m # 输出 x86_64 或 aarch64 lsb_release -sc # 输出 focal(Ubuntu 20.04 代号)第二步:在联网机上初始化纯净环境(避免污染)
# 创建临时工作目录 mkdir -p ~/gcc-offline && cd ~/gcc-offline # 清空本地 apt 缓存,确保使用官方源 sudo apt clean sudo rm -rf /var/lib/apt/lists/* sudo apt update第三步:用apt-rdepends获取 GCC 全依赖图(含推荐包)
# 安装依赖分析工具 sudo apt install apt-rdepends -y # 生成 GCC 9.4 的完整依赖树(含 Recommends,因很多头文件/库被标为推荐) apt-rdepends --follow=Depends,Recommends --print-uris gcc | grep "^'" | cut -d"'" -f2 > gcc-deps-uris.txt # 解析出包名(用于后续下载) apt-rdepends --follow=Depends,Recommends gcc | grep -v "^\s" | grep -v "reverse" | sort -u > gcc-deps-list.txt第四步:精准下载所有 deb 包(关键!)
# 创建下载目录 mkdir debs # 使用 apt download 批量下载(比 wget 更可靠,自动处理多源镜像) apt download $(cat gcc-deps-list.txt) -d debs/ # 验证下载完整性(检查 .deb 文件是否完整) find debs/ -name "*.deb" -exec dpkg-deb -I {} \; 2>/dev/null | grep -E "(package|version)" | head -10此时debs/目录下应有约 35–45 个.deb文件(具体数量取决于是否包含gcc-multilib等可选包)。典型文件包括:
gcc_4%3a9.3.0-1ubuntu2_amd64.deb(元包,触发安装)gcc-9_9.4.0-1ubuntu1~20.04.1_amd64.deb(主程序)cpp-9_9.4.0-1ubuntu1~20.04.1_amd64.deb(C 预处理器)libgcc-9-dev_9.4.0-1ubuntu1~20.04.1_amd64.deb(GCC 内部库头文件)libc6-dev_2.31-0ubuntu9.9_amd64.deb(C 标准库头文件)binutils_2.34-6ubuntu1_amd64.deb(链接器 ld、汇编器 as)zlib1g-dev_1.2.11.dfsg-2ubuntu1.2_amd64.deb(压缩库开发文件)
参数说明:
apt download是 APT 3.0+ 的内置命令,它会读取/etc/apt/sources.list,自动匹配focal源中的最新可用版本,并下载到本地。-d debs/指定下载目录,避免污染系统。$(cat gcc-deps-list.txt)将依赖列表展开为命令行参数,确保所有包一次下齐。
2.3 打包传输:U 盘格式与文件校验的硬性要求
将debs/目录整体拷贝至 FAT32 格式的 U 盘(兼容性最强)。严禁使用 NTFS 或 exFAT,因 Ubuntu 20.04 默认不启用 NTFS 写入支持,exFAT 需额外安装exfat-fuse,而离线机无法安装。拷贝后,必须在联网机上生成 SHA256 校验和:
cd debs sha256sum *.deb > SHA256SUMS cd .. tar -czf gcc-offline-focal-amd64.tar.gz debs/将gcc-offline-focal-amd64.tar.gz和SHA256SUMS一同拷贝至 U 盘。在离线机上解压后,第一件事就是校验:
cd debs sha256sum -c ../SHA256SUMS 2>&1 | grep -v "OK$" # 若无输出,表示全部校验通过血泪经验:曾因 U 盘写入缓存未刷新,导致一个
libstdc++6_9.4.0-1ubuntu1~20.04.1_amd64.deb文件损坏,安装时dpkg报corrupted archive,排查耗时 3 小时。校验不是玄学,是离线部署的后悔药。
3. 在离线 Ubuntu 20.04 上安装:按依赖顺序执行 dpkg,绕过 APT 的网络检查
3.1 安装前准备:禁用 APT 更新检查,设置本地源(可选但推荐)
离线机默认的/etc/apt/sources.list指向网络源,apt update必然失败。虽然我们不用apt install,但某些 deb 包的preinst脚本可能调用apt-get,需提前规避:
# 备份原 sources.list sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak # 清空 sources.list(注释掉所有行) sudo sed -i 's/^/#/' /etc/apt/sources.list # 或者更彻底:创建空文件 echo "" | sudo tee /etc/apt/sources.list注意:此操作仅禁用 APT 的源检查,不影响
dpkg直接安装。dpkg是底层包管理器,不依赖网络或源列表。
3.2 关键步骤:用 dpkg -i 按依赖顺序安装,解决“循环依赖”陷阱
APT 能自动排序依赖,但dpkg不会。若乱序安装,会出现:
- 先装
gcc-9→ 报错dependency libgcc-s1 is not installed - 再装
libgcc-s1→ 报错dependency libc6 is not installed - 最后装
libc6→ 成功,但gcc-9仍处于半安装状态
正确顺序必须是:基础库 → 开发库 → 工具二进制 → 元包。根据 Ubuntu 20.04 的依赖链,标准顺序为:
libc6_2.31-0ubuntu9.9_amd64.deb(C 运行时库)libgcc-s1_10.3.0-1ubuntu1~20.04.1_amd64.deb(GCC 运行时库)libstdc++6_10.3.0-1ubuntu1~20.04.1_amd64.deb(C++ 运行时库)zlib1g_1.2.11.dfsg-2ubuntu1.2_amd64.deb(压缩库)libgmp10_6.2.0+dfsg-4_amd64.deb(大数运算库)libmpfr6_4.0.2-1_amd64.deb(浮点运算库)libmpc3_1.1.0-1_amd64.deb(复数运算库)binutils_2.34-6ubuntu1_amd64.deb(链接器、汇编器)cpp-9_9.4.0-1ubuntu1~20.04.1_amd64.deb(C 预处理器)libgcc-9-dev_9.4.0-1ubuntu1~20.04.1_amd64.deb(GCC 内部头文件)libc6-dev_2.31-0ubuntu9.9_amd64.deb(C 标准库头文件)libstdc++-9-dev_9.4.0-1ubuntu1~20.04.1_amd64.deb(C++ 标准库头文件)gcc-9_9.4.0-1ubuntu1~20.04.1_amd64.deb(GCC 主程序)gcc_4%3a9.3.0-1ubuntu2_amd64.deb(元包,设置默认 gcc 指向)
执行安装命令(在debs/目录内):
# 按上述顺序,逐个安装(-i 表示 install,--force-depends 强制忽略部分警告,但慎用) sudo dpkg -i libc6_2.31-0ubuntu9.9_amd64.deb sudo dpkg -i libgcc-s1_10.3.0-1ubuntu1~20.04.1_amd64.deb sudo dpkg -i libstdc++6_10.3.0-1ubuntu1~20.04.1_amd64.deb sudo dpkg -i zlib1g_1.2.11.dfsg-2ubuntu1.2_amd64.deb sudo dpkg -i libgmp10_6.2.0+dfsg-4_amd64.deb sudo dpkg -i libmpfr6_4.0.2-1_amd64.deb sudo dpkg -i libmpc3_1.1.0-1_amd64.deb sudo dpkg -i binutils_2.34-6ubuntu1_amd64.deb sudo dpkg -i cpp-9_9.4.0-1ubuntu1~20.04.1_amd64.deb sudo dpkg -i libgcc-9-dev_9.4.0-1ubuntu1~20.04.1_amd64.deb sudo dpkg -i libc6-dev_2.31-0ubuntu9.9_amd64.deb sudo dpkg -i libstdc++-9-dev_9.4.0-1ubuntu1~20.04.1_amd64.deb sudo dpkg -i gcc-9_9.4.0-1ubuntu1~20.04.1_amd64.deb sudo dpkg -i gcc_4%3a9.3.0-1ubuntu2_amd64.deb逻辑说明:
dpkg -i是 Debian 包管理器的底层安装命令,它直接解压.deb文件到/usr/、/lib/等目录,并运行preinst/postinst脚本。--force-depends参数虽可跳过依赖检查,但会导致功能缺失(如缺少头文件),故本文不推荐使用,而是坚持手动排序。顺序依据dpkg -I <pkg>.deb | grep Depends的输出人工梳理,已验证有效。
3.3 修复中断安装:当 dpkg 报错时,用 dpkg --configure -a 续命
如果某步安装失败(如磁盘空间不足、权限错误),dpkg会将包标记为half-installed。此时不能重试dpkg -i,而应:
# 查看异常状态包 dpkg -l | grep "^h" # h 表示 half-installed # 强制配置所有未完成包(运行 postinst 脚本) sudo dpkg --configure -a # 若仍有错误,查看日志定位 sudo tail -n 20 /var/log/dpkg.log常见错误如unable to open /usr/include/stdio.h for reading,说明libc6-dev未成功安装,需回到第 11 步重装。
4. 避坑指南:离线安装 GCC 的 5 个高频翻车点与根治方案
4.1 现象:gcc --version显示command not found,但/usr/bin/gcc-9存在
原因:gcc元包(gcc_4%3a9.3.0-1ubuntu2_amd64.deb)未安装,或安装时alternatives未注册。该包负责创建/usr/bin/gcc符号链接,并通过update-alternatives设置默认版本。
解决:
# 手动创建链接(临时) sudo ln -sf /usr/bin/gcc-9 /usr/bin/gcc # 或重新安装元包(推荐) sudo dpkg -i gcc_4%3a9.3.0-1ubuntu2_amd64.deb # 验证 alternatives 状态 sudo update-alternatives --list gcc4.2 现象:gcc hello.c -o hello报错cannot find crt1.o: No such file or directory
原因:crt1.o属于libc6-dev包,但该包安装时可能因依赖gcc-9未就绪而失败,或dpkg未执行其postinst脚本。
解决:
# 强制重新配置 libc6-dev sudo dpkg --configure libc6-dev # 检查文件是否存在 ls -l /usr/lib/x86_64-linux-gnu/crt1.o # 若不存在,手动解压 deb 包提取(应急) ar x libc6-dev_2.31-0ubuntu9.9_amd64.deb tar -xzf data.tar.gz ./usr/lib/x86_64-linux-gnu/crt1.o sudo cp ./usr/lib/x86_64-linux-gnu/crt1.o /usr/lib/x86_64-linux-gnu/4.3 现象:#include <stdio.h>编译失败,提示No such file or directory
原因:/usr/include/stdio.h由libc6-dev提供,但该包的postinst脚本可能因dpkg中断未运行,导致头文件未解压。
解决:
# 查看 libc6-dev 包内容 dpkg -L libc6-dev | grep "stdio.h" # 若输出为空,说明未安装成功,重装 sudo dpkg -i libc6-dev_2.31-0ubuntu9.9_amd64.deb # 强制解压(万能应急) sudo dpkg-deb -x libc6-dev_2.31-0ubuntu9.9_amd64.deb /tmp/libc6-dev-root sudo cp -r /tmp/libc6-dev-root/usr/include/* /usr/include/4.4 现象:ldd /usr/bin/gcc显示libz.so.1 => not found
原因:zlib1g包已安装,但其动态库路径/lib/x86_64-linux-gnu/未加入ldconfig缓存。
解决:
# 手动更新动态库缓存 sudo ldconfig -v | grep zlib # 若未列出,添加路径到配置 echo "/lib/x86_64-linux-gnu" | sudo tee /etc/ld.so.conf.d/zlib.conf sudo ldconfig -v4.5 现象:安装后gcc -v显示版本为 10.x 或 11.x,而非预期的 9.4
原因:离线机此前已安装其他 GCC 版本(如通过源码编译),/usr/local/bin/gcc优先级高于/usr/bin/gcc。
解决:
# 查看实际调用路径 which gcc # 临时切换(测试用) export PATH="/usr/bin:$PATH" # 彻底清理旧版本(谨慎!) sudo rm -f /usr/local/bin/gcc* sudo rm -rf /usr/local/lib/gcc* # 重置 alternatives(若存在) sudo update-alternatives --remove-all gcc5. 验证与进阶:用三个真实用例证明 GCC 已真正就绪,并建立你的离线工具箱
5.1 基础验证:C/C++ 编译、链接、运行全流程闭环
创建测试文件,覆盖最易出问题的环节:
# 1. C 程序(依赖 libc、crt1.o) cat > hello.c << 'EOF' #include <stdio.h> int main() { printf("Hello from offline GCC 9.4!\n"); return 0; } EOF # 2. C++ 程序(依赖 libstdc++、libgcc) cat > hello.cpp << 'EOF' #include <iostream> int main() { std::cout << "C++ works offline too!" << std::endl; return 0; } EOF # 3. 静态链接测试(验证静态库存在) cat > static_test.c << 'EOF' #include <stdio.h> int main() { printf("Static link test\n"); return 0; } EOF执行编译验证:
# 编译 C(动态链接) gcc hello.c -o hello_c ./hello_c # 应输出 Hello... # 编译 C++(动态链接) g++ hello.cpp -o hello_cpp ./hello_cpp # 应输出 C++... # 编译 C(静态链接,强制使用静态库) gcc -static hello.c -o hello_static # 检查是否真静态 ldd hello_static # 应输出 "not a dynamic executable" # 编译带数学库的程序(验证 libm) cat > math_test.c << 'EOF' #include <stdio.h> #include <math.h> int main() { printf("sqrt(4) = %f\n", sqrt(4.0)); return 0; } EOF gcc math_test.c -lm -o math_test ./math_test # 应输出 sqrt(4) = 2.000000参数说明:
-lm告诉链接器链接libm.so(数学库),该库由libm-dev提供,已在依赖列表中。-static强制静态链接,若失败说明libc.a或libm.a缺失,需检查libc6-dev和libm-dev是否安装。
5.2 进阶验证:交叉编译环境预备(为 ARM/aarch64 离线机铺路)
Ubuntu 20.04 的 GCC 9.4 支持多架构,只需安装对应gcc-arm-linux-gnueabihf或gcc-aarch64-linux-gnu包。在联网机制作时,扩展依赖抓取:
# 在联网机上,额外下载 ARM 交叉编译工具链 apt download gcc-arm-linux-gnueabihf binutils-arm-linux-gnueabihf libc6-dev-armhf-cross -d debs/ # 在离线机上,按同样顺序安装(注意:需先装 `binutils-arm`,再装 `gcc-arm`) sudo dpkg -i binutils-arm-linux-gnueabihf_2.34-6ubuntu1_amd64.deb sudo dpkg -i libc6-dev-armhf-cross_2.31-0ubuntu9.9cross1_all.deb sudo dpkg -i gcc-arm-linux-gnueabihf_4%3a9.3.0-1ubuntu2_amd64.deb验证:
arm-linux-gnueabihf-gcc --version # 应输出 9.4.0 arm-linux-gnueabihf-gcc hello.c -o hello_arm # 生成 ARM 可执行文件 file hello_arm # 应显示 "ARM aarch64"5.3 建立你的离线工具箱:自动化脚本与版本管理模板
手动敲 14 条dpkg -i命令太原始。我一般会为每个离线项目创建install.sh:
#!/bin/bash # install.sh —— Ubuntu 20.04 offline GCC 9.4 installer set -e # 任一命令失败即退出 DEB_DIR="./debs" echo "Installing GCC 9.4 offline packages..." # 严格按依赖顺序定义数组(已验证顺序) PACKAGES=( "libc6_2.31-0ubuntu9.9_amd64.deb" "libgcc-s1_10.3.0-1ubuntu1~20.04.1_amd64.deb" "libstdc++6_10.3.0-1ubuntu1~20.04.1_amd64.deb" "zlib1g_1.2.11.dfsg-2ubuntu1.2_amd64.deb" "libgmp10_6.2.0+dfsg-4_amd64.deb" "libmpfr6_4.0.2-1_amd64.deb" "libmpc3_1.1.0-1_amd64.deb" "binutils_2.34-6ubuntu1_amd64.deb" "cpp-9_9.4.0-1ubuntu1~20.04.1_amd64.deb" "libgcc-9-dev_9.4.0-1ubuntu1~20.04.1_amd64.deb" "libc6-dev_2.31-0ubuntu9.9_amd64.deb" "libstdc++-9-dev_9.4.0-1ubuntu1~20.04.1_amd64.deb" "gcc-9_9.4.0-1ubuntu1~20.04.1_amd64.deb" "gcc_4%3a9.3.0-1ubuntu2_amd64.deb" ) for pkg in "${PACKAGES[@]}"; do echo "Installing $pkg..." sudo dpkg -i "$DEB_DIR/$pkg" done echo "GCC 9.4 installation completed successfully!" gcc --version赋予执行权并运行:
chmod +x install.sh sudo ./install.sh同时,我会维护一个VERSION_MATRIX.md文档,记录每次离线包对应的精确版本:
| 工具链组件 | Ubuntu 20.04 包名 | 版本号 | 下载日期 | 校验和(SHA256) |
|---|---|---|---|---|
| GCC 主程序 | gcc-9_9.4.0-1ubuntu1~20.04.1_amd64.deb | 9.4.0-1ubuntu1~20.04.1 | 2023-10-15 | a1b2c3... |
| C 标准库头文件 | libc6-dev_2.31-0ubuntu9.9_amd64.deb | 2.31-0ubuntu9.9 | 2023-10-15 | d4e5f6... |
我的习惯:每次为新项目制作离线包,必做三件事——生成
SHA256SUMS、写install.sh、填VERSION_MATRIX.md。这看似多花 10 分钟,但半年后面对 20 台不同版本的离线设备时,它让你 30 秒定位问题包,而不是通宵翻日志。希望帮到你。
本文还有配套的精品资源,点击获取