mcommit's message

ソフトウェア開発の仕事をしているsimotinといいます。記事の内容でご質問やご意見がありましたらお気軽にコメントしてください\^o^/

yoctoに入門してみる

ちょっと前にyoctoについて色々と調べる機会があったので理解している範囲で書いておきたいと思います。

yoctoを一言で説明すると?

yoctoはLinuxカーネルとユーザーランドのプログラムを含めてビルドするためのプロジェクトでしょうか。
元々はOpenEmbeddedというプロジェクトからスタートしたようですので、組込用のイメージを簡単にビルドすることをイメージしているんだと思います。

知っておくと何が嬉しいのか?

組み込みLinuxの開発をするときに役に立ちます。近年ではボードベンダーから提供されるBSP(Board Support Package)のビルドがyoctoを前提としていることが増えてきているようですのでむしろ避けては通れなくなるような気がしています。
ただし、自分でユーザーランドのアプリケーションを開発する場合は結局自分の為にレシピを書かないといけないので正直メリットはあまりないのではないかと思う今日この頃です。

概念と用語

基本的な概念

yoctoでは、レイヤーとレシピという概念が存在します。
レシピは文字通り、ビルドを行うのに必要な手順やソースコードの情報になります。ソースコードの場所やビルド時に必要な手順を .bb という拡張子のファイル書いておきます。レイヤーは複数のレシピをまとめたものです。このレイヤーとレシピの依存関係を解決してよしなにイメージをビルドしてくれるるのがyoctoを使うメリットになるそうです。
ユーザーランドのアプリケーションはmake/Makefileを使ってビルドするプロジェクトとして開発をすることが多いと思いますが、makeで生成する実行モジュールやライブラリのビルドをレシピとして管理する形になります。

poky

pokyとは何でしょうか?公式サイトには

Poky is a reference distribution of the Yocto Project®. It contains the OpenEmbedded Build System (BitBake and OpenEmbedded Core) as well as a set of metadata to get you started building your own distro. To use the Yocto Project tools, you can download Poky and use it to bootstrap your own distribution. Note that Poky does not contain binary files – it is a working example of how to build your own custom Linux distribution from source.

と書かれています。要するにビルドに必要なツール類やスクリプト等の一式との認識でよいかと思います。
pokyのレポジトリをcloneして入手します*1

bitbake

組み込み開発のような様々なターゲット向けにビルドを行うことを前提としたツールセットです。BitBakeは元々OpenEmbeddedの一部としてスタートしたそうです。現在の私の認識は、bitbakeはpokyで提供されるビルドに必要なコマンド群というイメージです。

実際にyoctoでビルドしてみよう

なんちゃってうんちくはこれくらいにして、実際に手を動かしてビルドして自作のイメージを作る流れを体験してみましょう!

ターゲット

BeagleBone Black用のイメージをビルドして実機で動作させてみました。
BeagleBone Blackはyoctoプロジェクトのリファレンスターゲットとして含まれています。
ちなみに標準だとQEMU用のイメージがビルドされますが、それだと組み込み感がないので...

環境構築

まずはビルドに必要なツールやライブラリをインストールします。

# essentials
sudo apt-get install gawk wget git-core diffstat unzip texinfo gcc-multilib build-essential chrpath

# need for GUI
sudo apt-get install libsdl1.2-dev xterm

# need for build Application Development kit 
sudo apt-get install autoconf automake libtool libglib2.0-dev

pokyの入手

# ビルド用ディレクトリ作成とpokyの入手
$ mkdir yocto
$ cd yocto
$ git clone -b zeus git://git.yoctoproject.org/poky.git
$ source ./poky/oe-init-build-env build_bbb

yoctoのリリースとバージョンについて

Releases - Yocto Project

を見ると、yoctoは1年に1~2回程度は新しいバージョンがリリースされています。
バージョンによってコマンドなどで非互換というか機能が変わったりするものもあるようです。

