二、buildroot 构建交叉编译工具链
2.1 介绍
2.1.1 工具链简介
一个编译工具链模块是允许为系统编译代码的一组工具。它由一个编译器(在我们的例子中是 gcc)、像汇编器和链接器这样的二进制 utils(一般是 binutils)和一个C标准库(例如 GNU Libc, uClibc-ng)组成。
一个交叉编译工具链是可有在主机上运行的,但是编译出来的二进制文件只能运行在目标板或机器上。在我们的宿主机上也有工具链,它只能编译适用于我们的宿主机,编译出来的程序也只能运行在我们的宿主机上。
当前我们要使用 buildroot 编译出来一个交叉编译工具链,适用于我们的目标板。
目标板是 S3C2440,它是 ARM 架构的,arm920t 的核心。
2.1.2 buildroot 的工具链工具
buildroot 提供了两种建立交叉编译工具链的方式:
- 内部工具链后端,在配置接口中称为 Buildroot 工具链。
- 外部工具链后端,在配置接口中称为外部工具链。
使用工具链菜单中的工具链类型选项来选择这两种解决方案。一旦选择了一个解决方案,就会出现许多配置选项。
在 根目录下使用 make menuconfig,Toolchain--->Toolchain type
2.1.3 内部工具链
内部工具链是 Buildroot 在为目标嵌入式系统构建用户空间应用程序和库之前,自行构建的交叉编译工具链。
此交叉编译工具链支持几种 C 库:uClibc-ng, glibc 和 musl。
一旦选择这个类型的工具链后,大量的选项将出现。最重要的选项如下:
- 更改构建工具链需要的内核头文件版本。
- 在构建交叉编译工具链的过程中,C 库也在被构建。这个库提供了用户空间应用程序和 Linux 内核之间的接口。为了知道如何与 Linux 内核“对话”,C 库需要访问Linux内核头文件(即来自内核的.h文件),它定义了用户空间与内核之间的接口(系统调用、数据结构等)。
- 由于此接口是向后兼容的,因此用于构建工具链的 Linux 内核头的版本不需要与我们打算在嵌入式系统上运行的 Linux 内核的版本完全匹配。它们只需要有一个与我们要运行的 Linux 内核版本相同或更老的版本。
- 如果我们使用的内核头文件比我们在嵌入式系统上运行的 Linux 内核更新,那么C 库可能使用的接口不是我们的 Linux 内核提供的。
- 在构建交叉编译工具链的过程中,C 库也在被构建。这个库提供了用户空间应用程序和 Linux 内核之间的接口。为了知道如何与 Linux 内核“对话”,C 库需要访问Linux内核头文件(即来自内核的.h文件),它定义了用户空间与内核之间的接口(系统调用、数据结构等)。
- 更改 GCC 编译器、binutils 和 C 库的版本
- 选择编译器选项(只有使用 uClibc 的时候需要)
- 工具链是否应该有 RPC 支持(主要用于 NFS)、宽字符支持、语言环境支持(用于国际化)、c++ 支持或线程支持。
- 根据我们选择的选项,Buildroot 菜单中可见的用户空间应用程序和库的数量将会改变:许多应用程序和库需要启用某些工具链选项。
- 当需要某个工具链选项来启用那些包时,大多数包都会显示注释。如果需要,可以通过运行 make uClibc -menuconfig 进一步优化 uClibc 配置。
- 但是请注意,Buildroot中 的所有包都是根据内置的默认 uClibc 配置进行测试的:如果通过删除 uClibc 的特性而偏离了这个配置,那么一些包可能不再构建。
值得注意的是,每当修改其中一个选项时,就必须重新构建整个工具链和系统。
这种方式也有好处:与 Buildroot 有很好的集成并且快速,只构建必要的内容
缺点是:make clean 后需要重新构建工具链,这需要时间。如果我们试图减少构建时间,可以考虑使用外部工具链。
2.1.4 外部工具链
外部工具链允许使用现有的预先构建的交叉编译工具链。
Buildroot知道许多著名的交叉编译工具链(来自用于 ARM 的 Linaro、用于 ARM 的 Sourcery CodeBench、x86-64、PowerPC 和 MIPS),并且能够自动下载它们,或者指向一个定制的工具链,可以下载,也可以在本地安装。
我们有三种方式使用一个外部工具链:
- 使用预定义的外部工具链配置文件,并让 Buildroot 下载、提取和安装工具链。Buildroot 已经知道一些 CodeSourcery 和 Linaro 工具链。从可用的工具链中选择工具链配置文件。这绝对是最简单的解决方案。
- 使用预定义的外部工具链配置文件,但不是让 Buildroot 下载和提取工具链,我们可以告诉 Buildroot 我们的工具链已经安装在系统的哪个位置。只需通过可用的工具链选择工具链配置文件,自动取消选择下载工具链,并用交叉编译工具链的路径填充工具链路径
- 使用一个完全的自定义的外部交叉编译工具链。
- 这对于使用crosstool-NG或使用Buildroot本身生成的工具链特别有用。
- 要做到这些,首先要在 Toolchain 配置选项中选择 Custom toolchain
- 我们需要填写 Toolchain path, Toolchain prefix 和 External toolchain C library 选项
- 接着需要必须告诉 Buildroot 我们的外部工具链支持什么。如果外部工具链使用 glibc 库,只需要知道工具链是否支持 c++ 以及它是否有内置的 RPC 支持。如果外部工具链使用 uClibc 库,那么您必须告诉 Buildroot 它是否支持 RPC、宽字符、语言环境、程序调用、线程和c++。
- 在执行的开始,Buildroot 会告诉我们所选选项是否与工具链配置匹配。
- 这对于使用crosstool-NG或使用Buildroot本身生成的工具链特别有用。
如果想为自己的项目生成一个定制的工具链,它可以在 Buildroot中 使用外部工具链,建议使用 Buildroot 或 crosstool-NG 来构建它。
- 这种构建工具链的方式的好处是:
- 允许使用众所周知且经过良好测试的交叉编译工具链。
- 避免交叉编译工具链的构建时间,这在嵌入式Linux系统的总体构建时间中通常非常重要。
- 允许使用众所周知且经过良好测试的交叉编译工具链。
- 坏处是:
- 如果预先构建的外部工具链有错误,可能很难从工具链供应商那里得到修复,除非使用Buildroot或Crosstool-NG自己构建外部工具链。
2.2 构建工具链
2.2.1 使用 buildrtoo 构建外部工具链
内置的内部工具链选项可以用来创建外部工具链。下面是构建内部工具链并将其打包以供Buildroot自身(或其他项目)重用的一系列步骤。
make menuconfig 进入配置菜单
Target options 选择 CPU 架构:
ToolChain 中选择配置交叉编译工具链的一系列选项:
- Toolchain type:选择 Buildroot toolchain
- custom toolchain vendor name:buildroot 构建的交叉编译工具链的名字是 <arch>-<vendor>-<os>-<libc>,这个选项对应 vendor 名字,配置成 s3c24x0,那么我们生成的工具链是 arm-s3c24x0-linux-glibc
- C library:选择 glibc
- Kernel Headers:内核头文件,选择手动指定,或者选择里面提供的内核版本,我这里选择手动指定 Manually specified Linux version
- linux version:Linux 版本,填入 4.4.174
- Custom kernel headers series:自定义内核头文件系列,选择 4.4.x
- Install glibc utilities:启用这个选项将为目标编译和安装 getconf、ldconfig、ldd 和 locale glibc实用程序。按需要选择
- Binutils Version:binutils 版本,保持默认
- Additional binutils options:额外的 binutils 选项,保持为空
- GCC compiler Version:GCC 编译器版本,选择为 gcc 8.x
- Additional gcc options:额外的 GCC 选项,保持默认为空就好,如果需要,就自己填写
- 语言支持:可以支持 C++ ,Fortran,支持 C++即可
- Enable compiler link-time-optimization support:此选项支持gcc中的链接时间优化(LTO)。
- Enable compiler OpenMP support:为编译器启用 OpenMP 支持。主要是在编译时采用并行处理
- Enable graphite support:此选项启用编译器中的石墨优化。这个选项看不懂
- Build cross gdb for the host:构建一个运行在主机上的交叉 gdb,并调试运行在目标机上的程序。它需要在目标上安装'gdbserver',即 BR2_PACKAGE_GDB_SERVER(Target packages-> Debugging, profiling and benchmark-> gdb )
- TUI support:此选项为gdb启用终端用户界面(TUI)
- Python support:此选项支持交叉 gdb 中的 Python 支持。
- Simulator support:此选项启用了交叉 gdb 中的模拟器支持。
- GDB debugger Version:版本选择 gdb 8.2.x
- Copy gconv libraries:gconv 库用于在不同字符集之间进行转换。如果需要存储和/或显示不同的字符集,请使用'y'。
- Gconv libraries to copy:设置为要复制的gconv库列表。为空以复制所有gconv库。只指定库的基本名称,忽略。so扩展。如:IBM850 ISO8859-15 UNICODE。注意,gconv 库占用 8 M(在 ARM 上)。
- Extra toolchain libraries to be copied to target:如果工具链提供了需要复制到目标文件系统的额外库,请在这里输入它们,以空格作为分割符分割。如 "libasan liblsan libtsan libubsan"
- Enable MMU support: MMU 支持
- Target Optimizations:为目标主机构建时使用的优化。注意:gcc优化级别是在构建选项中定义的。一般不会选择
- Target linker options:为目标构建时要传递给链接器的额外选项。
- Register toolchain within Eclipse Buildroot plug-in:这个选项告诉 Buildroot 生成必要的配置文件,通过 Eclipse Buildroot 插件使工具链出现在 Eclipse 中。
System configuration 中需要禁用掉系统初始化选项和 /bin/sh:
- Init system:选择 none
- /bin/sh :设置为 none
Target packages 中要禁用 busybox:
- busybox:选项设为空
Build options 中,需要设置一下源的路径,在执行构建的过程中,需要从不同的源地址下载各种不同的包,由于国内的和谐,所以需要更改为国内镜像:
- Mirrors and Download locations
- Kernel.org mirror:https://mirrors.tuna.tsinghua.edu.cn/kernel
- GNU Software mirror:https://mirrors.tuna.tsinghua.edu.cn/gnu
- Kernel.org mirror:https://mirrors.tuna.tsinghua.edu.cn/kernel
Filesystem images 中禁用 tar the root filesystem
配置完成后,保存退出,然后执行命令 make sdk,编译完成后,如下:
SDK 的压缩包存放再 $(O)/images 下,如果指定了 $(O),就是指定的目录,未指定则是根目录下output 目录。压缩包名为 arm-s3c24x0-linux-gnueabi_sdk-buildroot.tar.gz:
保存这个 tarball,因为它现在是一个工具链,我们可以在其他 Buildroot 项目中重用它作为外部工具链。
在 buildroot 下建立自己的工作源码目录 source,虽然可以按 buildroot 的架构去添加包之类的,但是太过麻烦,每次只有在编译后,才能去看源码,在开发中,更多的是便开发边修改边编译。
mkdir source cd source cp ../output/images/arm-s3c24x0-linux-gnueabi_sdk-buildroot.tar.gz ./ mkdir toolchain mv arm-s3c24x0-linux-gnueabi_sdk-buildroot.tar.gz ./toolchain
cd toolchain
tar -zxvf arm-s3c24x0-linux-gnueabi_sdk-buildroot.tar.gz
rm -rf arm-s3c24x0-linux-gnueabi_sdk-buildroot.tar.gz
现在要单独保存一下 toolchain 的配置文件:
- 若是之前未使用 xxx_defconfig 生成的 .config 配置文件,根目录下执行 make savedefconfig 会在当前根目录下生成一个 defconfig 文件
- 若是使用的 xxx_defconfig 生成的 .config,则执行 make update-defconfig 会自动更新 xxx_defconfig 文件
- 生成 defconfig 后,保存到根目录下的 configs 文件夹下, cp defconfig configs/s3c24x0ToolSDK_defconfig,在自己的 source 中也保存一份 cp defconfig source/s3c24x0ToolSDK_defconfig
保存后,执行一下 make clean,同时修改一下根目录下的 Makefile,在执行 make distclean 的时候,不要删除 dl 目录,当然如果每次都想重新下载源码包的另说,不用改。
1070 行中,带 dl 的删除掉即可。
同时若是使用的 git 托管代码,需要修改 .gitignore,将 dl 那一行删除即可。
修改完成后,执行一下 make distclean,后面需要针对自己的工程进行配置,我们可以直接使用我们编译出来的工具链,作为外部工具链使用。
make menuconfig 进入配置。
- Target options 中的配置与交叉编译工具链的配置相同
- Toolchain 中,
- 将 Toolchain type 改为 External toolchain,
- Toolchain 选择成 Custom toolchain
- Toolchain origin 改为 Pre-installed toolchain
- Toolchain path 填写为我们的路径:$(TOPDIR)/source/ arm-s3c24x0-linux-gnueabi_sdk-buildroot.tar.gz
- External toolchain gcc version:改为我们编译的版本 8.x
- External toolchain kernel headers series:头文件改为 4.4.x
- External toolchain C library:改为 glibc
- Toolchain has SSP support?:勾选上
- Toolchain has SSP strong support?:选上
- Toolchain has RPC support?:勾选上
- Toolchain has C++ support:勾选上
- 其他的选项都保持和编译工具链的时候一致。
使用外部工具链比较坑的是,执行 make 的时候,工具链又被编译了一遍。这个问题再看看
指定 make savedefconfig 保存配置:
mv defconfig configs/s3c24x0_defconfig
执行 make distclean,上传至 gitee 或是 github。
gitee 工程地址:https://gitee.com/cocosleep/project