Edited at
Go3Day 11

GoのためのMakefile入門

More than 1 year has passed since last update.

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に書いていくことからはじめてみるのもいいと思います。言語に限らず汎用的に使えるので使いこなせればかなり便利になりそうです。