Created
June 12, 2024 22:23
-
-
Save thomasvincent/03440b6a82a772aa24158b09356cc1ec to your computer and use it in GitHub Desktop.
Modern Go Makefile
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# --- Project Configuration --- | |
PACKAGE := hellogopher | |
DATE ?= $(shell date +%FT%T%z) | |
VERSION ?= $(shell git describe --tags --always --dirty --match=v* 2> /dev/null || echo v0) | |
# --- Go Configuration --- | |
BIN := ./bin # Binary output directory | |
PKGS := $(shell go list ./... | grep -v /vendor/) | |
TESTPKGS := $(shell go list -f '{{ if or .TestGoFiles .XTestGoFiles }}{{ .ImportPath }}{{ end }}' ./...) | |
GO := go | |
# --- Build Options --- | |
TIMEOUT := 15 | |
V := 0 # Verbosity level (0 = quiet, 1 = verbose) | |
Q := $(if $(filter 1,$V),,@) | |
M := $(shell printf "\033[34;1m▶\033[0m") # Blue arrow for output | |
# --- Build Targets --- | |
.PHONY: all | |
all: fmt lint | $(BIN) | |
$(info $(M) Building executable...) | |
$Q $(GO) build -tags release -ldflags '-X main.Version=$(VERSION) -X main.BuildDate=$(DATE)' -o $(BIN)/$(PACKAGE) . | |
$(BIN)/%: # Ensure the bin directory exists | |
mkdir -p $(BIN) | |
# --- Tools --- | |
$(BIN)/%: # Generic rule for installing Go tools in BIN | |
$(GO) install $(subst $(BIN)/,,$@)@latest # Extracts package name and installs with 'go install' | |
GOLANGCI_LINT = $(BIN)/golangci-lint | |
$(GOLANGCI_LINT): # Install golangci-lint if not found | |
$(info $(M) Installing golangci-lint...) | |
$Q $(GO) install github.com/golangci/golangci-lint/cmd/golangci-lint@latest | |
# --- Tests --- | |
TEST_TARGETS := test-default test-bench test-short test-verbose test-race | |
.PHONY: $(TEST_TARGETS) test-xml check test tests | |
test-bench: ARGS=-run=__absolutelynothing__ -bench=. ## Run benchmarks | |
test-short: ARGS=-short ## Run only short tests | |
test-verbose: ARGS=-v ## Run tests in verbose mode | |
test-race: ARGS=-race ## Run tests with race detector | |
$(TEST_TARGETS): test | |
check test tests: fmt lint ; $(info $(M) running $(NAME:%=% )tests…) @ ## Run tests | |
$Q $(GO) test -timeout $(TIMEOUT)s $(ARGS) $(TESTPKGS) | |
test-xml: fmt lint | |
$(info $(M) running $(NAME:%=% )tests…) | |
$Q mkdir -p test | |
$Q $(GO) test -json $(TESTPKGS) | tee test/tests.output | $(GO2XUNIT) -output test/tests.xml | |
# --- Lint --- | |
lint: | $(GOLANGCI_LINT) | |
$(info $(M) running golangci-lint...) | |
$Q $(GOLANGCI_LINT) run | |
# --- Format --- | |
fmt: | |
$(info $(M) running gofmt...) | |
@ret=0 && for d in $$($(GO) list -f '{{.Dir}}' ./... | grep -v /vendor/); do \ | |
$(GOFMT) -l -w $$d/*.go || ret=$$? ; \ | |
done ; exit $$ret | |
# --- Misc --- | |
.PHONY: clean | |
clean: ; $(info $(M) cleaning…) @ ## Cleanup everything | |
@rm -rf $(BIN) | |
@rm -rf test/tests.* test/coverage.* | |
.PHONY: help | |
help: | |
@grep -E '^[ a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | \ | |
awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-15s\033[0m %s\n", $$1, $$2}' | |
.PHONY: version | |
version: | |
@echo $(VERSION) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment