Go
golang
Makefile
Go3Day 11

GoのためのMakefile入門

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

Makefileってなに?

Wikipedia

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

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

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

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

makefile
greet:
  @echo helloworld
shell
$ make
helloworld

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

Makefileはどうやって書くの?

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

makefile
target:   dependencies ...
          commands
          ...

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

makefile
greet:
    @echo helloworld
greet2:
    @echo konichiwa
shell
$ make
helloworld

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

makefile
all: target1 target2 ...

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

shell
$ make greet2
konichiwa

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

makefile
dep1: dep2
  @echo This is dep1
dep2: dep3
  @echo This is dep2
dep3:
  @echo This is dep3
shell
$ make
This is dep3
This is dep2
This is dep1

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

makefile
dep1: dep3 dep2
  @echo This is dep1
dep2: dep3
  @echo This is dep2
dep3:
  @echo This is dep3
shell
$ make dep1
This is dep3
This is dep2
This is dep1

変数定義

もちろんできます。

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

PHONY target

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

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
clean:
  @rm *.txt
shell
$ ls
clean         makefile        test.txt
$ make clean
make: `clean' is up to date.

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

makefile
.PHONY: clean
clean:
    @rm *.txt
shell
$ make clean
$ ls
clean         makefile

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

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

Makefileで何ができるの?

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

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

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

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