Files
tyapi-server/docs/Makefile使用指南.md

16 KiB
Raw Blame History

📋 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

详细步骤:

  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

执行逻辑:

# 步骤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

执行逻辑:

# 步骤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-amd64
  • bin/tyapi-server-linux-arm64
  • bin/tyapi-server-darwin-amd64
  • bin/tyapi-server-darwin-arm64
  • bin/tyapi-server-windows-amd64.exe

▶️ 运行相关命令

make run

执行逻辑:

# 步骤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

执行逻辑:

# 直接执行 (已去掉air检查)
go run cmd/api/main.go

详细步骤:

  1. 源码编译: Go 编译器实时编译 main.go 及其依赖
  2. 内存运行: 不生成磁盘文件,直接在内存中运行
  3. 依赖加载: 自动下载并编译所有 import 的包
  4. 服务启动: 启动 HTTP 服务器监听 8080 端口

与 build 的区别:

  • 无需预先构建
  • 代码变更后需手动重启
  • 每次启动都需要重新编译

🛠️ 开发工具命令

make deps

执行逻辑:

# 步骤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

执行逻辑:

go fmt ./...

详细步骤:

  1. 递归扫描: 扫描当前目录及所有子目录的.go 文件
  2. 格式化规则应用:
    • 统一缩进 (tab)
    • 统一换行
    • 移除行尾空格
    • 规范化大括号位置
  3. 文件修改: 直接修改源文件 (in-place)
  4. 报告: 输出被修改的文件列表

影响的文件: 所有.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

详细步骤:

  1. 工具检查: 使用 command -v 检查 golangci-lint 是否在 PATH 中
  2. 如果已安装:
    • 读取 .golangci.yml 配置 (如果存在)
    • 运行多个 linter 检查 (默认包括: errcheck, gosimple, govet, ineffassign 等)
    • 分析所有.go 文件
    • 输出问题报告
  3. 如果未安装: 显示提示信息并跳过

检查项目: 代码质量、潜在 bug、性能问题、安全问题等


🧪 测试相关命令

make test

执行逻辑:

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

执行逻辑:

# 步骤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

执行逻辑:

# 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

执行逻辑:

# 依赖: 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

执行逻辑:

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

执行逻辑:

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

执行逻辑:

# 检查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

执行逻辑:

docker-compose -f docker-compose.dev.yml down

详细步骤:

  1. 容器停止: 优雅停止所有服务容器 (发送 SIGTERM)
  2. 容器删除: 删除所有相关容器
  3. 网络清理: 删除自定义网络
  4. 数据保留: 保留数据卷 (数据不丢失)

保留的资源: 数据卷、镜像 删除的资源: 容器、网络


🗃️ 数据库相关命令

make migrate

执行逻辑:

# 步骤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

执行逻辑:

# 步骤1: 执行make build (依赖)
# 步骤2: 运行健康检查
./bin/tyapi-server -health

详细步骤:

  1. 健康检查启动: 以健康检查模式启动应用
  2. 组件检查:
    • PostgreSQL 数据库连接
    • Redis 缓存连接
    • 关键配置项验证
    • 必要文件存在性检查
  3. 状态报告: 输出每个组件的健康状态
  4. 退出码: 成功返回 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 ""

详细步骤:

  1. Go 清理:
    • 清理编译缓存
    • 删除临时构建文件
    • 清理测试缓存
  2. 目录删除:
    • 删除整个 bin 目录及内容
    • Windows: rmdir /s /q
    • Unix: rm -rf
  3. 文件删除:
    • 删除 coverage.out 测试覆盖率文件
    • 删除 coverage.html 覆盖率报告
  4. 错误抑制: 使用 2>nul2>/dev/null 忽略"文件不存在"错误

删除的内容: bin/, coverage.out, coverage.html, Go 构建缓存


🚀 流水线命令

make ci

执行逻辑:

# 顺序执行5个步骤:
make deps    # 安装依赖
make fmt     # 代码格式化
make lint    # 代码检查
make test    # 运行测试
make build   # 构建应用

详细流程:

  1. deps: 确保所有依赖最新且完整
  2. fmt: 统一代码格式,确保可读性
  3. lint: 静态代码分析,发现潜在问题
  4. test: 运行所有测试,确保功能正确
  5. build: 验证代码可以成功编译

失败策略: 任何一步失败,立即停止后续步骤

make release

执行逻辑:

# 顺序执行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

执行时机建议

每次开发前

make setup    # 首次使用
make dev-up   # 启动依赖服务
make dev      # 开始开发

提交代码前

make ci       # 完整检查

发布版本前

make release  # 完整构建

这个指南详细说明了每个命令背后的具体操作逻辑,帮助您完全理解 Makefile 的工作原理! 🎯