32blogby Studio Mitsu

Yocto bbappendの書き方と実践パターン5選

Yocto Projectで既存レシピをカスタマイズするbbappendファイルの書き方を、Scarthgap 5.0 LTSベースで基礎から実践パターンまで解説する。

by omitsu14 min read

当記事にはアフィリエイト広告が含まれています

目次

.bbappend はYoctoで既存レシピをカスタマイズするための仕組みだ。元の .bb ファイルを直接編集せず、パース時に変更を追記することで、アップストリームの更新と自分のカスタマイズを完全に分離できる。

.bb を直接いじると、次に git pull した瞬間に変更が消える。bbappendなら大丈夫だ。

この記事では、Yocto Scarthgap 5.0 LTS をベースに、bbappendの基礎から実践的なユースケース5つまでを解説する。

bbappendとは何か

.bbappend ファイルは、別のレイヤーにある .bb レシピに対して変数やタスクを追記するためのファイルだ。

仕組みはシンプル。BitBakeがレシピを読み込むとき、対応する .bbappend があれば、レシピの末尾に内容を追記してから処理する。つまり .bbappend に書いた設定は .bb の設定を上書きできる。

meta-poky/recipes-example/someapp/someapp_1.0.bb     ← 元のレシピ
meta-mylayer/recipes-example/someapp/someapp_%.bbappend  ← あなたの追記

この分離が重要な理由は2つある。

  • アップストリームとの共存: meta-pokygit pull で更新しても、あなたのカスタマイズは meta-mylayer に残る
  • 変更の可視性: どのレイヤーが何を変更しているか、bitbake-layers show-appends で一覧できる

レイヤーの作成方法についてはレイヤー作成ガイドを参照。

ファイル名の命名規則

bbappendのファイル名は、対象レシピのファイル名と一致させる必要がある。

バージョン完全一致

someapp_1.0.bbappend  → someapp_1.0.bb にのみ適用
someapp_1.1.bbappend  → someapp_1.1.bb にのみ適用

バージョンが完全に一致しないと適用されない。レシピのバージョンが上がると bbappend が無視される。

ワイルドカード % を使う(推奨)

バージョンアップのたびに bbappend のファイル名を変えるのは面倒だ。% ワイルドカードを使えば、バージョンに関係なく適用できる。

someapp_%.bbappend  → someapp_1.0.bb, someapp_2.3.bb 等すべてに適用

適用確認

bbappendが正しく認識されているか確認するには、以下のコマンドを使う。

bash
# bbappend の一覧と対応レシピを表示
bitbake-layers show-appends

# 特定レシピの全バージョンを確認(バージョン不一致の特定に便利)
bitbake-layers show-recipes someapp

変数の操作方法

bbappendで最も使う操作は、変数への値の追加と上書きだ。

値を追加する(:append)

:append は変数の末尾に値を追加する。先頭にスペースを入れること。 :append はスペースを自動挿入しない。

bash
# 正しい(先頭スペースあり)
SRC_URI:append = " file://my-patch.patch"

# 間違い(スペースなし → 前の値と結合して壊れる)
SRC_URI:append = "file://my-patch.patch"

+= でも追加できるが、:append のほうが「追記である」ことが明示的で好まれる。

bash
# これも動く(+= はスペースを自動挿入する)
SRC_URI += "file://my-patch.patch"

値を削除する(:remove)

bash
DISTRO_FEATURES:remove = "bluetooth wifi"

値を上書きする

bash
# 完全に上書き
SOME_VARIABLE = "new-value"

FILESEXTRAPATHS — 追加ファイルの検索パス

bbappendで独自のファイル(パッチ、設定ファイル等)を追加する場合、そのファイルの置き場所をBitBakeに教える必要がある。FILESEXTRAPATHS 変数がファイルの検索パスを制御する。

bash
FILESEXTRAPATHS:prepend := "${THISDIR}/files:"

この1行には3つの重要なポイントがある。

  1. :=(即時展開)を使う: ${THISDIR} は「このファイルがあるディレクトリ」を指す変数。遅延展開(=)だと .bb ファイル側のディレクトリに解決されてしまう
  2. 末尾のコロン : は必須: FILESEXTRAPATHS はコロン区切りのリスト。コロンがないと次のパスと結合して壊れる
  3. :prepend を使う: 既存のパスより先に検索させるため

