iMX6Ull采用Yocto构建嵌入式Linux系统之Yocto开发一般过程

Yocto的开发一般包括:创建Layers、添加新的软件包、扩展或定制系统镜像以及移植到新的硬件平台(增加新的MACHINE)等。

创建Layers

Yocto使用的是OpenEmbeded来构建系统,并且支持以Metadata的形式来组织管理构建系统所使用的软件包、源代码、配置信息等。Metadata一定程度上可以理解为Layers,实际上就是一个个的文件夹(这些文件夹通常以meta-xxx的形式命名)。采用Layers的方式管理源数据,有利于保持模块化的设计方式,一个Layer包含了一些特定功能所需要的源数据,各Layer之间互不干扰,当所构建的系统需要的功能发生变化时,只需要修改该功能对应的Layer即可,保持了功能的独立性及模块化设计。

创建Layers的步骤

1、查看已存在的Layers:通常来说,

http://layers.openembedded.org/layerindex/layers/ 列出了目前已经存在的公共的开放的Metadata,当需要创建新的Layer时,可以先在该网站上查看下是否已经有了现成的Metadata可供使用,如果有,直接使用即可。如果没有,就需要自己新创建。

2、创建一个文件夹,用来存放Layer里的数据,通常将该文件夹命名为meta-xxx。例如:meta-mylayer、meta-GUI_XYZ、meta-mymachine等。

3、创建Layer配置文件。在新创建的Layer文件夹下(例如:meta-mylayer)创建conf/layer.conf 文件,该layer.conf文件基本框架如下:

# We have a conf and classes directory, add to BBPATH
BBPATH .= ":${LAYERDIR}"

# We have recipes-* directories, add to BBFILES
BBFILES += "${LAYERDIR}/recipes-*/*/*.bb \
${LAYERDIR}/recipes-*/*/*.bbappend"

BBFILE_COLLECTIONS += "mylayer"
BBFILE_PATTERN_mylayer = "^${LAYERDIR}/"
BBFILE_PRIORITY_mylayer = "5"
LAYERVERSION_mylayer = "3

其中,各变量含义如下:

(1). BBPATH:将新增加的Layer路径增加至全局变量BBPATH中,BitBake在构建系统时,会根据该变量找到相对应的Layer。

(2). BBFILES:将新增加的Layer中的Recipe文件(即:.bb或.bbappend文件)增加至全局变量BBFILES中,BitBake在构建系统时,会根据该变量找到对应的recipe文件。

(3). BBFILE_COLLECTIONS:将layer名字追加到BBFILE_COLLECTIONS变量,即将Layer的文件夹名字meta-xxx中的xxx赋值给BBFILE_COLLECTIONS 即可。

(4). BBFILE_PATTERN:BBFILE_PATTERN变量为正则表达式,用来匹配BBFILES所在的层,按照基本框架修改即可。

(5). BBFILE_PRIORITY:Layer的优先级。当不同的Layer中定义了相同的recipe时,将按照BBFILE_PRIORITY所对应的高优先级使用相对应的recipe文件。

(6). LAYERVERSION:定义了Layer的版本信息。

4、增加内容。根据Layer的类型,有的Layer会增加machine和distro配置,因此,需要在Layer下的conf/machine/文件中添加机器配置,在该层的conf/distro/文件中添加发行版配置。

创建Layers时的一些原则

考虑到创建的Layers易于维护,且不会影响到其他Layer,创建Layers时,应该遵循一些原则:

  1. 避免覆盖其他Layer中的recipe。也就是说,尽量不要将其他Layer中的整个recipe复制到新创建的Layer中,并对其进行修改。而是采用追加文件.bbappend文件的方式,覆盖仅需要修改的部分。

  2. 避免重复包含文件。对于需要包含文件的recipe,使用.bbappend文件或者使用相对于原始Layer的相对路径在进行应用,例如:使用require recipes-core/package/file.inc代替require file.inc。

使能Layer

