首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

gcc交叉编译工具链和QtCreator编译构建Linux的代码时用到的sysroot(System Root)目录是怎么回事儿?怎么样得到它?

  • 25-03-05 03:00
  • 2201
  • 8255
blog.csdn.net

引言

截止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,你可以:

  1. 从 目标设备 拷贝 lib 和 usr/include 目录:
    rsync -avz root@target:/lib /path/to/sysroot/
    rsync -avz root@target:/usr/include /path/to/sysroot/usr/
    
    • 1
    • 2
  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 是不够的,还需要:

  1. 完整的 Linux 内核源码
    • 例如 /home/book/linux-4.17.8/
  2. 正确配置的 .config 文件
    • 确保 make menuconfig 选择了合适的配置
  3. 内核编译后的 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 源码和编译环境! ?

总结

  1. sysroot 是交叉编译工具链的 伪根目录,存放 目标系统的库和头文件。
  2. sysroot 独立于主机系统,确保交叉编译的代码可以正确链接目标系统的库。
  3. GCC 默认使用 sysroot,可以通过 gcc --print-sysroot 查看当前的 sysroot 目录。
  4. sysroot 可以通过 Buildroot、Yocto 或手动拷贝 生成,并在编译时使用 --sysroot=路径 选项指定。
  5. sysroot 目录的正确使用,可以 避免链接主机库的问题,确保交叉编译程序能够在目标设备上正常运行。
  6. sysroot 主要针对用户空间编译,而内核空间代码的编译需要完整的 Linux 源码和编译环境
昊虹嵌入式技术交流群
QQ群名片
注:本文转载自blog.csdn.net的昊虹AI笔记的文章"https://blog.csdn.net/wenhao_ir/article/details/145468785"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2492) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

101
推荐
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2025 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top