Writing rules ----
The rules contain two parts, one is a dependency, one is a way to generate the target.
In Makefile, the order of the rules is very important, because only one ultimate goal is in Makefile, other goals are coming from this target, so be sure to let Make know what your ultimate goal is. In general, it may be a lot of targets defined in makefile, but the target in the first rule will be established as the final goal. If there are many objectives in the first rule, then the first goal will become the final goal. This goal is made by Make.
Ok, let's take a look at how to write rules.
First, rule example
Foo.O: foo.c defs.h # foo module cc -c -g foo.c
Seeing this example, you should not be very strange. I have said before, foo.o is our goal, foo.c and defs.h are the source files dependent on the target, and only one command "cc -c - g foo.c "(beginning with a Tab). This rule tells us two things:
1, the dependency of the file, foo.o depends on the file of foo.c and defs.h, if foo.c and defs.h's file date should be new, or foo.o does not exist Then, the dependency occurs. 2. Generate (or update) the foo.o file. That is the CC command, which explains how to generate foo.o file. (Of course, foo.c files include DEFS.H file)
Second, the syntax of the rules
Targets: Prerequisites Command ...
Or this:
Targets: prerequisites; Command Command ...
Targets is the file name, separated by space, and can use wildcard. In general, our goal is basically a file, but it may be multiple files.
Command is a command line if it is not with "Target: prerequisites", then, must start with the [Tab key], if Prerequisites are in one line, then the semicolon is separated by sections. (See)
Prerequisites is also a file (or dependent objective) that is dependent on the target. If a file is to be new than the target file, then the goal is considered "Out of", it is considered to be reborn. This has been told in front.
If the command is too long, you can use a backslash box ('/') as a newline. Make has no restrictions on how many characters on a line. The rule tells make two things, dependencies, and how to become a target file.
In general, Make will execute commands with UNIX standard shell, that is, / bin / sh.
Third, using wildcards in rules
If we want to define a series of similar files, we naturally think of using wildcards. Make supports three wildcards: "*", "?" and "[...]. This is the same as UNIX's B-shell.
Wave number ("~") characters also have a relatively special purpose in the file name. If it is "~ / test", this means the TEST directory under the $ HOME directory of the current user. And "~ hchen / test" represents the Test directory under the host directory of the user's hCHEN. (These are small knowledge under UNIX, Make also supports) and under Windows or MS-DOS, the user does not have a host directory, then the directory referred to by the Wave is determined according to the environment variable "home". Wildcard replaces your series of files, such as "* .c" means that the suffix is C. One requires us to pay attention, if there is a wildcard in our file name, such as "*", you can use the escape character "/", such as "*" to represent the true "*" character, not any length String.
Ok, let's take a few examples first:
Clean: rm -f * .o
I don't have much to say this above, this is the wildcard supported by the operating system shell. This is a wildcard in the command.
Print: * .c lpr -p $? Touch Print
The above example illustrates the wildcards or in our rules, the target Print relies on all [.c] files. Where "$?" Is an automated variable, I will tell you later.
Objects = * .o
The above example, indicated, the harness can also be used in the variable. Not to say [* .o] will start, no! The value of Objects is "* .o". The variable in makefile is actually a macro in C / C . If you want a wildcard to expand in the variable, that is, the value of Objects is all the collection of file names of [.o], then you can:
Objects: = $ (Wildcard * .o)
This method is pointed out by keyword "wildcard", and we will discuss later about MAKEFILE.
Fourth, file search
In some big projects, there are a lot of source files, and our usual approach is to classify this many source files and store them in different directories. So, when Make needs to find the dependencies of the document, you can add a path before the file, but the best way is to tell Make with a path, let Make go automatically.
The special variable "vpath" in the makefile file is to complete this feature. If this variable is not specified, Make will only find dependencies and destination files in the current directory. If this variable is defined, Make will find a file in the specified directory when the current directory is not found.
Vpath = src: ../ Headers
The above definition specifies two directories, "src" and "../headers" ,make will search in this order. The directory is separated by a "colon". (Of course, the current directory is always the highest priority search)
Another way to set the file search path is to use the "vPath" keyword (note that it is a lot of writing), this is not a variable, this is a keyword, which is similar to the VPath variable mentioned above. But it is more flexible. It can specify different files in different search directories. This is a very flexible function. There are three ways to use:
1, vpath
Specify search directory
2, vpath
Clear the search directory of files that match the pattern
Clear all file search directories that have been set.
vpath% .h ../headers
This statement is indicated that Make is required to search all files ending with ".h" in the ".h" directory. (If a file is not found in the current directory)
We can use the vPath statement continuously to specify different search strategies. If the same
vpath% .c foo vPath% blish vPath% .c bar
It means ".C" file, first in the "foo" directory, then "BLISH", and finally the "bar" directory.
vpath% .c foo: bar vpath% blish
The above statement indicates ".C" file, first in the "foo" directory, then "Bar" directory, and finally the "blish" directory.
V. Pseudo
In an early first example, we mentioned a "clean" goal, this is a "pseudo-objective",
Clean: rm * .o Temp
Just like "clean" in our previous example, we have generated many file compilation files, and we should also provide a "target" to clear their "target" to prepare to compile completely. (Use "Make Clean")
Because we don't generate "clean" files. "Pseudo Target" is not a file, just a label, because "pseudo-target" is not a file, so Make cannot generate its dependencies and decide whether it is to be executed. We only make it effective by indicating this "target" by displaying. Of course, "pseudo-target" is named with the file name, otherwise it will lose the meaning of "pseudo-target".
Of course, in order to avoid this situation to be renowned, we can use a special tag ".phony" to display a "pseudo-target", explain to make, regardless of this file, this goal is " Pseudo-target.
.Phony: Clean
As long as there is this statement, no matter whether there is a "clean" file, you have to run the "clean" target, only "make clean". So the whole process can write this:
.Phony: Clean Clean: Rm * .o Temp
Pseudo-targets generally have no dependencies. However, we can also specify the dependencies dependent on the pseudo target. The pseudo target can also be used as a "default target" as long as it is placed in the first one. One example is that if your makefile needs to generate a number of executable files, you just want to simply knock an opportunity, and all the target files are written in a makefile, then you can use "PseudoT" This feature:
All: PROG1 PROG2 PROG3.PHONY: ALL
PROG1: PROG1.O Utils.o Cc -o PROG1 PROG1.O Utils.o
PROG2: PROG2.O CC -O PROG2 PROG2.OPROG3: PROG3.O Sort.o Utils.o Cc -o PROG3 PROG3.O SORT.O Utils.o
We know that the first goal in makefile will be used as its default target. We declare a "all" pseudo-target that relies on the other three goals. Since the characteristics of the pseudo objective are always being executed, the three goals depending on the dependence are always like "all". Therefore, the rules of the other three goals will always be resolution. Just achieve the goal of us to generate multiple goals. ".Phony: all" declares that "all" is "pseudo-target".
Just mention, from the above example we can see that the goal can also be dependent. Therefore, the pseudo target can also be dependent. Look at the example below:
.Phony: CleanAll Cleanobj Cleandiff
Cleanall: Cleanobj Cleandiff RM Program
Cleanobj: rm * .o
CleanDiff: rm * .diff
"Make Clean" will clear all files to be cleared. "Cleanobj" and "Cleandiff" are a bit like "subroutine". We can enter the "make cleanl" and "make clean cleanobj" and "make cleandiff" commands to achieve the purpose of clearing different kinds of files.
<- Previous Next -> (All rights reserved, please indicate the author and source)