タスクの拡張

bbappendでは、レシピのタスク(do_install, do_configure等)に処理を追加できる。

bash
do_install:append() {
    install -d ${D}${sysconfdir}
    install -m 0644 ${WORKDIR}/myconfig.conf ${D}${sysconfdir}/
}

:append はタスクの末尾に処理を追加する。元のタスクの処理は維持される。

:prepend を使えば先頭に追加することもできる。

bash
do_configure:prepend() {
    # configure の前に実行される処理
    cp ${WORKDIR}/my-makefile ${S}/Makefile
}

実践パターン5選

ここからは実際のユースケースを5つ紹介する。

パターン1: パッチを当てる

最も基本的なユースケース。アップストリームのソースコードにバグ修正や機能追加のパッチを当てる。

ディレクトリ構成:

meta-mylayer/
  recipes-example/
    someapp/
      someapp_%.bbappend
      someapp/
        0001-fix-memory-leak.patch
bash
# someapp_%.bbappend
FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"
SRC_URI:append = " file://0001-fix-memory-leak.patch"

${PN} はパッケージ名(この場合 someapp)に展開される。${THISDIR}/${PN} でbbappendと同じディレクトリ内の someapp/ サブディレクトリを指す。

パターン2: 設定ファイルを追加する

独自の設定ファイルをターゲットに配置する。

meta-mylayer/
  recipes-core/
    busybox/
      busybox_%.bbappend
      files/
        custom-inittab
bash
# busybox_%.bbappend
FILESEXTRAPATHS:prepend := "${THISDIR}/files:"
SRC_URI:append = " file://custom-inittab"

do_install:append() {
    install -m 0644 ${WORKDIR}/custom-inittab ${D}${sysconfdir}/inittab
}

パターン3: systemdサービスを追加する

既存のアプリケーションにsystemdサービスファイルを追加して自動起動させる。systemdレシピの詳しい書き方はsystemd自動起動ガイドを参照。

meta-mylayer/
  recipes-example/
    myapp/
      myapp_%.bbappend
      files/
        myapp.service
bash
# myapp_%.bbappend
FILESEXTRAPATHS:prepend := "${THISDIR}/files:"
SRC_URI:append = " file://myapp.service"

SYSTEMD_SERVICE:${PN} = "myapp.service"
SYSTEMD_AUTO_ENABLE:${PN} = "enable"

FILES:${PN} += "${systemd_system_unitdir}/myapp.service"

do_install:append() {
    install -d ${D}${systemd_system_unitdir}
    install -m 0644 ${WORKDIR}/myapp.service ${D}${systemd_system_unitdir}/
}

注意: このパターンは、元の .bb レシピが inherit systemd を含んでいる前提だ。inherit ディレクティブは .bb.bbclass でのみ有効で、.bbappend では公式にサポートされていない。元のレシピがsystemdクラスを継承していない場合は、bbappendではなくレシピ自体の修正が必要になる。

パターン4: コンパイルオプションを変更する

PACKAGECONFIG を使って、レシピのビルドオプションを変更する。

bash
# curl_%.bbappend
# OpenSSLサポートを有効化
PACKAGECONFIG:append = " openssl"

# GnuTLSサポートを無効化
PACKAGECONFIG:remove = "gnutls"

PACKAGECONFIG は多くのレシピで対応しているオプション管理の仕組みだ。対応オプションはレシピの .bb ファイル内の PACKAGECONFIG[xxx] で定義されている。

autotools系のレシピでは、configure オプションを直接追加することもできる。

bash
EXTRA_OECONF:append = " --enable-my-feature"

パターン5: 依存関係を追加する

ビルド時やランタイムの依存関係を追加する。

bash
# mypackage_%.bbappend

# ビルド時依存
DEPENDS:append = " libssl"

# ランタイム依存(${PN} でパッケージを明示する)
RDEPENDS:${PN}:append = " python3"

RDEPENDS には ${PN} が必要だ。RDEPENDS はパッケージごとに設定する変数で、${PN} を省略するとどのパッケージの依存関係かが不明になる。

よくあるトラブルと対処法

