我为何创建 lazymake:解决 Make 的 UX 问题

发布: (2026年1月5日 GMT+8 02:43)
8 min read
原文: Dev.to

Source: Dev.to

请提供您希望翻译的具体文本内容,我将按照要求保留源链接并进行简体中文翻译。

新项目的典型工作流程

  1. 打开 Makefile
  2. 浏览 500 + 行晦涩的规则
  3. 试图弄清 buildbuild‑prodbuild‑all 的作用
  4. 最终运行了错误的目标,导致出错
  5. 在 Slack 中写道:“大家,我需要运行什么命令才能部署到 staging?”

我发现自己为每个项目单独记录最常用的命令——这感觉很奇怪,因为 Makefile 的全部意义就在于将这些命令集中管理。

The Breaking Point

我决定必须改变的那一刻,是在我加入一个新项目时。我的资深同事,一位优秀的工程师,简单地说:

“看看 Makefile,里面一切都很清晰。”

我打开它,惊恐不已:

  • 大约 600 行代码
  • 到处都是变量
  • 条件逻辑和嵌套依赖

我无法在不在脑中逐行解析数百行语法的情况下,弄清楚如何在本地运行项目。这简直是疯狂。

我想到像 lazygit 这样的工具,它为 Git 提供了漂亮的 TUI,于是想,为什么没有类似的工具用于 Makefile 呢?这激发了我开发自己的 TUI 应用的想法。

开发

我从一个简单的想法开始:显示一个目标列表,让用户挑选一个,运行它,并展示输出。一个使用 Bubble Tea 构建的非常基础的 TUI。第一版只有 200–300 行 Go 代码,却已经可以工作。

此后,我不断添加功能,以解决多年积累的痛点。

依赖图

第一个主要特性是 依赖图。现在,当我需要运行某个目标时,我可以看到:

  • 完整的依赖树
  • 执行顺序
  • 临界路径(决定整体执行时间的最慢链)
  • 并行化机会——哪些可以使用 make -j 运行

在任意目标上按 g 键即可查看图形:

Dependency Graph

仅此一点就让项目变得有价值:我现在可以准确看到某个目标到底做了什么,而不必从 Makefile 中猜测。它还能捕获可能不小心出现的循环依赖。

Source:

变量检查器

Make 的变量系统功能强大,却不透明。诸如以下问题:

  • $(LDFLAGS) 会展开成什么?
  • 哪些目标使用了 $(VERSION)

以前需要在整个文件中 grep。

使用 lazymake 时,只需按 v 键即可打开功能完整的浏览器,显示每个变量、它的定义以及使用位置:

Variable Inspector

过去需要 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 的目标中使用同样的命令会触发确认提示。

它真的帮我避免了不良后果吗?是的——多次。

Safety Features

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 时你最大的痛点是什么?

GitHub | Documentation

如果你觉得这很有用,请给仓库加星 ⭐ 并告诉我你的想法。我始终乐于听取反馈(或抱怨——它们也很有价值)。

Back to Blog

相关文章

阅读更多 »

Lyra:命令行助手

我为助手编写了框架和主循环。之所以选择 CLI 助手而不是语音或 AI 助手,是因为我的硬件限制。我……