Reputation: 1474
A lot of the examples I see regarding make files are somewhat inconsistent in regards to what files are considered dependencies of main.o
and I was wondering what is the safest and most efficient way of going about creating a makefile.
An example from https://www.tutorialspoint.com/makefile/makefile_quick_guide.htm:
hello: main.o factorial.o hello.o
$(CC) main.o factorial.o hello.o -o hello
main.o: main.cpp functions.h
$(CC) -c main.cpp
factorial.o: factorial.cpp functions.h
$(CC) -c factorial.cpp
hello.o: hello.cpp functions.h
$(CC) -c hello.cpp
As you can see, the header file functions.h
is a dependency of main.o
.
An example from my textbook:
myprog.exe : main.o threeintsfcts.o
g++ main.o threeintsfcts.o -o myprog.exe
main.o : main.cpp threeintsfcts.cpp threeintsfcts.h
g++ -Wall -c main.cpp
threeintsfcts.o : threeintsfcts.cpp threeintsfcts.h
g++ -Wall -c threeintsfcts.cpp
clean :
rm *.o myprog.exe
As you can see, the header file .h
and it's .cpp
are dependencies of main.o
.
I've also seen another example (from https://www.youtube.com/watch?v=_r7i5X0rXJk) where the only dependency of main.o
is main.cpp
.
Something like:
myprog.exe : main.o threeintsfcts.o
g++ main.o threeintsfcts.o -o myprog.exe
main.o : main.cpp
g++ -Wall -c main.cpp
threeintsfcts.o : threeintsfcts.cpp threeintsfcts.h
g++ -Wall -c threeintsfcts.cpp
clean :
rm *.o myprog.exe
When a main.cpp
includes a .h
file, should both the .h
and its respective .cpp
be included as dependencies?
One of the thoughts that came into my head was this: why should any .h
file be included as a dependency anyways? Wouldn't a change in any .h
file register as a change in the respective .cpp
file since the contents of the .h
are just going to be copy and pasted into the respective .cpp
file through #include?
I am also unsure of whether to have the respective .cpp
as a dependency.
(ex. main.o : main.cpp threeintsfcts.cpp threeintsfcts.h
).
I think doing so would go against one of the main benefits of makefiles which is the efficiency of modular compilation. (You would have to recompile the main
whenever threeintsfcts.cpp
changes).
However, it might make sense to do so in case threeintsfcts.cpp
changes the name of one of its functions used in main
and you forget to change it in main
.
Upvotes: 0
Views: 823
Reputation: 99094
The example from your textbook:
main.o : main.cpp threeintsfcts.cpp threeintsfcts.h
g++ -Wall -c main.cpp
is wrong. The purpose of separating source code into two files is so that they can be compiled independently; if one depends on the other, they have been separated incorrectly.
"...Why should any .h file be included as a dependency anyways? Wouldn't a change in any .h file register as a change in the respective .cpp file since the contents of the .h are just going to be copy and pasted into the respective .cpp file through #include?"
If threeintsfcts.h
is the only file that has been changed, then main.cpp
has not been changed. Make is not smart enough to parse main.cpp
and deduce that threeintsfcts.h
ought to be a prerequisite of main.o
. (There are ways to get Make to do that, but you must master the basics first.)
...In case threeintsfcts.cpp changes the name of one of its functions used in main and you forget to change it in main.
In that case you will not be able to build the executable; Make can (and will) inform you of the problem, but not fix it, no matter how you arrange the prerequisite lists.
Upvotes: 1
Reputation: 22152
Each object file target needs to depend on its source file, obviously, but also all header files that it is including. The make
program itself does not parse the source files, so it doesn't know what headers a source file includes. If one of the header files is missing and modified, the source file will not be automatically recompiled by make
.
Because tracking the header file dependencies manually is cumbersome and error-prone, there are tools to automate it, see e.g. this question.
Other source files should however not be dependencies, because one source file should not be including another, so there cannot be any dependency that isn't resolved in the later linker step in the main executable target.
Any change in one source file that would affect a change in the compilation step of another source file would have to be through a change in the former source file's header file which is included in the later one. Therefore the header dependencies are sufficient.
Therefore I see no justification for the textbook example you posted. The first example is fine however, as long as the project size is small enough to track the dependencies manually. The third example is wrong, because it wont recompile main.cpp
if the header file changes. (Assuming threeintsfcts.h
is included in main.cpp
, which is the only thing making sense)
Upvotes: 2
Reputation: 2027
No you shouldn't have .cpp dependency to main, the whole point of Makefile is for separate compilation.
If you were to include .cpp as a dependency to main, then every time the implementation of that cpp changes main and the cpp would get recompiled which is not what we want. Rather, we only want the cpp file to get re-compiled and main stay the same.
I think that the example from your textbook is a mistake. I could be wrong, Makefiles is an old friend for me, so I want to know what others have to say on the matter.
I'm answering based on what I personally do and this is what also makes sense to me.
Upvotes: 1