# Minimal Golang Makefile

Having build many Golang projects I came with a minimalist makefile that might work for you.
by Ciro S. Costa , Nov 11 - 2017

https://ops.tips/blog/minimal-golang-makefile/

Most of the time I see myself creating a Golang project: be it a one-file single-purpose thing or a more complex project.

In order to facilitate that process, I try to always keep the structure the same such that there’s no need to put much thought into the process of bootstrapping a new project.

The file structure usually looks like this:

.├── .editorconfig├── Dockerfile├── Makefile├── VERSION├── lib│   ├── foo.go│   ├── foo_test.go│   ├── something.go│   └── something_test.go└── main.go

Some things to pay attention:

1. editorconfig is a real deal - I use vim with set shiftwidth=2; set tabstop=2, that is, 2 as the indentation. For go, tab with 8 spaces as indentation.

2. be it a cli tool or a library, I always make use of a main.go in the root so that’s it’s obvious how to fetch it - go get -u <repo>.

## Snippet

Given the filestructure described above, below is the Makefile. In this case I extracted the Makefile from a test project I started some time ago (a “load-balancer” that makes use of fasthttp: cirocosta/l7).

# I usually keep a VERSION file in the root so that anyone# can clearly check what's the VERSION of master or any# branch at any time by checking the VERSION in that git# revisionVERSION         :=      $(shell cat ./VERSION)IMAGE_NAME := cirocosta/l7# As a call to make without any arguments leads to the execution# of the first target found I really prefer to make sure that this# first one is a non-destructive one that does the most simple # desired installation. It's very common to people set it as all# but it could be anything like a.all: install# Install just performs a normal go install which builds the source# files from the package at ./ (I like to keep a main.go in the root# that imports other subpackages). As I always commit vendor to git# a go install will typically always work - except if there's an OS# limitation in the build flags (e.g, a linux-only project).install: go install -v# keeping ./main.go with just a cli and ./lib/*.go with actual # logic, tests usually reside under ./lib (or some other subdirectories).# Here we could do something like find . -name "*" -type d -exec ... but IMO# that's unnecessary. Just cding to what matters to you is fine - no need to# handle the case of directories that you don't want to execute a command.test: cd ./lib && go test -v# Just like test, formatting what matters. As main.go is in the root,# go fmt the root package. Then just cd to what matters to you (vendor# doesn't matter).fmt: go fmt cd ./lib && go fmt# This target is only useful if you plan to also create a Docker image at# the end. I have a separate gist with a sample Dockerfile tailored for# golang that you can check out at <TODO>.# I really like publishing a Docker image together with the GitHub release# because Docker makes it very simple to someone run your binary without# having to worry about the retrieval of the binary and execution of it# - docker already provides the necessary boundaries.image: docker build -t cirocosta/l7 .# This is pretty much an optional thing that I tend to always include.# Goreleaser is a tool that allows anyone to integrate a binary releasing# process to their pipelines. Here in this target With just a simple # make release you can have a tag created in GitHub with multiple# builds if you wish. # See more at gorelease github repo.release: git tag -a$(VERSION) -m "Release" || true    git push origin \$(VERSION)    goreleaser --rm-dist.PHONY: install test fmt release

Save that content in the Makefile file in root directory of the project, create a VERSION file with something like 0.0.1 (semver) and you’re ready to go.

## Closing thoughts

I think it’s very useful to keep a standard way of performing basic operations across multiple repositories. In my experience this reduces the friction of moving from one project to another. Having a common flow of how to build, create an image and publish a project using a Makefile has helped me in such area.

Do you think the same? What are your thoughts?

Reach me on Twitter at any time @cirowrc and subscribe to the list if you’re a Golang developer or simply likes software stuff!

finis