私の経験上、ビルドしたいレシピがバージョンによってはすんなりとビルドが通らないバージョンもあるのでエラーにはまって原因調査に時間を取られるよりは違うバージョンを試した方が無難な気がします。

今回試したyoctoのバージョンは記事を書いている時点の最新版で、3.0 Zeus になります。

ちなみにボードベンダーのBSPを使って開発をするときは yoctoのバージョンも決まっていて、

git clone -b jethro git://git.yoctoproject.org/poky.git

のようにバージョンに対応するブランチを指定してpokyを入手することが多いかと思います。

ビルド用初期化

oe-init-build-envはビルド時に使用する環境変数等を設定するスクリプトになっています。

oe-init-build-env ビルド用ディレクトリ名

として実行します。
既に同名のディレクトリがあればそのディレクトリに移動します。
oe-init-build-envを実行すると、指定したディレクトリにビルドに関する設定ファイルが生成されます。
環境変数として、PATH,BUILDDIR,BB_ENV_EXTRAWHITEといった変数が追加・更新されます。
ビルド時にはbitbakeコマンドを実行しますが、bitbakeコマンドがあるディレクトリへのパスの追加もこの oe-init-build-env がやってくれています。

ビルドターゲットの変更

conf/local.conf を編集しビルドターゲットを指定します。

MACHINE ?= "beaglebone-yocto"

の行のコメントアウトを削除して有効にします。
ここでの MACHINE ?= の ?= は代入だけど、最後に指定されたされた ?= が有効になります。
また、 MACHINEに関して、

MACHINE ??= "qemux86-64"

という行がありますが、 ??=はMACHINEに何値が設定されていない場合に ??= で指定された値を設定するという意味です。
要するに、最後に書いておけばデフォルト値として使えるよということだと思います。
QEMUで試してみたいという人はこのconf/local.confの MACHINE を変更する必要はありません。

ビルドの実行

デフォルトのレシピとしていくつかターゲット用イメージをビルドするレシピが含まれていますが、各イメージの詳細はいまいちよくわかりません。

ここでは最小構成のイメージをビルドするcore-image-minimalをビルドしてみます。

bitbake core-image-minimal

実行するとしばらく時間がかかりますので放置しておきましょう。
といっても途中でビルドがエラー終了したりすることはよくあるので、初めてのビルドであれば時々進捗具合をした方がよいかもしれません。

私の手元では、core i7-870の古いPCをSSDへ換装し、メモリも16GBにしてビルドマシンとして使っていますが2~3時間程度でビルドは無事完了しました。*2

ちなみに、yoctoではビルド結果の情報を保持していて、2回目以降のビルドでは依存関係をチェックして必要なレシピのみビルドしてくれます。

ビルドの生成物はどこにできているのか?

ビルドが終わったら何をすればいいのでしょうか。そもそも成果物はどこにできているのでしょうか?
結論でいうと tmpディレクトリの中にできているのですが、大まかなディレクトリ構成についても触れておきたいと思います。

ディレクトリ構成

bitbakeでビルドしたときにできるディレクトリ構成についてみてみます。
ビルド用ディレクトリ(今回の場合 build_bbb)には、

  • cache
  • conf
  • downloads
  • sstate-cache
  • tmp

ディレクトリができています。このうち、confディレクトリとその中身は oe-init-build-env を実行した際に生成されます。

cache

cacheは文字通りビルドに必要な情報のキャッシュ用フォルダのようです。レシピファイルの解析だけでもちょっと時間がかかったりするのでビルド時間を短縮するためにできるだけキャッシュしておこうというのがyoctoのコンセプトのようです。

downloads

yoctoではレシピをビルドする際にビルドに必要なソースコードをインターネットから入手できます。
例えばあるプロジェクトの最新のソースをgithubからダウンロードしたり、特定のバージョンのtar.gzファイルを取ってきたりとかです。
downloadsはそういったネットから入手したファイルを保持しておくディレクトリです。このディレクトリのパスはlocal.confの DL_DIR で定義されており変更することもできます。

