All Posts Makefile Featured

Published on September 16th, 2012 | by Vaibhav

2

Makefile Simplified!

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:

cc mycfile.c

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:

output: mycfile.c

       cc mycfile.c -o output

And to run the Makefile, just type

make

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

install: output

       ./output

clean:

       rm *.o output

Sample Makefile

Now in this single Makefile, three options are available which are:

  1. output: It is the default case which is selected when we run make.

  2. install: It is the second case to run the output file. This is usually called as installing. We access this by typing:

    make install

  3. 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:

    make clean

 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!

Tags: , , ,


About the Author

Vaibhav is an free software enthusiast and likes to try out new things in the free software world. When he is not working on a computer, he likes to play games like chess and badminton.



2 Responses to Makefile Simplified!

  1. free4freedom says:

    Great work Vaibhav !!
    A couple of doubts :
    1.When I changed only main.c & did “make” , still everything got compiled. So I don’t know why that happened.

    2.Suppose I want my output to be seen everytime I compile, then what changes should be done? Right now, I have to first say “make” & then say “make install” to see my o/p , I want both of these to happen in single command only.

    3.Didn’t get u r home-work at the end !! Can u please elaborate ?

    • Vaibhav says:

      If you might have observed, then the dependency for the make install command is the output file. So if you just run the make install command, then the dependency, i.e. output will be generated which is the same as using make!
      The homework is just to implement a make check, to check whether the output files (output and ‘.o’ files) are present or not!
      About the first question I am not sure what happened at your end, but as I have shown it works in the way mentioned…

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Back to Top ↑