mcommit's message

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

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

以前書いた記事、
mcommit.hatenadiary.com

ではBeagleBoneBlack用のイメージを作るのを試してみましたが今回はyocto を使って共有ライブラリ(.so)と共有ライブラリを参照する実行モジュールのビルド&イメージ化を試してみました。
組込Linuxの開発では(組込じゃなくても)共有ライブラリ(.so)を作って各実行モジュールでそれを呼び出すようなアプリケーションを開発することはよくあります。
ホスト環境で開発する場合は割と簡単ですが、できたプロジェクト一式をyoctoを使ってクロスコンパイルし、イメージ化する方法はあまり情報がなく、試行錯誤するのに割と時間がとられたので記事として挙げておきます。

とりあえず試したいという人はここを読んでください

この記事の内容を3分クッキング的におまとめしたレポジトリをGitHubに挙げております。

以下の手順で、環境構築~追加したレシピ(ライブラリ・実行モジュール)のビルド、イメージ作成までを試して頂けます。
※イメージでは追加した共有ライブラリは /usr/libに、実行モジュールは/usr/binに配置されます。

# yoctoで使用するツールのインストール
$ sudo apt install -y gawk wget git-core diffstat unzip texinfo gcc-multilib build-essential chrpath libsdl1.2-dev xterm autoconf automake libtool libglib2.0-dev

# ホームディレクトリ/yocto に作業用ディレクトリを作成
$ cd
$ mkdir yocto
$ cd yocto

# 3.0 zeusのpokyを取得
$ git clone -b zeus git://git.yoctoproject.org/poky.git

# サンプルレイヤを取得
$ git clone git@github.com:simotin13/yocto-mysample-layers.git
   
# ビルド用ディレクトリ作成・bitbake 環境変数初期化
$ source ./poky/oe-init-build-env build_bbb

# bblayers.conf, local.conf の更新 
# bblayers.conf ではサンプルレイヤ(meta-calc)をbblayers.confに追加しています
# レイヤのパスは $HOME/yocto/octo-mysample-layers/meta-calcとしています 必要に応じて変更してください。
$ cp ../../yocto/yocto-mysample-layers/meta-calc/build_conf_sample/bblayers.conf conf/

# local.conf では ターゲットを MACHINE ?= "beaglebone-yocto" とし、実行モジュール(calc)をイメージに追加しています。
$ cp ../../yocto/yocto-mysample-layers/meta-calc/build_conf_sample/local.conf conf/

# 最小構成のイメージである core-image-minimalに組み込む
$ bitbake core-image-minimal

環境構築

yoctoを利用するには必要なツール類をインストールする必要があります。

ツールのインストールが完了したら、続けてyoctoのレポジトリを入手します。
本記事では Yocto Project Version 3.0 Zeusを使って説明します。
レシピの追加作業はターゲットとはあまり関係ありませんが local.confでは MACHINE ?= "beaglebone-yocto" を指定することを想定しています。
source ./poky/oe-init-build-env ディレクトリ名 でビルド用のディレクトリが作成され、bitbakeを使うための諸々の環境変数が設定されます。

ここでは 作業用ディレクトリとしてホームディレクトリ以下に yocto というディレクトリを作成して作業します。
また、ビルド用ディレクトリは build_bbb とします。

# yoctoで使用するツールのインストール
$ sudo apt install -y gawk wget git-core diffstat unzip texinfo gcc-multilib build-essential chrpath libsdl1.2-dev xterm autoconf automake libtool libglib2.0-dev

# ホームディレクトリ/yocto に作業用ディレクトリを作成
$ cd
$ mkdir yocto
$ cd yocto

# 3.0 zeusのpokyを取得
$ git clone -b zeus git://git.yoctoproject.org/poky.git

# ビルド用ディレクトリ作成・bitbake 環境変数初期化
$ source ./poky/oe-init-build-env build_bbb

今回試すプロジェクトの構成

例としてint型の四則演算をするライブラリ(libcalc)とそれを使用するモジュール(calc)を例にイメージを作るために必要なことを説明していきます。
1ファイルずつのシンプルな構成ですが、多くのアプリケーションでもこのように

