安装方式
手动下载安装
下载 ZIP 后解压到技能目录即可安装。若在桌面客户端 WebView中直接下载出现异常,本站会改为提示页 + 原始链接,请按页内说明操作。
下载 ZIP (shub-makefile-build-v1.0.0.zip)触发指令
/makefile-build
跨平台安装指引
该技能声明兼容以下 1 个平台,将 ZIP 解压到对应目录即可被识别。
unzip shub-makefile-build-v1.0.0.zip -d ~/.claude/skills/
mkdir -p 创建;启用 Skill 后请重启对应 Agent 让配置生效。
使用指南
Makefile 构建
围绕 Makefile 构建:目标、变量、伪目标与依赖管理,用于本地与 CI 构建自动化;避免递归 make 陷阱见文档。 无需在每次任务前把零散英文说明手工拼进上下文,也 减少 与客户端默认行为脱节的试错;具体命令、钩子与 JSON 参数仍以 ZIP 包内 SKILL.md 为权威。下文结构与站内 MCP CLI 类专题稿相同:何时用、前置、流程、速查与故障。
何时使用
- 目标、变量、伪目标与依赖管理,用于本地与 CI 构建自动化
- 避免递归 make 陷阱见文档
- 已获取本技能 ZIP,并准备在 Claude Code / OpenClaw 中按 SKILL.md 挂载。
- 希望用中文专题稿快速判断「该不该启用」,再深入英文 SKILL 查参数与边界。
- 需要与团队对齐同一套触发方式、目录约定或回调格式时。
前置条件
- 通用:可运行 Claude Code 或文档要求的客户端;有可读写的项目工作区(或 SKILL.md 指定的沙箱目录)。
- 权威细节:API Key / OAuth、钩子路径、环境变量以 ZIP 内 SKILL.md 为准。
典型流程
- 从 ClawHub / 站内分发获取技能 ZIP,校验版本与校验和(若提供)。
- 阅读 SKILL.md 的安装段落:目录落点、客户端类型(Claude Code / OpenClaw / 脚本)。
- 用文档中的最小示例完成第一次调用(单文件修改、单次查询或单次委派)。
- 确认工作目录、权限边界与输出路径后,再处理多文件或长耗时任务。
- 需要回调 / Webhook / 通知时,按 SKILL.md 配置端点并在测试环境先验通。
与 ZIP / SKILL.md 的关系
站内专题稿与 MCP CLI 类 oss 稿同样:概括何时用、怎么接、怎么排错;命令模板、钩子名、JSON 字段、版本矩阵一律以 ZIP 内 SKILL.md 与 ClawHub 上游为准。
命令示例(摘自包内 SKILL.md)
以下为从上游 SKILL.md(或入库正文)自动抽取的终端/脚本片段;路径、环境变量与参数以当前 ZIP 与官方说明为准。
ClawHub slug:makefile-build(安装命令以 SKILL.md / claw CLI 为准)。
# Install: https://github.com/casey/just
# Run:
just # Default recipe
just build # Specific recipe
just run 9090 # With argument
just --list # List all recipes
# Install: https://taskfile.dev/installation/
# Run:
task # Default task
task build # Specific task
task --list # List all tasks
站内入库时的触发命令(完整语义见 ZIP):
# 使用本技能时可在对话中引用或执行上述指令;完整参数与示例见下载包内 SKILL.md。
/makefile-build
最佳实践
- 先 SKILL.md 再猜参数;站内专题稿不替代 schema 与必填字段说明。
- 委派任务时写清验收标准(命令、文件路径、测试命令),减少来回追问。
- 长任务用文档推荐的回调 / 日志落盘代替高频轮询,省 Token 也省机器负载。
- 多技能同时启用时,注意钩子加载顺序与重复工具调用(以 SKILL.md 冲突说明为准)。
调试与排错
- 打开 stderr 与客户端日志;PTY/tmux 场景同时看面板最后几十行输出。
- 参数错误时对照 SKILL.md 中的 JSON/CLI 示例(引号、转义、工作目录)。
- 网络类失败:查代理、防火墙、MCP 传输方式(stdio / HTTP / SSE)。
速查
| 动作 | 说明 |
|------|------|
| 获取技能包 | ClawHub / 站内 ZIP,核对版本 |
| 权威步骤 | 优先阅读 ZIP 内 SKILL.md |
| 首次试跑 | 使用 SKILL.md 最小示例 |
| 验收 | 对照路径、测试命令或回调负载 |
常见故障
- 无输出或立即退出 → 工作目录错误、依赖未装、或 Claude Code 未登录;按 SKILL.md 自检清单执行。
- 权限被拒绝 → 检查沙箱路径、
--permission-mode与工具白名单。 - 与简介不符 → 以英文 SKILL 与上游仓库为准,站内稿仅作结构化导读。
# Makefile & Build
Write Makefiles for project automation across any language. Covers targets, dependencies, variables, pattern rules, phony targets, and using Make for Go, Python, Docker, and Node.js projects. Includes Just and Task as modern alternatives.
## When to Use
- Automating build, test, lint, deploy commands
- Defining dependencies between tasks (build before test)
- Creating a project-level task runner (consistent across team)
- Replacing long CLI commands with short memorable targets
- Managing multi-step build processes
- Any project that needs a `make build && make test && make deploy` workflow
## Makefile Basics
### Structure
```makefile
# target: prerequisites
# recipe (MUST be indented with TAB, not spaces)
build: src/main.go
go build -o bin/app src/main.go
test: build
go test ./...
clean:
rm -rf bin/
# First target is the default (runs with bare `make`)
```
### Variables
```makefile
# Simple assignment
CC = gcc
CFLAGS = -Wall -O2
# Deferred assignment (expanded when used)
FILES = $(wildcard src/*.go)
# Immediate assignment (expanded when defined)
VERSION := $(shell git describe --tags --always)
# Conditional assignment (only if not already set)
PORT ?= 8080
# Use variables
build:
$(CC) $(CFLAGS) -o app main.c
@echo "Version: $(VERSION)"
```
### Automatic variables
```makefile
# $@ = target name
# $< = first prerequisite
# $^ = all prerequisites
# $* = stem (pattern match)
# $(@D) = directory of target
# $(@F) = filename of target
bin/app: src/main.go src/util.go
go build -o $@ $^
# $@ = bin/app
# $^ = src/main.go src/util.go
# $< = src/main.go
# Pattern rule
%.o: %.c
$(CC) -c -o $@ $<
# For foo.o: $@ = foo.o, $< = foo.c, $* = foo
```
### Phony targets (not files)
```makefile
# Without .PHONY, if a file named "clean" exists, `make clean` does nothing
.PHONY: build test clean lint fmt help
build:
go build -o bin/app ./cmd/app
test:
go test ./...
clean:
rm -rf bin/ dist/
# List all targets
help:
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | \
awk 'BEGIN {FS = ":.*?## "}; {printf " \033[36m%-15s\033[0m %s\n", $$1, $$2}'
```
### Self-documenting Makefile
```makefile
.DEFAULT_GOAL := help
build: ## Build the application
go build -o bin/app ./cmd/app
test: ## Run all tests
go test -v ./...
lint: ## Run linters
golangci-lint run
clean: ## Remove build artifacts
rm -rf bin/ dist/
help: ## Show this help
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | \
awk 'BEGIN {FS = ":.*?## "}; {printf " \033[36m%-15s\033[0m %s\n", $$1, $$2}'
```
## Language-Specific Makefiles
### Go
```makefile
BINARY_NAME := myapp
VERSION := $(shell git describe --tags --always --dirty)
LDFLAGS := -ldflags "-X main.version=$(VERSION)"
GOFILES := $(shell find . -name '*.go' -not -path './vendor/*')
.PHONY: all build test lint clean run
all: lint test build
build: ## Build binary
CGO_ENABLED=0 go build $(LDFLAGS) -o bin/$(BINARY_NAME) ./cmd/$(BINARY_NAME)
test: ## Run tests
go test -race -coverprofile=coverage.out ./...
test-coverage: test ## Show coverage report
go tool cover -html=coverage.out
lint: ## Run linters
golangci-lint run ./...
fmt: ## Format code
gofmt -w $(GOFILES)
run: build ## Build and run
./bin/$(BINARY_NAME)
clean: ## Clean build artifacts
rm -rf bin/ coverage.out
# Cross-compilation
build-linux: ## Build for Linux
GOOS=linux GOARCH=amd64 go build $(LDFLAGS) -o bin/$(BINARY_NAME)-linux-amd64 ./cmd/$(BINARY_NAME)
build-all: ## Build for all platforms
GOOS=linux GOARCH=amd64 go build $(LDFLAGS) -o bin/$(BINARY_NAME)-linux-amd64 ./cmd/$(BINARY_NAME)
GOOS=darwin GOARCH=arm64 go build $(LDFLAGS) -o bin/$(BINARY_NAME)-darwin-arm64 ./cmd/$(BINARY_NAME)
GOOS=windows GOARCH=amd64 go build $(LDFLAGS) -o bin/$(BINARY_NAME)-windows-amd64.exe ./cmd/$(BINARY_NAME)
```
### Python
```makefile
PYTHON := python3
VENV := .venv
BIN := $(VENV)/bin
.PHONY: all install test lint fmt clean run
all: install lint test
$(VENV)/bin/activate:
$(PYTHON) -m venv $(VENV)
$(BIN)/pip install --upgrade pip
install: $(VENV)/bin/activate ## Install dependencies
$(BIN)/pip install -r requirements.txt
$(BIN)/pip install -r requirements-dev.txt
test: ## Run tests
$(BIN)/pytest -v --cov=src --cov-report=term-missing
lint: ## Run linters
$(BIN)/ruff check src/ tests/
$(BIN)/mypy src/
fmt: ## Format code
$(BIN)/ruff format src/ tests/
run: ## Run application
$(BIN)/python -m src.main
clean: ## Remove venv and caches
rm -rf $(VENV) __pycache__ .pytest_cache .mypy_cache .ruff_cache
find . -type d -name '__pycache__' -exec rm -rf {} + 2>/dev/null || true
```
### Node.js / TypeScript
```makefile
.PHONY: all install build test lint clean dev
all: install lint test build
node_modules: package.json
npm install
@touch node_modules
install: node_modules ## Install dependencies
build: node_modules ## Build TypeScript
npx tsc
test: node_modules ## Run tests
npx vitest run
test-watch: node_modules ## Run tests in watch mode
npx vitest
lint: node_modules ## Lint code
npx eslint src/ --ext .ts,.tsx
npx tsc --noEmit
fmt: node_modules ## Format code
npx prettier --write 'src/**/*.{ts,tsx}'
dev: node_modules ## Run in development mode
npx tsx watch src/index.ts
clean: ## Clean build artifacts
rm -rf dist/ node_modules/.cache
```
### Docker
```makefile
IMAGE_NAME := myapp
VERSION := $(shell git describe --tags --always)
REGISTRY := ghcr.io/myorg
.PHONY: build push run stop clean
build: ## Build Docker image
docker build -t $(IMAGE_NAME):$(VERSION) -t $(IMAGE_NAME):latest .
push: build ## Push to registry
docker tag $(IMAGE_NAME):$(VERSION) $(REGISTRY)/$(IMAGE_NAME):$(VERSION)
docker tag $(IMAGE_NAME):latest $(REGISTRY)/$(IMAGE_NAME):latest
docker push $(REGISTRY)/$(IMAGE_NAME):$(VERSION)
docker push $(REGISTRY)/$(IMAGE_NAME):latest
run: ## Run container
docker run --rm -p 8080:8080 --name $(IMAGE_NAME) $(IMAGE_NAME):latest
stop: ## Stop container
docker stop $(IMAGE_NAME) 2>/dev/null || true
clean: ## Remove images
docker rmi $(IMAGE_NAME):$(VERSION) $(IMAGE_NAME):latest 2>/dev/null || true
compose-up: ## Start with docker compose
docker compose up -d --build
compose-down: ## Stop compose
docker compose down
compose-logs: ## Follow compose logs
docker compose logs -f
```
## Advanced Patterns
### Conditional logic
```makefile
# OS detection
UNAME := $(shell uname -s)
ifeq ($(UNAME),Darwin)
SED := sed -i ''
else
SED := sed -i
endif
# Environment-based config
ENV ?= development
ifeq ($(ENV),production)
CFLAGS += -O2
LDFLAGS += -s -w
else
CFLAGS += -g -O0
endif
# Check if command exists
HAS_DOCKER := $(shell command -v docker 2>/dev/null)
docker-build:
ifndef HAS_DOCKER
$(error "docker is not installed")
endif
docker build -t myapp .
```
### Multi-directory builds
```makefile
SERVICES := api worker scheduler
.PHONY: build-all test-all $(SERVICES)
build-all: $(SERVICES)
$(SERVICES):
$(MAKE) -C services/$@ build
test-all:
@for svc in $(SERVICES); do \
echo "Testing $$svc..."; \
$(MAKE) -C services/$$svc test || exit 1; \
done
```
### Include other Makefiles
```makefile
# Split large Makefile into modules
include mk/docker.mk
include mk/test.mk
include mk/deploy.mk
# Optional include (no error if missing)
-include .env.mk
```
### Silent execution and output control
```makefile
# @ suppresses command echo
install:
@echo "Installing dependencies..."
@npm install
# .SILENT for entire targets
.SILENT: help clean
# Make less verbose globally
MAKEFLAGS += --no-print-directory
```
## Just (Modern Alternative)
### Justfile syntax
```just
# justfile — simpler than Make, no TAB requirement
# Set shell
set shell := ["bash", "-euo", "pipefail", "-c"]
# Variables
version := `git describe --tags --always`
default_port := "8080"
# Default recipe (first one)
default: lint test build
# Recipes
build: ## Build the application
go build -ldflags "-X main.version={{version}}" -o bin/app ./cmd/app
test: ## Run tests
go test -race ./...
lint: ## Run linters
golangci-lint run
run port=default_port: build ## Run with optional port
./bin/app --port {{port}}
clean: ## Clean artifacts
rm -rf bin/ dist/
# Recipes with dependencies
deploy: build test
./scripts/deploy.sh
# OS-specific
[linux]
install-deps:
sudo apt install -y build-essential
[macos]
install-deps:
brew install go golangci-lint
# List recipes
help:
@just --list
```
```bash
# Install: https://github.com/casey/just
# Run:
just # Default recipe
just build # Specific recipe
just run 9090 # With argument
just --list # List all recipes
```
## Task (Go Task Runner)
### Taskfile.yml
```yaml
# Taskfile.yml
version: '3'
vars:
VERSION:
sh: git describe --tags --always
BINARY: myapp
tasks:
default:
deps: [lint, test, build]
build:
desc: Build the application
cmds:
- go build -ldflags "-X main.version={{.VERSION}}" -o bin/{{.BINARY}} ./cmd/{{.BINARY}}
sources:
- ./**/*.go
generates:
- bin/{{.BINARY}}
test:
desc: Run tests
cmds:
- go test -race ./...
lint:
desc: Run linters
cmds:
- golangci-lint run
run:
desc: Build and run
deps: [build]
cmds:
- ./bin/{{.BINARY}} {{.CLI_ARGS}}
clean:
desc: Clean artifacts
cmds:
- rm -rf bin/ dist/
docker:build:
desc: Build Docker image
cmds:
- docker build -t {{.BINARY}}:{{.VERSION}} .
# Task with preconditions
deploy:
desc: Deploy to production
preconditions:
- sh: test -f bin/{{.BINARY}}
msg: "Build first: task build"
- sh: git diff --quiet
msg: "Uncommitted changes detected"
cmds:
- ./scripts/deploy.sh
```
```bash
# Install: https://taskfile.dev/installation/
# Run:
task # Default task
task build # Specific task
task --list # List all tasks
```
## Make vs Just vs Task
| Feature | Make | Just | Task |
|---|---|---|---|
| Config format | Makefile (TAB-sensitive) | justfile | Taskfile.yml |
| Dependencies | File-based + phony | Recipe-based | Task-based |
| File change detection | Built-in | No | sources/generates |
| Variables | Yes (complex) | Yes (simple) | Yes (YAML) |
| Cross-platform | Needs make installed | Single binary | Single binary |
| Learning curve | High | Low | Low |
| Best for | C/C++ builds, complex deps | Task runner replacement | YAML-native projects |
## Tips
- The number one Makefile bug: using spaces instead of tabs for indentation. Make requires literal TAB characters in recipes.
- `.PHONY` every target that isn't a real file. Without it, `make clean` won't run if a file named `clean` exists.
- Use `@` prefix to suppress command echo for cleaner output: `@echo "Building..."` prints only "Building...", not the echo command itself.
- The self-documenting `help` target (with `## comments`) is worth adding to every Makefile. `make help` becomes the project's command reference.
- Make is overkill for simple task running. If you just want named commands, Just or Task are simpler and don't have the TAB footgun.
- Use `?=` for variables users might want to override: `PORT ?= 8080` lets `PORT=9090 make run` work.
- For polyglot projects (Go + Python + Docker), a Makefile at the root that delegates to language-specific tools is a clean pattern.
- Make's file-based dependency tracking is genuinely powerful for build systems. If your project compiles files, Make's `target: prerequisites` model avoids unnecessary rebuilds.