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 \

という話でした!