2.3 make tool and makefile
Make is a very important compilation tool in both Linux and UNIX environments. Make is required for project development and application software installation. With the make tool, large development projects can be divided into multiple modules that are easier to manage. For an application that contains hundreds of source files, you can use the make tool and makefile to straighten out the relationship between each source file. In addition, if so many source files need to be compiled by entering the gcc command every time, it is hard for programmers to endure. The make tool can automatically complete compilation, and only compile the part modified by the programmer after the last compilation. Therefore, effective use of the make tool can greatly improve the efficiency of project development.
2.3.1 Introduction to make
1. How make works
The most basic function of the make tool is to call the makefile file to describe the dependency between source programs and automatically maintain the compilation. Of course, the makefile file needs to be compiled according to certain syntax. It needs to explain how to compile each source file and generate an executable file and define the dependency between the source files. Makefile is a common method for many compilers (including compilers in Windows) to maintain compilation information. In the integrated development environment, you can modify the makefile file on a friendly interface.
For example, if there is a file named "makefile" under the current target, its content is as follows (the syntax structure of this file will be described in the following content ):
# It is a example for describing makefile
Edit: main. o kbd. o command. o display. o insert. o search. o files. o utils. o // top-level dependency
Cc-o edit main. o kbd. o command. o display. o insert. o search. o files. o utils. o
Main. o: main. c defs. h // main. c dependency
Cc-c main. c // compiled
Kbd. o: kbd. c defs. h command. h // kdo. c dependency
Cc-c kbd. c
Command. o: command. c defs. h command. h
Cc-c command. c
Display. o: display. c defs. h buffer. h
Cc-c display. c
Insert. o: insert. c defs. h buffer. h
Cc-c insert. c
Search. o: search. c defs. h buffer. h
Cc-c search. c
Files. o: files. c defs. h buffer. h command. h
Cc-c files. c
Utils. o: utils. c defs. h
Cc-c utils. c
Clean: // the operation that the make clean command will execute
Rm edit main. o kbd. o command. o display. o insert. o search. o files. o utils. o
This description file is a simple makefile file. In this example, the behavior comment line with the first character # is used. The first non-Comment row specifies that the edit object is specified by the target file main. o, kbd. o, command. o, display. o, insert. o, search. o, files. o, utils. o connection generation, which only indicates a dependency. The third line describes how to create an executable file from the file on which edit is dependent, that is, the command cc-o edit main. o kbd. o command. o display. o insert. o search. o files. o utils. o, that is, the gcc compilation is called. o file Generation edit executable file. The following even lines specify the. c and. H files on which each target file depends. The odd line that follows the dependency relationship specifies how to create a target from the file on which the target depends.
By default, enter the "make" command in the current directory prompt. The system will automatically complete the following operations.
(1) The make tool searches for files named "Makefile" or "makefile" in the current directory, the GNU Make tool searches the current working directory for makefile execution files in the order of GNUmakefile, Makefile, and makefile.
(2) If it is found, it will find the first target file in the file. In the above example, the system will find the target "edit, and use this file as the final target file.
(3) If the edit file does not exist, or. o file modification time is later than the edit file, then the system will execute the command defined later to generate the edit file.
(4) If. o file does not exist, so the make tool will find the target in the current file. o file dependency. If found, it is generated according to this rule. o file.
(5) If *. C file and *. H files exist, so the make tool will first generate. o file, and then use. o file generation executable file edit.
This is the dependency of the make file. make will find the dependency of the file layer by layer until the first target file is finally compiled. During the search process, if an error occurs, for example, the dependent file is not found, make will directly exit and report an error. Make does not check the errors of the defined commands.
In general, the makefile file also defines the clean object, which is a pseudo object (which will be described in detail in subsequent sections). It can be used to clear intermediate files generated during the compilation process, for example, clearing the content in the previous example:
Clean:
Rm edit main. o kbd. o command. o display. o insert. o search. o files. o utils. o
The simpler method is:
Clean:
Rm-f *. o
In the makefile file above, clean is not directly or indirectly associated with the first target file, and the commands defined after it will not be automatically executed. However, you can run the "make clean" command in the command to clear all target files for recompilation.
2. make command
The make command can contain four optional parameters: Flag, macro definition, description file name, and target file name. The standard format is:
Make [flags] [macro] [definitions] [targets]
(1) The flags option and its meaning are as follows.
-F file: Specifies the file as the description file. If the file parameter is a "-" character, the description file points to the standard input. If the "-f" parameter is not specified, the makefile or Makefile file in the current directory is used as the description file by default. If you want to use other files as makefile files, you can use the following make Command Options to specify.
$ Make-f filename
-I: Ignore the error message returned by the command execution.
-S: silent mode. No command line information is output before execution.
-R: Do not use the build-in rule.
-N: in non-execution mode, all execution commands are output but not executed.
-T: update the target file.
-Q: The make operation returns the status information of "0" or not "0" based on whether the target file has been updated.
-P: output the description of all macro definitions and target files.
-D: Debug mode, which outputs detailed information about the file and detection time.
-C di: change to the specified directory dir before reading makefile.
-I dir: used to specify the search directory when other makefile files are included.
-H: help text block. All make options are displayed.
-W: the working directory is displayed before and after makefile processing.
(2) There are two macro definitions. One is to define the macro in the makefile file, and the other is to directly input the macro definition in the command line when using the make command (if the macro is the same as the macro in the makefile file, it will replace the macro in the makefile file ).
When referencing a macro in the makefile file, you only need to add the $ symbol before the variable. If the length of the variable name exceeds one character, you must add parentheses "()" When referencing the variable "()". The following are valid macro references:
$ (CFLAGS)
$ Z
$ (Z)
The last two references are the same. The following are examples of macro variables.
# Define a macro for the object files
OBJECTS = filea. o fileb. o filec. o // define the "OBJECTS" variable
# Define a macro for the library file
LIBES =-LS // defines the "LIBES" variable
# Use macros rewrite makefile
Prog: $ (OBJECTS) // reference the "OBJECTS" variable
Cc $ (OBJECTS) $ (LIBES)-o prog // reference "OBJECTS" and "LIBES" Variables
......
If you execute the make command without parameters, it will call GCC to connect three target files and the library file LS to generate the executable file prog. If the make command has a new macro definition:
Make "LIBES =-LL-LS"
The macro definition after the command line overwrites the macro definition in the makefile file. If LL is also a library file, the make command will connect the three target files and the LS and LL library files.
(3) The target parameter is used to specify the target file to be compiled by the make command, and multiple compilation objects can be defined at the same time. During the operation, the target files are compiled sequentially from left to right. If the target file is not specified in the command line, the system points target to the first target file in the description file by default.
Generally, the makefile file has several preset targets for use. The following commands should be used.
Make all: compile all targets. Or enter make only. At this time, the source code is compiled, connected, and an executable file is generated.
Make clean: Clear the previously compiled executable files and target files (object file, *. o ).
Make distclean: In addition to clearing executable and target files, Makefile files are also cleared.
Make install: install the program to the system. If the source code is compiled correctly and the execution result is correct, you can install the program to the preset path where the execution file is stored. If bin_PROGRAMS is used, the program will be installed in the/usr/local/bin directory.
Make dist: Package programs and related files into a compressed file for release. After the execution, a file named packageversion.tar.gz will be created under the current directory.
2.3.2 makefile common rules
The makefile file contains five items: explicit rules, concealed rules, macro definitions, file instructions, and annotations.
(1) explicit rules. Explicit rules describe how to generate one or more target files. This is clearly pointed out by makefile writers, including the command to generate the dependent files required for the target file, and to generate the target file. For example:
Foo. o: foo. c defs. h # foo Module
Cc-c-g foo. c
Foo. o is the target, foo. c and defs. h is the source file on which the target depends. The command is "cc-c-g foo. c "(This line must start with the Tab key ). This rule includes the following two main contents:
File dependency: foo. o depends on foo. c and defs. h file, if foo. c and defs. the file date of h is later than that of foo. o new, or foo. o does not exist, so the dependency occurs.
The cc command shows how to generate the foo. o file.
(2) concealed rules. Because make has the automatic derivation function, it determines whether the source file needs to be re-compiled and the compiling sequence between the source files based on the dependency. Therefore, the concealed rules allow programmers to easily write makefile files.
(3) macro (variable) Definition. In makefile, You need to define a series of macros (variables). Macros (variables) are generally strings, similar to Macros in C language. When makefile is executed, all the variables in the makefile will be extended to the corresponding reference location. This content is described in the previous section.
(4) file instructions. It consists of three parts: one makefile file references another Makefile file, just like the include in the C language; it specifies the valid part of The makefile according to certain situations, just like the pre-compiled # if statement in C, it defines multi-line commands.
(5) annotations. Makefile only contains line comments. Like a UNIX Shell script, the comments start with the "#" character, similar to "//" in C/C ++ "//". If you want to use the "#" character in makefile, you must use a backslash to escape it, for example :"\#".
When writing each part of the content, you can use the following method.
1. Use wildcards
Make supports three wildcards: "*" and :"*","? "And" [] ". This is the same as B-Shell. Tilde ("~ ") Characters are also used in file names, for example "~ /Test ", which indicates the test directory under the $ HOME directory of the current user.
Wildcards are used to replace a series of contents. For example, "*. c" indicates all files suffixed with. c. Note that if the file name contains wildcards, such as "*", you must use the Escape Character "\", such as "\ *" to indicate the real "*" character.
Wildcard characters can be used in display rules, such:
Print: *. c
The target print depends on all. c files.
Wildcards are also available in variables, such:
Objects = *. o
The value of objects is "*. o ".
2. Search by file
In a large project, there will be a large number of source files, which are usually stored in different directories. Therefore, when make needs to find the file dependency, it can add a path before the file, but the best way is to tell make the path so that make can perform automatic search. The special variable "VPATH" in the makefile file is used to complete this function. If this variable is not specified, make will only search for dependent files and target files in the current directory. If this variable is defined, make automatically searches the specified directory if no relevant file is found in the current directory.
VPATH = src: ../headers
This Code specifies two directories: "src" and "../headers". make searches in this order. Separate Directories With a colon.
Another way to set the file search path is to use the "vpath" keyword of the make command (note that it is in lower case). This is similar to the VPATH variable, but it is more flexible. It can be used to search for different files in different directories. This is a flexible feature. It can be used in three ways:
Vpath <pattern> <directories>: Specifies the search directory for pattern-compliant files.
Vpath <pattern>: clears the file search directory that meets the pattern <pattern>.
Vpath: clears all configured file search directories.
<Pattern> specifies the file set to be searched. <pattern> it must contain the "%" character. "%" Indicates matching one or more characters, for example:
"%. H
Indicates all files ending with ". h.
<Directories> specifies the search directory of the <pattern> file set. For example:
Vpath %. h ../headers
The make command is required to search all files ending with ". h" in the "../headers" Directory (if the file is not found in the current directory ).
Programmers can use the vpath statement consecutively to specify different search policies. If the same <pattern> or repeated <pattern> exists in a continuous vpath statement, make executes the search in the order of the vpath statement. For example:
Vpath %. c foo
Vpath %. c blish
Vpath %. c bar
Objects ending with ". c" are first searched under the "foo" folder, then searched under the "blish" folder, and finally searched under the "bar" folder.
3. Description of pseudo targets
As mentioned above, the clean pseudo-target syntax is as follows:
Clean:
Rm *. o temp
Clean is not a file, but a pseudo-target. Since "pseudo-target" is not a file, make cannot generate its dependency and decide whether to execute it. Therefore, you must explicitly specify this "target" to make it take effect. This requires that the pseudo-target cannot be the same as the file name. To avoid invalid objects due to duplicate file names, you can use a special mark ". PHONY" to explicitly specify a target as a "pseudo target ". That is, to explain to the make command, whether or not this file exists, this target is a "pseudo target ". Syntax:
. PHONY: clean
Clean:
Rm *. o temp
If you run the make clean command, the rm *. o temp command will be executed.
Generally, the pseudo-target does not depend on the file. However, you can also specify the dependent file for the pseudo-target. A pseudo-target can also be used as the "Default target", as long as it is placed in the first one. For example, the Makefile file needs to generate several executable files, but the user just wants to simply knock on a make command, and all target files are written in a makefile file, in this case, you can use the "pseudo target" 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.o
Prog3: prog3.o sort. o utils. o
Cc-o prog3 prog3.o sort. o utils. o
". PHONY: all" declares that "all" is a "pseudo target ". The first target in makefile will be used as its default target. Here we declare the pseudo-target of "all", which depends on the other three. Because pseudo targets are always executed, the three targets on which they depend are always newer than "all. Therefore, rules for the other three goals are always executed.
References:
[1] linux advanced programming [books]