C++ Makefile Dependencies: What Files Do Object Files Depend On?

I'm a little confused on the Makefile dependencies for .cpp files. For example, say I have a file main.cpp that includes Point.h and Rectangle.h. I would think that the Makefile dependency line for main.o looks like:

main.o: main.cpp

But it seems most people would do:

main.o: main.cpp Point.h Rectangle.h

I don't understand why. Object files are created before linking, right? So when main.cpp is compiled to main.o, its references to Point and Rectangle functions are still unresolved references, in a way. Then, when making the final executable, the linker resolves the references with the machine code for Point and Rectangle. In other words, main.o doesn't really get impacted if I change Point.h or Rectangle.h. The final executable does depend on all three, but main.o does not. What is wrong with my thinking?

1 answer

  • answered 2019-12-14 23:00 Sam Varshavchik

    Let's say your Point.h header file defines a class as follows:

    class Point {
    
        int x;
    
        int y;
    
        int hash() const
        {
              return x+y;
        }
    };
    

    The class may have other stuff in it, or some other class method. This is just an example.

    Your main.cpp calls the hash() method of some Point. And you compile it.

    Now you go back, and edit this header file:

        int hash() const
        {
              return x*y;
        }
    

    You don't change anything in main.cpp.

    But you obviously must recompile it, since it's now supposed to be doing something different, since it calls hash().

    Pretty much any kind of change in the header file potentially affects any .cpp file that includes it, hence they all must be recompiled.

    An #include is logically equivalent to replacing the line with the #include with the entire contents of the included file.

    So, if you change anything in the header file, it is logically equivalent to changing something in the .cpp file that includes it. It is the compiled code in the main.o that's affected by it, and not just the final executable. Here, you'll just relink the same code in main.o that still uses the definition of hash() that you already changed now.