CS 242 Spring 2010 : Makefile Tutorial

CS 242 Spring 2010 : Makefile Tutorial

This page last changed on Feb 17, 2009 by csvenss2.

Makefiles are a vital part of any project. They allow you to build your projects with a single command, and can significantly reduce the time needed to compile large projects. I’ve come up with a sample makefile for a fictional (but perhaps familiar) project: Makefile. This file is explained in pieces below.

Variables

# Variables
CC=gcc # This will be our compiler of choice
FLAGS=-W # Any compiler flags can go here
OBJ=main.o dem.o bmp.o txt.o # These are the modules of the application
OUT=dem2bmp # This is what we want our executable named

Makefiles can have variables, similar to variables in any other programming language. You’ll also notice that Makefiles can contain comments as well. Comments start with a #. Variables are typically all upper-case (this is just convention, not required) and are declared with the following syntax:

VAR=value

You should think of these variables as straight substitution. That is, anywhere you see the variable in the makefile, you can substitute value for that variable. In this example we’ve made some variables that you may commonly see in Makefiles. CC specifies what compiler to use, FLAGS denote any compiler flags we will use frequently, and OUT is the name of our executable. The OBJ variable will be used to tell our makefile what we expect to compile as part of our project. In this case, the project has several modules: main.o, dem.o, bmp.o, and txt.o.

Targets

# If you just type make, the first rule will execute
# Before we can execute this rule, every file in OBJS
# Must be created
all: $(OBJ)
$(CC) $(FLAGS) $^ -o $(OUT)

Here we can see how variables are used. To refer to a variable we need a $ in front of the variable name. Variables whose names are more than one character need to be encompassed with parentheses as shown. Targets are defined in a Makefile in the following manner:

target: dependencies
command

Makefiles are very picky, and there needs to be a tab (t character) preceding the command. The target is the name of your rule. You can type ‘make target’ at the command line, and the corresponding command(s) will be executed. If no target is specified, make uses the first target defined in the file. Each target can have a list of dependencies. These dependencies can either be files or other targets. In this example, in order to make the target ‘all’ we need to have all of our .o files. If they do not exist, then the Makefile needs to know how to create the .o files, otherwise the build will fail.

Wildcards

# Here we define how to create .o files
# We take the corresponding .c file and
# Compile it into a .o
%.o: %.c
$(CC) $(FLAGS) -c $< -o $@

Above we have a very general rule (target) for any .o file. This is dependent on the .c file of the same name. When used in the target, % matches any character, and when used in the dependence list, % matches the same characters as in the target. That is, example.o will depend on example.c in this example.

Additionally, we can use the special variable $< to refer to the FIRST name in the dependency list. $@ Matches the name of the target (in this case, example.o).