Access Keys:
Skip to content (Access Key - 0)

Makefile Tutorial

Some of the content in this tutorial will be reinforced in our Makefile Dependencies video. For a more detailed explanation of compilation and Makefiles, try the Compilation video.

Check Out the Provided Code

Before you start this tutorial, you'll need to check out mp1 from the class repository and open the Makefile tutorial by typing the following into the terminal:

svn export https://subversion.ews.illinois.edu/svn/sp14-cs225/NETID/mp1
cd mp1/makefiletutorial

Where NETID is your university NetID.

Compiling Code

To run the C++ code that you write, you will first need to compile it - this is when the computer translates code from C++ to CPU instructions. Using g++, the compiler for this class, looks like this:

> g++ -c sphere.cpp
> g++ -c main.cpp
> g++ main.o sphere.o -o myprogram

The last line is called linking; it takes the compiled source files and combines them into a single, runnable program.

Try this (you don't have to type the '>', it represents the command prompt). This will compile the provided code and make a program called myprogram, which you can run by typing ./myprogram

make and the Makefile

The program make lets you automate this process, so that instead of running the three commands above, you can just type make in the terminal to compile your whole project.

There is a second benefit as well. Let's say you just change main.cpp, and leave the sphere class unchanged. You don't need to recompile the sphere class, so you could just type:

> g++ -c main.cpp
> g++ main.o sphere.o -o myprogram

When you set up your Makefile correctly, make detects these changes and figures out which files need to be recompiled, and only recompiles those, letting you get back to coding and debugging faster.

The Makefile explained

First, you'll want to create a file, called Makefile, with a capital M.

> gedit Makefile &

A Makefile has 5 main parts:

Comments

Good code deserves comments; so does a good Makefile. A # starts a comment in a Makefile, just as // starts a comment in C/Java/C++.

Variable declarations

Just like in C++, Makefiles can (and should) have variables. We usually declare our compiler and compiler options:

COMPILER = g++
COMPILER_FLAGS = -c -g -O0 -Wall -Werror
LINKER = g++

You can also make variables for things such as your program's name or source files, but you won't need to do that for this class.

Compilation Steps

We'll need to tell make how to compile each of our source code files

main.o : main.cpp sphere.h
	$(COMPILER) $(COMPILER_FLAGS) main.cpp

The first line tells make the name of the object file it is compiling, followed by a colon. Object files are what your .cpp source files are compiled to, and they usually have the same filename as their .cpp file, but with a .o extension.

After the colon is a list of dependencies - files that are used by the source .cpp file. If any of these files changes, the .o file will be recompiled. For example, the main.cpp code uses the sphere class, so it depends on sphere.h, and must be recompiled if the sphere class functions change. It does not technically depend on sphere.cpp.

The second line contains the instructions for compiling main.o. To recompile main.o, we want to call our compiler, with our compiler flags, on main.cpp. To access the variables we set earlier, we surround their names in $(), so $(COMPILER) evaluates to g++. Note that there must be one level of indentation on the second line, which MUST be a TAB character, not spaces.

You'll also need to add a step to compiler sphere.o from the sphere sources.

A Linking Step

To get make to link our program, we tell make how to link myprogram, just like we told make how to compile main.o:

myprogram : main.o sphere.o
	$(LINKER) main.o sphere.o -o myprogram

myprogram depends on main.o and sphere.o - if either of those files is recompiled, myprogram must be recompiled. The second line again is the instructions on how to create myprogram, which is done by running the linker on main.o and sphere.o, and outputting (with the -o flag) myprogram.

For most of your MPs, you will be using EasyPNG, which needs the library libpng to be linked with your program. To link libpng, add the linker option -lpng during your linking step:

myprogram : main.o sphere.o
	$(LINKER) main.o sphere.o -lpng -o myprogram

Note that running make defaults to compiling the first target, the linking step should be placed ABOVE the compilation steps described earlier, so that when make reads the file line-by-line from the top, it sees the linking step first.

A clean option

Occasionally you'll want to remove all precompiled files from your folder, so that you can recompile from scratch. If your Makefile has a dependency problem, recompiling from scratch usually fixes it temporarily. We do this by having a clean target in the Makefile. This looks like:

clean:
	-rm -f *.o myprogram

This is special syntax for the clean target; if you are curious about how it works you are more than welcome to look up Makefile information online .

Now save your Makefile, and type make or make myprogram on the terminal, and you should see the steps to compile your program (from the top of the page), output on your terminal. You can run myprogram by typing ./myprogram on the terminal. You can remove all compiled files by typing make clean at the terminal.

Common Issues

If you use spaces instead of a single TAB character for indentation inside your Makefile, you'll get the following error:

Makefile:6: *** missing separator.  Stop.

If you forget to define rules for compiling each of your .cpp files, you'll get errors which look like the following:

make: warning: undefined variable `CXXFLAGS'
make: warning: undefined variable `CPPFLAGS'
make: warning: undefined variable `TARGET_ARCH'

For other issues, talk to course staff or post on the newsgroup .

Adaptavist Theme Builder (4.2.2) Powered by Atlassian Confluence 3.4.9, the Enterprise Wiki