这里简单说一下Makefile的写法,主要是个人的喜欢写法,复杂的语法部门没有加入,只是一些简单的入门,同时也是我经常使用的。
常用的函数
在Makefile中也是有一些我们常用的函数的,简单的比如:
addprefix
主要功能就是增加前缀,用法如下:
$(addprefix PREFIX,NAMES...)
例子:
$(addprefix src/,foo.c bar.c)
得到的列表为src/foo.c src/bar.c
addsuffix
增加后缀,用法与addsuffix
类似,用法如下:
$(addsuffix PREFIX,NAMES...)
例子:
$(addsuffix c,foo bar)
得到的列表为foo.c bar.c
wildcard
获取当前目录下符合条件的文件,也是使用一个简单的例子:
SRC_FILES = $(wildcard *.c *.cpp)
此时会将文件夹内的c和cpp文件赋值给SRC_FILES
,后续可以使用这个变量进行处理。wildcard
的语法是:
$(wildcard PATTERN...)
在Makefile中,他被展开为已经存在的,使用空格分开的并且匹配此模式的文件列表。通常会使用通配符进行匹配,如果匹配不到任何文件,则会返回空。
patsubst
这个函数主要用匹配替换,还是先出一个例子:
OBJS = $(patsubst %.c,%.o,$(patsubst %.cpp,%.o,$(SRC_FILES)))
上面这个离职中,OBJS的值会是$(SRC_FILES)
中所有文件的名字,但是以.o
最为扩展名。patsubst
的语法规则如下:
$(patsubst %.c,%.o,$(file_list))
patsubst有三个参数,分别是:
1. 第一个参数是需要匹配的样式
2. 第二个参数是替换后的样式
3. 第三个参数是以空格隔开的需要处理的列表
一般都是用于生成.o
的列表,然后通过依赖关系依次展开。
内置变量
变量 | 变量含义 |
---|---|
$@ | 扩展单钱的目标文件名 |
$< | 扩展成依赖的列表中的第一个依赖文件名 |
$^ | 扩展成整个依赖的列表(去重) |
$? | 表示比目标还要新的文件列表 |
$% | 仅当目标是函数库文件中,表示规则中的目标成员名。 |
$+ | 和$^ 类似,是所有依赖目标的集合,但是并不去重 |
$* | 这个变量表示目标模式中% 以及之前的部分。 |
下面三个并不常用,也比较难理解,所以我加了一个例子,这里把%.o:%.c
展开写,并为了区分$<
和$^
稍作修改:
cpp_func.o : cpp_func_1.cpp cpp_func_2.cpp
此时,
- $@
| cpp_func.o
- $<
| cpp_func_1.cpp
- $^
| cpp_func_1.cpp cpp_func_2.cpp
- $?
| cpp_func_1.cpp cpp_func_2.cpp
- $%
| 这种情况下应该是空的
- $*
| cpp_func(但是上面的没有使用%.o
这种形式去推到,上面那么写并不一定会是这样的)
外部变量赋值
这个比较简单,用一个比较简单的例子就可以很明确了:
SRC_FILE = $(in)
在执行make的时候,在shell里面如下输入即可:
make all in=hello_world.cpp
简单的一个Makefile实例
XX = g++
CC = g++
CFLAGS = -g
CFLAGSXX = -g --std=c++11
INC = -I./
LIB = -L./
TARGET = test_hello
SRC_FILES = $(wildcard *.c *.cpp)
OBJS = $(patsubst %.c,%.o,$(patsubst %.cpp,%.o,$(SRC_FILES)))
%.o:%.c
@echo "excu $(CC) -c $< -o $@ $(CFLAGS) $(INC)"
$(CC) -c $< -o $@ $(CFLAGS) $(INC)
%.o:%.cpp
@echo "excu $(XX) -c $< -o $(CFLAGSXX) $(INC)"
$(XX) -c $< -o $@ $(CFLAGSXX) $(INC)
$(TARGET):$(OBJS)
@echo "make $@ by $^"
$(XX) $^ -o $@ $(CFLAGS) $(INC) $(LIB)
$(RM) *.o $(OBJS)
all:$(TARGET)
@echo "make all"
clean:
$(RM) $(TARGET) $(OBJS)
test:$(TARGET)
@echo "make test"
./$(TARGET)