我是在平时写源程序的时候看makefile的,平时有个习惯:就是将来几个月可能我会一直学习编程,我会将这个月的每一天使用目录文件保存在父目录下:
然后我想每天晚上想回过头来复习自己今天敲的代码,于是我要先一次性删除这些可执行文件吧,又要一个个的删;然后在一个个的编译很麻烦,然后现在温新C++,当前目录下既有*.c文件又有*.cpp文件,然后使用一个makefile,只能编译一种类型的源文件,因为C/C++本来就是一家人,所以我要想个法子,让当前文件下的所有C/C++源文件生成相应的可执行文件,删除的时候也可以选择删除目标文件,也可以选择删除全部(不包括源文件)。
例如:
这个目录下既有*.cpp文件又有*.c文件,要怎么实现上述的要求?
一、模式匹配
%.c : %.o #表示匹配零个或若干个字符,例:%.h 表示所有以“.h”结尾的文件。
并依次匹配上方依赖,目标也可以是变量 ,这些只能在规则中使用。
必须要记的三个自动变量: $@:当前模式下的目标文件 $<:当前模式下的第一个依赖 $^:当前模式下的所有依赖
二、makefile函数(一般makefile函数都要取返回值,才是有意义的操作)
wildcard( ./*.c) #返回当前目录下的所有 .c 源文件;
例子:src = $(wildcard( ./*.c)) #返回当前目录下的所有 .c 源文件, 并将其存放在变量src中;
obj = $(patsubst( ./%.c, ./%.o, $(src)))
patsubst() 模式匹配字符串替换:将src变量中的所有*.c 文件替换成 *.o 文件 ,$()去变量值,并将他们保存在obj 变量中。
ifdef-endif 、 ifndef-endif 、 ifeq-endif 、 ifneq-endif
ifdef-else-endif 、 ifndef-else-endif 、 ifeq-else-endif 、 ifneq-else-endif
同大多语言中语句类似,依次是非空为真, 空为真, 相等为真, 不相等为真
能够联合else使用, makefile中没有 else if!
$(findstring( <find>, <in> )) 查找字符串函数 ,在字符串<in>中查找<find>子串
三、结合具体的例子
我前期的makefile:
.PHONY : clean all #伪声明
cc = gcc #变量存储
CFLAGS = -Wall -g #编译选项,CFLAGS是make内置的变量
BIN = #这里填写自己的目标文件,且目标文件必须是去除尾缀后的名称
all : $(BIN)
%.o : %.c #模式匹配
$(cc) $(CFLAGS) -c $< -o $@ #还有三个必须记忆的自动变量
clean:
rm -rf *.o
四、实现
.PHONY:clean all clean_a
src = $(wildcard ./*.c) #获取当前目录下的所有C源文件
targetsc = $(patsubst %.c, %, $(src)) #利用模式匹配将变量名逐个截断成指定形式
objc = $(patsubst %.c, %.o, $(src)) #所有的依赖文件列表, 使用空格分隔
srcpp = $(wildcard ./*.cpp) #获取当前目录下的C++源文件
targetscpp = $(patsubst %.cpp, %, $(srcpp)) #利用模式匹配将变量名逐个截断成指定形式
objcpp = $(patsubst %.cpp, %.o, $(srcpp)) #所有的依赖文件列表, 使用空格分隔
pp = g++
cc = gcc
CPPFLAGS = -I ./
CFLAGS = -g -lpthread #若要一次性把当前目录下所有.cpp/.c文件都生成可执行文件 这里要将所有需要链接的库文件都添加进来
#也能使用多个变量,使此来区别链接哪些库!
#$(targetsc):%:%.o 表示我要告诉make你需要使用gcc来完成链接操作
ifeq ($(findstring .c, $(src)), .c)
all:$(targetsc)
$(targetsc):%:%.o
$(cc) $(CFLAGS) $< -o $@
$(objc):%.o:%.c
$(cc) $(CPPFLAGS) -c $<
endif
#$(targetscpp):%:%.o 表示我要告诉make你需要使用g++来完成链接操作
ifeq ($(findstring .cpp, $(srcpp)), .cpp)
all:$(targetscpp)
$(targetscpp):%:%.o
$(pp) $(CFLAGS) $< -o $@
$(objcpp):%.o:%.cpp
$(pp) $(CPPFLAGS) -c $<
endif
clean:
rm -rf $(objc) $(objcpp)
clean_a:
rm -rf $(objc) $(objcpp)
rm -rf $(targetsc) $(targetscpp)
检测:
PEACE....