Skip to content

go-makefile-writer skill 解析

go-makefile-writer 是一套面向 Go 仓库根级 Makefile 的设计与重构框架。它的核心设计思想是:Makefile 的作用是把仓库入口、目标命名、版本注入、工具安装、CI 对齐和兼容性约束组织成一组稳定、可读、可演进的工程入口。 因此它把 Create/Refactor 双模式、仓库结构发现、target 规划、Go 版本感知、验证闭环和结构化输出串成了一条明确流程。

1. 定义

go-makefile-writer 用于:

  • 为 Go 仓库创建新的根级 Makefile
  • 在尽量小改动前提下重构已有 Makefile
  • 统一 build、run、test、lint、cover、ci、version、clean 等入口
  • cmd/ 目录结构规划可预测的 per-binary targets
  • 将工具安装、代码生成、Docker、交叉编译等能力纳入统一约定
  • 在 Refactor 模式下保留兼容 alias,避免破坏既有使用方式

它输出的不只是 Makefile 内容,还包括:

  • 当前模式和选择理由
  • Go 版本、仓库布局、entrypoints 发现结果
  • 新增或修改的 targets
  • deprecated / aliased targets
  • 假设与缺失工具
  • 实际执行过的验证命令及结果

从设计上看,它更像一个“Go 仓库命令面设计器”,而不是一个只会生成 Make 语法的模板工具。

2. 背景与问题

这个 skill 要解决的,不是“大家不会写 Makefile”,而是 Go 仓库里的 Makefile 经常出现几类更本质的问题:

  • target 命名和仓库入口结构脱节
  • 本地、CI、工具安装、版本注入各自为政
  • 仓库已经有人在用旧 target,但重构时直接破坏兼容性

如果没有清晰框架,常见问题通常集中在 8 类:

问题 典型后果
target 命名不随 cmd/ 结构变化 单二进制时叫 build,多二进制后必须整体重命名
缺少统一 core targets 团队不知道标准入口是什么,CI 也难与本地对齐
install-tools 缺失或使用 @latest CI 不可复现,lint / codegen 漂移
build targets 不做版本注入 二进制缺少可追踪的 version / commit / build time
test / cover / lint 规则不统一 开发者本地通过,但 CI 行为不同
Refactor 时大改文件 审阅成本高,也更容易破坏现有脚本调用
target 重命名不保留 alias shell 脚本、CI 和团队习惯一起断裂
输出不结构化 团队不知道改了哪些入口、为什么这样命名、验证是否真正执行

go-makefile-writer 的设计逻辑,就是先把“仓库有哪些入口、哪些约束必须保留”查清楚,再把“Makefile 应该如何组织”系统化。

3. 与常见替代方案的对比

先看它与几种常见做法的区别:

维度 go-makefile-writer skill 直接让模型“写个 Makefile” 手工零散维护 Makefile
cmd/ 语义驱动的命名
Create/Refactor 区分
向后兼容性
工具安装与版本锁定
ci target 规范化
版本注入纪律
输出契约
anti-pattern 规避

它的价值,不只是生成一个可运行的 Makefile,而是把 Makefile 设计从“命令集合”提升成“仓库标准入口层”。

4. 核心设计逻辑

4.1 先区分 Create 和 Refactor 两种模式

go-makefile-writer 的第一步不是直接写内容,而是先选 Create 还是 Refactor

这是一个非常关键的设计,因为:

  • 新建 Makefile 没有兼容性包袱,可以按完整 target 体系生成
  • 重构已有 Makefile 时,最重要的问题不是“写得更漂亮”,而是“能不能在修问题的同时不破坏已有调用”

skill 因此在 Refactor 模式中明确要求:

  • 最小差异修改
  • 保留现有有价值 targets
  • target 改名时保留 alias
  • 对比改动前后的 target list

这说明它不把“生成”与“重构”混为一谈,而是把兼容性成本放进了设计本身。

