Makefile学习笔记05|自动推导与伪目标
自动推导
自动推导涉及到.o文件。开始之前需要先删除掉之前产生的.o文件和可执行文件first_make。
rm *.o first_make
再修改一下makefile文件。
# ~/make/src/first_make/makefile
# $^ 依赖 不重复
# $@ 目标
# @ 不显示命令执行
# - 发生错误后继续向后执行
TARGET=first_make
LIBS=-lpthread
# 修改一下上一节的makefile文件,把.cpp改成.o
$(TARGET):first_make.o xdata.o
@#内部注释,加@防止被打印出来
@echo "begin build $(TARGET)"
@$(CXX) $^ -o $@ $(LIBS)
@echo "$(Target) build success!"
执行结果如下:
g++ -c -o first_make.o first_make.cpp
g++ -c -o xdata.o xdata.cpp
begin build first_make
first_make build success!
这里make就进行了自动推导,虽然我们没有明确地告诉make两个.o文件该如何生成,自动还是自动为我们生成了两个.o文件。然而,make的能力也是有限的。为了进一步学习,我们创建一个目录:~/make/src/test_gcc,在此路径下新建文件:test.h。之后让first_make.cpp引用头文件test.h中的内容。
// ~/make/src/test_gcc/test.h
// 对于makefile文件来讲,相对路径为../test_gcc
// 该头文件没有什么实际的内容,只做一个宏定义
#define CONF_PATH "/usr/local/"
//first_make.cpp
#include <iostream>
#include <thread>
#include "xdata.h"
#include "test.h"
using namespace std;
void ThreadMain()
{
cout<<"Thread Main"<<endl;
}
int main(int argc, char *argv[])
{
thread th(ThreadMain);
cout <<"test make "<<endl;
th.join();
XData d;
return 0;
}
这时我们再编译就会出现问题:fatal error: test.h: No such file or directory。我们可以手动指明头文件的路径,操作如下:
g++ -c -o first_make.o first_make.cpp -I../test_gcc
手动添加头文件路径当然不能满足我们的需求,还是要修改makefile文件。改过之后就可以正确地完成编译了。
# ~/make/src/first_make/makefile
# $^ 依赖 不重复
# $@ 目标
# @ 不显示命令执行
# - 发生错误后继续向后执行
TARGET=first_make
LIBS=-lpthread
OBJS=first_make.o xdata.o
CXXFLAGS=-I../test_gcc
# 修改一下上一节的makefile文件,把.cpp改成.o
$(TARGET):$(OBJS)
@#内部注释,加@防止被打印出来
@echo "begin build $(TARGET)"
@$(CXX) $^ -o $@ $(LIBS)
@echo "$(Target) build success!"
伪目标
新的需求来了,有时我们希望缩小工程的体积或者更新源代码,这就需要删除掉工程中的.o、.i等中间文件。这样就引出了这一章的主题:伪目标。伪目标不同于一般目标的最大特点是伪目标一般没有目标文件生成。makefile代码如下:
# ~/make/src/first_make/makefile
# $^ 依赖 不重复
# $@ 目标
# @ 不显示命令执行
# - 发生错误后继续向后执行
TARGET=first_make
LIBS=-lpthread
OBJS=first_make.o xdata.o
CXXFLAGS=-I../test_gcc
# 修改一下上一节的makefile文件,把.cpp改成.o
$(TARGET):$(OBJS)
@#内部注释,加@防止被打印出来
@echo "begin build $(TARGET)"
@$(CXX) $^ -o $@ $(LIBS)
@echo "$(Target) build success!"
# 定义伪目标clean
clean:
$(RM) $(OBJS) $(TARGET)
# 定义完还要声明
.PHONY: clean *clean
要运行伪目标时只需要输入命令:make clean即可。如果make后不加任何目标名,则执行第一个目标,即$(TARGET)。