CS170 Lab: C++ Separate Compilation and Makefile
Highlights of this lab:
The purpose of this lab is to show you how to compile a C++
program that is formed by several separate files.
Makefiles simplify this process a great deal.
Lab Exercise:
Separate Compilation
Suppose you had a main function in the file main.cpp,
and a function in the file myfunction.cpp.
Further suppose that both main.cpp and myfunction.cpp each had
a reference to the .h file myfunction.h.
You would have to compile each of these files separately to produce
.o files
and then link them all together.
The following commands show how to do this.
Notice the -c
option you need to specify when you want to compile only , not to
compile and link.
Compile only:
g++ -c main.cpp
|
Compile only:
g++ -c myfunction.cpp
|
Link:
g++ main.o myfunction.o
-o main
|
Note that if you wanted to compile a whole set of C++ programs at the same time,
you could enter:
g++ -c *.cpp
Be careful with this though, for these reasons:
- Using the wildcard "*" will refer to every .cpp file in the current directory.
If you are going to use this, you should first put all the files
for the program in a special directory for that program.
- If you have only made a change to one file, there is no reason to compile
every single file.
In a program that consists of many files, this is extremely time-consuming.
Note that to link a whole set of object files
you could have just entered:
g++ *.o -o main
Again, you should be careful that you have all your files in one directory.
The following diagram illustrates how the previous example appears conceptually:
Building Executables with "make"
You can use the Unix utility called make to help you
create an executable file from several C++ files.
There are many other uses for make, but this lab focuses
on how to use it to help simplify working with C++ files.
Here is a list of references for using make:
When you type make at the Unix/Linux command prompt,
it looks for a file called
Makefile or makefile
which you would have created with a text editor.
Inside the Makefile
you have to put in the names of the C++ and object files that
you need to create the executable file for the C++ project
you are working with.
Before we get into Makefile features such as
targets,
variables, and dependencies let's look at
an example of how you would create a C++ project without
a Makefile.
We can then see how to make life simpler by using a Makefile to
create that same C++ project.
Let's look at the files for a simple calculator project.
The files are:
Calculatr.cpp
DoMenu.cpp
GetOperands.cpp
AddNums.cpp
ModNums.cpp
Expon.cpp
and
Calculatr.h
- Enter mkdir CalculatrPgm
to create a directory for those files.
- Copy them to your Hercules disk space
with these commands:
cp /net/data/ftp/pub/class/170/ftp/cpp/CalculatrPgm/*.cpp CalculatrPgm
cp /net/data/ftp/pub/class/170/ftp/cpp/CalculatrPgm/*.h CalculatrPgm
-
Enter cd CalculatrPgm
to move into your new directory.
Those steps just set you up to work with the files.
You still need to compile the separate C++ modules and link them all together.
Here are the steps to do that:
- g++ -c Calculatr.cpp
- g++ -c DoMenu.cpp
- g++ -c GetOperands.cpp
- g++ -c AddNums.cpp
- g++ -c ModNums.cpp
- g++ -c Expon.cpp
- g++ Calculatr.o DoMenu.o GetOperands.o AddNums.o
ModNums.o Expon.o -o Calculatr
Now everytime you make a change to one or two modules, you
have to recompile those files and then perform the link again.
And if you make a change to the .h file that all of those .cpp
files depended upon, you have to recompile everything
and do the link again.
Of course you can just do this:
- g++ -c *.cpp
- g++ *.o -o Calculatr
but that is time-consuming and not at all necessary.
It is much better to only compile the files you need to.
This is where a Makefile can help you.
You have to be observe a little syntax when you create your
Makefile with a text editor.
Here are a few very simple rules:
This is a simple introduction to Makefiles.
As you become comfortable with them you will find that you
can elaborate with targets to clean up old .o files and so on.
However, to start, here is a simple Makefile to deal with the
Calculatr project.
# Makefile to create the Calculatr project
Calculatr.o: Calculatr.cpp Calculatr.h
g++ -c Calculatr.cpp
DoMenu.o: DoMenu.cpp Calculatr.h
g++ -c DoMenu.cpp
GetOperands.o: GetOperands.cpp Calculatr.h
g++ -c GetOperands.cpp
AddNums.o: AddNums.cpp Calculatr.h
g++ -c AddNums.cpp
ModNums.o: ModNums.cpp Calculatr.h
g++ -c ModNums.cpp
Expon.o: Expon.cpp Calculatr.h
g++ -c Expon.cpp
Calculatr: Calculatr.o DoMenu.o GetOperands.o AddNums.o ModNums.o Expon.o
g++ Calculatr.o DoMenu.o GetOperands.o AddNums.o ModNums.o Expon.o -o Calculatr
Now that you understand what is in a Makefile you need to know how
to use it.
It's quite straightforward - simply enter make target
at the system prompt.
The make process will report on what it is doing.
The following examples performed on the Venus computer
illustrate how you to compile a single module, and how to link all files.
venus[24]% make DoMenu.o
g++ -c DoMenu.cpp
venus[27]% make Calculatr
g++ Calculatr.o DoMenu.o GetOperands.o AddNums.o ModNums.o -o Calculatr
venus[28]%
If you enter a target that is already current, "make" reports that.
e.g.
venus[22]% make DoMenu.o
`DoMenu.o' is up to date.
The bottom line here is that Makefiles help you work with multiple C++
files that make up a project.
By only compiling the C++ files that you have to compile,
you save a lot of time recompiling files needlessly.
For greater detail on Makefiles, go back to any of the tutorials
given at the start of this explanation.
Lab Exercise:
Copyright: Department of Computer Science, University of Regina.