刚拿到一台Kylin初始系统的服务器网络是隔离的内网连yum仓库都连不出去第一个任务就是离线配置g。这事儿听起来像一条命令的事但真正在离线环境里做过的都知道光是“离线”两个字就能把人折腾够呛。我这次把整个过程完整走了一遍从识别系统版本、准备离线包、处理依赖到最后验证编译踩了不少坑也摸出几条高效路径。这篇文章就把完整流程和关键经验写下来给同样在内网机房、离线部署环境里折腾Kylin的人一个可以直接抄作业的参考。1. 先分清Kylin的Debian血统和RPM血统这决定了离线安装姿势1.1 两条命令识别系统的“血统”Kylin V10和普通的CentOS/Ubuntu不太一样市面上常见的是两个大系列。一个是服务器版银河麒麟高级服务器操作系统V10版本号里常带SP1/SP2/SP3软件管理走yum/dnf包后缀是.rpm整体对标RHEL/CentOS生态。另一个是桌面版银河麒麟桌面操作系统V10软件管理走apt/dpkg包后缀是.deb整体对标Debian生态。问题在于这两个系列离线配置g的方法完全不一样网上搜到的教程如果不先看版本直接照搬很容易装到一半就报一堆依赖错误。所以第一步不是找安装包而是确认这台机器到底属于哪套体系。最简单的办法是执行cat /etc/os-release看输出里的 NAME、VERSION、ID字段。出现“Kylin Server”或“Kylin Advanced Server”字样基本走RPM体系出现“Kylin Desktop”大概率走DEB体系。如果还不放心再跑一条which yum || which dnf which apt-get哪个命令存在就用哪套体系。这一步花30秒能省后面1小时。我见过有人拿桌面版的思路去服务器版上搞结果rpm数据库一路报错最后只能重装系统。1.2 别忽略CPU架构aarch64和x86_64不通用确认包管理体系之后还要确认CPU架构uname -mx86_64是Intel/AMD架构aarch64是ARM架构Kylin服务器上常见的飞腾、鲲鹏都属于后者。离线rpm/deb包必须和架构严格匹配否则安装时直接报“架构错误”。很多人踩过这个坑在有网机器上随手下了x86_64的包拷到aarch64的机器上一装就废白白浪费一次传输时间。1.3 为什么不能照搬在线教程在线教程普遍这么写yum install -y gcc-c或者apt-get install -y g。它之所以能一条命令搞定是因为系统里配置了可用的软件源包管理器自动完成依赖解析。离线环境没有可用源yum会立刻报“Could not resolve host”之类的错误。换句话说离线配置g真正要解决的不是“安装”这个动作本身而是把在线时由包管理器自动完成的依赖解析和顺序控制变成手工可控的流程。理解这一点后面看到缺依赖的报错就不会慌。2. 离线安装包从哪来先用好手边的系统ISO再做依赖收集2.1 最省心的方案挂载Kylin安装ISO当临时源我在隔离环境配基础环境第一选择永远是找系统安装镜像。初始系统的机器一般会随机器附带同版本ISO直接挂载进系统看有没有软件仓库目录mkdir -p /mnt/kylin_iso mount -o loop /path/to/kylin.iso /mnt/kylin_iso ls /mnt/kylin_isoRPM系的光盘里通常有 repodata 目录和 Packages 目录。只要能看到 repodata说明ISO本身就是一套完整的离线yum源。顺手检查一下有没有g相关包ls /mnt/kylin_iso/Packages | grep -E gcc|g\\如果有我强烈建议直接用它建本地源而不是手动rpm装。因为ISO里的包跟系统版本配套依赖版本一致性最好几乎不会出现编译时链接库版本不匹配的问题。Debian系的光盘结构是 pool/ 和 dists/同样能当apt源用具体写法在第3章讲。2.2 有网同版本机器上收集依赖RPM系如果没有ISO那就找一台同版本、同架构且能连网的非生产机器在那边把依赖全部下载下来再打包拷过去。RPM系比较标准第一步安装yum-utilsyum install -y yum-utils然后带着依赖解析一起下载yumdownloader --resolve gcc-c --destdir/tmp/kylin_gcc_rpms--resolve参数非常关键它会连带下载gcc、cpp、glibc-devel、libstdc-devel这些间接依赖。下载完直接打包cd /tmp tar czf gcc_rpms.tar.gz kylin_gcc_rpms拷到目标机后解压安装。注意目标机和下载机最好是同一个大版本比如都是Kylin V10 SP2。小版本差异偶尔会导致glibc或libstdc的符号版本对不上装完能编译但运行时可能报找不到GLIBCXX版本类错误。2.3 有网同版本机器上收集依赖Debian系Debian系同样有对应思路。在有网的同版本Kylin桌面机器上执行apt-get install -y --download-only g--download-only会让apt把g及其依赖的deb全部下载到 /var/cache/apt/archives/ 目录。然后ls /var/cache/apt/archives/*.deb mkdir -p /tmp/kylin_gcc_debs cp /var/cache/apt/archives/*.deb /tmp/kylin_gcc_debs/ tar czf gcc_debs.tar.gz /tmp/kylin_gcc_debs拷到目标机后用dpkg -i *.deb安装。如果提示缺依赖再单独补对应的deb。也可以用 apt-rdepends 列出完整依赖树但对于g这种基础包--download-only通常已经够用。2.4 gcc-c的完整依赖链认识一下这几个“老演员”为了后面报错时能看懂先把核心依赖包的职责列出来包名体系作用gcc-c / gRPM / DEBC编译器前端提供g命令gcc两者都有C编译器g工作时调用其内部组件cpp两者都有C/C预处理器负责头文件展开libstdc-devel / libstdc-6-devRPM / DEBC标准库开发包提供iostream头文件和libstdc.so软链glibc-devel / libc6-devRPM / DEB系统C库开发文件提供stdio.h等基础头文件binutils两者都有链接器ld、汇编器as编译链接阶段必须RPM系安装顺序一般照着依赖方向走cpp → glibc-devel → libstdc-devel → gcc → gcc-c。DEB系因为dpkg不强制严格顺序实际操作常是一把dpkg -i *.deb下去缺什么再补什么。把这些包名记住后面报错基本一眼就能定位缺的是谁。3. 核心实操Debian系与RPM系两条安装路径3.1 RPM系手工装按依赖顺序 rpm -ivh如果依赖包已经齐了可以手工安装顺序很重要cd /tmp/kylin_gcc_rpms rpm -ivh cpp-*.rpm glibc-devel-*.rpm libstdc-devel-*.rpm gcc-*.rpm gcc-c-*.rpm这里尽量不要一上来就rpm -ivh *.rpm --nodeps。--nodeps相当于关掉依赖检查短时间看是装上了但有的包在文件层面被强行安装实际内容不完整编译时才会在ld链接阶段炸出“cannot find -lstdc”之类的问题。手工按顺序装的好处是如果缺了哪个包rpm会明确告诉你“xxx is needed by gcc-c”把它补进同一句命令再跑即可。安装完成后验证核心包是否都在rpm -qa | grep -E ^(gcc|g\\) rpm -qa | grep -E ^(libstdc\\-devel|glibc-devel)3.2 RPM系省事法createrepo 建本地仓库再 yum install手工rpm装适合一次性操作但如果你后面还要装make、cmake、openssl-devel等一堆编译依赖我强烈建议直接把离线包做成一个本地yum仓库。先在目标机上装createrepoyum install -y createrepo如果这台机器完全离线连createrepo都没有可以到ISO里找或者在有网机器上把它和依赖一起下载过来。把离线rpm统一放到一个目录例如mkdir -p /opt/kylin_local_repo cp /tmp/kylin_gcc_rpms/*.rpm /opt/kylin_local_repo/生成仓库元数据createrepo /opt/kylin_local_repo然后新建 /etc/yum.repos.d/kylin-local.repo[kylin-local] nameKylin Local Repo baseurlfile:///opt/kylin_local_repo enabled1 gpgcheck0刷新缓存yum clean all yum makecache yum install -y gcc-c此时yum走的就是本地仓库依赖自动解析跟在线环境一样省心。后续再往这个目录塞新的rpm包重新跑一遍createrepo --update /opt/kylin_local_repo就能继续使用算是一劳永逸。3.3 Debian系安装dpkg -i 和本地apt源Debian系的目标机器上把拷贝过来的deb包全部放进一个目录mkdir -p /tmp/kylin_gcc_debs tar xzf gcc_debs.tar.gz -C /tmp cd /tmp/kylin_gcc_debs dpkg -i *.deb如果dpkg提示有依赖未满足一般有两种情况一是部分deb没有下载到二是安装顺序造成的“循环依赖”。前者回到有网机器上补下载后者可以跑dpkg --configure -a或者调整顺序把libstdc6-dev、libc6-dev这类基础包先装再装g。DEB系虽然不如RPM系对顺序敏感但基础包装在前确实更稳。如果你手里有桌面版的ISO也可以直接用file源。先看目标系统的VERSION_CODENAMEgrep VERSION_CODENAME /etc/os-release然后把ISO路径加入apt源echo deb [trustedyes] file:/mnt/kylin_iso codename main universe /etc/apt/sources.list apt-get update apt-get install -y gtrustedyes是让apt信任本地非签名源的必要项不加的话update会拒绝使用该源。4. 装完别急着写代码验证、配PATH、处理三个高频报错4.1 第一个C程序把工具链真正跑起来装完之后先确认编译器版本g --version正常会输出类似 g (Kylin 10) 8.3.1 的信息。然后写个最小程序验证整套流程cat hello.cpp EOF #include iostream int main() { std::cout Hello Kylin std::endl; return 0; } EOF g hello.cpp -o hello ./hello输出 Hello Kylin说明编译器、头文件、标准库、链接器全部正常。这一步不能省因为有些机器g命令能启动但一编译就报错下面这三个坑就是这种“半成功状态”的典型。4.2 报错一fatal error: iostream: No such file or directory这个报错的意思是g可执行文件找到了但找不到C标准库头文件。iostream头文件在RPM系的libstdc-devel包、DEB系的libstdc-6-dev包里提供。排查方法ls /usr/include/c/ | head find /usr/include -name iostream如果目录里没有iostream文件说明开发包没装完整。回到离线包目录找到libstdc-devel开头的rpm或deb包重新安装。还有一种少见情况包装了但路径不在默认搜索范围内可以临时设置export CPLUS_INCLUDE_PATH/usr/include/c/版本号不过正常yum/dpkg安装会自动把路径放对配置环境变量的方案只是兜底。4.3 报错二/usr/bin/ld: cannot find -lstdc编译过了预处理和编译前端但在链接阶段挂了提示找不到-lstdc。这里-lstdc对应的是libstdc.so这个链接器输入文件。系统运行时只有libstdc.so.6动态库本体开发包会额外提供一个不带版本号的软链让链接器找到它ls -l /usr/lib64/libstdc.so*正常情况应该看到/usr/lib64/libstdc.so - libstdc.so.6 /usr/lib64/libstdc.so.6 - libstdc.so.6.0.24如果少了第一条软链就是缺libstdc-devel / libstdc-6-dev补装后一般自动生成。这个报错的本质是开发包和运行包分离导致的理解了这一点以后遇到-lxxx找不到就都知道往对应的-devel包上想。4.4 报错三IDE报 cannot run compiler gQt Creator经典问题这个报错在热搜里经常出现很多人在Qt Creator或VS Code里配置工具链时看到。报错关键词是“cannot run compiler g”或者“could not find a valid executable”。在Kylin上遇到先不要怀疑编译器坏了先查两件事第一系统是否真的装了g第二IDE里填的编译器路径对不对。终端里先跑which g正常会输出/usr/bin/g。然后在Qt Creator中依次打开工具 → 选项 → Kits → 编译器 → 添加 → GCC → CCompiler path填/usr/bin/gABI选系统对应平台。特别注意如果机器是aarch64别把交叉编译的aarch64-linux-gnu-g当本机编译器填进去Kylin桌面自带的Qt套件有时会自动识别出交叉编译链导致编译时找不到系统库。路径确认无误后回到Kits页面把编译器和Qt版本绑到同一套Kit里。改完后先编译一个空项目验证不要直接在业务工程里来回试探。4.5 顺手把PATH和软链理一遍如果which g没有输出说明g的安装位置不在PATH里。用下面命令定位find / -name g -type f 2/dev/null找到后加软链或加PATH。最常用的是软链到/usr/bin下ln -s /usr/bin/g-8 /usr/bin/g如果走的是源码编译GCC新版本g可能在/usr/local/bin/g而系统默认PATH里/usr/bin排在/usr/local/bin前面可能出现系统自带的旧g抢先被调用的情况。这种问题在纯rpm安装方式下遇不到但离线场景下确实有人直接源码编译GCC所以顺带提一下。需要时把/usr/local/bin提到PATH前面即可。5. 把离线环境做成可复用工具包本地源与依赖清单存档5.1 从零建一个可离线复用的本地yum源g装完之后基础环境并没有结束后续大概率还要装make、cmake、boost、openssl-devel等。与其每次离线都现找包不如定义一套固定目录和配置文件。第3章建的/opt/kylin_local_repo就是现成基础我通常的做法是把该机器需要的所有离线rpm按类别分目录如compiler/、libs/、tools/每个目录生成独立repodata或者统一放一个大目录只建一个repodata将整个目录在部门内网共享NFS或HTTP都行其它机器直接配同一个baseurl。共享的repo文件可以这样写[kylin-local] nameKylin Local Repo baseurlfile:///opt/kylin_local_repo # 如果通过NFS挂载直接用挂载后的本地路径 # 如果通过HTTP分发则改成 baseurlhttp://内网服务器ip/kylin_local_repo enabled1 gpgcheck0第二台、第三台机器就都是yum install -y gcc-c一条命令的事跟在线环境几乎一样。这才是离线配置的最终形态不是把某一次安装做完而是把离线软件源搭起来。5.2 Debian系的离线仓库dpkg-scanpackages 生成索引Debian系对应做法也简单。把离线deb放到统一目录例如/opt/kylin_debs然后安装dpkg-devapt-get install -y dpkg-dev cd /opt/kylin_debs dpkg-scanpackages . /dev/null | gzip Packages.gz之后在/etc/apt/sources.list里加deb [trustedyes] file:/opt/kylin_debs ./apt-get update后就能install目录里的deb。这个方案对维护离线Kylin桌面环境很顺手更新依赖时往里丢新deb再重新扫描即可。5.3 记录依赖清单让下一台机器2分钟配完最后分享一个低成本高收益的习惯在配置完成的机器上把关键软件包清单导出存档。RPM系rpm -qa | grep -E ^(gcc|g\\|libstdc\\|glibc-devel|binutils|cpp) /root/kylin_compiler_deps.txtDEB系dpkg -l | grep -E gcc|g\\|libstdc\\|libc6-dev|binutils /root/kylin_compiler_deps.txt这份清单配合/opt/kylin_local_repo目录里的具体rpm/deb文件就是完整的“环境快照”。下次再来一台初始系统对着清单核对、下载、安装基本不会漏东西。我实际配置多台同型号机器时从挂载ISO到g跑通hello.cpp单台耗时能控制在10分钟以内关键就在于把源和清单都固化了。最后再提一句我踩过的坑最开始图省事在离线机上直接rpm -ivh *.rpm --nodeps一把梭表面全装上了结果编译Qt程序时链接阶段逐个报缺库补包补了整整三天。后来老老实实搭本地源、按依赖装反而一次到位。离线配置g这件事真正的难度从来不是“装上”而是“装对”。把依赖链搞清楚、把本地源建好剩下就是机械操作了。