Skip to content

Instantly share code, notes, and snippets.

@angus-g
Created June 22, 2016 00:02
Show Gist options
  • Save angus-g/b1bf6d6c2cac9edee10004535eabc8d1 to your computer and use it in GitHub Desktop.
Save angus-g/b1bf6d6c2cac9edee10004535eabc8d1 to your computer and use it in GitHub Desktop.

Makefile

Makefiles are used to specify rules for GNU make. In its simplest form, the syntax involves declaring targets and their prerequisites, along with instructions to make the former from the latter:

foo: foo.c
	$(CC) $(OUTPUT_OPTION) $^

A lot of informative output is printed when invoking make -p, which prints the database of rules and variables. This shows make’s implicit rules, such as %: %.c to compile a C file, without having to manually specify the rule as in the example above.

See Managing Projects with GNU Make, 3rd edition for more information and examples.

Variables

Automatic variables

$<

the name of the first prerequisite

$^

the names of all prerequisites, separated by spaces

$?

the names of all prerequisites newer than the target

$*

the stem with which an implicit rule matches

$@

the filename of the target

Target variables

Target variables are useful when dealing with generic makefiles that involve multiple targets. For example, to add linker flags to a certain target:

target: LDFLAGS+=$(shell pkg-config --libs libfoo)

Functions

Functions can be used to transform text, which is particularly used when turning source filenames into their intermediate targets.

Substitutions

To automatically create a variable holding outputs from a list of sources, use patsubst to change file extensions:

OBJS = $(patsubst %.c,%.o,$(SOURCES))

File name manipulation

$(dir names)

extracts the directory-part of each file name in names, up to and including the last slash

$(notdir names)

extracts everything but the directory-part of each file in names, the exact opposite of $(dir names)

$(basename names)

extracts all but the suffix of each file in names

$(addsuffix suffix,names)

suffix is appended to the end of each file in names

Meta

To evaluate expressions within a rule, the eval function can be used:

target: deps
	$(eval VAR := $(shell mktemp))
	mv $(VAR) $@

Targets

Multiple targets can be defined from the same rule by separating them by spaces:

%.byte %.native: %.ml
	ocamlbuild $@

Targets declared as .PHONY are expected to not produce an output of the same name, and will thus usually run unconditionally. This is often used for the clean target:

.PHONY: clean

clean:
	rm -f $(OBJS)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment