衝撃のわからなさ

わかってません

2024/02/28日報

mimic-cross実装

Pythonのバージョン指定を柔軟に

versionハードコードをやめた。パッチが当たる限りは同じ処理が使い回せる。

Remove version hardcoding in python.postInstall

サポートバージョンを増やす

正規表現でかけるようにしようかと考えたが、コードが複雑になり実行時コストも増えるので 力技でgcc-9, gcc-10, gcc-11...みたいな設定を書いておくことで増やした。

Support more versioned packages

ubuntu20.04対応

localでテスト流れるところは確認した。テストまわりは期待値のハードコード部分が多いので今後要対処。

2024/02/27日報

coderabbit導入

した。便利な気配がしている。
localでも随時reviewして欲しい。

mimic-cross実装

設定をconfigurableにする

deno compileとdynamic importの両立はとてもつらいことがわかったので、 変更後にrecompileしてもらう方針にした。

How to customize mimic-cross for your environment

Make configurable by /etc/mimic-cross/custom

2024/02/25日報

deno compileするとdynamic importできない

最新issueは多分これ
deno compile output can't dynamically import files that were not present at compilation time · Issue #18327 · denoland/deno · GitHub

issueにある通り、下記を使うのが良さそう。

GitHub - ayoreis/import: A dynamic imports polyfill for Deno Deploy and compiled executables

localにあるファイルをdynamic importする場合、 file://で始めるかimport.meta.url相対パスで始めないとdeno.landなどに向いてしまったので注意。

またimport.meta.urlはビルド時のパスになる。
さらに、compileしたパスと実行時のcwdが揃っていないと絶対パス指定はうまく動かない。
これはdeno compileされたものかどうかの判定条件に起因している。

force optionをつけると解決するのでdeno compileして使う前提の場合は 脳死でつけたほうがいい。

commit: dynamic-import.deno

mimic-cross実装

denoがarm64向けバイナリを公式にくばるようになったので、downloadの向き先を変えた

Switch aarch64 deno to official
Fix deno version

2.1.0リリース

gccの=native対応とdeno compile使用が入った

Release 2.1.0

2024/02/24日報

gitコマンドをgithub actionsのuse: dockerコンテナ内で呼ぶ方法

git config safe.directory inside docker containers · Issue #2033 · actions/runner · GitHub
これに引っかかった。

zigやめてrustにするか検討

gccのjump処理を同じようにrustで書いてみて比較した。
commit: mimic-arg.rust

バイナリサイズ比較

RUST 2.1M vs zig 17K

rustはoptimize z, ltoなど組み合わせて2Mほど減った。 zigは雑にRelaseSmallにするだけで一気に減る。

deno_bindgen

なにか処理がdenoから呼べたら便利かなと思ってみたが、文字列の配列などを渡す方法がわからず一旦見送った。 かなりドキュメントが少ない。

結論

とりあえずバイナリサイズが小さく、 ポータビリティもあって助かるのでzigのままにしておく。

mimic-cross実装

execvpでgccを呼ぶようにするとfind_pacakge(MPI)でエラー

  • cmake --trace-expandで変数のdiff取って睨みつける
  • FindMPIが不正にTrueになっていそう

あれ戻り値伝搬がおかしいのでは…?

常に0になってしまっていた。直した。
Fix gcc return value

Lint on CI

サボっていたのでやった。
actionsで書いても結局localで実行するときに困るので、dockerに固めた。 が、それにより上述の問題に引っかかった。git ls-files使わない実装にした。

Run lint on CI by impactaky

PFNから数えて計4年4ヶ月勤めたPreferred Roboticsを退職して、転職活動しながらクロスコンパイル環境を作ったりしています

はじめに

退職しました。
カチャカというロボットに主に組み込みまわりで関わっていて、発売されて満足しました。
量産ロボットに携わるという夢が1つも叶いました。

2ヶ月の有休期間中に、この間に作成したmimic-crossというクロスコンパイル用のDocker imageを 整備していろいろな人に使ってもらえるようにできればと考えています。
この記事ではなぜこのツールを開発した背景を振り返りながら、課題と共に紹介します。

