Writing a basic makefile
- Q: Why should we split our program instead of
placing all the code in one file?
A: If/When our program becomes very large, or it contains
the code for some entirely different sets of functionalities,
it may become cumbersome for us to edit/read the lengthy
code.
Also, if we make a small change and then try to recompile,
the whole giant file will get compiled again and may
consume quite some amount of time.
Dividing our source code into separate files makes it
manageable since we'll be knowing which file do we have
to edit to get the `x` effect. Other files will stay as
they are.
Less time will be spent in compilation since only those
files will be compiled which have the recent uncompiled
changes.
- Q: How to compile the source files separately?
A: Suppose our main directory is `makeFileDemo`.
It contains sub directories namely `header` and `source`.
The source files we have are `sourceA.cpp`, `sourceB.cpp`,
and `main.cpp` stored in the sub directory namely `source`.
The header file we have is `headerAB.h` stored in the sub
directory namely `header`.
Code:anisha@linux-y3pi:~/makefilesDemo> ls -R .: header source ./header: headerAB.h ./source: main.cpp sourceA.cpp sourceB.cpp
directory `source` (assuming we are currently
in the main directory makeFileDemo) to get a
final executable file is:
Code:anisha@linux-dopx:~/makeFileDemo> g++ source/x.cpp source/y.cpp source/main.cpp anisha@linux-dopx:~/makeFileDemo> ls a.out header source
It is a possibility that we've just modified one source file out of for example existing ten files, so logically we shouldn't be bothered to re-compile the other nine source files every time we modify just one of them.
To avoid recompiling the other n-1 source files every time we modify just one of the n files, we can create object files of all the n files and then simply link them together.
Code:anisha@linux-dopx:~/makeFileDemo> g++ -c source/x.cpp anisha@linux-dopx:~/makeFileDemo> g++ -c source/y.cpp anisha@linux-dopx:~/makeFileDemo> g++ -c source/main.cpp anisha@linux-dopx:~/makeFileDemo> ls header main.o source x.o y.o
Code:anisha@linux-dopx:~/makeFileDemo> g++ main.o x.o y.o -o executable anisha@linux-dopx:~/makeFileDemo> ls executable header main.o source x.o y.o
To see the effect of the edit we made to the y.cpp, we have to recreate the y.cpp's object file.
Code:anisha@linux-dopx:~/makeFileDemo> g++ -c source/y.cpp
Code:anisha@linux-dopx:~/makeFileDemo> g++ main.o x.o y.o -o executable
- Why do we need a Makefile?
We need a Makefile if we don't want to bother ourselves by rerunning and retyping all the above shown commands each and every time we modify a tiny piece of code. Also since simply recompiling each and every file may consume a heavy amount of time depending on the code.
Makefile contains the dependency graph of the desired files of a particular project. The program make checks the modification times of the files, and whenever a file gets edited more recently
than something that depends "on" it, it runs the compiler accordingly.
For example, if you edit y.c, it becomes "newer" than its previously created object file y.o.
In this case, make runs:
Code:g++ -c y.cpp
Code:g++ main.o x.o y.o -o executable
- How to write a Makefile?
Target is considered to be a file which will be created or updated when any of its source files are modified.
Example: when a source file y.cpp is modified we need to recompile it so that the changes get reflected in its corresponding object file. So, here the target is the object file of the source
file y.cpp.
Target syntax:
Code:y.o : y.cpp xy.h
Makefile syntax:
- We need to combine the all the individual object files of all the individual source files and produce one target object file.
Specification of the final target and the corresponding command need to be the first statements in the Makefile.
In the below code finalObjectFile is the name of our object file which is the merger of all other individual object files.
Code:finalObjectFile: x.o main.o y.o
- We need to specify the usual compiler command which will take all the individual object files of all the individual source files and produce one target object file. The commands need to be started
with a TAB.
Code:g++ x.o main.o y.o -o finalObjectFile
- We need to specify the target object file for the individual source files.
We first specify the target and then its dependencies.
Code:x.o: source/x.cpp header/xy.h g++ -c source/x.cpp
Code:y.o: header/xy.h source/y.cpp g++ -c source/y.cpp main.o: header/x.h source/main.cpp g++ -c source/main.cpp
Total Comments 0