I've recently started to learn how to write makefile, and I've got a question which seems to me to have a simple answer. It's that how can we write makefile when two header files include eachother? I've searched for an answer to it but I couldn't find anything. (I want the content of the makefile be as simple as possible)
-
1Two header files should not include each other. – juanchopanza May 23 '14 at 13:41
-
@juanchopanza so there isn't any answer to this question? – user3590783 May 23 '14 at 13:43
-
If you use inclusion headers this should be fine and you make file should just compile the source right? – Montaldo May 23 '14 at 13:44
-
Well, re-factor your code such that you don't have circular include dependencies. – juanchopanza May 23 '14 at 13:44
-
Two header files including each other should be fine as long as they both have re-include guards and the things they define and expect from each other can be lined up correctly so as to function I think. That fact has nothing to do with make at all though. – Etan Reisner May 23 '14 at 13:44
-
The question doesn't really make sense. There's no particular appropriate way to write a makefile when you have circularly-dependent headers. – nobody May 23 '14 at 13:45
-
@AndrewMedico I just asked this question because I've got two different classes that need eachother and I have to put these two classes in two different headerfiles. – user3590783 May 23 '14 at 13:50
-
@Montaldo I've tried it and it doesn't work! – user3590783 May 23 '14 at 13:54
-
So what is the compiler throwing at you? – Montaldo May 23 '14 at 13:55
-
@Montaldo "'web' has not been declared" while compiling the first header file(web is the name of a class in the second header file) – user3590783 May 23 '14 at 14:00
-
forward declare web. class web; – Montaldo May 23 '14 at 14:01
1 Answers
Initially, just focusing on the Makefile problem:
Objects depend on source files... on all the source (and headers) files that are read during the compilation... Unless you're doing code generation, there's no makefile dependency among the source/headers used to produce one particular object.
For example, you have foo.cpp.
foo.cpp will produce foo.o
So your target is foo.o, that depends on foo.cpp.
foo.o: foo.cpp
Now, if foo.cpp includes a header bar.hpp, you can add that as a dependency (i.e. if bar.hpp changes you want foo.o to be recompiled), then you add it in the dependency list:
foo.o: foo.cpp bar.hpp
Now, if bar.hpp includes rec.hpp, we will do the same.
foo.o: foo.cpp bar.hpp rec.hpp
If rec.hpp includes again bar.hpp you doesn't really need to add it to the dependencies, because it is already there.
Note that we don't have a dependency of foo.cpp to bar.hpp or of bar.hpp to rec.hpp, because the generation of the foo.o target involves a single step that reads all three files.
At the C/C++ preprocessor level, multiple inclusions are prevented by the include guards (e.g. #ifndef XXX #define XXX .... #endif) that you should have on every header file.
Now this renders a circular inclusion a no-op... probably making your compilation to fail (a difficult to spot problem) because one of the definitions will not be where you expect it to be.
How do you manage a circular type reference depends on the nature of the reference. In many cases you can get away (and you should) with forward declaration of one of the types. In other cases you can move the references to the implementation, removing the circular dependency.

- 4,972
- 16
- 27