背景

PFN入社からしてすぐ、後にカチャカとなるプロジェクトで ARM CPUボードへのインテグが始まろうとしており、 全体SlackでYoctoを知っている人がいないかという呼びかけがされてました。

私自身はPFVMという自社のNN実行フレームワークを作成するチームに配属されましたが、 ロボットのチームがこのフレームワークを使う橋渡しのようなことをやってもらいたいと言われていました。
記念受験のつもりで受けたPFNに運良く採用してもらえたのは、こういった仕事があったおかげだと思います。 本当に幸運でした。

前職のルネサスエレクトロニクスでYoctoを利用したLinux BSPまわりの業務経験があった私はもちろんすぐに手をあげ、 最終的にはロボットとエフォート50/50で働いていました。

Yocto vs Ubuntu

今組み込みまわりのディストリビューションを選定するとき、主にこれらの系統の2つを比較することになるかと思います。 私の認識ではありますが、簡単にそれぞれの特徴をまとめてみます。

Yocto

  • 特定のHWや製品向けにカスタムがしやすく、組み込みLinuxのベースとして広く使われている
  • 強力なライセンス管理機能があり、ライセンスリスト作成や特定条件を満たさないライセンスの除外などが行いやすい
  • ロスコンパイル向けのレシピを書く仕組みがある
  • ビルド済みパッケージの配布はなく、新規パッケージのビルドに時間がかかることがある
  • 対応していないソフトウェアは新規にbitbake形式のレシピを書く必要がある

Ubuntu

  • カスタムしやすくはない。その代わりHWが違っても環境が揃いやすい
  • パッケージにライセンスが同梱されてはいるが、特に管理機能はない
  • ロスコンパイルを書きやすくする仕組みはない、クロスコンパイルツールは提供されてはいる
  • ビルド済みパッケージが配布されており、非組み込み環境の資産を活用し易い
  • 多くのソフトウェアやライブラリが標準環境として利用しており、独自の手順が必要になりにくい

ディストリビューションを作る側に優しいのはYocto。
アプリケーション開発の観点からは普段のマシンの開発と同じようにUbuntuを使いたいというのが多いのではないでしょうか。

多くのソフトウェアやライブラリはUbuntuをサポート環境として提供していますが、Yoctoはサポートしていません。
カチャカには様々なソフトウェアスタックが搭載されています。
組み込み向けに開発されていない多くのソフトウェアをCPUにデプロイする必要がありました。

またAIは発展速度が早く、新しく出てくるものをすぐに試して開発サイクルを回す必要があります。
新しく出てきたものを手数少なく、エッジデバイスで動かす必要がありました。

ロスコンパイルの問題を解決してUbuntuを採用できれば最高なのだけれど…どうしようというのが検討段階の問題でした。

ロスコンパイルの問題

ロスコンパイル簡単じゃないという話

コンパイラ変えたりarchitecture指定とかすればいいでしょ?と思うかもしれません。 そもそも工数が発生してしまうのは開発サイクルからは好ましくありあますせん。 クロスコンパイルの手順は言語やビルドツールそれぞれで違い、1つ1つ対処していかなくては行けないのです。 依存パッケージを取得するのだってそのままapt-getするのではすみません。

さらに、PythonパッケージがC/C++のビルドを含む場合などはそもそもパッチを当てないとクロスコンパイルできない可能性があります。
開発開始当時はまだnumpyやgrpcなどもaarch64向けにはビルド済みパッケージが提供されておらず、 ロボットという多くのものを扱うプロダクトでこれらのものを1つ1つ確認して対処するのは困難でした。

また自身の開発チームのプロダクトもC++をビルドしてPython Wheelを作成しており対応が必要でした。

こういったケースで以下のような対応策を取られる事が多いかと思います。

ネイティブコンパイル

プロジェクトでもまずネイティブコンパイルが試されてました。
しかしメモリが4GBしかないボードではメモリ不足でビルドを回すことができませんでした。
また(当時は)CI環境でARMインスタンスを使うことができず、Apple SiliconのPCや性能の高いJetsonなどもなく、 利用することができない状態でした。

