Lab 13. Separate compilation

Lab 13. Separate compilation

How to submit your code

Each program (the source code .cpp files + Makefile) should be submitted through Blackboard (Course Materials > Lab).

You can submit all your programs at the end of the lab session in one submission. This way, we can hopefully avoid the situation when you are quickly writing your program, immediately uploading it to Blackboard, but then, say 10 minutes later, realizing that there is a bug in it.

Basically, submit when you are sure that it will be your final version.

Each program should start with a comment that contains your name and a short program description, for example:

/*
  Author: Your Name 
  Description: Lab 1. Task 1. Hello world
*/

You can submit incomplete programs, but their “incomplete” status must be clearly mentioned in the comment to the program. In this case, also briefly describe what is implemented, and what is not.

Intro 1. Makefiles

To execute multiple commands in particular order, taking into account dependencies between the files, one can use the program called make

A trivial case is when you just want to compile a single file program program.cpp, a Makefile may look as follows (Note that indentation symbols should be TABs, not simple spaces, otherwise it would not work):


all: program

program: program.cpp
    g++ -Wall -o program program.cpp

clean:
    rm program 

If you have both the cpp file and the Makefile in your current working directory, simply type:

make

The program will take your Makefile, read and execute it. By default it will perform the first rule it finds. In this case, the first rule is the target called all. This rule does not do anything by itself, but it requires to call another rule, program, which actually builds your program. And now you can run the program you just built:

./program

You can explicitly ask make to execute a particular rule, for example:

make all

or

make clean

Intro 2. Breaking a program into several files

The program used in the previous section can be broken down into three files:

Both .cpp files must be built with g++ separately:

g++ -c intset.cpp
g++ -c main.cpp
g++ -o prog intset.o main.o

Also note that both of the files depend on the header file, because both include it with the preprocessor directive #include. The dependencies diagram looks like this.

Every time some source code file (.cpp or .h) gets updated, the files that depend on it must be updated!

Let’s use make to do this automatically. Instead of calling g++ three times every time we want to build the program, we can write a Makefile to do this work:

# The main goal is build the executable "prog"
all: prog

# To build the program prog, two object files 
# "intset.o" and "main.o" must be built,
# then we can link them and produce the executable:
prog: intset.o main.o 
    g++ -Wall -o prog intset.o main.o

intset.o: intset.cpp intset.h
    g++ -Wall -c intset.cpp

main.o: main.cpp intset.h
    g++ -Wall -c main.cpp

# Remove the object files and the executable "prog"
clean:
    - rm -rf *.o prog

Task 0A (Don’t submit).

Read the sections Intro-1 and Intro-2. For each download the source code files, the Makefile, and build the program using make.

Task 0B (Don’t submit).

Examine the files from the Intro-2. Observe how the previously monolithic program program.cpp was divided into three separate files. The declarations of the class IntSet are put into its header file, and its implementation is is now in its own .cpp file.

The contents of each header file are enclosed into #ifndef preprocessor directive that prescribes that the header is included into the .cpp files only once.

#ifndef INTSET_H
#define INTSET_H

...

#endif

All source code files (.cpp or .h) that call functions or use other names declared in the header files, have to include those header files, for exmaple:

#include "intset.h"

Task 1.

In this task you will be given a C++ program and its Makefile, and you have to divide it into mutiple files.

>>> Download: generate.cpp and Makefile <<<

This program generates a random graph (mathematical object = set of nodes together with the set of edges that connect the nodes). In particular, it produces Erdos-Renyi random graph.

To run the program, it requires two parameters, the number of nodes and the filename to save the file, for example:

./generate 100 output.dot

The result is saved in the dot-format that can be converted into a graphics file (PDF in this case) using the program Graphviz, with the following command:

dot -O -Tpdf -Kfdp output.dot

Your task will be to gradually change the program, eventually dividing it into 7 files:

  1. First, separate the class Random into random.cpp and random.h, the rest of the code keep in the program main.cpp. Make sure it compiles and works correctly. Only then move on to the next step. Use the IntSet example as a model.

  2. The same way, separate the class Graph into graph.cpp and graph.h.

  3. Separate the function save_graph() in its own dot.cpp and dot.h