simotin13's message

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

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

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

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

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

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

github.com

以下の手順で、環境構築~追加したレシピ(ライブラリ・実行モジュール)のビルド、イメージ作成までを試して頂けます。
※イメージでは追加した共有ライブラリは /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

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

ディレクトリのファイルについて説明しておきます。

calcディレクト

このフォルダにはライブラリ(libcalc)を呼び出す側(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_

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}

注意すべきポイント

結論ですが、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() {
        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の構成になっています。ここにビルド結果をコピーします。
ただし、/usr/などのルート(/)以下のディレクトリは存在しない状態になっています。

ビルド時の${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の一覧について
https://ja.osdn.net/projects/openzaurus-ja/forums/9476/11329/

qiita.com

qiita.com

qiita.com

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

参考書籍

Cookbook ではChapter 4 Application Development Developing with librariesに共有ライブラリのビルドについて書かれていて参考になりました。
まぁ、書いてある通りに試してもエラーがいっぱい出ましたが...

まとめ

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

感想

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

yoctoはたかだか共有ライブラリ(Shared Object)と実行モジュールをクロスコンパイルしてイメージを作るだけなのにやたらと覚えることが多いです。学習コストがかなり高くついている気がします。
ただ、組み込みLinuxではyoctoは避けて通れなくなってきている感があるので引き続き勉強していきたいです。

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

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

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

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

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

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

Hyper-Vの仮想マシンに"接続"できないときの対処法

タイトルの通りHyper-V仮想マシンに接続できなくなるという謎な現象が起こっていました。
仮想マシンを起動すると確かに起動はして普通に動いてはいるようですが、「接続」を選択しても仮想マシンの画面が表示されないのです。

つまり、仮想マシンのネットワークの設定ができていない状態だと手も足もでないという絶望的な状況です。

色々調べた結果、こちらの記事が参考になりました。

social.technet.microsoft.com

結論として、仮想マシンへの接続画面が表示されない場合は

C:\Windows\System32\vmconnect.exe

を起動すると接続用の画面が表示されます。

Hyper-V仮想マシンへの接続
仮想マシンへの接続ツール
※もちろんHyper-Vを有効化しておく必要があります。

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:気がついたら終わっていたので正確な時間が分かりません...

LinuxからVxWorksへの移植は簡単か?

前回の記事
mcommit.hatenadiary.com

ではどういった言語や開発環境でVxWorksのアプリケーションを開発するのかについて触れましたが、今回はVxWorksC/C++言語プログラミングに関して、ライブラリや移植性といった点でまとめてみたいと思います。

利用できるライブラリについて

VxWorksのライブラリは機能毎に50近いライブラリが提供されています。
VxWorksが提供するライブラリはxxLibのようにUnix系OSではあまり聞きなれない名前がついています。しかし利用するに当たって必要なのはヘッダファイルを適切にインクルードするだけでAPIを呼び出すことができます。gccの -lxxx のようにライブラリを明示的にリンクする必要はありません。

ライブラリ関数について

各ライブラリではC言語の関数として多くのAPIが提供されています。VxWorksではANSI C言語標準ライブラリて規定されている関数群はサポートされています。具体的には

  • printf,fopen,fclose,fprintfなど標準出力やファイル操作に関する関数
  • time,localtime,sleepといった時刻やタイマーに関わる関数
  • malloc,freeといったメモリ操作に関わる関数

などはVxWorksで利用できる関数です。

スレッドの扱い

VxWorksではpthreadLibという文字通りpthreadを扱うためのAPIが提供されています。
pthread_create,pthread_cond_waitといったpthreadを利用するためのAPIが利用できます。
従ってpthredを使っているプログラミングであればそのままVxWorksでも動かすことが可能です。

ネットワークについて

ネットワークについてはどうでしょうか。
ターゲットがインターフェースを実装していることが前提ですが、TCP,UDPを扱ういわゆるソケットプログラミングはUnix系OSと同様に可能です。
サーバとしての機能を実装する場合はlisten,bind,acceptといった関数が利用できますし、クライアント側を実装する場合はconnect,sento,send,recvといった関数が利用できます。

ネットワークプログラミングはLinuxで書いたコードがほぼそのまま流用できるといってよいでしょう。

移植性について

ANSI Cとの互換性やPOSIXへの準拠を踏まえると、UnixLinux向けに書かれたプログラムをVxWorksに移植するのは比較的容易でした。Linuxからの移植ですと一部ライブラリ関数のオプションなどで違いがあり若干の手直しは必要になりますが、概ね流用できると考えてよいでしょう。

移植に関する注意点

移植性が高いといってもUnix,Linuxのプログラムが何もしなくても100%流用できるかというと実はそうではありません。
移植に当たって変更が必要になるであろうポイントや、注意すべきポイントを挙げておきます。

ヘッダファイルのインクルード

VxWorksUnix系OSのプログラムは関数レベルでは高い互換性がありますが、実はヘッダファイル名やヘッダファイルのパスが微妙に異なっていることがあります。移植時はコンパイルエラーが発生するのでAPIのリファレンスを参考にインクルードするファイル名をコツコツと変更していく作業が発生するでしょう。とはいってもファイル名ですのでエディタの一括置換や変換のためのスクリプト等を書くことでそれほど時間をかけずに対応できると考えられます。

モジュールの形式

VxWorksでは、実行モジュールは大きく「カーネルモジュール」と「Real Time Process(RTP)」の2つが存在します。
モジュールのタイプについて前回の記事を参照してください。

5分で理解するVxWorks入門

概要

組み込みソフトウェアの開発ではリアルタイムOS(RTOS)が採用されることが多く、RTOSの例としてiTronVxWorksが挙げられます。しかしながら、VxWorksが具体的にどういったOSなのかあまり世の中に広くは知られていないように思います。この記事では何回かに分けてVxWorkに関して具体的にどういったOSなのかを説明してきたいと思います。

そもそもVxWorksとは?

WindRiver社から販売されているリアルタイムOSです。 航空・宇宙・防衛の分野で広く使われています。NASAの火星探査機でも使用があり信頼性の高いOSとして知られています。
日本国内でも工場向け機器などで採用されています。

ターゲットCPU

リアルタイムOSというとターゲットのCPUはワンチップマイコンのようなローエンドのCPUがイメージされますが、VxWorksではどういったCPUがサポートされているのでしょうか。VxWorksでは

等のアーキテクチャをサポートしており、MMUを搭載したハイエンドモデルのCPUをターゲットとし、SMP構成をサポートしています。RTOSとしてこう言ったハイエンドのCPUをサポートしているOSはあまりありません。他にはQNXというUnix系のOSが組み込みでは利用されることがありますが、知名度でいうとVxWorksの方が知られているかもしれません。

特徴

ハイエンドなCPU向けのOSですが、RTOSですので、リアルタイム性を実現するための機能はサポートされています。タスク(スレッド)単位で優先度を指定でき、セマフォを使ったタスク間の同期・排他なども比較的容易に実現できます。

またファイルシステムやネットワークプロトコルスタックの機能も存在します。これらの機能のAPIは100%ではありませんがPOSIXに準拠したAPIとして提供されているのでUnix/Linuxでのプログラミングになじみのある方には比較的容易にプログラミングができるでしょう。過去にUnix系OSで使用されるオープンソースをいくつかVxWorksに移植して利用したことがありますが、Unix系OSで動作するソースコードからの移植性はかなり高いと感じました。

非常に高機能で便利なOSではありますが、値段はどのくらいなのでしょうか。契約形態によって異なるので、直接具体的な価格を知ることはできませんが、ターゲットボードのサポートを考慮するとそれなりの価格になることは容易に想像できます。

開発環境

VxWorksの開発環境はどのような構成になっているのでしょうか。
WindRiver社からはWindRiverWorkbenchというEclipseベースの統合開発環境が提供されています(有償)。開発に使用する言語としては、アセンブラC言語C++言語での開発が可能です。 workbenchでは開発ツールとしてgccベースのツールチェイン一式を使ってビルドを行います。デバッグgdbを使ったデバッグができ、workbenchのGUI上からデバッグが可能です。

また、ターゲット上でのデバッグだけでなく、ホスト環境上で動作するシミュレータもワークベンチには含まれているので実装後に気軽にデバッグすることが可能です。

近年WindRiverはLLVMベースの開発環境の整備に力を入れており、最新のバージョンでは利用できるプログラミング言語の選択肢も広がっているようです。

参考

VxWorksの概要については、英語になりますがWindRiverから公開されている動画が参考になります。
www.youtube.com

まとめ

今回は簡単にVxWorksについてまとめてみました。次回は今回の記事で書けなかったAPIVxWorksを使った開発に関する話を書いていきたいと思います。