news 2026/5/24 2:54:19

Ubuntu 22.04编译Linux内核踩坑记:解决‘multiple definition of yylloc’的完整心路历程

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Ubuntu 22.04编译Linux内核踩坑记:解决‘multiple definition of yylloc’的完整心路历程

Ubuntu 22.04编译Linux内核实战:从"multiple definition"错误到完整解决方案

当你在Ubuntu 22.04上尝试编译Linux内核时,可能会遇到一个令人困惑的错误信息:/usr/bin/ld: scripts/dtc/dtc-parser.tab.o:(.bss+0x50): multiple definition of 'yylloc'。这个错误看似简单,却可能让你花费数小时甚至数天时间才能找到真正的解决方案。本文将带你深入理解这个问题的本质,并提供一套完整的排查思路和解决方案,而不仅仅是简单的步骤说明。

1. 问题背景与初步分析

Linux内核编译是一个复杂的过程,涉及数百个文件和工具链的协同工作。当你在Ubuntu 22.04这样的较新系统上编译为旧版系统设计的内核时,版本差异往往会带来各种意想不到的问题。

multiple definition of 'yylloc'错误通常出现在编译设备树编译器(DTC)组件时。这个错误表明链接器(ld)在尝试将多个目标文件合并时,发现yylloc变量被重复定义。具体来说:

  • 第一次定义出现在scripts/dtc/dtc-lexer.lex.o
  • 第二次定义出现在scripts/dtc/dtc-parser.tab.o

为什么会出现这个问题?

在较新的Ubuntu系统中,工具链和编译器的行为可能与旧版系统有所不同。特别是:

  1. GCC版本差异:Ubuntu 22.04默认使用GCC 11,而旧版系统可能使用GCC 5或7
  2. 链接器行为变化:新版ld可能对符号重复定义更加严格
  3. Bison/Flex版本:语法分析器生成工具的版本差异可能导致生成的代码不同

2. 常见解决方案及其局限性

大多数在线资源会建议以下解决方案:

// 在dtc-parser.tab.c中添加extern声明 extern YYLTYPE yylloc;

这个方案看似合理,因为它遵循了C语言中解决重复定义问题的常规方法:将其中一个定义改为声明。然而,在实际操作中,你可能会发现:

  1. 修改后错误依然存在
  2. 重新编译时,你的修改似乎被"撤销"了

为什么会这样?

关键在于理解内核编译系统的完整工作流程。DTC(设备树编译器)的源文件在编译过程中会经历以下步骤:

  1. 由Bison和Flex工具从.y.l文件生成.c文件
  2. 生成的.c文件被编译为目标文件
  3. 目标文件被链接为最终的可执行文件

问题在于,每次编译时,系统都会重新生成这些中间文件,覆盖你手动修改的版本。这就是为什么简单的编辑解决方案往往无效。

3. 深入解决方案:修改生成规则

要永久解决这个问题,我们需要修改生成这些中间文件的规则。以下是详细步骤:

3.1 定位相关Makefile

首先,找到控制DTC编译的Makefile:

cd linux-kernel-directory find . -name Makefile | grep dtc

通常,相关Makefile位于scripts/dtc/Makefile

3.2 修改生成规则

在Makefile中,我们需要修改Bison和Flex的生成规则。添加以下内容:

# 在scripts/dtc/Makefile中添加 dtc-parser.tab.o: dtc-parser.tab.c dtc-lexer.lex.o $(CC) $(CFLAGS) -c -o $@ $< -Wno-error=redundant-decls dtc-lexer.lex.o: dtc-lexer.lex.c $(CC) $(CFLAGS) -c -o $@ $< -Wno-error=redundant-decls

3.3 修改源文件

同时,我们需要修改.y.l源文件:

  1. scripts/dtc/dtc-parser.y开头添加:

    %code requires { extern YYLTYPE yylloc; }
  2. scripts/dtc/dtc-lexer.l开头添加:

    YYLTYPE yylloc;

3.4 清理并重新编译

make clean make mrproper make oldconfig make -j$(nproc)

4. 问题背后的技术原理

理解这个问题的根本原因有助于你在遇到类似问题时更快找到解决方案。

YYLTYPE和yylloc是什么?

  • YYLTYPE是Bison定义的结构体,用于存储位置信息(行号、列号等)
  • yylloc是Flex和Bison共享的全局变量,用于在词法分析器和语法分析器之间传递位置信息

为什么会出现重复定义?

  1. Flex生成的词法分析器(dtc-lexer.lex.c)默认会定义yylloc
  2. Bison生成的语法分析器(dtc-parser.tab.c)在某些配置下也会定义yylloc
  3. 当这两个目标文件被链接时,链接器发现同一个符号被定义了两次

版本差异的影响

在较新的Ubuntu系统中:

  1. Bison/Flex版本可能生成略有不同的代码
  2. GCC默认启用更多警告和错误检查
  3. 链接器对符号可见性规则更加严格