创建了新的Layer需要使能之后才能参与到系统的构建过程中。在build/conf/bblayers.conf中定义了参与构建系统使用到的Layers。对于iMX6ULL,Freescale官方提供了imx-setup-release.sh脚本用于修改build/conf/bblayers.conf文件,在初始化Yocto构建目录时,调用imx-setup-release.sh脚本。因此,修改imx-setup-release.sh脚本即可,修改方式如下:

新增加的echo "BBLAYERS += " ${BSPDIR}/sources/meta-bird-imx6ull "" >> $BUILD_DIR/conf/bblayers.conf就是将build/conf/bblayers.conf中的BBLAYERS变量增加新增的meta-bird-imx6ull。

使用.bbappend文件

用于将Metadata附加到其他recipes的recipes称为BitBake附加文件。 BitBake附加文件使用.bbappend文件类型后缀,而要附加Metadata的相应的recipes则使用.bb文件类型后缀。通过.bbappend文件,可以使得创建的Layer在不拷贝其他recipe到新建的Layer中的情况下,以附加或改写的方式改变其他Layer中的内容。直观来看,就是新建的Layer中的.bbappend文件,与需要修改或附件额外内容的.bb文件处于不同的Layer。

附件文件(.bbappend)必须和对应的recipes(.bb)文件名(或文件名与版本号)一致。例如:附件文件someapp_2.1.bbappend只对someapp_2.1.bb文件有效,也就是说,当someapp_2.1.bb文件升级至someapp_2.2.bb或其他版本的.bb文件时,相应的附件文件someapp_2.1.bbappend也要进行相应的升级,如someapp_2.2.bbappend。在构建系统过程中,当BitBake检测到某个.bbappend文件没有对应的.bb文件时,将会报错。

设置Layer优先级

每一个Layer都分配了一个优先级。当在不同的Layer中,出现了同样的recipe时,Layer中分配的优先级的值越大,将优先使用该Layer中的recipe。优先级的值同样会影响到.bbappend文件。如,BBFILE_PRIORITY_mylayer = "5"。 需要注意的是:有可能会出现低版本但是拥有高优先级的recipe优先执行的情况。

Layers管理

BitBake提供了Layer管理工具,用来查看Layers的一些基本信息。使用方式如下:

$ bitbake-layers command [arguments]

可以使用的命令如下:

  • help:帮助命令。

  • show-layers: 显示当前配置的Layer。

  • show-recipes: 显示可用的recipes以及recipes提供的layers。

  • show-overlayed: 显示覆盖的recipes。高优先级Layer中的recipe将覆盖其他低优先级Layer中相同的recipes。

  • show-appends: 显示.bbappend文件,以及对应的recipe文件。

  • show-cross-depends: 显示不同Layer中recipes的依赖关系。

增加COPYING.MIT和README文件

在Layer中,增加相应的COPYING.MIT文件和README文件是比较推荐的做法。

自定义系统镜像文件

实际工程应用中,需要根据不同的需求定制化系统。该小节概要性的描述了定制化系统的几种方法,先对定制化系统的方法有个整体性的认识,后续章节会对定制化系统的详细步骤进行讲解。Yocto提供了几种定制化系统的方法,可以根据实际应用场景选择不同的方法。

通过local.conf增加软件包

通过直接修改build/conf路径下的local.conf配置文件增加软件包是最简单的定制系统的方法之一。同时,由于是直接修改local.conf文件,这种方法一般来说仅适用于在系统image文件中增加软件包。当使用local.conf文件中的变量增加软件包时,需要注意的是,增加的软件包对于所有的系统image文件都有效。例如,在local.conf文件中增加如下语句,将在生成的系统image文件中安装“strace”软件:

IMAGE_INSTALL_append = " strace"

注:等号与软件包名“strace”之间的空格是必须的。 同样的,修改local.conf中的IMAGE_INSTALL_append将影响所有的image文件。如果需要只针对某一特定的image文件有效,可以通过扩展语句的方式实现,如:

IMAGE_INSTALL_append_pn-core-image-minimal = " strace"