sstate-cache

このディレクトリの役割はよく分かっていません。sstateをキャッシュしてくれているんですよ、きっと。

tmp

皆さんお待ちかねのディレクトリです。ビルドプロセスで出来た中間生成物や最終生成物はこのディレクトリ以下に含まれています。
yoctoではクロスコンパイルする際に必要なクロスコンパイラのビルド自体がレシピとして含まれていますが、ビルドされたクロスコンパイラはworkディレクトリにできています。

ビルド成果物の流れとして、

  1. tmp/work以下にとりあえず成果物ができる。
  2. ROM焼きとかブート用SDへの書き込みに必要なファイルはtmp/workからtmp/deploy/images 以下に展開される

という流れになります。

SDカードへの書き込み

話を戻して、SDカードからイメージを起動されるため、ビルドしてできたファイルをSDカードへコピーしていきます。

SDカードの準備

BeagleBoneBlackで使用するSDカードはブートローラ用のパーティションとROOTFS用のパーティションの最低2つのパーティションが必要になります。

以下の用にパーティションを設定します。

パーティションラベル ファイルシステム サイズ 注意事項
BOOT FAT32(LBA) 32MB BOOTフラグを有効にすること
ROOT ext4 残り全てのサイズ -

ここではコマンドの詳細は省略しますが、fdiskを使って適切に設定してください。

パーティションを適切に設定できたら、マウント用ディレクトリを作成し、マウントします。

$ sudo mkdir /media/$USER/BOOT
$ sudo mkdir /media/$USER/ROOT
$ sudo mount /dev/sdd1 /media/$USER/BOOT
$ sudo mount /dev/sdd2 /media/$USER/ROOT

SDカードの2つのパーティションをマウントしたら必要なファイルをコピーしていきます。

BOOTパーティション

まずはBOOTパーティションからです。
BOOTパーティションは文字通りLinuxのブートに必要なファイルを配置するパーティションです。
MLOやU-BOOTのイメージ、デバイスツリー等のファイルをコピーしていきます。

$ cd yocto/build_bbb/tmp/deploy/images/beaglebone-yocto/
$ sudo cp MLO /media/$USER/BOOT
$ sudo cp u-boot.img /media/$USER/BOOT
$ sudo cp zImage /media/$USER/BOOT
$ sudo cp am335x-bone.dtb /media/$USER/BOOT/
$ sudo cp am335x-boneblack.dtb /media/$USER/BOOT/
U-BOOT用ファイルの配置

uEnv.txtをBOOTパーティションにおいておくことで、起動方法を細かく指示できます。このuEnv.txtはyoctoのビルドでは生成されないので自分で書く必要があります。

ブートに必要な情報を書き込んだらSDカードのBOOTパーティションに配置します。

$ echo "bootdir=/boot" >> uEnv.txt
$ echo "bootpart=0:2" >> uEnv.txt
$ sudo cp uEnv.txt /media/USER/BOOT/

これでBOOTパーティションの準備は完了です。

ROOTパーティション

ROOTパーティションLinuxのルート(/)以下として見えるディレクトリ構成です。yoctoのビルドではtar.bz2形式でrootfs一式が圧縮されていますのでROOTパーティション以下に展開します。

sudo tar -xf core-image-minimal-beaglebone-yocto.tar.bz2 -C /media/$USER/ROOT

これでSDカードの準備ができました。

最後にアンマウントします。

$sudo umount /dev/sdd1 
$sudo umount /dev/sdd2

SDカードからの起動

書き込みが完了したSDカードをBeagleBoneBlackに差し込み起動します。
起動中のログはシリアルコンソールに出力されるのでUSB-シリアル変換ケーブルが必要になります。
私は秋月電子で買ったケーブルを愛用しています。

