C及びC++でIDEなしでそれなりに快適な開発環境

# 概要

現在僕が使っている開発環境を共有して、少しでもマシな開発環境にするアドバイスが欲しい。
ノウハウとしてはC++寄りだけれど、大抵の言語に横展開可能なテクニックだと思う。

#### 想定されるご意見：IDE使え

うちのCLion2016.1.3(CL-145.1617)さん、プロジェクト開いただけでCPUを100%食いつぶしたまま帰ってこないんですが…。静的解析をオフにしてみたけどダメ。そもそも静的解析してくれないならなんのための統合開発環境かっていう話にもなるので、いつかマシになると信じてとりあえずEmacsで開発してるのが今。

# 環境セット

以下の組み合わせで開発している。

- CMake(+Makefile)
- gtest
- Emacs
- watchmedo
- notify-send(MacならGrowlなりなんなり)

## CMake

しばらく[waf](http://matsu911.github.io/waf_book_ja/)も使い込んでいたし、特に不便も感じていなかったけれど、CLionでそのまま使えなかったのと、CLionがデフォルトで用意してくれているのでそのまま使うことにしている。

手元のベースラインはこんな感じ。

```cmake:CMakeList.txt
cmake_minimum_required(VERSION 3.3)
project(プロジェクト名)

enable_testing() # ctestを有効化するのに必要
add_subdirectory(src/third_party/gtest)

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DNDEBUG -std=c++11 -ggdb -Wall -Wextra -O3") # -fsanitize=address -fno-omit-frame-pointer") # 必要ならAddress Sanitizerも使える
set(SOURCE_FILES 使ってるソースファイル)

include_directories(src)
include_directories(src/third_party/gtest/googletest/include)
add_executable(実行ファイル ${SOURCE_FILES})

# 渡されたテスト名を実行用ファイルとしてctestの対象に加えていく関数
function (add_gtest_target test_name)
  add_executable(${test_name} src/${test_name}.cpp)
  target_link_libraries(${test_name} gtest_main)
  add_test(
    NAME ${test_name}
    COMMAND ./${test_name})
  link_directories(src/third_party/gtest/googlemock/gtest/)
endfunction()

set(gtest_targets # テストファイルはこの配列に追加していく
    hoge_test
    fuga_test)

# 上で定義されたテストファイル群をadd_gtest_target関数に渡すだけのループ
foreach(target ${gtest_targets})
  add_gtest_target(${target})
endforeach()
```

こういうのを用意して、`src/third_party` ディレクトリ以下で

```bash:
$ git clone https://github.com/google/googletest
```
とでもしておく。

```bash
$ mkdir build
$ cd build
$ cmake -DCMAKE_BUILD_TYPE=Relese ..
```

こうすれば `build` ディレクトリ以下に Makefileなどが一式用意されてビルドできるようになる。`CMakeLists.txt` と同じディレクトリで cmakeをすると後片付けが大変なので別ディレクトリを掘ったほうがいい。

## watchmedo

毎回コードを更新するたびにターミナルに戻ってビルドコマンド走らせるのは辛いので監視させて継続的にビルドさせたい。
[OMake](http://omake-japanese.osdn.jp/)はそういう需要を満たす優れたソフトウェアだけれどCLionが対応してなさそうなので別の方法で解決した。
Pythonの `watchdog` というモジュールについてくる `watchmedo` というソフトが便利。

```bash
$ pip install watchdog
```

すると watchmedoコマンドが使えるようになるのでこんなふうに使う。

```bash:
$ watchmedo shell-command --patterns="*pp" --recursive --wait --command="cd build && make -j8 > build.log 2>&1 && ctest >> build.log 2>&1 && notify-send BUILD-success || notify-send Failed."
```

これは「今居るディレクトリより下の、ファイル名が`pp`で終わる全てのファイルを監視して、更新されたら `--command`オプションで指定された `make -j8 > build.log 2>&1 && ctest >> build.log 2>&1 && notify-send BUILD-success || notify-send Failed.` を実行せよ。という意味になる。
もちろん開発を始めるたびにこんなクソ長いコマンド打ってられないので、プロジェクトのルートにシェルスクリプトとして置いている。特定のテストを重点的に行いたい場合はctestの部分を書き換えれば良いので楽。

## notify-send

`&&` というのは論理演算と同様に「直前のコマンドが成功したらこの右辺を実行せよ」という意味で使えるモノで、この使い方なら「`make`を実行して成功したら`ctest`を実行して成功したら `notify-send BUILD-success`を実行せよ。」という意味になる。notify-sendというのはLinuxのgnome環境で使えるデスクトップ通知を飛ばすだけのソフトであり、Ubuntuなら

```bash
$ sudo apt-get install libnotify-bin
```

でインストールできる。
`||` も論理演算と同様に「直前のコマンドが失敗したらこの右辺を実行せよ」という意味で使えるモノで、makeかctestのどちらかがコケたら`Failed`とデスクトップ通知で伝えてくれる。C++のビルドは時間がかかるので、エディタで保存したら通知が来るまでtwitterでも眺めていれば良い。


## emacs

C++のコンパイルエラーはエラーになった先頭数行しか使わない事が多く、その割にはコンパイルエラーがターミナルを埋め尽くして辛いのでファイルに書き出すのが便利だ。grepもできるしエディタ上でログを検索・整形することだってできる。上のコマンドでも makeと ctestの結果は `build.log` ファイルに書き出している。build.logファイルがポンポン更新されるので

```
(global-auto-revert-mode 1)
```

を.emacs.el に加える事で自動的にリロードさせている。

## 現状の問題点

使っていて今のところ困っているのはこんな感じ。

- watchmedoは何故か一度のファイル変更を複数回の変更とみなしてビルドが複数回トリガされてしまう。emacsの保存手続きが悪さしているかも知れない。
- auto-revertの頻度が秒単位。もっとキビキビリロードして欲しい。