使用GCC 11编译GCC 4.1.2时出现多重定义错误求助
编译OS161修改版GCC 4.1.2时的多重定义错误解决方法
问题背景
我正在跟随2023春季的操作系统课程,搭建环境完成课程作业,需要编译一个适配OS161的修改版GCC 4.1.2。使用RHEL系统,当前系统自带GCC版本为11.3.1,编译过程中出现exact_log2与floor_log2函数的多重定义错误,错误信息如下:
/usr/bin/ld: attribs.o: in function `floor_log2':/home/ec2-user/gcc-4.1.2+os161-2.0/host-x86_64-unknown-linux-gnu/gcc/../.././gcc/toplev.h:177: multiple definition of `floor_log2'; c-lang.o:/home/ec2-user/gcc-4.1.2+os161-2.0/host-x86_64-unknown-linux-gnu/gcc/../.././gcc/toplev.h:177: first defined here /usr/bin/ld: attribs.o: in function `exact_log2':/home/ec2-user/gcc-4.1.2+os161-2.0/host-x86_64-unknown-linux-gnu/gcc/../.././gcc/toplev.h:183: multiple definition of `exact_log2'; c-lang.o:/home/ec2-user/gcc-4.1.2+os161-2.0/host-x86_64-unknown-linux-gnu/gcc/../.././gcc/toplev.h:183: first defined here /usr/bin/ld: c-errors.o: in function `floor_log2':/home/ec2-user/gcc-4.1.2+os161-2.0/host-x86_64-unknown-linux-gnu/gcc/../.././gcc/toplev.h:177: multiple definition of `floor_log2'; c-lang.o:/home/ec2-user/gcc-4.1.2+os161-2.0/host-x86_64-unknown-linux-gnu/gcc/../.././gcc/toplev.h:177: first defined here /usr/bin/ld: c-errors.o: in function `exact_log2':/home/ec2-user/gcc-4.1.2+os161-2.0/host-x86_64-unknown-linux-gnu/gcc/../.././gcc/toplev.h:183: multiple definition of `exact_log2'; c-lang.o:/home/ec2-user/gcc-4.1.2+os161-2.0/host-x86_64-unknown-linux-gnu/gcc/../.././gcc/toplev.h:183: first defined here
推测错误与GCC 10及以上版本默认启用-fno-common标志有关,但直接在Makefile的CFLAGS中添加-fcommon并未解决问题。相关函数在toplev.h中的原定义如下:
/* Inline versions of the above for speed. */ #if GCC_VERSION >= 3004 extern inline int exact_log2 (unsigned HOST_WIDE_INT x) { return x == (x & -x) && x ? (int) CTZ_HWI (x) : -1; } #endif /* GCC_VERSION >= 3004 */
解决步骤
1. 修改内联函数的存储类型
高版本GCC对extern inline的处理规则与旧版本不同,会导致多个编译单元生成相同的函数定义引发冲突。将toplev.h中的extern inline替换为static inline,让每个编译单元拥有独立的函数实例:
修改后的exact_log2函数:
/* Inline versions of the above for speed. */ #if GCC_VERSION >= 3004 static inline int exact_log2 (unsigned HOST_WIDE_INT x) { return x == (x & -x) && x ? (int) CTZ_HWI (x) : -1; } #endif /* GCC_VERSION >= 3004 */
对toplev.h中的floor_log2函数执行同样修改,将extern inline替换为static inline。
2. 在配置阶段传入-fcommon标志
若修改代码后仍有问题,需要在GCC配置阶段就指定-fcommon,确保所有编译单元都使用该规则:
./configure --prefix=/你的安装路径 CFLAGS="-fcommon" CXXFLAGS="-fcommon"
3. 清理旧编译产物
修改前先清理之前的编译文件,避免残留文件干扰:
make distclean
之后重新执行make和make install即可完成编译。
内容的提问来源于stack exchange,提问作者whaleshark
相关产品推荐
相关产品推荐

