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.gocmd/consumer/sync/main.gocmd/cron/cleanup/main.go
时,skill 会把它们稳定映射到:
build-apibuild-consumer-syncbuild-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 规划阶段会优先建立一组核心目标:
helpfmttidytestcoverlintciversionclean
然后再按仓库实际需要补充常见增强目标,例如:
fmt-checkcover-checkinstall-toolscheck-toolsgenerate/generate-checkswaggertest-integrationbenchdocker-build/docker-pushbuild-linux/build-all-platforms
这层设计的价值,是把 Makefile 从“每个仓库一套临时习惯”收敛成“团队可预测入口”。评估里 ci、tidy、install-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-checklinttestcover-check
必要时还会加入:
generate-check
这个设计很成熟,因为 make ci 解决的是“开发者能不能在 push 前本地复现 CI 失败”的问题。它不是给 Makefile 增加一个好看的 target,而是在本地开发和 CI 之间建立稳定桥梁。
4.7 版本注入被要求进入所有 build targets¶
go-makefile-writer 明确要求通过 -ldflags 注入:
versioncommitbuildTime
并把它应用到所有 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.mod 的 go 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 helpmake test- 一个代表性的
build-* make version
必要时再跑:
run-*make lintmake 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 的真正亮点,不是它能写出一个带 .PHONY 的 Makefile,而是它把 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.mk或golden/complex-project.mk中体现的标准结构发生变化。skills/go-makefile-writer/scripts/discover_go_entrypoints.sh的输出字段、分类规则或 target suffix 生成逻辑发生变化。evaluate/go-makefile-writer-skill-eval-report.md或evaluate/go-makefile-writer-skill-eval-report.zh-CN.md中支撑本文判断的核心结果发生变化。
建议按季度复查一次;如果 go-makefile-writer 的命名规则、Refactor 兼容策略或 golden examples 有明显重构,则应立即复查。
10. 相关阅读¶
skills/go-makefile-writer/SKILL.mdskills/go-makefile-writer/references/makefile-quality-guide.mdskills/go-makefile-writer/references/golden/simple-project.mkskills/go-makefile-writer/references/golden/complex-project.mkskills/go-makefile-writer/scripts/discover_go_entrypoints.shevaluate/go-makefile-writer-skill-eval-report.mdevaluate/go-makefile-writer-skill-eval-report.zh-CN.md