みつきんのメモ

組み込みエンジニアです。Interface誌で「Yocto Projectではじめる 組み込みLinux開発入門」連載中

yoctoでもRust

はじめに

最近流行りのRust。meta-rustを使えばyocto環境でもRustアプリケーションを使えるようにできる。

meta-rustネタとしてはこちらに先を越されたが、試したブランチがsumo、rockoと古めなのと観点がRust開発者よりなので、本記事ではすこしyocto的に見てみる。

ちなみに筆者はRust初心者未満なのでRustの解説はリンク先の方を参照してください。

ターゲット環境はラズベリーパイ3。

環境構築

いつもの。

ソース取得

ラズベリーパイ環境のビルドのためのレイヤをダウンロードする。

$ mkdir -p rpi-thud/layers
$ cd rpi-thud/layers
$ git clone git://git.yoctoproject.org/poky.git -b thud
$ git clone git://git.yoctoproject.org/meta-raspberrypi -b thud
$ git clone git://git.openembedded.org/meta-openembedded -b thud

rustのパッケージを含んでいるmeta-rustはsumo(2.5)以降ブランチを切っていない。

masterブランチのLAYERSERIES_COMPATを確認すると次のようになっているので、thudwarriorを使用したい場合はmasterブランチを使用することになる。

LAYERSERIES_COMPAT_rust-layer = "rocko sumo thud warrior"

次のコマンドでソースを取得する。

$ git clone https://github.com/meta-rust/meta-rust.git
$ cd ../

環境変数の設定

環境変数の読み込みとビルドディレクトリを作成する。

$ source layers/poky/oe-init-build-env build_rust

コマンド実行後はビルドディレクトリに自動的に移動される。 ここではbuild_rustとしている。

レイヤの追加

ビルド対象にレイヤを追加する。 依存関係があるので追加する順番は変更しないこと。

$ bitbake-layers add-layer ../layers/meta-openembedded/meta-oe
$ bitbake-layers add-layer ../layers/meta-openembedded/meta-python
$ bitbake-layers add-layer ../layers/meta-openembedded/meta-networking
$ bitbake-layers add-layer ../layers/meta-raspberrypi
$ bitbake-layers add-layer ../layers/meta-rust

local.confの修正

MACHINEをラズベリーパイ3にする。

INITはsystemdで。あとは細かい設定。

MACHINE = "raspberrypi3"
DL_DIR ?= "${TOPDIR}/../downloads"

# enable uart
ENABLE_UART = "1"

# systemd
DISTRO_FEATURES_append = " systemd pam"
VIRTUAL-RUNTIME_init_manager = "systemd"
DISTRO_FEATURES_BACKFILL_CONSIDERED = "sysvinit"
VIRTUAL-RUNTIME_initscripts = ""

IMAGE_INSTALL_append = " rust-hello-world"

ビルド

Linuxイメージを生成する。

$ bitbake core-image-base

Rustバージョンの確認

Rustのバージョンを確認。

$ find ./tmp/work -maxdepth 2 -and -type d -and -name 'rust*' | xargs ls
./tmp/work/cortexa7t2hf-neon-vfpv4-poky-linux-gnueabi/rust-hello-world:
git-r0

./tmp/work/x86_64-linux/rust-cross-arm:
1.33.0-r0

./tmp/work/x86_64-linux/rust-llvm-native:
1.33.0-r0

./tmp/work/x86_64-linux/rust-native:
1.33.0-r0

最新のstableが1.34.1みたいなので若干古い?。ここらへんは疎いので。

SDの作成

ddコマンドでマイクロSDにイメージを書き込む

$ sudo dd if=tmp/deploy/images/raspberrypi3/core-image-base-raspberrypi3.rpi-sdimg of=/dev/sdX bs=100M

/dev/sdXはマイクロSDのデバイスなので適宜sdbsdcなどに書き換えること。

ddの代わりにEtcherを使用することもできる。

実行確認

作成したマイクロSDをラズベリーパイ3に挿入し電源をいれ、rust-hello-worldを実行してみる。

# rust-hello-world
Hello, world!

問題なく動作した。

開発環境の確認

yoctoではbitbakeで作成したLinuxイメージ上で動くプログラムを開発するためのクロスコンパイル環境を作成することができる。 これは、作成したLinux上にインストールされているライブラリを使用するために必要な情報が全て含まれている。

基本的にはGCCC/C++向け環境となっているので、Rustの開発環境はどのようになっているか確認する。

まず、次のコマンドでSDKを作成する。

$ bitbake core-image-base -c populate_sdk

tmp/deploy/sdkインストーラスクリプトが作成されるので、次のコマンドを実行しSDKをインストールする。

$ tmp/deploy/sdk/poky-glibc-x86_64-core-image-base-cortexa7t2hf-neon-vfpv4-toolchain-2.6.2.sh

インストール先は自由に設定できるが、デフォルトでは/opt/poky/2.6.2にインストールされる。

SDKを使用できるようにするために環境変数を読み込む。

$ source /opt/poky/2.6.2/environment-setup-cortexa7t2hf-neon-vfpv4-poky-linux-gnueabi

環境変数CCの値が次のようになっていればSDKが使用できる。

$ echo $CC
arm-poky-linux-gnueabi-gcc -march=armv7ve -mthumb -mfpu=neon-vfpv4 -mfloat-abi=hard -mcpu=cortex-a7 --sysroot=/opt/rust/2.6.2/sysroots/cortexa7t2hf-neon-vfpv4-poky-linux-gnueabi

最低でもrustcが入っていなければRust向けの開発環境とは言えないので探してみる。 SDKでインストールされたファイルは/opt/poky/2.6.2/sysroot以下にあるためそこの下をfindする。

$ cd /opt/poky/2.6.2/sysroot
$ sudo find -iname 'rustc'

見つからない。

*rust**cargo*などで検索してもRustの開発に必要なコマンドやファイルが見つからないことがわかる。

まとめ

低レイヤ強くなりたい組込み屋さんのブログで次のように言っている。

どうしてもYoctoでビルドしてdistributionとして配布したい、という状況でなければ、わざわざYoctoでビルドするうまみはなさそうです。

こちらは開発環境の古さなどの観点からの言葉なので若干言いたいポイントは異なるのだろうとも思うが、 Rustでの開発の観点で言えば全面的に同意できる。

ただ、SDKにRustの開発環境が含まれないことからmeta-rustではyoctoで作成したLinuxの上で開発・デバッグを行うことは目的に含まれていない。そのため「Yoctoでの配布目的以外ではうまみがない」のではなく「使えない」で良いと思う。

個人的にyoctoのうまみは一度作った設定済みのLinuxイメージを量産できるところにあると思っている。meta-rustもRustで書かれたアプリケーションをyoctoのイメージに取り込むのがこれを使用する目的であって、この観点ではmeta-rustのスタンスも間違ってはいないし存在意義もあると思っている。

yocto環境でのRustの開発環境を期待しているとハズレ感はあると思う。

異論は認める!

参考