news 2026/4/23 10:25:52

Makefile入门实战让构建自动化

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Makefile入门实战让构建自动化

很多人觉得Makefile是C/C++的东西,跟自己没关系。

其实Makefile就是一个任务自动化工具,什么项目都能用。我现在Python、Go、前端项目都会写个Makefile,把常用命令封装起来。

这篇讲讲Makefile的基本写法,看完就能上手。

为什么用Makefile

项目里常用的命令:

# 启动开发环境docker-composeup -dexport$(cat.env|xargs)python manage.py runserver# 跑测试pytest tests/ -v# 构建镜像dockerbuild -t myapp:v1.2.3.dockerpush myapp:v1.2.3# 部署sshserver"cd /app && git pull && systemctl restart myapp"

每次都敲一遍很烦,而且新人来了不知道怎么跑。

写个Makefile:

.PHONY: dev test build deploy dev: docker-compose up -d python manage.py runserver test: pytest tests/ -v build: docker build -t myapp:$(VERSION) . deploy: ssh server "cd /app && git pull && systemctl restart myapp"

然后:

makedev# 启动开发环境maketest# 跑测试makebuildVERSION=v1.2.3# 构建镜像makedeploy# 部署

新人来了,先make help或者看Makefile就知道怎么跑项目。

基本语法

最简单的形式

目标: 依赖 命令

注意:命令前面必须是Tab,不是空格,这是很多人踩的坑。

hello: echo "Hello, World!"
makehello# echo "Hello, World!"# Hello, World!

依赖

build: clean test echo "开始构建" clean: rm -rf dist/ test: pytest

执行make build时,会先执行clean和test。

变量

# 定义变量 APP_NAME = myapp VERSION = 1.0.0 # 使用变量 build: docker build -t $(APP_NAME):$(VERSION) .

命令行传入变量:

makebuildVERSION=2.0.0

环境变量

# 从环境变量获取,有默认值 DB_HOST ?= localhost DB_PORT ?= 3306 run: DB_HOST=$(DB_HOST) DB_PORT=$(DB_PORT) python app.py
makerun# 使用默认值DB_HOST=prod.dbmakerun# 使用环境变量makerunDB_HOST=prod.db# 命令行传入

伪目标

如果目录里有个文件叫test,执行make test会说"已是最新"。

用.PHONY声明伪目标:

.PHONY: test clean build test: pytest

所有不生成文件的目标都应该声明为.PHONY。

静默执行

默认make会打印执行的命令,加@可以隐藏:

hello: @echo "Hello"

或者全局静默:

make-s hello

多行命令

默认每行命令在单独的shell里执行,上一行的变量下一行拿不到:

# 这样不行 test: cd /tmp pwd # 还是在原来的目录 # 这样可以 test: cd /tmp && pwd # 或者用反斜杠 test: cd /tmp && \ pwd && \ ls

错误处理

默认命令失败就停止。加-可以忽略错误:

clean: -rm -rf dist/ # 即使失败也继续

或者用 || true:

clean: rm -rf dist/ || true

实用模式

帮助信息

.PHONY: help help: @echo "可用命令:" @echo " make dev - 启动开发环境" @echo " make test - 运行测试" @echo " make build - 构建镜像" @echo " make deploy - 部署到服务器" # 把help放第一个,make不带参数就显示帮助 .DEFAULT_GOAL := help

更高级的写法,自动从注释生成:

.PHONY: help help: ## 显示帮助信息 @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}' dev: ## 启动开发环境 docker-compose up -d test: ## 运行测试 pytest build: ## 构建镜像 docker build -t myapp .
makehelp# dev 启动开发环境# test 运行测试# build 构建镜像

include其他文件

# 引入其他Makefile include config.mk # 如果文件不存在不报错 -include local.mk

条件判断

ifeq ($(ENV), prod) DB_HOST = prod.db.com else DB_HOST = localhost endif run: @echo "连接 $(DB_HOST)"

获取Git信息

GIT_COMMIT := $(shell git rev-parse --short HEAD) GIT_BRANCH := $(shell git rev-parse --abbrev-ref HEAD) BUILD_TIME := $(shell date +%Y%m%d-%H%M%S) build: docker build \ --build-arg GIT_COMMIT=$(GIT_COMMIT) \ --build-arg BUILD_TIME=$(BUILD_TIME) \ -t myapp:$(GIT_COMMIT) .

检查命令是否存在

check-docker: @which docker > /dev/null || (echo "请先安装docker" && exit 1) build: check-docker docker build -t myapp .

实际项目示例

Go项目

.PHONY: build test run clean help APP_NAME := myapp VERSION := $(shell git describe --tags --always --dirty) BUILD_TIME := $(shell date -u +%Y-%m-%dT%H:%M:%SZ) LDFLAGS := -X main.Version=$(VERSION) -X main.BuildTime=$(BUILD_TIME) help: ## 帮助 @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-15s\033[0m %s\n", $$1, $$2}' build: ## 构建 go build -ldflags "$(LDFLAGS)" -o bin/$(APP_NAME) . test: ## 测试 go test -v ./... run: build ## 运行 ./bin/$(APP_NAME) clean: ## 清理 rm -rf bin/ lint: ## 代码检查 golangci-lint run docker: ## 构建Docker镜像 docker build -t $(APP_NAME):$(VERSION) . .DEFAULT_GOAL := help

