Yoctoレシピ(.bbファイル)は、ソースの取得方法・ビルド手順・インストール先をBitBakeに伝える設計図だ。自作アプリでもGitHubのOSSでも、レシピさえ書ければYoctoイメージに組み込める。
この記事では、Yoctoレシピを ゼロから作成する方法 を、Hello WorldからGitHub取得、CMake/Autotools継承まで、実際のコード例とともに解説する。
Yoctoレシピとは
レシピ(Recipe) とは、特定のソフトウェアをビルドしてインストールするための「設計図」だ。Yocto Development Tasks Manualに仕様の全体像がある。
拡張子は .bb で、以下の情報を記述する:
- どこから ソースコードを取得するか(SRC_URI)
- どうやって ビルドするか(do_compile)
- どこに インストールするか(do_install)
- ライセンス は何か(LICENSE)
レシピファイルの命名規則
レシピファイル名は パッケージ名_バージョン.bb の形式で命名する。
hello-world_1.0.bb # hello-world バージョン1.0
myapp_2.3.1.bb # myapp バージョン2.3.1
busybox_1.36.1.bb # busybox バージョン1.36.1
ファイル名からパッケージ名(PN)とバージョン(PV)が自動的に設定される。変数の全リストはYocto Reference Manual — Variables Glossaryで確認できる。
レシピの基本構造
# hello-world_1.0.bb
# ===== メタデータ =====
SUMMARY = "Hello World サンプル"
DESCRIPTION = "Yoctoレシピの学習用サンプルアプリケーション"
LICENSE = "MIT"
LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302"
# ===== ソースコードの取得 =====
SRC_URI = "file://hello.c"
# ===== ビルドディレクトリの設定 =====
S = "${WORKDIR}"
# ===== ビルド処理 =====
do_compile() {
${CC} ${CFLAGS} ${LDFLAGS} -o hello hello.c
}
# ===== インストール処理 =====
do_install() {
install -d ${D}${bindir}
install -m 0755 hello ${D}${bindir}
}
主要な変数
レシピで使う主要な変数を表にまとめた。
| 変数名 | 説明 | 例 |
|---|---|---|
SUMMARY | パッケージの短い説明 | "Hello World サンプル" |
DESCRIPTION | パッケージの詳細説明 | "学習用サンプルアプリ..." |
LICENSE | ライセンス種別(SPDX表記) | "MIT", "GPL-2.0-only", "Apache-2.0" |
LIC_FILES_CHKSUM | ライセンスファイルのチェックサム | file://LICENSE;md5=xxx |
SRC_URI | ソースコードの取得元 | "file://", "git://", "https://" |
S | ソースコードの展開先ディレクトリ | $/git |
ビルド・インストール用の変数
| 変数名 | 説明 | 展開例 |
|---|---|---|
${WORKDIR} | ビルド作業ディレクトリ | /tmp/work/.../hello-world/1.0-r0/ |
${D} | インストール先のルート | .../image/ |
${bindir} | /usr/bin のパス | /usr/bin |
${libdir} | /usr/lib のパス | /usr/lib |
${sysconfdir} | /etc のパス | /etc |
${CC} | クロスコンパイラ | arm-poky-linux-gnueabi-gcc |
Hello Worldレシピを作成する
まずは最もシンプルなレシピを作成してみよう。
カスタムレイヤーを作成
レシピは自作レイヤー内に配置するのがベストプラクティスだ。Pokyのレイヤーに直接置いてはいけない。
cd ~/yocto/poky
source oe-init-build-env build
# 新しいレイヤーを作成
cd ..
bitbake-layers create-layer meta-mylayer
# レイヤーをビルドに追加
cd build
bitbake-layers add-layer ../meta-mylayer
レイヤーの詳細はレイヤー作成ガイドを参照してほしい。
レシピ用ディレクトリとソースコードを作成
mkdir -p ../meta-mylayer/recipes-example/hello-world/files
files/hello.c を作成する。
// files/hello.c
#include <stdio.h>
int main(void) {
printf("Hello from Yocto!\n");
printf("This app was built with a custom recipe.\n");
return 0;
}
レシピファイルを作成
hello-world_1.0.bb を作成する。
# hello-world_1.0.bb
SUMMARY = "Hello World - Yoctoレシピ学習用サンプル"
DESCRIPTION = "Yoctoでカスタムレシピを作成する方法を学ぶためのサンプルアプリケーション"
LICENSE = "MIT"
LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302"
SRC_URI = "file://hello.c"
S = "${WORKDIR}"
do_compile() {
${CC} ${CFLAGS} ${LDFLAGS} -o hello hello.c
}
do_install() {
install -d ${D}${bindir}
install -m 0755 hello ${D}${bindir}
}
ビルドしてイメージに組み込む
# 個別にレシピをビルド
bitbake hello-world
# ビルド成功のメッセージ
NOTE: Tasks Summary: Attempted 123 tasks of which 120 didn't need to be rerun
conf/local.conf に以下を追加してイメージに組み込む:
IMAGE_INSTALL:append = " hello-world"
イメージを再ビルドしてQEMUで確認:
bitbake core-image-minimal
runqemu qemux86-64 nographic
# ログイン後、helloコマンドを実行
root@qemux86-64:~# hello
Hello from Yocto!
This app was built with a custom recipe.
GitHubからソースを取得する
実際の開発では、外部リポジトリからソースを取得するパターンの方が多い。
例:nlohmann/jsonライブラリ
# nlohmann-json_3.11.3.bb
SUMMARY = "JSON for Modern C++"
DESCRIPTION = "Header-only JSON library for C++"
HOMEPAGE = "https://github.com/nlohmann/json"
LICENSE = "MIT"
LIC_FILES_CHKSUM = "file://LICENSE.MIT;md5=f969127d7b7ed0a8a63c2bbeae002588"
# GitHubからソースを取得
SRC_URI = "git://github.com/nlohmann/json.git;protocol=https;branch=develop"
# 特定のコミットを指定(再現性のため必須)
SRCREV = "9cca280a4d0ccf0c08f47a99aa71d1b0e52f8d03"
# ソースの展開先(gitクローン時は ${WORKDIR}/git)
S = "${WORKDIR}/git"
inherit cmake
EXTRA_OECMAKE = "-DJSON_BuildTests=OFF"
SRC_URIの書き方パターン
| 取得元 | SRC_URI の書き方 |
|---|---|
| ローカルファイル | file://hello.c |
| Git (HTTPS) | git://github.com/user/repo.git;protocol=https;branch=main |
| Git (SSH) | git://git@github.com/user/repo.git;protocol=ssh;branch=main |
| HTTP/HTTPS | https://example.com/file.tar.gz |
| パッチファイル | file://fix-build.patch |
継承クラスを活用する
Yoctoには、よく使うビルドパターンをまとめた「クラス」がある。inherit で継承すると、do_compile や do_install を自動化できる。
| クラス | 用途 | 主な自動化 |
|---|---|---|
cmake | CMakeプロジェクト | cmake → make → make install |
autotools | Autoconfプロジェクト | configure → make → make install |
meson | Mesonプロジェクト | meson → ninja → install |
setuptools3 | Pythonパッケージ | setuptools / wheel インストール |
systemd | systemdサービス | サービスの有効化 |
CMakeプロジェクトの例
# myapp-cmake_1.0.bb
SUMMARY = "My CMake App"
LICENSE = "MIT"
LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302"
SRC_URI = "git://github.com/user/myapp.git;protocol=https;branch=main"
SRCREV = "abc123def456..."
S = "${WORKDIR}/git"
# CMakeクラスを継承するだけでビルドが自動化される
inherit cmake
EXTRA_OECMAKE = "-DBUILD_TESTS=OFF -DCMAKE_BUILD_TYPE=Release"
Autotoolsプロジェクトの例
# myapp-autotools_1.0.bb
SUMMARY = "My Autotools App"
LICENSE = "GPL-2.0-only"
LIC_FILES_CHKSUM = "file://COPYING;md5=..."
SRC_URI = "https://example.com/myapp-1.0.tar.gz"
SRC_URI[sha256sum] = "def456..."
inherit autotools
EXTRA_OECONF = "--disable-docs"
systemdサービス
起動時にアプリを自動実行したい場合は inherit systemd を使う。詳しい設定方法はsystemdサービスガイドを参照してほしい。
よくあるエラーと解決方法
LIC_FILES_CHKSUM mismatch
ERROR: License checksum mismatch...
原因: ライセンスファイルのMD5ハッシュが一致しない。
解決: 正しいMD5を計算して更新。
md5sum LICENSE
do_fetch failed
ERROR: Fetcher failure: Unable to find file...
原因: SRC_URIのパスが間違っている、またはネットワーク問題。
解決: パスを確認。Gitの場合はSRCREVを正しいコミットハッシュに設定。
Nothing PROVIDES 'hello-world'
ERROR: Nothing PROVIDES 'hello-world'
原因: レイヤーがbblayers.confに追加されていない。
解決: bitbake-layers add-layer でレイヤーを追加して確認。
SRC_URI checksum mismatch
ERROR: SRC_URI checksum mismatch...
原因: HTTP/HTTPSで取得するファイルのチェックサムが未設定または不一致。
解決: 正しいチェックサムを計算して設定。
sha256sum ダウンロードしたファイル.tar.gz
依存関係の管理
実際のレシピでは、他のパッケージへの依存関係を設定する場面が多い。Yoctoではビルド時と実行時の依存を区別する。
DEPENDSとRDEPENDS
| 変数 | タイミング | 例 |
|---|---|---|
DEPENDS | ビルド時 — コンパイルに必要なライブラリ/ヘッダ | DEPENDS = "openssl zlib" |
RDEPENDS:${PN} | 実行時 — ターゲットに必要なパッケージ | RDEPENDS:${PN} = "libssl" |
# myapp_1.0.bb — 依存関係の設定例
SUMMARY = "My App with Dependencies"
LICENSE = "MIT"
LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302"
SRC_URI = "file://myapp.c"
S = "${WORKDIR}"
# ビルド時: OpenSSLのヘッダとライブラリが必要
DEPENDS = "openssl"
# 実行時: OpenSSLの共有ライブラリが必要
RDEPENDS:${PN} = "openssl"
do_compile() {
${CC} ${CFLAGS} ${LDFLAGS} -o myapp myapp.c -lssl -lcrypto
}
do_install() {
install -d ${D}${bindir}
install -m 0755 myapp ${D}${bindir}
}
requireとinclude
レシピのロジックを複数ファイルに分割できる:
require— 別ファイルを読み込む(ファイルがなければエラー)include— 別ファイルを読み込む(なければスキップ)
# myapp_1.0.bb
require myapp-common.inc
SRC_URI = "https://example.com/myapp-1.0.tar.gz"
SRC_URI[sha256sum] = "abc123..."
Pokyの公式レシピでも、バージョン間でメタデータを共有するためにこの手法が多用されている。
FAQ
SRCREVとAUTOREVの違いは?
SRCREV は特定のGitコミットハッシュに固定する変数で、マシンやCI環境が変わっても同じコードをビルドできる。AUTOREV(SRCREV = "${AUTOREV}")はビルドのたびに最新コミットを取得する。BitBake User Manualでもプロダクション用途でのAUTOREVは非推奨とされている。ビルドの再現性が損なわれ、未テストの変更が混入するリスクがある。
SRC_URIに複数のファイルを追加するには?
スペース区切りで列挙するか、バックスラッシュで改行して記述する:
SRC_URI = "file://main.c \
file://utils.c \
file://utils.h \
file://config.json \
"
file:// のファイルはレシピと同じ階層の files/ ディレクトリか、レシピ名と同じ名前のディレクトリに配置する。
レシピ内でPythonは使える?
使える。BitBakeレシピではインライン式 ${@expression} と、Python関数 python do_taskname() の2つの方法がある:
# Python式で変数を設定
DATEVAR = "${@time.strftime('%Y%m%d', time.gmtime())}"
python do_configure:prepend() {
bb.note("Configuring with custom Python logic")
}
詳細はBitBake User ManualのPythonタスクの章を参照。
inheritとrequireの違いは?
inherit は .bbclass ファイルを読み込み、標準的なビルド動作(cmakeやautotools等)を追加する。require / include は別の .bb や .inc ファイルを読み込み、レシピのメタデータを共有する。inherit は「このビルドシステムを使う」、require は「共有設定を読み込む」と覚えるとわかりやすい。
ビルドに失敗したレシピをデバッグするには?
devshell を使うと、レシピのビルド環境にインタラクティブシェルで入れる:
bitbake -c devshell hello-world
クロスコンパイラやsysrootパス等の環境変数がセットされた状態でターミナルが開くため、手動でmakeを実行したりファイルを確認できる。体系的なデバッグ手法はビルドエラーデバッグガイドを参照。
/etcに設定ファイルを配置するには?
do_install で ${sysconfdir}(/etc に展開される)を使う:
do_install() {
install -d ${D}${sysconfdir}/myapp
install -m 0644 ${WORKDIR}/myapp.conf ${D}${sysconfdir}/myapp/
}
設定ファイルは SRC_URI にも追加するのを忘れずに。
do_installとdo_deployの違いは?
do_install はターゲットのルートファイルシステムのステージングエリア(${D})にファイルを配置する。do_deploy はデプロイディレクトリに出力する——ブートイメージやブートローダバイナリ等、rootfsに含まれないが書き込み時に必要なアーティファクト向けだ。大半のレシピでは do_install だけで事足りる。
まとめ
この記事ではYoctoレシピの作成方法を解説した。
- レシピは
.bbファイルで、取得・ビルド・インストールの全工程を記述する - 主要変数:
SRC_URI、do_compile、do_install、DEPENDS、RDEPENDS - 自作レイヤーにレシピを配置するのがベストプラクティス
inheritでCMake/Autotools/Mesonプロジェクトを自動化IMAGE_INSTALL:appendでイメージに組み込むSRCREVは必ず固定する(再現性のため)DEPENDSでビルド時、RDEPENDSで実行時の依存を管理する
レシピ作成のリファレンスはYocto Development Tasks Manualが最も正確だ。次のステップに進もう。
- レイヤーの作成と管理 — レシピを配置するレイヤーの設計
- bbappend実践ガイド — 既存レシピのカスタマイズ
- Raspberry PiでカスタムLinuxをビルドする — 実機で動かす
- SBOM・CVE管理ガイド — レシピのサプライチェーンセキュリティ
組み込みLinuxの世界をもっと深く学びたい人には、以下の書籍がおすすめだ。
関連記事: