16 KiB
📋 Makefile 命令详细执行逻辑指南
本文档详细说明了 TYAPI 项目中每个 Make 命令的执行逻辑、具体步骤和背后原理。
🚀 快速开始
# 查看所有可用命令
make help
# 设置开发环境
make setup
# 启动开发依赖服务
make dev-up
# 开发模式运行应用
make dev
📖 命令详细执行逻辑
🔍 信息查看命令
make help
执行逻辑:
# 1. 检测操作系统类型
# 2. 输出预定义的帮助信息
@echo "TYAPI Server Makefile"
@echo "Usage: make [target]"
@echo "Main targets:"
@echo " help Show this help message"
# ... 更多帮助信息
实际效果:
- 📄 直接打印硬编码的帮助文本
- 🚫 不执行任何文件操作
- ⚡ 瞬间完成,无依赖
make version
执行逻辑:
# 步骤1: 自动执行 make build (依赖检查)
# 步骤2: 执行构建好的二进制文件
./bin/tyapi-server -version
详细步骤:
- 依赖检查: 检查是否需要重新构建 (通过 make build)
- 参数传递: 向应用程序传递
-version标志 - 读取构建信息: 应用程序输出编译时注入的版本信息
main.version(来自 Makefile 的 VERSION 变量)main.commit(来自 git rev-parse --short HEAD)main.date(来自构建时间)
相关文件: bin/tyapi-server, cmd/api/main.go
🏗️ 构建相关命令
make build
执行逻辑:
# 步骤1: 检测操作系统
ifeq ($(OS),Windows_NT)
# Windows: 创建bin目录 (如果不存在)
@if not exist "bin" mkdir "bin"
else
# Unix: 创建bin目录
@mkdir -p bin
endif
# 步骤2: 构建Go应用程序
go build -ldflags "-X main.version=1.0.0 -X main.commit=abc123 -X main.date=2025-01-01T00:00:00Z" -o bin/tyapi-server cmd/api/main.go
详细步骤:
- 环境检测: 通过
$(OS)变量检测操作系统 - 目录创建:
- Windows:
if not exist "bin" mkdir "bin" - Unix:
mkdir -p bin
- Windows:
- 版本信息收集:
BUILD_TIME: PowerShell/date 命令获取当前时间GIT_COMMIT: git 命令获取当前 commit hashVERSION: 硬编码版本号 1.0.0
- 编译执行:
- 使用
go build命令 -ldflags注入版本信息到可执行文件- 输出文件到
bin/tyapi-server
- 使用
生成文件: bin/tyapi-server (Windows 下为 .exe)
make build-prod
执行逻辑:
# 步骤1: 创建bin目录 (同build)
# 步骤2: 生产环境构建
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags "..." -a -installsuffix cgo -o bin/tyapi-server-linux-amd64 cmd/api/main.go
关键参数解析:
CGO_ENABLED=0: 禁用 CGO,生成纯静态二进制GOOS=linux GOARCH=amd64: 强制 Linux 64 位平台-a: 重新构建所有包-installsuffix cgo: 避免缓存冲突- 结果: 生成可在任何 Linux x64 环境运行的静态二进制文件
make build-all
执行逻辑:
# 步骤1: 创建bin目录
# 步骤2: 循环构建5个平台
# Linux AMD64
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build ... -o bin/tyapi-server-linux-amd64
# Linux ARM64
CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build ... -o bin/tyapi-server-linux-arm64
# macOS Intel
CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build ... -o bin/tyapi-server-darwin-amd64
# macOS Apple Silicon
CGO_ENABLED=0 GOOS=darwin GOARCH=arm64 go build ... -o bin/tyapi-server-darwin-arm64
# Windows
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build ... -o bin/tyapi-server-windows-amd64.exe
生成的 5 个文件:
bin/tyapi-server-linux-amd64bin/tyapi-server-linux-arm64bin/tyapi-server-darwin-amd64bin/tyapi-server-darwin-arm64bin/tyapi-server-windows-amd64.exe
▶️ 运行相关命令
make run
执行逻辑:
# 步骤1: 执行make build (依赖)
# 步骤2: 直接运行构建好的二进制文件
./bin/tyapi-server
详细流程:
- 依赖检查: Make 自动检查 build 目标是否需要重新执行
- 文件存在性检查: 确认
bin/tyapi-server存在 - 权限检查: Unix 系统检查执行权限
- 进程启动: 启动 Gin HTTP 服务器
- 端口监听: 默认监听 8080 端口
运行环境: 需要 PostgreSQL 和 Redis 服务可用
make dev
执行逻辑:
# 直接执行 (已去掉air检查)
go run cmd/api/main.go
详细步骤:
- 源码编译: Go 编译器实时编译 main.go 及其依赖
- 内存运行: 不生成磁盘文件,直接在内存中运行
- 依赖加载: 自动下载并编译所有 import 的包
- 服务启动: 启动 HTTP 服务器监听 8080 端口
与 build 的区别:
- ✅ 无需预先构建
- ✅ 代码变更后需手动重启
- ❌ 每次启动都需要重新编译
🛠️ 开发工具命令
make deps
执行逻辑:
# 步骤1: 下载依赖
go mod download
# 步骤2: 整理依赖
go mod tidy
详细步骤:
- go mod download:
- 读取
go.mod文件 - 下载所有依赖包到
$GOPATH/pkg/mod/ - 验证包的 checksum (通过 go.sum)
- 不修改 go.mod 文件
- 读取
- go mod tidy:
- 扫描所有.go 文件中的 import 语句
- 添加缺失的依赖到 go.mod
- 移除未使用的依赖
- 更新 go.sum 文件
影响的文件: go.mod, go.sum, $GOPATH/pkg/mod/
make fmt
执行逻辑:
go fmt ./...
详细步骤:
- 递归扫描: 扫描当前目录及所有子目录的.go 文件
- 格式化规则应用:
- 统一缩进 (tab)
- 统一换行
- 移除行尾空格
- 规范化大括号位置
- 文件修改: 直接修改源文件 (in-place)
- 报告: 输出被修改的文件列表
影响的文件: 所有.go 源码文件
make lint
执行逻辑:
# 检查golangci-lint是否安装
@if command -v golangci-lint >/dev/null 2>&1; then \
golangci-lint run; \
else \
echo "golangci-lint not installed, skipping lint check"; \
fi
详细步骤:
- 工具检查: 使用
command -v检查 golangci-lint 是否在 PATH 中 - 如果已安装:
- 读取
.golangci.yml配置 (如果存在) - 运行多个 linter 检查 (默认包括: errcheck, gosimple, govet, ineffassign 等)
- 分析所有.go 文件
- 输出问题报告
- 读取
- 如果未安装: 显示提示信息并跳过
检查项目: 代码质量、潜在 bug、性能问题、安全问题等
🧪 测试相关命令
make test
执行逻辑:
go test -v -race -coverprofile=coverage.out ./...
参数详解:
-v: 详细输出,显示每个测试的名称和结果-race: 启用竞态条件检测器-coverprofile=coverage.out: 生成覆盖率数据文件./...: 递归测试所有包
详细步骤:
- 包发现: 递归扫描所有包含*_test.go 的目录
- 编译测试: 为每个包编译测试二进制文件
- 竞态检测: 启用 Go race detector
- 执行测试: 逐个运行 Test*函数
- 覆盖率收集: 记录每行代码是否被执行
- 生成报告: 输出到 coverage.out 文件
生成文件: coverage.out
make coverage
执行逻辑:
# 步骤1: 执行make test (依赖)
# 步骤2: 生成HTML报告
go tool cover -html=coverage.out -o coverage.html
# 步骤3: 提示用户
@echo "Coverage report generated: coverage.html"
详细步骤:
- 依赖检查: 确保 coverage.out 文件存在
- HTML 生成:
- 读取 coverage.out 二进制数据
- 生成带颜色标记的 HTML 页面
- 绿色 = 已覆盖,红色 = 未覆盖
- 文件输出: 生成 coverage.html 文件
生成文件: coverage.html (可在浏览器中打开)
🗂️ 环境管理命令
make env
执行逻辑:
# Windows环境
ifeq ($(OS),Windows_NT)
@if not exist ".env" ( \
echo Creating .env file... && \
copy env.example .env && \
echo .env file created, please modify configuration as needed \
) else ( \
echo .env file already exists \
)
# Unix环境
else
@if [ ! -f .env ]; then \
echo "Creating .env file..."; \
cp env.example .env; \
echo ".env file created, please modify configuration as needed"; \
else \
echo ".env file already exists"; \
fi
endif
详细步骤:
- 文件检查: 检查.env 文件是否已存在
- 如果不存在:
- Windows: 使用
copy命令复制 - Unix: 使用
cp命令复制 - 复制
env.example→.env
- Windows: 使用
- 如果已存在: 显示提示信息,不覆盖现有文件
相关文件: env.example → .env
make setup
执行逻辑:
# 依赖: make deps env
# 然后执行:
@echo "Setting up development environment..."
@echo "1. Dependencies installed"
@echo "2. .env file created"
@echo "3. Please ensure PostgreSQL and Redis are running"
@echo "4. Run 'make migrate' to create database tables"
@echo "5. Run 'make dev' to start development server"
详细步骤:
- 执行 make deps: 安装 Go 依赖
- 执行 make env: 创建环境配置文件
- 输出设置指南: 显示后续步骤提示
完成后状态: 开发环境基本就绪,需要手动启动数据库服务
🐳 Docker 相关命令
make docker-build
执行逻辑:
docker build -t tyapi-server:1.0.0 -t tyapi-server:latest .
详细步骤:
- 读取 Dockerfile: 从当前目录读取 Dockerfile
- 构建上下文: 将当前目录作为构建上下文发送给 Docker daemon
- 镜像构建:
- 执行 Dockerfile 中的每个指令
- 逐层构建镜像
- 缓存中间层以提高构建速度
- 标签应用: 同时打上版本标签和 latest 标签
生成镜像: tyapi-server:1.0.0, tyapi-server:latest
make docker-run
执行逻辑:
docker run -d --name tyapi-server -p 8080:8080 --env-file .env tyapi-server:latest
详细步骤:
- 环境检查: 确认.env 文件存在
- 容器创建: 基于 latest 镜像创建容器
- 参数应用:
-d: 后台运行 (detached mode)--name tyapi-server: 设置容器名称-p 8080:8080: 端口映射 (主机:容器)--env-file .env: 加载环境变量文件
- 容器启动: 启动应用程序进程
结果: 后台运行的 Docker 容器,端口 8080 可访问
🔧 服务管理命令
make services-up / make dev-up
执行逻辑:
# 检查docker-compose.dev.yml文件
# Windows:
@if exist "docker-compose.dev.yml" ( \
docker-compose -f docker-compose.dev.yml up -d \
) else ( \
echo docker-compose.dev.yml not found \
)
详细步骤:
- 文件检查: 验证 docker-compose.dev.yml 文件存在
- Docker Compose 启动:
- 读取 docker-compose.dev.yml 配置
- 拉取所需的 Docker 镜像 (如果本地不存在)
- 创建 Docker 网络 (tyapi-network)
- 创建数据卷 (postgres_data, redis_data 等)
- 按依赖顺序启动服务:
- PostgreSQL (端口 5432)
- Redis (端口 6379)
- pgAdmin (端口 5050)
- Prometheus (端口 9090)
- Grafana (端口 3000)
- Jaeger (端口 16686)
- MinIO (端口 9000/9001)
- MailHog (端口 8025)
启动的 8 个服务: 数据库、缓存、监控、管理工具等完整开发环境
make services-down / make dev-down
执行逻辑:
docker-compose -f docker-compose.dev.yml down
详细步骤:
- 容器停止: 优雅停止所有服务容器 (发送 SIGTERM)
- 容器删除: 删除所有相关容器
- 网络清理: 删除自定义网络
- 数据保留: 保留数据卷 (数据不丢失)
保留的资源: 数据卷、镜像 删除的资源: 容器、网络
🗃️ 数据库相关命令
make migrate
执行逻辑:
# 步骤1: 执行make build (依赖)
# 步骤2: 运行迁移
./bin/tyapi-server -migrate
详细步骤:
- 应用程序启动: 以迁移模式启动应用
- 数据库连接: 连接到 PostgreSQL 数据库
- 迁移文件扫描: 扫描 migrations 目录下的 SQL 文件
- 版本检查: 检查数据库中的迁移版本表
- 增量执行: 只执行未应用的迁移文件
- 版本更新: 更新迁移版本记录
- 应用退出: 迁移完成后程序退出
相关文件: internal/domains/user/migrations/, PostgreSQL 数据库
make health
执行逻辑:
# 步骤1: 执行make build (依赖)
# 步骤2: 运行健康检查
./bin/tyapi-server -health
详细步骤:
- 健康检查启动: 以健康检查模式启动应用
- 组件检查:
- PostgreSQL 数据库连接
- Redis 缓存连接
- 关键配置项验证
- 必要文件存在性检查
- 状态报告: 输出每个组件的健康状态
- 退出码: 成功返回 0,失败返回非零
检查项目: 数据库、缓存、配置、权限等
🧹 清理命令
make clean
执行逻辑:
# 步骤1: Go缓存清理
go clean
# 步骤2: 文件删除 (根据操作系统)
# Windows:
@if exist "bin" rmdir /s /q "bin" 2>nul || echo ""
@if exist "coverage.out" del /f /q "coverage.out" 2>nul || echo ""
@if exist "coverage.html" del /f /q "coverage.html" 2>nul || echo ""
详细步骤:
- Go 清理:
- 清理编译缓存
- 删除临时构建文件
- 清理测试缓存
- 目录删除:
- 删除整个 bin 目录及内容
- Windows:
rmdir /s /q - Unix:
rm -rf
- 文件删除:
- 删除 coverage.out 测试覆盖率文件
- 删除 coverage.html 覆盖率报告
- 错误抑制: 使用
2>nul或2>/dev/null忽略"文件不存在"错误
删除的内容: bin/, coverage.out, coverage.html, Go 构建缓存
🚀 流水线命令
make ci
执行逻辑:
# 顺序执行5个步骤:
make deps # 安装依赖
make fmt # 代码格式化
make lint # 代码检查
make test # 运行测试
make build # 构建应用
详细流程:
- deps: 确保所有依赖最新且完整
- fmt: 统一代码格式,确保可读性
- lint: 静态代码分析,发现潜在问题
- test: 运行所有测试,确保功能正确
- build: 验证代码可以成功编译
失败策略: 任何一步失败,立即停止后续步骤
make release
执行逻辑:
# 顺序执行3个步骤:
make ci # 完整CI检查
make build-all # 交叉编译所有平台
make docker-build # 构建Docker镜像
详细流程:
- CI 检查: 确保代码质量和功能正确性
- 多平台构建: 生成 5 个平台的可执行文件
- Docker 镜像: 构建容器化版本
输出产物:
- 5 个平台的二进制文件
- Docker 镜像 (2 个标签)
- 测试覆盖率报告
💡 命令执行顺序和依赖关系
🔗 依赖关系图
version ─────► build
health ──────► build
run ─────────► build
migrate ─────► build
coverage ────► test
ci ──────────► deps → fmt → lint → test → build
release ─────► ci → build-all → docker-build
setup ───────► deps → env
⚡ 执行时机建议
每次开发前
make setup # 首次使用
make dev-up # 启动依赖服务
make dev # 开始开发
提交代码前
make ci # 完整检查
发布版本前
make release # 完整构建
这个指南详细说明了每个命令背后的具体操作逻辑,帮助您完全理解 Makefile 的工作原理! 🎯