Yoctoで生成した環境上で動かすことを目的としたTensorflowLite v2.4.0-rc4のスタンドアロン2MBインストーラとlibedgetpu.so.1のビルド

# 1. はじめに
超ライトな記事を書きます。 ことの発端は下記のやりとりでした。 **`Yocto`** で **`EdgeTPU`** を動かしたいだって！？ カオスさしか感じない問い合わせからスタートしたのでした。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr"><a href="https://twitter.com/PINTO03091?ref_src=twsrc%5Etfw">@PINTO03091</a><br>お世話になります。<br>TPUのチュートリアル（オウムの推論）がうまく動かせない状況がずっと続いており解決できず、もし、PINTOさんの方で何かお分かりになれば少しアドバイスいただけると嬉しいです。。。😭</p>&mdash; かさた@幸せな世界を作る (@funny_man_daa) <a href="https://twitter.com/funny_man_daa/status/1334789043452690433?ref_src=twsrc%5Etfw">December 4, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">現在TPUでオウムの推論チュートリアルを<a href="https://t.co/VJRPFZk15k">https://t.co/VJRPFZk15k</a>(aarch64)上で動かそうとしているのですが、Yoctoで生成したlinux OSでapt-getが使えない環境なので、<br>他のlinux環境にて入手したedgetpuファイル（swig/edgetpu_cpp_wrapper.pyが含まれているファイル）を直接移植して、</p>&mdash; かさた@幸せな世界を作る (@funny_man_daa) <a href="https://twitter.com/funny_man_daa/status/1334789150109650944?ref_src=twsrc%5Etfw">December 4, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">パスなどを合わせてparrotチュートリアルが動くようになりましたが、推論速度が280ms/枚程度であり、実際にTPUが使われていない状況かと思います。<br><br>しかしTPUを抜くと<a href="https://t.co/Ga1hB4KUZn">https://t.co/Ga1hB4KUZn</a>がないというエラーで動かなく、TPUを挿すことはアプリを動作させる条件となっているようなのです。</p>&mdash; かさた@幸せな世界を作る (@funny_man_daa) <a href="https://twitter.com/funny_man_daa/status/1334789250378727429?ref_src=twsrc%5Etfw">December 4, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">ls /sys/bus/usb/devices/で見るとTPUを挿すことでデバイスファイルもできています。<br><br>つまり「オウムの推論プログラムで、TPUを挿してもCPU推論しかできないが、TPUを挿していないとCPU推論も動かせない」状況となります。何か思い当たる原因や解決策などございませんでしょうか？😭</p>&mdash; かさた@幸せな世界を作る (@funny_man_daa) <a href="https://twitter.com/funny_man_daa/status/1334789378703441922?ref_src=twsrc%5Etfw">December 4, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

Yoctoで作った環境ですので制限がとても厳しく、 **`apt`** コマンドすら使えないなど、とても苦労されているようでした。 で、やりとりを続けていくと、下記のコマンドで表示されるライブラリのバージョンと、EdgeTPUの公式が配布しているライブラリのバージョンがアンマッチであることが分かりました。

- お使いの環境のライブラリのバージョン

```console:環境のライブラリのバージョンチェック_サンプル
$ ldd --version

ldd (GNU libc) 2.27
Copyright (C) 2018 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Written by Roland McGrath and Ulrich Drepper
```
- 公式サイトの手順に従ってインストールした場合の libedgetpu.so.1 が要求するライブラリのバージョン **`GLIBC 2.28`**

![Eoov2UiVgAU15Fl.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/194769/565584d5-f716-8ff7-6fda-155434ba16a0.png)

ということで、ライブラリのバージョンが一致しないなら自力でビルドして合わせてしまえばいいじゃん、とすぐに考えてしまうのがビルドジャンキーです。

# 2. 手順
利用中の環境のコンパイラのバージョンを使用して全ての依存ライブラリをビルドします。 今回は **`GLIBC 2.27`** でしたので、 **`Ubuntu 18.04`** が同じバージョンのコンパイラを保持していることを知っていました。 じゃあ、 **`Ubuntu 18.04`** 上でビルドしてしまえばいいじゃん。となりました。

ビルドに使用するのは下記のリポジトリです。

