用到4个文件:hello.h hello.cpp main.cpp Makefile
hello.h
#ifndef MAKE_FILE_TEST #define MAKE_FILE_TEST void hello(); #endif
hello.cpp
#include <iostream> #include "hello.h" using namespace std; void hello() { cout<<"hello Makefile!"<<endl; }
main.cpp
#include "hello.h" int main() { hello(); return 0; }
Makefile
cc=g++ target=main $(target):main.o hello.o $(cc) -o $(target) main.o hello.o main.o:main.cpp $(cc) -c -o main.o main.cpp hello.o:hello.cpp $(cc) -c -o hello.o hello.cpp .PHONY:clean clean: -rm -f $(target) *.o
执行make,会生成main程序,一切OK。
但是如果我们把hello.h中的void hello();注释掉,再次make,将会出现
make: `main' is up to date.正常情况下,是会出错的,因为main.cpp虽然包含了hello.h,但是展开hello.h之后,并没有void hello();这个函数声明,main.cpp会出现一个编译错误。但是这里的情况是所有的源文件(.CPP)都没有被重新编译,因为他们我们的makefile的规则中,没有指明这些源文件依赖了hello.h。
当然,我们可以修改Makefile,指明源文件依赖了hello.h。
cc=g++ target=main $(target):main.o hello.o $(cc) -o $(target) main.o hello.o main.o:main.cpp hello.h $(cc) -c -o main.o main.cpp hello.o:hello.cpp hello.h $(cc) -c -o hello.o hello.cpp .PHONY:clean clean: -rm -f $(target) *.o分别在main.o:main.cpp 和hello.o:hello.cpp后面添加了hello.h,指明这两个源文件依赖了hello.h。
执行make
g++ -c -o main.o main.cpp main.cpp: In function ‘int main()’: main.cpp:5:8: error: ‘hello’ was not declared in this scope make: *** [main.o] Error 1OK,错误出现了。
这个反例只是为了说明如何做,才能让头文件被修改时,依赖这个头文件的源文件被重新编译。
但是,如果一个工程中有几百个头文件(.h)和几百个源文件(.cpp),再假设这个工程根本不是自己写的,那该怎么办?难道打开所有的cpp文件看看他们包含了哪些头文件???
还好,编译器可以自动推导出来cpp依赖的头文件。
root@ubuntu:/home/workspace/Makefile/mf2# arm-linux-gcc -MM hello.cpp hello.o: hello.cpp hello.h root@ubuntu:/home/workspace/Makefile/mf2# g++ -MM hello.cpp hello.o: hello.cpp hello.h root@ubuntu:/home/workspace/Makefile/mf2# gcc -MM hello.cpp hello.o: hello.cpp hello.h root@ubuntu:/home/workspace/Makefile/mf2# cc -MM hello.cpp hello.o: hello.cpp hello.h可以看到,-MM选项可以让编译器去推敲依赖的文件。
继续往下之前,先来一个小插曲。Makefile可以自动推导编译命令,把hello.h中的void hello(); 取消注释。修改Makefile如下:
cc=g++ target=main $(target):main.o hello.o $(cc) -o $(target) main.o hello.o main.o:main.cpp hello.h hello.o:hello.cpp hello.h .PHONY:clean clean: -rm -f $(target) *.o执行make clean,然后make,可以看到程序被正确编译了。
root@ubuntu:/home/workspace/Makefile/mf2# make clean rm -f main *.o root@ubuntu:/home/workspace/Makefile/mf2# make g++ -c -o main.o main.cpp g++ -c -o hello.o hello.cpp g++ -o main main.o hello.o注意:目标规则中编译命令不能省略。即$(cc) -o $(target) main.o hello.o不能省略。这条命令中指明的编译器将是自动推敲出来的命令使用的编译器。
因为我们使用的是g++,所以自动推导出来的命令也使用g++。
OK,小插曲结束,继续。
利用-MM推敲依赖文件,修改Makefile。
cc=g++ target=main src=main.cpp hello.cpp $(target):main.o hello.o $(cc) -o $(target) main.o hello.o include $(src:.cpp=.d) %.d:%.cpp set -e;rm -f $@;\ $(cc) -MM $< >$@ .PHONY:clean clean: -rm -f $(target) *.o思路已断,未完待续