みつきんのメモ

組み込みエンジニアです。Interface誌で「Yocto Projectではじめる 組み込みLinux開発入門」連載中

YoctoProject 自分のレイヤから既存のbbclassの挙動を上書きする

はじめに

例えば既存のbbclassにデバッグ用のログを追加したり独自の改造を実験したい場合でも、 既存のレイヤのソースコードに手を加えるのは避けたい。

そのような場合、ちょっとした工夫で自分のレイヤから既存のbbclassの挙動を上書きすることができる。

How do I override a bbclass file?

WikiTechnical FAQによると下記のようにするとできるらしい。

This is tricky - bbclass files are found via BBPATH, which is added to by each layer.conf either by prepending or appending. Assuming you are putting your bbclass in a custom layer, you will probably want to have your layer's layer.conf prepend to BBPATH, but then you will also need to make sure that your layer does not appear before any other layer that is also prepending and overriding the same class.

複数の同名のbbclassが存在する場合bitbakeはBBPATHによって使用するbbclassを決定するらしい。 ただ、レイヤが前に見えるとか具体的にどのようにするのかよくわからない。

とりあえず実験してみる。

Pokyの作成

特に実機である必要は無いので最小構成で環境を作成する。

対象とするレシピはpoky/documentation/ref-manual/examples/hello-autotools/hello_2.3.bbとする。

DESCRIPTION = "GNU Helloworld application"
SECTION = "examples"
LICENSE = "GPLv3"
LIC_FILES_CHKSUM = "file://COPYING;md5=adefda309052235aa5d1e99ce7557010"

SRC_URI = "${GNU_MIRROR}/hello/hello-${PV}.tar.bz2"

inherit autotools

autotoolsをinheritしているため今回の実験には都合が良い。

収録してある場所的にこのままでは使いづらいので自作のレイヤmeta-workを作成しそこにコピーする。 また、meta-workには挙動を上書きするためのbbclassファイルも格納する。

環境構築

メタデータの取得から自作レイヤの設定までを下記のコマンドで行う。

$ mkdir -p override_test/layers
$ cd override_test/layers
$ git clone git://git.yoctoproject.org/poky.git -b dunfell
$ cd ..
$ source layers/poky/oe-init-build-env build
$ bitbake-layers create-layer meta-work
$ cp ../layers/poky/documentation/ref-manual/examples/hello-autotools/hello_2.3.bb meta-work/recipes-example/example/
$ mv ./meta-work ../layers
$ bitbake-layers add-layer ../layers/meta-work

helloのビルド

追加したhelloがビルドできるか確認する。

$ bitbake hello

見事にエラーが発生。多分実用のレシピじゃないのでメンテされてないか、実際のビルドを想定していないのか。

ERROR: hello-2.3-r0 do_fetch: No checksum specified for '/home/mickey/work/yocto/override_test/build/downloads/hello-2.3.tar.bz2', please add at least one to the recipe:
SRC_URI[sha256sum] = "41cbb1b8296f7f791164e4da1d10c6c8b905bc7d0136f34ebe0b198fb08cfb30"
ERROR: hello-2.3-r0 do_fetch: Fetcher failure for URL: 'https://ftp.gnu.org/gnu/hello/hello-2.3.tar.bz2'. Missing SRC_URI checksum
ERROR: Logfile of failure stored in: /home/mickey/work/yocto/override_test/build/tmp/work/core2-64-poky-linux/hello/2.3-r0/temp/log.do_fetch.28859
ERROR: Task (/home/mickey/work/yocto/override_test/layers/meta-work/recipes-example/example/hello_2.3.bb:do_fetch) failed with exit code '1'

メッセージに従ってSRC_URI[sha256sum]の行をレシピに追加してみる。

--- hello_2.3.bb.orig    2020-09-17 07:33:18.033586666 +0900
+++ hello_2.3.bb  2020-09-17 07:49:13.982314976 +0900
@@ -4,5 +4,6 @@ LICENSE = "GPLv3"
 LIC_FILES_CHKSUM = "file://COPYING;md5=adefda309052235aa5d1e99ce7557010"
 
 SRC_URI = "${GNU_MIRROR}/hello/hello-${PV}.tar.bz2"
+SRC_URI[sha256sum] = "41cbb1b8296f7f791164e4da1d10c6c8b905bc7d0136f34ebe0b198fb08cfb30"
 
 inherit autotools

