...making Linux just a little more fun!
By Tedi Heriyanto
Imagine you are developing a program called foo, which consists of five headers, that is 1.h, 2.h, 3.h, 4.h, and 5.h, six C-language source code files named 1.cpp to 5.cpp, and a main.cpp file (Remember: we do not recommend to use such file naming scheme in the real life).
Suppose you find a bug in 2.cpp and has fix it. In order to get a new foo program, you have to recompile all files, header and source code, even though you just change one file. This is not a fun job, waiting for the computer to finished its process compiling your program. Particularly if you don't have fast computer.
What can you do then? Is there any solution for this problem ?
Please do not worry my friends. That kind of problem has already been experienced by our fellow computer hackers years ago. To tackle this problem, they have developed a program called make. Instead of build all of the source codes, this program will only build source code that has been changed. If you change file 2.cpp, then make will only build it. Isn't it fun?
The followings are several other reasons why we need make  :
Although make is very useful, it cannot do its job without the instructions given by us, the programmer. make instructions is stored in a text file. This file is usually called makefile and contains commands that must be processed by make.
This file is normally named makefile or Makefile. As a convention, GNU programs named their makefile, Makefile, because it is easy to see (if you do "ls" then this file is usually always on the top of the list). If you give it another name, just make sure you include option -f to make command in order to let it know that you use it.
For example, if we have a makefile named bejo, then the command we use to instruct make to process that file is :
make -f bejo
A makefile consists of target, dependencies and rules section. Dependecies are things or source code needed to make a target; target is usually an executable or object file name. Rules are commands needed to make the target.
Following is a simple description of a makefile :
target: dependencies command command ...
The following is a simple makefile example (line numbers added for the article):
1 client: conn.o 2 g++ client.cpp conn.o -o client 3 conn.o: conn.cpp conn.h 4 g++ -c conn.cpp -o conn.o
In the makefile above, dependencies is line contained client: conn.o, while rules is line contained g++ client.cpp conn.o -o client. Note that every rule line begins with a tab, not spaces. Forgetting to insert a tab at the beginning of the rule line is the most common mistakes in constructing makefiles. Fortunately, this kind of error is very easy to be spotted, because make program will complain about it.
Detail description of the makefile depicted above are as follows :
To give a comment in makefile, merely put '#' in the first column of each line to be commented.
Below is an example makefile that has already been commented :
# Create executable file "client" 1 client: conn.o 2 g++ client.cpp conn.o -o client # Create object file "conn.o" 3 conn.o: conn.cpp conn.h 4 g++ -c conn.cpp -o conn.o
A phony target is a fake filename. It is just a name for commands that will be executed when you give an explicit request. There are two reasons for using phony target : to avoid conflicts with a file with the same name, and to enhance the makefile performance.
If you write a rule whose command will not create a target file, those commands will be executed every time the target is remade. For example:
clean: rm *.o temp
Because the command rm will not create a file named clean, that file will never exist. Command rm will always be executed every time you called make clean, because make assume that the clean file is always new.
The above target will stop working if a file named clean exists in the current directory. Because it does not require dependencies, file clean will be considered up-to-date, and the command 'rm *.o temp' will not be executed. To resolve this problem, you can explicitly declare a target as phony, using special target command .PHONY. For example :
.PHONY : clean
In the makefile above, if we give instruction make clean from the command-line, the command 'rm *.o temp' will always be run, whether or not a file named clean exists in the current directory.
As a convention, a variable name is given in uppercase, for example :
To get a varible's value, put the symbol $ before the variable's name, such as :
In makefile, there are two kinds of variables, recursively expanded variable and simply expanded variable.
In the recursively expanded variable, make will continue expanding that variable until it cannot be expanded anymore, for example :
SRCDIR variable will be expanded, first by expanding TOPDIR variable. The final result is /home/tedi/project/src
But, recursively expanded variable will not be suitable for the following command :
CC = gcc -o CC = $(CC) -O2
Using a recursively expanded variable, those command will go to endless loop. To overcome this problem, we use a simply expanded variable :
CC := gcc -o CC += $(CC) -O2The ':=' symbol creates the variable CC and given its value "gcc -o". The '+=' symbol appends "-O2" to CC's value.
I hope this short tutorial will give you enough knowledge to create makefile. Until then, happy hacking.