$ tree
.
├── calc
│   ├── Makefile
│   └── main.c
├── include
│   └── libcalc.h
└── libcalc
    ├── Makefile
    └── libcalc.c

のような構成で開発することが多いと思いますのでこの構成で基本をマスターすれば応用を利かせられるのではないかと思います。

各ファイルについて説明しておきます。

libcalcディレクト

このフォルダには計算ライブラリ用のソースコードMakefileを配置しています。

libcalc/libcalc.c
足し算・引き算・掛け算・割り算の関数を実装しています。

int add(int a, int b)
{
	return a + b;
}

int sub(int a, int b)
{
    return a - b;
}

int mul(int a, int b)
{
	return a * b;
}

int div(int a, int b)
{
	return a / b;
}


libcalc/Makefile

TARGET=libcalc.so
SRCS=libcalc.c

all:
	${CC} ${SRCS} -shared -o ${TARGET}

install:
	sudo cp ${TARGET} /usr/local/lib;
	sudo ldconfig;

clean:
	rm -f ${TARGET}

calcディレクト

このフォルダにはライブラリを呼び出す側(main関数)のソースコードMakefileを配置しています。
calc/main.c

#include <stdio.h>
#include "libcalc.h"

int main(int argc, char **argv)
{
	printf("1 + 2 = %d\n", add(1, 2));
	printf("3 - 1 = %d\n", sub(3, 1));
	printf("2 * 5 = %d\n", mul(2, 5));
	printf("9 / 3 = %d\n", div(9, 3));

	return 0;
}

calc/Makefile

TARGET=calc
SRCS=main.c

all:
	${CC} ${SRCS} -I../include -lcalc -o ${TARGET}

clean:
	rm -f ${TARGET}

includeディレクト

ライブラリ関数の公開用ヘッダファイルを配置しています。

include/libcalc.h

#ifndef _LIBCALC_H_
#define _LIBCALC_H_

extern int add(int a, int b);
extern int sub(int a, int b);
extern int mul(int a, int b);
extern int div(int a, int b);

#endif	// _LIBCALC_H_

注意すべきポイント

結論ですが、yoctoでビルドする場合はMakefileの書き方に注意が必要です。

Makefileを制する者がyoctoを制する

と言っても過言ではないのではないかと個人的には思っています。

bitbakeによるビルドプロセスは、終了コードが正常でなければ止まり、コンソール画面が真っ赤なエラー出力で埋め尽くされます。
セルフ開発用に書かれたMakefileだと恐らくそのままではyoctoで使えなくて、Makefileを書き直すか .bb側で回避する手順を書く必要が出てきます。

なのでMakefileでは想定外のエラーが起こらないような書き方をしておく必要があります。

具体的な例ですが、

  • clean ターゲットが do_configureで呼ばれるので 必ず clean は定義しておく必要がある
  • clean するときは rm -f hoge のように-fオプションをつけておかないと未ビルドの状態でcleanが走ってビルドがこける
  • ビルド手順は gcc hoge.c -o hoge みたいに書いちゃだめ。 ${CC} hoge.c -o hoge とか ${CXX} hoge.cpp -o hoge と書くこと*1
  • サフィックスルール使うとCFLAGSとかがうまく機能しないことあるので注意。*2

レイヤーの作成

レシピ化したいプロジェクトが決まれば、まずはレイヤーを作成します。
レイヤはどこのディレクトリで作成しても問題ないのですが、ビルド用ディレクトリ(ここではbuild_bbb)には含めないのが一般的のようです。
とりあえずyoctoディレクトリ直下に作成します。

# yocto ディレクトリに移動
$ cd ~/yocto
$ bitbake-layers create-layer meta-calc
NOTE: Starting bitbake server...
Add your new layer with 'bitbake-layers add-layer ../meta-calc'

bitbake-layersコマンドは 環境変数が設定された状態、つまり

>>||
source ./poky/oe-init-build-env ディレクトリ名
|

をたたいた後でないと実行できないので注意してください。


作成されたレイヤーは以下のような構成になっています。

