make 是一个自动化构建工具,它根据一个名为 Makefile 的文件来决定如何编译和链接程序,这在 C/C++ 等语言的项目开发中非常常见。

确认已安装 make
在 Cygwin 的安装过程中,make 包含在 "Devel" (开发) 类别的软件包中。
- 打开 Cygwin 的安装程序 (
setup-x86_64.exe或setup-x86.exe)。 - 确保你处于 "Install" 或 "Update" 模式。
- 在包列表中,展开 "Devel" 类别。
- 找到
make包,确保它的状态是 "Default"(默认安装)或 "Skip"(跳过),如果不是,点击它将其设置为 "Default" 或 "Install"。 - 点击 "Next" 完成安装。
安装完成后,你可以通过以下命令验证 make 是否已正确安装:
make --version
如果安装成功,你会看到类似以下的输出,表明你正在使用 GNU Make:
GNU Make 4.4.1
Built for x86_64-pc-cygwin
Copyright (C) 1988-2025 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
make 的基本工作原理
make 的核心是 Makefile,Makefile 文件定义了一系列的 规则,每个规则都包含:

- 目标: 一个文件名,通常是程序、目标文件(
.o文件)或可执行文件。 - 依赖: 生成目标所需要的文件,如果依赖比目标文件新,
make就会执行规则中的命令来重新生成目标。 - 命令: 一系列 Shell 命令,用于从依赖文件生成目标文件。
基本语法:
target: dependencies
command
执行流程:
make首先在当前目录下寻找名为Makefile或makefile的文件。- 它读取 Makefile,找到第一个 目标(也称为 入口目标)。
- 检查该目标的 依赖 文件是否存在。
- 如果依赖文件不存在,
make会尝试在 Makefile 中找到生成该依赖文件的规则,并执行它。 - 如果依赖文件比目标文件新,或者目标文件不存在,
make就会执行该规则下的 命令 来更新目标文件。
- 如果依赖文件不存在,
- 这个过程是递归的,直到所有需要的依赖都满足,最终生成最初的目标。
创建一个简单的 C 语言项目示例
让我们通过一个经典的 "Hello, World!" C 项目来演示 make 的用法。
项目结构
假设你的项目目录如下:

