makefile concise tutorial

Posted by noise on Tue, 11 Jan 2022 01:57:15 +0100

5 Makefile project management

Script file: put a series of commands in a file for batch execution

Name: makefile Makefile

One rule:

Objectives: dependencies

Command (1 table indent before the command)

Two functions:

#The wildcard function, together with wildcards, finds all the files in the folder 	. c Documents
src=$(wildcard ./*.c)	
#Put all the c. replace the suffix of the document with o
obj=$(patsubst %.c,%.o,$(src))

Three automatic variables:

The three automatic variables can only be used in the command line, not in targets and dependencies!!!

$@: represents the target file;

$<: the first clause representing dependency conditions;

$^: represents all dependency conditions;

5.1 a rule

basic principle:

1. If you want to generate a target, check whether the dependency condition in the rule exists. If it does not exist, look for whether there is a rule to generate the dependency file;

2. Check whether the target in the rule needs to be updated. First check all its dependencies. If there are updates in the dependencies, the target must be updated

1) Analyze the relationship between objectives and dependencies

2) Execute commands from bottom to top according to dependencies;

3) Determine the update according to the modification time is newer than the target;

4) If the target does not depend on any conditions, execute the corresponding command to show the update

The file directory is as follows:

daniel@daniel-Vostro-5471:~/file/OS/test/make_test/make1$ tree
.
├── add.c
├── cal.h
├── Makefile
├── sub.c
└── test.c

0 directories, 5 files

The corresponding Makefile files are as follows:

test: test.o add.o sub.o
	gcc test.o add.o sub.o -o test -I.
test.o:test.c
	gcc -c test.c -o test.o
add.o:add.c
	gcc -c add.c -o add.o
sub.o:sub.c
	gcc -c sub.c -o sub.o
#The advantage of separating each file is that when a single file is changed, other files do not need to be recompiled
#Just compile the changed file and re link it

The make command checks the makefile file and takes the first statement as the ultimate goal; Therefore, it is best to put the overall generation steps at the front;

To solve the above disadvantages, you can use the ALL command to specify the final purpose of the makefile;

ALL:a.out

5.2 two functions

Two functions commonly used in makefile:

#Find all suffixes in the current directory c file, assigned to src
src=$(wildcard ./*.c)
#All suffixes in src variables are Replace the file of c with o
#Replace the part of parameter 3 containing parameter 1 with parameter 2
obj=$(patsubst %.c,%.o,$(src))

$(src) represents the value of the function; After the above function is called, the variable

src= add.c sub.c test.c

obj=add.o sub.o test.o

With two functions, the makefile can be rewritten as follows:

#Specify the final goal
ALL:main
#Two functions are used, src variable represents the source file and obj represents the compiled file o documentation
src=$(wildcard ./*.c)	#add.c sub.c test.c
obj=$(patsubst %.c,%.o,$(src))	#add.o sub.o test.o
main:$(obj)
	gcc $(obj) -o main -I.
test.o:test.c
	gcc -c test.c -o test.o -I.
add.o:add.c
	gcc -c add.c -o add.o
sub.o:sub.c
	gcc -c sub.c -o sub.o
#If you execute the make clean command alone, the *. In the file will be deleted o file and main file deletion
#add to 	 The make clean -n option is to simulate the execution of the command, and the file to be deleted will be displayed on the command line
clean:
	rm -rf $(obj) main
clean:
	-rm -rf $(obj) a.out
#If you execute the make clean command alone, the *. In the file will be deleted o file and main file deletion
#Add the make clean -n option to simulate the execution of commands

The clean command has no dependency. The "-" before rm is used to delete nonexistent files without reporting an error;

5.3 three automatic variables

3 automatic variables:

$@: in the command of the rule, it represents the target in the rule (it can not be used in the target or dependency);

$^: in the command of the rule, it represents all the dependency conditions of the rule;

$<: in the command of the rule, it represents the first dependency condition in the rule; If the automatic variable is applied to the pattern rule, it can successively take out the dependencies in the dependency condition list and apply the pattern rule;

With three automatic variables, the above makefile can be further rewritten as,

ALL:main
src=$(wildcard ./*.c)	#add.c sub.c test.c
obj=$(patsubst %.c,%.o,$(src))	#add.o sub.o test.o
main:$(obj)
	gcc $^ -o $@ -I.
test.o:test.c
	gcc -c $< -o $@ -I.
add.o:add.c
	gcc -c $< -o $@
sub.o:sub.c
	gcc -c $< -o $@
clean:
	-rm -rf $(obj) main

5.4 mode rules

The makefile in the previous section will each c compiled into o in the process of, the commands are the same, that is:

gcc -c $< -o $@

In this way, multiple instructions can be rewritten into the following form using pattern rules:

%.o:%.c
	gcc -c $< -o $@

The above makefile can be further rewritten as:

ALL:main
src=$(wildcard ./*.c)	#add.c sub.c test.c
obj=$(patsubst %.c,%.o,$(src))	#add.o sub.o test.o
main:$(obj)
	gcc $^ -o $@ -I.
%.o:%.c
	gcc -c $< -o $@
clean:
	-rm -rf $(obj)
#If you execute the make clean command alone, the *. In the file will be deleted o file and main file deletion
#add to 	 The make clean -n option is to simulate the execution of the command

Through multiple updates, the extensible function of makefile is realized. On the basis of the original file, a multiplication module, mul c. Makefiles do not need to be rewritten,

daniel@daniel-Vostro-5471:~/file/OS/test/make_test/make3$ tree
├── add.c
├── cal.h
├── makefile
├── mul.c
├── sub.c
└── test.c
0 directories, 6 files

5.5 extension

Static mode rules:

The following statement is to the obj variable o files, generating c) documents;

$(obj):%.o:%c
	gcc -c $< -o $@

Generate pseudo target:

Example: add a clean file in the above folder, that is, use the command touch clean. The file directory is as follows:

daniel@daniel-Vostro-5471:~/file/OS/test/make_test/make3$ tree
.
├── add.c
├── cal.h
├── clean
├── makefile
├── mul.c
├── sub.c
└── test.c

0 directories, 7 files

If you execute the make clean command later, an error will appear:

daniel@daniel-Vostro-5471:~/file/OS/test/make_test/make3$ make clean
make: "clean"Is up to date.

This is because the clean file in the folder interferes with the execution of the make clean file, especially in the clean command without dependencies. In this case, you can solve it by adding a pseudo target, as follows:

Pseudo target: do not generate files, but execute the target;

ALL:main
src=$(wildcard ./*.c)	#add.c sub.c test.c
obj=$(patsubst %.c,%.o,$(src))	#add.o sub.o test.o
main:$(obj)
	gcc $^ -o $@ -I.
%.o:%.c
	gcc -c $< -o $@
clean:
	-rm -rf $(obj)
#Pseudo target
.PHONY:clean ALL

Add compilation parameters:

You can add compilation parameters to myArgs, and then make $(myArgs) take out the parameters;

ALL:main
src=$(wildcard ./*.c)	#add.c sub.c test.c
obj=$(patsubst %.c,%.o,$(src))	#add.o sub.o test.o
myArgs=-Wall -g
main:$(obj)
	gcc $^ -o $@ -I. $(myArgs)
%.o:%.c
	gcc -c $< -o $@ $(myArgs)
clean:
	-rm -rf $(obj)
#Pseudo target
.PHONY:clean ALL

Library variable

It is a variable defined by yourself in the makefile library. Some variables have default values, while the variables defined by have no default values

CC: the default is CC =cc c language compiler

CPPFLAGS: C + + default parameter

CFLAGS: C default parameter

LDFLAGS: dynamic link parameters

Compile multiple file instances in the same directory at the same time:

daniel@daniel-Vostro-5471:~/file/OS/test/make_test/make5$ tree
.
├── add.c
├── makefile
├── mul.c
└── sub.c

0 directories, 4 files

Every%. Is required c files are compiled into a separate% out executable

The makefile is written as follows:

src=$(wildcard *.c)
# obj=$(patsubst %.c,%.o,$(src))
out=$(patsubst %.c,%.out,$(src))
ALL: $(out)
$(out):%.out:%.c
	gcc $< -o $@
clean:
	-rm -rf $(out)
.PHONY:ALL clean

5.6 standard examples

The directory of the file is as follows:

daniel@daniel-Vostro-5471:~/file/OS/test/make_test/make4$ tree
.
├── inc
│   └── cal.h
├── main
├── makefile
├── obj
└── src
    ├── add.c
    ├── mul.c
    ├── sub.c
    └── test.c

Requirement: put the compiled file into the obj directory

The makefile file is written as follows:

#Compile total target file
ALL:main
#set variable
src=$(wildcard ./src/*.c)	#./src/ add.c sub.c mul.c test.c
# #  %Equivalent substitution means to put the value of% taken from the first variable on the second%
obj=$(patsubst ./src/%.c,./obj/%.o,$(src))#./obj/ add.o sub.o mul.o test.o
# echo:
# 	echo $(src) $(obj)
#Header file location
inc_path=./inc
#Set compilation parameters
myArgs=-Wall -g 
#compile
main:$(obj)
	gcc $^ -o $@ $(myArgs)
# Replace obj directory with src directory
# Header file expansion runs in the preprocessing phase, so there is no need to add header files in line 17
$(obj):./obj/%.o:./src/%.c
	gcc -c $< -o $@ $(myArgs) -I $(inc_path)
clean:
	-rm -rf $(obj)
.PHONY: ALL clean

You can also run the command without using makefile. For example, give the file the name m6(mv makefile m6)

The operation method is: make -f m6

Many files are named: * * * * mk, which may be the makefile file

Make can perform multi-threaded compilation, make -j4 or make -j8

Topics: C++ Linux Unix server