语法规则
目标 … : 依赖 …
命令1
命令2
. . .
目标 就是要生成的文件
依赖 就是所需要的文件
命令 即通过执行命令由依赖文件生成目标文件
如果要生成多个文件,则会用到all
all: target1 target2 target3
target1:
编译规则1
target2:
编译规则2
target3:
编译规则3
变量
$符号表示取变量的值,当变量名多于一个字符时,使用"( )"
$^ 表示所有的不重复依赖文件
$< 代表第一个依赖文件
$@ 表示生成的目标文件
$+ 所有的依赖文件,以空格分隔
$* 不包括扩展名的目标文件名称
$? 所有时间戳比目标文件晚的依赖文件 空格隔开
%匹配符 <%.0:%.c>
@后加shell命令,可以执行功能
系统常量(make -p可查看)
AS | 汇编程序的名称 | 默认as
CC | C编译器名称 | 默认cc
CPP | c预编译器名称 | 默认cc -E
CXX | C++编译器名称 | 默认g++
RM | 文件删除程序别名 | 默认 rm -f
变量赋值
= 普通赋值,变量的值是最后被指定的值
:= 表示直接赋值,赋予当前位置的值
a := 1
b := a
a := 2 b的值还是1
?= 会判断是否有被赋值,如果没有被赋值那么就会将=右侧值赋予它,反之复制无效,只保留之前的旧值
预定义变量
CC:c编译器的名称,默认值为cc
去除回显
‘’’
@echo “clean done!”
‘’’
函数
通配符
SRC = $(wildcard ./*.c) (匹配目录下所有.c 文件,并将其赋值给SRC变量)
OBJ = $ $(patsubst %.c, %.o, $(SRC))
※示例:
SRC = $(wildcard *.c) (列出的文件是否存在,把存在的文件都列出来)
OBJ = $(patsubst %.c, %.o, $(SRC))
ALL: hello.out
hello.out: $(OBJ)
gcc $(OBJ) -o hello.out
%.o: %.c
gcc -c $< -o $@
foreach
$(foreach var,list,text)
对 list 中的每一个元素,取出来赋给 var,然后把 var 改为 text 所描述的形式。
wildcard
pattern 所列出的文件是否存在,把存在的文件都列出来
src_files := $( wildcard *.c)
// 最终 src_files 中列出了当前目录下的所有.c 文件
filter
把 text 中符合 pattern 格式的内容,filter(过滤)出来、留下来
obj-y := a.o b.o c/ d/
DIR := $(filter %/, $(obj-y)) //结果为:c/ d/
filter-out
与filter 相反把过滤出来的扔掉
patsubst
$(patsubst pattern,replacement,text)
寻找’text’中符合格式’pattern’的字,用’replacement’替换它们。'pattern’和`replacement’中可以使用通配符
subdir-y := c/ d/
subdir-y := $(patsubst %/, %, $(subdir-y)) // 结果为:c d
字符串替换和分析函数
$(subst from,to,text)//用to替换text中的from
$(strip string)//去掉前导和结尾空格,并将中间的多个空格压缩为单个空格
$(findstring find,in) //in中找find a b c 找c
$(sort list) //按字母顺序排序
文件名函数
$(dir names...) //抽取‘names...’中每一个文件名的路径部分
$(dir src/foo.c hacks)
结果为‘src/ ./’
$(notdir names...) //抽取‘names...’中每一个文件名中除路径部分外一切字符(真正的文件名)
$(notdir src/foo.c hacks)
结果为‘foo.c hacks’
$(suffix names...) //抽取‘names...’中每一个文件名的后缀
$(suffix src/foo.c src-1.0/bar.c hacks)
结果为‘.c .c’。
$(basename names...) //抽取‘names...’中每一个文件名中除后缀外一切字符
$(basename src/foo.c src-1.0/bar hacks)
结果为‘src/foo src-1.0/bar hacks’。
$(addsuffix suffix,names...) //suffix是一个后缀,加在每一个name后面
$(addsuffix .c,foo bar)
结果为‘foo.c bar.c’
$(addprefix prefix,names...) //prefix 是一个前缀名,加载每一个name的前面,将文件名串联起来
$(addprefix src/,foo bar)
结果为‘src/foo src/bar’
伪目标
伪目标只是一个标签,clean是个伪目标没有依赖文件,只有用make来调用时才会执行当目录下有与make 命令 同名的文件时 执行make 命令就会出现错误。解决办法就是使用伪目标
SRC = $(wildcard *.c)
OBJ = $(patsubst %.c, %.o, $(SRC))
ALL: hello.out
hello.out: $(OBJ)
gcc $< -o $@
$(OBJ): $(SRC)
gcc -c $< -o $@
clean:
rm -rf $(OBJ) hello.out
.PHONY: clean ALL
指定头文件路径
假设头文件在
/home/develop/include
可以通过-I指定
-I/home/develop/include
将该目录添加到头文件搜索路径中
CFLAGS=-I/home/develop/include
指定库文件路径
用-L指定
LDFLAGS=-L/usr/lib -L/path/to/your/lib
告诉链接器要链接哪些库文件,使用"-l"(小写L)如下:
LIBS = -lpthread -liconv
示例:
objs = a.o b.o c.o
dep_files := $(patsubst %,.%.d, $(objs))
dep_files := $(wildcard $(dep_files))
test: $(objs)
gcc -o test $^
ifneq ($(dep_files),)
include $(dep_files)
endif
%.o : %.c
gcc -c -o $@ $< -MD -MF .$@.d
clean:
rm *.o test
distclean:
rm $(dep_files)
.PHONY: clean
make执行的命令
提升
Makefile 中编译动态链接库
test:libtest.so
gcc -ltest -L./ test.cpp -o test
libtest.so:
gcc -fPIC -shared sotest.c -o libtest.so
clean:
rm -r *.so test
Makefile 中编译静态库
多目录公共Makefile
子目录
公共头