Writing Makefiles
1. Introduction to make and Makefile
1.1 The make Tool
The <span>make</span>
tool can automatically complete compilation tasks. These tasks include:
-
If only a few source files have been modified, only recompile those specific source files;
-
If a header file is modified, recompile all source files that include that header file.
This automatic compilation greatly simplifies development work and avoids unnecessary recompilation.
1.2 Makefile
<span>make</span>
uses a file called <span>Makefile</span>
to complete and automatically maintain compilation tasks. The <span>Makefile</span>
file describes the rules for compiling and linking the entire project.
2. Basic Rules of Makefile
TARGET ...:DEPENDENCIES ...
COMMAND ...
-
The target (TARGET) is the file produced, such as an executable file or object file; the target can also be an action to perform, such as
<span>clean</span>
, also known as a phony target. -
Dependencies (DEPENDENCIES) are the list of input files used to produce the target, and a target usually depends on multiple files.
-
The command (COMMAND) is the action executed by
<span>make</span>
(the command is a shell command or a program that can be executed in the shell). Note: The first character of each command line must be a<span>TAB</span>
character. -
If one or more files in
<span>DEPENDENCIES</span>
are updated, the<span>COMMAND</span>
will execute, which is the core content of<span>Makefile</span>
.
Next, we will write a basic <span>Makefile</span>
file based on these basic rules.
.PHONY:clean
main:main.o sub.o add.o print.o
gcc -Wall -g main.o add.o sub.o print.o -o main
main.o:main.c
gcc -Wall -g -c main.c -o main.o
add.o:add.c add.h
gcc -Wall -g -c add.c -o add.o
sub.o:sub.c sub.h
gcc -Wall -g -c sub.c -o sub.o
print.o:print.c print.h
gcc -Wall -g -c print.c -o print.o
clean:
rm -f *.o main
We can see that <span>main</span>
is the final target file we want to generate, which depends on the four <span>main.o sub.o add.o print.o</span>
object files. Therefore, the command <span>gcc -Wall -g main.o add.o sub.o print.o -o main</span>
must be executed to generate the target file, but currently, these <span>.o</span>
files do not exist, so we must first generate these <span>.o</span>
files. We wrote four lines of <span>xxx.o:xxx.c</span>
to execute <span>gcc -Wall -g -c xxx.c -o xxx.o</span>
, which will generate the dependencies for the target file.
The <span>clean</span>
is a phony target because it has no dependencies. We just want to delete the <span>.o</span>
files by using <span>make clean</span>
, but we usually specify the statement <span>.PHONY:clean</span>
to explicitly indicate that <span>clean</span>
is a phony target, to prevent having a file named <span>clean</span>
in the current directory. Thus, a simple <span>Makefile</span>
file is written.
3. Makefile Automatic Variables
Although the above can complete the compilation, it is clearly very cumbersome. Next, we will introduce the automatic variables of <span>Makefile</span>
.
Option Name | Function |
---|---|
$@ | The name of the target file of the rule |
$< | The name of the first dependency file of the rule |
$^ | The list of all dependency files of the rule |
We use these automatic variables to try to rewrite the previous <span>Makefile</span>
.PHONY:clean
OBJ=main.o sub.o add.o print.o
main:$(OBJ)
gcc -Wall -g $^ -o $@
main.o:main.c
gcc -Wall -g -c $< -o $@
add.o:add.c add.h
gcc -Wall -g -c $< -o $@
sub.o:sub.c sub.h
gcc -Wall -g -c $< -o $@
print.o:print.c print.h
gcc -Wall -g -c $< -o $@
clean:
rm -f *.o main
We defined a variable called <span>OBJ</span>
, which is our list of dependencies. We then used automatic variables to replace the corresponding files, as shown above.
However, we need to generate <span>.o</span>
files from these <span>.c</span>
files, which is still very cumbersome, so we will introduce some additional rules.
-
Pattern rules
-
<span>%.o:%.c</span>
-
Suffix rules
-
<span>.c:.o</span>
Let’s use these two rules:
.PHONY:clean
CC = gcc
CFLAGS = -Wall -g
OBJ = main.o sub.o add.o print.o
main:$(OBJ)
$(CC) $(CFLAGS) $^ -o $@
#%.o:%.c
.c.o:
$(CC) $(CFLAGS) -c $< -o $@
clean:
rm -f *.o main
By using these two rules, all <span>.c</span>
files will generate corresponding <span>.o</span>
files, making the <span>Makefile</span>
much more concise.
4. Common Built-in Functions in make
-
Function call
-
<span>$(function arguments)</span>
-
$(wildcard PATTERN)
-
Files matching the pattern in the current directory
-
For example: src=$(wildcard *.c)
-
$(patsubst PATTERN,REPLACEMENT,TEXT)
-
Pattern replacement function
-
For example: $(patsubst %.c, %.o, $src)
-
Equivalent to $(src:.c=.o)
-
shell function
-
Execute shell commands
-
For example: $(shell ls -d */)
RSS feed for Linux Community: https://www.linuxidc.com/rssFeed.aspxPermanent update link for this article: https://www.linuxidc.com/Linux/2018-01/150580.htm