Edited at

2016年だけどMakefileを使ってみる

More than 1 year has passed since last update.


この資料はなに?

Makeの良さを伝えるものです


  • CとかC++の持ち物じゃない

  • 普段使うコマンドのショートカットみたいな

  • 2016年でもMakefileは便利


 2016-10-19 19.11.07.png

頑張らないでScala 〜VOYAGE GROUPにおけるアドネットワーク開発の戦略〜 // Speaker Deck



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はるのとは違う

    • ディレクトリ(プロジェクト)毎にコマンドを用意できるので環境は汚れない



  • よく使うコマンドを共有できる


    • 「配信サーバに対するリクエストってどうやって送ればいいですか?」に応える





サンプル

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となっている点に注意。