Makefile-Getting started

What is Make?

The make command searches the “makefile” or “Makefile” for the first rule and uses this for its target. Make first ensures that all the files on which the target depends are up to date, and then it creates the target if it either doesn't exist or if it is older than one of the files on which it depends.

Variables

Variable definitions are in the following format in a make file:

VARNAME = Value

These command find use in places like setting the compiler for the program. This is helpful because you may want to switch from cc to gcc or to g++. We would have the following line in our makefile. (g++ for C++ and gcc for C files)

CC = g++

this assigns the variable CC to the string "g++". To expand variables, use the following form:

${VARNAME}

So to expand our CC variable we would say:

${CC}

Format of Makefiles -- Dependencies

Dependencies in a make file play a mojor rule. They govern the properties of the Makefile . The establish the link betwee files which reflect on the final executable. Dependencies have the following form:

dependecy1: dependencyA dependencyB ... dependencyN

Dependency1 is dependent upon dependencyA, and dependencyB, up to however many dependencies you have. The program make, looks at dependency1 and sees it is dependent upon dependencyA, so then it looks later in the makefile for how dependencyA is defined. Lets make a sample makefile:

myprogram: mainprog.cc myclass.cc
g++ mainprog.cc myclass.cc

When you type make, it automatically knows you want to compile the 'myprogram' dependency (because it is the first dependency it found in the makefile). It then looks at mainprog.cc and sees when the last time you changed it, if it has been updated since last you typed make then it will run the gcc mainprog.cc ... line. If not, then it will look at myclass.cc, if it has been edited then it will execute the gcc mainprog.cc ... line, otherwise it will not do anything for this rule.

Another example might be easier to see for dependencies, lets say you have a class, and more than one file depends upon objects of that class type. Then it makes sense to create a .o file of that class and compile it in with the file.

myprogram: mainprog.cc subfile1.o myclass.o
g++ mainprog.cc subfile1.o myclass.o
subfile1.o: subfile1.cc myclass.o
g++ -c mainprog.cc subfile1.o myclass.o
myclass.o: myclass.cc
g++ -c myclass.cc

Notice the dependencies here, when make is run, the dependency called "myprogram" is run first, and then the dependency subfile1.o is found, and then the myclass.o dependency is foudn withint subfile1.o. So myclass.cc is compiled, then subfile1.o is compiled, then we are finally back up to the myprogram dependency. Finally all three dependencies are compiled in to create a.out.

Here is an example of a simple make file.

COMPILER = g++
CCFLAGS = -g
myprogram: mainprog.cc subfile1.o myclass.o
${COMPILER} ${CCFLAGS} mainprog.cc subfile1.o myclass.o
subfile1.o: subfile1.cc myclass.o
${COMPILER} ${CCFLAGS} -c mainprog.cc subfile1.o myclass.o
myclass.o: myclass.cc
${COMPILER} ${CCFLAGS} -c myclass.cc
clean:
rm -rf *.o a.out

So when we type make clean at the command line, it will remove all our .o files and the executable that we have.

Reference: Dr. Chelberg’s webpage on Make files

PREVIOUS HOME NEXT