Skip to content

Instantly share code, notes, and snippets.

@Integralist
Last active January 14, 2025 10:33
Show Gist options
  • Save Integralist/0320ea5b1fccd4b1ad6aa6c369b011e7 to your computer and use it in GitHub Desktop.
Save Integralist/0320ea5b1fccd4b1ad6aa6c369b011e7 to your computer and use it in GitHub Desktop.
[Makefile syntax] #make #makefile #shell

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:

  • Compile and link code.
  • Automate repetitive tasks (e.g., testing, deploying).
  • Track changes in files and only rebuild what’s necessary.

Terminology

target: prerequisites
  recipe
  • target: is expected to be a filename.
  • prerequisites: is a list of files the target depends on
  • recipe: is the command(s) you run to create the target

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:

  • %: pattern rule
  • $@: target name
  • $<: first prerequisite
  • $^: list of prerequisites
  • $?: list of prerequisites that have changed
  • $*: the stem of a target

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. $@).

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