さらにもう一つエラー

ERROR: hello-2.3-r0 do_configure: QA Issue: AM_GNU_GETTEXT used but no inherit gettext [configure-gettext]
ERROR: hello-2.3-r0 do_configure: Fatal QA errors found, failing task.
ERROR: Logfile of failure stored in: /home/mickey/work/yocto/override_test/build/tmp/work/core2-64-poky-linux/hello/2.3-r0/temp/log.do_configure.12021
ERROR: Task (/home/mickey/work/yocto/override_test/layers/meta-work/recipes-example/example/hello_2.3.bb:do_configure) failed with exit code '1'

こちらもメッセージに従ってgettextを継承する。

--- hello_2.3.bb.orig    2020-09-17 07:33:18.033586666 +0900
+++ hello_2.3.bb  2020-09-17 08:15:16.209485733 +0900
@@ -4,5 +4,6 @@ LICENSE = "GPLv3"
 LIC_FILES_CHKSUM = "file://COPYING;md5=adefda309052235aa5d1e99ce7557010"
 
 SRC_URI = "${GNU_MIRROR}/hello/hello-${PV}.tar.bz2"
+SRC_URI[sha256sum] = "41cbb1b8296f7f791164e4da1d10c6c8b905bc7d0136f34ebe0b198fb08cfb30"
 
-inherit autotools
+inherit autotools gettext

最初のファイルからの差分。

これでビルドが通るようになる。

本題

autotools.bbclass

今回はautotools.bbclassで実験するので、poky/meta/classの下からmeta-workへコピーする。

$ mkdir ../layers/meta-work/classes
$ cp ../layers/poky/meta/classes/autotools.bbclass ../layers/meta-work/classes

そして、meta-work側で挙動を上書きできているか確認するために適当な関数にログを入れてみる。

