【修行】1CPU・容量制限VMでTensorFlow 2.4.0をソースビルドして.whl生成するまでの全記録

# 【修行】1CPU・容量制限VMでTensorFlow 2.4.0をソースビルドして.whl生成するまでの全記録

---

## 📌 はじめに
- よく昔の環境で作られたコードをcloneしたくなると思います。pipでは落とせないバージョンのライブラリが必要になりがちですよね。今回はそんな話です。
- 環境制限がある中で TensorFlow をソースからビルドする必要がありました。
- 特に以下のような条件でのチャレンジでした：
  - 仮想マシン（VM）
  - 1CPU・低メモリ（5GB）
  - `/`パーティションの容量が約36GB、空きは約8GB前後
  - TensorFlow 2.4.0 + FMA命令無効化でカスタムビルド

---

## 🛠 ビルドの目的と背景

- 開発対象のCPUがFMA命令に未対応 → pip版TensorFlowだと起動時に `Illegal instruction` が出る
- 公式ビルドでは `-mfma` などの最適化オプションが有効になっている
- そのため、**自分でFMA命令の最適化を無効化したTensorFlowをビルド**する必要があった
- GPU使わない方針です。

---

## 💻 環境構成

| 項目 | 内容 |
|------|------|
| OS | Ubuntu 24.04 (VM上) |
| CPU | 1 core (VirtualBox) |
| メモリ | 5GB |
| ディスク容量 | `/`に36GB（うち8GB空き） + `/mnt/VmShare`に222GB（共用マウント） |
| Python | Miniconda環境でPython 3.8（`score_sde_env`） |
| Bazel | v3.7.2（TensorFlow 2.4.0に合わせた） |

---

##  ビルドの流れ（概要）

1. TensorFlow公式リポジトリ（r2.4）をclone
2. `./configure` でFMAやXLAの有無などを指定
3. Bazelによるビルドを開始
4. キャッシュ・メモリ・tmpの最適化
5. Python依存 (`keras_preprocessing`) エラー対応
6. `.whl`ファイルを生成

---

## ポイント解説

### 1. FMA命令の無効化

- `CC_OPT_FLAGS="-march=native -Wno-sign-compare"` のような設定を `./configure` 時に与える
- または `--copt=-mfma` を入れないよう注意

### 2. `/`容量制限に対する対策

- `~/.cache/bazel` が肥大化するので `/mnt/VmShare` に逃がす方法を検討
- `TMPDIR` や `TEST_TMPDIR` を `/mnt/VmShare/tmp` に指定し一時ファイルを回避

```bash
export TMPDIR=/mnt/VmShare/tmp
export TEST_TMPDIR=/mnt/VmShare/tmp
```

### 3. Python依存の問題

```text
ModuleNotFoundError: No module named 'keras_preprocessing'
```
→ `pip install keras_preprocessing` で解決

### 4. Bazel再開とキャッシュの扱い

- 再起動後も `~/.cache/bazel` が残っていれば再開可能
- `bazel build //tensorflow/tools/pip_package:build_pip_package` を何度も繰り返す
### 5. コンパイラのバージョン、pythonのバージョン
- bazelでビルド中に呼ばれるコンパイラ(gcc, g++)、pythonのバージョンを適切にしましょう。
- gcc: gcc-9
- g++: g++-9
- python: 3.8.20
- pipも20.3.4ぐらいまで落としておいた方が良い(意外と重要らしい)
### 5. 出力先のパーミッション問題

```text
mkdir: cannot create directory ‘/mnt/VmShare’: Permission denied
```
→ 一旦 `~/tf_pkg` に出力し、あとから共有領域へ移動

```bash
./bazel-bin/tensorflow/tools/pip_package/build_pip_package ~/tf_pkg
```

---

## 🎉 ビルド成功！

```bash
ls ~/tf_pkg/
tensorflow-2.4.0-cp38-cp38-linux_x86_64.whl
```

→ `.whl` ができたら、あとはお好きな環境に `pip install` するだけ！

---

##  学んだこと

- ビルドシステムは「ファイルの依存だけでなく、ツールや中間生成物の構造も扱っている」
- Bazelの内部構造（外部リポジトリ取得・キャッシュ・DAGベースの依存評価）
- リソース制約下での戦略的な判断（何を捨てて、何を通すか）
- 反省として、最初からオブジェクトファイルの出力先を以下に指定しておけば楽ができた。
```bash
export TEST_TMPDIR=/mnt/VmShare/tmp
```
- bazelはSIGINTで途中で止めても、再開時途中からビルドしてくれます。有効活用できます。
---

## おまけ

- TensorFlow公式ビルド手順：https://www.tensorflow.org/install/source
- Bazelの公式ガイド：https://bazel.build/
- FMA・AVX命令とは？：https://en.wikipedia.org/wiki/FMA_instruction_set
---

##  最後に

今回のやり方では`/`パーティションに30GBほど余裕があると嬉しいですね。
一回のビルドで50時間程かかりました。
この経験が、誰かの「ビルドこわい…」を「やってみようかな」に変えるきっかけになれば幸いです。
> TensorFlowのビルドは、C++だけでなくPython・Protobuf・生成スクリプト・依存管理ツールが密接に絡み合っています。
> Bazelはその複雑な構造を、Skyframeによるグラフ評価エンジンで一元管理しているそうです。
> 今回の経験で、それが“使うだけのツール”から“構造を設計する技術”に見えてきました。

---
##  References

- [TensorFlow公式：ソースビルドガイド](https://www.tensorflow.org/install/source)
- [Bazel公式：Concepts](https://bazel.build/concepts) ← DAGやSkyframeの考え方が重要
- [Bazel Deep Dive Slides](https://docs.bazel.build/versions/main/skylark/concepts.html) ← 評価エンジンのしくみを知りたい方向け
- [Understanding Bazel’s Caching Mechanism](https://docs.bazel.build/versions/main/output_directories.html)