2016年だけどMakefileを使ってみる
2016-10-19
QiitaMakefileこの資料はなに?
Make の良さを伝えるものです
- C とか C++の持ち物じゃない
- 普段使うコマンドのショートカットみたいな
- 2016 年でも Makefile は便利
Make ってなに?Makefile???
make(メイク)は、プログラムのビルド作業を自動化するツール。コンパイル、リンク、インストール等のルールを記述したテキストファイル (makefile) に従って、これらの作業を自動的に行う。 出典:https://ja.wikipedia.org/wiki/Make
つまり、自動化のためのツール。
make が生成するのはふつう C のプログラムだが、べつに C のプログラムに限らず、Makefile に書く生成コマンドの書きように よっては、TeX のファイルだろうが、Java のプログラムだろうが 何でも make を利用して作業を軽減することができる。 出典:http://www.unixuser.org/~euske/doc/makefile/
なので、C だろうが C++だろうが Scala だろうが関係ない。
ぐぐるとこんなの出てきて難しそう...
PROGRAM = main
OBJS = main.o
CC = gcc
CFLAGS = -Wall -O2
.SUFFIXES: .c .o
.PHONY: all
all: depend $(PROGRAM)
$(PROGRAM): $(OBJS)
$(CC) -o $(PROGRAM) $^
.c.o:
$(CC) $(CFLAGS) -c $<
.PHONY: clean
clean:
$(RM) $(PROGRAM) $(OBJS) depend.inc
.PHONY: depend
depend: $(OBJS:.o=.c)
-@ $(RM) depend.inc
-@ for i in $^; do cpp -MM $$i | sed "s/\ [_a-zA-Z0-9][_a-zA-Z0-9]*\.c//g" >> depend.inc; done
-include depend.inc
http://www.ie.u-ryukyu.ac.jp/~e085739/c.makefile.tuts.html
何が良いの?
ぼくがおもう Make のいいところ
- わざわざインストールしなくていい(はず)
- デフォルトで入ってる(
/usr/bin/make
)
- デフォルトで入ってる(
- タブ補完が効く
- よく使うコマンドを保存出来る
- .bashrc に
alias
はるのとは違う- ディレクトリ(プロジェクト)毎にコマンドを用意できるので環境は汚れない
- .bashrc に
- よく使うコマンドを共有できる
- 「配信サーバに対するリクエストってどうやって送ればいいですか?」に応える
サンプル
Makefile はこんな感じ。
show-ip:
ipconfig getifaddr en0
これを使ってみる。
$ make show-ip
ipconfig getifaddr en0
192.168.0.27
これはshow-ip
というタスクでipconfig getifaddr en0
というコマンドを実行している。
難しいコマンドをおぼえなくていいし、Makefile の文法も簡単なので学習コストは低い。
書き方
ざっくりとはこれだけ。
<変数宣言>
<タスク名>:
<実行したいshell>
<タスク名>:<必要ファイル名>
<実行したいshell>
インデントはタブ文字なので注意。 ほんとは変数じゃなくてマクロと呼ばれる。
実行するシェルを標準出力に表示しない方法
実行すると実行するシェルが出力されてしまうので、鬱陶しい場合は@
を先頭につける。
show-files:
ls -lh
show-files-suppress:
@ls -lh
実行するときは何も変わらない
$ make show-files
ls -lh
total 8
-rw-r--r-- 1 petitviolet staff 51B Oct 15 15:10 Makefile
$ make show-files-suppress
total 8
-rw-r--r-- 1 petitviolet staff 51B Oct 15 15:10 Makefile
変数宣言
Makefile の中では変数を使用することが出来る。
$ cat Makefile
MESSAGE := "HELLO"
hello:
@echo $(MESSAGE)
$ make hello
HELLO
タスクで使用する際に上書き出来る。
$ make hello MESSAGE=こんにちは
こんにちは
タスク実行に必要なファイルを指定できる
activator
というファイルが存在していれば...みたいなタスクを定義する。
compile: activator
@echo "Yey!"
ファイルが無いと失敗し、ファイルがあれば成功する。
$ ls
Makefile
$ make compile
make: *** No rule to make target 'activator', needed by 'compile'. Stop.
$ touch activator
$ make compile
Yey!
順番にタスクを実行するような場合、ファイルの作成を持って成否判定を出来たりして便利!
タスクからタスクを呼ぶ
あるタスクの中から別のタスクを実行することも出来る。
task-a:
@echo "A"
@touch a.txt
@make task-b
task-b: a.txt
@echo "B"
@touch b.txt
@make task-c
task-c: b.txt
@echo "C"
@touch c.txt
clean: a.txt b.txt
@rm a.txt b.txt c.txt
@echo 'complete!!!'
doit:
@make task-a
@make clean
実行するとこんな感じになる。
$ make doit
A
B
C
complete!!!
複数行にわたるコマンドを実行したい時
一行ごとに別の shell として実行される点に注意。
$ ls
Makefile
$ cat Makefile
make-tmp-file-home:
@cd ~
@touch hogehoge
$ make make-tmp-file-home
$ ls
Makefile hogehoge
これはサブシェルの中でcd
して、別のサブシェルの中でtouch
しているので、カレントディレクトリでの操作となる。
&&
と\
でつないで 1 つのシェルとして実行すれば良い。
$ ll $HOME | grep 'hogehoge' | wc -l
0
$ cat Makefile
make-tmp-file-home:
@cd ~ && \
touch hogehoge
$ make make-tmp-file-home
$ ll $HOME | grep 'hogehoge' | wc -l
1
シェル変数と制御文
上記の点さえ気をつければ for 文も書ける。
LENGTH := 3
show-seq:
@for i in {1..$(LENGTH)}; do \
echo $$i; \
done
ここでシェル変数が$$i
となっている点に注意。
from: https://qiita.com/petitviolet/items/a1da23221968ee86193b