$ tree meta-calc/
meta-calc/
├── COPYING.MIT
├── README
├── conf
│   └── layer.conf
└── recipes-example
    └── example
        └── example_0.1.bb

3 directories, 4 files

補足(古いのバージョンのyoctoでのレシピの追加)

以前のyoctoでは ./poky/scripts/yocto-layer create レイヤ名 でレイヤとhelloworldのサンプルプログラムを作ることができていたのですが最近のバージョンでは廃止されたようです。
yocto-layer createの方式がどのバージョンで廃止されたのか分かりませんが、2.0(Jethro)では作成できました。

$ ./poky/scripts/yocto-layer create sample
Please enter the layer priority you'd like to use for the layer: [default: 6] 
Would you like to have an example recipe created? (y/n) [default: n] y
Please enter the name you'd like to use for your example recipe: [default: example] 
Would you like to have an example bbappend file created? (y/n) [default: n] n

New layer created in meta-sample.

Don't forget to add it to your BBLAYERS (for details see meta-sample\README).

bitbakeがレイヤとレシピを認識する流れ

レイヤを作成しただけではbitbakeのビルド対象に含まれません。
イメージのビルド用ディレクトリ(build_bbb)内の conf/bblayers.conf の BBLAYERS変数にレイヤのパスを追加する必要があります。

以下はBBLAYERS に meta-calc を追加した conf/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/simotin13/yocto/poky/meta \
  /home/simotin13/yocto/poky/meta-poky \
  /home/simotin13/yocto/poky/meta-yocto-bsp \
  /home/simotin13/yocto/meta-calc \
  "

サンプルのレポジトリの設定では /home/simotin13/ を ${HOME}としています。


bblayers.confを編集することで、meta-calcレイヤを追加することができました。

正しく追加できたかどうかは bitbake-layers show-layers コマンドで確認できます。
レイヤのパスが間違ってたりするとエラーメッセージ表示されます。

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

レシピをビルドしてみる

新規に作成したレイヤではexampleというレシピが含まれています。
レシピのビルドは bitbake レシピ名 でできます。
exampleレシピは何も生成しないのですが、bitbakeの標準の動作に従ってビルドプロセスが走るようです。

layer.conf について

bblayers.conf を編集してレイヤを追加する手順は分かりました。
ではレシピはどのようにbitbakeに認識されているのでしょうか?

レシピディレクトリ直下の conf/layer.conf にレシピを認識させるため設定が記述されています。

meta-calc/conf/layer.conf

# We have a conf and classes directory, add to BBPATH
BBPATH .= ":${LAYERDIR}"

# We have recipes-* directories, add to BBFILES
BBFILES += "${LAYERDIR}/recipes-*/*/*.bb \
            ${LAYERDIR}/recipes-*/*/*.bbappend"

BBFILE_COLLECTIONS += "meta-calc"
BBFILE_PATTERN_meta-calc = "^${LAYERDIR}/"
BBFILE_PRIORITY_meta-calc = "6"

LAYERDEPENDS_meta-calc = "core"
LAYERSERIES_COMPAT_meta-calc = "warrior zeus"

BBFILES += に.bbや .bbappend ファイルを追加していますが、
要するにレイヤのディレクトリ以下のrecipes-xxx というディレクトリから2階層下のディレクトリ内にある拡張子が .bb というファイルをレシピとして追加しています。
実際に、ひな形で生成されるサンプルのレシピ(example)も /meta-calc/recipes-example/example/example_0.1.bb として作成されています。

layer.conf の記載は自由に変更できますが、ディレクトリの構成は基本的にこの構成に従って作成していきます。

レシピフォルダ名を変更する

recipes-example では何のレシピか分かりつらいのでディレクトリ名を recipes-exampleに変更します。(recipes-xxxの形であれば.bbファイルは読み込まれる)
ひな形として作成されているexampleディレクトリ以下のディレクトリも削除します。

cd meta-calc
mv recipes-example/ recipes-calc
rm  -rf recipes-example/example

続けて、calc以下に今回ビルドするプロジェクト一式を配置します。
meta-calc以下のディレクトリ構成は以下のようになります。

