[Makefile]-GNU make Preface & Origin

When writing C++, when studying program construction, Python programmers have already gone home to hug his wife :)

Insert picture description here

What is Makefile?

In simple terms, Makefileit is a file that contains some compiled and linked rules ( rule), when we use the makecommand, makethe program will interpret these rules and execute them. A bit similar to a script, but it is mainly used to build projects (compile, link) to generate targets.

Why do I need Makefile?

The law of peace in the world

I must admit that in modern software development, integrated development environment ( IDE) may be substituted make; but makein Uniux系统a still relatively high position.

Second, while IDEhelping us to achieve the compiler and linker. But simply it means losing control over the details . To achieve control over details, you must face complexity.

It is important to find a balance between the two.

Insert picture description here
In most cases, we do not need to be compiled and linked detail control, IDEprovides a default compile and link the program, to help us write the Makefileliberation process, which is IDEone of value.

For make, considering its background, it helps us get rid of repeated compilation and linking instructions, and can control the details, which is the meaning of its existence.

So we now need to learn to write Makefileit?

  • Not IDEin the case, Makefileis still a good choice

  • Need to read the source code (it exists in some well-known open source projects Makefile, if you want to study them, you can’t get around Makefile)

Make tool

MakefileWe need maketo parse executed. There are many options in this regard:

  • Linux下的 GNU make
  • Visual C++ 的 nmake
  • ...

Different manufacturers makevary, grammar are not the same; but essentially make a fuss about file dependencies. This article chooses yes GNU make3.8.1.

In addition, since its Makefileappearance, many tools have been developed to help us generate Makefile, for example:

  • Qt 的 qmake
  • 支持跨平台的 CMake
  • Linux下的 Autoconf+Automake

GNUmake

Program compilation

In the absence Makefilebefore, we generate an executable file, you can execute the following command:

//编译
g++ -c main.cpp -o main.o
g++ -c foo.cpp -o foo.o
//链接
g++ main.o foo.o  -o app

These steps need to be performed every time the program is modified (this is still the simplest case, what if there are 10 files constituting our project?), and it is a repetitive mechanical movement.

As lazy behalf , thinking liberated from mechanical motion how can you call it laziness?

script

The first thing that comes to mind is: write a script and make it an "action".

For example, write one build.shand execute the script every time you need to build.

But this method introduces a problem, which is more obvious in large projects:
if you only modify a file and then execute the script, many files that do not need to be compiled again will be regenerated. If the file is very large ... like Ubuntuthe kind of level, the compilation time is very long. But in fact, we only need to compile the changed files and relink them.

Derived from make

To solve this problem, at the same time and a better readability shell, bashand so the script can not meet. So people defined it make, it reads in Makefile(makefile, MAKEFILE can also be), Makefilecontains source file dependencies and compilation rules; and then generates the target program through these rules.

As long as we are Makefilewell written, we only need one make指令, you can automatically and intelligently in accordance with the revision of the current file to determine which files need to be recompiled in order to automatically compile the necessary documents and link object files.

# 依赖关系
app: foo.o main.o
# 规则(注意:前面是一个Tab,不要打空格)
	g++ main.o foo.o -o app
foo.o: foo.cpp
	g++ -c foo.cpp -o foo.o
main.o: main.cpp
	g++ -c main.cpp -o main.o

Makefile The dependencies in constitute a dependency tree:

Insert picture description here

How does make work?

Note: Makefiles are not executed sequentially!

When we execute makethe instruction:

  • make Will find first Makefile

  • If you find the default will be the first target file as a final target file (for example app)

  • If the target file does not exist, or behind depends file modification time newer than the target file is re-executed later defined rules to generate an object file

  • If the dependent file already exists, it makewill look for the dependencies of the dependent file (for example foo.o). And generated according to the above rules. Will eventually find the dependency tree叶子节点

In the above process, if an error occurs, it makewill be said:I quit! And throw the error to you.

PHONY dependence

According to the above workflow, whether the rule is executed depends on whether the target exists, whether the dependency is updated, etc.

But sometimes, we look forward to certain rules unconditional implementation .

Then you can define a dependency that will never be satisfied:

clean:
	rm main.o 
	rm foo.o

clean文件It will never be produced, the rules must be enforced. Although this form of viable rules, but makewill be cleancompared to a file, when it became part of the dependency tree, it can easily lead to misunderstanding and error handling.

So Makefileallow us to rely target definition display is false ( Phony), so do not embarrass makethe.

.PHONY: clean

app: foo.o main.o
	g++ main.o foo.o -o app
foo.o: foo.cpp
	g++ -c foo.cpp -o foo.o
main.o: main.cpp
	g++ -c main.cpp -o main.o
	
clean:
	rm main.o 
	rm foo.o

Macro

We can find Makefilethere are many duplicate content, duplicate content of these can be replaced

.PHONY: clean

CC = g++ -c
LD = g++

app: foo.o main.o
	$(LD) main.o foo.o -o app
foo.o: foo.cpp
	$(CC) foo.cpp -o foo.o
main.o: main.cpp
	$(CC) -c main.cpp -o main.o
	
clean:
	rm main.o 
	rm foo.o

There is still a lot of repetition. For example, we wrote it in the dependency foo.oand wrote it again in the rule.

GNUmakeIt allows us to use $@alternative dependent objects , using the $^alternative was dependent objects .

So it can be rewritten as:

.PHONY: clean

CC = g++ -c
LD = g++

app: foo.o main.o
	$(LD) $^ -o $@
foo.o: foo.cpp
	$(CC) $^ -o $@
main.o: main.cpp
	$(CC) -c $^ -o $@
	
clean:
	rm main.o 
	rm foo.o

Wildcard

Obviously, there are still a lot of repetitions. We will change the repetitive part to 通配符:

.PHONY: clean

CC = g++ -c
LD = g++

app: foo.o main.o
	$(LD) $^ -o $@

%.o: %.cpp
	$(CC) $^ -o $@
	
clean:
	rm main.o 
	rm foo.o

Wildcard %means:

  • For example, we need to foo.oconstruct rules, just Makefilelook for, and then found%.o: %.cpp

  • foo.oSet into %.o, so %that foothe back of %.cppthatfoo.cpp

  • OK, construct

Implicit rule

There are more concise approach, namely the use of GNUmakeimplicit rules:

SRC = $(wildcard *.cpp)
OBJ = $(SRC:.cpp=.o)
app: $(OBJ)
	g++ $^ -o $@

Not defined here foo, maindependent, but gnumakeby default, if .cpppresent, .oto the corresponding dependent .cpp, and .oto .cppthe rule, by macros defined by default. We can modify CC, LDLIBSthis type of macro to change the default rule.

So far, preliminary spy Makefileor two.
Insert picture description here

Reference thanks

Getting started with Makefile concepts

Cheng Hao "Write Makefile with Me"

GNU Make (raw meat)

Xu Haibing translated "GNU make Chinese Manual"

The difference between the% mark in Makefile and the system wildcard *

Guess you like

Origin blog.csdn.net/weixin_40774605/article/details/106862014