CMake on DockerでC++コードを簡単ビルド

## はじめに
- WindowsPC上で、Linuxに対応したCppプロジェクトを作成したい
- CMakeのDockerコンテナを探しても見つからなかったので今回作成した

## 良い点
- ローカルフォルダをマウントするよう設定
    - ローカルフォルダ上でコードを編集すると、すぐにコンテナへ変更が反映される
    - コンテナにログインせずとも、VS code などのエディタで編集できる
    - ビルド後のファイルもdocker cp コマンドを使わずに取り出せる

## ダウンロード
- この記事で紹介したDocker imageは、[DockerHub](https://hub.docker.com/r/nkym0225/cmake-ubuntu-1804) からダウンロードすることができます。

    - CMakeの使い方等は[こちらの記事](https://qiita.com/shohirose/items/45fb49c6b429e8b204ac#cmakeを使ってみる)をご参考ください

## 活用例
- ①cppフォルダ内に、.cppファイルやCMakeLists.txtを置く
    - VSCodeなど、自分の使い慣れたエディタで編集する
- ②コンテナ内に入り、ビルド実行
- ③ビルド後のファイルは、ローカル環境のcppフォルダから取り出すことができる
<img width="510" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/349189/8e574b9f-7c58-6c53-bbec-70fa44166e53.png">

## フォルダ構成
- 下図のようにDockerfile, docker-compose.ymlを配置する
    - ソースコードは記事の下部に記載
- cppフォルダは、docker-compose up によって自動生成される
    - このフォルダ内に ソースコードを置く

```bash:tree
フォルダ構成
├── Dockerfile
├── docker-compose.yml
└── cpp  ← 自動生成される
```

## Dockerfile

```dockerfile:Dockerfile
FROM ubuntu:18.04

RUN apt-get update && apt-get -y upgrade && \
    apt-get install -y sudo && \
    apt-get install -y build-essential && \
    apt-get install -y vim && \
    apt-get install -y wget && \
    apt-get install -y unzip && \
    apt-get install -y git && \
    apt-get install -y libssl-dev

# Install compilers.
RUN apt-get install -y gcc && \
    apt-get install -y g++

# SET path to compilers.
# https://stackoverflow.com/questions/17275348/how-to-specify-new-gcc-path-for-cmake
ENV CC=/usr/bin/gcc \
    CXX=/usr/bin/g++

# Install newer CMake manually
# https://qiita.com/hyasuda/items/16c21458f0ecd08db857
RUN cd $HOME && \
    wget https://github.com/Kitware/CMake/releases/download/v3.17.1/cmake-3.17.1.tar.gz && \
    tar zxvf cmake-3.17.1.tar.gz && \
    cd cmake-3.17.1/ && \
    ./bootstrap && \
    make -j12 && sudo make install -j8
RUN echo 'export PATH=$HOME/cmake-3.17.1/bin/:$PATH' >> ~/.bashrc && \
    . ~/.bashrc

# OpenBlas, Lapack
RUN apt-get install -y libopenblas-dev && \
    apt-get install -y liblapack-dev

# Please use below directory to install cpp libraries.
WORKDIR $HOME/usr/
RUN mkdir ./library

CMD bash
```

## docker-compose.yml

```yaml:docker-compose.yml
version: '3'

services:
  cmake:
    container_name: cmake_container
    build:
      context: .
      dockerfile: Dockerfile
    
    tty: true
    command: /bin/bash

    volumes:
      - ./cpp:/usr/cpp
```

# 使い方
#### コンテナの起動

```bash:ローカル環境
# コンテナの初回起動
docker-compose up -d

# 起動中のコンテナに入る
docker-compose exec cmake bash
```

#### ソースコードのコンパイル

```bash:@make_container
# コンテナ内のcppフォルダに入る
cd cpp

# build フォルダを作成し入る
mkdir build
cd build

# cmakeの実行
cmake ../

# makeの実行
make
```

#### 注意点
- OS依存のライブラリは、cppフォルダ内で展開・インストールしないでください
    - 筆者は以下のエラーメッセージが表示され、コンテナのマウントが解除されてしまいました。
    - ```docker compose error while creating mount source path... ```
    - 依存ライブラリはコンテナ内で別フォルダを作り、そこにインストールしてください
       - 例) OpenCV

## チュートリアル
- 以下では、`Hello CMake!`と書かれたソースコードをビルドするまでをご紹介します。
- cppフォルダ内に以下の2つのファイルを作成してください。

```bash:cppフォルダ内の構成
cpp
├── main.cpp
└── CMakeLists.txt
```

- 各ファイルに以下の内容をコピーしてください。

```cpp:main.cpp
#include <iostream>
#include <string>

int main(void){
    std::cout << "Hello CMake!" << std::endl;
    return 0;
}
```

```cmake:CMakeLists.txt
# プロジェクト名
project("testCMake")

# CMakeのバージョンを設定
cmake_minimum_required(VERSION 2.8)

# testCMake.outという実行ファイルをmain.cppから作成
add_executable(testCMake main.cpp)
```

- 次に、コンテナでのビルド作業に入ります。
- 以下のコマンドを順に入力してビルドします。

```bash:@cmake_container
# コンテナ内のcppフォルダに入る
cd cpp

# ビルドフォルダを作る
mkdir build
cd build

# ビルド実行
cmake ../
make
```

- 最後にビルドしたプログラムを走らせてみましょう!
    - `./testCMake`と入力し、Hello CMake!と出力されれば成功です。

```bash:@cmake_container
./testCMake 
Hello CMake!
```