Build Systems, Libraries & Dependencies

Make and the Makefile

/ MAYK /

Make is the classic, decades-old build system on Unix-like systems, and the Makefile is the plain-text file where you write down your build instructions for it. If a build system is a kitchen assistant, Make is a particular, very widely used assistant, and the Makefile is the written recipe card you hand it. You run it by typing make in a directory that contains a file named Makefile.

A Makefile is mostly a list of rules. Each rule says: here is a thing I want to produce (the target), here are the things it is made from (the prerequisites), and here are the shell commands to make it (the recipe). Make reads all the rules, figures out the order from how the targets and prerequisites connect, and then runs only the recipes whose inputs are newer than their outputs. One crucial and infamous detail: each recipe line in a Makefile must begin with a real TAB character, not spaces, or Make reports a confusing error.

Why it matters: Make is everywhere, so being able to read a Makefile lets you build a huge amount of existing software. It is also small and transparent, which is good for learning. Its weaknesses are real, though: the syntax is terse and quirky, it is built around file timestamps (which can mislead it), and it does not by itself know how to find compilers or libraries on different systems, which is part of why meta-build tools like CMake exist on top of it.

A tiny Makefile (recipe lines start with a TAB): app: main.o util.o gcc main.o util.o -o app main.o: main.c gcc -c main.c Then: $ make

Three rules tell Make how app is built from object files, and each object file from its source.

The single most common beginner error is using spaces instead of a TAB to indent a recipe line; Make then prints 'missing separator', which does not obviously mean 'you used spaces'.

Also called
GNU Makemakefile