采用该方式,新增加的strace软件只对core-image-minimal 系统image文件有效。

通过IMAGE_FEATURES、EXTRA_IMAGE_FEATURES增加软件包

另一种增加软件包的方法是通过IMAGE_FEATURES、EXTRA_IMAGE_FEATURES变量。尽管IMAGE_FEATURES、EXTRA_IMAGE_FEATURES这两个变量在用法上几乎一致,但是,在实际使用过程中,IMAGE_FEATURES一般用于recipes内,而EXTRA_IMAGE_FEATURES一般用于build/conf路径下的local.conf文件中。总的来说,这两个变量最终都是通过修改IMAGE_INSTALL变量来实现的,该方法在实际过程中并不常用。

通过.bb文件定制系统镜像

比较常用的一种定制系统镜像的方法是使用.bb文件。可以通过创建一个recipe来定义镜像文件需要增加的软件包。例如,在新创建的.bb文件中,增加如下代码:

另一种方法,是通过在已经存在的系统镜像文件上进行修改。例如:如果想构建一个基于core-image-sato的系统镜像文件,但是,需要额外的增加strace软件包,可以通过拷贝/sources/poky/meta/recipes-sato/images/core-image-sato.bb文件,将其命名为一个新的.bb文件,然后在新的.bb文件中通过增加以下代码,实现strace软件包的增加:

IMAGE_INSTALL += "strace"

推荐使用这种方法。

通过Package Groups定制系统镜像

对于复杂的应用,可以使用package groups的方式定制系统镜像。例如:/sources/poky/meta/recipes-core/packagegroups/packagegroup-base.bb文件。

自定义主机名

一般来说主机名和系统中配置的主机名(/etc/hostname)是一致的。例如:如果MACHINE等于“qemux86”,那么写入/etc/hostnam的主机名就是“qemux86”。可以通过修改Recipe base-files中的hostname变量来实现自定义主机名。例如,可以在某一个.bbappend文件中使用如下代码:

hostname="myhostname"

或者,在配置文件中使用如下代码:

hostname_pn-base-files = "myhostname"

即可。

创建Recipes

Metadata(Layer)是由一些Recipes组成的。从形式上来看,Recipes是在metadata文件夹下的一些文件夹(同样的,惯例以recipes-xxx命名)。recipes-xxx文件夹中的recipes(.bb文件)是Yocto工程的最基础组成部分。OpenEmbedded构建系统使用的软件包等组件都是在recipe中定义的。

创建基础Recipes

有两种比较简便易行的创建新的recipes的方法:

  • recipetool:Yocto提供的工具,基于源文件自动创建基础recipe。

  • Exitsing Recipes:在一个功能需求相似的已有recipe基础上修改。

教程中着重讲解第二种方式。通常,recipe中定义了一些变量用于定义需要使用的软件包,其基本框架如下:

DESCRIPTION = ""

HOMEPAGE = ""

LICENSE = ""

SECTION = ""

DEPENDS = ""

LIC_FILES_CHKSUM = ""

SRC_URI = ""

存储和命名Recipes

通常,创建了基础的recipes之后,需要按照一定的目录框架将recipes放在合适的位置,以确保OpenEmbedded构建系统时能够找到。OpenEmbedded是通过Layer(meta-xxx文件夹)下的conf/layer.conf中的变量BBFILES找到构建过程中所使用的recipes。其典型的应用如下:

BBFILES += "${LAYERDIR}/recipes-//.bb \ ${LAYERDIR}/recipes-//.bbappend"

因此,必须确保新创建的recipe在layer中的正确路径。 此外,对于recipe文件的命名,也应该按照一定的规则,如下所示:

basename_version.bb

使用小写字母字符,并且不包括保留的后缀-native,-cross,-initial或-dev。例如:cups_1.7.0.bb、gawk_4.0.2.bb、irssi_0.8.16-rc1.bb等。

编译Recipes

对于新创建的recipe,往往需要不断的修改编译、反复迭代才能逐步实现完善最终的功能。在使用fls-setup-release.sh脚本初始化Yocto构建目录后,将自动进入build目录,在该路径下,通过如下命令即可编译recipe:

