ラズベリーパイ用のクロスビルド環境をdockerコンテナで用意する

お仕事でよくラズパイを使うことがあるのですが、開発用のPCに比べるとCPUの性能はそこまで高くないので、 ネイティブ環境でソフトウェアのビルドをすると結構な時間がかかっちゃいます。 仕事ではかなりまえからdockerコンテナでのクロスビルド環境を整えてたのですが、せっかくなので共有しておこうと思います。

いくつかオープンソースのソフトウェアをビルドするスクリプトも含めてます。

# サマリ

このリポジトリのDockerfileをビルドすれば、すぐさまクロス環境ができあがります👌

できること

  • ラズパイ用のバイナリをビルドできる
    gccを直接実行したり、cmakeやautotools系のビルドシステムでもクロスビルドできます
  • ラズパイのシステムをqemu(仮想環境)で実行できる
    ビルドしたバイナリをそのまま仮想環境で実行できますし、仮想環境内でapt実行してラズパイ用のソフトウェアをインストールしたりできます。
  • いくつかのサンプルプログラムやオープンソースソフトウェアをお試しビルドできる
    これはクロスビルドを試すために用意したものです。 Python, libmbedなど

補足情報

  • 生成するバイナリはRaspberry Pi OS (bullseye)の32bit用のみです。
    私がほかの環境を使うことがほぼないため、その他のクロス環境は用意できていません
  • クロスコンパイラはubuntu:22.04(x86_64)コンテナ上に構築されています。 そのためx86_64環境でdockerを実行してください。

# 使い方

  1. イメージの作成
    リポジトリをクローンしてきて、docker compose buildしましょう。

    $ git clone https://xxxx
    $ cd raspi-cross-toolchain-container
    $ docker compose build
    
  2. コンテナ実行
    いつも通り、compose up -dcompose execです。

    $ docker compose up -d
    $ docker compose exec raspi-cross /bin/bash
    root@.....:/opt#
    

    コンテナを停止するときは、コンテナのシェルを抜けて、docker compose downでOKです。

  3. サンプルプログラムのビルドと実行
    コンテナに入れば、helloworldのサンプルプログラムが用意されています。 makeすればラズパイ用の実行バイナリが生成されます。

    $ docker compose exec raspi-cross /bin/bash
    root@.....:/opt# cd build-test/sample_hello/
    root@.....:/opt/build-test/sample_hello# make
      :
    root@.....:/opt/build-test/sample_hello# ls
    Makefile  hello  hello.c  hello.o
    
    root@.....:/opt/build-test/sample_hello# file hello
    hello: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-armhf.so.3, for GNU/Linux 3.2.0, not stripped
    

    あとは生成された実行ファイルを、rsync等でラズパイにコピーすればそこの環境で実行できるはずです。

# CMakeや./configureなどのautotoolsを使ったビルドシステムの場合

多くのソフトウェアはいろいろなライブラリに依存していると思います。
そういうソフトウェアをビルドするときは、ラズパイ上のライブラリやヘッダファイルを参照できるようにする必要があるのですが、 このDockerイメージではラズパイのルートファイルシステムを丸ごと/sysrootに配置しています。(ビルド時にダウンロードして展開)

Makefileだけでビルドするようなソフトウェアや、直接gccやg++を叩くような場合は、上記のmakeファイル内のオプションを参考にすればいいと思います。

CMakeやautotoolsの場合はちょっと設定が必要です。

# CMake

ツールチェインファイルを用意しています。
cmakeのオプションに-DCMAKE_TOOLCHAIN_FILE=/opt/cross-env.cmakeを追加してビルドしてください。

cd some_project
mkdir build
cd build
cmake .. -DCMAKE_TOOLCHAIN_FILE=/opt/cross-env.cmake
make 
make install DESTDIR=/opt/sysroot

./build-test/build-mbed.shでは、実際にCMakeをビルドシステムとして使っているオープンソースのlibmbedをビルドする手順が記載されていますので参考になるかもしれません。

# autotools

こちらも環境変数を設定するスクリプト/opt/cross-env.shを用意しています。 自動で読み込まれるようにコンテナ内の.bashrcに追記していますので、あとは環境変数を使うだけです。

cd some_project
./configure $CONFIGURE_OPTIONS
make
make install DESTDIR=/opt/sysroot

./build-test/build-cpython.shでは、実際にautotoolsをビルドシステムとして使っているcpythonをビルドする手順が記載されていますので参考になるかもしれません。

# ほかにも

結構いろいろなことができます。いずれまた記事を書こうと思います。

  • sysroot内でapt実行
  • qemu内でgdbを使ってデバッグ

# 参考サイト