The main purpose of makefiles is to simplify build and reduce “ancestral” code.

I also read a lot of articles about Go Makefiles, but most of them were far from being used and a particularly simple example was posted, so I decided to write a generic template for Makefiles that I thought would cover most of the scenarios of Go projects.

The following scenarios are covered:

  • Multiprogram compilation
  • cross-compilation
  • Compile based on Docker
  • Coverage unit testing based on pakcage
  • Clean up the compilation environment

template

Since it is a template, it must involve modifying parameters. The variables that can be modified in a template are all in uppercase letters, so the meaning is very clear and I won’t talk about it here.

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 vendorCopy the code

use

In order to github.com/yakumioto/m… For example, run the macOS

The makefile - go - eample ├ ─ ─ build ├ ─ ─ CMD │ └ ─ ─ the add ├ ─ ─ images │ └ ─ ─ the add └ ─ ─ internal └ ─ ─ utilsCopy the code

Command chestnut:

  • make build add
  • make docker-build add
  • make build add GOOS=linux
  • make docker-build add GOOS=linux GOARCH=386
  • make test internal/utils
  • make clean

Of course, many commands can append parameters to achieve the desired purpose, but I think that covers most scenarios.

reference

  • Github.com/hyperledger…
  • www.gnu.org/software/ma…