引言
截止2025-02-06,我学习Linux嵌入式开发过程中遇到过几次sysroot目录了,比如下面三次:
①在gcc交叉编译工具链的目录:
/home/book/100ask_imx6ull-sdk/ToolChain/arm-buildroot-linux-gnueabihf_sdk-buildroot/arm-buildroot-linux-gnueabihf/
- 1
下面存在sysroot目录,如下图所示:
②在QtCreator构建工程时发现工程的Makfile中有下面的配置:
LFLAGS = --sysroot=/home/book/100ask_imx6ull-sdk/Buildroot_2020.02.x/output/host/arm-buildroot-linux-gnueabihf/sysroot
- 1
③在研究gcc交叉编译工具链的头文件搜索路径时(http://iyenn.com/rec/1709249.html),发现有目录:
/home/book/100ask_imx6ull-sdk/ToolChain/arm-buildroot-linux-gnueabihf_sdk-buildroot/arm-buildroot-linux-gnueabihf/sysroot/usr/include
- 1
以上情况说明这个目录很重要, 所以本篇博文需要研究下这个sysroot(System Root)目录。
什么是 sysroot
目录?
sysroot
(System Root)是一个用于交叉编译的 伪根目录(Fake Root),它包含目标系统的 头文件(headers) 和 库文件(libraries),让交叉编译工具链可以在第三方系统中正常编译出能运行于目标系统的用户空间的文件。
注意:sysroot 主要针对运行于用户空间的代码,关于这一点,本篇博文后面我有详细说明。
在交叉编译过程中,sysroot
目录的作用类似于目标设备的 /
(根目录),但它是一个独立的目录,可以放于自己的交叉编译环境中使用。
sysroot
目录的结构
一个典型的 sysroot
目录包含以下子目录:
sysroot/
├── usr/
│ ├── include/ # 目标系统的 C/C++ 头文件(如 stdio.h, stdlib.h)
│ ├── lib/ # 目标系统的动态库(如 libc.so, libm.so, libpthread.so)
│ ├── lib64/ # (某些 64 位架构会有这个目录)
│ ├── bin/ # 目标系统的工具(可能包含交叉编译的 binutils)
│ ├── sbin/ # 部分系统工具
│ └── share/ # 共享数据
├── lib/ # 目标系统的核心库(如 ld-linux.so, libgcc_s.so)
├── etc/ # 目标系统的配置文件
└── ... # 其他可能的目录,如 opt/, var/, dev/ 等
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
这个 sysroot
目录的内容与目标系统的 /
目录结构类似,但通常只包含 开发所需的库和头文件,不会包含完整的操作系统文件。
sysroot
的作用
1. 提供目标系统的库和头文件
在交叉编译时,编译器需要目标系统的头文件和库,而不能使用当前主机系统的文件。例如:
arm-buildroot-linux-gnueabihf-gcc -o my_program my_program.c --sysroot=/path/to/sysroot
- 1
这样,编译器会从 /path/to/sysroot/usr/include
查找头文件,并从 /path/to/sysroot/usr/lib
链接库文件,而不会使用主机的 /usr/include
和 /usr/lib
。
2. 让交叉编译环境更独立
sysroot
目录让交叉编译工具链 不依赖主机系统,确保编译出的程序能够在 目标设备 上运行,而不会意外链接到 主机系统的库。
例如:
- 如果不使用
sysroot
,编译器可能会使用主机/usr/include
下的stdio.h
,而这个文件可能不适用于目标设备,导致程序无法运行。 - 如果使用
sysroot
,编译器会使用sysroot/usr/include/stdio.h
,确保与目标系统匹配。
如何生成 sysroot
?
1. 使用 Buildroot 生成
使用Buildroot构建嵌入式开发环境时,Buildroot 会编译生成交叉工具链,显然在编译生成交叉工具链时会一并生成 sysroot
目录。
上面这张截图的目录路径如下:
/home/book/100ask_imx6ull-sdk/Buildroot_2020.02.x/output/host
- 1
上面这张截图的目录路径如下:
/home/book/100ask_imx6ull-sdk/Buildroot_2020.02.x/output/host/arm-buildroot-linux-gnueabihf
- 1
2. 使用 Yocto 生成
Yocto 也会为每个目标设备生成 sysroot
,路径类似:
/tmp/sysroots/
- 1
3. 手动创建
如果你没有现成的 sysroot
,你可以:
- 从 目标设备 拷贝
lib
和usr/include
目录:rsync -avz root@target:/lib /path/to/sysroot/ rsync -avz root@target:/usr/include /path/to/sysroot/usr/
- 1
- 2
- 使用
debootstrap
或multistrap
生成sysroot
:sudo debootstrap --arch=armhf buster /path/to/sysroot http://deb.debian.org/debian/
- 1
如何在编译时使用 sysroot
如何查看交叉编译工具链使用的sysroot
目录的路径
交叉编译工具链(如 arm-buildroot-linux-gnueabihf-gcc
)通常默认使用 sysroot
目录。你可以运行:
arm-buildroot-linux-gnueabihf-gcc --print-sysroot
- 1
示例输出:
/home/book/100ask_imx6ull-sdk/ToolChain/arm-buildroot-linux-gnueabihf_sdk-buildroot/arm-buildroot-linux-gnueabihf/sysroot
- 1
表示 GCC 默认的 sysroot
目录就是 /home/book/.../sysroot
,所以你不需要手动指定 --sysroot
选项。
手动指定 sysroot
的方法
编译时可以手动指定 sysroot
:
arm-buildroot-linux-gnueabihf-gcc --sysroot=/path/to/sysroot -o my_program my_program.c
- 1
或者在 CMake 中:
set(CMAKE_SYSROOT "/path/to/sysroot")
- 1
sysroot主要是针对用户空间中的代码编译,而不是内核空间中的代码编译
1. sysroot 主要针对用户空间(User Space)
sysroot
是为了 交叉编译用户空间应用 而准备的,它通常包含:
- C 标准库(如 glibc, uClibc, musl)
- 用户空间头文件(如
/usr/include
) - 用户空间库(如
/usr/lib
) - 动态链接器(如
/lib/ld-linux.so.3
)
当你用交叉编译器(如 arm-buildroot-linux-gnueabihf-gcc
)编译 Qt 应用、C 程序、Python 代码 等,它会去 sysroot
里面找 头文件和库。
2. 内核空间(Kernel Space)需要完整的 Linux 源码
如果你要编写 Linux 内核驱动(Device Driver),光有 sysroot
是不够的,还需要:
- 完整的 Linux 内核源码
- 例如
/home/book/linux-4.17.8/
- 例如
- 正确配置的
.config
文件- 确保
make menuconfig
选择了合适的配置
- 确保
- 内核编译后的
build
目录- 驱动程序需要
KERNEL_SOURCE/include
里面的内核头文件 - 需要
KERNEL_SOURCE/Module.symvers
以解析符号
- 驱动程序需要
3. 如何编译驱动
编译内核模块(驱动)时,通常会使用:
make -C /path/to/kernel M=$(pwd) modules
- 1
其中 /path/to/kernel
需要指向 正确的 Linux 内核源码目录,而不是 sysroot
。
如果你误用了 sysroot
,驱动编译时会报错:
fatal error: linux/module.h: No such file or directory
- 1
因为 sysroot
里没有完整的内核头文件。
4. 小结
用途 | 依赖于 sysroot? | 需要完整的 Linux 源码? |
---|---|---|
用户空间应用(Qt, C, Python) | ✅ 是 | ❌ 否 |
内核驱动(Device Driver) | ❌ 否 | ✅ 是 |
编译整个 Linux 内核 | ❌ 否 | ✅ 是 |
所以,sysroot 主要针对用户空间编译,而内核驱动需要完整的 Linux 源码和编译环境! ?
总结
sysroot
是交叉编译工具链的 伪根目录,存放 目标系统的库和头文件。sysroot
独立于主机系统,确保交叉编译的代码可以正确链接目标系统的库。- GCC 默认使用
sysroot
,可以通过gcc --print-sysroot
查看当前的sysroot
目录。 sysroot
可以通过 Buildroot、Yocto 或手动拷贝 生成,并在编译时使用--sysroot=路径
选项指定。sysroot
目录的正确使用,可以 避免链接主机库的问题,确保交叉编译程序能够在目标设备上正常运行。- sysroot 主要针对用户空间编译,而内核空间代码的编译需要完整的 Linux 源码和编译环境



评论记录:
回复评论: