目次
1.オブジェクトファイルの作り方
2.べた書き
3.パターンルール
4.サフィックスルール
5.沼った部分
6.おわりに
オブジェクトファイルの作り方
(1)べた書き
$(TARGET) : $(OBJCS)
$(CC) -o $@ $^
test1.o : test1.c
$(CC) -c test1.c
test2.o : test2.c
$(CC) -c test2.c
main.o : main.c
$(CC) -c main.c
少し面倒ですが、ひとつづつ書いていく作戦です
gcc -c test1.c
gcc -c test2.c
gcc -c main.c
gcc -o target test1.o test2.o main.o
ターミナルでしっかりと実行されていることが確認できます
(2)パターンルール
$(TARGET) : $(OBJCS)
$(CC) -o $@ $^
%.o : %.c
$(CC) -c $<
パターンルールを用いたものです!
拡張子以外が同じ名前ファイルからオブジェクトファイルを作るというルールを追加しています。
TARGETを生成する時にtest1.oが無ければ「%」の部分に「test1」が置き換えられて実行されます。そのため(1)と同じ実行結果が得られます。
(3)サフィックスルール
$(TARGET) : $(OBJCS)
$(CC) -o $@ $^
.c.o :
$(CC) -c $<
サフィックスルールを用いたものです(時代遅れらしい)
やっていることはパターンルールと全く同じです。
なんとこれだけでさっきと同じように実行されます。
(依存関係の部分に何も書かなくていいのが不思議)
自分が沼った部分2つ
そもそもオブジェクトファイルを生成してなかった
SRCS = test1.c test2.c main.c
OBJCS = $(SRCS:.c=.o)
TARGET = target
$(TARGET) : $(OBJCS)
$(CC) -o $@ $^
上のコードを書くだけで実行ファイルを生成できると思っていましたが下記のエラーが出てしまい、実行ファイルを生成できません。
No rule to make target 'test1.o', needed by 'target'. Stop.
ところが不思議なことにechoでOBJCSを見ると中身があるではないですか?!
test1.o test2.o main.o
OBJCSの中身にはしっかりとオブジェクトファイルが入っているのになぜtest.oが無いとエラーで言われるのでしょうか?
OBJCS = $(SRCS:.c=.o)
それはこの部分はSRCSの値を受け取り.cを.oに置き換えた文字列リストを作っているだけだからです。
そのため、TAEGETを作る際にtest.oという文字列のファイルねーじゃねーーか(# ゚Д゚)と怒られてしまうわけです。。
そこで実際にOBJECTを作る必要があるのです。
間違った作り方
$(TARGET) : $(OBJCS)
$(CC) -o $@ $^
$(OBJCS) : $(SRCS)
$(CC) $^ -c -o $@
ターゲットと依存関係について学んだ自分はこのように書きました
もちろんエラーが起きるのですが、はじめは原因がわからずにいました
makefileが悪いのではなくgccのコマンドが原因です。
gcc test1.c test2.c main.c -c -o test1.o
このようなコマンドを実行することになりエラーが起きてしまいます。
一度に3種類のオブジェクトファイルを作るgccコマンドは無いので上の方法で作るしかないです。もちろんSRCとOBJECTが一種類の場合は実行できます。
おわりに
やっていることは同じなのに複数の書き方があると、どれが正しいのか不安になり不要なことをしてしまいがちですよね、、上に書いた3つは同じ結果が得られるので好きな方法を使ってみてください!
参考文献
サフィックスルールとパターンルールについて
https://www.miraclelinux.com/tech-blog/q1kxz6
サフィックスルールについて
http://nenya.cis.ibaraki.ac.jp/TIPS/makefile2.html
makefileの入門
https://qiita.com/mizcii/items/cfbd2aa17f6b7517c37f