Python项目

.PHONY: install dev test lint format clean help PYTHON := python3 VENV := .venv PIP := $(VENV)/bin/pip PYTEST := $(VENV)/bin/pytest help: @echo "make install - 安装依赖" @echo "make dev - 启动开发服务" @echo "make test - 运行测试" @echo "make lint - 代码检查" @echo "make format - 格式化代码" $(VENV): $(PYTHON) -m venv $(VENV) install: $(VENV) $(PIP) install -r requirements.txt dev: install $(VENV)/bin/python manage.py runserver test: install $(PYTEST) tests/ -v lint: $(VENV)/bin/flake8 src/ $(VENV)/bin/mypy src/ format: $(VENV)/bin/black src/ tests/ $(VENV)/bin/isort src/ tests/ clean: rm -rf $(VENV) __pycache__ .pytest_cache .mypy_cache find . -type d -name "__pycache__" -exec rm -rf {} +

前端项目

.PHONY: install dev build test lint deploy help NODE_ENV ?= development help: @echo "make install - 安装依赖" @echo "make dev - 启动开发服务" @echo "make build - 构建生产版本" @echo "make deploy - 部署" install: npm ci dev: npm run dev build: NODE_ENV=production npm run build test: npm test lint: npm run lint deploy: build rsync -avz --delete dist/ server:/var/www/app/

Docker项目

.PHONY: up down logs ps build push clean help COMPOSE := docker-compose IMAGE := myapp REGISTRY := registry.example.com VERSION := $(shell git describe --tags --always) help: @echo "make up - 启动所有服务" @echo "make down - 停止所有服务" @echo "make logs - 查看日志" @echo "make build - 构建镜像" @echo "make push - 推送镜像" up: $(COMPOSE) up -d down: $(COMPOSE) down logs: $(COMPOSE) logs -f ps: $(COMPOSE) ps build: docker build -t $(REGISTRY)/$(IMAGE):$(VERSION) . docker tag $(REGISTRY)/$(IMAGE):$(VERSION) $(REGISTRY)/$(IMAGE):latest push: build docker push $(REGISTRY)/$(IMAGE):$(VERSION) docker push $(REGISTRY)/$(IMAGE):latest clean: $(COMPOSE) down -v --rmi local docker system prune -f

常见问题

Tab vs 空格

命令前必须是Tab,不是空格。如果你的编辑器把Tab转成空格了,会报错:

Makefile:2: *** missing separator. Stop.

VSCode可以在状态栏点击"空格:4"切换成Tab。

变量展开

# 立即展开 A := $(shell date) # 延迟展开 B = $(shell date)

:= 定义时就计算,= 使用时才计算。

Windows兼容

Windows上没有make命令,可以:

  • 用WSL
  • 安装MinGW的make
  • 用nmake(语法略有不同)

或者干脆用跨平台的工具如just、task。


Makefile不复杂,核心就是:

  • 目标、依赖、命令
  • 变量
  • .PHONY

写好一个Makefile,整个团队都能统一操作方式,还能当文档用。

值得花半小时学一下。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/23 11:13:09

HP7730打印机固件降级完全指南:解锁低成本打印新姿势

还在为昂贵的原装墨盒发愁吗?HP7730打印机固件降级技术让你告别原装耗材束缚,实现真正的打印自由!本指南将带你深入了解固件降级的技术原理、操作流程以及实际应用效果。 【免费下载链接】HP7730固件降级教程及资源下载 HP7730 固件降级教程及…

作者头像 李华
网站建设 2026/4/23 12:34:17

DeepSeek-V3:开源大模型架构创新的突破性进展

DeepSeek-V3:开源大模型架构创新的突破性进展 【免费下载链接】academic-ds-9B 项目地址: https://ai.gitcode.com/hf_mirrors/ByteDance-Seed/academic-ds-9B 引言 当前大语言模型领域正经历着前所未有的技术变革,开源与闭源模型之间的性能差距…

作者头像 李华
网站建设 2026/4/23 12:36:34

Swift Composable Architecture终极指南:构建可测试的大型SwiftUI应用

Swift Composable Architecture终极指南:构建可测试的大型SwiftUI应用 【免费下载链接】swift-composable-architecture pointfreeco/swift-composable-architecture: Swift Composable Architecture (SCA) 是一个基于Swift编写的函数式编程架构框架,旨在…

作者头像 李华
网站建设 2026/4/23 12:56:08

快速掌握Drogon框架:从容器打包到云原生集群的全流程实战

快速掌握Drogon框架:从容器打包到云原生集群的全流程实战 【免费下载链接】drogon 项目地址: https://gitcode.com/gh_mirrors/dro/drogon Drogon是一款基于C17/20标准构建的高性能Web应用开发框架,以其完全异步的编程模型和跨平台支持能力著称。…

作者头像 李华
网站建设 2026/4/23 17:43:56

NYC插件系统深度解析:构建企业级代码覆盖率工具链

NYC插件系统深度解析:构建企业级代码覆盖率工具链 【免费下载链接】nyc the Istanbul command line interface 项目地址: https://gitcode.com/gh_mirrors/ny/nyc 在当今快速迭代的软件开发环境中,代码质量保障已成为项目成功的关键因素。NYC作为…

作者头像 李华