我为何创建 lazymake:解决 Make 的 UX 问题
Source: Dev.to
请提供您希望翻译的具体文本内容,我将按照要求保留源链接并进行简体中文翻译。
新项目的典型工作流程
- 打开
Makefile - 浏览 500 + 行晦涩的规则
- 试图弄清
build、build‑prod和build‑all的作用 - 最终运行了错误的目标,导致出错
- 在 Slack 中写道:“大家,我需要运行什么命令才能部署到 staging?”
我发现自己为每个项目单独记录最常用的命令——这感觉很奇怪,因为 Makefile 的全部意义就在于将这些命令集中管理。
The Breaking Point
我决定必须改变的那一刻,是在我加入一个新项目时。我的资深同事,一位优秀的工程师,简单地说:
“看看 Makefile,里面一切都很清晰。”
我打开它,惊恐不已:
- 大约 600 行代码
- 到处都是变量
- 条件逻辑和嵌套依赖
我无法在不在脑中逐行解析数百行语法的情况下,弄清楚如何在本地运行项目。这简直是疯狂。
我想到像 lazygit 这样的工具,它为 Git 提供了漂亮的 TUI,于是想,为什么没有类似的工具用于 Makefile 呢?这激发了我开发自己的 TUI 应用的想法。
开发
我从一个简单的想法开始:显示一个目标列表,让用户挑选一个,运行它,并展示输出。一个使用 Bubble Tea 构建的非常基础的 TUI。第一版只有 200–300 行 Go 代码,却已经可以工作。
此后,我不断添加功能,以解决多年积累的痛点。
依赖图
第一个主要特性是 依赖图。现在,当我需要运行某个目标时,我可以看到:
- 完整的依赖树
- 执行顺序
- 临界路径(决定整体执行时间的最慢链)
- 并行化机会——哪些可以使用
make -j运行
在任意目标上按 g 键即可查看图形:
仅此一点就让项目变得有价值:我现在可以准确看到某个目标到底做了什么,而不必从 Makefile 中猜测。它还能捕获可能不小心出现的循环依赖。
Source:
变量检查器
Make 的变量系统功能强大,却不透明。诸如以下问题:
$(LDFLAGS)会展开成什么?- 哪些目标使用了
$(VERSION)?
以前需要在整个文件中 grep。
使用 lazymake 时,只需按 v 键即可打开功能完整的浏览器,显示每个变量、它的定义以及使用位置:
过去需要 20 分钟的调试时间,现在只需 20 秒即可查找。
Safety
我经常看到同事(包括我自己)因为不了解目标会做什么而意外运行了破坏性的命令。
为了解决这个问题,lazymake 包含了一个 模式匹配安全系统,它会标记危险命令:
rm -rf / # CRITICAL – requires confirmation
DROP DATABASE # CRITICAL – requires confirmation
git push --force # WARNING – shows alert
terraform destroy # WARNING – context‑aware
该系统具备上下文感知能力。例如,在名为 clean-test-cache 的目标中使用 rm -rf 是可以接受的,但在名为 nuke-everything 的目标中使用同样的命令会触发确认提示。
它真的帮我避免了不良后果吗?是的——多次。
TL;DR
- lazymake 提供了一个 TUI,用于浏览 Makefile 的目标、依赖关系和变量。
- 它可视化依赖图,突出关键路径,并建议并行化。
- 变量检查器使原本不透明的变量系统变得透明。
- 内置安全检查防止意外执行破坏性命令。
所有这些将对庞大的 Makefile 进行令人沮丧的手动搜索,转变为快速、交互式的体验。
高亮
这最初并不在我的功能列表中。但 Makefile 可以包含几乎任何语言——bash、Python、Go,甚至其他任何语言。因此,为了读取多行配方,我集成了 Chroma 来实现自动代码检测和高亮:
它通过 shebang、命令模式或手动提示来检测语言。让阅读复杂的配方变得更加轻松。
我没想到的
我在早期测试时添加了一些功能。例如,性能跟踪。它会自动计时执行并报告是否有某些操作变慢(> 25 % 的正常执行时间)。这样我捕获了几次回归。
我还添加了工作区管理。你可以按 w 查看项目中的所有 Makefile。结果发现,这在单体仓库中很有用。
此外,我添加了执行历史。最近的 5 个目标会首先显示。根据我的经验,我注意到大多数情况下我都会运行相同的命令。
困难之处
解析 Makefile
Makefile 既不是编程语言,也不是简单的配置文件。变量展开、模式规则、条件包含——所有这些都相当复杂。
起初,我想直接使用 Make 本身:
make -pn | grep "^[a-zA-Z].*:"
但我还需要从 Makefile 中提取注释、依赖关系等信息。因此我仍然自己编写了一个解析器。当然它并不完美,但似乎能够完成任务。
实时输出
Bubble Tea 帮助我在 TUI 中实现命令的流式输出。
跨平台支持
我发现要让该应用在 macOS、Linux、Bash、Zsh 等平台上都能良好运行相当困难。终端能力差异很大。说实话,我仍然不能完全确定所有功能在各处都能如预期工作,但大体上似乎可以正常运行。 :)
亲自尝试
# macOS/Linux
brew install rshelekhov/tap/lazymake
# Or via Go
go install github.com/rshelekhov/lazymake/cmd/lazymake@latest
# Then simply:
lazymake
可用于任何 Makefile,即使没有配置也能运行(虽然我仍然添加了根据你的需求配置程序的功能)。
我想进一步开发这个项目,但为此我需要了解用户的需求。如果你对该项目感兴趣并考虑开始使用,请告诉我:使用 Makefile 时你最大的痛点是什么?
如果你觉得这很有用,请给仓库加星 ⭐ 并告诉我你的想法。我始终乐于听取反馈(或抱怨——它们也很有价值)。



