yocto系列讲解 (理论篇) 56 - poky下目录结构

前言

我相信大家在看到poky目录下的内容时有点一脸懵逼,搞不清楚每个目录和文件是做什么的,甚至目录和文件名都让人望而却步,人大多都是抵触新事物的,因为要花时间和精力来了解新事物。
了解poky下每个文件和子目录作用对我们熟悉yocto还是很有帮助的。

poky]$ ls
bitbake        LICENSE               MEMORIAM        meta-mylayer  meta-selftest      README.hardware  scripts
build          LICENSE.GPL-2.0-only  meta            meta-poky     meta-skeleton      README.OE-Core
contrib        LICENSE.MIT           meta-freescale  meta-qcom     meta-yocto-bsp     README.poky
documentation  Makefile              meta-mybsp      meta-qt5      oe-init-build-env  README.qemu
  • 1
  • 2
  • 3
  • 4
  • 5

注意:其中有些目录比如meta-qt5、meta-mybsp是我后面加上去的, 自己的poky目录里面没有不要紧哈

随着你慢慢熟悉yocto,你会发现yocto中有很多跟厨房有些关系的概念和命名,比如:

  • poky: (of a room or a building 屋子或建筑物) 狭窄的;
  • bitbake:其中bake是"烤,烘焙"的意思;
  • recipes: 英文意思是食谱、配方;

我认真思索了一下,其实你可以这么联想:在一个烤箱(poky)内,按照预先设定的规则(recipe)食谱,来烘烤(bake)任意项目,将其变成二进制(bit)文件菜肴等。是不是这样就很容易理解yocto中出现的很多命名规则了呢?

yocto是由许多的文件、目录和子目录组成,了解它们的每个文件或者目录的意义和作用可以有效的帮助我们学习和使用Yocto项目。
本篇内容简要的讲解下poky目录下各个子目录和文件的一些知识。

poky目录下的核心组件

bitbake目录

poky]$ ls bitbake/
AUTHORS  ChangeLog  doc  LICENSE               LICENSE.MIT  toaster-requirements.txt
bin      contrib    lib  LICENSE.GPL-2.0-only  README
  • 1
  • 2
  • 3

bitbake是一个独立的项目(属于 openembedded ),这里的 poky/bitbake 目录下就放了这个 bitbake 项目的副本,我们在使用 bitbake 命令的时候其实用的就是这目录里面的bitbake,而不是系统里面的。 bitbake 是用来读取和解析meta 目录中的数据,并创建相应的任务来处理,其他的目录基本上都是被bitbake使用的,用来按照相应的规则编译某个项目。通常编译失败的时候不用去bitbake目录里面找原因,而应该从meta等目录中查找,而更多时候yocto自带的meta元数据通常不会出错,那就很可能是自己创建的meta 中有问题。

https://github.com/openembedded/bitbake
  • 1

当我们source环境(比如source oe-init-build-env)的时候,会将 scripts/ bitbake/bin/ 两个子目录的路径添加到 PATH 环境变量中:

poky]$ source oe-init-build-env
build]$ echo $PATH
/home/peeta/poky/scripts:/home/peeta/poky/bitbake/bin:/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
  • 1
  • 2
  • 3

build目录

一开始 git clone 下来的干净的poky目录下是没有这个build目录的,是我们 source 的过程中才开始创建的这个目录(有兴趣的参考脚本 oe-init-build-env poky/scripts/oe-setup-builddir
这个 poky/build/ 目录中包含用户配置文件和OpenEmbedded构建系统在其标准配置中生成的输出,其中下载和解压后的源代码与编译输出结果都在这里面。
build目录也可以不固定放在poky目录下,或者名字也可以不固定,只要在source的时候带上参数即可,例如:

. ./oe-init-build-env <builddir> 
  • 1

meta目录

meta目录包含最小的、底层的OpenEmbedded核心元数据,保存着可以运行的虚拟目标,比如qemux86、qemuarm等的recipes、公共的class类和machine机器的配置。

poky]$ ls meta/
classes      files        recipes-connectivity  recipes-extended  recipes-kernel      recipes-sato     site
conf         lib          recipes-core          recipes-gnome     recipes-multimedia  recipes-support
COPYING.MIT  recipes-bsp  recipes-devtools      recipes-graphics  recipes-rt          recipes.txt
  • 1
  • 2
  • 3
  • 4

meta-poky目录

该目录用来添加足够的元数据来定义Poky reference distribution,是基于meta目录之上的扩展。build目录中的conf目录就是从lmeta-poky/conf中演变过来的,例如local.conf和bblayers模板就在这里面。

