
你是不是也踩过这个坑在 Windows 的 PowerShell 或者 CMD 窗口里敲下make命令结果终端回你一句“无法将‘make’项识别为 cmdlet、函数、脚本文件或可运行程序的名称”或者干脆报“make 不是内部或外部命令也不是可运行的程序或批处理文件”。这个报错我在做 C/C 项目、编译 Redis、跑一些开源工具时反复遇到今天就把 Windows 下安装 make 工具的几种方法、原理和避坑点一次讲透。这篇文章适合三类人刚接触 Makefile 的初学者、需要在 Windows 上编译 Linux 风格开源项目的开发者、以及被各种“failed to build”折磨到想换系统的老哥。我会把安装 make 的来龙去脉、方案选型、具体步骤和常见报错全盘托出保证你照着操作就能跑通。1. 为什么 Windows 上装 make 会这么折腾1.1 先搞明白 make 到底是个什么东西make 是一个构建自动化工具它读取 Makefile 文件根据文件里定义的规则、依赖关系和时间戳来决定哪些源文件需要重新编译、哪些可以跳过。简单说它就像一位包工头——不会让你把所有砖头重搬一遍只盯着那些“过期”的瓦片去换。Linux/macOS 自带或者可以一行命令装好 make但 Windows 上情况完全不同因为 Windows 本身没有 POSIX 风格的 shell 环境make 依赖的一些底层工具链比如 sh、rm、mkdir 等在原生 Windows 上是不存在的。所以你会发现一个怪事明明 make.exe 已经躺在某个目录里了执行的时候还是报“找不到 make”。这背后的本质原因是路径问题——Windows 不会在全局范围内搜索那个 exe它只看环境变量 PATH 里列出来的目录。1.2 Windows 上 make 往往不是“一个文件”的事在 Linux 上make 通常跟编译工具链一起配合使用gcc、g、make、binutils 这些是打包在一起的。但在 Windows 上不同的发布渠道给出了完全不同的“配方”。比如 GnuWin32 那一套是把 make 打包成独立安装包装完只有 make 本身而 MSYS2/MinGW-w64 则是提供一个完整的 POSIX 模拟层make 是其中一部分。如果你装的是前者可能在简单项目上能跑但遇到稍微复杂点的 Makefile里面用了shell函数、wildcard等语法直接歇菜。这个认知很重要安装 make 不是终点让它能在你的终端里被找到、并且能执行 Makefile 里需要的各类命令才是终点。2. 安装方案选型每条路都有人走但岔路容易迷2.1 方案对比MSYS2、Chocolatey、Scoop、GnuWin32、WSL我先放一张对比表再逐个细讲方案获取难度环境完整性对新手友好度我个人的推荐指数MSYS2/MinGW-w64中等很完整中上★★★★★Chocolatey 安装 make简单一般高★★★★Scoop 安装 make简单一般高★★★★GnuWin32 独立安装简单差中★★WSL 安装 make较复杂最完整低★★★之所以把 MSYS2 放在第一位是因为它最接近 Linux 的开发体验。make 在执行 Makefile 时会调用系统 shell 来跑命令MSYS2 自带的 MSYS2 Shell 提供了完整的 bash 环境里面配备了 coreutilsls、rm、cp 等。如果你直接拿 CMD 或 PowerShell 里的 make 去跑一个用了 rm 命令的 Makefile八成会报“系统找不到指定的文件”但是在 MSYS2 里就没有这个困扰。Chocolatey 和 Scoop 都是 Windows 上的包管理器它们装 make 的思路很简单下载一个编译好的二进制文件扔到固定目录然后配置 PATH。好处是快、静默、方便卸载坏处是拿到手的 make 是个“裸”的没有配套的 sh、coreutils遇到复杂 Makefile 就露馅。GnuWin32 是我最早用过的方案现在基本不推荐了。它虽然是成套的有 coreutils、gzip、tar 等但是项目更新太慢打包的 make 版本老某些新语法不支持而且安装过程还会往系统里塞一堆老掉牙的工具得不偿失。WSL 本质上是个虚拟机/子系统装完可以作为完整的 Linux 开发环境但它跟 Windows 原生进程的交互有额外开销而且需要重启系统、配置子系统镜像等如果你只是想编译个小项目有点杀鸡用牛刀。不过话说回来如果手头的开源项目本身就是面向 Linux 的WSL 反而是最稳的选择。2.2 我为什么最终推荐 MSYS2说说我的实际使用场景。之前我折腾过一个跨平台项目Makefile 里用到了$(shell pwd)、mkdir -p这类 POSIX 风格的命令。第一次我用 Chocolatey 装了 make然后在 PowerShell 里执行make all结果连编译阶段都没到做目录检查那一步就挂了。因为 PowerShell 环境里根本没有mkdir -p这个语法——PowerShell 的 mkdir 是个别名跟 POSIX 的 mkdir 完全是两码事。后来换成 MSYS2 之后在它的终端里跑同样的 Makefile一路顺畅通关。这就是我强烈推荐 MSYS2 的原因它不是给了你一个 make.exe而是给了你一套和 Linux 兼容的“生活方式”。如果你只做一个用户态工具直接在 MSYS2 的 shell 里执行就可以了。当然MSYS2 生成的 exe 是原生的 Windows 程序不依赖虚拟化编译出来的二进制可以直接丢给别人跑。3. 实操过程MSYS2 与包管理器两条路线全记录3.1 路线一MSYS2 完整安装首选先去 MSYS2 官网下载安装包这个安装包大概 100MB 左右下载慢的话可以找国内镜像源具体方法文末说。安装时一路 Next默认安装在C:\msys64装完会在开始菜单生成几个终端入口MSYS2 MSYS、MSYS2 UCRT64、MSYS2 CLANG64等。启动MSYS2 MSYS终端第一件事就是更新软件源pacman -Syuu这里有个小细节-Syuu的意思是先同步软件源数据库-Sy再执行系统完整升级第二个-u会把核心软件包也升级。如果中途遇到“无法锁定数据库”之类的提示说明有另一个 pacman 进程占用了数据库把所有 MSYS2 终端窗口关掉再打开就行。然后安装 make以及配套的编译工具链。如果只是想要 make一行命令pacman -S make但建议连基础工具链一起装pacman -S base-devel gccbase-devel这个包组里包含了 make、autoconf、automake、flex、bison 等一堆编译项目必需品。装完验证一下make --version看到类似GNU Make 4.4.1的输出就说明成了。注意我这里是在 MSYS 终端里验证的它的 PATH 自动带了/usr/bin。如果你想在 Windows 自带的 CMD 或者 Windows PowerShell 里也能直接用 make得手动把C:\msys64\usr\bin加到系统环境变量 PATH 里。提示把C:\msys64\usr\bin加到 PATH 之后会有一批 GNU 工具同时暴露给 Windows 的所有终端比如 ls、grep、tar 等。这既是福利也是坑——以后在 CMD 里敲where ls可能会命中两个不同位置注意区分。3.2 路线二Chocolatey / Scoop 轻量安装如果你只是想让make命令在 Windows Terminal 里不报“无法将‘make’项识别为 cmdlet”而且项目 Makefile 相对简单那走包管理器路线更省事。先看 Chocolatey。以管理员身份打开PowerShell执行Set-ExecutionPolicy Bypass -Scope Process [System.Net.ServicePointManager]::SecurityProtocol [System.Net.ServicePointManager]::SecurityProtocol -bor 3072 iex ((New-Object System.Net.WebClient).DownloadString(https://community.chocolatey.org/install.ps1))装好 Chocolatey 之后一行命令装 makechoco install make -y这里有个隐藏细节Chocolatey 从 https://gnuwin32.sourceforge.io/ 下载 make 安装包所以你的网络环境得能正常访问 SourceForge。装完一样验证make --version。再看 Scoop。Scoop 的好处是不需要管理员权限对用公司电脑的开发者比较友好。先打开 PowerShell 执行Set-ExecutionPolicy RemoteSigned -Scope CurrentUser irm get.scoop.sh | iex然后把 main bucket 加进来安装 makescoop install main/makeScoop 装的 make 放在%USERPROFILE%\scoop\shims\里面这个 shim 目录默认就在 PATH 里所以开个新终端直接能用。3.3 两条路线我都跑过说点真实差异MSYS2 路线装完make 的默认 shell 是 bashMakefile 里随便写rm -rf、mkdir -p、cp -r都能跑。Chocolatey 路线装完默认调用的 shell 是 Windows 的 cmd.exe遇到 POSIX 命令就直接报错。我拿一个真实例子Makefile 里有如下一段clean: rm -rf *.o用 Chocolatey 装的 make 执行make clean时会报“系统找不到指定的文件。rm”因为 cmd 里没有 rm 这个命令。而 MSYS2 环境下因为 PATH 里有 coreutilsrm是存在的所以没问题。所以我的选型建议很简单要编译的是纯原生 Windows 程序且 Makefile 是手写的、兼容 Windows 风格 → Chocolatey/Scoop 够用要编译的是从 Linux 迁移过来的开源项目Makefile 里充满了 POSIX 命令 → 无脑 MSYS2要做嵌入式开发或者交叉编译 → MSYS2 里的 MinGW-w64 工具链也很方便不用单独装 Cygwin4. 环境变量与终端选择决定成败的隐藏细节4.1 PATH 配置详解安装完 make 只是第一步能不能在当前终端里调起来是第二步。Windows 下查找可执行文件的顺序是当前目录 → PATH 里的每一个路径。CMD 的提示语是“make 不是内部或外部命令”PowerShell 的提示语是“无法将‘make’项识别为 cmdlet、函数、脚本文件或可运行程序的名称”——这两个提示本质上都在说“PATH 里没有 make.exe”。配置方法右键点击“此电脑”→ 属性 → 高级系统设置 → 环境变量在“系统变量”中找到 Path点击编辑把 MSYS2 的C:\msys64\usr\bin加进去然后逐个点确定保存。注意改完环境变量必须开一个新终端才能生效老终端的进程环境没有刷新。还有一个坑如果你同时装了 Chocolatey 的 make 和 MSYS2 的 make两个目录会冲突。Windows 按 PATH 的顺序从左到右找谁靠前优先用谁。用where makeCMD或Get-Command makePowerShell可以查看当前终端实际命中的是哪一个。4.2 IDE 和编辑器里调用 make 的注意事项很多人在 VS Code 里装了 C/C 插件或者用 JetBrains 家的 IDE里面的终端默认是 PowerShell头一回调 make 直接报错。解决方案有两个要么把 IDE 的默认终端改成 CMD要么在 VS Code 的 settings.json 里加一段terminal.integrated.profiles.windows: { MSYS2 Bash: { path: C:\\msys64\\usr\\bin\\bash.exe, args: [--login] } }, terminal.integrated.defaultProfile.windows: MSYS2 Bash这样 VS Code 的内置终端就变成了完整的 bash 环境make 以及其他工具链都好用。JetBrains 系 IDECLion、GoLand 等也有类似设置路径在 Settings → Tools → Terminal → Shell path填C:\msys64\usr\bin\bash.exe即可。4.3 “找不到 makefile”的经典场景配好了 PATH、终端也换了结果执行make又报“Makefile: No such file or directory”或者“make: *** No targets specified and no makefile found. Stop.”。这通常是因为你在错误的目录下执行了 make。make 默认只在当前目录找Makefile、makefile或GNUmakefile这三个文件名。你进入项目源码目录再执行cd /path/to/project make或者用-f参数显式指定文件make -f my_makefile还有一种特例从网上下载的源码包解压后没有 Makefile只有一个configure脚本需要先跑./configure生成 Makefile。在 Windows MSYS2 环境下如果你直接执行./configure报 permission denied多半是因为压缩包解压时丢掉了可执行权限解决办法是用 MSYS2 终端执行chmod x configure ./configure5. 常见报错与排查技巧实录5.1 高频报错速查表我把这几年在不同机器上遇到的报错整理成一个速查表报错内容出现场景根本原因解决办法无法将“make”项识别为 cmdlet、函数...PowerShell 里执行 make未装 make 或 PATH 未配置安装 MSYS2 或 choco配置 PATHmake 不是内部或外部命令CMD 里执行 make同上同上make: *** No targets specified and no makefile found执行 make 但当前目录没有 Makefile目录不对cd 到项目目录或添加-f参数make:make不是文件还是目录命令敲错把make当文件名参数传给 make直接用make命令不需要参数/bin/sh: line 1: ./incdefs.sh: Permission denied在 Windows 上跑开源项目的构建脚本解压丢失了 Unix 可执行权限chmod x对应脚本或用 MSYS2 的 bash 执行error writing temporary file: make: chmod: Operation not permitted某些沙箱环境临时目录权限受限设置 TMPDIR 指向可写目录sh: syntax error near unexpected token(Makefile 里有 Windows 风格的命令make 调用的是 cmd 而非 bash确保用 MSYS2 的 bash 环境recipe for target failed编译过程中报错编译参数或路径有问题根据实际出错命令逐条排查5.2 报错案例一MSYS2 里跑 install 权限使用 MSYS2 时很多人图省事直接pacman -S make但如果你是在权限不足的目录下编译项目比如把代码放在了C:\Program Files下面会出现error writing temporary file这类错误。因为 make 在编译过程中会生成临时文件而系统保护目录没有写权限。解决思路是把项目放到用户目录下cp -r /c/project ~/project cd ~/project make5.3 报错案例二终端用错了还有一个很有迷惑性的场景你在 VS Code 里装的终端插件默认是 PowerShell但是插件里某个 task 配置用的是 bash。这时候你明明装了 MSYS2在烧写脚本里却调不到 make。排查思路先手动在同一个终端里跑make --version如果报错说明该终端的 PATH 没有更新去环境变量里检查一遍如果手动跑 OK说明 task 配置里没有继承系统 PATH需要在 task 里显式设置options: { env: { PATH: C:\\msys64\\usr\\bin;${env:PATH} } }。5.4 报错案例三make.exe 版本冲突我之前在一台用 Chocolatey 日常装软件的机器上编译项目make --version显示的是GNU Make 3.81这个版本太老处理一些较长路径时经常抽风。后来发现是 Chocolatey 装的 make 版本 3.81 占了优先位置而 MSYS2 里是 4.4.1。遇到这种情况我建议把 MSYS2 的路径在 PATH 里提前。如果不想改全局 PATH可以在当前终端临时调整$env:Path C:\msys64\usr\bin; $env:Path这个设置只对当前终端窗口生效适合快速验证。5.5 排查思路总结每一次 make 相关报错先看终端类型CMD/PowerShell/MSYS2 bash、再看 PATH 顺序、最后看 Makefile 内容。我踩坑多了以后养成了一个习惯装完工具链的第一件事不是急着去编译项目而是先跑一个最小验证all: echo make works用这个三行内容验证环境是否正常。如果这个能跑通说明 make 本体没问题如果跑不通问题集中在环境上而不是项目上。这个习惯帮我节省了很多冤枉时间。6. 写在最后选工具链别纠结适合场景就好我这几年先后用过 GnuWin32、Chocolatey、Scoop、MSYS2 和 WSL每次换项目都忍不住想重新折腾一遍。最后发现决定成败的往往不是 make 版本新旧而是它周围有没有配套的 shell 工具链。一个光秃秃的 make.exe 就像只有方向盘没有车轮的车看着能用实际上寸步难行。我个人目前的固定搭法是主力编译环境用 MSYS2日常快速验证用 Scoop 装的轻量 make两套环境互不干扰。如果你配好之后也遇到那些奇奇怪怪的“权限 denied”“找不到 shell 命令”报错多半不是 make 本身的问题而是少装了基础开发包。记住在 MSYS2 里把base-devel一起装上这个包组能省掉后面无数个坑。