これは今日の開発においてもクラウドサービスがARM環境を選択できない、あってもARM + CUDAのテストはできない。 開発PCはx86_64マシンであるなどの問題があるかと思います。

QEMUを利用したクロスコンパイル

その他の解決方法として検索するとよく出てくるのはQEMUを使うという方法です。
この方法は遅いという問題があります。 呼び出される命令によりまちまちですが、私はQEMUにした場合およそ10倍ぐらいになるかなと普段見積もっています。

QEMUを使ってビルドはできてたのですが、プロジェクト初期の段階ですでにフルビルドが走ると2日かかっており、 QEMUのように使えて早い環境があれば…!となってました。

mimic-crossを作った

ということで作られたのがこちらです。
(業務時間外で作ってOSSと言い張ってきたので手元にある。)

github.com

これは単純にbinutilsをビルドしている例です。
このようにbaseimageを付け替えることで--platform=linux/arm64つけてクロスコンパイルした場合の時間が、 ubuntu:22.04指定の 434.8sec → 34.6sec に短縮できています。

同じ Dockerfileでnativeビルドもできるため、テストやシミュレータなどはnativeで実行するなどの使い分けもできます。

# FROM ubuntu:22.04
FROM --platform=${BUILDPLATFORM} impactaky/mc-ubuntu22.04-${TARGETARCH}:2.0.0

RUN apt-get update && \
    apt-get install -y --no-install-recommends \
        wget ca-certificates \
        binutils gcc make libc6-dev && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists

RUN wget -q https://ftp.gnu.org/gnu/binutils/binutils-2.36.tar.gz \
    && tar xf ./binutils-2.36.tar.gz
WORKDIR /binutils-2.36
RUN ./configure
RUN make -j "$(nproc)"

良いと思ったらsponsorください(直球)

mimic-crossは3年以上前から存在していてカチャカのソフトウェアビルドに使っていたのですが、 すべてbashで書いてしまいメンテが絶望的だったので今年の年末あたりから書き直し始め、 有給休暇の力で一旦旧実装程度まで実装ができました。

まだまだいろいろなコーナーケースがあると思うのですが、イメージを付け替えるだけで試せるので、 ぜひ試して問題など教えていただけると嬉しいです。

対応したい機能はまだまだ大量にあり、今後も継続して開発するつもりです。
3月末までは有給なので特に頑張ります。

このプロジェクトがクロスコンパイルできなくて困っているなどありましたら、 教えていただけると嬉しいです!

今後について

決まってません! このクロスコンパイル環境の開発は継続していきたいと考えており、このような環境の需要を抱えている会社を御存じでしたら、教えていただけると大変ありがたいです。

組み込みソフトウェアというのは多くの会社において、プロダクトを作成するのに必要な1要素であり、 プロジェクトの競争力をもたらすものではなく、枯れた要素を使うべき領域だとされると思います。
しかしながらこの記事で述べたように、AIなどの開発が早く新しい技術と枯れた部分の界面になる領域でもあります。
mimic-crossのようなツールを作成することで、このような界面への課題に取り組むことができればいいなと考えています。

長い記事を最後まで呼んでいただきありがとうございました!

2024/02/14日報

github actionsのドキュメント読む

今まで完全に雰囲気コピペして使ってたのでちゃんと一回ドキュメントを呼んだ。

メモ * 一番の本質が奥まったところにある ワークフロー構文 * ファイルと対応するのがworkflow * コンテナ一個と対応するのはjob * 1job 6時間まで * actions -> codeQLで可視化できる * GitHub Marketplace でアクション検索できる * ジョブ間でデータを共有する * 組み込み言語みたいなやつ * * コンテキスト * 変数 * actions -> 新しいワークフローでtemplate選べる * ワークフローのトリガー

後で見たい * Docker コンテナーのアクションを作成する - GitHub Docs * GitHub Actions でのシークレットの使用 - GitHub Docs

mimic-cross実装

Releaseに向けた作業

commit: Update example commit: Add script dir commit: Update README commit: Lint