bbappendが適用されない

bash
# まず bbappend が認識されているか確認
bitbake-layers show-appends | grep someapp

# レイヤーが bblayers.conf に登録されているか確認
bitbake-layers show-layers

原因として多いのは、バージョン番号の不一致(% を使っていない)とレイヤーの未登録だ。

変数の値がおかしい

bash
# Scarthgap 推奨のデバッグコマンド
bitbake-getvar -r someapp SRC_URI
bitbake-getvar -r someapp FILESEXTRAPATHS

bitbake-getvar は変数の最終的な値と、どのファイルで設定されたかを表示してくれる。展開前・展開後の両方を、ファイル名と行番号つきで確認できる。

ファイルが見つからない(do_fetch エラー)

FILESEXTRAPATHS の設定ミスが原因であることが多い。

  • :== にしていないか
  • 末尾のコロン : を忘れていないか
  • files/ ディレクトリの位置がFILESEXTRAPATHSのパスと一致しているか

よくある質問

bbappendで inherit は使える?

公式には inherit.bb.bbclass でのみ有効だ。BitBake User Manual.bbappendinherit の有効な場所として記載していない。実際に動くケースもあるが、元レシピが必要なクラスを継承していなければ、bbappendではなくレシピ自体を修正するか新しいレシピを作るのが正しい。

:append+= は何が違う?

どちらも値を追加するが、:append はオーバーライドスタイルの演算子で、すべての += の後に実行される。:append はスペースを自動挿入しないので自分で入れる必要がある。+= はパース時に評価されスペースを自動挿入する。bbappendでは、元レシピの代入より確実に後で実行される :append が推奨される。

同じレシピに複数のbbappendを適用できる?

できる。複数のレイヤーが同じレシピへのbbappendを持っている場合、bblayers.conf に記載された順番で適用される。変数が競合した場合は後のレイヤーが勝つ。bitbake-layers show-appends で適用順を確認しよう。

元レシピの変数を完全に上書きするには?

単純な代入(=)を使う。bbappendの内容は元レシピの後に追記されるので、bbappendでの = が最終的な値になる。ただし SRC_URI のような累積的な変数には :append を使うこと。= で上書きすると元の値が全部消えてしまう。

レイヤー内のディレクトリ構成は重要?

bbappendは元レシピと同じ相対パスに置く必要がある。元レシピが meta-poky/recipes-core/busybox/busybox_1.36.1.bb なら、bbappendは meta-mylayer/recipes-core/busybox/busybox_%.bbappend に置く。BitBakeはレシピ名で照合するが、同じディレクトリ構成にしておくのが読みやすさの面で重要だ。

対応するレシピが存在しないbbappendはどうなる?

デフォルトではBitBakeが無視する。これを検出するには local.confBB_DANGLINGAPPENDS_WARNLEVEL = "error" を追加する。対応レシピのないbbappendがあるとビルドがエラーで止まるようになり、レシピの削除やリネーム後に残った古いbbappendを見つけやすい。

元レシピがインストールするファイルを削除できる?

できる。do_install:append()rm を使えば、元の do_install が配置したファイルを削除できる。

bash
do_install:append() {
    rm -f ${D}${bindir}/unwanted-binary
}

あるいは PACKAGESFILES 変数で最終パッケージからファイルを除外する方法もある。ビルドディレクトリからは消さずにパッケージにだけ含めない、という使い分けができる。

まとめ

bbappendは、Yoctoで既存レシピをカスタマイズする唯一の正しい方法だ。覚えるポイントは少ない。

  • ファイル名は レシピ名_%.bbappend% ワイルドカード推奨)
  • ファイルを追加するときは FILESEXTRAPATHS:prepend := "${THISDIR}/files:":= と末尾コロン必須)
  • 値の追加は :append(先頭スペース忘れずに)
  • タスクの拡張は do_install:append() { ... }
  • 困ったら bitbake-layers show-appendsbitbake-getvar で確認

基礎を押さえたら、次はビルド環境の最適化にも取り組もう。

bbappendやレシピのカスタマイズをもっと深く学びたい人には、以下の書籍がおすすめだ。特に『Yocto Project Customization』はカスタムレイヤーの設計パターンに特化している。

関連記事: