When you install any software from source, you typically execute commands like — “make”, “make install”, “make clean”, etc. Have you wondered what all these make commands are really making? Sure, we know that it is trying to compile and install the software. But, why make? What does it really do?
For compiling a single C program, cc command is very helpful. For compiling multiple C programs, Make utility is very helpful.
Also, C programmers and sysadmins will find it helpful to automate the compilation related tasks using make utility. In this article, let us review how to use make command.
1. Create the Makefile for a Simple Compilation
Let us assume that you have the sample C program file called helloworld.c. Using cc command, typically you would compile it as shown below.
$ cc -o helloworld helloworld.c
While you don’t need to use make for compiling single a program, the following example will give you an idea on how to use make. Create a makefile as shown below.
$ vim makefile helloworld : helloworld.c cc -o helloworld helloworld.c
Execute make to create the helloworld executable as shown below.
$ make helloworld (or) $ make
Since makefile contains only one target “helloworld”, you can also call make command without any argument as shown above.”make”.
Please ensure that both makefile and the source code are present in the same directory, otherwise specify the respective path of source files in makefile.
By default, make command expects the make filename to be either Makefile or makefile. If the make filename is different than any of these two, you should specify that to the make command using -f option as shown below.
$ make -f sample.txt
For those who are new to C, read C Hello World Program article.
2. Create the Makefile to Compile More than One File
For the multiple file compilation, let us use three files — getname.c, getaccno.c and main.c.
Based on these three *.c files, let us create an executable called “getinto”.
Using the cc command, you would typically do the compilation as shown below.
$ cc -o getinfo main.c getname.c getaccno.c header.h
You can also compile the individual *.c files as shown below and finally create the “getinfo” executable as shown below.
$ cc -c getname.c $ cc -c getaccno.c $ cc -c main.c $ cc -o getinfo main.o getname.o getaccno.o header.h
Using our friendly make utility, you can effectively do this as shown below.
$ vim makefile getinfo:getname.o getaccno.o main.o header.h cc -o getinfo getname.o getaccno.o main.o header.h main.o:main.c cc -c main.c getaccno.o:getaccno.c cc -c getaccno.c getname.o:getname.c cc -c getname.c
Finally, execute the make command as shown below.
$ make getinfo
Note: Everytime make command gets invoked, it checks and compiles only the file that are modified. This is huge for C programmers, where they typically have multiple C file, and compiling the whole project several times during development phase.
You can also use gdb to debug C programs.
3. Add Target for Cleanup Process
Inside the makefile (or Makefile), you can also add target to cleanup the object files, as shown below.
clean : rm getname.o getaccno.o main.o
Now you can clean the object files from the current directory as shown below.
$ make clean
Note: Instead of specifying the individual *.o file in the rm command, you can also give rm *.o.
You can also create a C archive files (*.a) using ar command.
4. Variable Handling in Makefile
Inside makefile (or Makefile) you can use variables, which can be used throughout the makefile. An example usage is shown below, where $obj contains all the object file names.
$ vim makefile obj= getname.o getaccno.o main.o getinfo: $(obj) header.h cc -o getinfo getname.o getaccno.o main.o header.h main.o:main.c cc -c main.c getaccno.o:getaccno.c cc -c getaccno.c getname.o:getname.c cc -c getname.c clean: rm getinfo $(obj)
5. Simplifying the Makefile Further
Make utility implicitly invokes the cc -c command to generate .o files for the corresponding .c file. We really don’t need to specify the “cc -c” inside the makefile. So, we can rewrite the makefile to reflect this implicit rule as shown below.
$ vim makefile obj= getname.o getaccno.o main.o getinfo: $(obj) header.h cc -o getinfo getname.o getaccno.o main.o header.h main.o: getaccno.o: getname.o: clean: rm getinfo $(obj)
6. Insert Debug Messages inside Makefile
When you are compiling a big project, you might want to displays some friendly message. Make utility can print messages to the standard output, which might help you to debug any potential issues in the make process. Use the @echo statement throughout your makefile as shown below to display custom messages.
$ vim makefile obj= getname.o getaccno.o main.o getinfo: $(obj) header.h cc -o getinfo getname.o getaccno.o main.o header.h @echo "make complete." main.o: getaccno.o: getname.o: clean: rm getinfo $(obj) @echo "getinfo, $(obj) files are removed."
There you have it. Make is not a mystery anymore. If you liked this article, please bookmark it in delicious, or stumble it.