Macでgendarmeを使う


[Gendarme](http://www.mono-project.com/docs/tools+libraries/tools/gendarme/)は
.NETアプリケーションやライブラリ向けの静的解析ツールです。ルールベースで問題検知をしてくれます。

## 前提条件
検証日 2016.10.04
MacOSX 10.11
Unity 5

## unity-gendarmeを使う
Unityなプロジェクトで導入する場合、[unity-gendarme](https://github.com/fderudder/unity-gendarme)
を使います。
[Download Packages](https://github.com/fderudder/unity-gendarme/downloads)ページからパッケージを
ダウンロードできるので、`mono gendarme.exe` とか実行してあげると動くと思います。

```console
$ mono gendarme.exe
Gendarme v2.11.0.0
Copyright (C) 2005-2011 Novell, Inc. and contributors

Usage: gendarme [--config file] [--set ruleset] [--{log|xml|html} file] assemblies
Where
  --config file		Specify the rule sets and rule settings. Default is 'rules.xml'.
  --set ruleset		Specify a rule set from configfile. Default is 'default'.
  --log file		Save the report to the specified file.
  --xml file		Save the report, as XML, to the specified file.
  --html file		Save the report, as HTML, to the specified file.
  --ignore file		Do not report defects listed in the specified file.
  --limit N		Stop reporting after N defects are found.
  --severity [all | [[audit | low | medium | high | critical][+|-]]],...
			Filter defects for the specified severity levels.
			Default is 'medium+'
  --confidence [all | [[low | normal | high | total][+|-]],...
			Filter defects for the specified confidence levels.
			Default is 'normal+'
  --console		Show defects on the console even if --log, --xml or --html are specified.
  --quiet		Used to disable progress and other information which is normally written to stdout.
  --v			When present additional progress information is written to stdout (can be used multiple times).
  assemblies		Specify the assemblies to verify.
```


## gendarme(mono-tools)をソースからビルドする
unity-gendarme使えば事足りるのですが、どうしてもソースからビルドしたいこともあるかもしれません。
その場合は[mono-tools](https://github.com/mono/mono-tools)をビルドします。gendarmeはmono-toolsの1機能として提供されています。

以下ビルド手順です。
（結局unity-gendarmeを使ってるのですが、先にソースビルド試してしまって、
その時にハマリまくったのでこのメモを公開しました。これがメイン。）

### brew経由で必要なものをインストール
```console
$ autoconf pkg-config readline automake gettext glib intltool libtool cairo libglade libpng12
```

### gtk-sharpをインストール

```console
$ wget http://download.mono-project.com/sources/gtk-sharp212/gtk-sharp-2.12.40.tar.gz
$ tar xzf gtk-sharp-2.12.40.tar.gz
$ cd gtk-sharp-2.12.40
$ ./configure
$ make && make install
```

### libgdiplusをインストール
```console
$ git clone https://github.com/mono/libgdiplus.git
$ cd libgdiplus
$ CPPFLAGS="-I/usr/local/opt/libpng12/include -I/opt/X11/include" LDFLAGS="-L/usr/local/opt/libpng12/lib -L/usr/X11/lib" ./autogen.sh
$ ./configure
$ make && make install
```

### mono-toolsをインストール
```console
$ git clone https://github.com/mono/mono-tools.git
$ cd mono-tools
$ PKG_CONFIG_PATH=/Library/Frameworks/Mono.framework/Versions/Current/lib/pkgconfig/ ./autogen.sh
$ ./configure
$ make && make install
```
何度かmakeでエラーっぽい出力があるかもしれませんが、無理やりmakeを通します(`make`を実行する)。


以下のようなエラーがでるならmonoのバージョンが古い可能性あるので brew reinstall mono してgtk-sharp入れ直すところから再度実行してください。

```
error CS0006: Metadata file `/usr/local/lib/pkgconfig/../../lib/mono/2.0/nunit.core.dll' could not be found
error CS0006: Metadata file `/usr/local/lib/pkgconfig/../../lib/mono/2.0/nunit.core.interfaces.dll' could not be found
error CS0006: Metadata file `/usr/local/lib/pkgconfig/../../lib/mono/2.0/nunit.core.extensions.dll' could not be found
error CS0006: Metadata file `/usr/local/lib/pkgconfig/../../lib/mono/2.0/nunit.framework.dll' could not be found
error CS0006: Metadata file `/usr/local/lib/pkgconfig/../../lib/mono/2.0/nunit.framework.extensions.dll' could not be found
error CS0006: Metadata file `/usr/local/lib/pkgconfig/../../lib/mono/2.0/nunit.mocks.dll' could not be found
error CS0006: Metadata file `/usr/local/lib/pkgconfig/../../lib/mono/2.0/nunit.util.dll' could not be found
error CS0006: Metadata file `/usr/local/lib/pkgconfig/../../lib/mono/2.0/nunit-console-runner.dll' could not be found
```

ここまでで`gendarme`を実行できるようになります。

```console
$ gendarme
Gendarme v4.2.0.0
Copyright (C) 2005-2011 Novell, Inc. and contributors

Usage: gendarme [--config file] [--set ruleset] [--{log|xml|html} file] assemblies
Where
  --config file		Specify the rule sets and rule settings. Default is 'rules.xml'.
  --set ruleset		Specify a rule set from configfile. Default is 'default'.
  --log file		Save the report to the specified file.
  --xml file		Save the report, as XML, to the specified file.
  --html file		Save the report, as HTML, to the specified file.
  --ignore file		Do not report defects listed in the specified file.
  --limit N		Stop reporting after N defects are found.
  --severity [all | [[audit | low | medium | high | critical][+|-]]],...
			Filter defects for the specified severity levels.
			Default is 'medium+'
  --confidence [all | [[low | normal | high | total][+|-]],...
			Filter defects for the specified confidence levels.
			Default is 'normal+'
  --console		Show defects on the console even if --log, --xml or --html are specified.
  --quiet		Used to disable progress and other information which is normally written to stdout.
  --v			When present additional progress information is written to stdout (can be used multiple times).
  assemblies		Specify the assemblies to verify.
```

## 使用例
```console
$ mono gendarme.exe --config rules.xml --set "unity-full" --xml result.xml YOUR.dll
Gendarme v2.11.0.0
Copyright (C) 2005-2011 Novell, Inc. and contributors

Initialization: 0.6 seconds
YOUR.dll: 3.8 seconds
TearDown: <0.1 seconds

One assembly processed in 4.3 seconds.
4274 defects found. Report written to: `result.xml'.
```

* `--config` オプションはルール設定ファイルを指定します。 `mono-tools/gendarme or unity-gendarme`の下に`rules.xml`が
存在すると思いますので、それをベースに調整して使います。
* `--set`オプションは`rules.xml`内のどの`ruleset`を使うかを指定できます。指定しない場合は`default`が使われます。
* `--xml`オプションはXML形式で結果を書き出します。他にも`--log`や`--html`を指定することができます。

## Jenkinsで警告表示したい
[Violations Plugin](https://wiki.jenkins-ci.org/display/JENKINS/Violations)を使います。

この時に2点注意すべき点があります。

* 特定のファイルだけ解析したい、とかがやりにくい
* そのままだと対応箇所がJenkins上で見れない

1つめはgendarmeコマンドのオプションで指定しにくい。（できなくは無いが、無視するファイルリストを作ったりしないといけないっぽい）
2つめはrules.rule.Typeが"Method"以外("Assembly"とか"Type")の場合、Jenkins上で参照することができません。
またresults.rule.target.defect.Sourceがからの場合もソースが参照できず、結果的にJenkins上で参照することができません。

これらを解決するために、XML出力結果をパースして、不要なノードを削除したり、アトリビュートを書き換えて対応しました。
[Go使ったスクリプトをGistに公開](https://gist.github.com/hhatto/6ca28c6bc3e961a6c95a9b22f70455d8)しておきましたので参考まで。
<img width="923" alt="gendarme-setting.png" src="https://qiita-image-store.s3.amazonaws.com/0/1775/a9baba77-fd12-4b54-8136-1566d84383de.png">
<img width="529" alt="gendarme-dashboard.png" src="https://qiita-image-store.s3.amazonaws.com/0/1775/b0f4ecf7-e785-c0dd-44d3-0eca3f3af201.png">
<img width="671" alt="gendarme-summary.png" src="https://qiita-image-store.s3.amazonaws.com/0/1775/a23995d5-a973-2dc6-35b8-1b1298f3acc1.png">
<img width="593" alt="gendarme-fileview.png" src="https://qiita-image-store.s3.amazonaws.com/0/1775/4e4b0cba-c083-1374-dfd4-17d165ff7914.png">