--- autotools.bbclass.orig   2020-09-17 10:18:52.930186568 +0900
+++ autotools.bbclass 2020-09-17 10:20:14.943187756 +0900
@@ -244,6 +244,7 @@ autotools_do_compile() {
 }
 
 autotools_do_install() {
+   bbwarn "################ autotools_do_install #################"
    oe_runmake 'DESTDIR=${D}' install
    # Info dir listing isn't interesting at this point so remove it if it exists.
    if [ -e "${D}${infodir}/dir" ]; then

これはdo_installタスク実行時に起動される。

とりあえず実行してみる。

$ bitbake hello -c install

特に変化はない。

BBPATH

現状のBBPATHの値を確認する。

$ bitbake hello -e | grep '^BBPATH='
BBPATH="/home/mickey/work/yocto/override_test/layers/poky/meta-poky:/home/mickey/work/yocto/override_test/build:/home/mickey/work/yocto/override_test/layers/poky/meta:/home/mickey/work/yocto/override_test/layers/poky/meta-yocto-bsp:/home/mickey/work/yocto/override_test/layers/meta-work"

下記の順番でファイルを検索していることが分かる。

  1. layers/poky/meta-poky
  2. build
  3. layers/poky/meta
  4. layers/poky/meta-yocto-bsp
  5. layers/meta-work

これを変えるにはどうするか。

レイヤの状態を確認してみる。

$ bitbake-layers show-layers 
NOTE: Starting bitbake server...
layer                 path                                      priority
==========================================================================
meta                  /home/mickey/work/yocto/override_test/layers/poky/meta  5
meta-poky             /home/mickey/work/yocto/override_test/layers/poky/meta-poky  5
meta-yocto-bsp        /home/mickey/work/yocto/override_test/layers/poky/meta-yocto-bsp  5
meta-work             /home/mickey/work/yocto/override_test/layers/meta-work  6

レイヤの優先度は関係無いようだ。

直にbblayers.confを確認してみる。

# POKY_BBLAYERS_CONF_VERSION is increased each time build/conf/bblayers.conf
# changes incompatibly
POKY_BBLAYERS_CONF_VERSION = "2"

BBPATH = "${TOPDIR}"
BBFILES ?= ""

BBLAYERS ?= " \
  /home/mickey/work/yocto/override_test/layers/poky/meta \
  /home/mickey/work/yocto/override_test/layers/poky/meta-poky \
  /home/mickey/work/yocto/override_test/layers/poky/meta-yocto-bsp \
  /home/mickey/work/yocto/override_test/layers/meta-work \
  "

必ずしもBBLAYERS変数の順番通りというわけでもなさそう。

とりあえず、bblayers.confの並び順でmeta-workを上に持っていってみる。

# POKY_BBLAYERS_CONF_VERSION is increased each time build/conf/bblayers.conf
# changes incompatibly
POKY_BBLAYERS_CONF_VERSION = "2"

BBPATH = "${TOPDIR}"
BBFILES ?= ""

BBLAYERS ?= " \
  /home/mickey/work/yocto/override_test/layers/meta-work \
  /home/mickey/work/yocto/override_test/layers/poky/meta \
  /home/mickey/work/yocto/override_test/layers/poky/meta-poky \
  /home/mickey/work/yocto/override_test/layers/poky/meta-yocto-bsp \
  "

この状態でBBPATHを確認する。

$ bitbake hello -e | grep '^BBPATH='
BBPATH="/home/mickey/work/yocto/override_test/layers/poky/meta-poky:/home/mickey/work/yocto/override_test/build:/home/mickey/work/yocto/override_test/layers/meta-work:/home/mickey/work/yocto/override_test/layers/poky/meta:/home/mickey/work/yocto/override_test/layers/poky/meta-yocto-bsp"
  1. layers/poky/meta-poky
  2. build
  3. layers/meta-work
  4. layers/poky/meta
  5. layers/poky/meta-yocto-bsp

meta-workがmetaよりも先に来ていることが確認できた。

この状態でbitbakeを実行してみる。

$ bitbake hello -c install
...(snip)...
WARNING: m4-native-1.4.18-r0 do_install: ################ autotools_do_install #################
WARNING: autoconf-native-2.69-r11 do_install: ################ autotools_do_install #################
WARNING: automake-native-1.16.1-r0 do_install: ################ autotools_do_install #################
WARNING: libtool-native-2.4.6-r0 do_install: ################ autotools_do_install #################
WARNING: xz-native-5.2.4-r0 do_install: ################ autotools_do_install #################
WARNING: gmp-native-6.2.0-r0 do_install: ################ autotools_do_install #################
WARNING: pkgconfig-native-0.29.2+gitAUTOINC+edf8e6f0ea-r0 do_install: ################ autotools_do_install #################
WARNING: popt-native-1.16-r3 do_install: ################ autotools_do_install #################
WARNING: gperf-native-3.1-r0 do_install: ################ autotools_do_install #################
WARNING: attr-native-2.4.48-r0 do_install: ################ autotools_do_install #################
WARNING: flex-native-2.6.4-r0 do_install: ################ autotools_do_install #################
WARNING: acl-native-2.2.53-r0 do_install: ################ autotools_do_install #################
WARNING: patch-native-2.7.6-r0 do_install: ################ autotools_do_install #################
WARNING: make-native-4.3-r0 do_install: ################ autotools_do_install #################
WARNING: sqlite3-native-3_3.31.1-r0 do_install: ################ autotools_do_install #################
WARNING: autoconf-archive-native-2019.01.06-r0 do_install: ################ autotools_do_install #################
WARNING: bison-native-3.5.3-r0 do_install: ################ autotools_do_install #################
WARNING: rsync-native-3.1.3-r0 do_install: ################ autotools_do_install #################
WARNING: mpfr-native-4.0.2-r0 do_install: ################ autotools_do_install #################
WARNING: gettext-native-0.20.1-r0 do_install: ################ autotools_do_install #################
WARNING: libmpc-native-1.1.0-r0 do_install: ################ autotools_do_install #################
WARNING: hello-2.3-r0 do_install: ################ autotools_do_install #################

gettext.bbclassは至るところで使用されているのでhello以外のパッケージにも影響が出ているが、meta-workgettext.bbclassが実行されていることが分かる。

まとめ

BBPATHの順序を入れ替えることで、既存のbbclassをカスタムレイヤのbbclassで上書きできることが確認できた。

ただし、WikiTechnical FAQにもあるように、

Ultimately, overriding bbclass files is not good practice long term - you are opening yourself up to maintenance issues when the original class changes, and the override is fragile as hinted above. The best solution is to try to get whatever changes you need into the original class; this does of course require additional work and time though.

この手法を恒久的な解決とすることは脆弱であるためあくまでデバッグのために使用するか、 必要に応じて本来の持ち主にパッチを送って変更を取り込んでもらうようにするべき。