引言
Makefile 是一个强大的自动化构建工具,它可以帮助开发者管理复杂的项目,提高代码的可维护性和可移植性。本篇博客将从头开始,深入探讨如何创建、编写和使用 Makefile。
什么是 Makefile?
Makefile 是一个文本文件,其中包含了一系列规则,用于定义项目的构建过程。通过 Makefile,开发者可以指定如何编译和链接源代码文件,以及如何生成最终的可执行文件或库。
创建一个简单的 Makefile
让我们从一个简单的示例开始。假设我们有一个名为 hello.c
的 C 程序文件,我们想要编译成一个可执行文件。我们可以创建一个名为 Makefile
的文件,并将以下内容复制进去:
hello: hello.c
gcc -o hello hello.c
这个 Makefile 定义了一个目标 hello
,它依赖于 hello.c
文件。当我们运行 make
命令时,Make 工具将会执行编译命令,生成名为 hello
的可执行文件。
编写更复杂的 Makefile
现在让我们看一个稍微复杂一些的例子,涉及到多个源文件的编译和链接。假设我们的项目包含 main.c
和 utils.c
这两个源文件,我们需要将它们编译成一个可执行文件。我们可以创建一个名为 Makefile
的文件,并将以下内容复制进去:
# 定义编译器和编译选项
CC = gcc
CFLAGS = -Wall -Wextra -std=c11
# 定义目标文件和依赖关系
TARGET = myprogram
SRCS = main.c utils.c
OBJS = $(SRCS:.c=.o)
DEPS = utils.h
# 默认构建规则
all: $(TARGET)
# 构建目标文件
%.o: %.c $(DEPS)
$(CC) $(CFLAGS) -c $< -o $@
# 构建可执行文件
$(TARGET): $(OBJS)
$(CC) $(CFLAGS) $^ -o $@
# 清理生成的文件
clean:
rm -f $(OBJS) $(TARGET)
这个 Makefile 包含了更多的功能,比如定义了编译器和编译选项、目标文件和依赖关系、构建规则等。
让我们来解释一下这个 Makefile 中的各个部分:
CC
和CFLAGS
定义了编译器和编译选项。TARGET
定义了最终生成的可执行文件的名称。SRCS
定义了源文件的列表。OBJS
定义了目标文件的列表,通过将每个 .c 文件的扩展名替换为 .o 得到。DEPS
定义了头文件的列表。all
是默认构建目标,依赖于$(TARGET)
。%.o: %.c $(DEPS)
是一个规则模式,它表示每个 .o 文件依赖于对应的 .c 文件和头文件。$(TARGET): $(OBJS)
表示生成可执行文件的规则,依赖于所有目标文件。clean
是清理规则,用于删除生成的目标文件和可执行文件。
如果你想要分别编译两个或多个源文件并生成两个独立的可执行程序,可以按以下编写
示例:
CC=g++
CFLAGS=-Wall
SOURCES=file1.cpp file2.cpp
EXECUTABLES=$(SOURCES:.cpp=)
all: $(EXECUTABLES)
%: %.cpp
$(CC) $(CFLAGS) $< -o $@
clean:
rm -rf $(EXECUTABLES)
这个 Makefile 中的关键变化是 EXECUTABLES
变量,它将每个源文件的名称用于生成对应的可执行文件。然后,all
目标依赖于 $(EXECUTABLES)
,这样在运行 make
时,将会编译所有的源文件并生成所有的可执行文件。
$(SOURCES:.cpp=)
的作用是将 SOURCES
变量中的每个 .cpp
文件的文件名进行替换,去掉 .cpp
扩展名。这样就得到了一个不带扩展名的文件列表,用于作为可执行文件的名称。
%: %.cpp
这条规则用于指定如何将每个 .cpp
源文件编译成一个可执行文件。%
表示任意的文件名,.cpp
表示以 .cpp
结尾的文件。$<
是自动变量,代表规则中的第一个依赖项,即源文件的名称。-o $@
表示将编译结果输出为规则的目标,即可执行文件的名称。
这个 Makefile 将会在你的项目目录中生成两个可执行文件,分别与你的源文件同名。
使用 Makefile
使用 Makefile 很简单,只需在终端中进入到包含 hello.c
或 main.c
、utils.c
和 Makefile
的目录,并运行以下命令:
make
这将会执行 Makefile 中定义的规则,根据需要编译和链接源文件,并生成最终的可执行文件。如果需要清理生成的文件,可以运行以下命令:
make clean
这将会删除生成的目标文件和可执行文件,使得项目目录变得干净整洁。