$ tree
.
├── COPYING.MIT
├── README
├── conf
│   └── layer.conf
└── recipes-calc
    └── calc
        ├── calc
        │   ├── Makefile
        │   └── main.c
        ├── include
        │   └── libcalc.h
        └── libcalc
            ├── Makefile
            └── libcalc.c

レシピファイル(.bbファイルを作る)

ディレクトリ構成はひとまずこれで準備できました。
後は.bbファイルを作成していくだけです。zeusで作成される.bbファイルは実質的に何もしないので参考になりません。
ひな形としては、yoctoの以前のバージョンで作成できていたhelloworldレシピの .bb ファイルが参考になります。

レシピファイル名のルール

レシピファイルには、

  • 拡張子は.bb
  • レシピ名の後に_0.1.bb のようにバージョンをつける*3

など基本的なルールがあるようです。
またパッチを充てる時などには.bbapendというファイルを別途書くのが作法らしいですが今回は触れません。

出来上がったレシピファイルを挙げておきます。

ライブラリ用レシピ libcalc_1.0.bb

SUMMARY = "Simple calc library"
SECTION = "libs"
LICENSE = "MIT"
LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302"

PACKAGES = "${PN}"
PROVIDES = "${PN}"

FILES_${PN} += "${libdir}/libcalc.so"
INHIBIT_PACKAGE_DEBUG_SPLIT = "1"

SRC_URI = "file://."
S = "${WORKDIR}"
TARGET_CC_ARCH += "${LDFLAGS}"

do_compile() {
        echo "WORKDIR:${WORKDIR}" >> ~/build.log
        echo "D:${D}" >> ~/build.log
        echo "S:${S}" >> ~/build.log
        oe_runmake
}

do_install() {
             install -d ${D}${libdir}
             install -m 0755 libcalc.so ${D}${libdir}
}

実行モジュール用レシピ calc_1.0.bb

SUMMARY = "Simple calc application"
SECTION = "applications"
LICENSE = "MIT"
LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302"

SRC_URI = "file://.."

S = "${WORKDIR}/calc"

DEPENDS = "libcalc"
RDEPENDS_${PN} = "libcalc"

TARGET_CC_ARCH += "${LDFLAGS}"

do_compile() {
        oe_runmake
}

do_install() {
        install -d ${D}${bindir}
        install -m 0755 calc ${D}${bindir}
}

レシピファイルの解説~正しく書かないとエラーの群れが襲ってくるよ~

レシピファイルの内容について説明してみます。
まずはライブラリ用のレシピファイルから順に中身を説明していきたいと思います。

SECTIONとLICENSE

SUMMARY は レシピのsummaryです。
SECTION は レシピの分類です。一応共有ライブラリは libs、実行モジュールは applications としてみましたがいまだにこの分類が何の役に立つのかよくわかりません。

LICENSE,LIC_FILES_CHKSUMは文字通りライセンス関係の変数です。
これらはきちんと定義されていないとビルドは通りません。とりあえずひな形のままとしています。

SRC_URI

SRC_URI はソースファイルあるいはフォルダのパスです。
yoctoではネット上からソースをダウンロードしてビルドしたりできるので git://hogeとか http://hoge みたいなスキームがあります。

ローカルにソース一式がある場合は file:// を使います。
パスの指定は、レシピ名に対応するディレクトリが基準になるようです。
yoctoのひな形レシピでは、

└── example
    ├── example-0.1
    │   ├── example.patch
    │   └── helloworld.c
    └── example_0.1.bb

のような構成上で、

SRC_URI = "file://helloworld.c"

と書かれています。

SRC_URI = "file://."

とするとexample-0.1ディレクトリ以下がビルド対象になります。
今回はローカル上にソースファイルを配置した状態でビルドするのでfile://のスキームで記述します。

ビルド時の動作とビルド対象のファイルについて

bitbakeでのビルドはどのように行われるのでしょうか?ここまでの手順でmeta-calcというレイヤディレクトリを作成し、ビルド対象のソースファイル等を配置しました。
では、ビルドはこのmeta-calc以下で行われて、ここに成果物が生成されるかというとそうではありません。