4.2 优先做 entrypoint discovery

skill 优先使用 scripts/discover_go_entrypoints.sh,在脚本不可用时再回退到基于 rg 的发现方式。它的目标,是从 cmd/**/main.go 中提取:

  • kind
  • name
  • target_name(目标名后缀)
  • dir

这层设计的价值在于,它把 target 命名从主观发挥,变成仓库结构驱动的结果。特别是当目录是:

  • cmd/api/main.go
  • cmd/consumer/sync/main.go
  • cmd/cron/cleanup/main.go

时,skill 会把它们稳定映射到:

  • build-api
  • build-consumer-sync
  • build-cron-cleanup

评估里最大的单项差异,恰好就来自这层规则:without-skill 在单二进制场景容易退回泛化的 build / run,而 with-skill 保持了和 cmd/ 路径一致的命名。

4.3 把命名规范当成核心规则 vs 书写偏好

go-makefile-writer 明确要求 target 名称映射 cmd/ 语义:

  • cmd/<name>build-<name> / run-<name>
  • cmd/<kind>/<name>build-<kind>-<name> / run-<kind>-<name>

这不是表面上的风格要求,而是非常实际的可扩展性设计。因为如果单二进制仓库先用 build / run,等仓库长成多二进制后就会出现两个问题:

  • 原 target 名称失去语义
  • CI、脚本、团队习惯都要跟着改

也就是说,这个命名规则解决的不是“更整齐”,而是“仓库从简单演进到复杂时,不必推倒重来”。

4.4 core target set 要标准化

skill 在 target 规划阶段会优先建立一组核心目标:

  • help
  • fmt
  • tidy
  • test
  • cover
  • lint
  • ci
  • version
  • clean

然后再按仓库实际需要补充常见增强目标,例如:

  • fmt-check
  • cover-check
  • install-tools
  • check-tools
  • generate / generate-check
  • swagger
  • test-integration
  • bench
  • docker-build / docker-push
  • build-linux / build-all-platforms

这层设计的价值,是把 Makefile 从“每个仓库一套临时习惯”收敛成“团队可预测入口”。评估里 citidyinstall-tools 的稳定通过率优势,本质上都来自这组标准化 target 集合。

4.5 特别强调 install-tools 和版本锁定

在很多 baseline Makefile 里,lint target 会直接:

  • 省略工具安装
  • 或者在运行时自动 go install ...@latest

go-makefile-writer 对可复现性很敏感,因此会优先推动以下模式:

  • 工具安装入口独立到 install-tools
  • 在 CI 或需要可复现的场景里精确锁定版本
  • check-tools 或等价的清晰失败提示暴露缺失工具

这层设计非常重要,因为它解决的是 CI 可复现性,而不是单次本地可运行性。评估报告在大多数场景里都体现了这一项的明显差距,也说明这个 skill 最强的价值之一不是“Make 语法写得好”,而是它明确知道哪些 target 必须服务于可重复的工程流程。

4.6 ci target 被当成一等公民

skill 明确规定 ci 不是可有可无的别名,而是应该镜像真实 CI pipeline 的核心入口。

这意味着它通常至少要串起:

  • fmt-check
  • lint
  • test
  • cover-check

必要时还会加入:

  • generate-check

这个设计很成熟,因为 make ci 解决的是“开发者能不能在 push 前本地复现 CI 失败”的问题。它不是给 Makefile 增加一个好看的 target,而是在本地开发和 CI 之间建立稳定桥梁。

4.7 版本注入被要求进入所有 build targets

go-makefile-writer 明确要求通过 -ldflags 注入:

  • version
  • commit
  • buildTime

并把它应用到所有 build targets。

这层设计解决的是二进制可追踪性。很多 baseline Makefile 会构建出可运行程序,但不会留下足够版本信息,导致排障和发布管理都很弱。skill 在这里的重点不是“让 build 命令更复杂”,而是让产物成为可追踪资产。

