« Back to Index

Make: Makefile syntax

View original Gist on GitHub

Tags: #make #makefile #shell

Makefile.md

Make

Make is a build automation tool that uses a file called a Makefile to define how to build, test, or manage dependencies in a project.

It’s commonly used to:

Terminology

target: prerequisites
  recipe

The entire block of code (target, prerequisite, recipe) is called a ‘rule’.

[!NOTE] Not all ‘targets’ will be a filename because you don’t always want to use Make to create files. You often want to use Make to just run some code without the side-effect of creating a new file. In these cases you annotate your rule with .PHONY: target.

[!NOTE] You can have multiple prerequisites, and they can either be a filename or they can be the name of another target.

Automatic Variables

Make’s Automatic Variables are special variables that represent parts of a rule, making Makefiles more concise and flexible. They get their values automatically based on the target, prerequisites, or commands.

You’ll see a few different automatic variables used:

[!IMPORTANT] Any time you need to use a shell variable (i.e. $foo) it must be prefixed with $.
This is because $ already has a special meaning in Make.
So, the variable would be referenced like $$foo (see also Make’s shell function).

Example

Let’s look at an example rule:

%.mock.pid: %.mock
  ./%.mock -addr=127.0.0.1:8446 > .$<.log & echo $$! > $@

Then it could be invoked (as an example) like so:

make mustang.mock.pid

The % wildcard would match the above Makefile target %.mock.pid.

Next it would ensure the prerequisite mustang.mock existed (i.e. %.mock).

Next it would run the ./mustang.mock binary (i.e. ./%.mock).

The stdout (>) would be written to .mustang.mock.log (i.e. .$<.log).

Finally, the process ID ($$!) is written to mustang.mock.pid (i.e. $@).

Performance

Make has built-in rules (e.g., for compiling .c to .o) called implicit rules.
https://www.gnu.org/software/make/manual/html_node/Implicit-Rules.html

The following example disables default implicit rule searches:

# These empty rules tell Make *not* to search for implicit rules for .go, .mk, .json & the Makefile itself.
# Searching for them can be slow. This speeds up dependency checking.
Makefile : ;

# The double-colon `::` fully disables the implicit search.
%.go %.mk %.json :: ;

Functions

There are many built-in functions you can use.

Here are some useful documentation pages:

Generating Help Output

https://gist.github.com/Integralist/4447885192c7e84e01ca7c9f2e08ef17