Published on September 16th, 2012 | by Vaibhav2
Makefile is the file created by the use of the make utility, which comes preloaded in most of the Linux distros. It forms a core part of the operating system by helping different packages to compile and install, on the system. By its use we can automatically build programs and run them from the Terminal.
I will be concentrating more on the practical use than the other information about Make, but if you are interested you can read more about it here.
Makefile is a special type of shell program implementing the simple commands, so you can even put in commands like ‘ls’ (we won’t be using it though) in the make file. The only difference is that we don’t have to make the Makefile executable. The GNU make utility, automatically looks up in the present working directory for the files named as GNUmakefile, makefile or Makefile (yes, the last two are different files in Linux, it being case-sensitive).
Syntax and usage:
Firstly we will see how to write a Makefile. Writing a Makefile involves simple rules. On the first line specify the target to be built. Put a colon (:) and specify the dependencies for the target, on the same line separated by a. On the following line pressonce, and specify the rule to make the target.
For example consider a C program, named mycfile.c
Now you compile a C program through terminal as:
An output file can be specified by using the “-o” option followed by the output filename (no extension necessary!) as
cc mycfile.c -o output
(If it is not specified, by default the output file is named as a.out in the current folder.)
We can also partially compile a program (to create the object file: ‘.o’ file) by specifying the “-c” option as
cc -c mycfile.c
If no output file is specified, in this case the output file has the same filename (here mycfile.o) but with the .o extension, and yes we can specify a output file here too as:
cc -c mycfile.c -o partial.o
This will generate the output and put it in the file named as partial.o
So if we don’t want to use the partial compiling method, and want to write the Makefile, it will be like:
cc mycfile.c -o output
And to run the Makefile, just type
The command specified on the second line i.e. cc mycfile.c -o output is run and the output file output is generated. Note that the present working directory must be the same in which you have written the Makefile.
What happens at the back, is that the utility searches for the output file to be generated in the first line (here output), and looks up for its dependencies (here mycfile.c). As mycfile.c is already available, it goes on the second line to look for the rule specified to create output, and the output file is generated.
Now with these basics, let us try to explore a few more options in the Makefile, like adding a option to remove the extra files once we complete our work, or to run the output file.
Let us now have a look on how to write the Makefile for multiple files that are to compiled together.
Suppose I have written a program for an infix calculator, which takes input from the user, processes it and gives back the output. To do this work I have three functions, one for taking continuous inputs, one for processing it, and the last for displaying the output. Suppose that they are written in separate files with the names ‘input.c’, ‘process.c’ and ‘main.c’ (containing the main() function). Also suppose that we have a header file named ‘header.h’ containing the function prototypes, and some other # directives.
We now write the Makefile (considering the partial compilation also) as:
output: main.o input.o process.o
cc main.o input.o process.o -o output
main.o: main.c header.h
cc -c main.c
input.o: input.c header.h
cc -c input.c
process.o: process.c header.h
cc -c process.c
rm *.o output
Now in this single Makefile, three options are available which are:
output: It is the default case which is selected when we run make.
install: It is the second case to run the output file. This is usually called as installing. We access this by typing:
clean: This option removes all the generated files, i.e. here the ‘.o’ object files and the final executable file ‘output’. We do this by typing:
Use of Makefile:
As you might have observed, it simplifies the lengthy procedure of typing each and every command repeatedly. Also the make utility checks the last modified time of the dependencies, and previously generated files (like in this case the ‘.o’ files). It skips those commands which do not need to be run, i.e. they are already up-to-date, i.e. the make utility check recursively for the modifications in its dependencies and then builds only the changed files, like, I built the project and then changed the main.c file, only. So only the main.c needs to be built, which it does automatically. See it here:
Try this out: Try to implement an additional option in the Makefile, to check whether the built correctly before using install, and let me know!