Yocto项目摸象之旅--移植tinyalsa
从哪里 开始
最近参与一个base on Yocto的项目,首先需要将tinyalsa集成到系统里。有点抓虾的感觉,像没头苍蝇乱看一气,也没啥进展,不如退而结网,一步一个脚印的学习起来,笨鸟先飞,从几个基础概念先分析起来。本文将按照笔者自己的理解,将外文网站的资料进行重新组织,结合应用实例和经验,为摸象之旅做笔记。
Terminology Yocto中术语的翻译和理解
本章节列出Yocto网站的几个术语解释,我觉得理解和记住这几个术语对阅读Yotco开发手册和理解Yocto开发过程的概念是有所帮助的。
- Yocto Project: A Linux Foundation project that acts as an umbrella for various efforts to improve Embedded Linux. 项目的介绍,不赘述
- OpenEmbedded: The build system architecture promoted by the Yocto Project. OpenEmbedded其实是一个编译,打包,发布的自动化构建框架和交叉编译环境,这是由2003年成立的OpenEmbedded社区开发和维护的。2011年3月被Yocto项目采用和集成,成为Yocto项目推荐的构建(build)系统。
- BitBake: A tool that reads metadata and runs tasks. 是继承了OpenEmbedded 构建框架,基于BitBake 菜单“recipes”,指定一个包如何被构建,包括依赖list和源码位置,还有安装/删除包的指令等。OpenEmbedded 工具利用菜单获取和打包源码,编译和链接二进制文件,生成二进制包和创建可以boot的images文件。 对于入门者来说:理解BitBake和recipes可以类比make 和 makefile。我暂时也只能理解到这了,但是能把项目进行移植以及完成交叉编译安装的关键就是对BitBake规则的理解运用以及如何创建属于自己的recipes了。
- OpenEmbedded-Core: The common base set of metadata that BitBake uses. This metadata is shared between OpenEmbedded and the Yocto Project。OpenEmbedded-Core is a base layer of recipes, classes and associated files that is meant to be common among many different OpenEmbedded-derived systems and forms the basis of the new structure for OpenEmbedded. (其实没搞懂这个词,以后理解了再补充)
- Poky: A reference distribution used for test and release purposes by the Yocto Project. 一个用于测试和发布为目的参考分发,这是由Yocto项目自己创建的。
- Recipe: Meta data defining how bitbake is to configure, build and package a software project. 用好菜单和用好makefile一样,当然对于门外汉,这跟看天书区别不大。
- Layer: A collection of recipes and/or configuration used by bitbake. Typically each layer is organised around a specific theme, e.g. adding recipes for building web browser software. 分层是为了更清晰的组织文件,结构化设计, 这不难理解。据说之前OpenEmbedded 将recipes统统收在一个简单的仓库里, yocto项目里所谓的元数据(metadata) 以一种叫做“OpenEmbedded-Classic”的形式组织。到2010年,由于要管理的recipes越来越多,老的recipes收集和组织形式越来越困难,为了解决这个问题,recipe元数据开始分开存放在多层,而包含独立于平台和分发的元数据的最低层,被称之为"OpenEmbedded-Core"。 而应用特殊架构、特殊应用和分发依赖指令的层级能够从更低的层获取帮助来改写或者补充指令。除此之外,在核心层“core-layer”对于recipes的改变是以一种pull方式来管理,即代替直接commit他们的变化到仓库,开发者现在发送他们的补丁到邮件列表,补丁由维护者来merge。
指南里讲了什么
据说快速构建指南(Yocto Project Quick Build)可以帮助菜鸟先飞起来。
Yocto项目开发任务手册(Yocto Project Development Tasks Manual )大而全
Yocto项目项目总览和概念手册(The Yocto Project Overview and Concepts Manual)也不错
Yocto项目参考手册比较适合资深玩家(Yocto Project Reference Manual)
盲人摸象 摸哪就从哪开始
但是浏览了这些指南和手册,我还是不知道如何建立自己的recipes,如何让tinyalsa跑起来,可能是我总觉得bb能让编译变得更简单,总想找到那颗银色子弹。最后开始一遍又一遍的刷Yocto项目开发任务手册里的3.3. Writing a New Recipe。当看到3.3.21.1. Single .c File Package (Hello World!)这个例子.bb文件,我居然看到了最简单的编译方法—gcc。
SUMMARY = "Simple helloworld application"
SECTION = "examples"
LICENSE = "MIT"
LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302"
SRC_URI = "file://helloworld.c"
S = "${WORKDIR}"
do_compile() {
${CC} helloworld.c -o helloworld
}
do_install() {
install -d ${D}${bindir}
install -m 0755 helloworld ${D}${bindir}
}
于是我开始手敲一条条的编译,刚开始的
do_compile() {
${CC} tinyplay.c -o tinyplay
}
开始尝试编译,当然会报错,第一条错误是找不到include/tinyalsa/asoundlib.h,这个通过手册找到方法
CFLAGS_prepend = "-I ${S}/include "
继续报错,很多函数和文件都找不到,联想在android下的编译依赖,打开了Android.bp,结构如下
cc_library {
name: "libtinyalsa",
host_supported: true,
vendor_available: true,
vndk: {
enabled: true,
},
srcs: [
"mixer.c",
"pcm.c",
],
cflags: ["-Werror", "-Wno-macro-redefined"],
export_include_dirs: ["include"],
local_include_dirs: ["include"],
target: {
darwin: {
enabled: false,
},
},
}
cc_binary {
name: "tinyplay",
host_supported: true,
srcs: [
"tinyplay.c",
"log.c"
],
shared_libs: ["libtinyalsa"],
cflags: ["-Werror"],
target: {
darwin: {
enabled: false,
},
},
}
这个结构很清晰,首先需要编译mixer.c和pcm.c,生成tinyalsa.lib,然后后面的tools再根据lib继续编译链接最后生成可执行文件。下面是编译通过后的样子。
TARGET_CC_ARCH += "${LDFLAGS}" ------ 避免yocto QA报错,在yocto论坛找到的解决方案
do_compile() {
${CC} ${CFLAGS} mixer.c pcm.c -c -I -Wno-macro-redefined
ar -crv libtinyalsa.a mixer.o pcm.o
${CC} ${CFLAGS} tinymix.c -o tinymix -L. -ltinyalsa -I -Wall
${CC} ${CFLAGS} tinyplay.c log.c -o tinyplay -L. -ltinyalsa
${CC} ${CFLAGS} tinycap.c log.c -D__unused='__attribute__ ((unused))' -o tinycap -L. -ltinyalsa ----- 宏定义找不到,手动加吧。
${CC} ${CFLAGS} tinypcminfo.c -o tinypcminfo -L. -ltinyalsa -I -Wall
}
一顿操作过后,编译过去了,样子虽然丑了些,能用先用起来才是硬道理。后面安装就简单了:
do_install() {
install -d ${D}${bindir}
install -m 0755 tinycap ${D}${bindir}
.............................
一切ok后,我在嵌入的系统上找到了这几个小工具,初战告捷。
其实我已经站到了巨人的肩膀上,跳吧
回想起来,刚开始接触新玩意,心理总被恐惧和懒惰支配,但只要努力寻找答案,阅读手册,冲过这道关卡,后面就是水到渠成的事情了。大系统已经有牛人搭建好了,我们已经站在了巨人的肩膀上,要勇于尝试,跳吧,呵呵。