1. **[TensorFlow v2.4.0-rc4](https://github.com/tensorflow/tensorflow/tree/v2.4.0-rc4)**
2. **[libedgetpu 2020.12.07時点のmasterブランチ](https://github.com/google-coral/libedgetpu.git)**

## 2-1. TensorFlow Lite v2.4.0-rc4 のWheelインストーラのビルド
下記の通りの手順を踏むだけで１０分弱でビルドできます。 Dockerを使用してクロスコンパイルでビルドしたい環境に使用するOSを **`BASE_IMAGE`** に指定するだけです。 簡単ですね。

```console:TensorFlowLiteのインストーラのビルド
$ cd ~
$ git clone -b v2.4.0-rc4 https://github.com/tensorflow/tensorflow.git
$ cd tensorflow/tensorflow/lite/tools/pip_package
$ make BASE_IMAGE=ubuntu:18.04 PYTHON=python3 TENSORFLOW_TARGET=aarch64 BUILD_DEB=y docker-build
```
**`tensorflow/tensorflow/lite/tools/pip_package/gen/tflite_pip/python3/dist/`** にインストーラが生成されます。
![Screenshot 2020-12-08 00:29:44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/194769/8d982c1b-cf75-af2c-2d1c-bc9c951defb3.png)

## 2-2. libedgetpu.so.1 のビルド
特に難しいことはありませんが、公式のビルドシーケンスを一箇所だけ変更する必要があります。

```console:
$ cd ~
$ git clone https://github.com/google-coral/libedgetpu.git
$ cd libedgetpu
$ nano Makefile

### コレを
DOCKER_IMAGE ?= debian:stretch
↓
### このように修正します
DOCKER_IMAGE ?= ubuntu:18.04
```
レッツ、ビルド！！

```console:
$ DOCKER_CPUS="aarch64" DOCKER_TARGETS=libedgetpu make docker-build
```
５分ほどで終わりました。 **`libedgetpu/out/direct/aarch64/`** あるいは **`libedgetpu/out/throttled/aarch64/`** の配下に EdgeTPU をコントロールするために必要なデリゲート用.soファイルが生成されます。
![Screenshot 2020-12-08 00:34:59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/194769/71ec933f-6090-c179-9e65-28cf51b618b2.png)

で、サポートをご依頼いただいた方へ上記の一式をご提供しました。
<blockquote class="twitter-tweet"><p lang="en" dir="ltr">！！！<br>（throttled） <a href="https://t.co/J7eXXd0nsd">pic.twitter.com/J7eXXd0nsd</a></p>&mdash; かさた@幸せな世界を作る (@funny_man_daa) <a href="https://twitter.com/funny_man_daa/status/1335958839607214083?ref_src=twsrc%5Etfw">December 7, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">！！！<br>（direct、こちらの方が早い） <a href="https://t.co/dNZSprW6ev">pic.twitter.com/dNZSprW6ev</a></p>&mdash; かさた@幸せな世界を作る (@funny_man_daa) <a href="https://twitter.com/funny_man_daa/status/1335959108143337475?ref_src=twsrc%5Etfw">December 7, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">動きました！！！</p>&mdash; かさた@幸せな世界を作る (@funny_man_daa) <a href="https://twitter.com/funny_man_daa/status/1335959145447473152?ref_src=twsrc%5Etfw">December 7, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">PINTOさんのHeadPoseDetectionの方も試してみます！！</p>&mdash; かさた@幸せな世界を作る (@funny_man_daa) <a href="https://twitter.com/funny_man_daa/status/1335959264406323200?ref_src=twsrc%5Etfw">December 7, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

あ、私のお遊びモデルを動かすことが本来の目的だったのですね。。。 いずれにせよ、動作したようで何よりです。 それにしても 3ms/推論 ってめちゃくちゃ速いですね。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">いまビルドした、できたてほやほや Ubuntu 18.04 aarch64 版の tflite_runtimeの.whl です。<a href="https://t.co/OM1gvtD8Wz">https://t.co/OM1gvtD8Wz</a></p>&mdash; Super PINTO (@PINTO03091) <a href="https://twitter.com/PINTO03091/status/1335946678889680899?ref_src=twsrc%5Etfw">December 7, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">併せて GLIBC 2.27 でビルドした <a href="https://t.co/6wjeKQEq7P">https://t.co/6wjeKQEq7P</a>.1 を圧縮して下記に置いてみました。 私は、初心者なので動かしたことがありません。<a href="https://t.co/FIsy38PsuH">https://t.co/FIsy38PsuH</a></p>&mdash; Super PINTO (@PINTO03091) <a href="https://twitter.com/PINTO03091/status/1335953706026561538?ref_src=twsrc%5Etfw">December 7, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

# 3. おわりに
ビルドジャンキーなんで、ビルドだけして楽しんで、作ったバイナリは一切使わないんですよね。 でも、アホみたいにビルドすればどんな環境でもだいたい動くんではないでしょうか？

対応開始序盤で **[@Nextremer_nb_o さん](https://twitter.com/Nextremer_nb_o)** にヘルプを求めてしまいました。 そこから２人がかりで、あーでもないこーでもない、と議論し初めて、ちょっと楽しかったです。

Yocto で EdgeTPU、動くんすね。 ちょっと感動です。

Happy TensorFlow ！！ :laughing: