跳转到内容
新建笔记

Makefile

GNU make


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
类别变量/函数名描述示例
内置变量CCC 编译器的名称,默认为 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=main
src=$(shell find -name '*.c')
object=$(src:.c=.o) #模式规则中的替换操作,将 $(src) 中所有以 .c 结尾的文件名替换成以 .o 结尾的文件名。
$(ELF):$(object)
gcc $^ subtract.o -o $@
$(object):
.PHONY:clean
clean:
rm -f $(object) $(ELF)

示例:

# 编译器
CC = gcc
CFLAGS = -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),用于清理所有对象文件和可执行文件,通常用于准备下一次干净的构建。