多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

中标麒麟V7.6升级GCC 8.5.0实战:C++17编译与多版本共存

中标麒麟V7.6升级GCC 8.5.0实战:C++17编译与多版本共存 1. 为什么要在中标麒麟V7.6上折腾GCC 8.5.01.1 系统默认工具链的尴尬GCC 4.8.5 到底差在哪中标麒麟高级服务器操作系统V7.6这套底子基于RHEL7体系稳定性、兼容性和国产化适配都做得相当扎实不少单位的内网服务器、业务平台就长期跑在它上面。但它自带的默认编译器一直停在GCC 4.8.5这个版本是2015年前后的产物C标准支持只到C11的一部分C14支持得残缺C17基本别想。很多人第一次在这套系统上编译现代开源组件时会被一个看似莫名其妙的报错卡住——源码里明明写得好好的#include filesystem找不到if constexpr不认识结构化绑定auto [a, b] ...直接报语法错误。问题的根源就在这里语言标准对不上。我给几个具体的门槛线你一看就知道自己撞上的是哪一堵墙。std::make_unique是GCC 4.9才加入的std::optional、std::variant、std::string_view这些C17组件要GCC 7起步std::filesystem在GCC 8才正式进标准库GCC 5到7挂在std::experimental实验命名空间里if constexpr、结构化绑定、内联变量这些语法糖同样卡在GCC 7。你手上如果是一个2020年之后活跃维护的第三方库作者基本默认编译器支持C17那么在4.8.5上就是编译不过没有商量余地。除了C标准还有一层更隐蔽但同样致命的问题编译优化和诊断能力。GCC 8之后对-Wall -Wextra的告警更智能对未定义行为的捕获更细产生的二进制在部分计算密集型场景下性能也有提升。还有一个绕不开的点——某些用新GCC编译出来的第三方预编译库其libstdc.so.6要求更高的GLIBCXX符号版本你用4.8.5去链接会直接报version GLIBCXX_3.4.21 not found。所以很多时候不是你想不想升级而是不升级就没法继续往下走。1.2 什么场景下必须升级什么场景下别乱动升级系统编译器这件事一定要分清楚场景别一上来就干。我把常见的情况分成两类你自己对号入座。必须升级的场景你要编译的第三方组件明确要求GCC 7以上比如近期版本的MySQL、部分AI推理框架、新版的Redis模块、一些C17写成的中间件你需要在服务器上做本地化开发写现代C代码你要编译的某个库依赖链里有一环用了C17特性导致整条链都过不去。这些情况下原地不动是没出路的。建议别动、或者至少别动系统默认编译器的场景系统上的软件包全靠yum管理而你只是偶尔编译一两个小工具这台机器上跑着需要内核模块编译的业务比如某些第三方驱动内核模块和系统GCC版本有强绑定关系你没有足够的磁盘和时间成本编译GCC是一件耗时以小时计、占用好几个G空间的体力活。这里有个关键的判断原则我想强调一下升级GCC不等于替换系统GCC。中标麒麟这类企业级系统/usr/bin/gcc被大量系统组件、yum包管理、内核工具链引用。你一旦把系统默认GCC指向4.8.5以外的东西很可能引发连锁反应轻则yum报错重则系统工具链崩溃。所以正确姿势是新老版本共存把GCC 8.5.0装到独立目录按需切换。这一点在后面的章节里我会专门展开。1.3 升级前必须想清楚的三个取舍动手之前有三个决策先想明白能帮你少走很多弯路。第一要不要自举bootstrap。GCC官方默认启用--enable-bootstrap意思是用刚编出来的GCC再把自己重新编译一遍甚至两遍做交叉验证保证编译器自身没有因为构建环境问题而带病出厂。好处是可靠代价是编译时间差不多翻两到三倍。如果你的目标是生产环境稳定运行我建议保留自举如果只是内网临时验证、赶时间可以--disable-bootstrap省时间但要心里有数这个编译器没经过自校验。第二要不要同时支持32位和多版本ABI。CentOS 7时代默认还留着multilib32位64位双库。但现在绝大多数服务器业务都是纯64位除非你有历史遗留的32位程序要链接否则直接--disable-multilib能省掉大量32位依赖的安装麻烦和编译时间。第三装到哪个目录、用谁来管版本。常见选择是/usr/local/gcc-8.5.0或者/opt/gcc-8.5.0。我偏好/usr/local下带版本号的目录一眼能看出装了什么、装在哪卸载时直接删目录干净利落。至于切换方式是改环境变量还是用alternatives还是靠update-alternatives脚本这个后面细说但一定要提前定好别装完再纠结。把这三个问题想清楚了再往下走能避免那种编译到一半发现方向错了的崩溃体验。下面进入动手环节。2. 升级前的环境勘察与依赖准备2.1 摸清家底系统版本、内核、现有GCC与glibc不管是内网提工单还是自己折腾第一件事永远是先看清这台机器长什么样。很多人跳过这一步直接开编结果编到一半发现是ARM架构、或者glibc版本比预期低前面的时间全白费。下面这几条命令建议你一条条敲过去把结果记下来。# 看系统发行版信息 cat /etc/neokylin-release cat /etc/os-release # 看内核版本 uname -r # 看系统架构x86_64 还是 aarch64 uname -m # 看现有GCC版本 gcc --version g --version # 看glibc版本 ldd --version # 看可用内存和磁盘 free -h df -h /usr/local df -h /tmp # 看CPU核数 nproc对这些输出你要重点关注几个数字。系统架构决定后面编译参数和依赖包的选择x86_64和aarch64的依赖包名、部分configure参数都不一样。glibc版本这块中标麒麟V7.6大致对应glibc 2.17这个版本偏老直接影响了GCC 8.5.0的部分组件能否顺利编译——比如libsanitizer内存/地址检测工具库在老glibc上经常编不过这就是后面configure参数里要预先处理掉的坑。内存和核数直接决定make -j并行度编错了要么慢到怀疑人生要么内存被打爆直接OOM kill。磁盘方面光源码解压加中间产物加安装结果GCC 8.5.0整个流程要吃6到10个G/tmp和/usr/local都得留足空间别到时候写到一半提示No space left on device。顺便提醒一个新版的差异点网上现在大量教程讲的是银河麒麟服务器操作系统V10 SP3在ARM架构上的编译经验那套系统和V7.6并不是同一个世代——V10对应的glibc更新、包管理更接近新平台很多参数不能照搬。你要是搜到V10的经验帖一定要先对照自己的系统版本别混着抄。2.2 编译GCC需要哪些前置依赖GCC本身要顺利编译需要三大数学库GMP大数运算、MPFR多精度浮点、MPC复数运算外加可选的ISL循环优化GCC 8默认会用。这些库如果系统里装的是开发包-devel版本configure阶段能直接识别如果没有就得靠GCC自带的脚本来下载源码一起编译。在中标麒麟上最省事的办法是先把系统自带的高版本开发包装上。但要注意系统仓库里的gmp-devel这类包版本可能偏老达不到GCC 8.5.0要求的门槛。所以我一般走两条路——能联网就用自带的download_prerequisites脚本拉源码不能联网就提前把四个依赖的源码包gmp-6.1.0、mpfr-3.1.4、mpc-1.0.3、isl-0.18下载好拷进去。这套网络隔离的服务器很常见提前准备依赖包是基本素养。基础编译工具链也要补齐# 安装基础开发工具集 yum groupinstall Development Tools -y yum install -y gcc-c make wget bzip2 tar \ gmp-devel mpfr-devel libmpc-devel isl-devel \ zlib-devel # 如果是内网无源至少确保下面这些已在系统里 rpm -qa | grep -E gcc|make|binutils|glibc-devel这里我要单独说一句binutils。GCC的编译和链接依赖ld、as这些工具如果系统binutils版本过老某些新语法或者链接选项可能不支持。中标麒麟V7.6自带的binutils通常够用但要是configure阶段提示链接器相关错误可以考虑一并升级binutils。不过升级binutils比升级GCC更敏感因为系统大量二进制依赖它这块要单独评估除非确有报错否则不动为好。2.3 磁盘、内存与编译参数的预估动手前做个简单估算能避免很多中途翻车的尴尬。GCC 8.5.0源码包解压后大约1G多加上四个依赖库源码、build目录的中间产物整个编译过程轻则6G、重则10G上下。保险起见给/usr/local和/tmp各留10G以上空闲空间。内存这块更微妙。make -jN里的N不是越大越好。GCC编译单个大型源文件比如某些优化pass的代码峰值内存能到几百兆甚至超过1G。经验公式是并行数N不要超过「可用内存GB数 ÷ 2」。比如你有16G内存N取8比较稳32G内存N取8到16都行如果只有4G内存还硬上make -j8大概率在编译后半程被OOM killer干掉报一堆virtual memory exhausted或者进程直接消失那种绝望感我经历过。我的建议第一次编译保守一点用make -j4先跑起来观察内存占用另开一个终端top或者free -h盯着确认有余量再加大。编译时间上8核16G的机器、开自举整条流程大概1.5到3个小时你就当泡杯茶、去干点别的别一直盯着屏幕。纯64位、关自举的话时间能压缩到40分钟到一个多小时。把这一步的账算清楚你后面执行的时候心里就有底了不会因为进度条半天不动而焦虑。3. GCC-8.5.0 编译安装全流程实操3.1 获取源码与依赖拉取脚本假设你已经把gcc-8.5.0.tar.gz和依赖包放到了/opt/src目录下我们一步一步来。mkdir -p /opt/src cd /opt/src # 解压主源码包 tar -xf gcc-8.5.0.tar.gz # 进入源码目录 cd gcc-8.5.0 # 查看自带的依赖拉取脚本 ls contrib/download_prerequisitescontrib/download_prerequisites这个脚本是GCC官方提供的它的作用是自动下载并解压GMP、MPFR、MPC、ISL这几个依赖到源码根目录configure时就能自动发现它们。能联网的环境直接跑./contrib/download_prerequisites离线环境就要自己处理了。手动把gmp-6.1.0.tar.bz2、mpfr-3.1.4.tar.bz2、mpc-1.0.3.tar.gz、isl-0.18.tar.bz2放到源码根目录然后手动解压并创建对应的软链接让configure能找到它们cd /opt/src/gcc-8.5.0 tar -xf gmp-6.1.0.tar.bz2 tar -xf mpfr-3.1.4.tar.bz2 tar -xf mpc-1.0.3.tar.gz tar -xf isl-0.18.tar.bz2 ln -sf gmp-6.1.0 gmp ln -sf mpfr-3.1.4 mpfr ln -sf mpc-1.0.3 mpc ln -sf isl-0.18 isl这个软链接的操作细节很多人不知道我第一回编GCC的时候就在这卡了半小时——依赖解压了、也放在源码目录里了但configure还是报Building GCC requires GMP 4.2, MPFR 2.4.0 and MPC 0.8.0。原因就是GCC的构建系统默认去找gmp、mpfr、mpc这样的目录名而不是带版本号的目录名软链接一下就好了。3.2 configure 参数逐项拆解关键原则不要在原源码目录里编译。GCC官方强烈建议out-of-tree build也就是另外建一个build目录在build目录里执行configure。这样做的好处是源码目录保持干净出问题好重来也避免和源码里的中间文件混淆。mkdir -p /opt/build/gcc-8.5.0 cd /opt/build/gcc-8.5.0 /opt/src/gcc-8.5.0/configure \ --prefix/usr/local/gcc-8.5.0 \ --enable-languagesc,c,fortran \ --disable-multilib \ --enable-bootstrap \ --disable-libsanitizer \ --with-system-zlib \ --enable-threadsposix \ --enable-__cxa_atexit \ --enable-shared我逐个解释为什么这么写你理解了才能根据自己的场景调整。--prefix/usr/local/gcc-8.5.0安装路径带版本号方便共存和卸载前面强调过了。--enable-languagesc,c,fortran按需选择语言前端。绝大多数业务只需要c和cfortran是给科学计算场景留的。每多一种语言编译时间和磁盘占用都增加不需要就果断砍掉。注意go语言前端在这里支持得不算好有需要的话建议单独评估。--disable-multilib纯64位环境跳过32位库编译能省掉一大堆32位依赖问题。--enable-bootstrap启用三阶段自举保证编译器可靠。追求速度可以改成--disable-bootstrap但生产环境我还是推荐保留。--disable-libsanitizer这个参数在旧glibc环境上几乎是必备的。libsanitizer包含AddressSanitizer、ThreadSanitizer这些内存检测工具它对glibc头文件版本有一定要求在中标麒麟V7.6这种glibc 2.17的老底子上很容易编译报错。禁用掉它不影响C/C正常编译只是少了那几个检测工具对绝大多数业务没影响。--with-system-zlib使用系统自带的zlib省得再编一份。--enable-threadsposix启用POSIX线程支持多线程程序必须。--enable-__cxa_atexit使用__cxa_atexit处理C的全局对象析构这是标准做法。--enable-shared生成共享库libstdc.so等动态链接的程序需要它。configure跑完之后如果结尾打印出一段构建配置摘要没有红色error就可以进入下一步了。如果报错仔细看它说缺什么八成是依赖没找到或者某个库版本太低。3.3 make 编译阶段与并行度控制configure通过后就是漫长的编译。前面说过并行度要克制这里给个稳妥的起手式# 保守起步观察内存 make -j4 # 或者用nohup挂后台避免SSH断连中断编译 nohup make -j8 /opt/build/gcc-build.log 21 # 实时查看进度 tail -f /opt/build/gcc-build.log这里有个极其重要但经常被忽略的点SSH断连。GCC编译动辄一两个小时如果你直接前台跑中途网断了、终端关了make进程收到HUP信号会被终止前面编的全都白费。所以长任务一定要nohup或者setsid挂后台日志重定向到文件随时能看进度。我见过太多人第一次编GCC就是因为这个编到90%断了欲哭无泪。编译过程中怎么判断有没有出问题盯着日志看几个信号如果某一步长时间不动可能是某个超大文件在编译正常如果日志里出现virtual memory exhausted: Cannot allocate memory或者某个cc1plus进程消失那就是内存不够需要减小编译并行度重来如果出现error:字样就是真的编译错误得停下来查。需要特别说明的是并行度不是一劳永逸的make -j8在编译前期可能很轻松但到后期编某些特定文件时内存飙升此时如果总内存不够就会挂。所以我一般先用-j4跑通一遍心里有数再考虑加大。3.4 make install 与目录规划make顺利跑完退出码为0日志末尾没有error就可以安装了。make install如果你只是要一个能用的编译器不折腾权限make install用普通用户就够了因为它装到--prefix指定的用户可写目录。但如果prefix在系统目录下、你又想全局可用就得sudo make install或者直接用root装。安装完成后检查一下目标目录的结构ls -l /usr/local/gcc-8.5.0/bin/ ls -l /usr/local/gcc-8.5.0/lib64/ | head # 看看都产出了什么 /usr/local/gcc-8.5.0/bin/gcc --version /usr/local/gcc-8.5.0/bin/g --version如果gcc --version打印出gcc (GCC) 8.5.0那装是装上了但现在还没法直接被系统识别——因为缺了环境变量和动态库路径配置直接调gcc还是老版本链接也会找不到新的libstdc.so.6。这就进入下一章的内容。4. 让新GCC真正可用的环境配置4.1 动态库路径与ldconfig新装的GCC产出的libstdc.so.6、libgcc_s.so.1这些动态库在/usr/local/gcc-8.5.0/lib64/下系统默认的动态库搜索路径里没有它所以用新GCC编译出来的程序一运行就可能报error while loading shared libraries: libstdc.so.6: version GLIBCXX_3.4.21 not found解决办法是把这个库目录告诉系统的动态链接器。在中标麒麟这类RHEL系系统上标准做法是往/etc/ld.so.conf.d/下加一个配置文件echo /usr/local/gcc-8.5.0/lib64 /etc/ld.so.conf.d/gcc-8.5.0.conf ldconfig # 验证 ldconfig -p | grep libstdc这里有个必须谨慎处理的细节ldconfig一执行系统全局的动态库搜索顺序就变了。如果新GCC的libstdc.so.6版本比系统自带的新系统里所有依赖旧libstdc的程序都会去找新的那份。正常情况下向后兼容没问题但极少数老程序可能因为符号冲突出问题。所以稳妥的做法是加配置之前先备份加完之后立刻在一台测试机上跑几个关键业务程序验证确认没问题再推广。生产服务器的每一步都要有回退预案。另外一个常见的替代方案是不改全局只针对具体程序指定运行库路径编译时加-Wl,-rpath,/usr/local/gcc-8.5.0/lib64把库路径编进二进制里。这样程序运行时会优先找这个目录不影响全局。如果你只是想让某几个程序用新库这个方案更安全。4.2 PATH优先级与多版本共存要让命令行里敲gcc时默认用新版本最直接的办法是调整PATH。有三种常见做法我逐个分析。做法一改用户级环境变量。在~/.bashrc或~/.bash_profile里加export PATH/usr/local/gcc-8.5.0/bin:$PATH export LD_LIBRARY_PATH/usr/local/gcc-8.5.0/lib64:$LD_LIBRARY_PATH注意$PATH是追加在后面新GCC的bin目录放前面所以敲gcc优先找新的。这种办法只影响当前用户最安全适合开发人员自己用。缺点是LD_LIBRARY_PATH有时会在子进程里出问题且不解决系统级依赖。做法二改全局/etc/profile.d/。建一个/etc/profile.d/gcc.sh内容同上。这样所有登录用户都生效但影响面大生产服务器要慎重尤其是改动涉及到系统编译环境时。做法三软链接到/usr/local/bin。因为/usr/local/bin通常排在/usr/bin前面可以把新GCC的关键命令软链接过去ln -sf /usr/local/gcc-8.5.0/bin/gcc /usr/local/bin/gcc ln -sf /usr/local/gcc-8.5.0/bin/g /usr/local/bin/g ln -sf /usr/local/gcc-8.5.0/bin/gfortran /usr/local/bin/gfortran这种方式的好处是不动系统的/usr/bin/gcc系统工具链保持原样只有用户主动调用时才走新版本。这是我在生产环境最常用的方式——既让新编译器随手可用又给系统留了后路。想切回去删掉这几个软链接就行干净利落。4.3 alternatives机制管理版本切换如果你的系统里同时存在多个GCC版本希望像切换Java版本那样一键切换那可以借助update-alternatives工具。不过要明确一点我一般不建议把系统gcc注册进alternatives因为系统很多组件依赖那个固定的/usr/bin/gcc随意切换会出问题。但如果你确实需要可以这么做# 注册新版本优先级设高一点比如100 update-alternatives --install /usr/bin/gcc gcc /usr/local/gcc-8.5.0/bin/gcc 100 update-alternatives --install /usr/bin/g g /usr/local/gcc-8.5.0/bin/g 100 # 交互式切换 update-alternatives --config gcc执行后会列出所有可用版本让你输入编号选择。想切回系统默认选对应的编号即可。这个机制的好处是切换集中管理、随时可回退日志清晰。坏处还是那句话动到了系统级的/usr/bin/gcc风险自担。所以我更倾向于把它当作开发机的便利工具生产服务器还是用软链接隔离的方式。4.4 验证与回退方案配置完之后一定要做一轮完整验证别急着宣布成功。# 检查默认gcc是哪一份 which gcc gcc --version which g # 写个C17的小程序验证 cat /tmp/test17.cpp EOF #include iostream #include optional #include string_view #include filesystem int main() { std::optionalint v 42; std::string_view sv hello; std::cout value *v , sv sv std::endl; namespace fs std::filesystem; std::cout exists(/tmp) fs::exists(/tmp) std::endl; return 0; } EOF g -stdc17 /tmp/test17.cpp -o /tmp/test17 /tmp/test17 # 看程序真正链接的是哪个libstdc ldd /tmp/test17 | grep stdc如果这段代码能编过、能运行、ldd指向新的库说明配置到位了。顺便看一下ldd输出里的libstdc.so.6路径确认是/usr/local/gcc-8.5.0/lib64/下的那一份。回退方案也要提前想好如果新编译器引发问题最快的回退是删掉PATH改动或软链接让系统回到老的/usr/bin/gcc如果全局ldconfig引发了动态库问题删掉那个.conf文件再ldconfig一次即可。所以我反复强调改全局配置之前先记录原状态旧的ldconfig -p输出、原来的PATH这样回退时心里有数。5. 编译链接中的常见问题与排查实录5.1 configure阶段报错速查configure阶段最常见的报错就是依赖问题。如果你看到Building GCC requires GMP 4.2, MPFR 2.4.0 and MPC 0.8.0八成是前面说的软链接没建或者依赖包没解压对位置。解决方式是回到源码目录确认gmp、mpfr、mpc这几个软链接指向正确的解压目录或者干脆用--with-gmp/path、--with-mpfr/path、--with-mpc/path显式指定路径。还有一种报错是C compiler cannot create executables这通常意味着系统基础编译环境本身有问题或者临时目录不可写。检查/tmp权限、检查gcc能否编译一个helloworld一般能找到原因。如果报错涉及libsanitizer或者error: Cannot use zlib之类的前者直接按前面的办法加--disable-libsanitizer后者确认zlib-devel装了没或者去掉--with-system-zlib让它用自带的。5.2 make阶段内存与时间问题make阶段最让人头疼的是内存不足被系统杀掉。症状是编译日志里出现virtual memory exhausted或者make突然停下来某些目标没编完dmesg里能看到Out of memory: Killed process ... cc1plus。解决办法就是降低并行度重来把-j8改成-j4甚至-j2保留已经编好的中间产物make有增量编译能力不用从头来继续跑。所以第一遍编译用保守的并行度就是为了避免这种中途翻车。时间问题也很磨人。GCC自举编译本来就慢如果你的机器核少、磁盘还是机械盘可能四五个小时都正常。我的经验是开着-j并行、挂后台、定期看日志就行别盯着。如果确实等不及重新configure时--disable-bootstrap能显著提速代价是没有自校验。另外如果编译过程中某个文件反复报同一个错误、重试也没用那可能是源码真的有问题或者某个依赖版本不对这时候要停下来查清楚别一味重跑。5.3 运行期libstdc版本冲突这是升级GCC后期最隐蔽的一类问题。表现是编译通过了一运行就报GLIBCXX符号找不到./myapp: /usr/lib64/libstdc.so.6: version GLIBCXX_3.4.25 not found或者反过来——系统某个程序因为搜到了新库而崩溃。这类问题的本质是新旧libstdc.so.6的搜索顺序没理清。排查思路是# 看程序实际用哪个库 ldd ./myapp | grep libstdc # 看某个库支持哪些GLIBCXX版本 strings /usr/local/gcc-8.5.0/lib64/libstdc.so.6 | grep GLIBCXX | tail # 看当前动态库搜索路径 ldconfig -p | grep libstdc如果程序找的还是老库就按4.1节的办法配ldconfig或者加-Wl,-rpath。如果是系统程序受影响就要考虑优先保证系统库路径的稳定把新库的使用范围限制在你的业务程序里而不是全局替换。这里有个非常实用的技巧给新编译的程序加上rpath让它在运行时优先找自己带的库g -stdc17 myapp.cpp -o myapp \ -Wl,-rpath,/usr/local/gcc-8.5.0/lib64这样即使系统全局库没改程序也能找到配套的新库最大化隔离风险。5.4 常见问题速查表为了让你排查时不用翻来翻去我把上面这些坑整理成一张表。现象可能原因处理办法configure报缺GMP/MPFR/MPC依赖未解压或目录名不匹配建gmp/mpfr/mpc软链接或--with-xxx指定路径make中途进程消失内存不足被OOM降低-j并行度保住中间产物重跑virtual memory exhausted单文件编译内存峰值过高减并行数或增大swaplibsanitizer编译失败老glibc不兼容加--disable-libsanitizer解除运行报GLIBCXX not found动态库路径没配配ldconfig或-Wl,-rpath系统程序异常全局库被替换回退ld.so.conf.d配置ldconfig刷新SSH断连导致编译中断未挂后台nohup/setsid跑长任务编译极慢并行度低或磁盘慢适当提高-j用SSD这张表基本覆盖了我这些年在中标麒麟上编GCC踩过的绝大多数坑。遇到问题先对照一下往往能省下大量搜索时间。6. 一些实操心得与收尾6.1 我踩过的坑最后分享几个别人文档里不常提、但实际很要命的经验。第一千万别图省事去动系统/usr/bin/gcc。我早年在一个内网环境里直接把系统gcc指向了新版本当时没出问题结果过了一个月有台机器要重编某个内核模块编译出来的模块加载时和系统内核版本对不上排查了半天才发现是编译器换了。从那以后我坚决用软链接隔离系统工具链一个字都不动。第二make install之前先确认一遍prefix。有一次我configure时手滑写错了prefix编了俩小时结果装到了个奇怪的目录。虽然可以重装make install很快但源目录里的中间产物一旦混乱重新configure还得再来一遍。所以configure命令一定仔细核对。第三给编译机留足swap。内存不够的时候swap是最后的缓冲虽然慢但能避免编译进程被直接杀掉。我给编译机通常配和内存等量的swap实测能明显减少OOM概率。第四用新GCC编译业务代码时别忘了同时指定C和C编译器。有些项目的构建系统比如CMake、autotools会分别探测CC和CXX环境变量你只改了gcc没改g混着用会造成库版本不一致链接时报奇怪的错误。养成习惯export CC/usr/local/gcc-8.5.0/bin/gcc export CXX/usr/local/gcc-8.5.0/bin/g6.2 后续扩展建议如果你已经顺利把GCC 8.5.0装好接下来可以考虑几个方向。一是按需再装更高版本比如GCC 10、11用于纯开发验证多版本继续用软链接或alternatives隔离互不干扰。二是把整套编译流程脚本化把configure参数、依赖准备、环境配置写成一个build-gcc.sh下次在新机器上复用省得重新回忆每个参数。三是关注你业务真正需要的语言标准像现在很多C项目已经上C20那可能迟早要升到GCC 10以上提前规划好比临时抱佛脚从容得多。这套流程我在多台中标麒麟V7.6的机器上实操过x86_64和鲲鹏ARM架构上略有差异但主干一致。关键还是那句老话升级环境变量、隔离系统工具链、留好回退路径把这三件事守住剩下的就是耐心等编译。
返回列表