Makefile基本语法
Makefile的意义:使项目实现自动化生成。
Makefile的作用:指导make按照规则编译和链接程序。
Makefile的工作方式
- 导入主Makefile
- 导入主Makefile调用的其他Makefile
- 初始化文件中的变量
- 推导隐晦规则,分析所有规则
- 为所有的目标文件创建依赖关系链
- 根据依赖关系,确定需要生成的目标
- 执行生成命令
Makefile的元素
- 显示规则
- 隐含规则
- 变量定义
- 文件指示
- 注释
Makefile的规则
一句话概括就是,只编译涉及修改的文件。
或者说是,依赖的源文件比目标文件新,则执行规则。
源按规则生成目标,写成如下形式:
目标:依赖的源
规则
规则前的分隔符要用Tab
,不能使用空格,否则会报错。
例:
hello : hello.o
hello.o : hello.c
cc -c hello.c
clean :
rm hello hello.o
规则中常用的通配符
变量 | 含义 |
---|---|
\* | 任意一个或者多个字符 |
? | 一个字符 |
[...] | [0-9]:0~9中任意一个数字;[a b c d]:a b c d中任意一个字符;[^ a b c d]:除a,b,c,d以外的字符 |
~ | 用户的home目录 |
隐含变量
变量 | 含义 |
---|---|
RM | rm -f |
AR | ar |
CC | gcc |
CXX | g++ |
ARFLAGS | AR命令的参数 |
CFLAGS | C语言编译器的参数 |
CXXFLAGS | C++语言编译器的参数 |
Makefile的语法
变量定义
exec = edit
temp = $(exec) $(objects)
objects := main.o other.o
$(exec) : $(objects)
cc -o $(exec) $(objects)
.....
clean :
rm $(temp)
注意=
和:=
的区别在于
:=
:只能使用前面定义好的变量=
:可以使用后面定义的变量
自动变量
自动变量 | 含义 |
---|---|
$@ | 目标集合 |
$% | 当目标是函数库文件时,表示其中的目标文件名 |
$< | 第一个依赖目标或逐个目标 |
$? | 比目标新的依赖目标集合 |
$^ | 所有依赖的集合,去除重复的目标 |
$+ | 所有依赖的集合,不去除重复的目标 |
变量替换
SRCS := main.c other.c
OBJS := $(SRCS:%.c=%.o)
变量追加值
SRCS := other.c
SRCS += main.c
命令前缀
前缀 | 说明 |
---|---|
无前缀 | 输出执行的命令以及命令执行的结果,出错则停止执行 |
@ | 只输出命令执行的结果,出错则停止执行 |
- | 忽略错误,继续执行 |
引用其他的Makefile
直接include
即可
include **/**/Makefile
伪目标
不生成文件,调用的时候需要显示的调用。
.PHONY: clean
clean :
-rm $(temp)
clean后面没有依赖,make不会自动执行里面的规则,需要显示地执行make clean
约定的伪目标
伪目标 | 含义 |
---|---|
all | 所有目标的目标,编译所有的目标 |
clean | 删除创建的文件 |
install | 安装已经编译好的程序 |
tar | 源程序打包备份 |
TAGS | 更新所有的目标 |
check或test | 测试makefile流程 |
常用参数
参数 | 说明 |
---|---|
--debug | 输出make的调试信息,可以带参数a, b, v |
-j 线程数 | 多线程 |
-C 目录 | 指定读取makefile的目录 |
-f=makefile | 指定需要执行的makefile |
-i , --ignore-errors | 执行时忽略所有的错误 |
-n , --just-print | 输出执行过程中的命令序列,但不执行 |
Makefile模板
SOURCE := $(wildcard *.c) $(wildcard *.cpp)
OBJS := $(patsubst %.c,%.o,$(patsubst %.cpp,%.o,$(SOURCE)))
TARGET := test
CC := gcc
LIBS :=
LDFLAGS :=
DEFINES :=
INCLUDE := -I.
CFLAGS := -g -Wall -O3 $(DEFINES) $(INCLUDE)
CXXXFLAGS:= $(CFLAGS)
.PHONY : everything objs clean veryclean rebuiild
everything : $(TARGET)
all : $(TARGET)
objs :$(OBJS)
rebuild : veryclean everything
clean :
rm -rf *.so
rm -rf *.o
veryclean: clean
rm -rf $(TARGET)
$(TARGET): $(OBJS)
$(CC) $(CXXFLAGS) -o $@ $(OBJS) S(LDFLAGS) $(LIBS)