Cコンパイラ作成入門のメモ #5 (Step8)

はじめに

こちらをやってみたときのメモを書いていく。

www.sigbus.info

今回は分割コンパイルとリンク、Step8

Commit

Step8

github.com

調べたこと

make

コード

CFLAGS=-std=c11 -g -static
SRCS=$(wildcard *.c)
OBJS=$(SRCS:.c=.o)

9cc: $(OBJS)
        $(CC) -o 9cc $(OBJS) $(LDFLAGS)

$(OBJS): 9cc.h

test: 9cc
        ./test.sh

clean:
        rm -f 9cc *.o *~ tmp*

.PHONY: test clean
}

実行されるコマンド

$ make
cc -std=c11 -g -static   -c -o tokenize.o tokenize.c
cc -std=c11 -g -static   -c -o 9cc.o 9cc.c
cc -std=c11 -g -static   -c -o parse.o parse.c
cc -std=c11 -g -static   -c -o codegen.o codegen.c
cc -o 9cc tokenize.o 9cc.o parse.o codegen.o 

理解したこと

Makefileの前提知識

  • コロン(:)で区切られた行と、タブでインデントされた0行以上のコマンドの行が1つのルールを構成する
    • コロンの前の名前のことを「ターゲット」という -コロンの後の0個以上のファイル名のことを依存ファイルという
  • .PHONY
    • ダミーのターゲットを表している
    • make test や make cleanのtest,cleanというのは、そういう名前のファイルを作成するために指定しているわけでは無いが、makeにはそれがわからない。
    • .PHONYで指定してあげることで、本当にそういう名前のファイルを作りたいわけではなく、指定されたターゲットのファイルが存在しているかどうかに関わらずルールのコマンドを実行するべき。ということをmakeに伝えることができる。

なぜこのMakefileでこのコマンドが実行されるのか

コンパイルオプション

ルールを分解して考える

9cc: $(OBJS)
        $(CC) -o 9cc $(OBJS) $(LDFLAGS)

のルールでmakeがやることは?

変数

SRCSに含まれるのは?⇒tokenize.c,9cc.c, parse.c, codegen.c
OBJSに含まれるのは?⇒tokenize.o,9cc.o, parse.o, codegen.o

流れ
  1. 9ccを作りたいからOBJSを見に行こう
  2. OBJSにはtokenize.oが含まれるぞ
  3. .oには.cが必要だからtokenize.cを見に行こう
  4. tokenize.cが更新されているからコンパイルしよう
  5. cc -std=c11 -g -static -c -o tokenize.o tokenize.c コマンドが叩かれる
    CFLAGSで指定されている引数をつかってコマンドが叩かれる
  6. 上記2. - 5. が全OBJS指定ファイル分繰り返される
  7. OBJSが揃ったから、いよいよコマンド行の実行をするぞ。
    cc -o 9cc tokenize.o 9cc.o parse.o codegen.o
  8. おわり

ちなみに、$(OBJS): 9cc.h の意味は
ちなみにOBJSは9cc.hに依存すると書いてあるので、もし9cc.hが更新されてたら、全.oは再度作り直しの意味

その他

思ったこと

  • tokenizerについてはファイル分けると書いてなかったが、Referenceも分けているので分けといた
  • makeにもccにもユーザが指定せずとも勝手にやってくれていることがたくさんあって、それを理解するのが大変。
    • 理解しなくてもいいのかもだけど。