$ bitbake basename

其中,basename是recipe的文件名。在编译过程中,OpenEmbedded编译系统会为每一个recipe创建一个临时的文件夹,用来存放解压文件、日志文件等。每一个recipe的临时文件夹都按照如下的方式组织:

例如:假设生成的系统架构为qemux86-poky-linux,recipe文件为foo_1.3.0.bb ,那么,将生成如下的文件:

/build/tmp/work/qemux86-poky-linux/foo/1.3.0-r0

在该路径下,还可以看到image、packages-spilt和temp等文件夹。编译之后,可以通过查看这些文件夹里的内容确定编译过程是否正确。

获取源码

构建系统的过程,实际上是将一些软件源码编译成系统镜像文件的过程,因此,recipe的第一步是定义如何获取相关的软件源码。在recipe中,通过SRC_URI变量定义了软件源码的位置。BitBake编译系统镜像文件的过程可以分为几个任务分步完成的,其中一个任务do_fetch会根据SRC_URI变量值的前缀确定使用哪个fetcher从什么地方获取软件源码。获取源码结束后,do_patch任务也会根据SRC_URI变量值来打补丁。

recipe中的SRC_URI定义了软件源码的唯一地址。推荐在SRC_URI变量中定义的软件源码地址包含${PV}的方式,以便在获取软件源码过程中使用recipe文件名中定义的版本,同时,后续当需要升级软件版本时,只需要将recipe文件名进行版本号升级即可。例如:meta/recipes-devtools/cdrtools/cdrtoolsnative_3.01a20.bb的recipe中,SRC_URI变量值使用了“PV”值,

还可以通过SCM(Source Control Managers)获取软件源码,例如Git。对于Git来说,还需要在recipe中定义SRCREV和SRCPV变量值,例如:meta/recipeskernel/blktrace/blktrace_git.bb:

SRCREV = "d6918c8832793b4205ed3bfede78c2f915c23385"

PR = "r6"

PV = "1.0.5+git${SRCPV}"

SRC_URI = "git://git.kernel.dk/blktrace.git \

file://ldflags.patch"

其中,SRCPV = "${@bb.fetch2.get_srcrev(d)}"

此外,如果SRC_URI指向的软件源码地址不是从SCM,而是远程服务器或其他地址的软件源码包,则需要定义相对应的软件源码包校验值,以便BitBake在编译时通过校验值确定软件包的完整性。例如:

SRC_URI = "${DEBIAN_MIRROR}/main/a/apmd/apmd_3.2.2.orig.tar.gz;name=tarball \ ${DEBIAN_MIRROR}/main/a/apmd/apmd_${PV}.diff.gz;name=patch

SRC_URI[tarball.md5sum] = "b1e6309e8331e0f4e6efd311c2d97fa8" SRC_URI[tarball.sha256sum] = "7f7d9f60b7766b852881d40b8ff91d8e39fccb0d1d913102a5c75a2dbb52332d"

SRC_URI[patch.md5sum] = "57e1b689264ea80f78353519eece0c92" SRC_URI[patch.sha256sum] = "7905ff96be93d725544d0040e425c42f9c05580db3c272f11cff75b9aa89d430"

解压源码

如果获取的源码是压缩包的形式,在编译过程中,do_unpack任务会将压缩包进行解压。

补丁代码

有时在获取了软件源码之后,需要进行打补丁。在SRC_URI中以.patch、.diff或者是这些后缀的压缩包(如:diff.gz)都是补丁代码。在执行do_patch任务时,会自动的应用补丁。

License

在recipe中,需要包含LICENSE和LIC_FILES_CHKSUM变量。例如:

LICENSE = "GPLv2"

LIC_FILES_CHKSUM = "file://COPYING;md5=xxx"

LICENSE变量确定了软件采用的license,通常来说,可以在软件包的说明,例如,COPYING、LICENSE、README等文件中找到对应软件包的License定义,也有可能会在软件源码文件的头部找到相关的信息。

