Ubuntu高版本编译Linux 4.1.x内核报 multiple definition of yylloc 解决方法
Ubuntu 高版本编译 Linux 4.1.x时提示 multiple definition of yylloc 解决方法1. 问题背景在编译 NXP i.MX6ULL 平台 BSP 时使用厂家提供的老版本 Linux 内核linux-imx-rel_imx_4.1.15_2.1.0_ga执行make ARCHarm CROSS_COMPILEarm-linux-gnueabihf- -j16编译过程中出现错误/usr/bin/x86_64-linux-gnu-ld.bfd: scripts/dtc/dtc-parser.tab.o:(.bss0x50): multiple definition of yylloc; scripts/dtc/dtc-lexer.lex.o:(.bss0x0): first defined here collect2: error: ld returned 1 exit status make[2]: *** [scripts/Makefile.host:100: scripts/dtc/dtc] Error 12. 问题定位从错误可以看到scripts/dtc/dtc-parser.tab.o scripts/dtc/dtc-lexer.lex.o出错位置是scripts/dtc而不是 ARM 内核代码。说明失败的是编译运行在主机上的设备树编译器 dtcLinux 编译过程中会先编译一些 host 工具scripts/ | -- kconfig | -- dtc | -- modpost这些工具运行在 PC 上而不是运行在目标 ARM 板子上。3. 根本原因yylloc来自scripts/dtc/ | -- dtc-lexer.lex.c | -- dtc-parser.tab.c这两个文件分别由flexbison生成。里面都有类似YYLTYPE yylloc;的全局变量定义。老 GCC 行为以前 GCC 默认-fcommon多个同名未初始化全局变量int a;会合并处理。例如a.cint yylloc;b.cint yylloc;链接时正常通过新 GCC 行为GCC 10 开始默认-fno-common同名全局变量会被认为是重复定义multiple definition所以老版本 LinuxLinux 4.1 U-Boot 2016在新 UbuntuUbuntu 20.04 GCC 10环境下容易出现该问题。4. 解决方法方法一增加 -fcommon推荐修改 Linux 顶层 Makefile找到HOSTCC gcc HOSTCXX g HOSTCFLAGS -Wall -Wmissing-prototypes -Wstrict-prototypes -O2 -fomit-frame-pointer -stdgnu89 HOSTCXXFLAGS -O2修改HOSTCC gcc HOSTCXX g HOSTCFLAGS -Wall -Wmissing-prototypes -Wstrict-prototypes -O2 -fomit-frame-pointer -stdgnu89 HOSTCFLAGS -fcommon HOSTCXXFLAGS -O2作用让 host 工具编译时恢复 GCC 老版本行为。方法二编译时临时指定不修改源码make ARCHarm \ CROSS_COMPILEarm-linux-gnueabihf- \ HOSTCFLAGS-fcommon \ -j16如果编译通过再永久修改 Makefile。5. 为什么不是修改 dtc 源码也可以修改scripts/dtc/dtc-lexer.lex.c把YYLTYPE yylloc;改成extern YYLTYPE yylloc;但是不推荐。原因这些文件是自动生成的dtc-lexer.l | flex | v dtc-lexer.lex.c重新编译可能会被覆盖。6. 总结编译老版本 BSP 时例如i.MX6ULLi.MX6Linux 4.xU-Boot 2016如果遇到multiple definition of xxx特别是yylloc通常原因GCC 10 修改了默认全局变量处理规则。解决HOSTCFLAGS -fcommon即可。这个问题本质不是代码错误而是老版本嵌入式 Linux BSP 与新开发环境之间的兼容性问题。

相关新闻