bitbakeでビルドが行われるとき、SRC_URIで指定されたディレクトリやファイルがビルド用の一時ディレクトリ(tmp/work以下にできる)にコピーされ、そこでビルドが行われます。*4

従って、SRC_URIの指定に含まれないディレクトリやファイルはビルド時には見つかりません。
※ただし標準ライブラリや標準インクルードヘッダは除く。これらはビルド用のsysroot以下に配置されていてビルド時には適切に参照されます。

話をlibcalcに戻すと、SRC_URI = "file://."と書くことで

の2ファイルがビルド実行時にビルド用ディレクトリにコピーされます。

SとmakeとWORKDIR

S = "${WORKDIR}"

の行がありますが、S は bitbakeがコンパイルを行うディレクトリです。
makeでコンパイルするプロジェクトの場合はMakefileが配置されている必要があります。

が設定されています。

WORKDIR はビルド用の一時ディレクトリです。
今回のケースではSRC_URIディレクトリとMakefileを配置しているディレクトリは一致していますが、もう少しディレクトリ階層が複雑な場合は指定してあげる必要があります。

ビルド時の手元の環境では、WORKDIRは

/home/simotin13/yocto/build_bbb/tmp/work/cortexa8hf-neon-poky-linux-gnueabi/libcalc/1.0-r0

になっていました。

PACKAGESとPROVIDES

PACKAGES = "${PN}"
PROVIDES = "${PN}"

パッケージ名・プロバイダ名の設定です。${PN}はレシピ名が設定されています。(ここではlibcalc)

PACKAGESとPROVIDESは指定しなくても標準的にレシピ名が設定されるようですが、ライブラリ側ではこのような指定しておかないと実行モジュール側から見つけてもらえないようなエラーが出ました。

ERROR: libcalc-1.0-r0 do_package_qa: QA Issue: -dev package contains non-symlink .so: libcalc-dev path '/work/cortexa8hf-neon-poky-linux-gnueabi/libcalc/1.0-r0/packages-split/libcalc-dev/usr/lib/libcalc.so' [dev-elf]
ERROR: libcalc-1.0-r0 do_package_qa: QA run found fatal errors. Please consider fixing them.
ERROR: Logfile of failure stored in: /home/simotin13/yocto/build_bbb/tmp/work/cortexa8hf-neon-poky-linux-gnueabi/libcalc/1.0-r0/temp/log.do_package_qa.13360
ERROR: Task (/home/simotin13/yocto/yocto-mysample-layers/meta-calc/recipes-calc/calc/libcalc_1.0.bb:do_package_qa) failed with exit code '1'

FILES

FILES_${PN} += "${libdir}/libcalc.so"

FILES は パッケージ化対象のファイルを指定する変数です。サフィックスとして${PN}を指定するのが一般的なようです。

指定しない場合、

ERROR: libcalc-1.0-r0 do_package: QA Issue: libcalc: Files/directories were installed but not shipped in any package:
  /usr
  /usr/lib
  /usr/lib/libcalc.so
Please set FILES such that these items are packaged. Alternatively if they are unneeded, avoid installing them or delete them within do_install.
libcalc: 3 installed and not shipped files. [installed-vs-shipped]
ERROR: libcalc-1.0-r0 do_package: Fatal QA errors found, failing task.
ERROR: Logfile of failure stored in: /home/simotin13/yocto/build_bbb/tmp/work/cortexa8hf-neon-poky-linux-gnueabi/libcalc/1.0-r0/temp/log.do_package.13887
ERROR: Task (/home/simotin13/yocto/yocto-mysample-layers/meta-calc/recipes-calc/calc/libcalc_1.0.bb:do_package) failed with exit code '1'

のようなエラーが出ます。

bitbakeのビルドプロセスではビルドが正常に通った後は、レシピをパッケージにするプロセス(do_package)が走ります。
このとき do_install でコピーしたファイルが指定されていないということでこのようなエラーが発生するようです。

bitbake「ビルドしたけどパッケージ化しなくていいの?とりあえずエラーにしとくね」
simotin13「あっ、ごめん FILES_${PN} 書くの忘れてた!」

的なことでしょう。