配置Recipes

大多数软件在编译前,提供了一些方式用于配置软件。通常来说,采用带有参数选项的脚本或配置文件是比较典型的方式。在OpenEmbedded编译过程中同样如此。其中,软件配置的主要一部分是检测软件编译过程中的依赖关系,可以通过recipe文件中的DEPENDS变量值,指定该软件包的依赖项,这些依赖项通常会在软件包的描述文档中有所涉及。 一般来说,可以将软件包的配置项分为以下三类:

  1. Autotools:对于提供了configure.ac文件的软件包,一般采用的是Autotools工具进行配置,对于这种情况,直接修改configure.ac文件即可。但是需要注意的是,由于使用了Autotools,需要在recipe中引入autotools class。并且在recipe中不需要在包含do_configure任务。

  2. CMake:对于提供了CMakeLists.txt文件的软件包,一般采用的是CMake工具进行配置,对于这种软件包,只需要直接修改CMakeLists.txt配置文件即可。同样的,由于使用了CMake,因此,需要在recipe中引入cmake class。并且在recipe中不需要在包含do_configure任务。

  3. Other:对于没有采用Autotools或CMake的软件包,并且需要进行配置的话,则需要在recipe中提供do_configure任务,用于编译前配置软件包。当然,如果软件包不需要进行任何的配置除外。

在OpenEmbedded编译完成后,可以通过log.do_configure文件查看软件包的配置项,以确定配置项是否成功。

编译recipe

在获取、解压、配置软件源码之后,BitBake通过do_compile任务自动开始编译recipe。

安装应用

Linux下安装软件大致过程如下:

  1. 建立安装目录

  2. 拷贝类库

  3. 拷贝可执行程序

  4. 根据需要选择性配置和启动服务

在编译recipe过程中的do_install任务,将构建的文件及其层次结构复制到生成的镜像文件相应的位置中,即可实现软件的安装。不同的软件编译方式,其安装方式也会有所不同:

  • Autotools以及CMake:如果使用的是Autotools或者CMake编译软件,则OpenEmbedded构建系统会自动使用Autotools或者CMake中的安装方式进行软件的安装,因此,不需要在recipe文件中增加do_install函数;但是,如果需要在安装软件增加额外的文件(这些文件未被Autotools或CMake在安装过程中使用),则可以在recipe文件中增加do_install_append函数来进行安装,安装方式和手动安装一致。

  • 手动安装:在recipe文件中,通过定义do_install函数,可以用来安装相应的软件。在do_install函数中,必须先使用install -d命令,来创建一个安装目录,然后就可以使用install命令来手动将编译好的软件安装(复制)到对应的文件夹中。

    关于install更多的方法,可以参见http://www.gnu.org/software/coreutils/manual/html_node/install-invocation.html

使能系统服务

可以通过在recipe中增加一些定义,用来安装一些需要在系统开始运行时或者在后台一直运行的进程服务。当需要增加系统服务,可以通过在recipe中使用do_install_append函数来安装相应的服务。当然,如果在recipe已经存在了do_install函数,那么在do_install中实现系统服务的安装也是一种更好的选择。 OpenEmbedded提供了两种方式用于启动系统服务:

  • SysVinit:SysVinit是一种系统和服务管理器,用来管理系统初始化过程,控制着系统基础功能。Linux内核启动之后,最开始调用的就是初始化程序。要想通过SysVinit使能系统服务,在recipe中需要引入update-rc.d,用来实现安全的安装软件包,同时,还需要设置INITSCRIPT_PACKAGES、INITSCRIPT_NAME以及INITSCRIPT_PARAMS变量。

  • systemd:systemd(System Management Daemon)取代了SysVinit,用来提供系统服务的更高阶管理。可以通过http://freedesktop.org/wiki/Software/systemd/ 获取更多关于systemd的信息。同样的,要想使用systemd来使能系统服务,需要在recipe中引入systemd。使用方法可以参见systemd.bbclass.

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值