Makefile 的主要的作用是简化构建难度,以及减少 “祖传” 代码。
我也看了很多关于 Go 的 Makefile 文章,但是大部分都是如何用,以及贴上一个特别简单的例子,想要放到 实际项目中使用还相差的很远,所以决定自己写一份自认为可以覆盖 Go 项目的大部分场景的 Makefile 通用 模版。
覆盖了以下场景:
- 多程序编译
- 交叉编译
- 基于 docker 编译
- 基于 pakcage 的覆盖率单元测试
- 清理编译环境
模版
既然是模版所以肯定会涉及到参数的修改,模版中可以修改的变量都为大写字母,意思也很明确这里就不多介绍了。
VERSION ?= v1.0.0
BUILD_DIR ?= build
PKG_NAME = github.com/yakumioto/go-makefile-example
IMAGE_NAME = yakumioto/go-makefile-example-
CGO_ENABLED ?= $(shell go env CGO_ENABLED)
GOARCH ?= $(shell go env GOARCH)
GOOS ?= $(shell go env GOOS)
GO_LDFLAGS ?= -s -w -extldflags \"-static\"
override timestamp = $(shell date '+%s')
override app = $(filter-out $@,$(MAKECMDGOALS))
override package = $(PKG_NAME)/$(filter-out $@,$(MAKECMDGOALS))
override output_build_dir = $(BUILD_DIR)/apps/$(GOOS)
override output_test_dir = $(BUILD_DIR)/tests
.PHONY : build docker-build test clean
%:
@:
build:
@echo "Building $(app) app..."
@mkdir -p $(output_build_dir)
CGO_ENABLED=$(CGO_ENABLED) GOOS=$(GOOS) GOARCH=$(GOARCH) go build -o $(output_build_dir)/$(app) -ldflags '$(GO_LDFLAGS)' $(PKG_NAME)/cmd/$(app)
docker-build:
@echo "Building $(app) app in docker..."
@echo "Building vendor..."
@go mod vendor
@echo "Building image..."
@docker build \
--build-arg command="CGO_ENABLED=$(CGO_ENABLED) go build -o /app -ldflags '$(GO_LDFLAGS)' $(PKG_NAME)/cmd/$(app)" \
-t $(IMAGE_NAME)$(app):$(VERSION) -f images/$(app)/Dockerfile .
test:
@echo "Testing $(package) ..."
@mkdir -p $(output_test_dir)
go test -coverprofile=$(output_test_dir)/$(timestamp).out $(package)
clean:
@echo "Cleaning..."
@rm -rf build/*
@rm -rf vendor
使用
以 github.com/yakumioto/m… 为例,系统为 macOS
makefile-go-eample
├── build
├── cmd
│ └── add
├── images
│ └── add
└── internal
└── utils
命令栗子:
make build addmake docker-build addmake build add GOOS=linuxmake docker-build add GOOS=linux GOARCH=386make test internal/utilsmake clean
当然很多命令都可以追加参数,以达到想要的目的,不过我觉得已经覆盖大部分场景了。