Make
What is it
GNU Make is a tool which controls the generation of executables and other non-source files of a program from the program's source files.
In plain terms, Make is a language-agnostic tool used for building things.
When to use it
Building Go projects
Our Go projects typically use a Makefile
at the root of the project, whose default target runs the
full set of CI build steps and checks for the project.
How to get it
Make is already pre-installed on Ubuntu (recommended).
OSX
OSX users can use a Homebrew formula to install GNU Make. Make sure to follow the
instructions on replacing the default make
with gmake
.
How to learn it
Run through the excellent Makefile Tutorial.
Conventions
Strictly follow the Rules of Makefiles and take as much inspiration as possible from Clark Grubb's Makefile style guide.
The tools/
directory
Our Make projects with dependencies on external build tools (for example command line tools that are
required as part of the build) typically use a tools/
directory to modularize and simplify
managament tooling dependencies.
The typical high-level structure of the tools/
directory is:
tools/
├── tool-1
│ ├── 0.41.0
│ ├── 0.42.0
│ └── rules.mk
├── tool-2
│ ├── 0.7.0
│ └── rules.mk
└── tool-n
├── 1.2.3
└── rules.mk
Every subdirectory of tools/
contains Make rules for a specific tool, and that subdirectory always
contains a rules.mk
with the rules needed to download and/or build that specific tool.
Since Make puts variables from all include
d files into a common global namespace, rules.mk
files
should prefix all variables with the name of the tool itself to minimize variable naming conflicts.
Example tools.mk
An annotated example tools.mk
file for the Buf CLI:
# 1) The parent directory
buf_cwd := $(abspath $(dir $(lastword $(MAKEFILE_LIST))))
# 2) The tool version
buf_version := 0.56.0
# 3) Path to the tool executable
buf := $(buf_cwd)/$(buf_version)/bin/buf
# 4) URL for downloading the tool
buf_bin_url := https://github.com/bufbuild/buf/releases/download/v$(buf_version)/buf-$(shell uname -s)-$(shell uname -m)
# 5) Make rule for downloading the tool
$(buf): $(buf_cwd)/rules.mk
$(info [buf] feching version $(buf_version)...)
@mkdir -p $(dir $@)
@curl -sSL $(buf_bin_url) -o $@
@chmod +x $@
@touch $@
1) The parent directory
The <tool>_cwd
variable is initialized to the current working directory (cwd) of the tool.
$(abspath $(dir $(lastword $(MAKEFILE_LIST))))
is a Make-ism for "the directory of the current
Make file".
2) The tool version
Updating the <tool>_version
variable should be all that is needed when upgrading to a newer
version of the tool.
3) The Path to the tool exectuable
The <tool>
variable contains the absolute path to the current version of the tool binary and will
be used to invoke the tool in the parent Makefile.
4) URL for downloading the tool
Use the output of the uname
command to fetch the correct distribution of the tool for your OS and
CPU architecture.
5) Make rule for downloading the tool
The Make rule for the <tool>
variable fetches, unpacks and updates the modified timestamp of the
tool binary.
The rule depends on $(<tool>_cwd)/rules.mk
to ensure that modifying the rule itself causes the
rule to be re-run.