Home -> Unix Programming Tools

make is a standard POSIX program to read in a Makefile and execute one or more rules to compile your program.

A Makefile consists of a series of variables and rules. Each rule has three different parts.

rule1: dependency1 dependency2
		action
rule2: dependency1 dependency2 dependency3
		action
	  

rule_name:
The rule name is what is to be built. When you call make without any arguments, the program will look for the first rule and execute that. If you give it an argument, then make will look for a matching rule and execute it directly.
dependency
Each dependency, in a space-separated list, is a file or object that needs to be present in order for the action to be executed. The make program will do two useful things here:
  1. If the dependency exists, but is newer than the last time the target being built, then it will rebuild it, as one of its files has changed.
  2. If the dependency does not exist, then make will look for a rule with that dependency's name and execute that. When make finishes that action to build the dependency, then it will verify it exists and continue down the chain of dependencies.
This way make only executes rules if something has changed and will automatically try and create missing dependencies by using their own rules to build them.
action
The action must be tabbed over; it has to be one tab, not spaces. Once all of the dependencies are verified and up to date, then the action is executed.

Example: Let's look at a Makefile to build a simple C program called hello.c

Makefile:
hello: hello.c
		gcc -o hello hello.c
	  

We would then execute make hello, or even just make as hello is the first rule, in our code directory to build the program.

Terminal:
kandrea@zeus-1:~/tmp/doc$ ls
hello.c  Makefile 
kandrea@zeus-1:~/tmp/doc$ make hello 
gcc -o hello hello.c 
kandrea@zeus-1:~/tmp/doc$ ls 
hello  hello.c  Makefile 
kandrea@zeus-1:~/tmp/doc$ 
	  

This is nice, but can be much more useful with variables.

In a Makefile, a variable can be created by making an assignment using the = symbol. These variables can then be used by referencing them within a $() enclosure.

These variables are commonly used to store frequently used options for compiling, as shown here:

Makefile:
CFLAGS=-g -Wall -Og       
CC=gcc       
       
hello: hello.c       
		$(CC) $(CFLAGS) -o hello hello.c       
	  

This now supports more common options. By running make, hello will still be built using hello.c, however, now we are also building it for GDB debugging with the -g flag, for debug-level optimization with -Og, and with all warnings turned on with -Wall. One nice thing here is that we can now add many more rules that all use the same common options.

The last little change is when we look at the action line, the hello.c depenency is still hardcoded in to the action. Makefiles support several standard built-in variables that can be used in its place:

$@
The name of the target. So, if the rule was hello.o: , then $@ would become hello.o
$*
The name of the target without extension. So, if the rule was hello.o: , then $* would become hello
$<
The name of the first dependency. So, if the dependency list was hello.c hi.c yo.c , then $< would be hello.c
$^
The name of all the dependencies. So, if the dependency list was hello.c hi.c yo.c , then $^ would be hello.c hi.c yo.c

Here's an example in action:

Makefile:
CFLAGS=-g -Wall -Og       
CC=gcc       
       
hello: hello.c       
		$(CC) $(CFLAGS) -o $@ $^       
	  

This example will build hello using the following action:

Terminal:
kandrea@zeus-1:~/tmp/doc$ make
gcc -g -Wall -Og -o hello hello.c
kandrea@zeus-1:~/tmp/doc$ 
	  

While nice, the real power of make is when you have to build a program using multiple source files. Those are easy with a Makefile, since all you need to do is add them to the dependencies and then use the appropriate built-in variables and any custom action you need to write. Once all of that is written, even the most complicated program can be re-built using just a single call to make from the command line.