指定しないとエラーになるやつ(TARGET_CC_ARCHとINHIBIT_PACKAGE_DEBUG_SPLIT )

  • TARGET_CC_ARCH
TARGET_CC_ARCH += "${LDFLAGS}"

よくわかりませんが、この指定がないとエラーがでました。

ERROR: libcalc-1.0-r0 do_package_qa: QA Issue: No GNU_HASH in the ELF binary /home/simotin13/yocto/build_bbb/tmp/work/cortexa8hf-neon-poky-linux-gnueabi/libcalc/1.0-r0/packages-split/libcalc/usr/lib/libcalc.so, didn't pass LDFLAGS? [ldflags]
ERROR: libcalc-1.0-r0 do_package_qa: QA run found fatal errors. Please consider fixing them.
ERROR: Logfile of failure stored in: /home/simotin13/yocto/build_bbb/tmp/work/cortexa8hf-neon-poky-linux-gnueabi/libcalc/1.0-r0/temp/log.do_package_qa.12896
ERROR: Task (/home/simotin13/yocto/yocto-mysample-layers/meta-calc/recipes-calc/calc/libcalc_1.0.bb:do_package_qa) failed with exit code '1'

指定しておかないとLDFLAGSがちゃんと渡されないっぽいです。

  • INHIBIT_PACKAGE_DEBUG_SPLIT
INHIBIT_PACKAGE_DEBUG_SPLIT = "1"

こちらも指定しておかないとエラーが出ます。

ERROR: libcalc-1.0-r0 do_package: QA Issue: libcalc: Files/directories were installed but not shipped in any package:
  /usr/lib/.debug
  /usr/lib/.debug/libcalc.so
Please set FILES such that these items are packaged. Alternatively if they are unneeded, avoid installing them or delete them within do_install.
libcalc: 2 installed and not shipped files. [installed-vs-shipped]
ERROR: libcalc-1.0-r0 do_package: Fatal QA errors found, failing task.
ERROR: Logfile of failure stored in: /home/simotin13/yocto/build_bbb/tmp/work/cortexa8hf-neon-poky-linux-gnueabi/libcalc/1.0-r0/temp/log.do_package.13106
ERROR: Task (/home/simotin13/yocto/yocto-mysample-layers/meta-calc/recipes-calc/calc/libcalc_1.0.bb:do_package) failed with exit code '1'

stackoverflow.com

を読むと .debug というデバッグ関連のディレクトリが生成されるようです。
記事では do_installで生成されると書いてありますが、 do_installではなく、do_packageあたりのビルド成果物をimages ディレクトリに配置するタイミングっぽいです。*5

ということで .debugの生成を抑制するため指定しておきましょう。

タスクの処理の書き方(do_compile, do_install)

do_compile, do_install

do_compile, do_installはレシピ内で実行されるタスクです。

do_compileは、

do_compile() {
        oe_runmake
}

としていますが、bitbakeはデフォルトで Makefileをみつけてmakeを実行してくれるので、libcalcの場合は書かなくてもビルドが通ります。

do_installは

do_install() {
             install -d ${D}${libdir}
             install -m 0755 libcalc.so ${D}${libdir}
}

となっています。
${D}はイメージを作成するためのディレクトリでrootfsの構成になっています。ここにビルド結果をコピーします。
ただし、ルート(/)以下のディレクトリは存在しない状態になっているので

ビルド時の${D}は手元の環境では、

/home/simotin13/yocto/build_bbb/tmp/work/cortexa8hf-neon-poky-linux-gnueabi/libcalc/1.0-r0/image

となっていました。

処理内容ですが、

install -d ${D}${libdir}

ディレクトリを作成してあげています。
install コマンドは知りませんでしたが、文字通りinstallとかする時に使うコマンドです。-d オプションで mkdir -P 的なことをしてくれます。
${libdir} は /usr/lib が標準で設定されているそうです。

続けて実行する

install -m 0755 libcalc.so ${D}${libdir}

でビルド成果物である libcalc.so をコピーします。

libcalc_1.0.bbの内容はこんな感じです。

呼び出し側の実行モジュールのレシピファイルを見てみる

続いて、ライブラリを使う側のレシピファイルで注意すべき箇所を見てみます。

