Go has excellent build tools that mitigate the need for using make
.
For example, go install
won't update the target unless it's older
than the source files.
However, a Makefile can be convenient for wrapping Go commands with
specific build targets that simplify usage on the command line.
Since most of the targets are "phony", it's up to you to weigh the
pros and cons of having a dependency on make
versus using a shell
script. For the simplicity of being able to specify targets that
can be chained and can take advantage of make
's chained targets,
having a good Makefile can be effective.
Makefile
SHELL := /bin/bash
# The name of the executable (default is current directory name)
TARGET := $(shell echo $${PWD\#\#*/})
.DEFAULT_GOAL: $(TARGET)
# These will be provided to the target
VERSION := 1.0.0
BUILD := `git rev-parse HEAD`
# Use linker flags to provide version/build settings to the target
LDFLAGS=-ldflags "-X=main.Version=$(VERSION) -X=main.Build=$(BUILD)"
# go source files, ignore vendor directory
SRC = $(shell find . -type f -name '*.go' -not -path "./vendor/*")
.PHONY: all build clean install uninstall fmt simplify check run
all: check install
$(TARGET): $(SRC)
@go build $(LDFLAGS) -o $(TARGET)
build: $(TARGET)
@true
clean:
@rm -f $(TARGET)
install:
@go install $(LDFLAGS)
uninstall: clean
@rm -f $$(which ${TARGET})
fmt:
@gofmt -l -w $(SRC)
simplify:
@gofmt -s -l -w $(SRC)
check:
@test -z $(shell gofmt -l main.go | tee /dev/stderr) || echo "[WARN] Fix formatting issues with 'make fmt'"
@for d in $$(go list ./... | grep -v /vendor/); do golint $${d}; done
@go tool vet ${SRC}
run: install
@$(TARGET)
This is wonderfully useful, thanks! A few small adjustments I made for myself:
"$${PWD##*/}"
instead of escaping.go vet ./...
, solved to the following errors:invoking "go tool vet" directly is unsupported; use "go vet"
named files must all be in one directory; have pkg/k8s and cmd/rolegen
when using${SRC}
go version 1.19.6, GNU Make 4.3 and bash 5.1.16 on Ubuntu.