一、 YOCTO 认识简介
- YOCTO 项目历史
YOCTO 项目定义如下:
"The Yocto Project provides open source, high-quality infrastructure and tools to help developers create their own custom Linux distributions for any hardware architecture, across multiple market segments. The Yocto Project is intended to provide a helpful starting point for developers."
YOCTO 项目是一个开源协作的项目,为使用者提供模板、工具和方法以帮助使用者创建基于 Linux 系统的定制化的嵌入式产品而不用在意具体的硬件架构。其中 OpenEmbedded-Core 是核心的系统模块,由 OpenEmbedded 项目提供。
2. OpenEmbedded
OpenEmbedded-Core元数据集合提供了 Poky 构建工具的引擎。它旨在提供核心功能,并且需要尽可能干净。支持 5 种不同的处理器架构(ARM, x86, x86-64, PowerPC, MIPS 和 MIPS64)
3. Poky
Poky 的目标是提供嵌入式开发者需要的所有特性。
4. Bitbake
Bitbake 是一个用来解析 Python 和 shell 脚本混合代码的任务调度器,解析后生成并运行任务。
5. Metadata
Metadata, 即元数据,是由 Python 和 Shell 脚本组成的文本文件。Poky 使用元数据对 OpenEmbedded-Core 进行扩展并增加了两个不同的层,分别是:
Meta-yocto: 该层提供默认和受支持的发行版,视觉品牌和元数据跟踪信息(维护者,上游状态等)Meta-yocto-bsp: 提供了用于Poky的硬件参考板支持
二、 制作一个基于 Poky 的系统
1. 配置一个主机系统,可选用以下系统进行,若需要的系统不在以下之列,也并不意味着不可配置,只是需要注意在配置过程种可能会出现一些出乎意料的问题。2. 安装 Poky 实例
- 不同系统安装命令实例
实例 1 :安装在 Debian 上使用以下安装命令(针对 “无头系统”)
$: sudo apt-get install gawk wget git-core diffstat unzip texinfo build-essential chrpath
如果自己的系统具备图形支持,运行以下命令:
$: sudo apt-get install libsdl1.2-dev xterm
以上的命令与 Ubuntu 的版本兼容
实例 2 :安装在 Fedora 上使用以下安装命令(针对 “无头系统”)
$: sudo yum install gawk make wget tar bzip2 gzip python unzip perl patch diffutils diffstat git cpp gcc gcc-c++ eglibc-devel texinfo chrpath ccache
如果自己的系统具备图形支持,运行以下命令:
$: sudo yum install SDL-devel xterm
无头系统 :指的是一个计算机系统或设备被配置成无显示器(无头)、无键盘鼠标运行的状态。
b. 下载 Poky 源码
$: git clone git://git.yoctoproject.org/poky --branch daisy
c. 准备编译环境
$: source poky/oe-init-build-env [build-directory]
d. 认识 conf 文件,可以用来配置编译过程的各个方面,PATH : [build-directory]/conf/local.conf
例如:编译针对的目标机器,交叉编译链,优化编译下载时间。
最经常修改的几个变量如下:
BB_NUMBER_THREADS ?= "${@oe.utils.cpu_count()}"
PARALLEL_MAKE ?= "-j ${@oe.utils.cpu_count()}"
MACHINE ??= "qemux86"
Poky 支持的目标机器如下:
Beaglebone,genericx86, genericx86-64, mpc8315e-rdb,edgerouter,qemuarm,qemumips,
qemumips64,qemuppc, qemux86-64,qemux86
若要支持其他的目标机器,只需要提供对应厂商的 BSP 层。
e. 编译目标镜像文件
$: ls meta*/recipes*/images/*.bb
$: bitbake
例如 core-image-full-cmdline, 运行下列命令:
$: bitbake core-image-full-cmdline
f.在 QEMU 中进行仿真运行,运行的命令格式如下,前提是 MACHINE 设置生成的目标机器就是用于仿真的,如 MACHINE ??= "qemux86"
$: runqemu
三、 掌握 Bitbake 工具
1. Bitbake 使用的元数据(metadata)主要分以下三种类型Configuration( .conf ) //定义全局内容以提供信息和配置 recipes 的工作方式
Classes( .bbclass ) //由系统使用并可由 recipes 进行继承
Recipes( .bb & .bbappend ) //和 Classes 一起描述了运行的任务并提供需要的信息以使得 Bitbake 生成需要的任务链
2. Dependencies
为了完成依赖,Recipes 需要在编译过程中声明所需要的。
DEPENDS :编译时依赖
RDEPENDS :应用运行时依赖
Recipes 如果不存在依赖关系就以并行方式运行,若存在就以串行的符合依赖关系的方式进行。
3. 远程文件下载
a. 最通用的几种方式:http://, https://, ftp://
当执行 do_fetch 任务的时候,会检查 SRI_URI 的内容,例如:libjson recipe Path:meta/recipesdevtools/libjson/libjson_0.9.bb, 相关变量如下:
SRC_URI = "http://oss.metaparadigm.com/json-c/json-c-${PV}.tar.gz"
SRC_URI[md5sum] = "3a13d26...de24abae"
SRC_URI[sha256sum] = "702a486...39439475
在下载完成后会对 sha256sum 和 md5sum 与 recipe 中的值进行比较,若一致,则创建 ${DL_DIR}/json-c-0.9.tar.gz.done 文件以标识下载的资源被成功下载与校验,下次需要该文件时就能安全使用并无需再次进行校验
PV 变量含义:包的版本
解析后结果如下:http://oss.metaparadigm.com/json-c/jsonc-0.9.tar.gz
结果保存在 DL_DIR变量指向的位置,默认 DL_DIR = build/downloads,也可以自定义
b. 其他方式,例如 git://URL
当执行 do_fetch 任务的时候,会检查 SRI_URI 的内容,例如:linux-firmware recipe
Path: meta/recipes-kernel/linux-firmware/linux-firmware_git.bb
SRCREV = "600caefd83a406540b2a789be6415e44c9b87add"
...
SRC_URI =
"git://git.kernel.org/pub/scm/linux/kernel/git/firmware/linuxfirmware.git"
结果会保存在:${DL_DIR}/git2/
c. 优化源码下载
为增加源码下载的健壮性, Poky 提供镜像机制,可通过对其进行配置实现以下两点
.提供一个首选的服务端进行下载
.提供备选的服务端进行下载
相关的变量如下:PREMIRRORS, MIRRORS
4. 将网络访问 Disable
有时需要将网络访问 Disable, 主要有以下几个方面的原因。
.政策原因
.网络数据带宽大
.编译速度受限
.缺少网络访问资源
Disable 的方式如下:
PATH:build/conf/local.conf
添加如下:BB_NO_NETWORK = "1"
5. Bitbake 的任务
$: bitbake //运行一系列任务
$: bitbake -c //运行指定的任务
$: bitbake -c listtasks //输出任务列表
具体可参考下表:
Bitbake 参数 |
描述 |
示例 |
备注 |
直接编译/执行一个 recipe |
bitbake core-image-minimal |
| |
. -c task |
执行某个 recipe 的某个任务 |
bitbake -c build glibc |
示例表示执行 glibc 的 do_build 任务 |
. -c listtasks |
显示某个 recipe 可执行的任务 |
bitbake -c listtasks glibc |
查询 recipe 支持哪些任务 |
. -c <**.bb> |
用 bitbake 直接执行这个 bb 文件 |
bitbake -b rtl8188eu-driver_0.1.bb |
单独编译 rtl8188eu-driver 这个任务 |
. -s |
显示所有可以 bitbake 的包 |
bitbake -s | grep hello |
例如自己在一个 Layer 下面安装了一个 hello.bb, |
. -v |
显示执行过程 |
|
|
. -k |
有错误发生时也继续构建 |
|
|
. -e |
显示当前的执行环境 |
查找包的原路径: |
|
. -vDDDD |
打印一些调试信息 |
bitbake -vDDDD -c build glibc |
|
. -g |
显示一个包在 bitbake 时与其他包的依赖关系,生成依赖图 |
bitbake -g glibc |
在当前目录生成一些文件 |
下面以 SemiDrive 为例执行相关命令并查验结果
说明:本例已经在服务器系统为 Ubuntu16.04 下搭建好了 Yocto 环境,并通过以下命令进入 docker 运行环境以便于使用 root 权限,有root 权限的不需要对 docker 进行配置。
|
在使用 bitbake 之前,需要先设置下环境,如下所示:
DISTRO=cluster-qt MACHINE=x9h_ref source sd_setup.sh -b build-x9ref //设置环境 export LANG=en_US.UTF-8 |
- bitbake -s
- bitbake core-image-base //编译文件系统
- bitbake -c listtasks core-image-base
支持任务如下:
- bitbake -c menuconfig virtual/kernel //virtual/kernel 用来指定 kernel
do_menuconfig 执行失败,原因分析:可能是因为通过远程控制的方式执行而导致的,在远程控制下执行该命令可能需要额外的配置
解决方式:
sudo apt-get install tmux 或者 sudo apt-get install screen
sudo apt-get install build-essential
sudo apt-get install libncurses5
apt-get install libncurses5-dev
- bitbake -c compile virtual/kernel
- bitbake -c compile_kernelmodules virtual/kernel
- bitbake -c deploy virtual/kernel
- bitbake -c compile u-boot //单独编译 u-boot
在 build-x9ref/local.conf 目录下添加变量 UBOOT_MACHINE=“***_defconfig” 后再次编译
在 SemiDrive 中因为无搭配相应的 uboot 源码,因此这里不再测试 uboot 的编译。
- bitbake -c clean virtual/kernel //清除编译结果
bitbake -c cleansstate virtual/kernel
bitbake -c cleanall virtual/kernel
6. 使用 _append / _preappend 扩展任务
Do_install_append() {
# Do my commands
}
7. 生成根文件系统镜像
.生成 rootfs 目录
.创建要求的文件
.根据特定要求打包文件系统
.条件允许下,则进行压缩
以上四个步骤通过子任务 do_rootfs 执行生成。
四、 解析临时编译目录
1. build 目录介绍conf: 用来控制 Poky 和 Bitbake
downloads: 缓存下载的压缩包文件
sstate-cache: 保存包数据快照,主要用来加速编译过程
tmp: 临时编译目录
2. Bitbake 的基本工作流程
.Fetching
.Source preparation
.Configuration and building
.Installing
.Wrapping the sysroot
.Creating the package
3. 解析 tmp 目录
最重要的几个目录如下:
.Deploy //包含了编译的输出结果,镜像、包、SDK
.Sysroots //包含了在编译过程中使用到的库、头文件、工具
.Work //包含了源码、任务配置、执行 Log、生成的包的内容
五、 深入元数据的使用
Bitbake 中使用了大量的元数据,为了能更好的使用 Poky,需要对其进行掌握。
- 追踪元数据的变化
$: bitbake -e | grep //当需要观察变量在编译过程中的变化时,可使用该命令
- 变量赋值
FOO = “bar”
- 变量扩展
A = “aval”
B = “pre${A}post”
结果:A=“aval” B=”preavalpost”
注意:变量只有在实际使用的时候才进行扩展
A =“aval”
B = “pre${A}post”
A = “change”
结果:A=“aval” B=”preachangepost”
- ?= 使用
A ?= “aval”
表示若变量 A 已有默认值,则使用默认值,否则赋值 “aval”
- ??= 使用
A ?? =”somevalue”
A ?? =”someothervalue”
赋值发生在分析的最后阶段,因此以上语句最终赋值为 ”someothervalue”
- 中间变量扩展
T = "123"
A := "${B} ${A} test ${T}"
结果:A = “test 123”
注意::= 表示对变量进行立即扩展,因为变量 B 和 A 在这之前皆为空,因此最终结果 A = “test 123”
- 前置(+=) 与 后置 (=+) 的使用
B = "bval"
B += "additionaldata"
C = "cval"C =+ "test"
结果:B = bval additionaldata , C= test cval
注意:中间是有空格的
若要不带空格,则使用如下符号
.= 与 =. 或者 B_append 与 C_prepend
- 条件元数据集
OVERRIDES = "architecture:os:machine"
TEST = "defaultvalue"
TEST_os = "osspecificvalue"
当 os 在 OVERRIDES 表示的集合中时,TEST 赋值为 osspecificvalue 。
- 条件前置添加
DEPENDS = "glibc ncurses"
OVERRIDES = "machine:local"
DEPENDS_append_machine = " libmad"
当 machine 在 OVERRIDES 表示的集合中时,DEPENDS 进行扩展为 glibc ncurses libmad
- 头文件导入的两种方式
- include
- require
Yocto 中主要还是采用 include 的方式
- Python 变量扩展
VARIABLE = "${@}"
例如:
DATE = "${@time.strftime('%Y%m%d',time.gmtime())}"
- 定义可执行的元数据
可以在 .bb 或者 .bbclass 中使用 shell 脚本如下:
do_mytask () {
echo "Hello, world!"
}
也可以使用如下方式插入 python 代码:
python do_printdate () {
import time
print time.strftime('%Y%m%d', time.gmtime())
}
- 继承机制
intherit autotools //指导 Bitbake 继承 autotools.bbclass
六、 YOCTO 项目开发
- YOCTO SDK
Software development kit (SDK) 就是一系列用于开发和调试的工具和文件。这些工具中包含编译器、连接器、调试器、外部库的头文件以及二进制文件,也可能包含定制的功能和应用,这一系列的工具就叫做工具链。当 Poky 通过 Bitbake 执行任务时,同样需要工具链去执行编译和连接,而这个叫做内部的工具链,只能为内部的编译系统所使用。
- 创建基于镜像的 SDK
当我们编写并测试我们的应用时,我们只关心应用本身,因此需要创建一个 SDK 包用于安装在任何其他电脑上,其上的工具链就可以配合 Poky 环境为外部使用。
a. $: bitbake core-image-full-cmdline -c populate_sdk
b.可在以下路径找到对应的二进制脚本文件 build/tmp/deploy/sdk/pokyeglibc-x86_64-core-image-full-cmdline-armv5te-toolchain-1.6.sh.
c. 运行脚本文件如下所示:
脚本安装后提供以下内容:
environment-setup-armv5te-poky-linux-gnueabi:设置使用工具链所需要的所有环境变量
site-config-armv5te-poky-linux-gnueabi:工具链创建所使用的文件
version-armv5te-poky-linux-gnueabi:版本以及时间戳信息
sysroots:生成 SDK 时复制的文件系统,包括其中的二进制文件,头文件,库文件
armv5te-poky-linux-gnueabi:包含针对 ARM 的文件
x86_64-pokysdk-linux:包含针对 x86-64 兼容的机型文件
3. 创建一个通用的 SDK
$: bitbake meta-toolchain
4. 使用 SDK
a. $: source /opt/poky/1.6/environment-setup-armv5te-poky-linux-gnueabi
b. $: ${CC} hello-world.c -o hello-world
c. $: file hello-world
编译 Linux 内核则可通过以下方式
a. $: source /opt/poky/1.6/environment-setup-armv5te-poky-linux-gnueabi
b. $: unset LDFLAGS
c.$: make defconfig
d. $: make uImage
七、 启动自制的嵌入式 Linux
本例讲述如何启动自制的 Linux,不同的厂商会提供不同的层也就是 layer, 例如有以下的 layer 层:
假使手中的板子是 Wandboard, 因为 Wandboard 使用的是 Freescale 的 i.MX6 Soc,因此为在 Yocto 工程中需添加以下的 BSP layer
meta-fsl-arm: 添加了 Freescale 的基本机器类型并提供了基本的 BSP 支持
meta-fsl-arm-extra:支持基于 Freescale Soc 上设计的第三方的板子,例如 Wandborad, 同时需要 meta-fsl-arm,因为其提供了基本的支持。
更多的信息可以参考以下的网址:http://freescale.github.io/
a. 首先下载对应的 BSP layer
$: git clone --branch daisy https://github.com/Freescale/meta-fsl-arm-extra.git $: git clone --branch daisy git://git.yoctoproject.org/meta-fsl-arm |
下载完成后目录结构应如下所示:
b. 配置环境
$: source poky/oe-init-build-env build-wandboard |
c. 在 build-wandboard/conf/bblayers.conf 文件中做如下添加
d. 编译镜像
$: MACHINE=wandboard-solo bitbake core-image-sato |
e. 烧写镜像
$: sudo dd if=core-image-sato-wandboard-solo.sdcard of=/dev/sdX bs=1M |
关于 BSP 调试与进阶的更多博文内容可以通过关注大大通,或者扫描以下二维码即可链接到上一篇博文《 S32V NFS 环境搭建 》, 二维码如下所示: |
评论