关于 makefile-generator
makefile-generator 是为新项目生成 Makefile 的技能,面向需要构建自动化或 CI/CD 集成的开发者。它覆盖 C/C++、Python、Go、Java 和通用项目,并包含需求收集、文档查阅及验证流程。
主要功能
- 01生成多语言 Makefile
- 02提供标准构建目标
- 03遵循 GNU 编码标准
- 04包含安全加固建议
- 05生成后验证与格式处理
适用场景
- 01为 Go 服务创建 Makefile
- 02将手动构建流程转为自动化
- 03为项目配置标准构建目标
- 04集成 CI/CD 构建流程
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ akin-ozer/ cc-devops-skills --skill makefile-generator安装后在 Claude Code 中输入/makefile-generator确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
assets/templates/.gitkeepdocs/makefile-structure.mdoptimization-guide.mdpatterns-guide.mdsecurity-guide.mdtargets-guide.mdvariables-guide.mdscripts/add_standard_targets.shgenerate_makefile_template.shtest/test_helper_scripts.sh详细介绍
Makefile 生成器
概述
为 C/C++、Python、Go、Java 和通用项目生成符合生产要求的 Makefile,并遵循最佳实践。具备符合 GNU 编码标准、提供标准目标、强化安全性等特性,并通过 devops-skills:makefile-validator 技能自动验证。
使用场景
- 从头创建 Makefile
- 为项目设置构建系统(C/C++、Python、Go、Java)
- 实现构建自动化和 CI/CD 集成
- 将手动构建流程转换为 Makefile
- 用户要求“创建”、“生成”或“编写”Makefile
请勿用于: 验证现有 Makefile(使用 devops-skills:makefile-validator)、调试(使用 make -d)或运行构建。
触发短语
当提示类似以下内容时,请使用此技能:
- “为 Go 服务生成 Makefile”
- “创建包含 install/test/help 目标的生产级 Makefile”
- “为带有依赖跟踪的 C 项目编写 Makefile”
- “为此现有 Makefile 添加标准 GNU 目标”
生成工作流
阶段 1:收集需求
收集以下类别的信息。如果信息缺失或含糊,请使用 AskUserQuestion:
| 类别 | 所需信息 |
|---|---|
| 项目 | 语言(C/C++/Python/Go/Java)、结构(单目录/多目录) |
| 构建 | 源文件、输出产物、依赖项、构建顺序 |
| 安装 | PREFIX 位置、目录(bin/lib/share)、要安装的文件 |
| 目标 | all、install、clean、test、dist、help(需要哪些?) |
| 配置 | 编译器、标志、pkg-config 依赖项、交叉编译 |
何时使用 AskUserQuestion(符合以下任一条件时必须询问):
| 条件 | 示例问题 |
|---|---|
| 未指定语言 | “此项目使用什么编程语言?(C/C++/Go/Python/Java)” |
| 项目结构不明确 | “这是单目录项目还是多目录项目?” |
| 用户要求 Docker,但未指定镜像仓库 | “应使用哪个容器镜像仓库?(docker.io/ghcr.io/custom)” |
| 可能生成多个二进制文件 | “应构建单个二进制文件还是多个可执行文件?” |
| 需要安装目标,但路径不明确 | “二进制文件应安装到哪里?(默认:/usr/local/bin)” |
| 提到交叉编译 | “目标平台/架构是什么?” |
何时跳过 AskUserQuestion(采用默认值继续):
- 用户明确提供了所有必需信息
- 项目类型标准且默认值显而易见(例如,“带 Docker 的 Go 项目” → 使用标准的 Go + Docker 模式)
- 用户表示“使用默认值”或“标准设置”
默认假设(不询问时):
- 单目录项目结构
- PREFIX=/usr/local
- 标准目标:all、build、test、clean、install、help
- 不进行交叉编译
阶段 2:文档查询
必须查询时(必须执行查询):
- 用户请求与不熟悉的工具、框架或构建系统集成
- 第 3 阶段示例未涵盖的复杂构建模式(例如 Bazel、Meson、自定义工具链)
- Docker/容器集成(Dockerfile 构建、多阶段构建、推送到注册表)
- 特定于 CI/CD 平台的集成(GitHub Actions、GitLab CI、Jenkins)
- 面向特殊目标平台或嵌入式系统的交叉编译
- 包管理器集成(Conan、vcpkg、Homebrew formulas)
- 多二进制文件或多库项目
- 通过 ldflags 或构建时变量嵌入版本信息
可选查询时(可以跳过外部查询):
- 第 3 阶段已涵盖的标准语言模式(C/C++、Go、Python、Java)
- 没有外部依赖的简单单二进制文件项目
- 用户提供了完整且明确的需求
- 内部文档已全面涵盖所需模式
查询流程(按顺序执行):
-
始终先使用明确的文件打开命令查阅内部文档(主要事实来源):
完整文档路径映射(优先使用完整路径,以确保访问结果一致):
文档 完整路径 结构指南 devops-skills-plugin/skills/makefile-generator/docs/makefile-structure.md变量指南 devops-skills-plugin/skills/makefile-generator/docs/variables-guide.md目标指南 devops-skills-plugin/skills/makefile-generator/docs/targets-guide.md模式指南 devops-skills-plugin/skills/makefile-generator/docs/patterns-guide.md优化指南 devops-skills-plugin/skills/makefile-generator/docs/optimization-guide.md安全指南 devops-skills-plugin/skills/makefile-generator/docs/security-guide.md需求 查阅此文档 Docker/容器目标 .../docs/patterns-guide.md(模式 8:Docker 集成)多二进制文件项目 .../docs/patterns-guide.md(模式 7:多二进制文件项目)含版本信息嵌入的 Go 项目 .../docs/patterns-guide.md(模式 5:Go 项目)并行构建、缓存、ccache .../docs/optimization-guide.md凭据、机密信息、API 密钥 .../docs/security-guide.md复杂依赖、模式规则 .../docs/patterns-guide.md仅排序前置条件 .../docs/optimization-guide.md或.../docs/targets-guide.md变量、赋值运算符 .../docs/variables-guide.md确定性打开/读取命令:
# From repository root: sed -n '1,220p' devops-skills-plugin/skills/makefile-generator/docs/patterns-guide.md rg -n "Pattern 5|Pattern 8" devops-skills-plugin/skills/makefile-generator/docs/patterns-guide.md # From skill directory: sed -n '1,220p' docs/security-guide.md如果无法使用 shell 命令,请使用环境提供的文件打开/读取功能访问相同路径。
必需的工作流示例(Docker + 含版本信息嵌入的 Go):
# Step 1: Read Go pattern rg -n "Pattern 5" devops-skills-plugin/skills/makefile-generator/docs/patterns-guide.md # Step 2: Read Docker pattern rg -n "Pattern 8" devops-skills-plugin/skills/makefile-generator/docs/patterns-guide.md # Step 3: Read security guidance sed -n '1,220p' devops-skills-plugin/skills/makefile-generator/docs/security-guide.md然后生成 Makefile,并在头部注释中列出查阅过的文档。
-
尝试使用 context7 查询外部工具文档(当内部文档未涵盖某个特定工具时):
# Only needed for tools/frameworks NOT covered in internal docs mcp__context7__resolve-library-id: "<tool-name>" mcp__context7__query-docs: query="<integration-topic>" # Example queries: # - For Docker: query="dockerfile best practices" # - For Go: query="go build ldflags" # - For specific tools: query="<tool> makefile integration"**回退方案:**如果 context7 不可用或未返回有用内容,请记录这一情况,然后继续第 3 步。
-
回退到 WebSearch(仅当内部文档或 context7 中找不到相关模式时):
"<specific-feature>" makefile best practices 2025 Example: "docker makefile best practices 2025" Example: "go ldflags version makefile 2025"**触发 WebSearch 的条件:**内部文档未涵盖特定集成,且 context7 未返回相关结果。
**注意:**在回复中注明查阅过哪些内部文档(在生成的 Makefile 头部添加注释)。
阶段 3:生成 Makefile
可选的辅助脚本快捷方式(适用于标准布局):
# Generate template: TYPE NAME OUTPUT
bash scripts/generate_makefile_template.sh go myservice Makefile
# Add only selected standard targets
bash scripts/add_standard_targets.sh Makefile install clean help
当需求较复杂时(Docker 发布流程、多二进制文件矩阵、自定义工具链),请手动编写。
文件头(选择一种样式)
传统样式(兼容 POSIX):
.DELETE_ON_ERROR:
.SUFFIXES:
现代样式(GNU Make 4.0+,推荐):
SHELL := bash
.ONESHELL:
.SHELLFLAGS := -eu -o pipefail -c
.DELETE_ON_ERROR:
.SUFFIXES:
MAKEFLAGS += --warn-undefined-variables
MAKEFLAGS += --no-builtin-rules
标准变量
# User-overridable (use ?=)
CC ?= gcc
CFLAGS ?= -Wall -Wextra -O2
PREFIX ?= /usr/local
DESTDIR ?=
# GNU installation directories
BINDIR ?= $(PREFIX)/bin
LIBDIR ?= $(PREFIX)/lib
INCLUDEDIR ?= $(PREFIX)/include
# Project-specific (use :=)
PROJECT := myproject
VERSION := 1.0.0
SRCDIR := src
BUILDDIR := build
SOURCES := $(wildcard $(SRCDIR)/*.c)
OBJECTS := $(SOURCES:$(SRCDIR)/%.c=$(BUILDDIR)/%.o)
特定语言的构建规则
C/C++:
$(TARGET): $(OBJECTS)
$(CC) $(LDFLAGS) $^ $(LDLIBS) -o $@
$(BUILDDIR)/%.o: $(SRCDIR)/%.c
@mkdir -p $(@D)
$(CC) $(CPPFLAGS) $(CFLAGS) -MMD -MP -c $< -o $@
-include $(OBJECTS:.o=.d)
Go:
$(TARGET): $(shell find . -name '*.go') go.mod
go build -o $@ ./cmd/$(PROJECT)
Python:
.PHONY: build
build:
python -m build
.PHONY: develop
develop:
pip install -e .[dev]
Java:
$(BUILDDIR)/%.class: $(SRCDIR)/%.java
@mkdir -p $(@D)
javac -d $(BUILDDIR) -sourcepath $(SRCDIR) $<
标准目标
.PHONY: all clean install uninstall test help
## Build all targets
all: $(TARGET)
## Install to PREFIX
install: all
install -d $(DESTDIR)$(BINDIR)
install -m 755 $(TARGET) $(DESTDIR)$(BINDIR)/
## Remove built files
clean:
$(RM) -r $(BUILDDIR) $(TARGET)
## Run tests
test:
# Add test commands
## Show help
help:
@echo "$(PROJECT) v$(VERSION)"
@echo "Targets: all, install, clean, test, help"
@echo "Override: make CC=clang PREFIX=/opt"
阶段 4:验证和格式化
每个生成的 Makefile 都必须经过验证。
验证工具预检(默认 + 后备方案)
- 首选方式: 运行
devops-skills:makefile-validator。 - 如果验证器技能不可用: 运行本地后备检查:
# Required fallback check (if make exists) make -f <Makefile> -n --dry-run # Structural fallback checks rg -n '^ {1,}\S' <Makefile> # suspicious space-indented recipe lines rg -n '^\.PHONY:' <Makefile> - 如果
make不可用: 仅运行结构检查,报告“由于缺少 make 二进制文件,验证不完整”,并在声称已达到生产就绪状态之前请求用户确认。
必需的验证循环
1. Generate Makefile following stages above
2. Run validator skill (or fallback checks if unavailable)
3. Fix all errors (MUST have 0 errors before completion)
4. Apply formatting fixes (see "Formatting Step" below)
5. Fix warnings when feasible (SHOULD fix; explain if skipped)
6. Address info items for large/production projects
7. Re-run validation until checks pass
8. Output structured validation report (REQUIRED - see format below)
格式化步骤(必需)
当 mbake 报告格式问题时,你必须执行以下操作之一:
-
自动应用格式化(小问题优先采用此方式):
mbake format <Makefile> -
说明未应用的原因(如果格式化会破坏功能):
Formatting not applied because: - [specific reason, e.g., "heredoc syntax would be corrupted"] - Manual review recommended for: [specific lines]
如果未安装 mbake 或无法执行,则跳过格式化程序的运行,并记录:
Formatting skipped: mbake unavailable in current environment.
格式化决策指南:
| mbake 报告 | 操作 |
|---|---|
| “Would reformat”,且未指出具体问题 | 使用 mbake format 自动应用格式化 |
| 存在具体的空白字符/缩进问题 | 使用 mbake format 自动应用格式化 |
| 问题出现在复杂 heredoc 或多行字符串中 | 跳过格式化,并在输出中说明 |
问题出现在 # bake-format off 区段中 | 跳过(已刻意禁用格式化) |
mbake 命令不可用 | 跳过格式化,并记录工具不可用的原因 |
验证通过标准:
| 级别 | 要求 | 操作 |
|---|---|---|
| 错误(必须为 0) | 语法错误、缺少制表符、无效目标 | 完成前必须修复 |
| 警告(可行时修复) | 格式问题、缺少优化 | 应当修复;如跳过则说明原因 |
| 信息(生产环境需处理) | 改进建议、风格偏好 | 生产环境 Makefile 应当处理 |
已知的 mbake 误报(可安全忽略):
mbake 验证器可能会针对有效的 GNU Make 特殊目标发出警告。这些属于误报,可以忽略:
| mbake 警告 | 实际状态 | 说明 |
|---|---|---|
| “Unknown special target '.DELETE_ON_ERROR'” | ✅ 有效 | 关键的 GNU Make 目标,可删除构建失败的产物 |
| “Unknown special target '.SUFFIXES'” | ✅ 有效 | 用于禁用/设置后缀规则的标准 GNU Make 目标 |
| “Unknown special target '.ONESHELL'” | ✅ 有效 | GNU Make 3.82+ 的功能,可让配方在单个 shell 中执行 |
| “Unknown special target '.POSIX'” | ✅ 有效 | POSIX 合规性声明 |
验证报告输出(必需)
验证完成后,必须按以下格式输出结构化报告。此项为必填。
报告格式要求:
## Validation Report
**Result:** [PASSED / PASSED with warnings / FAILED]
**Errors:** [count]
**Warnings:** [count]
**Info:** [count]
### Errors Fixed
- [List each error and how it was fixed, or "None" if 0 errors]
### Warnings Addressed
- [List each warning that was fixed]
### Warnings Skipped (with reasons)
- [List each warning that was NOT fixed and explain why]
- Example: "mbake reports '.DELETE_ON_ERROR' as unknown - this is a valid GNU Make
special target (false positive)"
### Formatting Applied
- [Yes/No] - [If No, explain why formatting was skipped]
### Info Items Addressed
- [List info items that were addressed for production Makefiles]
- [Or "N/A - simple project" if not applicable]
### Remaining Issues (if any)
- [List any issues requiring user attention]
- [Or "None - Makefile is production-ready"]
完整报告示例:
## Validation Report
**Result:** PASSED with warnings
**Errors:** 0
**Warnings:** 2
**Info:** 1
### Errors Fixed
- None
### Warnings Addressed
- Fixed: Added error handling to install target (|| exit 1)
### Warnings Skipped (with reasons)
- mbake reports ".DELETE_ON_ERROR" as unknown - this is a valid and critical
GNU Make special target that ensures failed builds don't leave corrupt files.
See: https://www.gnu.org/software/make/manual/html_node/Special-Targets.html
### Formatting Applied
- Yes - Applied `mbake format` to fix whitespace issues
### Info Items Addressed
- Added .NOTPARALLEL for Docker targets (parallel safety)
- Added error handling for docker-push target
### Remaining Issues
- None - Makefile is production-ready
需要处理的常见信息项:
| 信息项 | 需要修复的情况 | 修复方法 |
|---|---|---|
| “mkdir 不带仅排序前置条件” | 大型项目(>10 个目标) | 使用 target: prereqs | $(BUILDDIR) 模式 |
| “配方命令缺少错误处理” | 关键操作(安装、部署) | 在 .SHELLFLAGS 中添加 set -e,或使用 && 链接命令 |
| “考虑使用 ccache” | 编译时间较长 | 添加 CC := ccache $(CC) 模式 |
| “检测到对并行敏感的命令” | Docker/npm/pip 目标 | 为受影响的目标添加 .NOTPARALLEL:,或设置正确的依赖关系 |
生产质量要求(Docker/部署目标必须处理):
生成包含 Docker 或部署目标的 Makefile 时,必须应用以下生产环境模式:
-
docker-push 的错误处理:
## Push Docker image to registry (with error handling) docker-push: docker-build @echo "Pushing $(IMAGE)..." docker push $(IMAGE) || { echo "Failed to push $(IMAGE)"; exit 1; } docker push $(IMAGE_LATEST) || { echo "Failed to push $(IMAGE_LATEST)"; exit 1; } -
Docker 目标的并行安全性:
# Prevent parallel execution of Docker targets (race conditions) .NOTPARALLEL: docker-build docker-push docker-run或通过设置正确的依赖关系来串行执行:
docker-push: docker-build # Ensures build completes before push docker-run: docker-build # Ensures build completes before run -
install 目标的错误处理:
install: $(TARGET) install -d $(DESTDIR)$(PREFIX)/bin || exit 1 install -m 755 $(TARGET) $(DESTDIR)$(PREFIX)/bin/ || exit 1
注意: 验证结果中若出现错误处理或并行安全性相关的信息项,则对于任何包含 Docker、deploy 或 install 目标的 Makefile,都必须处理。请在回复中说明应用了哪些模式。
验证清单:
- 语法正确(
make -n通过) - 所有非文件目标都声明了 .PHONY
- 使用 Tab 缩进(而非空格)
- 没有硬编码凭据
- 用户可覆盖的变量使用
?= - 包含 .DELETE_ON_ERROR
- 包含 MAKEFLAGS 优化(Modern 标头)
- 为构建目录设置仅排序前置条件(大型项目)
- 关键配方(install、deploy、docker-push)中包含错误处理
最佳实践
变量
- 用户可覆盖的变量(CC、CFLAGS、PREFIX)使用
?= - 项目专用变量(SOURCES、OBJECTS)使用
:= - 使用 pkg-config:
CFLAGS += $(shell pkg-config --cflags lib)
目标
- 始终为非文件目标声明
.PHONY - 默认目标应为
all - 使用
.DELETE_ON_ERROR确保安全 - 使用
##注释为 help 目标编写文档
目录创建
创建构建目录有两种方式:
简单方式(内联 mkdir):
$(BUILDDIR)/%.o: $(SRCDIR)/%.c
@mkdir -p $(@D)
$(CC) $(CFLAGS) -c $< -o $@
优化方式(仅排序前置条件): 防止目录时间戳变更导致不必要的重建。
$(BUILDDIR):
@mkdir -p $@
$(BUILDDIR)/%.o: $(SRCDIR)/%.c | $(BUILDDIR)
$(CC) $(CFLAGS) -c $< -o $@
对于目标较多的大型项目,使用仅排序前置条件(|)。
配方
- 使用 Tab,切勿使用空格
- 在 shell 中引用变量:
$(RM) "$(TARGET)" - 使用
@前缀使命令静默执行 - 先用
make -n测试
辅助脚本(可选)
这些脚本是用于快速生成模板的可选便捷工具。
何时使用脚本,何时手动生成
| 场景 | 建议 |
|---|---|
| 简单的标准项目(单个二进制文件,无特殊功能) | ✅ 使用 generate_makefile_template.sh 提高效率 |
| 复杂项目(Docker、多二进制文件、自定义模式) | ❌ 手动生成,以便完全掌控 |
| 为现有 Makefile 添加目标 | ✅ 使用 add_standard_targets.sh |
| 用户有特定的格式或风格要求 | ❌ 手动生成 |
| 快速原型开发 / 概念验证 | ✅ 使用脚本,之后再自定义 |
| 可用于生产环境的 Makefile | ⚠️ 先使用脚本,再手动自定义 |
generate_makefile_template.sh
为特定项目类型生成完整的 Makefile 模板。
脚本路径:scripts/generate_makefile_template.sh
bash scripts/generate_makefile_template.sh [TYPE] [NAME] [OUTPUT_FILE]
Types: c, c-lib, cpp, go, python, java, generic
示例:
bash scripts/generate_makefile_template.sh go myservice
# Creates Makefile with Go patterns, version embedding, standard targets
bash scripts/generate_makefile_template.sh go myservice build/Makefile
# Writes template to build/Makefile (TYPE NAME OUTPUT)
add_standard_targets.sh
为现有 Makefile 添加缺失的标准 GNU 目标。
脚本路径:scripts/add_standard_targets.sh
bash scripts/add_standard_targets.sh [MAKEFILE] [TARGETS...]
bash scripts/add_standard_targets.sh [TARGETS...] # uses ./Makefile
Targets: all, install, uninstall, clean, distclean, test, check, help, dist
示例:
bash scripts/add_standard_targets.sh Makefile install uninstall help
# Adds install, uninstall, help targets if they don't exist
bash scripts/add_standard_targets.sh clean test
# Explicit-target mode: modifies ./Makefile
bash scripts/add_standard_targets.sh -n Makefile dist
# Dry-run mode: shows planned changes without editing files
注意: 按照 Stage 3 模式手动生成的结果与此等效,但可进行更多自定义。
辅助脚本回归冒烟测试
修改辅助脚本或模板后运行:
bash test/test_helper_scripts.sh
完成标准
仅当满足以下所有检查项时,才认为任务已完成:
- 已匹配触发条件并澄清缺失的要求(或应用了已记录的默认值)。
- 生成前已通过明确的文件路径打开相关内部文档。
- 生成的 Makefile 已为所有非文件目标完整添加
.PHONY。 - Go 模板包含可选的
go.sum处理和可配置的GO_MAIN入口点。 - 已使用
makefile-validator(首选)运行验证,或运行了已记录的备用检查。 - 已使用
mbake应用格式化;若跳过,则明确说明工具不可用或不兼容的原因。 - 最终回复包含所需的结构化验证报告。
文档
docs/ 中的详细指南:
- makefile-structure.md - 组织、布局、包含文件
- variables-guide.md - 赋值运算符、自动变量
- targets-guide.md - 标准目标、.PHONY、前置条件
- patterns-guide.md - 模式规则、依赖项
- optimization-guide.md - 并行构建、缓存
- security-guide.md - 安全展开、凭据处理