SECTION
SECTION = "applications"

何度もいいますが、このSECTIONの指定がどこでどのように役に立っているのかは謎です。

試しに

SECTION = "ちんちんブラブラ"

としてみましたがエラーにはなりませんでした。そこはエラーになって欲しかった...

SRC_URIとS

calcでのSRC_URIの書き方はlibcalcと異なり、

SRC_URI = "file://.."

としています。
1階層上のディレクトリからなのでcalcディレクトリの他、include,libcalcも含んでWORKDIRにコピーされます。
この書き方では.bbファイルもコピーされてしまいますしビルドには関係ないlibcalcもコピー対象に含んでしまいます。
本来であればもう一階層ディレクトリを分けるべきですが、レシピを作る前のプロジェクトのディレクトリをできるだけ変えないでビルドを通したかったのでとりあえず今回はよしとします。

ここで、SRC_URI = "file://.." としている理由ですが、includeディレクトリを含めたかったからです。
このため S変数の指定は、

S = "${WORKDIR}/calc"

とcalcディレクトリを明示的に指定しています。

DEPENDSとRDEPENDS_${PN}
DEPENDS = "libcalc"
RDEPENDS_${PN} = "libcalc"

の行があります。

あとはだいたいライブラリ側と似たような感じです。

レシピをビルドする

レシピができてbblayers.confにレイヤが追加できていれば

bitbake libcalc

bitbake calc

レシピのビルドが試せます。

イメージへの追加

上記の

bitbake libcalc
bitbake calc

ではレシピのタスクが実行されビルドはされますが、そのままでイメージに組み込まれるわけではありません。
自作したレシピの成果物をイメージに追加するには ビルドディレクトリの local.confに

IMAGE_INSTALL_append = " calc"

と記載する必要があります。

local.confの編集が終わればイメージを作成するレシピであるcore-image-minimalかcore-image-satoを指定すればイメージ作成のレシピの手順が実行されます。
私は手元の環境ではターゲットをMACHINE ?= "beaglebone-yocto"としてBeagleBoneBlack向けのイメージを作成し、SDカードに書き込んで試しています。

# イメージを作成するレシピの実行
bitbake core-image-minimal

参考

LICENSE, SECTIONの一覧について
スレッド bitbake:bitbake ファイルの書き方 - OpenZaurus-ja - OSDN

qiita.com

qiita.com

qiita.com

参考にさせて頂きましてありがとうございます。

参考書籍

Embedded Linux Projects Using Yocto Project Cookbook by Alex Gonzalez(2015-03-31)

Embedded Linux Projects Using Yocto Project Cookbook by Alex Gonzalez(2015-03-31)

  • 作者:Alex Gonzalez
  • 出版社/メーカー: Packt Publishing - ebooks Account
  • 発売日: 1895
  • メディア: 文庫
Cookbook ではChapter 4 Application Development Developing with librariesに共有ライブラリのビルドについて書かれていて参考になりました。
まぁ、書いてある通りに試してもエラーがいっぱい出ましたが...

まとめ

  • スムーズにビルドを通したければbitbakeに愛されるMakefileを書きましょう
  • bitbakeのエラーは意味不明
  • bitbakeのビルドは時間がかかるので人権のある環境で作業しましょう

感想

ソースコードやレシピを挙げて書いたのでかなり長い記事になってしまいました。間違っているところや他のやり方などあれば教えて頂けると幸いです。

yoctoはたかだか共有ライブラリと実行モジュールをクロスコンパイルしてイメージを作るだけなのにやたらと覚えることが多いです。学習コストがかなり高くついている気がします。

学習もコストも大嫌いなのですが、組み込みLinuxではyoctoは避けて通れなくなってきている感があるので引き続き勉強していきたいです。

次は時間があればopenembeddedで提供されているレシピの使い方とかについてもまとめておきたいと考えています。

*1:ロスコンパイラが動かないので

*2:yoctoとは直接関係ないかも

*3:でも_0.1のようなバージョンは無くてもビルドできた...

*4:このためyoctoでビルドすると尋常じゃないサイズのディスクの肥やしが生み出される

*5:深くはおっていませんが