4.8 Refactor 模式要保留 alias 和前后 target 对比

在已有 Makefile 上重构时,skill 要求:

  • 先快照旧 target 列表
  • 验证关键旧 target 仍可用,或者有 alias
  • 输出 deprecated / aliased targets

这是一种非常强的演进意识。很多 Makefile 重构失败,并不是因为新设计不好,而是因为:

  • 团队脚本仍在调用旧 target
  • CI job 仍引用旧名称
  • 文档和人肉习惯没有同步

因此 go-makefile-writer 在 Refactor 模式中真正保护的,不只是文件内容,而是仓库周边生态的稳定性。

4.9 Go Version Awareness 被单独纳入规则

这个 skill 要求读取 go.modgo directive,并根据版本做保守决策。例如:

  • < 1.16 的工具安装方式不同
  • < 1.18 没有 go build -cover
  • >= 1.21 可以考虑 integration coverage 相关 target
  • >= 1.22 没有直接 Makefile 行为变化,但要在输出里记录

这层设计很值得保留,即使评估场景没有把这部分价值完全测出来。原因很简单:Makefile 是长期资产,版本相关行为一旦写错,后续迁移成本会很高。skill 在这里体现的是“面向未来维护”的意识,而不是只针对当前场景凑出一个能跑的文件。

4.10 monorepo support 和 explicit targets 能同时存在

go-makefile-writer 一方面支持 monorepo / 多模块 layout,另一方面又明确反对过度动态的 Make 元编程。

这两点并不冲突。它的设计立场其实很清楚:

  • 当仓库结构变复杂时,可以增加聚合 targets 和模块级 targets
  • 但如果 explicit targets 更清晰,就不要为了 DRY 而引入难读的 eval/call/define

评估里的复杂场景也验证了这一点:without-skill 会更自然地走向动态模板,而 with-skill 会更稳定地维持显式 per-binary targets。它优先优化的是可读性和可调试性,而不是模板技巧。

4.11 验证与输出契约绑定

go-makefile-writer 不只要求写文件,还要求报告:

  • mode
  • Go version / layout / entrypoints
  • changed files
  • new / updated targets
  • deprecated / aliased targets
  • assumptions / missing tools
  • validation commands executed

同时它还要求实际运行:

  • make help
  • make test
  • 一个代表性的 build-*
  • make version

必要时再跑:

  • run-*
  • make lint
  • make ci

这层设计的价值,是把 “写 Makefile” 从文本生成升级成“有验证证据的工程修改”。评估也表明,baseline 模型就算能写出还不错的 Makefile,通常也不会补这一层可审计的交付说明。

5. 这个设计解决了哪些具体问题

结合当前 SKILL.md、quality guide、golden examples、discovery 脚本和评估报告,可以把它解决的问题归纳为:

问题类型 skill 中的对应设计 实际效果
cmd/ 与 target 命名脱节 entrypoint discovery + naming convention 生成稳定、可扩展的 target 名称
本地入口不统一 core target set + ci target 提供团队可预测的标准入口
工具安装不可复现 install-tools + pinned versions 保持 CI 和本地工具行为稳定
二进制缺少构建元信息 -ldflags version injection 提高发布与排障可追踪性
重构破坏现有脚本 Refactor mode + aliases 降低改名和收敛成本
Makefile 越写越动态难懂 anti-pattern rules + golden examples 优先 explicit、可维护结构
仓库版本差异被忽略 Go Version Awareness 避免不适配的 Make 规则
改动无法审计 输出契约 + validation report 团队能看到入口、假设、兼容性和验证结果

6. 主要亮点

6.1 它把 Makefile 当成“仓库标准入口层”

这是整个 skill 最核心的定位。Makefile 不只是命令容器,而是团队对 build / test / lint / run / ci 入口的统一约定。

6.2 cmd/ 语义驱动命名是最大亮点之一

评估里最大的单项差异,就来自这一层。它非常朴素,但对长期扩展特别重要。