写真のようにつないでください。
ケーブルから見て、オレンジ:TX 黄色:RX 黒:GNDです。
f:id:simotin13:20191104161756j:plain

f:id:simotin13:20191104161747j:plain

シリアルコンソールの通信設定は、

  • ボーレート:115200
  • データビット:8bit
  • ストップビット:1bit
  • パリティ:None

です。

ログを見てみると無事起動できたようなのでrootユーザーでログインしてみます。パスワードはありません。

INIT: Entering runlevel: 5
Configuring network interfaces... cpsw 4a100000.ethernet: initializing cpsw version 1.12 (0)
SMSC LAN8710/LAN8720 4a101000.mdio:00: attached PHY driver [SMSC LAN8710/LAN8720] (mii_bus:phy_addr=4a101000.mdio:00, irq=POLL)
udhcpc: started, v1.31.0
udhcpc: sending discover
udhcpc: sending discover
cpsw 4a100000.ethernet eth0: Link is Up - 100Mbps/Full - flow control off
IPv6: ADDRCONF(NETDEV_CHANGE): eth0: link becomes ready
udhcpc: sending discover
udhcpc: sending select for 192.168.1.15
udhcpc: lease of 192.168.1.15 obtained, lease time 86400
/etc/udhcpc.d/50default: Adding DNS 192.168.1.1
done.
Starting syslogd/klogd: done

Poky (Yocto Project Reference Distro) 3.0 beaglebone-yocto /dev/ttyS0

beaglebone-yocto login: root
root@beaglebone-yocto:~# uname -a                                                                                                      
Linux beaglebone-yocto 5.2.17-yocto-standard #1 PREEMPT Mon Nov 4 01:49:00 UTC 2019 armv7l GNU/Linux
root@beaglebone-yocto:~# 

unameで見るとLinux beaglebone-yocto 5.2.17-yocto-standardとなっているので無事書き込めてそうです。

twitterを見てみると最初にBeagleBoneBlackで試したのは9月26日だったようです。記事を書くまで時間が空いてしまいました...


参考記事など

kiyomi2013.net

www.slideshare.net

qiita.com

上記、参考にさせて頂いた記事の皆様、ありがとうございます。


yoctoに関する日本語の書籍はないようですし、手を動かしてみないとだめですね。英語だと割と書籍が出ていて、私は以下の2冊を購入してみました。

Using Yocto Project with BeagleBone Black (English Edition)

Using Yocto Project with BeagleBone Black (English Edition)

Cookbookの方は割と満遍なく色んな情報が載っています。Using Yocto Project with BeagleBone Blackは分かりやすいですが、少し情報が古いです。実際、最新のpokyではBOOTパーティション用のファイルが現状のpokyの内容と違っているのでこの本に書かれている通りに試すことはできません。

上記はamazonのリンクですが、packt本家のサイトで買った方が安いです。

www.packtpub.com

ちなみに月数ドル払うと、「ダウンロードはできないけど、読み放題」みたいなプランもあります。サブスクの時代ですね。

まとめ

書いてみるとかなり長い記事になりました。yoctoはLinuxのボードベンダーの人達にとってはメリットがあるかもしれませんが
、覚えることが多く学習コストが高いので、組込アプリケーション開発者には正直あまりメリットがないような気がしています。

Linuxを採用する理由って、「サポートはないけどとりあえず全部入りで、無償で簡単に開発が始められるから」というのがあると思いますが、そもそも開発する際の学習コストが高かったり、よく分からないところで頻繁にはまるようだとLinuxを採用する意味ってあまり無くなってくるんじゃないかと思います。

感想

ざっと手順を押さえるだけでも調べること(結構書くこと)があって疲れた...

続けてレシピの自作ネタの方法とMakefileのプロジェクトをレシピ化する記事も書こうと思います。

*1:私の中ではyocto=poxyみたいな認識があります。pokyを使わなかったらどうするんだろう

*2:気がついたら終わっていたので正確な時間が分かりません...