poky]$ tree meta-poky/
meta-poky/
├── classes
│   └── poky-sanity.bbclass
├── conf
│   ├── bblayers.conf.sample
│   ├── conf-notes.txt
│   ├── distro
│   │   ├── include
│   │   │   ├── poky-distro-alt-test-config.inc
│   │   │   ├── poky-floating-revisions.inc
│   │   │   └── poky-world-exclude.inc
│   │   ├── poky-altcfg.conf
│   │   ├── poky-bleeding.conf
│   │   ├── poky.conf
│   │   └── poky-tiny.conf
│   ├── layer.conf
│   ├── local.conf.sample
│   ├── local.conf.sample.extended
│   └── site.conf.sample
├── README.poky
└── recipes-core
    ├── busybox
    │   ├── busybox
    │   │   └── poky-tiny
    │   │       └── defconfig
    │   └── busybox_%.bbappend
    ├── psplash
    │   ├── files
    │   │   └── psplash-poky-img.h
    │   └── psplash_git.bbappend
    └── tiny-init
        ├── files
        │   ├── init
        │   └── rc.local.sample
        └── tiny-init.bb

12 directories, 22 files
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38

meta-yocto-bsp目录

这个目录下yocto官方为了方便BSP开发人员在开发和添加自己的BSP layer时,提供了3种目前主流体系架构的硬件平台BSP模板用于参考。
比如这个目录下就有arm架构对于的beaglebone平台,mips对应的edgerouter平台,x86/x86-64对应的genericx86.conf/genericx86-64.conf。主要是给大家演示这些平台如何添加相应的内核、bootloader和其他的BSP配置。

poky]$ tree meta-yocto-bsp/
meta-yocto-bsp/
├── conf
│   ├── layer.conf
│   └── machine
│       ├── beaglebone-yocto.conf
│       ├── edgerouter.conf
│       ├── genericx86-64.conf
│       ├── genericx86.conf
│       └── include
│           └── genericx86-common.inc
├── lib
│   └── oeqa
│       ├── controllers
│       │   ├── beaglebonetarget.py
│       │   ├── edgeroutertarget.py
│       │   ├── grubtarget.py
│       │   └── __init__.py
│       └── selftest
│           └── cases
│               └── systemd_boot.py
├── README.hardware
├── recipes-bsp
│   ├── formfactor
│   │   ├── formfactor
│   │   │   ├── beaglebone-yocto
│   │   │   │   └── machconfig
│   │   │   ├── genericx86
│   │   │   │   └── machconfig
│   │   │   └── genericx86-64
│   │   │       └── machconfig
│   │   └── formfactor_0.0.bbappend
│   └── gma500-gfx-check
│       ├── gma500-gfx-check
│       │   ├── gma500-gfx-check.conf
│       │   └── gma500-gfx-check.sh
│       └── gma500-gfx-check_1.0.bb
├── recipes-graphics
│   └── xorg-xserver
│       ├── xserver-xf86-config
│       │   ├── beaglebone-yocto
│       │   │   └── xorg.conf
│       │   ├── genericx86
│       │   │   └── xorg.conf
│       │   └── genericx86-64
│       │       └── xorg.conf
│       └── xserver-xf86-config_0.1.bbappend
├── recipes-kernel
│   └── linux
│       ├── linux-yocto_5.4.bbappend
│       ├── linux-yocto_5.8.bbappend
│       └── linux-yocto-dev.bbappend
└── wic
    ├── beaglebone-yocto.wks
    ├── edgerouter.wks
    └── genericx86.wks.in
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56

meta-selftest目录

这个目录我还没有用过,目录名中有self test自测的意思,目录里面有很多其他额外的bb和append文件用来验证构建系统的方法。如果你没有这方面需求可以不添加到你的bblayers.conf文件中。

poky]$ ls meta-selftest/  
classes  conf  files  lib  README  recipes-devtools  recipes-test  wic
poky]$ ls meta-selftest/recipes-test/
aspell           emptytest           images   multiconfig      recipetool      selftest-hardlink
container-image  error               license  nopackages       recipeutils     sysroot-test
delay            fortran             m4       postinst         selftest-chown  xcursor-transparent-theme
devtool          git-submodule-test  man-db   pseudo-pyc-test  selftest-ed
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

meta-skeleton目录

skeleton英文意思是骨架,这个目录是提供了BSP和内核相关开发的模板,比如这里面就有一个hello-mod驱动模块的实例,系统层的服务程序,添加多个用户账户

