1. makefile rules
Makefile is a make rule description script file, which includes four types of lines: Target Line, command line, macro definition line, and make pseudo command line (such as "include "). The comments in the makefile file start. When a row cannot be written, you can use the "\" symbol to transfer it to the next row.
1.1 target row
The target row tells make what to create. It consists of a target table followed by a colon ":" And a dependency table.
Example:
Example: depfile deptarget
The target row indicates that the target example is dependent on depfile and deptarget. If depfile or deptarget is modified, the target is regenerated.
Example1 example2 example3: deptarget1 deptarget2 depfile
The target row indicates that the independent targets example1, example2, and example3 in the target table are generated using the same dependency list and rules.
Clean:
The empty dependency list indicates that the target clean has no other dependency.
The row starting with a Tab next to the target row indicates the generation rule of the target. The Tab character cannot be replaced by a space. For example:
Example. o: example. c example. h
Cc-c example. c
This example shows that the target example. o depends on example. c and example. h. If one of example. c or example. h is changed, run the cc-c example. c command to regenerate the target example. o.
You can use the file name pattern matching to automatically generate a dependency table for the target, for example:
Prog: *. c
The following is an example of a simple makefile:
Figure 1 simplest makefile example
Make uses makefile to start scanning from the first target. In the preceding example, the first target is all, so the target clean is not automatically executed. You can use the make clean command to generate the target.
1.2 command line
The command line defines the actions for generating the target.
In the target line, the semicolon ";" is regarded as a command, or a line that starts with a Tab is also a command.
For example, in the makefile example above, the cc command starting with the Tab character in the third line is a command line, which indicates the command to be generated for hello. It can also be written as: hello. o; cc-c hello-L...
Generally, the command line is highlighted in the standard output. For example, when the makefile is executed on the above makefile, the standard output is as follows:
Cc-c hello. c
Cc-o hello-L/usr/X11R6/lib-L/usr/lib-lXm-lXt-lX11 hello. o
Cc-c hello1.c
Cc-o hello1-L/usr/X11R6/lib-L/usr/lib-lXm-lXt-lX11 hello1.o
If you do not want the command to echo itself, add the @ character before the command. For example, you do not want to echo cc-c hello. c and cc-c hello1.c. You can modify the makefile file as follows:
Figure 2 makefile example for suppressing echo
When you execute make on the makefile, the standard output is as follows:
CC-O hello-L/usr/x11r6/lib-L/usr/lib-lxm-lxt-lx11 hello. o
CC-O hello1-L/usr/x11r6/lib-L/usr/lib-lxm-lxt-lx11 hello1.o
We can see that the @ character is not displayed in front of the command line.
1.3 macro definition line
In makefile, you can use macro definitions to reduce user input, for example, in the above example, the compilation options for hello and hello1 are "-l/usr/x11r6/lib-L/usr/lib-lxm-lxt-lx11", which can be replaced by a macro, for example:
Figure 3 makefile example with macro definition
The basic syntax of macro definition is:
Name = Value
Order is not important when macro is defined. Macros do not need to be defined before use. If a macro is defined multiple times, the last defined value is used.
You can use the "$" character and "()" or "{}" to reference macros. For example:
CC-O hello. o $ (ccflags) Hello. o
You can also assign a macro value to another macro, but such a definition cannot be nested cyclically, for example:
A = value1
B = value2
C = $ (a) $ (B) is equivalent to C = value1 value2
1.4 pseudoinstructions
Makefile consists of macro-defined lines, command lines, and target lines. The fourth type is the make command line. The make command is not standardized. Different make commands may support different sets of pseudo commands, which makes makefile incompatible. If you want to consider portability, avoid using the make pseudo command. However, some pseudocommands, such as include, are provided by many different make statements.
1.4.1 pseudocommand include
This pseudo-command is similar to # include in C, which allows you to write common definitions at a time and include them. The include Directive must be in a row. The first element must be include and be followed by a file name to be included, such:
Include default. mk
1.4.2 pseudocommand "#"
The "#" character is also a pseudo command of make. It indicates that the file after "#" is a comment, such:
PROGNAME = test # define macro
# Don't modify this
Two-suffix rules
2.1 dual suffix rules
In the previous makefile example, there are a lot of repeated content. For example, the command to generate hello and hello1 is similar to that to generate hello. the commands for o and hello1.o are similar. Except for files with different compilation or links, they are all the same. In this case, we can use suffix rules. First, let's look at an example of Dual-Suffix:
Figure 4 makefile example using dual-suffix rules
The suffix rule uses the special target name ". SUFFIXES ".
In the first line. the SUFFIXES dependency table is empty to clear the original suffix rules, because. SUFFIXES can be used multiple times in makefile. Each time a new suffix rule is added to a previous suffix rule.
In the second row, specify the suffix rule as ". c. o", which means to convert all. c files to. o files.
The third line specifies the method to convert the. c file to the. o file. $ (CC) is a pre-defined macro of make. Its default value is cc. $ <is a special macro, which replaces the current source file, that is, all. c files to be compiled.
The sixth line specifies the generation method of the target hello and hello1. $ @ Is a special macro that replaces the current target name, namely hello and hello1, $ @. o is hello. o and hello1.o.
The above example describes the dual-suffix rule, that is, it contains two suffixes, such as. c. o, which is used to compile a C source file as the target file. The dual-suffix rule describes how to generate a second file with a suffix type from the first file with a suffix type. For example, the. c. o rule describes how to generate a. o file from a. c file.
2.2 single suffix rules
A single suffix rule describes how to generate a file named by its base name from a file with the specified suffix. For example, if the single suffix rule. c is used, the hello and hello1 files can be generated by hello. c and hello1.c. For example, change the previous makefile:
Figure 5 makefile example using a single suffix rule
Because the. c suffix rule is the make standard suffix rule, make specifies the corresponding command line for it. Therefore, you do not need to specify the specific command line generated by the target in makefile.
The following table lists the standard suffix rules provided by make.
Table 1 make standard suffix rules
Suffix rule command line
. C $ (LINK. c)-o $ @ $ <$ (LDLIBS)
. C. ln $ (LINK. c) $ (poutput optput option)-I $ <
. C. o $ (COMPILE. c) $ (output option) $ <
. C. a $ (COMPILE. c)-o $ % $ <
$ (AR) $ (ARFLAGS) $ %
$ (RM) $ %
Three special objectives
The special target. SUFFIXES is used in the suffix rule to specify the new suffix rule. Make also provides several special targets for setting make behaviors. The following are some special targets:
? . IGNORE
When running the command, if the error code is returned, make stops and exits by default. After the target is added, make ignores the error code returned by the command line and continues to perform subsequent operations.
? . SILENT
As mentioned earlier, make will display the contents of the command line when executing the command line. Adding the "@" character before the command line will suppress the echo of the command line.
If this target is added, all command lines are no longer displayed, which is equivalent to adding the "@" character before each command line.
? . PRECIOUS
When you receive a signal or return a non-zero error code from the shell command, make deletes all created files. However, even if an error occurs in some files, the user does not want make to delete them. These files can be used as parameters of the. PRECIOUS target. It can appear multiple times in a makefile, accumulating a list of files each time.
? . SUFFIXES
It specifies a new suffix rule for makefile, and the new suffix rule is provided as the dependency table of. SUFFIXES .. SUFFIXES can be used multiple times in a makefile. Each time a new suffix rule is added to a previous suffix rule, if. if the dependency table of SUFFIXES is empty, the suffix rule table is empty.
Four special macros
For simple use rules, make provides several special macros:
? $ @
The value of the current target name can be replaced by the macro "$.
? $ <
The current source file is replaced by "$ <. For example, in the previous example, $ (CC)-c $ <is used, where "$ <" is all. c files to be compiled. The macro "$ <" is only valid in the suffix rule or. DEFAULT.
? $ *
The base name of the current target is replaced by the macro "$. For example, if the target name is hello. o, the base name is "hello" with the suffix. o removed.
The special macros described above use the make rules, which cannot be changed. The following table describes the pre-defined Macros in C.
Use macro Default Value
Library Document Assembly command AR ar AR
ARFLAGS rv
AS
ASFLAGS
COMPILE. s $ (AS) $ (ASFLAGS) $ (target arch)
C compiler command CC cc
CFLAGS
CPPFLAGS
COMPILE. c $ (CC) $ (CFLAGS) $ (CPPFLAGS) $ (target arch)-c
LINK. c $ (CC) $ (CFLAGS) $ (CPPFLAGS) $ (LDFLAGS) $ (target arch)
Link editor command LD ld
LDFLAGS
Rm command RM rm
SUFFIXES. o. c. c ~ . S. s ~ . S. S ~ . Ln. f. f ~ . F. F ~ . L. mod. mod ~ . Sym
. Def. def ~ . P. p ~ . R. r ~ . Y. y ~ . H. h ~ . Sh. sh ~ . Cps. cps ~
5. makefile Application
When you call make, it searches the current directory for a file named "makefile" or "Makefile" and runs the command.
If you do not want to use the above default file, you can use "-f" in the command line to specify the file. For example, if you name the makefile written as mklib, you can specify it as "make-f mklib ". 1. make compares the last modification time of the corresponding file (Rule target and dependency) to determine which files need to be updated and those files do not need to be updated. For files to be updated, make will execute the corresponding commands recorded in the database (a database describing the compilation process will be created after make reads the Makefile. This database records the relationships between all files and Their Relationship descriptions) to recreate it. make does not do anything for files that do not need to be rebuilt.
2. During writing, a long line can be decomposed into multiple lines by a backslash (\). This can make the Makefile clear and easy to read. Note: No space is allowed after the backslash!
3. In actual work, we agree that the following variables are used: "objects", "OBJECTS", "objs", and "OBJS. o file list replacement. Use this variable to replace the list of these files. For example, if the variable "OBJS" is defined, you can use "$ (OBJS)" as needed to represent it. 4. automatic deduction rules: make can automatically compile the. c file and generate the corresponding. o file. This is an implicit rule of make.
5. Recommended writing rules: single-target, multi-dependency. That is to say, try to make sure that only one target file exists in a rule and multiple dependent files exist. Avoid multiple targets as much as possible. In this way, the later maintenance will be very convenient, and the Makefile will be clearer and clearer.
6. A complete Makefile contains five parts: Display rules, implicit rules, variable definitions, indicators, and comments.
7. A Makefile can contain other Makefile files, which are implemented using the keyword include. This is consistent with the Inclusion Method of the C-language file. The include indicator tells make to stop reading the current Makefile, and transfers it to one or more files specified by include, and then continues reading the current Makefile. The Makefile indicator include is written in an independent line in the following format:
Include FILENAMES
FILENAMES is a file name supported by shell (wildcards can be used ). The line containing the indicator include can start with one or more spaces (make will ignore these spaces during processing), but remember not to start with the [TAB] character.
8. make: For an existing rule (clear rules and implicit rules), the make program compares the timestamps of the target file and all dependent files. If the target timestamp is updated than the timestamp of all dependent files, nothing will be done. Otherwise, if one or all of the dependent files have been modified after the previous make execution, the command for recreating the Target defined in the rule will be executed. This is the basis of make and the basis for the commands defined by its execution rules.
9. In the rule, the wildcard is automatically expanded, but the wildcard is not automatically expanded when the variable is defined and the function is used. If the Makefile contains the following sentence: "objects = *. o", the value of the variable objects is "*. o", rather than the list of all. o files separated by spaces. If the variable "objects" is required to represent all. o files, use the wildcard function to implement bjects =$ (wildcar *. o ). The usage of the function wildcard is: $ (wildcard PATTERN ...). In Makefile, it is expanded into a list of all existing files that are separated by spaces and match this mode. If no file meets this mode, the function ignores the mode and returns NULL.
10. In Makefile, if multiple executable programs need to be created under a directory, we can describe the reconstruction rules of all programs in a Makefile. Because the first goal in Makefile is the "ultimate goal", the agreed approach is to use a pseudo goal called "all" as the ultimate goal, and its dependent files are the programs to be created.
# Sample Makefile
All: prog1 prog2 prog3
. PHONY: allprog1: prog1.o utils. o
$ (CC) $ (CFLAGS) $ ^-o $ @ prog2: prog2.o
$ (CC) $ (CFLAGS) $ ^-o $ @ prog3: prog3.o sort. o utils. o
$ (CC) $ (CFLAGS) $ ^-o $ @
When you need to update a program separately, you can use the make command line option to specify the program to be rebuilt.
11. make has an embedded implicit variable "RM", which is defined as "RM = rm-f". Therefore, you can use $ (RM) for the command line when writing the clean rule) to replace rm, which can avoid unnecessary troubles. This is a recommended practice.
12. If the command to be executed starts with the character "@", make will not display the command during execution. A typical usage is when we use the echo command to output some information, such:
@ Echo "starting"
Therefore, you can use @ to control command echo when writing Makefile.
13. In a rule, when the target needs to be rebuilt, the command defined in the rule will be executed. If it is a multi-line command, make uses an independent sub-shell to execute each line of command. Therefore, the execution of multi-line commands is independent of each other and there is no dependency between them. Multiple commands written in the same line in Makefile belong to a complete shell command line, so note: In a rule command, changing the directory on command line cd does not affect subsequent command execution. That is to say, the working directory of the subsequent command execution is not the directory that was previously entered by using cd. To achieve this goal, you cannot write the cd and the subsequent commands in two lines. Instead, you should write the two commands on one line and separate them with semicolons. In this way, they are a complete shell command line. If you want to write a complete shell command line book on multiple lines, you need to use a backslash to connect the commands in multiple lines, indicating that they are a complete shell command line.
14. recursive call of make
In Makefile, use "make" as a command to execute itself or other makefile files. Recursive calling is very useful in a project with multi-level sub-directories.
Subsystem:
Cd subdir & $ (MAKE)
Equivalent
Subsystem:
$ (MAKE)-C subdir
This means to enter the subdirectory, and then execute make under the subdirectory.
15. make can customize command packages
When writing Makefile, multiple rules may use the same set of commands, just like the printf function that is frequently used in C language programs. You can encapsulate a group of commands similar to C-language functions. In the future, you can reference the group of commands by their names. This can reduce repetitive work and improve efficiency. In GNU make, you can use the indicator define to complete this function. Generally, a set of commands defined by define can be used as a command package. The syntax for defining a command package starts with define and ends with endef.
Define run-yacc
Yacc $ (firstword $ ^)
Mv y. tab. c $ @
Endef
In this way, run-yacc is the name of the command package. The command between define and endef is the main body of the command package. In the command package defined by define, variables and function references in the command body are not expanded. All the content in the command body, including $, is defined by the variable run-yacc. It is used in the same way as a macro in C language.
Usage:
Foo. c: foo. y
$ (Run-yacc)
16. differentiate variables in Makefile and shell.
Makefile single-character reference can be $ x $ (x) $ {x. Multi-character reference $ (xx) $ {xx }.
In shell, variables are referenced in two forms: $ {xx} $ xx.
Generally, when writing Makefile, we recommend that you reference the following formats for each part of variables:
(1) make variables (variables defined in Makefile or make environment variables) are referenced in the $ (VAR) format, whether VAR is a single-character variable name or a multi-character variable name.
(2) The shell variable that appears in the Rule command line (usually a temporary variable during command execution, which is not a Makefile variable but a shell variable) references the $ tmp format of shell.
(3) make variables in the command line are also referenced in the $ (CMDVAR) format.
17. Use directly expanded variables instead of recursive variables.
18. As a good programmer, in the face of a complex problem, we should seek a solution that is as simple, direct, and efficient as possible, rather than complicate the implementation of a simple problem. If you want to highlight your proficiency in a certain language on a simple question, it is a very stupid and immature behavior.
19. Can I assign a value to a variable that has not been defined before? =. If you want to append the value of a common variable, use + =.