Linux中编写自动编译的makefile的方法,以及详细解析。

makefile基本的编写方法在此就不在赘述,这里重点解析一下makefile的自动编译方法。
移植的时候去掉注释,修改编译器选项和相关路径即可。

CXX := g++ //表示使用何种编译器
CXXFLAGS = -g -D_DEBUG //编译器选项。如果要使用gdb调试就必须加上-g,而-D_DEBUG是为了与VC6自带的宏兼容,方便在VC6开发的时候写调试代码。release版就带-O3
INCLUDE = -I./include //包含头文件的搜索目录
LIBS = //静态和动态链接库的搜索目录
LIB = 

SRC_PATH = ./src //源文件目录
OBJ_PATH = ./debug

SRCS = $(wildcard $(SRC_PATH)/*.cpp)   //展开所有的源文件
OBJS = $(patsubst $(SRC_PATH)/%.cpp, $(OBJ_PATH)/%.o, $(SRCS))    //将源文件.cpp后缀替换成.o

TARGET = makeTest

.PHONY:all clean                //声明all和clean是伪指令

all:$(TARGET)
$(TARGET):$(OBJS)
$(CXX) $(CXXFLAGS) $(OBJS) $(LIB) $(LIBS) -o$(TARGET)

include $(OBJS:.o=.d) //将所有.o后缀替换成.d

$(OBJ_PATH)/%.d : $(SRC_PATH)/%.cpp
@set -e; rm -f $@; \
$(CXX) -MM $(CXXFLAGS) $(INCLUDE) $< > $@.$$$$; \
sed 's,.*\.o[ ]*:,$*.o $@ :,g'< $@.$$$$ > $@; \       
rm -f $@.$$$$                 //删除临时文件$@.$$$$
$(CXX) $(CXXFLAGS) $(INCLUDE) -c -o $(OBJ_PATH)/$*.o $<  //这句才是最后真正的编译


clean:
rm -f $(TARGET) $(OBJ_PATH)/*        //清除中间文件

网上找了很久都没有找到上面正则表达式的完整解释,总是到了关键地方就说这里太复杂不细讲,作用就是……
在此我就详细解释一下这段具体语义。
//set -e表示shell调用其他命令的时候遇到错误直接返回,加@表示不显示命令本身
//-MM……$<参数表示生成规则的依赖文件名,并保存到$@.$$中。$@表示规则的目标文件(这里就是(OBJ_PATH)/%.d),.$$表示生成和线程相关的id号,为了防止重命名。因为$在makefile中也特殊涵义,所以用$$转移,两个$$就需要$$$$来表示。
//这里用到了makefile的sed命令。读取$@.$$$$中的内容送给sed命令处理,最后输出到$@中。开头的s表示替换,结尾的g表示替换全部,否则只会执行一行操作。's,xxx,zzz,g'表示将xxx替换成zzz,这里就使用了正则表达式。.*\.o[]*:表示匹配“以任意个字符开头并后接.o后缀再跟任意个空格符,再以:结尾”的字符串,如asda.o  :成立。$*.o $@:这句表达式中的$*表示匹配目标中的"%"锁代表的值(这里就是(OBJ_PATH)/%.d中%的值),$@表示规则的目标文件(这里就是(OBJ_PATH)/%.d)。所以这句语句的完整语义举例可解释为:
main.o : main.cpp a.h b.h c.h
替换成
main.o main.d : main.cpp a.h b.h c.h

//注意,生成依赖文件的那四条语句其实是完整的一行!为了美观才分成了四行,并用\换行,所以这里的\是不能省略的!



你可能感兴趣的:(makefile,Linux)