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