my_project/
├── hello.c
└── Makefile
hello.c 源代码
这是一个简单的 C 程序。
// hello.c
#include <stdio.h>
int main() {
printf("Hello from Cygwin!\n");
return 0;
}
Makefile 文件
这是 make 的核心,我们将创建一个简单的 Makefile 来编译 hello.c。
# 定义变量,方便维护
CC = gcc
CFLAGS = -Wall -g
TARGET = hello
# 默认目标(第一个目标)
# 当你直接输入 make 时,make 会尝试构建这个目标
all: $(TARGET)
# 定义如何生成可执行文件 hello
# 它依赖于 hello.o 文件
hello: hello.o
$(CC) $(CFLAGS) -o $@ $<
# 定义如何生成目标文件 hello.o
# 它依赖于 hello.c 文件
hello.o: hello.c
$(CC) $(CFLAGS) -c -o $@ $<
# 清理生成的文件
clean:
rm -f $(TARGET) hello.o
# 这是一个伪目标,防止目录下有名为 clean 的文件导致冲突
.PHONY: clean
Makefile 详解:
CC = gcc: 定义一个变量CC,值为编译器gcc。CFLAGS = -Wall -g: 定义一个变量CFLAGS,值为编译选项(-Wall显示所有警告,-g包含调试信息)。TARGET = hello: 定义变量TARGET,值为最终可执行文件名。all: $(TARGET):all是一个常用的默认目标,它依赖于$(TARGET)(即hello),这意味着当你运行make或make all时,make会去构建hello这个目标。hello: hello.o: 定义hello的规则,它依赖于hello.o文件。$(CC) $(CFLAGS) -o $@ $<: 这是命令。- 是一个自动化变量,代表 目标,这里是
hello。 $<是一个自动化变量,代表 第一个依赖,这里是hello.o。
- 是一个自动化变量,代表 目标,这里是
hello.o: hello.c: 定义hello.o的规则,它依赖于hello.c文件。$(CC) $(CFLAGS) -c -o $@ $<: 这是命令。-c选项告诉gcc只编译,不链接,生成.o文件。- 是目标
hello.o。 $<是依赖hello.c。
clean: ...: 定义一个clean目标,用于清理编译过程中产生的中间文件。.PHONY: clean: 声明clean是一个 伪目标,伪目标不代表一个实际的文件,这可以防止当前目录下存在一个名为clean的文件时,make认为它已经是最新的而不会执行清理命令。
如何使用 make 命令
打开 Cygwin 终端,进入到你的项目目录 (my_project)。
1 首次编译
hello 和 hello.o 文件都不存在。
cd /path/to/my_project make
输出:
gcc -Wall -g -c -o hello.o hello.c
gcc -Wall -g -o hello hello.o
make 会发现 hello.o 不存在,于是先执行 hello.o 的规则来编译 hello.c,然后发现 hello 不存在,于是执行 hello 的规则来链接 hello.o,最终生成 hello 可执行文件。
2 重新编译
hello 文件已经存在,我们修改一下 hello.c,比如在 printf 后面加一行注释,然后再次运行 make。
// hello.c
#include <stdio.h>
int main() {
printf("Hello from Cygwin!\n");
// This is a new line.
return 0;
}
再次运行 make:
make
输出:
gcc -Wall -g -c -o hello.o hello.c
gcc -Wall -g -o hello hello.o
你会发现 make 重新执行了两个命令,这是因为 make 检查到 hello.c 文件比 hello.o 新,所以需要重新编译 hello.o,然后又检查到 hello.o 比最终的 hello 新,所以需要重新链接。
3 只编译修改过的文件
我们再次修改 hello.c,然后运行 make:
make
输出:
gcc -Wall -g -c -o hello.o hello.c
gcc -Wall -g -o hello hello.o
和上次一样,但如果我们只是修改了一个不相关的文件,README.md,然后运行 make,make 会检查所有依赖,发现 hello.c 没有变化,hello.o 和 hello 都比 hello.c 新,所以什么都不会做。
echo "some text" >> README.md make
输出:
make: 'hello' is up to date.
这正是 make 的优势所在:它只重新构建那些需要被重新构建的部分,极大地提高了构建效率。
4 执行特定目标
如果你想清理编译文件,可以执行 clean 目标:
make clean
输出:
rm -f hello hello.o
hello 和 hello.o 文件都被删除了,如果你想再次编译,可以再次运行 make。
你也可以显式指定构建 all 目标:
make all
这和直接运行 make 效果一样。
常见问题与解决
问题1:make 不是内部或外部命令...
原因: 这通常意味着你没有在 Cygwin 的终端中运行命令,而是在 Windows 的 CMD 或 PowerShell 中运行,或者 Cygwin 的 bin 目录没有被添加到系统的 PATH 环境变量中。
解决:
- 确保使用正确的终端: 打开 Cygwin Terminal (
cygwin64-terminal.exe或cygwin-terminal.exe),它应该以user@hostname ~开头。 - 检查 PATH: 在 Cygwin 终端中运行
echo $PATH,确保其中包含类似/usr/bin的路径,Cygwin 安装正确,这通常是自动配置的。
问题2:Makefile:1: *** missing separator. Stop.
原因: 这是最常见的 Makefile 语法错误,它表示在规则的目标和命令之间,必须使用 Tab 字符缩进,而不是空格。
解决:
- 检查你的 Makefile 文件。
- 确保
hello.o: hello.c这一行下面的gcc ...命令行开头是一个 Tab 键,而不是用空格键缩进。 - 很多文本编辑器(如记事本)默认用空格缩进,这会导致错误,推荐使用支持显示制表符的编辑器,如 VS Code、Notepad++、Vim 等。
问题3:make: *** No rule to make target 'xxx'. Stop.
原因: 你在命令行中指定了一个 make 目标(make build),但在 Makefile 中没有找到名为 build 的规则。
解决:
- 检查 Makefile 中的目标名称是否拼写正确。
- 如果你只想执行默认的构建规则,直接使用
make或make all即可。
在 Cygwin 中使用 make 非常直接,与在 Linux 或 macOS 上的使用方式完全一致,关键点在于:
- 安装: 确保
make包在 Cygwin 的 "Devel" 类别中被安装。 - 编写 Makefile: 核心工作,定义好目标、依赖和命令,特别注意使用 Tab 缩进。
- 运行命令:
make: 构建默认目标。make clean: 清理编译产物。make all: 显式构建默认目标。
掌握 make 是进行 C/C++ 等项目开发的必备技能,它能极大地简化你的编译流程。
