Docker (ubuntu 18.04) + Bazel + grpc + c++20 + boost をビルドする方法

#前書き
今回の記事は[OPTIMIND x Acompany Advent Calendar 2021](https://qiita.com/advent-calendar/2021/optimind_acompany) 21日目の記事です。

---

#経緯

Q：docker(ubuntu18.04)bazelを使って、gRPCとboostを使用したプログラムをc++20でビルドしたいです。
あまり記事がない物全てを掛け合わせると何が起こりますか？

---
A：<br>**記事が一つもなくなる<br>というか同じページしか出なくなるし基本全部それぞれのチュートリアル**

---

c++20の記事はある、Bazelもある、grpcもある、でも合わせた物が一つもない！

それぞれ別なのだから関係ないと思われるかもしれないが、関係多ありである。

それの対処に知らないツールやソースコード、issueを調べて行くしか道がなく、
非常に、とっても、すこぶる疲れる作業になったが、
これらのツールを使ってc++20を使いたい！
その一心で頑張ることにした。





---
#構築環境
Docker
OS : ubuntu 18.04
ビルドツール : Bazel 3.4.1
コンパイラ : g++-10
ライブラリ : grpc version 1.42.0,  boost version 1.77.0
        
---

##Dockerfile
```dockerfile:Dockerfile
FROM ubuntu:18.04
#最低限の部分をインストール

SHELL ["/bin/bash", "-c"]
RUN apt-get update && apt-get install -y \
    git wget clang build-essential libssl-dev \
    software-properties-common cmake
#bazel install
RUN echo "deb [arch=amd64] https://storage.googleapis.com/bazel-apt stable jdk1.8" | tee /etc/apt/sources.list.d/bazel.list && \
    wget https://bazel.build/bazel-release.pub.gpg && \
    apt-key add bazel-release.pub.gpg && \
    apt-get update && \
    apt-get -y install bazel-3.4.1 && \
    ln -s /usr/bin/bazel-3.4.1 /usr/bin/bazel
#g++10 install
RUN add-apt-repository ppa:ubuntu-toolchain-r/test &&\
    apt install -y gcc-10 g++-10

RUN update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-10 10\
    && update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-10 10
#boost install
#boostの使いたいライブラリのバージョン次第ではc++20でバグが発生するので注意！！
ARG boost_version=1.77.0
ARG boost_file=boost_1_77_0
RUN pushd /tmp \
    && wget https://boostorg.jfrog.io/artifactory/main/release/1.77.0/source/${boost_file}.tar.gz --no-check-certificate \
    && tar xfz ${boost_file}.tar.gz \
    && rm ${boost_file}.tar.gz \
    && pushd ${boost_file} \
    && ./bootstrap.sh \
    && ./b2 --without-python --prefix=/usr -j 4 link=shared runtime-link=shared install \
    && popd \
    && rm -rf ${boost_file} \
    && ldconfig\
    && popd
#grpc install
#versionが古いと特有のバグが入っているので最新にしておいた方が良い
#versionを固定しない場合はmasterを取ってくるのが吉
RUN git clone --recurse-submodules -b v1.43.0 https://github.com/grpc/grpc \
    && cd grpc\
    && mkdir -p cmake/build\
    && pushd cmake/build\
    && cmake -DgRPC_INSTALL=ON \
    -DgRPC_BUILD_TESTS=OFF \
    -DCMAKE_INSTALL_PREFIX=$MY_INSTALL_DIR \
    ../..\
    && make -j\
    && make install \
    && popd

```

---
ここでのgcc,g++は最新のものをビルドしても良いし、boostのバージョンは好きに選んで良い
ただgrpcやbazel系はバージョンが古いとエラーを起こしてc++20でビルドできないので注意
（それらのビルドのみc++17に落としても良いが単純にめんどくさいし、バグりそう）


もしgrpcのmakeが途中で失敗していたら大体がメモリの容量不足なのでdockerのメモリ容量を増やすか、他にメモリを使っているならそれを落とすかして起動する必要がある。
それでもダメな場合はRUNの部分をCMDにして実行時にインストールするように変更。

---
#補足

なぜg++の標準をg++-10に変えたのか。
**これは単純にbazelのコンパイラ変更が正常に動作しなかったので、直接大元のコンパイラを変えてみたら動いただけである。**

かなり邪道なことは百も承知だが、綺麗で動かせないものより汚くても動かせるものが欲しいのでこうしている。

ちなみにbazelの公式的には、toolchainやconfigでコンパイラ設定を作成して、starlarkなるものでルールを作成して変更することを推奨している。

が、これはできれば良いのだがあまりお勧めしない。
理由は単純難しいからである。

1. ドキュメントが全て英語であること
1. それらの用語を調べても同じサイトが出てきて解説が存在しないこと
1. 当然エラーも出まくるので精神が削られること

等々のbazelを嫌いになる要素が満載で、英語のドキュメントが読めない場合は完全にお手上げである。
環境構築でツールを嫌いになっていては開発なんてできなくなってしまう。
まぁ正直このツールは一般の人に使わせる気があるようには思えない。  ~~これ絶対cmake使った方がいい~~


新規のツールは開拓者がいないと後続が続けないので、
これらに詳しい人はコメントもしくは記事にしていただけると、本当に非常に助かります。

##まとめ
とりあえずこれでbazel + grpc + c++20 + boost を使用したプロジェクトを作成できる。
このようなニッチな需要があるかは知らないが、あまりにも日本語でのドキュメントが無さすぎるので記録を残すことにした。
より良い方法が確実にあるので、こちらを叩き台としてより洗練された作り方を模索して欲しい。