Linux 安装交叉编译器后丢失 `<asm/errno.h>` 的问题及解决方案
前言
在 Linux (Ubuntu等)环境下安装某些软件或开发环境时,我们可能会意外地引入交叉编译工具链,尤其是用于 ARM 架构的交叉编译器,比如 gcc-arm-linux-gnueabi 等。而这种行为会修改系统原有的开发环境,甚至导致无法编译原生程序。本文记录一次在 Ubuntu 18.04 上编译 C 程序时遇到 fatal error: asm/errno.h: No such file or directory 的报错,并给出详细排查和恢复步骤。
❗ 问题描述
在执行 make 或使用 gcc 编译一个看似正常的程序时,报出如下错误:
/usr/include/linux/errno.h:1:10: fatal error: asm/errno.h: No such file or directory
#include <asm/errno.h>
^~~~~~~~~~~~~
compilation terminated.
这意味着系统在 /usr/include/ 路径下未能找到 asm/errno.h,而这个头文件是 Linux 内核用户空间 API 中的一部分,通常是符号链接或文件指向实际的内核头路径。
系统上查看这个 ‘asm/errno.h’ 文件是存在的,就是指引 .h 头文件是有问题的。
⚙️ 这些头文件到底来自哪?
在 Linux 系统中,/usr/include/asm 并不是实际目录,而是一个符号链接,通常指向 asm-generic 或特定架构的头文件。例如:
/usr/include/asm -> asm-generic/
其中:
asm/errno.h是一个与架构相关的头文件,一般在安装linux-libc-dev包时由系统提供;linux-libc-dev是内核导出的用户空间头文件集,用于提供 UAPI 接口;libc6-dev是 C 语言运行时开发包,包含大部分通用的标准 C 头文件,如<errno.h>、<stdio.h>等。
当引入如 gcc-arm-linux-gnueabi 这样的交叉编译工具链时,系统可能同时添加 armhf 架构支持,并拉取一套用于 ARM 的头文件(如 linux-libc-dev:armhf),这将覆盖甚至替换当前系统对 x86_64 的头文件符号链接,最终导致头文件缺失。
🧩 排查思路与解决方案
一、确认系统已引入 ARM 架构支持
dpkg --print-foreign-architectures
若输出中包含 armhf,说明系统启用了 ARM 架构支持,这是引发交叉编译环境干扰的根源。
二、卸载交叉编译器及其依赖包
sudo apt-get remove --purge gcc-arm-linux-gnueabi g++-arm-linux-gnueabi
sudo apt-get autoremove --purge
这一步将移除 ARM 交叉编译器及其依赖的库工具,释放系统资源。
三、清除所有 ARM 多架构包
为防止交叉编译链残留包继续影响系统,应删除所有 :armhf 架构的开发包。
# 推荐先模拟查看要卸载的内容是否合理
apt-get purge --simulate $(dpkg-query -f '${Package}:'${Architecture}' ' -W '*:armhf')
# 然后正式执行
sudo apt-get purge $(dpkg-query -f '${Package}:'${Architecture}' ' -W '*:armhf')
接着移除 ARM 架构本身:
sudo dpkg --remove-architecture armhf
此时 dpkg --print-foreign-architectures 应仅剩原始架构(如 amd64)
四、恢复宿主机本地开发环境
我们需要重新安装正确版本的开发包来恢复 /usr/include/asm 及相关头文件。
sudo apt-get update
sudo apt-get install --reinstall linux-libc-dev libc6-dev linux-headers-$(uname -r)
这三者的作用分别是:
- libc6-dev:C 标准库开发头文件(如
<errno.h>); - linux-libc-dev:内核用户空间头文件(如
asm/*.h),linux-libc-dev会恢复/usr/include/asm -> asm-generic/及所有asm/*.h文件; - linux-headers-$(uname -r):确保头文件版本与当前内核一致,便于编译驱动或内核模块。
此时,应恢复 /usr/include/asm 符号链接:
ls -l /usr/include/asm
# 输出应为:/usr/include/asm -> asm-generic/
五、验证恢复是否成功
创建一个简单测试文件 test.c:
#include <asm/errno.h>
int main() { return ENOENT; }
然后尝试编译:
gcc -c test.c
如果没有再报错,说明头文件路径及内容恢复成功。
这里如果再执行:
dpkg --print-foreign-architectures会发现没任何输出,即不启用 ARM 架构支持。
✅ 总结
使用 ARM 编译工具,建议使用容器化或其他系统设备来来隔离交叉工具链,避免环境/系统污染。
| 操作 | 作用 |
|---|---|
dpkg --print-foreign-architectures |
检查系统是否开启了 ARM 架构 |
| 卸载交叉编译器 | 避免非原生架构工具干扰 |
| 移除 armhf 架构及包 | 恢复系统架构单一性 |
| 重新安装 libc6-dev 等包 | 恢复标准头文件和符号链接 |
| 编译测试 | 验证开发环境正常 |
注:
安装工具链/环境之前要检查会不会和原环境冲突,不然修复排查换源也挺麻烦,挺耗时间的,以后能用 docker 就尽量用 docker 吧。
更多推荐



所有评论(0)