When we use makefile, there are things that we often use and use very frequently, such, we compile the C/C ++ source program as the intermediate target file (in UNIX, it is [. o] file, which is [. OBJ] file ). This chapter describes some "implicit" rules in makefile, which were previously agreed and do not need to be written again.
"Implicit rules" is also a convention. Make will follow this "Convention" to operate with no such rules. For example [. c] compile the file [. o] File rules, you don't need to write them out at all. Make will automatically export such rules and generate what we need [. o] file.
Implicit Rules use some of our system variables. We can change the values of these system variables to customize the runtime parameters of implicit rules. For example, the system variable "cflags" can control the compiler parameters during compilation.
You can also write your own implicit rules in the form of "pattern Rules. Defining implicit rules with "suffix rules" has many restrictions. The use of "pattern rules" is more intelligent and clear, but "suffix rules" can be used to ensure the compatibility of makefile.
We understand "implicit rules", which can help us better serve us, and also let us know some things that are "customary, instead, we will not see something we think is inexplicable when running makefile. Of course, everything is in conflict, and water can be carried by boat, so sometimes "implicit rules" will also cause us a lot of trouble. Only by understanding it can we better use it.
I. Use implicit rules
If you want to use implicit rules to generate the target, all you need to do is not write the target rule. Then, make will try to automatically deduce the rules and commands that generate the target. If make can automatically deduce the rules and commands that generate the target, then this behavior is the automatic derivation of the implicit rule. Of course, the implicit rule is something that make agreed in advance. For example, we have the following makefile:
Foo: Foo. O Bar. o
CC-O Foo. O Bar. o $ (cflags) $ (ldflags)
We can note that this makefile does not write down the rules and commands for generating the foo. O and bar. O targets. Because the "implicit rules" function of make will automatically deduce the dependent targets and generate commands for the two targets.
Make will search for available rules in its "implicit rules" library. If found, it will be used. If it cannot be found, an error is returned. In the above example, the implicit rule called by make is to set [. O [. c], and use the C compilation command "cc-C $ (cflags )[. c] "to generate [. o. In other words, there is no need to write down the following two rules:
Foo. O: Foo. c
CC-C Foo. C $ (cflags)
Bar. O: bar. c
CC-C bar. C $ (cflags)
Because this is already a "Convention", make and we have agreed on the rules for generating the [. O] file with the C compiler "cc", which is an implicit rule.
Of course, if we write our own rules for the [. O] File, make will not automatically deduce and call the implicit rules, and it will faithfully execute them according to the rules we have written.
Also, in the "implicit rule repository" of make, each implicit rule has its sequence in the library. The more advanced the rule is, the more frequently used it is, this will cause us to ignore make even if we explicitly specify the target dependency. As shown in the following rule (no command ):
Foo. O: Foo. p
Dependent file "foo. P" (the source file of the PASCAL program) may become meaningless. If the "foo. c" file exists in the directory, our implicit rules will take effect, and the foo. o file will be generated by calling the C compiler through "foo. c. Because, in implicit rules, Pascal rules appear after C Rules, make finds the C rule that can generate Foo. O and no longer looks for the next rule. If you really don't want any implicit rule deduction, you don't just write "dependency rules" without writing commands.
Ii. List of implicit rules
Here we will describe all the implicit rules pre-configured (that is, make built-in). If we do not explicitly write the rules, make will search for the required rules and commands in these Rules. Of course, you can also use the "-R" or "-- no-builtin-Rules" parameter of make to cancel all preconfigured implicit rules.
Of course, even if we specify the "-R" parameter, some implicit rules will still take effect, because many implicit rules are defined by the "suffix rule". Therefore, as long as the implicit rule contains a "Suffix List" (that is, a system is defined in the target. suffixes dependency target), then the implicit rule will take effect. The default Suffix List 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. The details are described later.
Let's take a look at common implicit rules first.
1. Compile the implicit rules of the C program.
"<N>. O ", the target's dependency will be automatically deduced as" <n>. C ", and the generated command is" $ (CC)-C $ (cppflags) $ (cflags )"
2. Compile implicit rules for C ++ programs.
"<N>. O ", the target's dependency will be automatically deduced as" <n>. cc or <n>. C ", and the generated command is" $ (cxx)-C $ (cppflags) $ (cflags )". (We recommend that you use ". cc" as the suffix of the C ++ source file, instead of ". c ")
3. Compile the implicit rules of the PASCAL program.
"<N>. O ", the target's dependency will be automatically deduced as" <n>. p, and the generated command is "$ (PC)-C $ (pflags )".
4. Compile the implicit rules of the FORTRAN/ratfor program.
"<N>. O ", the target's dependency will be automatically deduced as" <n>. R "or" <n>. F "or" <n>. F ", and the generated command is:
". F" "$ (FC)-C $ (fflags )"
". F" "$ (FC)-C $ (fflags) $ (cppflags )"
". F" "$ (FC)-C $ (fflags) $ (rflags )"
5. pre-process the implicit rules of the FORTRAN/ratfor program.
The dependency target of the target of "<n>. F" is automatically deduced as "<n>. R" or "<n>. F ". This rule only converts ratfor or pre-processed fortran programs to a standard FORTRAN program. The command used is:
". F" "$ (FC)-F $ (cppflags) $ (fflags )"
". R" "$ (FC)-F $ (fflags) $ (rflags )"
6. Compile the implicit rules of the Modula-2 program.
"<N>. sym is automatically deduced as "<n>. def ", and the generated command is:" $ (m2c) $ (m2flags) $ (defflags )". "<N. o> "the target's dependent target is automatically deduced as" <n>. MOD ", and its generated command is:" $ (m2c) $ (m2flags) $ (modflags )".
7. Compile and compile hidden rules for preprocessing.
"<N>. O ", the target's dependency will be automatically deduced as" <n>. s. By default, the compilation product "as" is used, and its generated command is "$ (AS) $ (asflags )". "<N>. S is automatically deduced as "<n>. s. By default, the C pre-compiler "CPP" is used, and its generated command is: "$ (AS) $ (asflags )".
8. implicit rules for linking object files.
"<N>" depends on "<n>. O ", run the C compiler to run the link Program Generation (generally" LD "). The generated command is:" $ (CC) $ (ldflags) <n>. o $ (loadlibes) $ (ldlibs )". This rule is valid for projects with only one source file and for multiple object files (generated by different source files. For example, the following rule:
X: Y. o z. o
When "x. c", "Y. C", and "Z. c" exist, the implicit rule will execute 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
Rm-f x. o
Rm-f y. O
Rm-f z. o
If there is no source file (X. c) associated with your target name (X in the preceding example), you 'd better write your own generation rules. Otherwise, an error will be reported for implicit rules.
9. implicit rules in yacc c program.
"<N>. C "dependent files are automatically deduced as" N. "Y" (the file generated by YACC). The command is "$ (YACC) $ (yfalgs )". ("YACC" is a syntax analyzer. For details, refer to relevant information)
10. implicit rules for Lex C Programs.
"<N>. C "dependent files are automatically deduced as" N. L "(the file generated by lex). Its command is:" $ (lex) $ (lfalgs )". (For details about "Lex", please refer to relevant materials)
11. implicit rules for Lex ratfor programs.
"<N>. the r dependency file is automatically deduced as "N. L "(the file generated by lex). Its command is:" $ (lex) $ (lfalgs )".
12. Create implicit rules for the lint library from the c program, YACC file, or lex file.
"<N>. ln (lint generated file) dependent file is automatically deduced as "N. c. The generated command is: "$ (lint) $ (lintfalgs) $ (cppflags)-I ". The same rule is true for "<n>. Y" and "<n>. L.
Iii. variables used by implicit rules
Some preset variables are basically used in commands in implicit rules. You can change the values of these variables in your makefile, input these values in the make command line, or set these values in your environment variables, as long as these specific variables are set, they will take effect for implicit rules. Of course, you can also use the "-R" or "-- no-builtin-variables" parameter of make to cancel the effect of your Defined variables on implicit rules.
For example, the first implicit rule-the command for compiling the implicit rule of a C program is "$ (CC)-C $ (cflags) $ (cppflags )". The default compile command of make is "cc". If you change the variable "$ (CC)" to "GCC", change the variable "$ (cflags) then, all the commands in the implicit rule will be executed as "gcc-C-G $ (cppflags.
We can divide the variables used in implicit rules into two types: Command-related variables such as "cc" and parameter-related variables such as "cflags ". The variables used in all implicit rules are as follows:
1. About command variables.
Library package program. The default command is "Ar ".
Compile programs in assembly language. The default command is "".
C language compilation program. The default command is "cc ".
Compile the program in C ++. The default command is "G ++ ".
Extends the file program from the RFM file. The default command is "CO ".
The pre-processor of the C program (the output is a standard output device ). The default command is "$ (CC)-e ".
FORTRAN and ratfor compilers and preprocessing programs. The default command is "f77 ".
The program that extends the file from the SCCs file. The default command is "get ".
Lex method analyzer program (for C or ratfor ). The default command is "Lex ".
Compile the program in Pascal. 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 the texinfo source file (. Texi) to the info file program. The default command is "makeinfo ".
The program that creates the Tex DVI file from the Tex source file. The default command is "Tex ".
Create a program for the military Tex DVI file from the texinfo source file. The default command is "texi2dvi ".
The program that converts web to Tex. The default command is "weave ".
The program that converts C web to Tex. The default command is "cweave ".
A program that converts the Web to the PASCAL Language. The default command is "tangle ".
Convert C web to C. The default command is "ctangle ".
Delete a file. The default command is "RM-F ".
2. Variable about Command Parameters
The following variables are related to the parameters of the preceding command. If the default value is not specified, the default value is null.
Parameters of the Ar command in the library package. The default value is "rv ".
Compilation language compiler parameters. (When the ". s" or ". s" file is obviously called ).
C language compiler parameters.
C ++ language compiler parameters.
The RFM command parameters.
C Preprocessor parameters. (C and FORTRAN compilers will also be used ).
FORTRAN compiler parameters.
SCCs "get" program parameters.
Linker parameters. (For example, "LD ")
Lex syntax analyzer parameters.
PASCAL Compiler parameters.
The Fortran compiler parameter of the ratfor program.
YACC grammar analyzer parameters.
Iv. implicit rule chain
Sometimes, a target may be affected by a series of implicit rules. For example, a [. O] file may be first generated by the YACC [. Y] file into [. C] And then generated by the C compiler. We call this series of implicit rules "implicit rule chain ".
In the preceding example, if the file [. c], then the implicit rule of C's compiler is called directly. If no [. c] file, but there is [. y] file, the implicit rule of YACC will be called to generate [. c] file, and then call the implicit rules compiled by C [. c] generate [. o] file to achieve the target.
We call this [. C] file (or target) An intermediate target. In any case, make will try to automatically derive all the methods for generating the target, regardless of the number of intermediate targets, it will persistently combine all the implicit rules and the rules you write for analysis, if you try to achieve the goal, sometimes it may make you feel strange. How can my goal be generated like this? Why is my makefile crazy?
By default, an intermediate target is different from a general target in two places: The first difference is that the intermediate rule is triggered unless the intermediate target does not exist. The second difference is that as long as the target is successfully generated, the intermediate target file will be deleted with "RM-F.
Generally, a file specified by makefile as a target or dependent on a target cannot be used as an intermediary. However, you can clearly state that a file or target is an intermediary target. You can use the pseudo target ". Intermediate" to force the declaration. (For example,. Intermediate: Mid)
You can also prevent make from automatically deleting intermediate targets. To do this, you can use the pseudo target ". Secondary" to force the declaration (for example,. Secondary: sec ). You can also specify your target in the mode (for example, %. o) become a pseudo-target ". precious "to save the intermediate files generated by implicit rules.
In the implicit rule chain, it is prohibited to appear twice or more times for the same target. In this way, infinite recursion can be prevented during the make automatic derivation.
Make optimizes some special implicit rules without generating intermediate files. For example, from the file "foo. C "generates the target program" foo ". In principle, make will compile and generate the intermediate file" foo. O ", and then linked to" foo ", but in actual circumstances, this action can be completed by a" cc "command (CC-O Foo. c), So optimized rules will not generate intermediate files.
V. Define pattern rules
You can use a pattern rule to define an implicit rule. A pattern rule is like a general rule, but the target definition must contain the "%" character. "%" Indicates one or more arbitrary characters. You can also use "%" in the dependency target, but the value of "%" in the dependency target depends on the target.
Note that the expansion of "%" occurs after the expansion of variables and functions, and the expansion of variables and functions occurs when make loads makefile, the "%" in the mode rule occurs at runtime.
1. Introduction to pattern rules
In a pattern rule, at least "%" must be included in the target definition of the rule. Otherwise, it is a general rule. The "%" definition in the target indicates matching the file name, and "%" indicates any non-null string in length. Example: "%. C "indicates ". C "end of the file name (the file name length must be at least 3), and" s. %. C "indicates" s. "Start ,". the name of the file ending with C (the file name must be at least 5 characters in length ).
If "%" is defined in the target, the value of "%" in the target determines the value of "%" in the dependency target, that is, the "%" of the mode in the target determines the "%" of the dependency target. For example, there is a pattern rule as follows:
%. O: %. C; <command...>
It indicates how to generate the corresponding [. O] File rules from all [. C] files. If the target is "a. o B. O", "% C" is "a. c B. C ".
Once the "%" mode in the dependency target is determined, make will be required to match all the file names in the current directory. Once found, make will rule the commands, in pattern rules, there may be multiple targets. If a pattern matches multiple targets, make will generate all schema targets, make is concerned with the dependent file name and the command to generate the target.
2. Pattern Rule example
The following example shows how to compile all [. C] files into [. O] files.
%. O: %. c
$ (CC)-C $ (cflags) $ (cppflags) $ <-o $ @
"$ @" Indicates the value of all targets, and "$ <" indicates the value of all dependent targets. These strange variables are called "Automated variables", which will be detailed later.
In the following example, two goals are Schema:
%. Tab. C %. Tab. h: %. Y
Bison-d $ <
This rule tells make to put all [. y] All files are named "bison-D <n>. Y "Run and generate" <n>. tab. C "and" <n>. tab. H "file. ("<N>" indicates an arbitrary string ). If our execution program "foo" depends on the file "parse. tab. O "and" scan. O ", and file" scan. O "depends on the file" parse. tab. H ", if" parse. Y "file updated, according to the above rules," bison-D parse. Y "will be executed once, so," parse. tab. O "and" scan. o. (Assume, "parse. tab. O "by" parse. tab. C "generation, and" scan. O "by" scan. C "generation, and" foo "by" parse. tab. O "and" scan. O "link generation, and foo and its [. o] The dependency between files is also written, so all goals will be satisfied)
3. Automated Variables
In the above pattern rules, the target and dependent files are both a series of files. How can we write a command to generate the corresponding targets from different dependent files? This is because every parsing of pattern rules has different targets and dependent files.
Automated variables are used to complete this function. We have mentioned automation variables before. I believe you have a perceptual knowledge of them here. The so-called automatic variables are the variables that automatically extract a series of files defined in the pattern until all files in the pattern are completed. This automation variable should only appear in the Rule command.
The following describes all automation variables:
Indicates the target file set in the rule. In a pattern rule, if there are multiple targets, "$ @" is the set that matches the schema definition in the target.
Only when the target is in the function library file, it indicates the target member name in the rule. For example, if a target is "foo. A (Bar. o) ", then," $ % "is" bar. O "," $ @ "is" foo. A ". If the target file is not a function library file ([. A] in UNIX and [. Lib] in Windows), the value is null.
The first target name in the dependency target. If the dependency target is defined in the mode ("%"), "$ <" is a series of file sets that conform to the mode. Note that it is obtained one by one.
A set of new dependent targets. Separated by spaces.
A set of all dependent targets. Separated by spaces. If there are multiple duplicate dependency targets, the variable will remove the duplicate dependency targets and retain only one copy.
This variable is similar to "$ ^" and is also a set of all dependent targets. It does not remove repeated dependency targets.
This variable indicates "%" and its previous parts in the target mode. If the target is "DIR/. foo. B ", and the target mode is". %. B ", then, the value of" $ * "is" DIR/. foo ". This variable is relatively useful for constructing associated file names. If there is no schema definition in the target, "$ *" cannot be pushed or exported. However, if the suffix of the target file is what make recognizes, then "$ *" is the part except the suffix. For example, if the target is "foo. c", because ". c" is the suffix that can be identified by make, the value of "$ *" is "foo ". This feature is GNU make and may not be compatible with other versions of make. Therefore, you should avoid using "$ *" unless it is in implicit rules or static mode. If the Suffix in the target is not recognized by make, "$ *" indicates a null value.
When you want to operate only the updated dependent files, "$? "It is useful in explicit rules. For example, assume that there is a function library file named" lib ", which is updated by several other object files. The more efficient makefile rule for packaging object files is:
Lib: Foo. O Bar. O lose. o win. o
Ar R Lib $?
In the automatic variable listed above. Four variables ($ @, $ <, $ %, and $ *) only have one file during expansion, and the other three values are a file list. These seven automation variables can also get the directory name of the file or the pattern-compliant file name under the current directory. You only need to match the words "D" or "F. This is a feature of the old version of GNU make. In the new version, we can use the "dir" or "notdir" function. "D" means directory, that is, directory, and "F" means file, that is, file.
The following are the meanings of adding "D" or "F" to the above seven variables:
$ (@ D)
Indicates the directory section of "$ @" (not ending with a slash). If the "$ @" value is "DIR/Foo. O ", then" $ (@ D) "is" dir ", and if" $ @ "does not contain a slash, its value is ". "(current directory ).
$ (@ F)
Indicates the file part of "$ @". If the value of "$ @" is "DIR/Foo. O ", then" $ (@ f) "is" foo. O "," $ (@ f) "is equivalent to the function" $ (notdir $ @)".
"$ (* D )"
"$ (* F )"
As mentioned above, it is also the directory part and file part of the file. For the above example, "$ (* D)" returns "dir", while "$ (* f)" returns "foo"
"$ (% D )"
"$ (% F )"
Indicates the Directory and file of the function package file members. This is useful when "member" in the form of "archive (member)" contains different directories.
"$ (<D )"
"$ (<F )"
The directory and file of the dependent files.
"$ (^ D )"
"$ (^ F )"
Indicates the Directory and file of all dependent files. (None)
"$ (+ D )"
"$ (+ F )"
Indicates the Directory and file of all dependent files. (Can have the same)
"$ (? D )"
"$ (? F )"
Indicates the Directory and file of the updated dependent files.
Finally, we would like to remind you that for "$ <", to avoid unnecessary troubles, we 'd better add parentheses to the specific character after $, for example, "$ (<)" is better than "$ <.
Note that these variables are only used in the Rule command, they are generally "explicit rules" and "static mode rules" (see the previous chapter "Writing Rules ). It does not make sense in implicit rules.
4. Pattern Matching
In general, a target model has a "%" with a prefix or suffix, or does not have a prefix or suffix, and is directly a "% ". Because "%" represents one or more characters, in the defined mode, the content that "%" matches is called "stem", for example "%. C "matched file" test. in C, "test" is "stem ". If "%" is the same between the target and the dependent target, the "stem" of the dependent target will be passed to the target as the "stem" in the target ".
When a pattern match contains a file with a slash (not often included), the directory is removed first and then matched, then add the directory back. We need to know this step when transferring "stems. For example, if there is a mode "E % t", the file "src/eat" matches this mode, so "src/a" is its "stem ", if this mode is defined in the dependency target, and the target mode is "C % R", the target is "src/car ". ("Stem" is transferred)
5. Overload built-in implicit rules
You can reload built-in implicit rules (or define a brand new one). For example, you can reconstruct commands different from built-in implicit rules, such:
%. O: %. c
$ (CC)-C $ (cppflags) $ (cflags)-d $ (date)
You can cancel the built-in implicit rules, as long as you do not write commands later. For example:
%. O: %. s
Similarly, you can redefine a new implicit rule. Its position in the implicit rule depends on where you write the rule. The forward position is on the front.
6. Old-style "suffix rules"
Suffix rules are a relatively old-fashioned method for defining implicit rules. Suffix rules are gradually replaced by pattern rules. Because the pattern rules are stronger and clearer. GNU make is also compatible with makefiles of earlier versions. There are two suffix rules: "dual suffix" and "single suffix ".
The dual-suffix rule defines a suffix: The suffix of the target file and the suffix of the dependent target (source file. For example, ". c. o" is equivalent to "% O: % C ". A single suffix rule defines only one suffix, that is, the suffix of the source file. For example, ". c" is equivalent to "%: %. c ".
The suffix defined in the suffix rule should be recognized by make. If a suffix is recognized by make, this rule is a single suffix rule, if both suffixes are recognized by make, they are the dual-suffix rules. For example, both ". c" and ". O" are known as make. Therefore, if you define a rule ". c. O "then it is a dual-suffix rule, meaning ". C "is the suffix of the source file ,". O "is the suffix of the target file. Example:
. C. O:
$ (CC)-C $ (cflags) $ (cppflags)-o $ @ $ <
Suffix rules do not allow any dependent files. If there is a dependent file, it is not a suffix rule. All suffixes are considered as file names, such:
. C. O: Foo. h
$ (CC)-C $ (cflags) $ (cppflags)-o $ @ $ <
In this example, the file ". c. o" depends on the file "foo. H" instead of what we want:
%. O: %. c Foo. h
$ (CC)-C $ (cflags) $ (cppflags)-o $ @ $ <
In suffix rules, if there are no commands, it is meaningless. Because it does not move built-in implicit rules.
To let make know some specific suffixes, we can use the pseudo target ". suffixes" to define or delete them, such:
. Suffixes:. Hack. Win
Add the suffix. Hack and. Win to the end of the Suffix List.
. Suffixes: # Delete the default suffix
. Suffixes:. C. O. h # define your own suffix
First clear the default suffix, and then define your own Suffix List.
The default Suffix List used by the make parameter "-R" or "-no-builtin-Rules" is also null. The variable "suffixe" is used to define the default Suffix List. You can use ". suffixes" to change the Suffix List, but do not change the value of the variable "suffixe.
VII. implicit rule Search Algorithm
For example, we have a target called T. The following is an algorithm used to search for the rules of the target T. Note that the suffix rules are not mentioned below because all suffix rules are converted to the mode rules when makefile is loaded into memory. If the target is the file mode of the "archive (member)" function library, this algorithm will be run twice. The first time it is to find the target T. If it is not found, it will enter the second time, for the second time, "member" will be searched as T.
1. Separate the directory of T. D, while n. (For example, if T is "src/Foo. O", D is "src/", and N is "foo. O ")
2. Create a list Of all pattern rules matching T or N.
3. If there is a pattern matching all files in the Pattern Rule List, such as "%", remove other pattern from the list.
4. Remove the rule without commands from the list.
5. For the first schema rule in the list:
1) deduce its "stem" S. S should be T or n that matches the "%" non-null part in the pattern.
2) computing dependent files. Replace "%" in the dependency file with "stem" s. If the target mode does not contain the oblique box character, add D to the beginning of the first dependent file.
3) test whether all dependent files exist or are rational. (If a file is defined as the target file of another rule, or a dependency file of an explicit rule, this file is called "")
4) if all dependent files exist or exist, or no dependent files exist. This rule will be used to exit the algorithm.
6. If no Pattern Rule is found after step 1, perform further search. For the first schema rule that exists in the list:
1) if the rule is terminated, ignore it and continue with the next Pattern Rule.
2) computing dependent files. (Same as step 1)
3) test whether all dependent files exist or check if they exist.
4) for non-existing dependent files, recursively call this algorithm to find whether they can be found by implicit rules.
5) If all dependent files exist or exist, or there is no dependency file at all. Then this rule is used to exit the algorithm.
7. If there is no implicit rule, you can use it. view the ". Default" rule. If yes, use the ". Default" command to T.
Once the rule is found, it will execute its equivalent command. At this time, the value of our automated variable will be generated.