What is Makefile in Linux? How does it work?

  • 2020-11-26 19:07:36
  • OfStack

Use this handy tool to run and compile your programs more efficiently
makefile is used for automatic compilation and linking. A project is made up of many files, and every change to a file causes the project to be relinked - but not all files need to be recompiled. makefile can record the information of the files and decide which files need to be recompiled when linking!

The make tool is often used when you need to run or update a task after one of the source files has changed. The make tool needs to read an Makefile (or makefile) file that defines a series of tasks that need to be performed. You can use make to compile source code into executable programs. Most open source projects use make to compile the final 2-base file, then use the make install command to perform the installation.
This article will show you how to use make and Makefile with some basic and advanced examples. Before you begin, make sure you have make installed on your system.

Based on the sample
Again, start by printing "Hello World". First, create a directory named myproject and create a new Makefile file under the directory. The file contents are as follows:


say_hello:
echo "Hello World"

When make is executed in the myproject directory, it will have the following output:


$ make
echo "Hello World"
Hello World

In the above example, "say_hello" is similar to function names in other programming languages. This is called the goal (target). After the target is a preset condition or dependency. For the sake of simplicity, we do not define the preconditions in this example. The echo 'Hello World' command is called a step (recipe). These steps are based on preset conditions to achieve the goal. Goals, preconditions, and steps together constitute a rule.

In conclusion 1, the syntax of a typical rule is as follows:

Objective: Preset conditions
< TAB > steps

As an example, the target could be a base 2 file based on a preset condition (source code). On the other hand, a preset condition can also be a target that depends on other preset conditions.


final_target: sub_target final_target.c
Recipe_to_create_final_target
sub_target: sub_target.c
Recipe_to_create_sub_target

The target does not have to be a file, it can just be the name of the step, as in our example. We call them "pseudo-targets."

Back in the example above, when make is executed, the entire instruction echo "Hello World" is displayed before the actual execution results. If you do not want the instruction itself to be printed, you need to add @ before echo


say_hello:
@echo "Hello World"

Rerun make will have only the following output:


$ make
Hello World

Next add the following dummy targets in Makefile: generate and clean:


say_hello:
@echo "Hello World"
generate:
@echo "Creating empty text files..."
touch file-{1..10}.txt
clean:
@echo "Cleaning up..."
rm *.txt

Then when we run make, only the say_hello target is executed. This is because the first target in Makefile is the default target. Usually the default target is called, which is why you see all appearing as the first target in most projects. all is responsible for calling it his target. We can override the default behavior with the special pseudo-target.DEFAULT_ES82en.

Add.es86EN_ES87en at the beginning of the Makefile file:

.DEFAULT_GOAL := generate

make will make generate the default target:


$ make
Creating empty text files...
touch file-{1..10}.txt

As the name implies, the.DEFAULT_GOAL pseudo-target can only define 1 target. This is why many Makefile include the target all so that multiple targets can be invoked.
Delete.es103EN_ES104en below and add all target:


all: say_hello generate
say_hello:
@echo "Hello World"
generate:
@echo "Creating empty text files..."
touch file-{1..10}.txt
clean:
@echo "Cleaning up..."
rm *.txt

Before running, we add one more special dummy target. .PHONY is used to define that these are not the targets of the files. make calls the steps under these pseudo-targets by default without checking for the existence of the file name or the last modified date. The complete Makefile is as follows:


.PHONY: all say_hello generate clean
all: say_hello generate
say_hello:
@echo "Hello World"
generate:
@echo "Creating empty text files..."
touch file-{1..10}.txt
clean:
@echo "Cleaning up..."
rm *.txt

The make command calls say_hello and generate:


$ make
Hello World
Creating empty text files...
touch file-{1..10}.txt

clean should not be placed in all or in the first target. clean should be called manually when it needs to be cleaned up by make clean


$ make
echo "Hello World"
Hello World
0

Now that you have a basic understanding of Makefile, let's look at some more advanced examples.

Advanced sample
variable
In previous instances, most goals and preconditions were fixed, but in real projects, they were usually replaced by variables and patterns.

The simplest way to define a variable is to use the = operator. For example, assign the command gcc to the variable CC:


$ make
echo "Hello World"
Hello World
1

This is called a recursive extension variable and is used in the following rules:


$ make
echo "Hello World"
Hello World
2

As you might expect, these steps will be expanded when passed to the terminal as follows:

gcc hello.c -o hello

Both ${CC} and $(CC) can refer to gcc. But if a variable tries to assign itself to itself, it will cause an endless loop. Let's verify 1:


CC = gcc
CC = ${CC}
all:
@echo ${CC}

Running make at this point results in:


$ make
echo "Hello World"
Hello World
4

To avoid this, use the := operator (this is called a simple extension variable). The following code will not cause the above problem:


$ make
echo "Hello World"
Hello World
5

Patterns and functions
The following Makefile USES variables, patterns, and functions to compile all of the C code. Let's break it down line by line:


$ make
echo "Hello World"
Hello World
6

Lines that begin with # are comments
.PHONY = all clean line defines the all and clean pseudo-targets.
The variable LINKERFLAG defines the parameters required by the gcc command in the step.
SRCS := $(wildcard *.c) : $(wildcard pattern) is a function associated with the file name. In this example, all files with the ".c "suffix are stored in the SRCS variable.
BINS := $(SRCS:%.c=%) : This is called substitution citation. In this example, if the value of SRCS is' foo. c bar. c', then the value of BINS is 'foo bar'.
all: ${BINS} line: dummy target all calls all values in the ${BINS} variable as subtargets.
Rules:


$ make
echo "Hello World"
Hello World
7

Here is an example to understand this rule. Assume that foo is one value in the variable ${BINS}. % matches foo (% matches any 1 target). Here's what the rule expands to:


foo: foo.o
@echo "Checking.."
gcc -lm foo.o -o foo

As shown above, % is replaced by foo. $ < Replaced by foo.o. $ < Used to match the preset condition, $@ matches the target. For each value in ${BINS}, this rule is called 1 time.
Rules:


$ make
echo "Hello World"
Hello World
9

Each of the preconditions in the previous rule is treated as a target in this rule. Here's what it expands to:


foo.o: foo.c
@echo "Creating object.."
gcc -c foo.c

Finally, in the clean target, all base 2 files and compiled files will be deleted.
Here is the rewritten Makefile, which should be placed in a directory with the ES233en.c file:


# Usage:
# make # compile all binary
# make clean # remove ALL binaries and objects
.PHONY = all clean
CC = gcc # compiler to use
LINKERFLAG = -lm
SRCS := foo.c
BINS := foo
all: foo
foo: foo.o
@echo "Checking.."
gcc -lm foo.o -o foo
foo.o: foo.c
@echo "Creating object.."
gcc -c foo.c
clean:
@echo "Cleaning up..."
rm -rvf foo.o foo

These add up to one, makefile, but these features are too few to add to many other items. But the idea is to let the compiler know what other files it depends on to compile a file. When those dependent files change, the compiler automatically finds that the final build file is out of date and recompiles the module.

conclusion


Related articles: