Using Variables

So far, our makefile for compiling our program of two modules looks like this:

# Link command:
my_program: processing.o gui.o
	c++ processing.o gui.o -o my_program

# Compilation commands:
processing.o: processing.cxx
	c++ -c processing.cxx -o processing.o

gui.o: gui.cxx
	c++ -c gui.cxx -o gui.o

This works wonderfully, but suppose now we want to change some compilation options. Or maybe we want to use a different compiler. We'd have to change all three compilation lines.

Similarly, suppose we want to change the list of modules to compile. We'd have to change it in two places, and if we accidently made the change in only one of them, it could be very difficult to track down the problem.

A better way to do it is to use variables, like this:

# Define the symbols we might want to change:
CXX	:= c++
CXXFLAGS := -g

OBJECTS	:= processing.o gui.o

my_program: $(OBJECTS)
	$(CXX) $(OBJECTS) -o my_program

processing.o: processing.cxx
	$(CXX) $(INCLUDES) $(CXXFLAGS) -c processing.cxx -o processing.o

gui.o: gui.cxx
	$(CXX) $(CXXFLAGS) -c gui.cxx -o gui.o

Here $(CXX) expands to be the value of the variable CXX, and similarly for $(CXXFLAGS) and $(OBJECTS). Now we can just change one line in the makefile, and all relevant compilation commands are affected.

In fact, we don't even need to change the makefile to change compilation options. Assignments specified on the command line override assignments in the makefile. For example, we could type this to the shell:

makepp CXXFLAGS="-g -O2"

which overrides the setting of CXXFLAGS in the makefile. It is as if the makefile contained the line

CXXFLAGS := -g -O2

instead of the definition it does contain.

It might not at all be useful to be able to override these things for your own development, but if you distribute your sources to other people, they might appreciate it.

Variable names are case sensitive (e.g., OBJECTS is different from objects). Usually people write most variables in upper case only, but you don't have to.

If you need to put a literal dollar sign into a rule action, write it with a double dollar sign, like this:

test:
	for testfile in *.test; do run_test $$testfile; done

Conventionally, there are a few variables which you might want to set. These are just conventions, but you will see them in a lot of makefiles.

CC	:= cc			# The C compiler.
CFLAGS	:= -g			# C compilation options which relate to
				# optimization or debugging (usually
				# just -g or -O).  Usually this wouldn't
				# include -I options to specify the
				# include directories, because then you
				# couldn't override it on the command line
				# easily.
CXX	:= c++			# The C++ compiler.  (Sometimes "CPP" instead
				# of CXX.)
CXXFLAGS := -g			# C++ compilation options related to 
				# optimization or debugging (-O or -g).
F77	:= f77			# The fortran compiler.
FFLAGS	:=			# Optimization flags for fortran.

Makepp will guess appropriate values for some of these variables if you don't specify them, but it is usually best to set them explicitly--it makes it easier on anyone reading your makefile.

There are a lot more extremely powerful things you can do with variables, but first we need to explain some more things about makefiles.


Tutorial index | Next (pattern rules) | Previous (a simple makefile)
Last modified: Tue Dec 26 19:27:29 PST 2000