Introduction to Writing Makefiles

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 $&lt; -o $@
add.o:add.c add.h
    gcc -Wall -g -c $&lt; -o $@
sub.o:sub.c sub.h
    gcc -Wall -g -c $&lt; -o $@
print.o:print.c print.h
    gcc -Wall -g -c $&lt; -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 $&lt; -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

Leave a Comment