CS 70

Header Files and Recompilation

  • LHS Cow speaking

    Remember our cowchat and cowmath 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.

What commands would be necessary to recompile?

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.

What commands would be necessary to recompile?

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 #includes.)

state diagram showing the dependencies in the project files

  • Horse speaking

    Whoah. So when a header file is changed we have to recompile all the source files that include it.

  • LHS Cow speaking

    Yup!

  • RHS Cow speaking

    And don't forget that sometimes header files include header files.

  • LHS Cow speaking

    So when a header file is changed we also have to recompile source files that include a file that includes it, and so on.

  • Horse speaking

    Figuring all that out (i.e., what needs to be recompiled) seems like a bunch of work.

  • LHS Cow speaking

    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.)