Header Files and Recompilation
Remember our
cowchat
andcowmath
programs?
printmoos.hpp
:
#ifndef PRINTMOOS_HPP_INCLUDED
#define PRINTMOOS_HPP_INCLUDED
void printMoos(int numMoos);
#endif
printmoos.cpp
:
#include "printmoos.hpp"
#include <iostream> // for std::cin, std::cout
// Prints the given number of "moos"
void printMoos(int numMoos) {
std::cout << "Moo";
for (int i = 1; i < numMoos; ++i) {
std::cout << " moo";
}
std::cout << ".";
}
cowchat.cpp
:
#include "printmoos.hpp"
#include <iostream> // for std::cin, std::cout
#include <string> // for std::string
int main() {
std::cout << "Chat with a cow!";
std::string userIn;
do {
std::cout << std::endl // New line
<< "> "; // The prompt
std::getline(std::cin, userIn);
int nMoos = 1 + userIn.size() % 2;
// ^-- Either 1 or 2 moos;
printMoos(nMoos);
} while (std::cin.good() && userIn != "");
std::cout << "\n\nBye!\n";
return 0;
}
cowmath.cpp
:
#include "printmoos.hpp"
#include <iostream> // for std::cin, std::cout
int main() {
std::cout << "Cow math!\n";
std::cout << "Enter the first number: ";
int x = 0;
std::cin >> x;
std::cout << "Enter the second number: ";
int y = 0;
std::cin >> y;
if (std::cin.good()) {
std::cout << "The cow goes: ";
printMoos(x + y);
std::cout << std::endl;
} else {
std::cout << "\n\nSomething went wrong!\n";
}
return 0;
}
We can compile the whole project by running
clang++ -c printmoos.cpp
clang++ -c cowchat.cpp
clang++ -c cowmath.cpp
clang++ -o cowchat cowchat.o printmoos.o
clang++ -o cowmath cowmath.o printmoos.o
Recompiling After Changes
Say we make a change to cowchat.cpp
.
Since we only changed cowchat.cpp
, we only need to recompile cowchat.o
and relink our object files to get our executable cowchat
:
clang++ -c cowchat.cpp
clang++ -o cowchat cowchat.o printmoos.o
Okay, how about a trickier one? Now say we make a change to printmoos.hpp
.
Remember that we don't compile header files!
But printmoos.hpp
is included by all our source files. So whatever is in printmoos.hpp
is also in all the files after the preprocessor runs, so changes to printmoos.hpp
are, effectively, changes to all our .cpp
files!
Therefore, if printmoos.hpp
changes, we need to recompile all of our .o
files (and then relink as necessary):
clang++ -c printmoos.cpp
clang++ -c cowchat.cpp
clang++ -o cowchat cowchat.o printmoos.o
clang++ -c cowmath.cpp
clang++ -o cowmath cowmath.o printmoos.o
The diagram below shows the dependencies between the files in our project. (A solid arrow from a node to another node means “if the first node is updated, we need to rebuild the second node”; dotted lines show the #include
s.)
Whoah. So when a header file is changed we have to recompile all the source files that include it.
Yup!
And don't forget that sometimes header files include header files.
So when a header file is changed we also have to recompile source files that include a file that includes it, and so on.
Figuring all that out (i.e., what needs to be recompiled) seems like a bunch of work.
Later on, we'll see ways to automate the process of figuring out what needs to be recompiled, but one thing at a time.
(When logged in, completion status appears here.)