6.3 对 Refactor 模式的兼容性约束做得很扎实

最小差异修改、target alias、前后 target 对比,这些都说明它在重构场景下不是“重写”,而是在做可控收敛。

6.4 对 CI 可复现性有很强工程意识

install-tools、版本锁定、ci target 对齐、check-tools,这些规则共同保证 Makefile 不只是本地可用,而是长期可复现。

6.5 Golden examples 和 anti-pattern 组合得很好

它既给出正面模板,也明确告诉你哪些 Make 技巧不要用。这种“正反两侧都约束”的设计,比单纯给模板更稳。

6.6 当前版本的价值,不只在生成,更在于约束

评估最强地验证了它在命名规范、tool pinning、ci target 和输出契约上的价值。与此同时,当前 skill 还把 Go 版本感知、monorepo support、向后兼容性等内容也纳入了体系。因此它更像一套 Makefile 设计规范,而不只是一个生成器。

7. 什么时候适合用,什么时候不该硬用

场景 是否适合 原因
新建 Go 仓库根级 Makefile 适合 这是它的核心场景
重构质量一般但已有用户的 Makefile 非常适合 Refactor 模式和 alias 机制很有价值
多二进制 Go 服务 非常适合 cmd/ 语义驱动 target 规划特别有用
带 Docker / codegen / cross-compile 的仓库 适合 skill 已包含相关模式
monorepo / 多模块 Go 仓库 适合 但要进入额外布局处理
非 Go 项目 不适合 超出 skill 范围
只想临时跑两三个命令、不需要统一入口 不一定适合 Makefile 的结构化收益可能不明显

8. 结论

go-makefile-writer 的真正亮点,不是它能写出一个带 .PHONYMakefile,而是它把 Go 仓库入口设计里最容易被忽略的工程判断系统化了:先识别 entrypoints 和布局,再决定命名体系、标准 target 集合、版本注入与工具安装策略,重构时同时兼顾最小差异修改和向后兼容性,最后再用结构化输出和实际验证把整个改动说明白。

从设计上看,这个 skill 很清楚地体现了一条原则:好的 Makefile 不是命令越多越好,而是入口稳定、语义清楚、CI 可复现、仓库演进时不容易被迫整体推翻。 这也是它特别适合 Go 仓库 Makefile 创建与收敛的原因。

9. 文档维护

当以下内容发生变化时,这份文档应该同步更新:

  • skills/go-makefile-writer/SKILL.md 中的 执行模式、工作流程、Rules、Go Version Awareness、Monorepo Support、输出契约 或 Anti-Patterns 发生变化。
  • skills/go-makefile-writer/references/makefile-quality-guide.md 中关于 target 集、tool pinning、ci 规则、版本注入或向后兼容性的关键规则发生变化。
  • skills/go-makefile-writer/references/golden/simple-project.mkgolden/complex-project.mk 中体现的标准结构发生变化。
  • skills/go-makefile-writer/scripts/discover_go_entrypoints.sh 的输出字段、分类规则或 target suffix 生成逻辑发生变化。
  • evaluate/go-makefile-writer-skill-eval-report.mdevaluate/go-makefile-writer-skill-eval-report.zh-CN.md 中支撑本文判断的核心结果发生变化。

建议按季度复查一次;如果 go-makefile-writer 的命名规则、Refactor 兼容策略或 golden examples 有明显重构,则应立即复查。

10. 相关阅读

  • skills/go-makefile-writer/SKILL.md
  • skills/go-makefile-writer/references/makefile-quality-guide.md
  • skills/go-makefile-writer/references/golden/simple-project.mk
  • skills/go-makefile-writer/references/golden/complex-project.mk
  • skills/go-makefile-writer/scripts/discover_go_entrypoints.sh
  • evaluate/go-makefile-writer-skill-eval-report.md
  • evaluate/go-makefile-writer-skill-eval-report.zh-CN.md