Makefile编译工程文件开发
一、Makefile总览
二、 Makefile简介
- Makefile是什么?
- gcc hello.c -o hello
- gcc aa.c bb.c cc.c dd.c …
- make工具和Makefile
- make和Makefile是什么关系?
- make工具:找出修改过的文件,根据依赖关系,找出受影响的相关文件,最后按照规则单独编译这些文件。
- Makefile文件:记录依赖关系和编译规则。
- 怎么学习Makefile?
- Makefile的本质:无论多么复杂的语法,都是为了更好地解决项目文件之间的依赖关系。
三、Makefile三要素
-
Makefile三要素是什么?
- 目标、依赖、命令
-
怎么描述三要素的关系?
- 目标:依赖的文件或者是其他目标
- tab+命令1
tab+命令2
…
.PHONY:可以指定伪目标:每次都会执行该目标。
-
代码演示
.PHONY:targetb targeta:targetb targetc echo "targeta" targetb: echo "targetb" targetc: echo "targetc"
四、引入Makefile管理项目
mp3:main.o mp3.o
gcc main.o mp3.o -o mp3
main.o:
gcc -c main.c -o main.o
mp3.o:
gcc -c mp3.c -o mp3.o
.PHONE:clean
clean:
rm mp3
五、Makefile的变量、模式匹配
- 变量
- 系统变量
.PHONY:all all: echo "$(CC)" echo "$(AS)" echo "$(MAKE)"
- 自定义变量
- =,延迟赋值
- :=, 立即赋值
- ?=,空赋值
- +=,追加赋值
- 自动化变量
- $<:第一个依赖文件
- $^:全部的依赖文件
- $@:目标
CC=gcc TARGET=mp3 OBJS=main.o mp3.o $(TARGET):$(OBJS) $(CC) $^ -o $@ main.o: $(CC) -c main.c -o main.o mp3.o: $(CC) -c mp3.c -o mp3.o .PHONY:clean clean: rm mp3
- 模式匹配
- %:匹配任意多个非空字符
- shell:*通配符
CC=gcc TARGET=mp3 OBJS=main.o mp3.o $(TARGET):$(OBJS) $(CC) $^ -o $@ #main.o:main.c # $(CC) -c main.c -o main.o #mp3.o:mp3.c # $(CC) -c mp3.c -o mp3.o %.o:%.c $(CC) -c $< -o $@ .PHONY:clean clean: rm mp3
- 默认规则
- .o文件默认使用.c文件来进行编译
- 系统变量
六、Makefile的条件分支
ifeq (var1,var2)
...
else
...
endif
ifneq (var1,var2)
...
else
...
endif
-
程序
ARCH ?= x86 ifeq ($(ARCH),x86) CC=gcc else CC=arm-linux-gnueabihf-gcc endif TARGET=mp3 OBJS=main.o mp3.o $(TARGET):$(OBJS) $(CC) $^ -o $@ #main.o:main.c # $(CC) -c main.c -o main.o #mp3.o:mp3.c # $(CC) -c mp3.c -o mp3.o %.o:%.c $(CC) -c $< -o $@ .PHONY:clean clean: rm mp3
七、Makefile的常用函数
- Makefie官方手册:
https://www.gnu.org/software/make/manual - patsubst:
- notdir:
- wildcard:
- foreach:
- 源码
ARCH ?= x86 ifeq ($(ARCH),x86) CC=gcc else CC=arm-linux-gnueabihf-gcc endif TARGET=mp3 #OBJS=main.o mp3.o BUILD_DIR=build SRC_DIR=module1 module2 SOURCES=$(foreach dir,$(SRC_DIR),$(wildcard $(dir)/*.c)) OBJS=$(patsubst %.c,$(BUILD_DIR)/%.o,$(notdir $(SOURCES))) VPATH=$(SRC_DIR) $(BUILD_DIR)/$(TARGET):$(OBJS) $(CC) $^ -o $@ #main.o:main.c # $(CC) -c main.c -o main.o #mp3.o:mp3.c # $(CC) -c mp3.c -o mp3.o $(BUILD_DIR)/%.o:%.c | creat_build $(CC) -c $< -o $@ .PHONY:clean creat_build clean: rm -r $(BUILD_DIR) creat_build: mkdir -p $(BUILD_DIR)
八、Makefile解决头文件依赖
- 写一个头文件,并把头文件添加到编译器的头文件路径中。
gcc -I +“头文件” - 实时检查头文件的更新情况,一旦头文件发生变化,应该要重新编译所有相关文件。
gcc -MM - 源码
ARCH ?= x86 ifeq ($(ARCH),x86) CC=gcc else CC=arm-linux-gnueabihf-gcc endif TARGET=mp3 #OBJS=main.o mp3.o BUILD_DIR=build SRC_DIR=module1 module2 INC_DIR=include CFLAGS=$(patsubst %,-I%,$(INC_DIR)) INCLUDES=$(foreach dir,$(INC_DIR),$(wildcard $(dir)/*.h)) SOURCES=$(foreach dir,$(SRC_DIR),$(wildcard $(dir)/*.c)) OBJS=$(patsubst %.c,$(BUILD_DIR)/%.o,$(notdir $(SOURCES))) VPATH=$(SRC_DIR) $(BUILD_DIR)/$(TARGET):$(OBJS) $(CC) $^ -o $@ #main.o:main.c # $(CC) -c main.c -o main.o #mp3.o:mp3.c # $(CC) -c mp3.c -o mp3.o $(BUILD_DIR)/%.o:%.c $(INCLUDES) | creat_build $(CC) -c $< -o $@ $(CFLAGS) .PHONY:clean creat_build clean: rm -r $(BUILD_DIR) creat_build: mkdir -p $(BUILD_DIR)