Reputation: 440
I was looking at this flow diagram to understand how makefiles really operate but I'm still struggling to 100% understand what's going on.
I have a main.cpp file that calls upon some function that is defined in function.h and function.cpp. Then, I'm given the makefile:
main: main.cpp function.o
g++ main.cpp function.o -o main
mainAssembly: main.cpp
g++ -S main.cpp
function.o: function.cpp
g++ -c function.cpp
clean:
rm -f *.o *.S main
linkerError: main.cpp function.o
g++ main.cpp function.o -o main
What's going on? From what I understand so far is that we are compiling function.cpp, which turns into an object file? Why is this necessary?
I don't know what the mainAssembly
part is really doing. I tried reading the g++ flags but I still have trouble understand what this is. Is this just compiling main.cpp with the headers? Shouldn't we also convert main into an object file as well?
I guess main
is simply linking everything together into an exe called main? And I'm completely lost on what clean
and linkerError
are trying to do. Can someone help me understand what is going on?
Upvotes: 1
Views: 258
Reputation: 211580
That flowchart confuses more than it explains as it seems needlessly complicated. Each step is actually quite simple in isolation, and there's no point in jamming them all into one chart.
Remember a Makefile
simply establishes a dependency chain, an order of operations which it tries to follow, where the file on the left is dependent on the files on the right.
Here's your first part where function.o
is the product of function.cpp
:
function.o: function.cpp
g++ -c function.cpp
If function.cpp
changes, then the .o
file must be rebuilt. This is perhaps incomplete if function.h
exists, as function.cpp
might #include
it, so the correct definition is probably:
function.o: function.cpp function.h
g++ -c function.cpp
Now if you're wondering why you'd build a single .cpp
into a single .o
file, consider programs at a much larger scale. You don't want to recompile every source file every time you change anything, you only want to compile the things that are directly impacted by your changes. Editing function.cpp
should only impact function.o
, and not main.o
as that's unrelated. However, changing function.h
might impact main.o
because of a reference in main.cpp
. It depends on how things are referenced with #include
.
This part is a little odd:
mainAssembly: main.cpp
g++ -S main.cpp
That just dumps out the compiled assembly code for main.cpp
. This is an optional step and isn't necessary for building the final executable.
This part ham-fistedly assembles the two parts:
main: main.cpp function.o
g++ main.cpp function.o -o main
I say that because normally you'd compile all .cpp
files to .o
and then link the .o
files together with your libstdc++
library and any other shared libraries you're using with a tool like ld
, the linker. The final step in any typical compilation is linking to produce a binary executable or library, though g++
will silently do this for you when directed to, like here.
I think there's much better examples to work from than what you have here. This file is just full of confusion.
Upvotes: 2