simotin13's message

simotin13といいます。記事の内容でご質問やご意見がありましたらお気軽にコメントしてください\^o^/

yoctoに入門してみる

追記

こちらの記事は2019年に書いた記事でしたが、最近のyoctoでビルドするとこの記事の手順通りにしてもSDカードからLinuxを起動できなくなっていました。(2023年7月時点)
kirkstoneでビルドしたイメージを動かす記事を改めて書きましたのでBeagleBoneBlackで動かす部分については以下のリンクの記事の方を参考にしてください。
mcommit.hatenadiary.com

yoctoの基本的な知識についてはこちらの記事に書いてあることからあまり変わっていませんのでこちらの記事を読んで頂ければと思います。

(追記ここまで)

ちょっと前にyoctoについて色々と調べる機会があったので理解している範囲で書いておきたいと思います。
yoctoに関する基本的な知識BeagleboneBlack用のイメージをビルドし動かすまでの手順を書いたので少し長くなりました。

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のレポジトリをgit 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ではクロスコンパイルする際に必要なクロスコンパイラのビルド自体がレシピとして含まれていますが、ビルドされたクロスコンパイラはtmp/workディレクトリにできています。

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

  1. tmp/work以下に中間成果物ができる。(gitとかで取得するソースコードもここに展開されてビルドされる)
  2. ROM焼きとかブート用SDへの書き込みに必要なファイルはtmp/workからtmp/deploy/images 以下に展開される

という流れになります。

SDカードへの書き込み

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

SDカードの準備

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

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

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

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

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

注意
以下はSDカードが /dev/sdd1, /dev/sdd2 として認識されていることを前提としています。
実行する際は各自の環境に読みかえて実行してください。


$ sudo mkdir -p /media/$USER/BOOT
$ sudo mkdir -p /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 /media/$USER/BOOT
$ sudo umount /media/$USER/ROOT

SDカードからの起動

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

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

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

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

です。

SDカードから起動する場合の注意点

SDカードから起動する場合、BOOTボタンを押しながら起動する必要があります。
BeagleBoneBlackのブートデバイスのチェックではeMMCがSDカードより優先されています。
常にSDカードから起動したい場合は、基板上のeMMCのブートセクタの内容を消してしまうことで毎回BOOTボタンを押す必要はなくなります。
eMMCのブートセクタを消す場合、シリアル通信でコンソールの内容を確認しつつ、U-BOOTの起動中にエンターキーを押すことでU-BOOTの対話モードに入ることできます。パソコンの起動時にF2やF8キーなどを押してBIOS画面に入るのと同じようなイメージです。

U-BOOTの対話画面に入ったら

# mmc dev 1
# mmc erase 0 512

のコマンドを実行することでeMMCの内容を削除できます。これにより次回起動以降、SDカードからブートしてくれるようになります。

ただし、eMMCのブートセクタを削除してしまったので、eMMCからは起動できない状態になっています。
元のようにeMMCから起動したい場合は、復元用のSDカードを作成し起動することで復元することができます。
詳細は、マルツオンラインさんの以下の記事で詳しく解説してくださっているのでこちらの記事を参考になります。
www.marutsu.co.jp

SDカードからの起動確認

上記のような起動時の準備を終えて、無事SDカードから起動するとシリアルコンソールに以下のようなログが出力されます。
ログを見てみると無事起動できたようなので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日だったようです。記事を書くまで時間が空いてしまいました...

参考記事など

http://kiyomi2013.net/wiki/index.php?title=Yocto_BeagleBone_Black#.E3.83.93.E3.83.AB.E3.83.89.E3.81.AE.E5.AE.9F.E8.A1.8Ckiyomi2013.net

www.slideshare.net

qiita.com

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


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

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

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

www.packtpub.com

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

まとめ

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

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

感想

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

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

追記

共有ライブラリ(.so)を作るためのレシピを書いてみた

この記事を書いてから、もう少し勉強してみて、共有ライブラリとそれを呼び出す実行モジュールをビルドするためのレシピの書き方をまとめてみました。yoctoで共有ライブラリを作る情報はネット上にあまり情報が出ていなようなので参考になれば幸いです。

mcommit.hatenadiary.com

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

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