Makefile Grammar Basics
Under Linux, the automated compilation tools are done by the Make command (some tool vendors also provide their own make commands, such as gmake, etc.), the basic format of the make command is as follows:
make [-f makefile] [label]
It can specify the input file through the-f parameter, when the-f parameter is omitted, the default input file name is makefile, because we usually do not use the-f parameter, often with the default makefile file name.
Makefile is a text file that is based on certain grammatical rules, and its basic execution rules are defined as follows:
target : [prerequisites] command
- Target: Tag, used to flag the currently constructed rule, which can also be a file.
- Prerequisites: Dependencies, rules that are executed first when the tag is built
- Command make: commands that need to be executed. (Arbitrary shell Command)
Note: The makefile target is written by shelf, and command requires a TAB key.
For example, we write a simple makefile:
clean: @echo "clean"all: @echo "all"
When we execute the make command directly, the output is as follows:
$makeclean$make allall$make cleanclean
From what we can see: The first tag is built by default. The specified label can be constructed by parameters in the command-line arguments.
Then we'll look at how dependencies work, and this time we'll revise the makefile so that the all tag relies on the clean tag:
clean : @echo "clean"all : clean @echo "all"
When you execute make all again, you find that the clean tag is executed first:
$make allcleanall
Using makefile to build a project
With a simple understanding of the syntax of makefile, the following can be used to simplify our build operations with makefile. Or for the example of the previous stack, let's start by implementing one of the simplest examples:
all : gcc -o run main.c stack.c
This enables the execution of the entire command directly through the Make command gcc -o run main.c stack.c .
A step further, if we want to implement incremental compilation, we implement the following rules:
- If this project is not compiled, all of our C files are compiled and linked.
- If a few C files of this project are modified, then we only compile the modified C file and link the target program.
This is the time when the previous dependencies are needed:
run : stack.o main.o gcc -o run main.o stack.ostack.o : stack.c gcc -c stack.cmain.o : main.c gcc -c main.c
Run relies on STACK.O and MAIN.O by default, so when the run is built, STACK.O and MAIN.O are built first, with the following output:
makegcc -c stack.cgcc -c main.cgcc -o run main.o stack.o
When we change only one of these files, such as STACK.C, this is because MAIN.C does not change, so the MAIN.O is not recompiled, only the STACK.O and run will be rebuilt to achieve our incremental compilation. (This is actually a lot more powerful than the batch method written by the shell or scripting language)
makegcc -c stack.cgcc -o run main.o stack.o
Improved makefile by automatic derivation
As you can see from the example above, although we can implement incremental compilation, the entire makefile process is very complex and requires compiling a compilation script for each. o file. Writing a makefile file is cumbersome if you have more project files and additions and deletions.
To improve this problem, Makefile provides an auto-derivation function that simplifies our writing process. For example, the preceding example can be simplified as follows:
CC = gccobjs = stack.o main.orun : $(objs) $(CC) -o run $(objs)
Here we introduce two variables, the first row of CC has a compiler for GCC (if not specified is the default cc), and the second line has our obj file set.
This allows you to produce our program with just the Make command:
makegcc -c -o stack.o stack.cgcc -c -o main.o main.cgcc -o run stack.o main.o
As you can see, the make command automatically deduces how to root out the. o file. If our project file changes, we only need to change the OBJS variable, it is very convenient.
However, there are times when we may feel that the automatic derivation method is not enough, we need to manually control the compilation options, this time we can specify the derivation rule:
CC = gccobjs = stack.o main.orun : $(objs) $(CC) -o run $(objs)$(objs): %.o: %.c $(CC) -c -g $< -o [email protected]
In the above example, we indicate that our goal is to be obtained from the target, that is $objs %.o , the ". O" End of the goal, that stack.o main.o is, the pattern of the variable set, and the $objs dependency mode "%.C" is the mode %.o "%", that is, "stack main", and add the suffix ". C" to it, so our target is stack.c main.c . $<and the "[email protected]" in the command is an Automation variable that $< represents all the dependent target sets (that is stack.c main.c ), [email protected] representing the target set (that is stack.o main.o ). Thus, the above rules are expanded to be equivalent to the following rules:
stack.o : stack.c $(CC) -c -g stack.c -o stack.omain.o : main.c $(CC) -c -g main.c -o main.o
Imagine, if we %.o have hundreds of, the kind we just use this very simple "static mode rule" can write a bunch of rules, it is too effective rate. The use of static mode rules is flexible, and if used well, it can be a powerful feature. If you want to know more, you can refer to writing with me makefile this article.
From for notes (Wiz)
Linux advanced Programming--03.make and Makfile