據 AlphaMoat 統計,截至 2026-09,Makefile & Build 累計下載 2,676 次、獲 3 個星標,在全部 5,078 個 AI 技能中排名第 3,966 位,在「開發程式設計」分類(577 個)中排名第 498 位。
| 平台 | 累計安裝 | 累計下載 | 星標 | 評論 |
|---|---|---|---|---|
| ClawHub ↗ | 81 | 2645 | 3 | - |
| SkillHub ↗ | 122 | 2676 | 3 | — |
各平台的計數口徑不同,統計時間不一致。
內容涵蓋目標、依賴、變數、模式規則、偽目標及 Go、Python、Node.js、Docker 的示例,幷包含清理、部署和推送目標。複製或生成的目標可能刪除檔案、安裝依賴、釋出映象或部署程式碼;執行前應逐項審查,並固定依賴版本。
資料釋出於 2026-10-29
以下是根據技能文件生成的示例,不代表實際執行結果。
2026-09 起統計方法調整:同名技能按作者分別統計,並覆蓋全部技能。圖中虛線為調整前的月份,與之後的資料不直接比較,也不計算跨越調整的增長。
| 月份 | 累計下載 | 環比 | 星標 |
|---|---|---|---|
| 2026-09 | 2676 | — | 3 |
| 2026-08 | 2526 | +5.3% | 3 |
| 2026-07 | 2399 | +10.8% | 3 |
| 2026-06 | 2166 | +6.9% | 3 |
| 2026-05 | 2027 | — | 3 |
| 2026-03 | 1614 | — | 3 |
以下是作者釋出的原始檔案,按純文字顯示,本站未做修改或稽核;其中的連結不可點選,命令請核實後再執行。抓取於 2026-10-23。
---
name: makefile-build
description: Write Makefiles for any project type. Use when setting up build automation, defining multi-target builds, managing dependencies between tasks, creating project task runners, or using Make for non-C projects (Go, Python, Docker, Node.js). Also covers Just and Task as modern alternatives.
metadata: {"clawdbot":{"emoji":"🔨","requires":{"anyBins":["make","just","task"]},"os":["linux","darwin","win32"]}}
---
# 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.
用 gh 命令列工具檢視 GitHub 上的 PR 檢查、工作流執行與 API 查詢的技能。
聚合 16 個搜尋引擎、無需 API Key 的檢索技能。
用命令列直接列出、配置、授權並呼叫 MCP 服務與工具。
根據文字描述生成 Mermaid 圖表程式碼。
用受管 OAuth 訪問 YouTube Data API,檢索影片並管理頻道內容。
透過受管的 OAuth 連線訪問 GitHub REST API。
覆蓋規劃、實現、驗證與測試的編碼工作流技能。
整理 Docker 常用命令與容器工作流的技能。
在命令列查詢、設計、遷移與最佳化 SQL 資料庫。
security-audit 提供程式碼與基礎設施安全審查的清單和命令示例。
git-workflows 提供歷史整理、除錯和倉庫管理的進階 Git 流程。
在命令列裡搭、測、寫文件與排錯 HTTP 介面。
解析、檢索與分析各類應用日誌,定位報錯。
資料月份:2026-09 · 下載/星標/安裝數聚合自公開技能註冊庫(ClawHub、SkillHub),按月更新。口徑說明見資料方法。