Skip to content

Instantly share code, notes, and snippets.

@subfuzion
Last active June 11, 2024 22:07
Show Gist options
  • Save subfuzion/0bd969d08fe0d8b5cc4b23c795854a13 to your computer and use it in GitHub Desktop.
Save subfuzion/0bd969d08fe0d8b5cc4b23c795854a13 to your computer and use it in GitHub Desktop.
Makefile for Go projects

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)
@coopernetes
Copy link

coopernetes commented Feb 20, 2023

This is wonderfully useful, thanks! A few small adjustments I made for myself:

  • bash was complaining about bad substitution on the TARGET line. Wrapped the pwd expansion via "$${PWD##*/}" instead of escaping.
  • golint is deprecated so removed that from check
  • used 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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment