The make command under Linux is one of the most frequently used commands by system administrators and programmers. Administrators use it to compile and install many open source tools through the command line, and programmers use it to manage their large and complex project compilation problems. In this article, we will use some examples to discuss the working mechanism behind the make command.
How make works
For those who don’t know the mechanism behind it, the make command receives the target like a command-line argument. These targets are usually stored in a special file named “makefile”, which also contains operations corresponding to the target. For more information, read the series on how makefiles work.
When the make command is executed for the first time, it scans the makefile for the target and its dependencies. If these dependencies are themselves targets, continue to scan makefiles for these dependencies to establish their dependencies, and then compile them. Once the primary dependency is compiled, then the primary target is compiled (this is passed in through the make command).
Now, if you modify a source file, and you execute the make command again, it will only compile the target file related to the source file, so compiling the final executable file saves a lot of time.
Make command instance
Here is the test environment used in this article:
OS —— Ubunut 13.04 Shell —— Bash 4.2.45 Application —— GNU Make 3.81
The following is the content of the project:
$ ls anotherTest.c Makefile test.c test.h
Here’s what makefile does:
all: test test: test.o anotherTest.o gcc -Wall test.o anotherTest.o -o test test.o: test.c gcc -c -Wall test.c anotherTest.o: anotherTest.c gcc -c -Wall anotherTest.c clean: rm -rf *.o test
Now let’s look at some examples of the make command application under Linux:
1. A simple example
To compile the whole project, you can simply use make or bring the target all after the make command.
$ make gcc -c -Wall test.c gcc -c -Wall anotherTest.c gcc -Wall test.o anotherTest.o -o test
You can see the first dependency created by the make command and the actual target.
If you check the contents of the directory again, there are more. O files and execution files:
$ ls anotherTest.c anotherTest.o Makefile test test.c test.h test.o
Now, suppose you make some changes to the test. C file, and reuse make to compile the project:
$ make gcc -c -Wall test.c gcc -Wall test.o anotherTest.o -o test
You can see that only test. O is recompiled, but the other test. O is not.
Now clean up all the target files and executable files test, you can use the target clean:
$ make clean rm -rf *.o test $ ls anotherTest.c Makefile test.c test.h
You can see that all the. O files and the execution file test have been deleted.
2. Through the – B option, all targets are always re established.
So far, you may notice that the make command does not compile files that have not changed since the last compilation, but if you want to override the default behavior of make, you can use the – B option.
Here is an example:
$ make make: Nothing to be done for `all’. $ make -B gcc -c -Wall test.c gcc -c -Wall anotherTest.c gcc -Wall test.o anotherTest.o -o test
You can see that although the make command does not compile any files, make – B forces all the target files to be compiled as well as the final execution files.
3. Use the – D option to print debugging information
Use the – D option if you want to know what the make actually does when it executes.
Here is an example:
$ make -d | more GNU Make 3.81 Copyright (C) 2006 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. This program built for x86_64-pc-linux-gnu Reading makefiles… Reading makefile `Makefile’… Updating makefiles…. Considering target file `Makefile’. Looking for an implicit rule for `Makefile’. Trying pattern rule with stem `Makefile’. Trying implicit prerequisite `Makefile.o’. Trying pattern rule with stem `Makefile’. Trying implicit prerequisite `Makefile.c’. Trying pattern rule with stem `Makefile’. Trying implicit prerequisite `Makefile.cc’. Trying pattern rule with stem `Makefile’. Trying implicit prerequisite `Makefile.C’. Trying pattern rule with stem `Makefile’. Trying implicit prerequisite `Makefile.cpp’. Trying pattern rule with stem `Makefile’. --More--
This is a long output. You can see that I used the more command to display the output page by page.
4. Use the – C option to change the directory
You can provide different directory paths for the make command. You will switch directories before looking for makefiles.
This is a directory. Suppose you are in the current directory:
$ ls file file2 frnd frnd1.cpp log1.txt log3.txt log5.txt file1 file name with spaces frnd1 frnd.cpp log2.txt log4.txt
But the makefile file of the make command you want to run is saved in the directory.. / make dir /. You can do this:
$ make -C ../make-dir/ make: Entering directory `/home/himanshu/practice/make-dir’ make: Nothing to be done for `all’. make: Leaving directory `/home/himanshu/practice/make-dir
You can see that the make command first cuts to a specific directory, executes there, and then switches back.
5. Use the – f option to treat other files as makefiles
If you want to rename a Makefile, such as my “makefile” or any other name, we want make to treat it as a makefile. You can use the – f option.
make -f my_makefile
In this way, the make command chooses to scan my “makefile instead of makefile.