makeの動作gccとg++と暗黙のルール。
cをずーっと書いていて、c++に移行した再のmakeで罠ったので、書き留めておく。
簡潔、明瞭、寛大に書くと、
GNU makeは.oをコンパイルする際に、ソースファイルが.cの場合はgccが、.cppの場合はg++が、暗黙のルールでコンパイラとして選ばれる。
gccが暗黙のルールとして呼び出された場合、$(CFLAGS)が付属してコンパイルされる。
g++が暗黙のルールとして呼び出された場合、$(CPPFLAGS)が付属としてコンパイルされる。
ということを理解、認知、納得、勉強できたということなのなのです!
もっと詳しくは、
GNU make 日本語訳(Coop編) - 暗黙ルールの利用
に猛々しく、歴々と、漫然にして、明瞭に書かれている。
以下は、僕がいかにダメかということの証明が書かれています。
コンパイルが通らないって話。
#include "stdio.h" #include "test.h" int main() { test(); return 0; }
main.cがこのような内容だった時。
gccmakeする際に、よく書かれるMakefileを下に示してみる。
# gcc test # PROG=testexe CFLAGS+= \ -I. \ -I./header \ SRC= \ main.c OBJ=$(SRC:.c=.o) CC=gcc -g -Wall all : $(OBJ) $(PROG) : $(OBJ) $(CC) $(CFLAGS) -o $(PROG) $(OBJ) clean : rm -vf *.o $(PROG) ##### main.o: main.c ./header/test.h
これは、普通にmakeが通る。
次にc++用にmain.cをmain.cppにしてMakefileも書き換えてみる。
#include <iostream> #include "test.h" int main() { test(); return 0; }
# g++ test # PROG=testexe CFLAGS+= \ -I. \ -I./header \ SRC= \ main.cpp OBJ=$(SRC:.cpp=.o) CC=g++ -g -Wall all : $(OBJ) $(PROG) : $(OBJ) $(CC) $(CFLAGS) -o $(PROG) $(OBJ) clean : rm -vf *.o $(PROG) ###### main.o: main.cpp ./header/test.h
罠ったと書いたからにはこれでmakeが通ってもらっては困るし、実際に通らない。
もう通らないとなった時点で、僕の頭は大パニック!
うーうーうー言いながら、半ば諦めムードで、GNU make 日本語訳(Coop編) - 目次を見て、Makefileの根本を勉強し直したりしちゃったりして、もう何が悪いのかわからなくなってしまった。
てことで、先輩に見てもらいながら「なんでなんですかー」とか言いながら頭の整理に入った途端、なんとなぁくそうなんじゃないかなぁというところを発見!というか認知!
main.oをコンパイルする際に
g++ -c -o main.o main.cpp
とログに出ている。
これは、make側が.oをコンパイルする際に暗黙のルールで、cppの場合はg++をcの場合はgccを使うみたいだ。
ということがわかった。
cの場合のログを見ると
gcc -c -o -I. -I./header main.o main.c
とログに出ている。
暗黙のルールで使用されるコンパイラがgccの場合はCFLAGSがきちんと適応されていることがわかった。
ということは、g++に相当するCFLAGS的なものがあるはずであり、ググったら、至極簡単に、それはCPPFLAGSだということがわかり、c++のMakefile内のCFLAGSをCPPFLAGSに変更するだけで、コンパイルが通るようになった。
- CFLAGS+= \ + CPPFLAGS+= \ -I. \ -I./header \
という話でした!