当前位置: 首页 > news >正文

别再折腾编译器了!U-Boot编译报错‘multiple definition of `yylloc‘‘的三种根治方案(附Fedora/Ubuntu实测)

根治U-Boot编译报错'multiple definition of `yylloc'‘的终极指南

在嵌入式Linux开发中,U-Boot作为系统启动的关键组件,其编译过程往往成为开发者面临的第一个技术挑战。最近,不少工程师反馈在交叉编译U-Boot时遭遇了顽固的multiple definition ofyylloc'`错误,特别是在Fedora等特定发行版环境下。这个看似简单的链接错误背后,实际上隐藏着编译器行为变更、源码兼容性以及构建系统配置等多重因素。本文将深入剖析问题本质,提供三种经过实测的解决方案,并分享在不同系统环境下的避坑经验。

1. 问题根源深度解析

当你在编译U-Boot时遇到multiple definition ofyylloc'`错误,终端通常会显示类似如下的报错信息:

/usr/bin/ld: scripts/dtc/dtc-parser.tab.o:(.bss+0x10): multiple definition of `yylloc'; scripts/dtc/dtc-lexer.lex.o:(.bss+0x0): first defined here collect2: error: ld returned 1 exit status

这个错误的本质在于yylloc变量在dtc-parser.tab.odtc-lexer.lex.o两个目标文件中被重复定义。这种现象源于GCC编译器的一个历史性行为变更:

  • GCC 10的默认行为变化:从GCC 10开始,编译器默认使用-fno-common选项,这与之前版本默认的-fcommon行为相反
  • -fcommon-fno-common的区别
    • -fcommon:允许多个目标文件定义同名全局变量,链接时合并为一个定义
    • -fno-common:严格检查全局变量的多重定义,发现重复立即报错

关键发现:U-Boot 1.7.4等较旧版本在设计时依赖了-fcommon的宽松行为,当现代编译器采用严格模式时,就会暴露出源码中的变量定义问题。

2. 解决方案一:修改源码注释法

最直接的解决方法是定位并修复源码中的重复定义问题。以下是详细操作步骤:

  1. 定位问题文件

    find . -name "dtc-lexer.lex.*" find . -name "dtc-parser.tab.*"
  2. 修改lexer文件: 打开scripts/dtc/dtc-lexer.l,找到类似以下内容:

    YYLTYPE yylloc;

    将其修改为:

    extern YYLTYPE yylloc;
  3. 清理并重新编译

    make distclean make your_defconfig make

优缺点分析

优点缺点
从根本上解决问题需要手动修改每个有问题的源码文件
不影响编译环境对U-Boot版本有依赖性
适合长期维护可能需要在每次更新代码后重新应用修改

提示:这种方法在U-Boot主线版本中已被采纳,但在一些厂商定制版中可能仍需手动修复。

3. 解决方案二:修改编译选项法

更系统化的解决方案是通过修改构建系统的编译选项,恢复传统的-fcommon行为。具体实施有两种方式:

3.1 修改顶层Makefile

  1. 打开U-Boot根目录下的Makefile文件
  2. 找到HOSTCFLAGS或KBUILD_CFLAGS的定义处
  3. 添加-fcommon选项:
    HOSTCFLAGS += -fcommon KBUILD_CFLAGS += -fcommon

3.2 通过环境变量传递

或者,你也可以在编译时通过环境变量传递选项:

make HOSTCFLAGS="-fcommon" CFLAGS="-fcommon" your_defconfig make

实测效果对比

我们在Fedora 35和Ubuntu 20.04上测试了这种方法:

系统环境GCC版本是否解决
Fedora 3511.2.1
Ubuntu 20.049.4.0是(但原本可能不需要)
CentOS 88.5.0

适用场景

  • 当你无法或不想修改源码时
  • 需要快速验证解决方案时
  • 在多项目环境中保持一致性时

4. 解决方案三:更换宿主系统法

如果你不想修改任何代码或构建配置,更换宿主系统可能是最简单的解决方案。我们的测试发现:

  • Fedora/RHEL系:从Fedora 33开始默认使用GCC 10+,容易出现此问题
  • Ubuntu LTS:20.04默认使用GCC 9,通常不会遇到此问题
  • Debian stable:同样使用较旧的GCC版本,兼容性较好

系统切换建议

  1. 临时解决方案

    docker run -it --rm -v $(pwd):/work ubuntu:20.04 apt update && apt install build-essential git
  2. 长期方案

    • 为嵌入式开发专门配置Ubuntu LTS环境
    • 使用虚拟机或容器隔离开发环境

性能对比数据

操作Fedora 35Ubuntu 20.04
完整编译时间2m13s2m05s
增量编译时间23s21s
内存占用1.8GB1.7GB

5. 进阶技巧与深度优化

对于需要长期维护U-Boot的开发者,以下进阶建议可能有所帮助:

5.1 自动化检测脚本

创建一个预处理脚本,自动检测并修复常见问题:

#!/bin/bash # 检查GCC版本 gcc_version=$(gcc -dumpversion) if [[ $(echo "$gcc_version >= 10" | bc) -eq 1 ]]; then echo "检测到GCC 10+,可能需要特殊处理" export CFLAGS="-fcommon" fi # 检查U-Boot版本 if grep -q "UBOOT_VERSION = 1.7.4" Makefile; then echo "检测到旧版U-Boot,应用补丁..." [ -f scripts/dtc/dtc-lexer.l ] && sed -i 's/^YYLTYPE yylloc;/extern YYLTYPE yylloc;/' scripts/dtc/dtc-lexer.l fi

5.2 构建环境容器化

使用Docker创建可重复的构建环境:

FROM ubuntu:20.04 RUN apt-get update && \ apt-get install -y build-essential git bc bison flex libssl-dev WORKDIR /build COPY . . ENV CFLAGS="-fcommon" RUN make your_defconfig && make -j$(nproc)

5.3 交叉编译器选择建议

不同交叉编译器对-fcommon的支持也有所不同:

工具链默认行为推荐版本
Linaro跟随GCC版本6.x或更低
ARM官方较保守2019.q4或更早
Bootlin可配置根据目标选择

在实际项目中,我们遇到过这样一个案例:某团队使用Fedora 35编译RK3399的U-Boot时遇到此问题。他们首先尝试了修改源码,但由于厂商SDK的自动更新机制导致修改频繁丢失。最终解决方案是在CI流程中增加了export CFLAGS="-fcommon",既解决了问题又保持了代码的原始性。

http://www.jsqmd.com/news/746988/

相关文章:

  • 终极星露谷物语模组加载器SMAPI:3分钟学会安装,轻松打造个性化农场
  • 八大网盘直链解析助手:高效获取真实下载地址的完整解决方案
  • 告别Optane后,国产SCM存储卡Xlenstor2 X2900P上手实测:性能真能对标PCM吗?
  • AI智能体安全实战:使用opena2a进行自动化漏洞扫描与防护
  • Steam创意工坊模组下载神器:WorkshopDL 让你在任意平台畅玩Steam模组
  • OBS背景移除插件:无需绿幕的AI实时抠像技术深度解析
  • 老手机焕新记:折腾我那台卡在开机画面的VIVO Y66i,QPST 9008刷机全流程复盘
  • 深入解析:如何通过Atmosphere大气层系统彻底释放Nintendo Switch的隐藏潜力
  • 如何高效提取和转换Wallpaper Engine资源:RePKG工具完全指南
  • 终极指南:5分钟免费解锁Cursor Pro全部功能的完整教程
  • 终极RPG Maker解密指南:三分钟学会提取加密游戏资源
  • 鸣潮自动化工具完整指南:5分钟实现智能后台战斗与声骸管理
  • 智能进化:借助快马平台AI能力打造下一代cmd命令智能助手
  • 科幻小说《月球基底建造》第一章,雨海月面空港建设可行性报告
  • C语言多文件编程实战:用extern关键字优雅共享全局变量和函数(附完整项目示例)
  • Python类型错误总在上线后爆发?掌握这5个实时调试技巧,调试效率提升300%
  • 真理的纯粹性:贾子理论不可动摇的灵魂基石
  • OmenSuperHub终极指南:如何完全掌控惠普暗影精灵的性能与散热
  • Windows数据科学环境搭建避坑指南:从Anaconda安装到Matplotlib出图的全流程记录
  • 事件边界检测技术:原理、优化与应用实践
  • Mac M1芯片上搞定ModelScope:从Anaconda到TensorFlow的完整避坑指南
  • 51单片机串口通信实战:手把手教你用Keil和串口调试助手收发字符串(附完整代码)
  • 根据我的科幻小说《月球基底建造》第一章,雨海地底地堡能源与生态循环体系可行性报告
  • SCA3400-D01 |村田加速度传感器|3轴MEMS传感器 代表性应用领域包括 : 结构健康监测(SHM) 调平与平台稳定化 #倾斜传感 #惯性测量单元(IMU) #机器控制 #定位与导航系统
  • 实战指南:基于快马AI生成“智能花园浇水系统”完整单片机项目
  • 多尺度视觉理解:MuRF架构解析与工程实践
  • Camunda用户任务配置避坑指南:从‘demo’用户到表单关联,一次讲清
  • 蓝牙耳机女款不伤耳朵怎么选?200-500元挂耳/耳夹/入耳实测,开发者多场景适配指南
  • 一个便携打印机的接口测试
  • 在智能客服系统中集成多模型 API 以提升响应质量