Cコンパイラ作成入門のメモ #5 (Step8)
はじめに
こちらをやってみたときのメモを書いていく。
今回は分割コンパイルとリンク、Step8
Commit
Step8
調べたこと
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でこのコマンドが実行されるのか
- サフィックスルール
コンパイルオプション
- cc -cオプションって何?
- ld(1) によるリンクを行わず、ソースファイルごとに .o ファイルを作成する
- 参考: cc コンパイラオプション
- ld(1) によるリンクを行わず、ソースファイルごとに .o ファイルを作成する
- cc -oオプションって何?
- 出力ファイルに名前を付ける
ルールを分解して考える
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
流れ
- 9ccを作りたいからOBJSを見に行こう
- OBJSにはtokenize.oが含まれるぞ
- .oには.cが必要だからtokenize.cを見に行こう
- tokenize.cが更新されているからコンパイルしよう
cc -std=c11 -g -static -c -o tokenize.o tokenize.c
コマンドが叩かれる
CFLAGSで指定されている引数をつかってコマンドが叩かれる- 上記2. - 5. が全OBJS指定ファイル分繰り返される
- OBJSが揃ったから、いよいよコマンド行の実行をするぞ。
cc -o 9cc tokenize.o 9cc.o parse.o codegen.o
- おわり
ちなみに、$(OBJS): 9cc.h
の意味は
ちなみにOBJSは9cc.hに依存すると書いてあるので、もし9cc.hが更新されてたら、全.oは再度作り直しの意味
その他
- staticのお作法
- 同一ファイル内で定義された関数からしかアクセスされない関数はstaticをつける
- 参考:組込みソフト向けC言語コーディング規約|関数の定義と宣言 | ハングスタック
- 文字列リテラルとは
- ソースコード内にべた書きした文字列
- 仕様上は文字列リテラルはその領域の変更は不可
- ただ、定義上はchar型のポインタの扱いになるので、変更してもエラーは出ない
- なので char型ではなく、const char型を使用する
- 参考:文字列リテラルとは|「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典
- 参考:組込みソフト向けC言語コーディング規約|変数の定義と宣言 | ハングスタック
思ったこと
- tokenizerについてはファイル分けると書いてなかったが、Referenceも分けているので分けといた
- makeにもccにもユーザが指定せずとも勝手にやってくれていることがたくさんあって、それを理解するのが大変。
- 理解しなくてもいいのかもだけど。