(目录)
一、系统变量
系统变量 | 描述 |
---|---|
$* | 不包括扩展名的目标文件名称 |
$+ | 所有的依赖文件,以空格分隔 |
$< | 表示规则中的第一个依赖项 |
$? | 所有时间戳比目标文件晚的依赖文件,以空格分隔 |
$@ | 目标Target的完整名称 |
$^ | 所有不重复的依赖文件,以空格分隔 |
$% | 如果目标是归档成员,则该变量表示目标的归档成员名称 |
二、系统常量
可用 make -p 查看
系统常量 | 描述 | 默认值 |
---|---|---|
AS | 汇编程序的名称 | 默认值为 as |
CC | C编译器名称 | 默认值为 cc |
CPP | C预编译器名称 | 默认值为 cc -E |
CXX | C++编译器名称 | 默认值为 g++ |
RM | 文件删除程序别名 | 默认值为 rm -f |
注意:#为注释。
三、自定义变量
定义:VAR_NAME = VALUE 使用:$(VAR_NAME) 或 ${VAR_NAME}
注意:makefile中的变量是大小写敏感的。
四、伪目标和模式匹配
makefile默认先处理第一个目标。
1. 伪目标
.PHONY:clean
声明目标为伪目标之后,makefile将不会判断目标是否存在或该目标是否需要更新。
2. 模式匹配
符号 | 说明 | 备注 |
---|---|---|
%.o:%.cpp | .o依赖于对应的.cpp文件 | 通配符 |
wildcard | $(wildcard ./*.cpp) 获取当前目录下所有的.cpp文件名 | 空格分隔 |
patsubst | $(patsubst %.cpp, %.o, ./*.cpp) 将xxx.cpp文件名替换成对应的xxx.o文件名 |
五、基本使用
# 目标: 依赖
# $@ 目标;$< 第一个依赖;$^ 所有依赖
# 通过include指令可以包含其他makefile文件
# include ../makefile
# 不使用默认值cc
#CC=gcc
# 注意:hello后边#之前的空格也会作为赋值字符串的一部分
TARGET=hello # := 可以阻止递归展开的效果,即只展开一次再赋值(从上到下逐步展开)
# 当前目录下的所有.cpp文件名都放到SRC变量里
SRC=$(wildcard *.cpp)
# path路径替换:把变量SRC中的文件名(.cpp)替换为.o结尾并赋值给OBJ变量
OBJ=$(patsubst %.cpp, %.o, $(SRC))
CXXFLAGES=-c -Wall -g
$(TARGET): $(OBJ)
$(CXX) -o $@ $^
%.o: %.cpp
$(CXX) $(CXXFLAGES) $< -o $@
.PHONY: clean
clean:
$(RM) $(OBJ) $(TARGET)
在包含多文件的情况下可以采用如下方法避免重复赋值带来的递归展开问题
ifndef TARGET
TARGET:=hello
endif
六、调用shell
PWD:=$(shell pwd)
七、嵌套调用
# -C 指定目录,调用其中的Makefile。或者使用-f 指明文件名。
all:
$(MAKE) -C ./dir1
$(MAKE) -C ./dir2
$(MAKE) -C ./dir3 -f makefile03
clean:
make -C ./dir1 clean
make -C ./dir2 clean
make -C ./dir3 -f makefile03 clean
或者优化为
DIR=dir1 dir2 dir3
.PHONY:$(DIR) clean
all:$(DIR)
$(DIR):
make -C $@
clean:
@echo $(shell for dir in $(DIR); do make -C $$dir clean; done)
八、makefile中的条件判断
判断指令 | 描述 | 返回值 |
---|---|---|
ifeq | 判断是否相等 | 相等返回true,不相等返回false |
ifneq | 判断是否不相等 | 相等返回true,不相等返回false |
ifdef | 判断变量是否存在 | 存在返回true,不存在返回false |
ifndef | 判断变量是否不存在 | 不存在返回true,存在返回false |
ifeq,ifneq与条件之间要有空格,否则报错。 没有elseif的用法,如果要实现,则必须使用嵌套。
ifeq ($(A), 123)
RET1:=yes
else
ifneq ($(B), balabala)
RET1:=p1
else
RET1:=p2
endif
RET1:=no
endif
ifdef C
C:=123
else
C=123
endif
ifndef PARAM_NAME
PARAM_NAME=mufasa
endif
注意:make可以通过命令行参数PARAM_NAME=VALUE向makefile中的PARAM_NAME自定义变量传参。 make PARAM_NAME=VALUE
九、makefile中的循环
.PHONY:show
VAR=a b c d
FILE=$(foreach V, $(VAR), $V.txt)
ATTR=$(wildcard *.c)
show:
@echo $(FILE)
@for A in $(ATTR); do ls -l $$A; done;
显然使用shell命令的方式灵活性更强。
十、自定义函数
.PHONY:show
define func
@echo func
@echo $(1) $(2)
endef
show:
$(call func, 123, abc)
函数没有返回值。
十一、install的实现
.PHONY:install
install:
install -o bee -g bee -m 666 --suffix=.old hello.asm ./dir/hello.asm
以上命令的解释如下:
- -o bee:将目标文件所有者设置为bee用户。
- -g bee:将目标文件属组设置为bee。
- -m 666:将目标文件的权限设置为rw-rw-rw-。
- hello.asm:源文件的名称。
- ./dir/hello.asm:目标文件的路径名。
- --suffix=.old:如果目标文件已经存在,则将目标文件备份为hello.asm.old,并将新的源文件复制为hello.asm。