poky]$ tree meta-skeleton/
meta-skeleton/
├── conf
│   ├── layer.conf
│   ├── multilib-example2.conf
│   └── multilib-example.conf
├── recipes-baremetal
│   └── baremetal-examples
│       └── baremetal-helloworld_git.bb
├── recipes-core
│   └── busybox
│       ├── busybox
│       │   └── no_rfkill.cfg
│       └── busybox_%.bbappend
├── recipes-kernel
│   ├── hello-mod
│   │   ├── files
│   │   │   ├── COPYING
│   │   │   ├── hello.c
│   │   │   └── Makefile
│   │   └── hello-mod_0.1.bb
│   └── linux
│       ├── linux-yocto-custom
│       │   ├── 0001-linux-version-tweak.patch
│       │   ├── feature.scc
│       │   └── smp.cfg
│       └── linux-yocto-custom.bb
├── recipes-multilib
│   └── images
│       └── core-image-multilib-example.bb
└── recipes-skeleton
    ├── service
    │   ├── service
    │   │   ├── COPYRIGHT
    │   │   ├── skeleton
    │   │   └── skeleton_test.c
    │   └── service_0.1.bb
    └── useradd
        ├── useradd-example
        │   ├── file1
        │   ├── file2
        │   ├── file3
        │   └── file4
        └── useradd-example.bb

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  1. recipes-baremetal
    这个recipes-baremetal目录里面是一个不跑系统的裸机程序演示,感兴趣的可以看下这个:
    https://github.com/aehs29/baremetal-helloqemu/blob/master/hello_baremetal_arm.c

  2. recipes-kernel
    教你怎么给 linux 内核添加patch补丁和config配置,怎么在源码树之外添加驱动模块的实例

  3. recipes-skeleton
    教你怎么添加一个应用层的service,而且还给了一个启动脚本:

//meta-skeleton/recipes-skeleton/service/service/skeleton_test.c    
#include <unistd.h>

/* This demo does nothing except for testing /etc/init.d/skeleton */

int main(int argc, char *argv[])
{
        daemon(0, 0);
        while (1) {
                sleep(1);
        }
        return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
poky]$ cat meta-skeleton/recipes-skeleton/service/service/skeleton
...
case "$1" in
start)
        do_start
        ;;
stop)
        do_stop || exit $?
        ;;
status)
        status_of_proc
        ;;
restart)
        # Always start the service regardless the status of do_stop
        do_stop
        do_start
        ;;
try-restart|force-reload)
        # force-reload is the same as reload or try-restart according
        # to its definition, the reload is not implemented here, so
        # force-reload is the alias of try-restart here, but it should
        # be the alias of reload if reload is implemented.
        #
        # Only start the service when do_stop succeeds
        do_stop && do_start
        ;;
#reload)
        # If the "reload" action is implemented properly, then let the
        # force-reload be the alias of reload, and remove it from
        # try-restart|force-reload)
        #
        #do_reload
        #;;
*)
        echo "Usage: $0 {start|stop|status|restart|try-restart|force-reload}" >&2
        exit 3
        ;;
esac
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38

同时还演示了如何在bb文件中安装启动脚本的内容:

poky]$ cat meta-skeleton/recipes-skeleton/service/service_0.1.bb 
SUMMARY = "The canonical example of init scripts"
SECTION = "base"
LICENSE = "GPLv2"
LIC_FILES_CHKSUM = "file://${WORKDIR}/COPYRIGHT;md5=349c872e0066155e1818b786938876a4"

SRC_URI = "file://skeleton \
           file://skeleton_test.c \
           file://COPYRIGHT \
           "

do_compile () {
        ${CC} ${CFLAGS} ${LDFLAGS} ${WORKDIR}/skeleton_test.c -o ${WORKDIR}/skeleton-test
}

do_install () {
        install -d ${D}${sysconfdir}/init.d #先传创建xxx/image/etc/init.d目录
        cat ${WORKDIR}/skeleton | \
          sed -e 's,/etc,${sysconfdir},g' \
              -e 's,/usr/sbin,${sbindir},g' \
              -e 's,/var,${localstatedir},g' \
              -e 's,/usr/bin,${bindir},g' \
              -e 's,/usr,${prefix},g' > ${D}${sysconfdir}/init.d/skeleton #替换脚本文件内容演示,以及重定向安装到xxx/image/etc/init.d目录
        chmod a+x ${D}${sysconfdir}/init.d/skeleton #添加启动脚本的执行权限

        install -d ${D}${sbindir}
        install -m 0755 ${WORKDIR}/skeleton-test ${D}${sbindir}/ #安装服务程序
}

RDEPENDS_${PN} = "initscripts"

CONFFILES_${PN} += "${sysconfdir}/init.d/skeleton"
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  1. recipes-skeleton/useradd
    默认我们的/home目录下通常就只有一个root用户,这个recipe就在教我们如何添加多用户。还是很有意思的哈,感兴趣的可以了解下:
poky]$ tree meta-skeleton/recipes-skeleton/useradd/
meta-skeleton/recipes-skeleton/useradd/
├── useradd-example
│   ├── file1
│   ├── file2
│   ├── file3
│   └── file4
└── useradd-example.bb #重点在这个bb文件中
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8