Make是在软件开发中广泛使用的构建工具和构建脚本。它们用于自动化编译和链接源代码,生成可执行文件或库。
Makefile 是包含构建规则的文本文件,定义了项目中文件之间的依赖关系和构建步骤。每个规则包括一个目标(target)、依赖关系(dependencies)和构建命令(action)。
(1)基本结构
# Makefile 中的命令行需要严格遵循缩进规则
target: dependencies action# target(目标):要生成的文件,通常是可执行文件或库。# dependencies(依赖关系):目标生成所需的源文件或其他目标文件。# action(构建命令):用于生成目标文件的命令。# 冒号 `:` 的主要作用是定义规则(Rules)。**(2)规则:**定义了如何生成目标文件。一个常见的规则包括目标、依赖关系和动作。描述了如何生成一个或多个目标文件。例如:
my_program: main.o util.o gcc -o $@ $^
# 如main: main.o util.o gcc -o main main.o util.o| 类别 | 变量/函数名 | 描述 | 示例 |
|---|---|---|---|
| 内置变量 | CC | C 编译器的名称,默认为 cc。 | CC=gcc |
CFLAGS | 编译器选项,用于设置编译标志。 | CFLAGS=-I. -Wall -g | |
LDFLAGS | 链接器选项,用于设置链接标志。 | LDFLAGS=-L/usr/local/lib | |
RM | 删除命令,默认为 rm。 | RM=del (在 Windows 系统上) | |
| 用户自定义 | XX | 自定义 C 编译器的名称。 | XX=clang |
| 自动变量 | $@ | 目标文件的名称。 | $(TARGET): $(OBJS) |
$< | 第一个依赖文件的名称。 | $< 代表第一个依赖文件,如 main.o | |
$^ | 所有的依赖文件的名称。 | $^ 代表所有依赖文件,如 main.o util.o | |
| 内置函数 | wildcard | 匹配文件模式,返回文件列表。 | SRCS := $(wildcard *.c) |
notdir | 去除路径,返回文件名。 | OBJS := $(notdir $(SRCS:.c=.o)) | |
patsubst | 模式匹配替换。 | TARGETS := $(patsubst %.c,%.o,$(SRCS)) |
(3)多级目录的 Makefile
当源文件分布在不同目录中时,Makefile 仍然可以管理项目。通过适当的规则和变量设置,可以实现多级目录的项目构建。
ELF=mainsrc=$(shell find -name '*.c')object=$(src:.c=.o) #模式规则中的替换操作,将 $(src) 中所有以 .c 结尾的文件名替换成以 .o 结尾的文件名。$(ELF):$(object) gcc $^ subtract.o -o $@$(object):.PHONY:cleanclean: rm -f $(object) $(ELF)示例:
# 编译器CC = gccCFLAGS = -Wall -O2
# 目标可执行文件TARGET = my_program
# 源文件列表SOURCES = main.c file1.c file2.c
# 目标文件列表(对象文件)OBJECTS = $(SOURCES:.c=.o)
# 默认目标all: $(TARGET)
# 链接规则$(TARGET): $(OBJECTS) $(CC) $(CFLAGS) -o $@ $^
# 编译规则%.o: %.c $(CC) $(CFLAGS) -c $< -o $@
# 清理规则clean: rm -f $(TARGET) $(OBJECTS)
# 伪目标,伪目标(Phony target)是一种特殊的目标,它不对应于文件系统中的任何文件。.PHONY: clean all在编程和软件开发中,尤其是在使用Makefile进行自动化编译时,all是一个常用的目标(target),它用于定义一个默认的任务,当执行make命令而没有指定具体目标时所要执行的操作。以下是all目标的一些常见用途:
1)默认构建目标:当在命令行中只输入make而不指定任何目标时,make工具会自动寻找名为all的目标并执行与其关联的命令。
2)组合多个目标:all可以作为一个总目标,它依赖于其他一系列的子目标。这样,执行make all就相当于执行了这些子目标,从而完成了一个完整的构建过程。
3)简化命令:使用all目标可以简化用户的命令输入。用户不需要记住所有的子目标,只需要运行make all即可完成整个项目的构建。
4)顺序执行:在某些情况下,构建过程需要一定的顺序,all目标可以通过指定依赖关系来确保子目标按照正确的顺序执行。
例如,一个简单的Makefile可能包含如下内容:
TARGET = app
all: $(TARGET)
$(TARGET): main.o utils.o gcc -o $(TARGET) main.o utils.o
main.o: main.c gcc -c main.c
utils.o: utils.c gcc -c utils.c
clean: rm -f *.o $(TARGET)
.PHONY: all clean在这个Makefile中,all目标依赖于app,当执行make all时,它会按照Makefile中定义的规则编译main.o和utils.o,然后链接生成最终的app可执行文件。同时,clean是一个伪目标(phony target),用于清理所有对象文件和可执行文件,通常用于准备下一次干净的构建。