GoのためのMakefile入門

Goのエントリを見ているとたまにMakefileが出てくるけど何それ？という方に。

# Makefileってなに？

[Wikipedia](https://en.wikipedia.org/wiki/Makefile)に


> A **makefile** is a file containing a set of directives used with the make build automation tool.

とあるように、主な目的はプログラムのビルドをするための命令群を書いたファイルということになります。CやC++の界隈でよく使われているそうです。
Makefileはそもそも**make**コマンドに渡して実行させるためのものです。makeコマンドの実体は普通[GNU make](https://www.gnu.org/software/make/)というソフトウェアだそうで、MacやLinuxなら標準で使えます。

```shell:shell
$ make
make: *** No targets specified and no makefile found.  Stop.
```

今は読み込むmakefileが無いので何もせずに終了しました。
とりあえずhelloworldだけしてみましょう。

```makefile:makefile
greet:
  @echo helloworld
```

```shell:shell
$ make
helloworld
```

*greet*は命令の名前で、一行下から実行したい処理を書いていきます。*＠echo*の行のインデントはハードタブでないといけないです。自分はAtomエディタを使っているのですがそこらへんは勝手にやってくれました。

# Makefileはどうやって書くの？

基本こういうシンプルなルールで書いていきます。

```makefile:makefile
target:   dependencies ...
          commands
          ...
```

helloworldの例だと*greet*がtarget、*＠echo…*がcommandsに当たります。
複数のtargetを書いた場合はmakeコマンドで一番上のものだけ実行されます。

```makefile:makefile
greet:
	@echo helloworld
greet2:
	@echo konichiwa
```

```shell:shell
$ make
helloworld
```

なので一番上に*all*という名前で他targetを並べているのをよく見かけます。

```makefile:makefile
all: target1 target2 ...
```

targetを指定して実行することもできます。

```shell:shell
$ make greet2
konichiwa
```

**dependencies** には依存するtargetを書くことができます。

```makefile:makefile
dep1: dep2
  @echo This is dep1
dep2: dep3
  @echo This is dep2
dep3:
  @echo This is dep3
```

```shell:shell    
$ make
This is dep3
This is dep2
This is dep1
```

複数のtargetからdependenciesに指定されていても実行は一度です。

```makefile:makefile
dep1: dep3 dep2
  @echo This is dep1
dep2: dep3
  @echo This is dep2
dep3:
  @echo This is dep3
```

```shell:shell
$ make dep1
This is dep3
This is dep2
This is dep1
```

## 変数定義

もちろんできます。

```makefile:makefile
GOPHER = 'ʕ◔ϖ◔ʔ'
gopher:
  @echo ${GOPHER}
```

```shell:shell
$ make
ʕ◔ϖ◔ʔ
```

## PHONY target

こんな書き方がされているのをよく見ます。

```makefile:makefile
.PHONY: clean
clean:
  @rm *.txt
```

これは**PHONY target**と呼ばれるものです。

> Phony: not real or genuine; fake; counterfeit:
> http://www.dictionary.com/browse/phony

makeはそもそもビルドをするためのツールなのでコマンド`make hoge`を実行するとカレントディレクトリにhogeという名前のファイルがないか探しに行きます。
hogeというtargetをmakefileに定義していてもそうなってしまいます。

```makefile:makefile
clean:
  @rm *.txt
```

```shell:shell
$ ls
clean         makefile        test.txt
$ make clean
make: `clean' is up to date.
```

PHONY targetを使えば意図したとおりに動作させられます。

```makefile:makefile
.PHONY: clean
clean:
	@rm *.txt
```

```shell:shell
$ make clean
$ ls
clean         makefile
```

この例での*clean*なんて名前のファイルがあることは実際ないかもしれませんが、バグを減らすための慣習として積極的に使っていきたいです。

他にもかなり多機能な書き方ができますが、これだけ知っておけばなんとなくであってもmakefileを読めるし、調べながら書いていけるのではないでしょうか。

# Makefileで何ができるの？

いろいろな使用例があります。ビルドツールというより自動化ツールという感じですね。Node.jsでpackage.jsonのscriptsにいろいろ書くのと似ている気がします。

- ビルド
- バイナリビルド
- 開発環境のセットアップ
- go-bindataの処理
- ビルド生成ファイルの削除
- lint
- テスト実行

これらの書籍やエントリが参考になりそうです。

- [みんなのGo言語](http://gihyo.jp/book/2016/978-4-7741-8392-3) （技術評論社）初版 p.23
- [本物の golang を... 本物の Gopher を、お見せしますよ。](https://qiita.com/mattn/items/b7889e3c036b408ae8bd#-%E3%81%A9%E3%81%86%E3%82%84%E3%81%A3%E3%81%A6%E5%8B%95%E3%81%84%E3%81%A6%E3%81%84%E3%82%8B%E3%81%AE%E3%81%8B)
- [Go でツール書くときの Makefile 晒す](https://qiita.com/dtan4/items/8c417b629b6b2033a541)
- [Golang を使うなら Makefile を恐れるな](https://frasco.io/golang-dont-afraid-of-makefiles-785f3ec7eb32)
- [Automating Go development with Make](https://blog.gopheracademy.com/advent-2017/make/)
- [A Makefile for your Go project](https://vincent.bernat.im/en/blog/2017-makefile-build-golang)

ひとまず開発中によく実行するコマンドやセットになっているものをMakefileに書いていくことからはじめてみるのもいいと思います。言語に限らず汎用的に使えるので使いこなせればかなり便利になりそうです。