用到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 1
OK,错误出现了。
这个反例只是为了说明如何做,才能让头文件被修改时,依赖这个头文件的源文件被重新编译。
但是,如果一个工程中有几百个头文件(.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
思路已断,未完待续