Goのエントリを見ているとたまにMakefileが出てくるけど何それ?という方に。
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というソフトウェアだそうで、MacやLinuxなら標準で使えます。
$ make
make: *** No targets specified and no makefile found. Stop.
今は読み込むmakefileが無いので何もせずに終了しました。
とりあえずhelloworldだけしてみましょう。
greet:
@echo helloworld
$ make
helloworld
greetは命令の名前で、一行下から実行したい処理を書いていきます。@echoの行のインデントはハードタブでないといけないです。自分はAtomエディタを使っているのですがそこらへんは勝手にやってくれました。
Makefileはどうやって書くの?
基本こういうシンプルなルールで書いていきます。
target: dependencies ...
commands
...
helloworldの例だとgreetがtarget、*@echo…*がcommandsに当たります。
複数のtargetを書いた場合はmakeコマンドで一番上のものだけ実行されます。
greet:
@echo helloworld
greet2:
@echo konichiwa
$ make
helloworld
なので一番上にallという名前で他targetを並べているのをよく見かけます。
all: target1 target2 ...
targetを指定して実行することもできます。
$ make greet2
konichiwa
dependencies には依存するtargetを書くことができます。
dep1: dep2
@echo This is dep1
dep2: dep3
@echo This is dep2
dep3:
@echo This is dep3
$ make
This is dep3
This is dep2
This is dep1
複数のtargetからdependenciesに指定されていても実行は一度です。
dep1: dep3 dep2
@echo This is dep1
dep2: dep3
@echo This is dep2
dep3:
@echo This is dep3
$ make dep1
This is dep3
This is dep2
This is dep1
変数定義
もちろんできます。
GOPHER = 'ʕ◔ϖ◔ʔ'
gopher:
@echo ${GOPHER}
$ make
ʕ◔ϖ◔ʔ
PHONY target
こんな書き方がされているのをよく見ます。
.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に定義していてもそうなってしまいます。
clean:
@rm *.txt
$ ls
clean makefile test.txt
$ make clean
make: `clean' is up to date.
PHONY targetを使えば意図したとおりに動作させられます。
.PHONY: clean
clean:
@rm *.txt
$ make clean
$ ls
clean makefile
この例でのcleanなんて名前のファイルがあることは実際ないかもしれませんが、バグを減らすための慣習として積極的に使っていきたいです。
他にもかなり多機能な書き方ができますが、これだけ知っておけばなんとなくであってもmakefileを読めるし、調べながら書いていけるのではないでしょうか。
Makefileで何ができるの?
いろいろな使用例があります。ビルドツールというより自動化ツールという感じですね。Node.jsでpackage.jsonのscriptsにいろいろ書くのと似ている気がします。
- ビルド
- バイナリビルド
- 開発環境のセットアップ
- go-bindataの処理
- ビルド生成ファイルの削除
- lint
- テスト実行
これらの書籍やエントリが参考になりそうです。
- みんなのGo言語 (技術評論社)初版 p.23
- 本物の golang を... 本物の Gopher を、お見せしますよ。
- Go でツール書くときの Makefile 晒す
- Golang を使うなら Makefile を恐れるな
- Automating Go development with Make
- A Makefile for your Go project
ひとまず開発中によく実行するコマンドやセットになっているものをMakefileに書いていくことからはじめてみるのもいいと思います。言語に限らず汎用的に使えるので使いこなせればかなり便利になりそうです。