ししかわの二足ロボ研修

M5Stack UnitV2用クロスコンパイル環境の構築:ししかわの二足ロボ研修 Part.5

ししかわの二足ロボ研修
クロスコンパイルの例

ししかわです。

社員研修の一環で二足歩行ロボットを作って、競技会「Humanoid Autonomous Challenge(HAC)」に参加します。

記事一覧

M5Stackの画像認識モジュールM5Stack UnitV2」をM5Stackのユニットとしてではなく単独で使い、ロボットを制御できるようにしよう!というマニアックな計画を進めています。

今回はクロスコンパイル環境の構築です。

クロスコンパイル用のツールチェインをインストールする

クロスコンパイルの例

前回説明したとおり、クロスコンパイルとは、開発用の環境と異なる環境で動くプログラムをコンパイルすることです。組込みLinuxでは多くの場合、CPUの性能やメモリの容量がデスクトップと比べて非力で、自身のプログラムをコンパイルすることが難しいです。そんなときはクロスコンパイルの出番です。

まずは図中の左枠の環境を開発用PC上に整えていきます。なお開発用PCの環境はLinux(Ubuntu20.04)を使っています。

ソースコードを実行可能なバイナリに変換するためにはコンパイラやアセンブラなどのツール群(ツールチェイン)が必要です。クロスコンパイルを行う場合、プログラム実行環境のアーキテクチャに合わせたツールチェインを用意する必要があります。自分でクロスコンパイラをコンパイルすることもできますが、主要なアーキテクチャ向けのツールチェインは大抵aptなどのパッケージリポジトリにあるのでインストールします。

$ sudo apt install gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf

パッケージ名のうちarm-linux-gnueabihfがアーキテクチャを表現する3つ組の文字列で、ターゲットトリプルと呼ばれます。arm-linux-gnueabihfの場合次のようなアーキテクチャになります。

  • ArmアーキテクチャのCPU
  • Linux上で動作する
  • EABI(Embedded Application Binary Interface)というインタフェースを使う
  • Hard-float=浮動小数点演算をハードウェアで行う

Hello Worldをコンパイルする

試しに簡単なプログラムをコンパイルして実行してみましょう。次のC++のソースコードをコンパイルします。標準出力に1行「Hello World!!」と表示するだけのプログラムです。

#include <iostream>

int main() {
  std::cout << "Hello World!!";
}

次のコマンドを実行してコンパイルし、hello-worldという名前のバイナリを生成します。

$ arm-linux-gnueabihf-g++ ./hello-world.cpp -o hello-world

arm-linux-gnueabihf-g++がarm版のコンパイラ(クロスコンパイラ)です。こうして作ったバイナリはターゲット(UnitV2)のアーキテクチャ専用のバイナリとなります。試しに開発用PCの環境で実行しようとしてもExec format errorというエラーになります。

$ ./hello-world 
bash: ./hello-world: cannot execute binary file: Exec format error

fileコマンドを使うとファイルのフォーマットを確認できます。

$ file ./hello-world
./hello-world: ELF 32-bit LSB shared object, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-armhf.so.3, BuildID[sha1]=f9241dad4584b7b02039a8865c3f6b24af0e0ba6, for GNU/Linux 3.2.0, not stripped

先程のターゲットトリプルにも出ていた”ARM, EABI5″という文字列が見えますね。正しくUnitV2向けのバイナリが生成されていることが分かります。

プログラムを転送する(UnitV2でscpが使えない問題に対処)

続いてビルドしたプログラムをUnitV2にscpで転送してみましょう。

$ scp ./hello-world m5stack@unitv2.local:/home/m5stack/
m5stack@unitv2.local's password: 
Couldn't open /dev/null: Permission denied
lost connection

おや?エラーが出て失敗しました。どうやら/dev/nullが開けない様子。

UnitV2で/dev/nullを確認してみると、全ユーザに対する読み書きの権限が与えられていません。このファイルのパーミッションは通常666(全ユーザが読み書き可能)のはずですが、何かの対策なんでしょうか。

unitv2% ls -l /dev/null
crw-rw---- 1 root root 1, 3 Jan 1 00:00 /dev/null
unitv2% echo hoge > /dev/null
zsh: permission denied: /dev/null

暫定的にchmodコマンドで /dev/nullの権限を修正することで対処します。(前回の記事を参考にUnitV2でsudoが使えるようにしておきます)

unitv2% sudo chmod 666 /dev/null
Password: 
unitv2% ls -l /dev/null 
crw-rw-rw- 1 root root 1, 3 Jan 1 00:00 /dev/null

これで転送ができるようになりました。

$ scp ./hello-world m5stack@unitv2.local:/home/m5stack/
m5stack@unitv2.local's password: 
hello-world 100% 8720 3.7MB/s 00:00

UnitV2を再起動するとパーミッションが元に戻ってしまうので、都度↑のコマンドを打つ必要があります。根本原因と解決策が分かったら改めて記事にします。

プログラムを実行する

最後にUnitV2でプログラムを実行します。

unitv2% ./hello-world 
./hello-world: /lib/libstdc++.so.6: no version information available (required by ./hello-world)
./hello-world: /lib/libstdc++.so.6: no version information available (required by ./hello-world)
Hello World!!%

無事に「Hello World!!」の文字が表示されました!

このときno version information availableという警告が出ています。これはビルドした環境のライブラリよりも実行環境のライブラリのバージョンが古い時に出るもののようです。今の所支障無いので無視しています。


以上です。「クロスコンパイルのツールチェインを使ってバイナリをビルドする」「ターゲットデバイスに転送する」「実行する」という基本的な流れを行いました。

今回使ったarm向けのツールチェインや、UnitV2の他の依存ライブラリを含む開発環境一式をGitHubで公開中です。Docker一発で開発環境が整って便利ですのでぜひ使ってみてください。

GitHub - meganetaaan/UnitV2Framework
Contribute to meganetaaan/UnitV2Framework development by creating an account on GitHub.
タイトルとURLをコピーしました