macOSにおけるtensorflow 2.0 C++でビルド後にXcodeで使えるようにする

## 事のきっかけ
macOSでもやりたくなった。
(Visual Studio 2017 build toolがchocoで取れるのを知って、今更ながらWindowsでのビルドが成功したのは内緒。)

## 更新履歴

 - 2019/10/16:macOS Catalinaベースに変更


## 事前準備
- Homebrewのインストール
  
1.`/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"`を実行し、インストール。

- vimのインストール(vim派以外の方はお好きなものを)

1.`brew install vim`を実行し、インストール。

- pyenvのインストール

1.`brew install pyenv`を実行し、インストール。
2.`vim ~/.bash_profile`を実行し、以下全てを追記する。

```
PYENV_ROOT=/usr/local/var/pyenv
if which pyenv > /dev/null; then eval "$(pyenv init -)"; fi
```

3.`source ~/.bash_profile`を実行し、変更点を反映させる。

- python 3.7.4のインストール

1.`pyenv install 3.7.4`を実行し、インストール。
2.`pyenv global 3.7.4`を実行し、メインを3.7.4にする。
3.`python -V`を実行し、バージョンが一致しているか確認する。

- virtualenvのインストール

1.`pip install virtualenv`を実行し、インストール。

- tf2.0用の仮想環境作成

1.`mkdir virtualEnv`で仮想環境作成専用のフォルダ作成。(任意)
2.`cd virtualEnv`で移動。
3.`virtualenv tf2.0`を実行し、仮想環境を作成。
4.`source tf2.0/bin/activate`を実行し、仮想環境を起動させる。

## ビルド準備

- ビルド用のpythonにパッケージをインストール

1.以下のコマンドを1行ずつ実行していく。

```
pip install -U pip six numpy wheel setuptools mock

pip install -U keras_applications==1.0.6 --no-deps

pip install -U keras_preprocessing==1.0.5 --no-deps
```

- ビルドツールbazelのインストール

1.https://github.com/bazelbuild/bazel/releases/tag/0.26.1
にアクセスし、`bazel-0.26.1-installer-darwin-x86_64.sh` をダウンロード。
2.`chmod +x bazel-0.26.1-installer-darwin-x86_64.sh`で実行可能にする。
3.`sudo ./bazel-0.26.1-installer-darwin-x86_64.sh --user`を実行し、インストール。
4.`vim ~/.bash_profile`を実行し、以下の一行を追記する。

```
export PATH="$PATH:$HOME/bin"
```
5.`source .bash_profile `を実行し、設定を反映。
6.`bazel version`で確認し、0.26.1がインストールされているか確認する。

- Xcode事前設定

1.AppStoreからXcodeをインストール。
2.以下のコマンドを1行ずつ実行する。

```
sudo xcodebuild -license accept

sudo xcode-select -s /Applications/Xcode.app/Contents/Developer

sudo xcodebuild -license
```

- ビルド前の下ごしらえ

1.`brew install autoconf automake libtool cmake`を実行し、必要なものを揃える。

## ビルド

- tensorflowをビルド

1.`git clone https://github.com/tensorflow/tensorflow.git`を実行し、取得する。
2.`cd tensorflow`を実行し、移動。
3.`git checkout r2.0`でTensorflow2.0系を作成。
4.`./configure`を実行し、質問に答えていく。基本的にYes or No形式の質問は全てNOを選択し、[Default ...]といったYes or Noとは違う形式の質問は、基本的にエンターキーを押す。
5.`sudo bazel build  --verbose_failures --config=v2 //tensorflow:libtensorflow_cc.so`を実行する。(めちゃ時間かかる。)
6.`sudo bazel build --verbose_failures --config=v2 //tensorflow:libtensorflow_framework.so`を実行する。(割とすぐ終わる。)

- ビルド後

1.`./tensorflow/contrib/makefile/download_dependencies.sh`を実行する。
※ここで、プロキシ設定を通しておかないとうまくいかない。プロキシは、
`export ALL_PROXY=hogehoge`

- protobufをシステムにインストール

1.下記のコマンドを1行ずつ実行していく。

```
cd tensorflow/contrib/makefile/downloads/protobuf/

brew install automake libtool

./autogen.sh

./configure

make

make check

sudo make install
```
- 上記のフォルダがない場合

下記のコマンドを順に入力していく。

```
git clone https://github.com/protocolbuffers/protobuf.git

cd protobuf

git checkout xxx(tensorflow1.14は、3.7.x , tensorflow2.0は、多分3.8.xだったはず。)
git submodule update --init --recursive

./autogen.sh

./configure

make

make check

sudo make install
```

## Xcodeで設定
- Xcodeに導入

1.新規プロジェクトで、macOS->Command Line Toolを選択してプロジェクトを作成する。
2.以下のようにフォルダを作成する。

```
(新規フォルダ作成前)
[プロジェクトフォルダ]
|
|- [main.cppの入っているフォルダ]
|
|- [拡張子xcodeprjのファイル]

(新規フォルダ作成後)
[プロジェクトフォルダ]
|
|- [main.cppの入っているフォルダ]
|            |
|            |-[include](new!!)
|            |-[lib](new!!)
|- [拡張子xcodeprjのファイル]
```

- ライブラリやヘッダファイル等々を揃える

1.以下に記載してあるようにコピー元からコピー先へコピーする。

```
cp  tensorflow/bazel-bin/tensorflow/libtensorflow_cc.so [プロジェクトフォルダ]/.../lib/

cp  tensorflow/bazel-bin/tensorflow/libtensorflow_framework.so [プロジェクトフォルダ]/.../lib/

cp  /usr/local/lib/libprotobuf.a [プロジェクトフォルダ]/.../lib/

cp -r tensorflow/bazel-genfiles/* [プロジェクトフォルダ]/.../include

cp -r tensorflow/tensorflow/cc [プロジェクトフォルダ]/.../include/tensorflow

cp -r tensorflow/tensorflow/core [プロジェクトフォルダ]/.../include/tensorflow

cp -r /usr/local/include/google/* [プロジェクトフォルダ]/.../include

cp -r tensorflow/tensorflow/contrib/makefile/downloads/absl/absl [プロジェクトフォルダ]/.../include

cp -r tensorflow/third_party [プロジェクトフォルダ]/.../include

cp -r tensorflow/bazel-tensorflow/external/eigen_archive/unsupported [プロジェクトフォルダ]/.../include

cp -r tensorflow/bazel-tensorflow/external/eigen_archive/Eigen [プロジェクトフォルダ]/.../include

```

- Xcodeの設定

1.Xcodeの左端にあるプロジェクト名(青いアイコンがある)をクリックし、TARGETSの方にあるものをクリックし、Build Settings->ALL,Combinedにする。

2. Search Pathsがあるところまでスクロールし、以下のように設定する。

```
Header Search Paths => $(PROJECT_DIR)/include
Library Search Paths =>$(PROJECT_DIR)/lib
```

3.先ほどBuild Settingsをクリックした場所の近くにある、Build Phasesをクリックし、Link Binary With Librariesを開く。そして、libtensorflow_cc.soとlibtensorflow_framework.soを追加する。以上で終了。

## 感想
macOSは、UNIXベースということもあって非常に楽に導入できた。

Catalinaで語リーナ。）
# 参考資料
「How to use your C++ muscle using TensorFlow 2.0 and XCode (without using Bazel builds)」
https://itnext.io/how-to-use-your-c-muscle-using-tensorflow-2-0-and-xcode-without-using-bazel-builds-9dc82d5e7f80
「protobuf/src at master」
https://github.com/protocolbuffers/protobuf/tree/master/src