【初心者向け】Makefile入門

C言語で学ぶMakefile基礎。
初めてMakefileを作ろうと思っている初心者の方向け。

#なぜMakefileがスゴいのか
CやC++のコンパイルを**コマンドひとつで自動化できるのがめちゃくちゃ便利**。
>**make** - Wikipedia
>>make（メイク）は、プログラムのビルド作業を自動化するツール。コンパイル、リンク、インストール等のルールを記述したテキストファイル (makefile) に従って、これらの作業を自動的に行う。

ビルドしたいプログラムと同じ階層にMakefileという名前のファイルを作り、そのなかに独自の文法を使って変数や依存関係などのルールを書いておけば、それがMakefileとなる。

```
$ ls
Makefile    sample_A.c    sample_B.c    sample_C.c
```
### Makefileのメリット
- コマンドを自由に作れる（こういうルールでビルドしたい、を自由に定義可能）
- 変更差分だけコンパイルし直すことができ、時間短縮できる
- チーム開発する際、Makefileを共有すれば全員でコンパイルルールを統一できる
- 基本構造はシンプルなので、自分のテンプレートを一度作れば様々なプログラムに流用できる

#Makefileの基本構造
Makefileはざっくりと2つの構造から成り立っている。

①Makefileの中で用いる変数(マクロ)の設定
②ルールの設定

### Makefileのサンプル
<img width="865" alt="スクリーンショット 2020-06-25 7.19.16.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/660621/2f3abfae-21e6-cf3f-5669-2bcd8f9ec29c.png">
### サンプルで定義しているルール内容

1. **makeあるいはallコマンドで以下の動作を自動化する**

    1-1. 3つのファイル(sample_A.c,　sample_B.c,　sample_C.c)からオブジェクトファイルを生成
    1-2. 静的ライブラリhoge.aを生成し、全てのオブジェクトファイルをリンクさせる
    1-3. hoge.aにインデックスを付与
2. **cleanコマンドで全てのオブジェクトファイルを削除できる**
3. **fcleanコマンドで全てのオブジェクトファイルと静的ライブラリを削除できる**
4. **reコマンドでfclean→allを実行(コンパイルのやり直し)ができる**

### 【実行例】

```
% make
gcc -c sample_A.c -o sample_A.o
gcc -c sample_B.c -o sample_B.o
gcc -c sample_C.c -o sample_C.o
ar rc hoge.a sample_A.o sample_B.o sample_C.o　//静的ライブラリ生成
ranlib hoge.a　　　　　　　　　　　　　　　　　　　　//静的ライブラリにインデックス付与

% ls
Makefile	sample_A.c	sample_B.c	sample_C.c
hoge.a		sample_A.o	sample_B.o	sample_C.o
```

```
% make fclean
rm -f sample_A.o sample_B.o sample_C.o
rm -f hoge.a

% ls
Makefile	sample_A.c	sample_B.c	sample_C.c
```

# Makefileの書き方
### 1. Makefileの中で用いる変数(マクロ)の設定
#### 1-1. 設定のしかた
　　[変数名]　=　[定義]

文法はこれだけ！超シンプル！
慣例として、変数名は**全て大文字**で書くこと。
#### 1-2. どんな変数が必要なの？
基本的によく使うのは以下。
必要に応じてドキュメントを読みながら変数を追加/変更すべし。
<img width="759" alt="スクリーンショット 2020-06-25 8.38.05.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/660621/47553077-f6df-bf55-6e83-f37a4e0c1104.png">

### 2. ルールの設定
#### 2-1. ルールの書き方(1)
<コマンド名>:
　　　　　<呼び出されるルール>

```
// 例：変数TEXTに入っている文章を表示させるshow_textルールを設定する
TEXT = "this is a sample."

show_text:
            echo $(TEXT)
```
```
% make
echo "this is a sample."
this is a sample.
```
- コマンド名(任意)に:(コロン)をつけて改行
- 変数を呼び出すときは**$()で囲む**
- **必ずタブを使って**、ルール内容を書く
- 「make」を実行すると、Makefileで一番最初に見つかるルールが適用される（この場合、「make」と「make show_text」の実行結果は同じになる）


【Appendix】
　makeすると、実行された結果だけでなくルール内容までコマンドラインに表示されてしまう。
　鬱陶しい場合は、ルールの文頭に@をつければ表示されなくなる。

```
TEXT = "this is a sample."

show_text:
            @echo $(TEXT)
```
```
% make
this is a sample.
```
----------
#### 2-2. ルールの書き方(2)
<コマンド名>: <必要なファイル>
　　　　<呼び出されるルール>

```
SRCS = main.c aaa.c bbb.c
OBJS = $(SRCS:%.c=%.o)

test: $(OBJS)
             gcc -o $@ $(OBJ)
```
main.cとaaa.cとbbb.cからオブジェクトファイル(.o)をそれぞれ生成してコンパイルするルール。

【Appendix】
■ **$(SRCS:%.c=%.o)**って何？
　%を使うことで、SRCSで指定された.cファイルを.oファイルにそれぞれ置換している。

■ gccで指定されている**$@**って何？
　Makefileで使用できる自動変数のひとつ。
　$@はターゲットファイル名を指す。

■ サフィックスルール
　C言語では必ず.cから.oファイルが作られる性質を利用してルール化したもの

```
.c.o:
            $(CC) -c $< -o $@
```
----------
#### 2-3. ルールの書き方(3)

<コマンド名>: <呼び出すコマンド名>

複数のコマンドを連続して呼び出すことができる。

```
TEXT = "recompile done!"

re: fclean all show_text
```
```
% make re
rm -f sample_A.o sample_B.o sample_C.o　　　　　　//fclean実行
rm -f hoge.a
gcc -c sample_A.c -o sample_A.o　　　　　　　　　　//all実行
gcc -c sample_B.c -o sample_B.o
gcc -c sample_C.c -o sample_C.o
ar rc hoge.a sample_A.o sample_B.o sample_C.o
ranlib hoge.a
recompile done!　　　　　　　　　　　　　　　　　　　　//show_text実行
```

#### 2-4. 設定しておくと便利な3つのルール
- **clean**: 
コンパイルによって生成されたオブジェクトファイル(.o)を削除してクリーンにする
- **fclean**:オブジェクトファイルに加えて、実行ファイルや静的ライブラリなども削除することでコンパイル前の状態までクリーンアップする
- **re**: fcleanを呼び出してから改めてコンパイルする(やり直し)

#参考
[トリビアなmakefile入門](http://www.jsk.t.u-tokyo.ac.jp/~k-okada/makefile/)
[Makefileの書き方(初心者向け)](https://qiita.com/kashiraWork/items/ff343d381d9477e89f3b)