When we use makefile, there are some things we will use very often, and the use of very high frequency, for example, we compile the source program C/s + + for intermediate target files (Unix is [. o] File, under Windows is [. obj] file). This chapter deals with some of the "hidden", previously agreed upon makefile rules that we do not need to write again.
The "implied rule" is also a convention in which make will run in a manner that is "customary", fearing that no such rule is written in our makefile. For example, if you compile the [. c] File into the [. O] File, you don't have to write it, and make automatically deduces the rule and generates the [. o] File we need.
"Implied rules" use some of our system variables, and we can change the values of these system variables to customize the runtime parameters of the implied rules. such as the system variable "CFLAGS" can control compile-time compiler parameters.
We can also write down our own implicit rules by means of "pattern rules". There are a number of limitations to defining implied rules with the suffix rule. The use of "pattern rules" is more intelligent and clear, but "suffix rules" can be used to guarantee our makefile compatibility.
We understand the "hidden rules" that can make them better for us and will let us know something that is "conventional," rather than making us run makefile with something that we find baffling. Of course, anything is contradictory, water can carry a boat, but also overturn it, so, sometimes "hidden rules" will give us a little trouble. Only by understanding it can we use it better.
I. Use of implicit rules
If you want to use implicit rules to generate the goals you want, all you need to do is not write the rules for this goal. So, make will try to automatically derive the rules and commands that produce this goal, and if make can automatically deduce the rules and commands that generate the target, then this behavior is the automatic derivation of the implied rules. The implicit rule, of course, is something that make is agreed on in advance. For example, we have one of the following makefile:
Cc–o foo foo.o bar.o $ (CFLAGS) $ (ldflags)
We can note that this makefile does not write down the rules and commands for how to generate the two goals of FOO.O and BAR.O. Because the "implied rules" feature of make automatically automatically infers the dependent targets and build commands for these two targets.
Make will look for available rules in its own "hidden rules" library, and if found, it will be used. If you can't find it, you'll get an error. In the above example, the implicit rule of make invocation is to place the dependent file [. c] of the target of [. O], and use C's compile command "Cc–c $ (CFLAGS) [. c]" to generate the [. O] Target. In other words, we have absolutely no need to write down the following two rules:
Cc–c foo.c $ (CFLAGS)
Cc–c bar.c $ (CFLAGS)
Because, this is already a "convention" good thing, make and we agreed to use the C compiler "CC" to generate the [. O] File rules, this is the implied rule.
Of course, if we write our own rules for the [. O] File, then make does not automatically deduce and invoke the implied rules, which are faithfully executed according to the rules we have written.
Also, in the "Hidden Rules library" of make, each implied rule has its order in the library, and the more forward it is, the more often it is used, so this will cause us to have some time even if we specify the target dependency, and make does not control. As in the following rule (no command):
Depending on the file "FOO.P" (the Pascal program's source file) may become meaningless. If the "foo.c" file exists under the directory, then our implied rules will take effect, and the foo.o file will be generated by the compiler of "FOO.C" Call C. Because, in the implied rules, Pascal's rules appear after the C rule, so make finds the rule that generates FOO.O C and no longer looks for the next rule. If you do not want any implied rules to be deduced, then you should not write only "dependent rules" without writing commands.
Ii. List of implied rules
Here we'll cover all the implicit rules of pre-Setup (that is, make built-in), and if we don't explicitly write the rules, then make will look for the rules and commands that are needed in these rules. Of course, we can also use make's parameter "-R" or "--no-builtin-rules" option to cancel all pre-set implied rules.
Of course, even if we specify the "-r" parameter, some implied rules will take effect, since there are many implied rules that are defined using the "suffix rule", so long as there is a "suffix list" in the implied rule (and a system is defined on the target.) suffixes), then the implied rules will take effect. The default list of suffixes is:. Out,. A,. LN,. O,. C,. CC,. C,. P,. F,. F,. R,. Y,. L,. S,. S,. MoD,. Sym,. def,. h,. info,. DVI,. Tex,. Texinfo,. Texi,. Txinfo,. W,. Ch. Web,. SH,. ELC,. El. We will tell you the details in detail later.
Let's take a look at the usual hidden rules.
1. Compile the implicit rules of C program.
The target dependent target of "<N>.O" is automatically deduced as "<N>.C" and its generated command is "$ (CC) –c $ (cppflags) $ (CFLAGS)"
2. Compile the implicit rules of C + + program.
The target of "<N>.O" will be automatically deduced as "<n>.cc" or "<n>". C "and its build command is" $ (CXX) –c $ (cppflags) $ (CFLAGS) ". (". CC" is recommended as the suffix of the C + + source file instead of ". C ")
3. Compile the implied rules of Pascal program.
The target dependent target of "<N>.O" is automatically deduced as "<N>.P" and its generated command is "$ (PC) –c $ (pflags)".
4, compile the Fortran/ratfor program of the implicit rules.
The target of "<N>.O" is automatically deduced as "<N>.R" or "<n>". F "or" <N>.F ", and its generated commands are:
". F" "$ (FC) –c $ (fflags)"
“. F "" $ (FC) –c $ (fflags) $ (cppflags) "
". F" "$ (FC) –c $ (fflags) $ (rflags)"
5, pre-processing Fortran/ratfor program implicit rules.
The target of "<N>.F" is automatically deduced as "<N>.R" or "<n>". F ". This rule simply converts ratfor or has a pre-processed FORTRAN program to a standard FORTRAN program. The commands it uses are:
“. F "" $ (FC) –F $ (cppflags) $ (fflags) "
". R" "$ (FC) –F $ (fflags) $ (rflags)"
6, compile the Modula-2 program of the implicit rules.
The target dependent target for "<n>.sym" is automatically deduced as "<n>.def" and its generated command is: "$ (M2C) $ (m2flags) $ (defflags)". The target target of "<n.o>" is automatically deduced as "<n>.mod", and its generated command is: "$ (M2C) $ (m2flags) $ (modflags)".
7, compilation and compilation of the implicit rules of preprocessing.
The target target of "<N>.O" is automatically deduced as "<n>.s", using the compiled product "as" by default, and its generated command is "$ (AS) $ (asflags)". The target of "<n>.s" is automatically deduced as "<N>". S ", the C pre-compiler" CPP "is used by default, and its build command is:" $ (AS) $ (asflags) ".
8. Link the implicit rules of the object file.
The "<n>" target relies on "<N>.O" to run the linker generation (typically "LD") by running the C compiler, whose generated command is: "$ (CC) $ (ldflags) <N>.O $ (loadlibes) $ ( Ldlibs) ". This rule is valid for projects with only one source file, and also for multiple object files (generated by different source files). For example, the following rules:
And when both "x.c", "y.c", and "z.c" are present, the implied rule executes the following command:
Cc-c X.c-o X.O
Cc-c Y.c-o y.o
Cc-c Z.c-o Z.O
CC X.O Y.O Z.o-o x
If you don't have a source file (such as x.c in the previous example) associated with your target name (as in the example above), then you'd better write your own build rule, or the implied rule will report an error.
9, YACC C program when the implied rules.
The dependent file for "<n>.c" is automatically deduced as "N.Y" (the YACC generated file) and its generated command is: "$ (YACC) $ (YFALGS)". ("Yacc" is a parser, for details please see the relevant information)
10, Lex C program when the implied rules.
The dependent file for "<n>.c" is automatically deduced as "N.L" (the lex-generated file) and its generated command is: "$ (Lex) $ (LFALGS)". (For details on "Lex", please refer to the relevant information)
11, Lex ratfor Program when the implicit rules.
The dependent file for "<N>.R" is automatically deduced as "N.L" (the lex-generated file) and its generated command is: "$ (Lex) $ (LFALGS)".
12. Create an implicit rule for the lint library from a C program, a YACC file, or a lex file.
The dependent file for "<n>.ln" (LINT generated file) is automatically deduced as "N.C" and its generated command is: "$ (LINT) $ (LINTFALGS) $ (cppflags)-i". The same rules apply to "<n>.y" and "<N>.L".
Iii. variables used by implied rules
In the commands in the implied rules, some of the pre-set variables are basically used. You can change the values of these variables in your makefile, either by passing them on the command line of make, or by setting them in your environment variables, however, if you set these specific variables, they will work on the implied rules. Of course, you can also use Make's "-R" or "--no–builtin-variables" parameters to cancel the effect of the variables you define on the implied rules.
For example, the first implied rule--the command to compile an implied rule for a C program is "$ (CC) –c $ (CFLAGS) $ (cppflags)". Make the default compile command is "CC", if you redefine the variable "$ (cc)" to "GCC", the variable "$ (CFLAGS)" is redefined as "-G", then the implied rules of the command will be "Gcc–c-g $ (cppflags)" In the appearance of the execution.
We can divide the variables used in the implied rules into two kinds: one is command-related, such as "CC", and the other is the close of the parameter phase, such as "CFLAGS". Here are the variables that are used in all implied rules:
1, about the variables of the command.
function Library Packager. The default command is "AR".
Assembly language Compiler program. The default command is "as".
C language Compiler program. The default command is "CC".
C + + language compiler program. The default command is "g++".
Extend the file program from the RCS file. The default command is "CO".
C program's preprocessor (output is standard output device). The default command is "$ (CC) –E".
Fortran and Ratfor compilers and pre-processing programs. The default command is "F77".
The program that extends the file from the SCCs file. The default command is "get".
Lex Method Parser Program (for C or ratfor). The default command is "Lex".
Pascal language Compiler program. The default command is "PC".
YACC Grammar Analyzer (for C programs). The default command is "YACC".
YACC Grammar Analyzer (for ratfor programs). The default command is "Yacc–r".
Convert texinfo source file (. texi) to info file program. The default command is "Makeinfo".
A program for creating Tex-DVI files from Tex source files. The default command is "Tex".
Create an Army Tex DVI file from the Texinfo source file program. The default command is "Texi2dvi".
Convert the Web to Tex program. The default command is "weave".
Convert the C WEB to Tex program. The default command is "Cweave".
Convert the Web to Pascal language program. The default command is "Tangle".
Convert c Web to C. The default command is "Ctangle".
The delete file command. The default command is "Rm–f".
2. Variables for command parameters
The following variables are all parameters related to the command above. If the default value is not specified, the default value is null.
Parameters of the Function Library Packager ar command. The default value is "rv".
assembly language compiler parameters. (when obviously called ". S" or ". S "file).
C language Compiler parameters.
C + + language compiler parameters.
RCS command parameters.
C Preprocessor parameters. (The C and Fortran compilers are also used).
Fortran language compiler parameters.
SCCS "Get" program parameters.
Linker parameters. (eg: "LD")
Lex Grammar parser parameter.
Pascal language compiler parameter.
The Fortran compiler parameter for the RATFOR program.
YACC Grammar Analyzer parameters.
Iv. chain of implied rules
Sometimes, a goal may be a series of implicit rules to the effect. For example, a [. O] File generation may be preceded by the [. Y] File First YACC [. c] and then generated by the C compiler. We call this series of implicit rules "chain of implied rules".
In the example above, if the file [. c] exists, then the implicit rule of C's compiler is called directly, if there is no [. c] File, but there is a [. y] File, then the implied rule of YACC is called, the [. c] File is generated, and then the implicit rule of C compilation is eventually generated [. O] ] file to reach the target.
We call this [. c] File (or target) the intermediate target. In any case, make will try to automatically deduce all the methods of generating the target, regardless of the number of intermediate goals, it will persist in all the implied rules and the rules you write all together to analyze and strive to achieve the goal, so, sometimes it may make you feel strange, how my goal will be generated? Why is my makefile crazy?
By default, for intermediate targets, it differs from the general target in two places: the first difference is that the intermediate rule is raised unless the intermediate target does not exist. The second difference is that, as long as the goal is successful, the resulting intermediate target file is deleted as "Rm-f" when the final target is produced.
Typically, a file that is designated as a target or dependent by makefile cannot be used as an intermediary. However, you can clearly state that a file or target is an intermediary target, and you can use pseudo-target ". Intermediate "to enforce the declaration. (such as:. INTERMEDIATE:MID)
You can also prevent make from automatically deleting intermediate targets, and to do this you can use pseudo targets. " Secondary "to enforce the declaration (for example:. SECONDARY:SEC). You can also put your goals in a pattern way to specify (eg:%.O) into pseudo-targets ". Precious "To save the intermediate file generated by the implied rule.
In the chain of implied rules, it is forbidden to show the same target two or more times, or more than two times, which prevents infinite recursion when make is automatically deduced.
Make optimizes some special implicit rules without generating intermediate files. For example, from the file "foo.c" to generate the target program "Foo", according to the truth, make will compile to generate intermediate file "FOO.O", and then link to "foo", but in practice, this action can be a "CC" command to complete (cc–o foo FOO.C), then the optimized rule will not generate intermediate files.
V. Defining pattern rules
You can use pattern rules to define an implicit rule. A pattern rule is like a general rule, but in a rule, the definition of a goal requires a "%" character. "%" means one or more arbitrary characters. The "%" can also be used in a dependent target, depending on its target, only the value of "%" in the target.
It is important to note that the expansion of "%" occurs after the expansion of variables and functions, where the expansion of variables and functions occurs when make is loaded into the makefile, while the "%" in the pattern rule occurs at run time.
1. Introduction of Pattern Rules
In a pattern rule, you must include "%" at least in the target definition of the rule, otherwise, it is the general rule. The "%" definition in the target indicates a match to the file name, and "%" indicates any non-empty string of length. For example: "%.c" means the file name ending with ". C" (at least 3 of the file name), while "s.%.c" means "s." Start with the file name at the end of ". C" (at least 5 of the file name).
If "%" is defined in the target, then the value of "%" in the target determines the value of "%" in the dependent target, that is, the "%" of the pattern in the target determines the "%" of the dependent target. For example, there is a pattern rule as follows:
%.O:%.c; <command ......>
The implication is that the rules for how to generate corresponding [. o] Files from all [. c] files are indicated. If the target to be generated is "A.O b.o", then "%c" is "A.C B.C".
Once the dependent target "%" mode is determined, then make will be asked to match all the file names in the current directory, once found, make will rule the command, so, in the pattern rule, the target may be multiple, if the pattern matches multiple targets, make will produce all the pattern targets, At this point, make is concerned with both the dependent file name and the command that generated the target.
2. Pattern Rule Example
The following example shows that all [. c] files are compiled into a [. O] File.
$ (CC)-C $ (CFLAGS) $ (cppflags) $<-o [email protected]
where "[email protected]" denotes the value of all targets, "$<" indicates the value of all dependent targets. These strange variables are called "Automation variables" and are described in detail later.
In the following example, there are two goals in the pattern:
This rule tells make to execute all the [. Y] files as "bison-d <n>.y" and then generate "<N>.TAB.C" and "<n>.tab.h" files. (where "<n>" represents an arbitrary string). If our execution program "Foo" depends on the file "PARSE.TAB.O" and "SCAN.O", and the file "SCAN.O" depends on the file "Parse.tab.h", if the "parse.y" file is updated, then according to the above rules, "bison-d Parse.y "will be executed once, then," PARSE.TAB.O "and" SCAN.O "of the dependent files are aligned. (Suppose that "PARSE.TAB.O" is generated by "PARSE.TAB.C", and "SCAN.O" is generated by "scan.c", and "Foo" is delivered by the "PARSE.TAB.O" and "SCAN.O" links, and Foo and its [. o] File dependencies are also well written , then all the goals will be met)
3. Automation variables
In the above pattern rules, the target and dependent files are all examples of files, then how do we write a command to complete the corresponding target from different dependent files? Because every time you parse a schema rule, it will be a different target and dependent file.
The automation variable is the one that accomplishes this function. In the preceding, we have already been involved in the automation variables, I believe you see here has a perceptual knowledge of it. The so-called automation variable, that is, this variable will be defined in the pattern of a series of files automatically removed, until all the matching mode of the file is finished. This automation variable should only appear in the command of the rule.
Here are all the automation variables and their descriptions:
Represents a set of target files in a rule. In a pattern rule, if there are multiple targets, then "[email protected]" is the set that matches the schema definition in the target.
Represents the target member name in a rule only if the target is in a function library file. For example, if a target is "foo.a (BAR.O)", then "$%" is "BAR.O", "[email protected]" is "FOO.A". If the target is not a function library file (under UNIX is [. lib] under [. a],windows]), then its value is null.
The first target name in a dependent target. If the dependent target is defined in a pattern (that is, "%"), then "$<" will be a series of file sets conforming to the pattern. Note that it is taken out one by one.
A collection of all new dependent targets than the target. separated by a space.
A collection of all dependent targets. separated by a space. If there are multiple duplicates in the dependent target, that variable will remove the duplicate dependent target and keep only one copy.
This variable is much like "$^" and is also a collection of all dependent targets. It's just that it does not remove duplicate dependent targets.
This variable represents "%" in the target pattern and its previous part. If the target is "DIR/A.FOO.B" and the target's pattern is "a.%.b", then the value of "$*" is "Dir/a.foo". This variable is more relative to the file name that is associated with the construct. If there is no schema definition in the target, then "$*" cannot be deduced, but if the suffix of the target file is recognized by make, then "$*" is the part of the suffix. For example, if the target is "foo.c" because ". C" is the suffix name that make can recognize, the value of "$*" is "foo". This feature is GNU make and most likely not compatible with other versions of makes, so you should try to avoid using "$*" unless it is in implied rules or static mode. If the suffix in the target is not recognized by make, then "$*" is a null value.
When you want to manipulate only the updated dependent files, "$?" is useful in explicit rules, for example, suppose a library file is called "Lib", which is updated by several other object files. The more efficient makefile rule to package the object file is:
LIB:FOO.O BAR.O LOSE.O WIN.O
Ar r lib $?
In the automatic quantitative quantities listed above. The four variables ([email protected], $<, $%, $*) only have one file in the extension, and the other three values are a list of files. These seven automation variables can also get the directory name of the file or the file name in the current directory in accordance with the schema, only need to match the word "D" or "F". This is the feature of the old version of GNU make, which we can do with the function "dir" or "Notdir" in the new version. The meaning of "D" is directory, that is, the meaning of "F" is file.
Here are the meanings of "D" or "F" for each of the seven variables above:
"[Email protected]" In the directory section (do not end with a slash), if the "[email protected]" value is "dir/foo.o", then "$ (@D)" is "dir", and if "[email protected]" Does not contain a slash, its value is "." (current directory).
"[Email protected]" In the file section, if the "[email protected]" value is "dir/foo.o", then "$ (@F)" is "FOO.O", "$ (@F)" equivalent to the function "$ (notdir [email Protected]) ".
And the same as described above, but also to take the directory portion of the file and the file section. For the example above, "$ (*d)" returns "Dir", while "$ (*f)" returns "Foo"
Represents the directory part and file portion of a function package file member, respectively. This is useful for "member" in the form of "archive (member)" In a target that contains different directories.
Represents the directory part and file portion of the dependent file, respectively.
Represents the directory portion and file portion of all dependent files, respectively. (Not the same)
Represents the directory portion and file portion of all dependent files, respectively. (can have the same)
"$(? D) "
"$(? F) "
Represents the directory portion and file portion of the dependent file that was updated, respectively.
Finally, to remind you that for "$<", in order to avoid unnecessary trouble, we'd better give the specific character behind the $ parentheses, for example, "$ (<)" is better than "$<".
It is also important to note that these variables are used only in the commands of the rule, and are generally "explicit rules" and "Static Mode rules" (see the preceding "Writing Rules" chapter). It has no meaning in the implied rules.
4. Pattern matching
In general, a target pattern has a "%" with a prefix or suffix, or no prefix, which is directly a "%". Because "%" represents one or more characters, in a well-defined pattern, we call "%" the content that matches "stem", for example "%.C" matches the file "test.c" in "Test" is the "stem". Since there is a "%" in both the target and the dependent target, the "stem" of the dependent target is passed on to the target as the "stem" in the target.
When a pattern matches a file containing a slash (which is not often included), then when the pattern is matched, the part of the directory is first removed, then matched, and then added back to the directory. We need to know this step in the "stem" delivery. For example, there is a pattern "e%t", the file "src/eat" matches the pattern, so "src/a" is its "stem", if the pattern is defined in the dependent target, and is dependent on the model of the target has a pattern "c%r", then the goal is "Src/car". ("stems" are passed)
5. Overloaded built-in implicit rules
You can overload the built-in implicit rules (or define a whole new one), for example, you can reconstruct and construct commands with different implicit rules, such as:
$ (CC)-C $ (cppflags) $ (CFLAGS)-d$ (date)
You can cancel the built-in implicit rule, as long as you do not write the command in the following line. Such as:
Again, you can redefine a new implicit rule whose position in the implied rule depends on where you write the rule. The front-facing position is on the front.
Vi. "suffix rules" for old-fashioned style
The suffix rule is an old-fashioned way to define an implicit rule. Suffix rules are progressively replaced by pattern rules. Because the pattern rules are stronger and clearer. To be compatible with older versions of Makefile, GNU make is also compatible with these things. There are two ways to suffix a rule: "Double suffix" and "single suffix".
The double-suffix rule defines a pair of suffixes: the suffix of the target file and the suffix of the dependent target (source file). such as ". C.O" corresponds to "%o:%c". A single suffix rule defines only one suffix, which is the suffix of the source file. such as ". C" equals "%:%.c".
suffixes defined in the suffix rule should be known by make, and if a suffix is known by make, then this rule is a single-suffix rule, and if two of the suffixes are linked together by make, that is the double-suffix rule. For example, ". C" and ". O" are all known by make. Thus, if you define a rule that is ". C.O" Then it is a double-suffix rule, meaning ". C" is the suffix of the source file, and ". O" is the suffix of the destination file. The following example:
$ (CC)-C $ (CFLAGS) $ (cppflags)-o [email protected] $<
The suffix rule does not allow any dependent files, and if there are dependent files, it is not a suffix rule, and those suffixes are all considered filenames, such as:
$ (CC)-C $ (CFLAGS) $ (cppflags)-o [email protected] $<
This example, that is, the file ". C.O" relies on the file "Foo.h" instead of what we want:
$ (CC)-C $ (CFLAGS) $ (cppflags)-o [email protected] $<
In the suffix rule, if there is no command, it is meaningless. Because he would not remove the built-in implicit rules.
To let make know some specific suffixes, we can use pseudo-targets. " Suffixes "to define or delete, such as:
. Suffixes:. hack. Win
Add suffix. hack and. Win to the end of the suffix list.
. Suffixes: # Remove the default suffix
. Suffixes:. c. O H # define its own suffix
First clear the default suffix, then define your own suffix list.
The parameter "-R" or "-no-builtin-rules" of Make also uses the default suffix list to be empty. While the variable "SUFFIXE" is used to define the default suffix list, you can use ". Suffixes "To change the suffix list, but please do not change the value of the variable" SUFFIXE ".
Seven, implicit rule search algorithm
For example, we have a target called T. The following is the algorithm for searching for rules for target T. Note that in the following, we do not refer to the suffix rule because all suffix rules are converted to a schema rule when makefile is loaded into memory. If the target is "archive (member)" Function library file mode, then this algorithm will be run two times, the first is to find the target T, if not found, then enter the second time, the second will be "member" as T to search.
1. Separate the catalog parts of T. Called D, while the rest is called N. (such as: if T is "src/foo.o", then D is "src/", N is "foo.o")
2. Create a list of all pattern rules that match t or N.
3. If there is a pattern in the list of pattern rules that matches all files, such as "%", then remove the other mode from the list.
4. Remove the rule with no commands in the list.
5. For the first pattern rule in a list:
1) The derivation of its "stem" s,s should be T or N matched to the "%" non-empty part of the pattern.
2) Calculate dependent files. Replace the "%" in the dependent file with the "stem" S. If the target pattern does not contain a miter box character, add D to the beginning of the first dependent file.
3) test whether all dependent files exist or should exist. (If a file is defined as a target file for another rule, or a dependent file of an explicit rule, the file is called "rightfully present")
4) If all dependent files exist or are supposed to exist or are not dependent on the file. Then this rule will be used to exit the algorithm.
6, if after the 5th step, no pattern rules are found, then do a further search. For the first pattern rule that exists in the list:
1) If the rule is a terminating rule, ignore it and continue to the next pattern rule.
2) Calculate dependent files. (same as 5th step)
3) test that all dependent files exist or should exist.
4) for non-existent dependent files, recursively call the algorithm to find out if he can be found by the implied rules.
5) If all dependent files exist or are supposed to exist or are not dependent on the file at all. Then this rule is used to exit the algorithm.
7. If no implied rules can be used, view ". DEFAULT "rules, if any, adopt, put". The "DEFAULT" command is used for T.
Once the rule is found, it executes its equivalent command, at which point the value of our automation variable is generated.