makefile
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseMakefile Helper
Makefile 助手
Create Makefiles that are simple, discoverable, and maintainable.
创建简单、易发现、可维护的Makefile。
Core Principles
核心原则
- Default to rich help - Use categorized help with emoji headers unless user requests minimal
- Ask about structure upfront - For new Makefiles, ask: "Flat or modular? Rich help or minimal?"
- Follow existing conventions - Match the project's style if Makefile already exists
- Don't over-engineer - Solve the immediate need, not hypothetical futures
- Use - Always run Python commands via
uv runfor venv contextuv run - Explain decisions - If choosing flat/minimal, explain why before generating
- 默认提供丰富帮助 - 除非用户要求极简版本,否则使用带emoji标题的分类帮助
- 提前确认结构 - 对于新的Makefile,询问:「扁平结构还是模块化结构?丰富帮助还是极简帮助?」
- 遵循现有约定 - 如果项目已存在Makefile,匹配项目原有风格
- 不要过度设计 - 解决当前需求即可,无需考虑假设的未来场景
- 使用- 始终通过
uv run运行Python命令以继承虚拟环境上下文uv run - 解释决策逻辑 - 如果选择扁平/极简结构,生成前先说明原因
When to Use This Skill
适用场景
- Creating a new Makefile for a project
- Adding specific targets to an existing Makefile
- Improving/refactoring an existing Makefile
- Setting up CI/CD make targets
- Distributing pre-built binaries via GitHub Releases
- 为项目创建全新的Makefile
- 向现有Makefile添加特定目标
- 优化/重构现有Makefile
- 设置CI/CD对应的make目标
- 通过GitHub Releases分发预构建二进制文件
Quick Start
快速开始
For new projects, use the appropriate template:
| Project Type | Template | Complexity |
|---|---|---|
| Any project | | Minimal |
| Python with uv | | Standard |
| Python FastAPI | | Full-featured |
| Node.js | | Standard |
| Go | | Standard |
| Chrome Extension | | Modular |
| Flutter App | | Modular |
对于新项目,使用对应模板即可:
| 项目类型 | 模板 | 复杂度 |
|---|---|---|
| 任意项目 | | 极简 |
| 使用uv的Python项目 | | 标准 |
| Python FastAPI项目 | | 全功能 |
| Node.js项目 | | 标准 |
| Go项目 | | 标准 |
| Chrome 扩展 | | 模块化 |
| Flutter 应用 | | 模块化 |
Chrome Extension Structure
Chrome 扩展结构
The chrome extension template uses a modular structure:
Makefile # Main file with help + includes
makefiles/
colors.mk # ANSI colors & print helpers
common.mk # Shell flags, VERBOSE mode, guards
build.mk # Build zip, version bump, releases
dev.mk # Test, lint, clean, installCopy from to your project's directory.
templates/chrome-extension-modules/makefiles/Key features:
- - Version bump menu (major/minor/patch) + zip for Chrome Web Store
build-release - - (Optional) GitHub releases with
build-betaCLIgh - /
dev-test- Vitest + Playwright testingdev-test-e2e - - Show commands for debugging
VERBOSE=1 make <target>
Chrome扩展模板使用模块化结构:
Makefile # 主文件,包含帮助信息和引入声明
makefiles/
colors.mk # ANSI颜色与打印辅助函数
common.mk # Shell标志、VERBOSE模式、防护逻辑
build.mk # 构建zip包、版本号升级、发布
dev.mk # 测试、 lint、清理、安装将下的文件复制到项目的目录即可。
templates/chrome-extension-modules/makefiles/核心功能:
- - 版本号升级菜单(主版本/次版本/修订版)+ 生成Chrome应用商店所需的zip包
build-release - - (可选)通过
build-betaCLI发布到GitHub releasesgh - /
dev-test- Vitest + Playwright 测试dev-test-e2e - - 显示执行的命令用于调试
VERBOSE=1 make <target>
Flutter App Structure
Flutter 应用结构
Makefile # Main file with help + includes
makefiles/
colors.mk # ANSI colors & print helpers
common.mk # Shell flags, VERBOSE mode, guards
dev.mk # Setup, run simulator/device, devices, clean
build.mk # iOS/Android builds (IPA, APK, AAB)
deploy.mk # TestFlight upload
lint.mk # Dart analyze & formatCopy from to your project's directory.
templates/flutter-modules/makefiles/Key features:
- auto-boots simulator and waits for it
flutter-run-ios - auto-launches emulator and waits for it
flutter-run-android - auto-detects or uses
flutter-run-device/FLUTTER_IOS_DEVICEFLUTTER_ANDROID_DEVICE - +
flutter-build-ipafull iOS release workflowflutter-deploy-testflight - Dart formatting with FIX pattern
flutter-lint FIX=true - show commands for debugging
VERBOSE=1 make <target>
Makefile # 主文件,包含帮助信息和引入声明
makefiles/
colors.mk # ANSI颜色与打印辅助函数
common.mk # Shell标志、VERBOSE模式、防护逻辑
dev.mk # 环境配置、运行模拟器/真机、设备列表、清理
build.mk # iOS/Android构建(IPA、APK、AAB)
deploy.mk # 上传到TestFlight
lint.mk # Dart 静态分析与格式化将下的文件复制到项目的目录即可。
templates/flutter-modules/makefiles/核心功能:
- 自动启动模拟器并等待就绪
flutter-run-ios - 自动启动安卓模拟器并等待就绪
flutter-run-android - 自动检测设备,或使用
flutter-run-device/FLUTTER_IOS_DEVICE指定设备FLUTTER_ANDROID_DEVICE - +
flutter-build-ipa完整iOS发布工作流flutter-deploy-testflight - 带修复功能的Dart格式化
flutter-lint FIX=true - 显示执行的命令用于调试
VERBOSE=1 make <target>
Interaction Pattern
交互模式
- Understand - What specific problem are we solving?
- Check existing - Is there already a Makefile? Read it first!
- Default to modular - For 5+ targets, use modular structure unless user requests flat
- Match preferences - Use python-fastapi.mk template style as default for rich help
- Explain structure - If you choose flat/minimal, explain the reasoning
- Iterate - Add complexity or simplify based on feedback
- 理解需求 - 明确我们要解决的具体问题是什么?
- 检查现有文件 - 是否已经存在Makefile?先阅读现有内容!
- 默认使用模块化 - 目标超过5个时,除非用户要求扁平结构,否则默认使用模块化结构
- 匹配用户偏好 - 默认使用python-fastapi.mk模板的丰富帮助风格
- 说明结构选择 - 如果选择扁平/极简结构,解释选择的原因
- 迭代优化 - 根据反馈增加复杂度或简化
Naming Conventions
命名规范
Use kebab-case with consistent prefix-based grouping:
makefile
undefined使用kebab-case命名,通过前缀统一分组:
makefile
undefinedGood - consistent prefixes (hyphens, not underscores)
好的示例 - 前缀统一(使用连字符,不使用下划线)
build-release, build-zip, build-clean # Build tasks
dev-run, dev-test, dev-lint # Development tasks
db-start, db-stop, db-migrate # Database tasks
env-local, env-prod, env-show # Environment tasks
build-release, build-zip, build-clean # 构建相关任务
dev-run, dev-test, dev-lint # 开发相关任务
db-start, db-stop, db-migrate # 数据库相关任务
env-local, env-prod, env-show # 环境相关任务
Internal targets - prefix with underscore to hide from help
内部目标 - 下划线前缀,不会出现在帮助中
_build-zip-internal, _prompt-version # Not shown in make help
_build-zip-internal, _prompt-version # 不会在make help中显示
Bad - inconsistent
不好的示例 - 不统一
run-dev, build, localEnv, test_net
build_release, dev_test # Underscores - don't use
**Name targets after the action, not the tool:**
```makefilerun-dev, build, localEnv, test_net
build_release, dev_test # 不要使用下划线
**目标按动作命名,不要按工具命名:**
```makefileGood - describes what it does
好的示例 - 描述功能
remove-bg # Removes background from image
format-code # Formats code
lint-check # Runs linting
remove-bg # 移除图片背景
format-code # 格式化代码
lint-check # 执行lint检查
Bad - names the tool
不好的示例 - 只写工具名
rembg # What does this do?
prettier # Is this running prettier or configuring it?
eslint # Unclear
undefinedrembg # 不知道是做什么的?
prettier # 是运行prettier还是配置prettier?
eslint # 含义不明确
undefinedKey Patterns
核心模式
Binary Distribution
二进制分发
For projects distributed as pre-built binaries via GitHub Releases:
makefile
GITHUB_REPO ?= owner/repo
OS := $(shell uname -s | tr '[:upper:]' '[:lower:]')
ARCH := $(shell uname -m | sed 's/x86_64/amd64/' | sed 's/aarch64/arm64/')
.PHONY: install-cli
install-cli: ## Download and install CLI from latest GitHub release
@RELEASE=$$(curl -fsSL https://api.github.com/repos/$(GITHUB_REPO)/releases/latest | grep tag_name | cut -d'"' -f4); \
echo "Installing $$RELEASE for $(OS)/$(ARCH)..."; \
curl -fsSL -o ~/.local/bin/cli \
"https://github.com/$(GITHUB_REPO)/releases/download/$$RELEASE/cli-$(OS)-$(ARCH)"; \
chmod +x ~/.local/bin/cliKey considerations:
- Detect OS and architecture automatically
- Download from GitHub Releases (no Python/uv required)
- Install to (user-writable, in PATH)
~/.local/bin - Preserve existing config files during updates
对于通过GitHub Releases分发预构建二进制文件的项目:
makefile
GITHUB_REPO ?= owner/repo
OS := $(shell uname -s | tr '[:upper:]' '[:lower:]')
ARCH := $(shell uname -m | sed 's/x86_64/amd64/' | sed 's/aarch64/arm64/')
.PHONY: install-cli
install-cli: ## 从最新GitHub release下载并安装CLI
@RELEASE=$$(curl -fsSL https://api.github.com/repos/$(GITHUB_REPO)/releases/latest | grep tag_name | cut -d'"' -f4); \
echo "正在为$(OS)/$(ARCH)安装$$RELEASE..."; \
curl -fsSL -o ~/.local/bin/cli \
"https://github.com/$(GITHUB_REPO)/releases/download/$$RELEASE/cli-$(OS)-$(ARCH)"; \
chmod +x ~/.local/bin/cli核心注意点:
- 自动检测操作系统和架构
- 从GitHub Releases下载(无需Python/uv)
- 安装到(用户可写,默认在PATH中)
~/.local/bin - 更新时保留现有配置文件
Always Use uv run
for Python
uv runPython命令始终使用uv run
uv runmakefile
undefinedmakefile
undefinedGood - uses uv run with ruff (modern tooling)
好的示例 - 结合现代工具链使用uv run
dev-check:
uv run ruff check src/ tests/
uv run ruff format --check src/ tests/
uv run mypy src/
dev-format:
uv run ruff check --fix src/ tests/
uv run ruff format src/ tests/
dev-check:
uv run ruff check src/ tests/
uv run ruff format --check src/ tests/
uv run mypy src/
dev-format:
uv run ruff check --fix src/ tests/
uv run ruff format src/ tests/
Bad - relies on manual venv activation
不好的示例 - 依赖手动激活虚拟环境
dev-format:
ruff format .
undefineddev-format:
ruff format .
undefinedUse uv sync
(not pip install)
uv sync使用uv sync
(不要用pip install)
uv syncmakefile
env-install:
uv sync # Uses pyproject.toml + lock filemakefile
env-install:
uv sync # 使用pyproject.toml + lock文件Categorized Help (for 5+ targets)
分类帮助(目标超过5个时使用)
makefile
help:
@printf "$(BOLD)=== 🚀 API ===$(RESET)\n"
@printf "$(CYAN)%-25s$(RESET) %s\n" "api-run" "Start server"
@printf "%-25s $(GREEN)make api-run [--reload]$(RESET)\n" ""Makefile ordering rule - help targets go LAST, just before catch-all:
- Configuration (variables)
?= - definition
HELP_PATTERNS - Imports ()
include ./makefiles/*.mk - Main targets (grouped by function)
- and
help:targetshelp-unclassified: - Catch-all rule (absolute last)
%:
makefile
help:
@printf "$(BOLD)=== 🚀 API ===$(RESET)\n"
@printf "$(CYAN)%-25s$(RESET) %s\n" "api-run" "启动服务"
@printf "%-25s $(GREEN)make api-run [--reload]$(RESET)\n" ""Makefile顺序规则 - 帮助目标放在最后,紧接在全局捕获规则之前:
- 配置(定义的变量)
?= - 定义
HELP_PATTERNS - 引入其他文件()
include ./makefiles/*.mk - 主目标(按功能分组)
- 和
help:目标help-unclassified: - 全局捕获规则(绝对放在最后)
%:
Preflight Checks
前置检查
makefile
_check-docker:
@docker info >/dev/null 2>&1 || { echo "Docker not running"; exit 1; }
db-start: _check-docker # Runs check first
docker compose up -dmakefile
_check-docker:
@docker info >/dev/null 2>&1 || { echo "Docker未运行"; exit 1; }
db-start: _check-docker # 先执行检查
docker compose up -dExternal Tool Dependencies
外部工具依赖
When a target requires an external tool (not a system service):
- Don't create public install targets (no )
make install-foo - Use internal check as dependency (prefix with , no
_comment)## - Show install command on failure - tell user what to run, don't do it for them
makefile
undefined当目标需要外部工具(非系统服务)时:
- 不要创建公开的安装目标(不要写)
make install-foo - 使用内部检查作为依赖(下划线前缀,不带注释)
## - 失败时显示安装命令 - 告诉用户需要执行什么命令,不要自动帮用户安装
makefile
undefinedInternal check - hidden from help (no ##)
内部检查 - 不在帮助中显示(无##)
_check-rembg:
@command -v rembg >/dev/null 2>&1 || {
printf "$(RED)$(CROSS) rembg not installed$(RESET)\n";
printf "$(YELLOW)Run: uv tool install "rembg[cli]"$(RESET)\n";
exit 1;
}
printf "$(RED)$(CROSS) rembg not installed$(RESET)\n";
printf "$(YELLOW)Run: uv tool install "rembg[cli]"$(RESET)\n";
exit 1;
}
_check-rembg:
@command -v rembg >/dev/null 2>&1 || {
printf "$(RED)$(CROSS) 未安装rembg$(RESET)\n";
printf "$(YELLOW)执行:uv tool install "rembg[cli]"$(RESET)\n";
exit 1;
}
printf "$(RED)$(CROSS) 未安装rembg$(RESET)\n";
printf "$(YELLOW)执行:uv tool install "rembg[cli]"$(RESET)\n";
exit 1;
}
Public target - uses check as dependency
公开目标 - 依赖检查逻辑
.PHONY: remove-bg
remove-bg: _check-rembg ## Remove background from image
rembg i "$(IN)" "$(OUT)"
**Key points:**
- Name target after the action (`remove-bg`), not the tool (`rembg`)
- Check runs automatically - user just runs `make remove-bg`
- If tool missing, user sees exactly what command to run.PHONY: remove-bg
remove-bg: _check-rembg ## 移除图片背景
rembg i "$(IN)" "$(OUT)"
**核心要点:**
- 按动作命名目标(`remove-bg`),不要按工具命名(`rembg`)
- 检查自动执行 - 用户只需运行`make remove-bg`
- 如果工具未安装,用户可以直接看到需要执行的命令Env File Loading
环境文件加载
Load and export to child processes:
.envmakefile
undefined加载文件并导出到子进程:
.envmakefile
undefinedAt top of Makefile, after .DEFAULT_GOAL
在Makefile顶部,.DEFAULT_GOAL之后
-include .env
.EXPORT_ALL_VARIABLES:
For per-target env override:
```makefile-include .env
.EXPORT_ALL_VARIABLES:
按目标覆盖环境变量:
```makefileAllow: E2E_ENV=.test.env make test-e2e
支持:E2E_ENV=.test.env make test-e2e
test-e2e:
@set -a && . "$${E2E_ENV:-.env}" && set +a && uv run pytest tests/e2e/
undefinedtest-e2e:
@set -a && . "$${E2E_ENV:-.env}" && set +a && uv run pytest tests/e2e/
undefinedFIX Variable for Check/Format Targets
检查/格式化目标的FIX变量
Use a variable to toggle between check-only and auto-fix modes:
FIXmakefile
FIX ?= false
dev-check: ## Run linting and type checks (FIX=false: check only)
$(call print_section,Running checks)
ifeq ($(FIX),true)
uv run ruff check --fix src/ tests/
uv run ruff format src/ tests/
else
uv run ruff check src/ tests/
uv run ruff format --check src/ tests/
endif
uv run mypy src/
$(call print_success,All checks passed)In help output, show usage:
makefile
@printf "$(CYAN)%-25s$(RESET) %s\n" "dev-check" "Run linting (FIX=false: check only)"
@printf "%-25s $(GREEN)make dev-check FIX=true$(RESET) <- auto-fix issues\n" ""使用变量切换仅检查和自动修复模式:
FIXmakefile
FIX ?= false
dev-check: ## 执行lint和类型检查(FIX=false:仅检查)
$(call print_section,执行检查)
ifeq ($(FIX),true)
uv run ruff check --fix src/ tests/
uv run ruff format src/ tests/
else
uv run ruff check src/ tests/
uv run ruff format --check src/ tests/
endif
uv run mypy src/
$(call print_success,所有检查通过)在帮助输出中说明用法:
makefile
@printf "$(CYAN)%-25s$(RESET) %s\n" "dev-check" "执行lint检查(FIX=false:仅检查)"
@printf "%-25s $(GREEN)make dev-check FIX=true$(RESET) <- 自动修复问题\n" ""When to Modularize
什么时候使用模块化
Default to modular for any new Makefile with 5+ targets.
Use flat file only when:
- Simple scripts or single-purpose tools
- User explicitly requests it
- < 5 targets with no expected growth
Standard modular structure:
Makefile # Config, imports, help, catch-all
makefiles/
colors.mk # ANSI colors & print helpers
common.mk # Shell flags, VERBOSE, guards
<domain>.mk # Actual targets (build.mk, dev.mk, etc.)目标超过5个的新Makefile默认使用模块化结构。
仅在以下情况使用扁平文件:
- 简单脚本或单一用途工具
- 用户明确要求
- 目标少于5个且预期不会增加
标准模块化结构:
Makefile # 配置、引入、帮助、全局捕获
makefiles/
colors.mk # ANSI颜色与打印辅助函数
common.mk # Shell标志、VERBOSE、防护逻辑
<领域>.mk # 实际目标(build.mk、dev.mk等)Legacy Compatibility
遗留兼容
Default: NO legacy aliases. Only add when:
- User explicitly requests backwards compatibility
- Existing CI/scripts depend on old names (verify with )
rg "make old-name"
When legacy IS needed, put them in a clearly marked section AFTER main targets but BEFORE help:
makefile
############################默认不添加遗留别名。 仅在以下情况添加:
- 用户明确要求向后兼容
- 现有CI/脚本依赖旧名称(通过验证)
rg "make old-name"
需要兼容遗留时,放在主目标之后、帮助目标之前的明确标记区域:
makefile
############################Legacy Target Aliases
遗留目标别名
############################
.PHONY: old-name
old-name: new_name ## (Legacy) Description
undefined############################
.PHONY: old-name
old-name: new_name ## (遗留)描述
undefinedKey Rules
核心规则
- Always read existing Makefile before changes
- Search codebase before renaming targets ()
rg "make old-target" - Test with and
make helpmake -n target - Update docs after Makefile changes - When adding new targets:
- Add to output (in the appropriate section)
make help - Update if the project has one (document new targets)
CLAUDE.md - Update any other relevant docs (README.md, Agents.md, etc.)
- Add to
- Never add targets without clear purpose
- No line-specific references - Avoid patterns like "Makefile:44" in docs/comments; use target names instead
- Single source of truth - Config vars defined once in root Makefile, not duplicated in modules
- Help coverage audit - All targets with must appear in either
##ormake helpmake help-unclassified
- 修改前始终先阅读现有Makefile
- 重命名目标前搜索代码库()
rg "make old-target" - 使用和
make help测试make -n target - Makefile修改后更新文档 - 新增目标时:
- 添加到输出的对应分类中
make help - 如果项目有,更新该文件记录新目标
CLAUDE.md - 更新其他相关文档(README.md、Agents.md等)
- 添加到
- 不要添加无明确用途的目标
- 不要引用行号 - 避免在文档/注释中使用类似「Makefile:44」的模式,改用目标名称
- 单一数据源 - 配置变量在根Makefile中定义一次,不要在模块中重复定义
- 帮助覆盖度审计 - 所有带的目标必须出现在
##或make help中make help-unclassified
Help System
帮助系统
ASCII box title for visibility:
makefile
help:
@printf "\n"
@printf "$(BOLD)$(CYAN)╔═══════════════════════════╗$(RESET)\n"
@printf "$(BOLD)$(CYAN)║ Project Name ║$(RESET)\n"
@printf "$(BOLD)$(CYAN)╚═══════════════════════════╝$(RESET)\n\n"Categorized help with sections:
makefile
@printf "$(BOLD)=== 🏗️ Build ===$(RESET)\n"
@grep -h -E '^build-[a-zA-Z_-]+:.*?## .*$$' ... | awk ...
@printf "$(BOLD)=== 🔧 Development ===$(RESET)\n"
@grep -h -E '^dev-[a-zA-Z_-]+:.*?## .*$$' ... | awk ...Key help patterns:
- - Main categorized help
help - - Show targets not in any category (useful for auditing)
help-unclassified - - Show everything including internal targets
help-all - Hidden targets: prefix with (e.g.,
_)_build-internal - Legacy targets: label with and filter from main help
## (Legacy)
Always include a Help section in output:
make helpmakefile
@printf "$(BOLD)=== ❓ Help ===$(RESET)\n"
@printf "$(CYAN)%-25s$(RESET) %s\n" "help" "Show this help"
@printf "$(CYAN)%-25s$(RESET) %s\n" "help-unclassified" "Show targets not in categorized help"
@printf "\n"help-unclassified pattern (note the to strip filename prefix):
sedmakefile
help-unclassified: ## Show targets not in categorized help
@printf "$(BOLD)Targets not in main help:$(RESET)\n"
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | \
sed 's/^[^:]*://' | \
grep -v -E '^(env-|dev-|clean|help)' | \
awk 'BEGIN {FS = ":.*?## "}; {printf "$(CYAN)%-25s$(RESET) %s\n", $$1, $$2}' || \
printf " (none)\n"Description format - one line with example:
makefile
undefined使用ASCII框标题提高可见性:
makefile
help:
@printf "\n"
@printf "$(BOLD)$(CYAN)╔═══════════════════════════╗$(RESET)\n"
@printf "$(BOLD)$(CYAN)║ 项目名称 ║$(RESET)\n"
@printf "$(BOLD)$(CYAN)╚═══════════════════════════╝$(RESET)\n\n"分分类的帮助内容:
makefile
@printf "$(BOLD)=== 🏗️ 构建 ===$(RESET)\n"
@grep -h -E '^build-[a-zA-Z_-]+:.*?## .*$$' ... | awk ...
@printf "$(BOLD)=== 🔧 开发 ===$(RESET)\n"
@grep -h -E '^dev-[a-zA-Z_-]+:.*?## .*$$' ... | awk ...核心帮助模式:
- - 主分类帮助
help - - 显示未归入任何分类的目标(用于审计)
help-unclassified - - 显示所有内容包括内部目标
help-all - 隐藏目标:下划线前缀(例如)
_build-internal - 遗留目标:标记并从主帮助中过滤
## (Legacy)
make helpmakefile
@printf "$(BOLD)=== ❓ 帮助 ===$(RESET)\n"
@printf "$(CYAN)%-25s$(RESET) %s\n" "help" "显示此帮助"
@printf "$(CYAN)%-25s$(RESET) %s\n" "help-unclassified" "显示未归入分类的目标"
@printf "\n"help-unclassified模式(注意用去除文件名前缀):
sedmakefile
help-unclassified: ## 显示未归入分类的目标
@printf "$(BOLD)未出现在主帮助中的目标:$(RESET)\n"
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | \
sed 's/^[^:]*://' | \
grep -v -E '^(env-|dev-|clean|help)' | \
awk 'BEGIN {FS = ":.*?## "}; {printf "$(CYAN)%-25s$(RESET) %s\n", $$1, $$2}' || \
printf " (无)\n"描述格式 - 一行描述加示例:
makefile
undefinedGood - concise description + example on next line
好的示例 - 简洁描述 + 下一行示例
@printf "$(CYAN)%-14s$(RESET) %s\n" "scrape" "Fetch posts into SQLite, detect problems"
@printf " $(GREEN)make scrape SUBREDDITS=python,django LIMIT=10$(RESET)\n"
@printf "$(CYAN)%-14s$(RESET) %s\n" "dev-check" "Run ruff linter and formatter"
@printf " $(GREEN)make dev-check FIX=true$(RESET)\n"
@printf "$(CYAN)%-14s$(RESET) %s\n" "scrape" "拉取帖子存入SQLite,检测问题"
@printf " $(GREEN)make scrape SUBREDDITS=python,django LIMIT=10$(RESET)\n"
@printf "$(CYAN)%-14s$(RESET) %s\n" "dev-check" "运行ruff linter和格式化工具"
@printf " $(GREEN)make dev-check FIX=true$(RESET)\n"
Bad - too verbose, multi-line explanation
不好的示例 - 太冗长,多行解释
@printf " $(CYAN)$(BOLD)setup$(RESET)\n"
@printf " Install Python dependencies using uv. Run this once after cloning.\n"
@printf " Creates .venv/ and installs packages from pyproject.toml.\n"
@printf " $(GREEN)make setup$(RESET)\n"
**Help description rules:**
- **One line max** - Description must fit on single line unless user explicitly asks for more
- **Include what it affects** - e.g., "creates .venv", "exports to CSV", "deletes database"
- **Example on next line** - Show realistic usage with parameters in `$(GREEN)`
- **Skip examples for simple targets** - If no parameters, no example needed
**Catch-all redirects to help:**
```makefile
%:
@printf "$(RED)Unknown target '$@'$(RESET)\n"
@$(MAKE) help@printf " $(CYAN)$(BOLD)setup$(RESET)\n"
@printf " 使用uv安装Python依赖,克隆项目后运行一次即可。\n"
@printf " 创建.venv/目录并从pyproject.toml安装包。\n"
@printf " $(GREEN)make setup$(RESET)\n"
**帮助描述规则:**
- **最多一行** - 除非用户明确要求更多内容,否则描述必须在一行内显示
- **说明影响范围** - 例如「创建.venv」、「导出为CSV」、「删除数据库」
- **示例放在下一行** - 用`$(GREEN)`显示带参数的真实用法
- **简单目标跳过示例** - 没有参数的目标不需要示例
**全局捕获规则重定向到帮助:**
```makefile
%:
@printf "$(RED)未知目标'$@'$(RESET)\n"
@$(MAKE) helpCommon Pitfalls
常见陷阱
| Issue | Fix |
|---|---|
| Use |
Catch-all | Redirect to |
| Config vars scattered | Put all |
| Must match grep patterns in help target exactly |
| Duplicate defs in modules | Define once in root, reference in modules |
| Trailing whitespace in vars | Causes path splitting bugs - trim all variable definitions |
| Only use |
| Too many public targets | Don't expose |
| Appears grey/unreadable - use |
| Target named after tool | Name after the action: |
| Use |
No | Add |
| 问题 | 修复方案 |
|---|---|
Shell循环中的 | 使用 |
全局捕获 | 改为重定向到 |
| 配置变量分散 | 将所有 |
| 必须与帮助目标中的grep模式完全一致 |
| 模块中重复定义 | 在根目录定义一次,模块中引用 |
| 变量末尾空格 | 会导致路径拆分错误,修剪所有变量定义的末尾空格 |
文件目标加 | 仅对非文件目标使用 |
| 公开目标太多 | 不要暴露 |
用法文本用 | 会显示为灰色/不可读,改用 |
| 目标按工具命名 | 按动作命名: |
| 使用 |
未导出 | 在顶部添加 |
Cleanup Makefile Workflow
Makefile清理工作流
When user says "cleanup my makefiles":
IMPORTANT: Build a plan first and explain it to the user before implementing anything.
当用户说「清理我的makefile」时:
重要:先制定计划并向用户解释,确认后再执行任何修改。
Phase 1: Audit (no changes yet)
阶段1:审计(暂不修改)
bash
make help # See categorized targets
make help-unclassified # Find orphaned targets
cat Makefile # Read structure
ls makefiles/*.mk 2>/dev/null # Check if modular
rg "make " --type md # Find external dependencies
grep -E '\s+$' Makefile makefiles/*.mk # Trailing whitespacebash
make help # 查看分类目标
make help-unclassified # 查找孤立目标
cat Makefile # 阅读结构
ls makefiles/*.mk 2>/dev/null # 检查是否模块化
rg "make " --type md # 查找外部依赖
grep -E '\s+$' Makefile makefiles/*.mk # 末尾空格Phase 2: Build & Present Plan
阶段2:制定并展示计划
Create a checklist of proposed changes:
- Structure - Convert flat → modular (if 5+ targets) or vice versa
- Legacy removal - List specific targets to delete (with dependency check)
- Duplicates - List targets to consolidate
- Renames - List →
old_namechangesnew-name - Description rewrites - List vague descriptions to improve
- Missing targets - Suggest targets that should exist (e.g., )
help-unclassified - Ordering fixes - Config → imports → targets → help → catch-all
Ask user to approve the plan before proceeding.
创建建议修改的检查清单:
- 结构 - 扁平转模块化(如果目标超过5个)或相反
- 遗留移除 - 列出要删除的具体目标(已做依赖检查)
- 重复项 - 列出要合并的目标
- 重命名 - 列出→
old_name的修改项new-name - 描述重写 - 列出要优化的模糊描述
- 缺失目标 - 建议应该添加的目标(例如)
help-unclassified - 顺序修复 - 配置 → 引入 → 目标 → 帮助 → 全局捕获
继续前请先获得用户对计划的批准。
Phase 3: Implement (after approval)
阶段3:执行(批准后)
- Restructure (if needed) - Create directory, split into modules
makefiles/ - Remove legacy - Delete approved targets
- Consolidate duplicates - Merge into single targets
- Rename targets - Apply hyphen convention, add prefix for internal
_ - Rewrite descriptions - Make each explain the purpose
## - Fix formatting
- Usage examples in yellow:
$(YELLOW)make foo$(RESET) - Remove trailing whitespace
- only on non-file targets
.PHONY
- Usage examples in yellow:
- Add missing pieces - , catch-all
help-unclassified, etc.%:
- 结构调整(如果需要) - 创建目录,拆分到模块
makefiles/ - 移除遗留 - 删除已批准的目标
- 合并重复项 - 合并为单一目标
- 重命名目标 - 应用连字符规范,内部目标加前缀
_ - 重写描述 - 每个都要清晰说明用途
## - 修复格式
- 用法示例用黄色:
$(YELLOW)make foo$(RESET) - 移除末尾空格
- 仅非文件目标加
.PHONY
- 用法示例用黄色:
- 添加缺失部分 - 、全局捕获
help-unclassified等%:
Phase 4: Verify
阶段4:验证
bash
make help # Clean output?
make help-unclassified # Should be empty or minimal
make -n <target> # Dry-run key targetsbash
make help # 输出是否清晰?
make help-unclassified # 应该为空或极少内容
make -n <target> # 核心目标试运行What NOT to do without asking:
未询问用户前不要做的操作:
- Rename targets that CI/scripts depend on
- Remove targets that look unused
- Change structure (flat ↔ modular) without approval
- 重命名CI/脚本依赖的目标
- 删除看起来未使用的目标
- 未经批准修改结构(扁平 ↔ 模块化)
Files in This Skill
本技能包含的文件
- - Detailed patterns, categorized help, error handling
reference.md - - Full copy-paste Makefiles for each stack
templates/ - - Reusable pieces for complex projects
modules/
- - 详细模式、分类帮助、错误处理
reference.md - - 各技术栈可直接复制使用的完整Makefile
templates/ - - 复杂项目可复用的模块
modules/
Example: Adding a Target
示例:添加目标
User: "Add a target to run my tests"
makefile
.PHONY: test
test: ## Run tests
$(call print_section,Running tests)
uv run pytest tests/ -v
$(call print_success,Tests passed)User: "Add database targets"
makefile
.PHONY: db-start db-stop db-migrate
db-start: _check-docker ## Start database
docker compose up -d postgres
db-stop: ## Stop database
docker compose down
db-migrate: _check-postgres ## Run migrations
uv run alembic upgrade head用户:「添加一个运行测试的目标」
makefile
.PHONY: test
test: ## 运行测试
$(call print_section,运行测试)
uv run pytest tests/ -v
$(call print_success,测试通过)用户:「添加数据库相关目标」
makefile
.PHONY: db-start db-stop db-migrate
db-start: _check-docker ## 启动数据库
docker compose up -d postgres
db-stop: ## 停止数据库
docker compose down
db-migrate: _check-postgres ## 执行迁移
uv run alembic upgrade head