CMakeに関する個人的メモ

## はじめに
　本記事は，[モダンFortran勉強会.f02](https://qiita.com/implicit_none/items/ad4c556c043a91fa0dc4)での[@ijknablaさん](https://qiita.com/ijknabla)の発表[^cmakepresen]を聞いて，実際に自身の環境にCMake[^cmake]をインストールし利用してみた際の備忘録です．

[^cmakepresen]: cmake による Fortran90 ビルドの省力化　(https://qiita.com/ijknabla/items/05270ae5e597705d0dae)
[^cmake]: CMake 公式webサイト (https://cmake.org/)

## 更新履歴

2019.07.03 : 公開
2019.10.10 : @ijknablaさんにコメントで指摘いただいたことを[コンパイラとコンパイラオプション](#コンパイラとコンパイラオプション)の項に追加．Intel MKLに関する記載を[CMakeでIntel MKLをリンクする](https://qiita.com/toya42/items/bb57a2e04b1aaa2d2bcd)に分離



## バージョン

### macOS 10.14.5
　macportsを用いてインストールされたバージョンは，latest release (3.14.5)

### Ubuntu 16.04
　aptを用いてインストールされたバージョンは，3.5.1（正確にはxenial-updates,now 3.5.1-1ubuntu3 amd64）．このバージョンの挙動がmacにインストールしたlateset releaseのものと異なった．よってアンインストールをした後，公式サイトからlatest releaseの Unix/Linux sourceをダウンロードし，インストールした．

```bash
$wget https://github.com/Kitware/CMake/releases/download/v3.14.5/cmake-3.14.5.tar.gz
$tar -xzvf cmake-3.14.5.tar.gz
$cd cmake-3.14.5
$./configure
$make 
$sudo make install
```

手なりで`configure`を使ったが，READMEによれば

```bash
$ ./bootstrap && make && sudo make install
```

で良いらしい．

`prefix`でインストール場所を指定しなかったので，`/opt`以下に移し，シンボリックリンクを貼る[^qiitacmake1]

[^qiitacmake1]: Linuxに特定のバージョンのcmakeをインストール (https://qiita.com/pollenjp/items/391afc3e9f93006b83ba)



```bash
$cd ..
$sudo mv cmake-3.14.5/ /opt
$sudo ln -s /opt/cmake-3.14.5/bin/* /usr/bin/
```

Ubuntu 18.04については手元に環境がないため確認していない．



## コンパイラとコンパイラオプション

　`CMAKE_<LANG>_FLAGS`に`set`することで，コンパイラオプションを利用する[^lesson][^qiitacmake2]．次の例は，実行時オプションに合わせてコンパイラとコンパイルオプションを変えている． 

```cmake
#ifort
if(CMAKE_Fortran_COMPILER_ID MATCHES Intel)
    set(CMAKE_Fortran_FLAGS         "-O3 -p")
    set(CMAKE_Fortran_FLAGS_DEBUG   "-O0 -warn all -standf95")
    set(CMAKE_Fortran_FLAGS_RELEASE "-O3 -march=native")
endif()
#gfortran
if(CMAKE_Fortran_COMPILER_ID MATCHES GNU)
    set(CMAKE_Fortran_FLAGS         "-O3 -p")
    set(CMAKE_Fortran_FLAGS_DEBUG   "-O0 -Wall")
    set(CMAKE_Fortran_FLAGS_RELEASE "-O3 -march=native")
endif()
```

実行時に `-D`オプションをつけて，`CMAKE_Fortran_COMPILER`と`CMAKE_BUILD_TYPE`により指定する．(`CMAKE_BUILD_TYPE`は前回の値を記憶するので，毎回明示すること[^qiitacmake2])

```bash
$cmake -D CMAKE_Fortran_COMPILER=ifort -D CMAKE_BUILD_TYPE=debug 
```

ところが，stack overflowのあるQ&Aによるとmodernなcompile flagの設定には，
`CMAKE_<LANG>_FLAGS`ではなく，`target_compile_options`を使うほうが良いという趣旨の回答があった[^stackoverflow]．こみいった依存関係を持つ`project`にCMakeを利用する際は，注意したほうが良いのかもしれない．

### 2019.08.2? 追記

@ijknablaさんにコメントいただいたので，簡単に追記する．

* 一括でコンパイラオプションが設定されるのが，`CMAKE_<LANG>_FLAGS`の長所であり，短所．
* ファイル単位でコンパイラオプションの指定をしたい場合は`target_compile_options`が便利．


[^lesson]: CMake lesson (https://coderefinery.github.io/cmake/06-compilers/)
[^qiitacmake2]: CMake 簡易まとめ (https://qiita.com/janus_wel/items/a673793d448c72cbc95e)
[^stackoverflow]: stack overflow: What is the modern method for setting general compile flags in CMake? (https://stackoverflow.com/questions/23995019/what-is-the-modern-method-for-setting-general-compile-flags-in-cmake)


## 静的ライブラリのリンク

`target_link_libraries`で指定[^cmakepresen]．

```cmake
target_link_libraries(${EXECUTABLE}
    PRIVATE
    /(library path)/hoge.a
)
```

## Intel MKLのリンク

　~~コンパイルオプションに`-mkl`をつけるのではなく，`target_link_libraries`で`mkl_rt`を指定する．~~

```cmake
target_link_libraries(${EXECUTABLE}
    PRIVATE
    mkl_rt
)
```
### 2019.10.10追記
上記の方法は不十分かつ不正確なため分離して，新しい記事にできる限り詳しい説明を述べた．参照していただきたい．
[CMakeでIntel MKLをリンクする](https://qiita.com/toya42/items/bb57a2e04b1aaa2d2bcd)

## OpenMP, MPI
　[@ijknablaさん](https://qiita.com/ijknabla)の記事[^cmakepresen]そのままで利用できた．（Ubuntuにはじめにインストールした3.5.1では利用できなかった）

```cmake
find_package(MPI    REQUIRED)
find_package(OpenMP REQUIRED)

#~~~~~

target_link_libraries(${EXECUTABLE}
  PRIVATE
  MPI::MPI_Fortran
  OpenMP::OpenMP_Fortran
  )
```

## 疑問　
* コンパイルオプションを指定する最適な方法は何か？
* cmakeはcmakeが使えない環境用に，単体で運用できる（移植できる）makefileを出力できるのか