5. 替代解决方案比较

除了上述方法,还有其他几种解决思路:

解决方案优点缺点适用场景
修改生成规则永久解决需要理解Makefile长期开发
添加extern声明简单直接可能被覆盖快速测试
使用旧版工具链兼容性好需要安装旧版兼容性测试
修改编译器标志无需改代码可能掩盖其他问题临时解决方案

使用旧版工具链的方法

如果你需要与旧系统完全兼容,可以考虑使用Docker容器:

# 创建Ubuntu 16.04容器 docker run -it --name kernel-build -v $(pwd):/src ubuntu:16.04 # 在容器内安装工具链 apt update && apt install build-essential flex bison libssl-dev

6. 预防类似问题的通用策略

在编译复杂项目时,以下策略可以帮助你更高效地解决问题:

  1. 理解完整的构建流程

    • 不要只关注错误本身,要了解整个构建系统的运作方式
    • 使用make V=1查看详细的构建命令
  2. 版本控制是关键

    git init git add . git commit -m "Initial source code"

    这样你可以随时回退到已知良好的状态

  3. 增量调试技巧

    • 先尝试单独编译出问题的模块
    • 使用make scripts/dtc/dtc只编译DTC组件
  4. 文档与社区资源

    • 查阅内核文档(Documentation/kbuild)
    • 搜索LKML(Linux内核邮件列表)中的相关讨论

7. 高级技巧:深入构建系统

对于需要频繁修改和编译内核的开发者,以下高级技巧可能有用:

使用ccache加速编译

sudo apt install ccache export CC="ccache gcc" make -j$(nproc)

自定义构建输出

# 将构建输出与源码分离 mkdir build-output make O=build-output

调试链接问题

当遇到链接问题时,可以使用以下命令检查符号定义:

nm dtc-parser.tab.o | grep yylloc nm dtc-lexer.lex.o | grep yylloc

8. 实际案例:从错误到解决的完整过程

让我们通过一个真实场景来巩固所学内容:

  1. 初始错误

    /usr/bin/ld: scripts/dtc/dtc-parser.tab.o:(.bss+0x50): multiple definition of 'yylloc' scripts/dtc/dtc-lexer.lex.o:(.bss+0x0): first defined here
  2. 第一次尝试

    • dtc-parser.tab.c中添加extern YYLTYPE yylloc;
    • 重新编译,问题依旧
  3. 深入分析

    • 使用make V=1发现文件被重新生成
    • 检查.tmp_dtc目录发现备份文件
  4. 根本解决

    • 修改dtc-parser.ydtc-lexer.l
    • 更新Makefile规则
    • 彻底清理并重新编译
  5. 验证

    file scripts/dtc/dtc scripts/dtc/dtc: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=..., for GNU/Linux 3.2.0, not stripped

在解决这个问题的过程中,最关键的是理解构建系统的完整工作流程,而不仅仅是关注表面错误。这种系统性的思维方式对于解决复杂的编译问题至关重要。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/24 2:51:08

量子多体系统模拟:MPS与DMRG算法实践

1. 量子多体系统模拟基础框架在量子多体系统的研究中&#xff0c;矩阵乘积态(MPS)已成为描述一维强关联系统的标准工具。这种表示方法的核心思想是将一个N体量子态分解为N个局部张量的收缩形式&#xff0c;每个张量对应一个物理位点。具体数学表达为&#xff1a; [ |ψ⟩ \sum…

作者头像 李华
网站建设 2026/5/24 2:43:14

知识图谱与大语言模型协同:构建材料科学精准智能问答系统

1. 项目概述&#xff1a;当知识图谱遇见大语言模型“想象一下&#xff0c;未来有这样一个设备……个人可以存储他所有的书籍、记录和通信&#xff0c;并且它被机械化&#xff0c;可以以极高的速度和灵活性进行查阅。它是他记忆的一个放大的、亲密的补充。”——范内瓦布什&…

作者头像 李华
网站建设 2026/5/24 2:41:55

FP8量化与稀疏注意力优化视频生成模型

1. 项目概述在视频生成领域&#xff0c;计算效率和内存占用一直是制约模型规模和应用场景的关键瓶颈。传统全精度&#xff08;FP32/FP16&#xff09;模型虽然能保证生成质量&#xff0c;但对硬件资源的需求使得实时或大规模部署面临巨大挑战。我们提出了一种创新的联合优化方案…

作者头像 李华
网站建设 2026/5/24 2:41:47

Windows命令行高效安装与卸载Arm开发工具指南

1. Windows命令行安装与卸载Arm开发工具全指南作为一名长期使用Arm开发工具链的嵌入式工程师&#xff0c;我经常需要在多台Windows设备上批量部署Arm Development Studio和DS-5。相比图形界面安装&#xff0c;命令行方式能显著提升效率&#xff0c;特别是在自动化部署和远程配置…

作者头像 李华