makefile
makefile的三要素:
目标:要生成的目标文件
依赖:目标文件由哪些文件生成
命令:通过执行命令由依赖文件生成目标
规则:
目标:依赖
<Tab> 命令
执行make指令,默认是生成第一个目标
原理 :
1. 当依赖文件不存在,如果有的依赖文件不存在,则向下搜索规则,看是否有生成该依赖文件的规则,
如果有规则用来生成该依赖文件,则执行规则中的命令生成依赖文件;如果没有规则用来生成该依赖文件,则报错。
2. 当依赖文件存在,如果所有的依赖文件都存在,则检查规则中依赖文件是否比目标新,如果任一依赖文件都比目标文件新,则目标必须更新。
变量:
1. 普通变量:用户自定义的变量,要见名知义
makefile中变量一般有三种赋值,“=”赋值表示变量的值是整个makefile中最后被指定的值。
OBJ_A = A
OBJ_B = $(OBJ_A) B
OBJ_A = AA
all:
@echo $(OBJ_B)//输出AA B,不是A B,在执行make指令时,会把整个makefile展开,来决定变量的值
“:=”表示直接赋值,赋予当前位置的值
OBJ_A := A
OBJ_B := $(OBJ_A) B
OBJ_A := AA
all:
@echo $(OBJ_B)//输出A B,即根据当前位置进行赋值,“:=”才是真正意义上的直接赋值
“?=”表示如果该变量没有被赋值,赋予等号后面的值
VAR := B
VAR ?= A
all:
@echo $(VAR)//输出B
2. 自动变量:
函数
Makefile中的%表示通配符,而*表示任意字符,举例,%.o表示匹配所有的.o文件,注意是用于匹配的。*.o是表示所有的.o文件
用途方面:前者一般用作目标,后者一般用作删除
wildcard:
SRC = $(wildcard ./*.c)//当前目录下的所有.c文件,并将其赋值给SRC变量
pstsubst:$(patsubst 原模式, 目标模式, 文件列表)
OBJ = $(patsubst %.c, %.o, $(SRC))//将SRC中的所有.c文件替换为.o文件,并赋值给OBJ变量
链接库
Makefile中,如果一个规则没有命令或者依赖,并且它的目标不是一个存在的文件名。在执行此规则时,目标总会被认为是最新的。
就是说: 这个规则一旦被执行,make就认为它的目标已经被更新过。这样的目标在作为一个规则的依赖时,因为依赖总被认为被更新过,因此作为依赖所在的规则中定义的命令总会被执行。
all: FORCE @echo "****all: FORCE***" FORCE:; .PHONY: FORCE
在make后,all依赖FORCE,FORCE没有命令或者依赖,并且它的目标不是一个存在的文件名,在执行此规则时,目标总会被认为是最新的。所以这个规则一旦被执行,make就认为它的目标已经被更新过。
多文件管理:
fun目录下的Makefile
#获取当前目录下所有的.c文件 SRC=$(wildcard *.c) #准备把当前目录下的.c转换为.o文件 ===>OBJ=fun.o OBJ=$(patsubst %c,%o,$(SRC)) all:$(OBJ) $(OBJ): %.o:%.c $(CC) $(INCLUDE_DIR) -c $^ -o $(OBJ_DIR)/$@
global目录下的Makefile
#获取当前目录下所有的.c文件 SRC=$(wildcard *.c) #准备把当前目录下的.c转换为.o文件 ===>OBJ=fun.o OBJ=$(patsubst %c,%o,$(SRC)) all:$(OBJ) $(OBJ): %.o:%.c $(CC) $(INCLUDE_DIR) -c $^ -o $(OBJ_DIR)/$@
main目录下的Makefile
#获取当前目录下所有的.c文件 SRC=$(wildcard *.c) #准备把当前目录下的.c转换为.o文件 ===>OBJ=fun.o OBJ=$(patsubst %c,%o,$(SRC)) all:$(OBJ) $(OBJ): %.o:%.c $(CC) $(INCLUDE_DIR) -c $^ -o $(OBJ_DIR)/$@
obj目录下的Makefile
$(BIN_DIR)/$(TARGET) : *.o
$(CC) $(INCLUDE_DIR) $^ -o $@
主Makefile
CC := gcc INCLUDE_DIR := -I ../include OBJ_DIR := $(shell pwd)/obj BIN_DIR := $(shell pwd)/bin SUB_DIR := main fun global obj TARGET := my_exec #设置SUB_DIR变量导出为全局,其他文件也可以使用 export CC INCLUDE_DIR OBJ_DIR BIN_DIR SUB_DIR TARGET all:$(SUB_DIR) $(SUB_DIR) : MK_BIN make -C $@ #-C选项后跟目录,表示到子目录下执行子目录的Makefile MK_BIN: mkdir -p ./bin clean: rm -rf *.bin ./obj/*.o install: sudo cp $(BIN_DIR)/$(TARGET) /usr/bin uninstall: sudo rm -rf /usr/bin/$(TARGET)