(Reproduced) Write Makefile with me

xiaoxiao2021-03-06  105

Reprinted on http://blog.9cbs.net/haoel/ Write Makefile Chen Hao with me - What is makefile? Perhaps many of WinodWs's programmers don't know this, because those Windows IDE has done this job, but I think it is necessary to make a good and Professional programmer, makefile still wants. This seems to have so many HTML editors, but if you want to be a professional, you still have to understand the meaning of HTML's identity. Especially in UNIX software, you can't write makefile yourself, will not write makefile, from one side, explain whether a person has the ability to complete large-scale projects. Because Makefile is related to the compilation rules of the entire project. Source files in an engineering are not countful, which are placed in a number of directorys according to the type, function, and modules. Makefile defines a series of rules to specify, which files need to be compiled first, which files need to be compiled, which files need to be re- Compile, even more complex functional operations, because Makefile is like a shell script, which can also perform commands of the operating system. The benefits brought by makefile are - "Automated Compilation", once written, only one make command, complete automatic compilation, greatly improve the efficiency of software development. Make is a command tool that is a command tool that explains the command in Makefile. In general, most of the IDE has this command, such as: Delphi Make, Visual C NMAKE, Linux GNU Make. It can be seen that Makefile has become a compilation method in engineering. Now telling how to write Makefile's article is relatively small, this is the reason I want to write this article. Of course, the Make of different organizers is different, and there are different grammar, but their essence is in "document-dependent", here, I only tell the GNU's Make, my environment is Redhat Linux 8.0, Make's version is 3.80. By, this make is the most widely used and the most used. And it is still the most follow-in (POSIX.2) of IEEE 1003.2-1992. In this document, it will be based on the source code of C / C as our foundation, so it will inevitably involve knowledge of compilation of C / C , related to this, please check the relevant compiler documents. The compiler default here is GCC and CC under UNIX. About the program compilation and link ---------- Here, I think more about the specifications and methods of the program compilation. In general, whether C, C , or PAS, first of all to put the source file Compiled into an intermediate code file, it is .Obj file under Windows, UNIX is .o file, ie Object File, this action is called compilation. Then use a lot of Object File synthesizes the execution file, this action is a link (LINK). When compiling, the compiler needs the correctness of the syntax, the function of the function and the variable declaration. For the latter, it is usually the location you need to tell the compiler header file (the header should just declare, and the definition should be placed in the C / C file), as long as all the syntax is correct, the compiler can compile the intermediate target. file.

In general, each source file should correspond to an intermediate target file (O file or OBJ file). When linking, primarily link functions and global variables, so we can use these intermediate target files (O files or OBJ files) to link our applications. The linker does not manage the source file where the function is located, only the intermediate target file (Object file) of the function, in most, because the source file is too much, there are too many intermediate target files generated, and the middle is clearly pointed out in the link. The target file name, this is very inconvenient, so we have to make a package to the middle target file, which is called "library file" under Windows, that is, the .lib file, under UNIX, is Archive file, that is, .a file. Summary, the source file will generate an intermediate target file and then generate an execution file by the intermediate target file. At compiler, the compiler only detects the program syntax, and the function, whether the variable is declared. If the function is not declared, the compiler gives a warning, but can generate Object File. When the linker, the linker finds the implementation of a function in all Object File. If you can't find it, you will report the link error code (Linker Error), under VC, this error is generally: Link 2001 Error, meaning, the linker failed to find the implementation of the function. You need to specify the Object File of the function. Hello, the return of the gnu is a lot of content, how to get less, let us start. Makefile Presentation ------- Make Commands When you execute, you need a Makefile file to tell the make command to compile and link programs. First, we use an example to illustrate the writing rules of Makefile. In order to give you a real understanding. This example comes from the GNU's Make User Manual, in this example, our project has 8 C files, and 3 head files, we have to write a Makefile to tell the make command how to compile and link these files. Our rules are: 1) If this project is not compiled, all of our C files should be compiled and linked. 2) If a few C files in this project are modified, then we only build the modified C file and link the target program. 3) If the header file of this project is changed, then we need to compile C files that reference these header files and link the target program. As long as our makefile is well written enough, all of this, we can complete with a make command, and the make command will automatically intelligently determine which files need to be recompiled according to the current file modification, so that they need to compile it. Files and link target programs. 1. Makefile's rules before telling this makefile, let's take a look at the rules of Makefile first. Target ...: prerequisites ... command ... Target is also a target file, which can be Object File or a executable file. It can also be a label, which is a narrative in subsequent "Pseudo Target" chapters for labels.

Prerequisites is to generate the files required by Target or target. Command is also a command that make Make needs to be executed. (Any shell command) This is a dependency of a file, that is, Target This or more target files depend on the file in Preequisites, which generates rules defined in Command. To put it bluntly, if there is more than one file in Prerequisites, the command defined by Command is executed more than the TARGET file. This is the rule of Makefile. That is, the core content in Makefile. When I said, Makefile's thing is like this, as if I have this document. Ha ha. Not too, this is the main line and core of Makefile, but it is not enough to write a makefile. I will slowly come to you later. The content is more. :) Second, one example is as mentioned earlier, if a project has 3 head files, and 8 C files, in order to complete the three rules mentioned earlier, our makefile should be the following. Edit: main.o kbd.o command.o display.o / insert.o search.o files.o utils.o 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 cc -c main.c kbd.o: kbd.c defs.h command.h cc -c kbd.c command.o: Command.c DEFS. H command.h cc - Command.c Display.o: display.c defs.h buffer.h cc - Cd 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: rm edit main.o kbd.o command.o display.o / insert.o search.o files.o utils.o backslash (/) is the meaning of change. This is more convenient for Makefile easy to read. We can save this content in a file that "makefile" or "makefile", and then enter the command "make" directly in this directory to generate an execution file Edit. If you want to delete the execution file and all intermediate target files, then just make "make clean" as long as you do it. In this makefile, the target file (target) contains: execute file edit and intermediate target file (*.), Dependent file (prerequisites) is those .c files and .h files behind the colon.

Each .o file has a set of dependencies, and these .o files are also performing file edit reliance on files. The dependence is essentially indicated by which files are generated by the target file, in other words, which files are updated. After defining the dependency, subsequent rows define how to generate the operating system command of the target file, be sure to start with a Tab key. Remember, Make does not care how the command works, he only does the defined command. Make will compare the modification date of the targets file and prerequisites file. If the date of the Prerequisites file is more than the date of the targets file, or the target does not exist, Make will perform a subsequent command. Here, it will be that Clean is not a file, it is just a one action name, it is a bit like Lable in the C language, and there is nothing after his colon. So, Make will not automatically find the dependency of the file. You will not automate the commands defined later. To perform the subsequent command, you will clearly indicate the name of this Lable after the make command. Such methods are very useful, we can define unused compiles or compilers in a makefile, such as program packaging, procedures, and so on. Third, how is Make works in the default mode, that is, we only enter the Make command. So, 1, make will find the name "makefile" or "makefile" in the current directory. 2, if you find it, it will find the first target file in the file. In the above example, he will find the "Edit" file and use this file as the final target file. 3, if the Edit file does not exist, or the file modification time behind the EDIT is better than the Edit file, then he will perform the commands defined later to generate the Edit file. 4, if the EDIT is dependent on the .o file, Make will find the dependence of the target as the .o file in the current file, if you find it, generate the .o file according to the rule. (This is a bit like a stack process) 5. Of course, your C file and H file exist, so Make will generate .o file, then use .o file life make the ultimate task, that is, the execution file Edit . This is the dependence of the entire make, and make a layer of relying on the document again until the first target file is finally compiled. In the process of finding, if an error occurs, if the last dependent file cannot be found, Make will exit directly and report the error, and the error of the defined command, or the compilation is unsuccessful. Make only the dependence of the document, that is, if I find the dependencies, the file behind the colon is still, then I am sorry, I will not work. Through the above analysis, we know that like Clean, it is not directly or indirectly associated with the first target file, then the commands that will be later defined will not be executed automatically, however, we can display to execute it as you want. That is, command - "make clean" to clear all target files to recompile.

So in our programming, if this project has been compiled, when we modify one of the source files, such as file.c, then according to our dependence, our target file.o will be compiled (that is The commands defined later later), so File.o's files are also the latest, so file.o's file modification time is more new than Edit, so Edit will be resinted (see Edit target file for details) The command that is defined). And if we changed "command.h", then kdb.o, command.o and files.o will be recompiled, and Edit will be linked. IV. Makefile uses variables in the above example, let's take a look at the rules of Edit: edit: main.o kbd.o command.o display.o / insert.o search.o files.o utils.o cc - o Edit main.o kbd.o command.o display.o / insert.o search.o files.o utils.o We can see the string of the [.o] file twice, if our project needs Join a new [.o] file, then we need to add (it should be three places, there is also a place in Clean). Of course, our makefile is not complicated, so it is not tired in two places, but if Makefile is complicated, then we may have forgetting a place you need to join, but causing compilation to fail. So, for the easy maintenance of Makefile, we can use variables in Makefile. Makefile variables are also a string, understanding the macros in C language may be better. For example, we declare a variable called Objects, Objects, Objs, Objs, Obj, or Obj, anyway, no matter what, you can represent the OBJ file.

We will define this at Makefile: Objects = main.o kbd.o command.o display.o / insert.o search.o files.o utils.o, we can easily in our makefile "$ (Objects)" is used to use this variable, so our improvement version makefile turns the following: Objects = main.o kbd.o command.o display.o / insert.o search.o files. o Utils.o Edit: $ (Objects) cc -o edit $ (objects) main.o: main.c defs.h cc -c main.c kbd.o: kbd.c defs.h command.h cc -c Kbd.c command.o: command.c defs.h command.h cc - 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: RM Edit $ (Objects) Then if there is a new .o file join, we only need to simply modify the Objects variable. With regard to the topic of variables, I will give you a way. 5. Let Make automatically derive the GNU's Make very powerful. It can automatically derive the files and the commands behind the document dependencies, so we don't have to write similar orders after each [.o] file, because we Make will automatically identify and derive commands themselves. As long as Make sees an [.o] file, it will automatically put the [.c] file in the dependencies, if Make finds a wh dayver.o, then wherever.c will be the dependency of whatver.o . And cc -c whatver.c will also be derived, so our makefile will never write so complicated. We are new Makefile and released.

Objects = main.o kbd.o command.o display.o Utils.o Edit: $ (Objects) CC -O Edit $ (Objects) Main.o: Defs.h KBD. o: Defs.h command.h command.o: Defs.h command.h Display.O: Defs.h buffer.h insert.o: Defs.h buffer.h search.o: defs.h buffer.h files. o: Defs.h buffer.h command.h utils.o: defs.h .phony: Clean Clean: RM Edit $ (Objects) This method is Make's "Confirgin Rules". In the above file content, ". Phony" means that Clean is a pseudo target file. With more detailed "hidden rules" and "pseudo target files", I will give you a way. Sixth, alternative Makefile is just our makers can automatically derive the order, then I see that the bunch of [.o] and [.h] is a bit uncomfortable, so much repetition [.h], can It is gathers, well, no problem, this is easy for Make, who told it to provide automatic derivation of commands and files? Let's take a look at the latest style makefile. Objects = main.o kbd.o command.o display.o / insert.o search.o files.o utils.o Edit: $ (Objects) CC -O Edit $ (Objects): Defs.h KBD .o command.o files.o: command.h display.o insert.o search.o files.o: buffer.h .phony: Clean: RM Edit $ (Objects) This style makes our makefile become Very simple, but our documentation is a bit messy. You can not have it both ways. I still see your preference. I don't like this style. First, the dependency of the document is unclear. Second, if there are more files, join a few new .o files, it will not be clear. Seven, the rules of the empty target document should write a rule that empty the target file (.o and execution file), which is not only easy to compile, but also to keep the file clean. This is a "cultivation" (huh, I still remember my "programming cultivation"). The general style is: Clean: RM Edit $ (Objects) is more robust to: .phony: Clean Clean: -rm Edit $ (Objects) said before, .phony means that Clean is a "pseudo-target". . The meaning of adding a small minus sign in front of the RM command is that maybe some files have problems, but do not manage, continue to do. Of course, the rules of Clean do not place the beginning of the file, otherwise, this will become the default target of Make, I believe who is not willing to do this.

The rules of incomplete are - "Clean has never placed the last file". The above is the profile of makefile, is also the foundation of Makefile, and there are many Makefile related details, is it ready? Ready to get ready. Makefile's summary ------- First, what is Makefile? Makefile mainly includes five things: explicit rules, murgee rules, variable definitions, file instructions, and comments. 1. Explicit rules. Explicit rules illustrate how to generate one or more target files. This is clearly pointed out by Makefile's writing, the file, dependent file, the generation of the file, the resulting command. 2, the macious rules. Since our makers have automatic derived features, the concealed rules allow us to write Makefile relatively roughly, which is supported by Make. 3, the definition of the variable. In Makefile, we want to define a series of variables, the variables are generally strings, this a bit in your C language macro, when Makefile is executed, the variables are extended to the corresponding reference location. 4, file instructions. It includes three parts, one is to reference another Makefile in a makefile, just like include in the C language; the other means that the effective part in the makefile is specified according to some cases, just like the precompilation in the C language. #iF is the same; there is a multi-line command. I will talk about this part of the content. 5, comment. Makefile is only a row of comments, like UNIX's shell script, which comes with "#" characters, which is like "//" in C / C . If you want to use the "#" characters in your makefile, you can use the backstelvers to escape, such as "/ #". Finally, it is also worth mentioning that in the Makefile command, you must start with the [Tab] button. Second, Makefile's file name default, the make command will find the file name "gnumakefile", "makefile", "makefile", "makefile", "makefile", and find the file. In these three file names, it is best to use "makefile" file name, because this file name is the first character for uppercase, which has a dedicated feeling. It is best not to use "gnumakefile", this file is the GNU's Make recognition. There are additional Make only sensitive to the full-written "Makefile" file name, but basically, most of the Make supports "makefile" and "makefile" two default file names. Of course, you can use other file names to write makefile, such as "make.linux", "make.solaris", "make.aix", etc. If you want to specify a specific makefile, you can use Make's "-f" And "--file" parameters such as: make -f make.linux or make --file make.aix. Third, the reference to other makefiles In Makefile uses the include keywords to include other makefiles, which is like a C language #include, the included files are placed in the current file in the current file. Include's syntax is: include filename can be the file mode of the current operating system shell (can be saved) in front of include, but must never start with the [Tab] button.

Include and can be separated by one or more spaces. For example, you have such Makefile: A.mk, B.mk, C.mk, and a file called foo.make, and a variable $ (bar), which contains E.MK and F.MK , Then, the following statement: include foo.make * .mk $ (bar) is equivalent to: include foo.make a.mk b.mk c.mk E.mk f.mk make command, you will find Include The other Makefile pointed out, and places its content in the current position. Just like the #include directive of C / C . If the file does not specify an absolute path or relative path, Make will first look for in the current directory, if you are not found in the current directory, Make will find: 1, if Make is executed, With the "-i" or "-include-dir" parameter, Make will find the directory specified by this parameter. 2, if the directory / include (usually: / usr / local / bin or / usr / include) exists, Make will go. If there is no file, make Make generate a warning message, but it will not immediately appear. It will continue to load other files. Once make Makefile's read, make will try again, or if it cannot be read, Make will only have a fatal information. If you want Make ignore those files that you can't read, continue to execute, you can add a minus "-" in front of Include. Such as: -include It is said that no matter what error occurs, no error will continue to execute. And other version make-compatible related commands are sinclude, which is the same as this. Fourth, environment variables makefiles If you define environment variables Makefiles in your current environment, make makes values ​​in this variable similar to include in Include. The value in this variable is the other makefile, separated by spaces. However, it is different from the include that "target" from the Makefile introduced from this environment will not work. If the file defined in the environment variable finds an error, Make will ignore. But here I still recommend not using this environment variable, because as long as this variable is defined, when you use Make, all Makefile will be affected by it, this is not what you want to see. Here, this is just to tell you, maybe sometimes your makefile has a strange thing, then you can see if this variable is defined in the current environment. 5. Make's work mode GNU's Make operation steps in operation steps: (I want to come to other Make is also similar) 1. Read all Makefile. 2, read into other Makefiles of include. 3. Initialize the variables in the file. 4. Divide the murchest rules and analyze all rules. 5. Create a dependency chain for all target files. 6. Depending on the dependencies, decide which goals should be regenerated. 7, execute the generated command. 1-5 Steps to the first stage, 6-7 is the second phase. In the first phase, if the defined variable is used, Make will expand it in the location where it is used.

But Make will not completely start immediately. Make uses delay tactics. If the variable appears in the rules of dependencies, then the variable is only expanded within it only when this reliance is determined. Of course, this way you don't have to be clear, but you know this way you will be more familiar with Make. With this foundation, the subsequent part is easy to understand. Writing rules ---- Rule contains two parts, one is dependency, one is a way to generate the target. In Makefile, the order of the rules is very important, because only one ultimate goal is in Makefile, other goals are coming from this target, so be sure to let Make know what your ultimate goal is. In general, it may be a lot of targets defined in makefile, but the target in the first rule will be established as the final goal. If there are many objectives in the first rule, then the first goal will become the final goal. This goal is made by Make. Ok, let's take a look at how to write rules. First, the rules example foo.O: foo.c defs.h # foo module cc -c -g foo.c See this example, you should not be very strange, and I have said before, foo.o is our goal. , Foo.c and defs.h are the source files dependent on the target, and only one command "cc -c -g foo.c" (starting with the Tab). This rule tells us two things: 1, the dependency of the file, foo.o relies on the file of foo.c and defs.h, if foo.c and defs.h's file date is newer than the foo.o file date Or foo.o does not exist, then dependence occurs. 2. Generate (or update) the foo.o file. That is the CC command, which explains how to generate foo.o file. (Of course, foo.c files) DEFS.H files) Second, the syntax of the rules Targets: prerequisites command ... or this: targets: prerequisites; command command ... targets is a file name, separated by space, you can use wildcard . In general, our goal is basically a file, but it may be multiple files. Command is a command line if it is not with "Target: prerequisites", then, must start with the [Tab key], if Prerequisites are in one line, then the semicolon is separated by sections. (See) prerequisites is the file (or dependent target) that is dependent on the target. If a file is to be new than the target file, then the goal is considered "Out of", it is considered to be reborn. This has been told in front. If the command is too long, you can use a backslash box ('/') as a newline. Make has no restrictions on how many characters on a line. The rule tells make two things, dependencies, and how to become a target file. In general, Make will execute commands with UNIX standard shell, that is, / bin / sh. Third, using wildcards in rules If we want to define a series of similar files, we naturally remember to use wildcards. Make supports three wildcards: "*", "?" and "[...].

This is the same as UNIX's B-shell. Wave number ("~") characters also have a relatively special purpose in the file name. If it is "~ / test", this means the TEST directory under the $ HOME directory of the current user. And "~ hchen / test" represents the Test directory under the host directory of the user's hCHEN. (These are small knowledge under UNIX, Make also supports) and under Windows or MS-DOS, the user does not have a host directory, then the directory referred to by the Wave is determined according to the environment variable "home". Wildcard replaces your series of files, such as "* .c" means that the suffix is ​​C. One requires us to pay attention, if there is a wildcard in our file name, such as "*", you can use the escape character "/", such as "*" to represent the true "*" character, not any length String. Ok, or let's take a few examples: Clean: rm -f * .o, I don't say much, this is the wildcard support supported by the operating system shell. This is a wildcard in the command. Print: * .c lpr -p $? Touch Print The above example illustrates that wildcards can also be in our rules, the target print relies on all [.c] files. Where "$?" Is an automated variable, I will tell you later. Objects = * .o above this example, indicating that the harness can also be used in the variable. Not to say [* .o] will start, no! The value of Objects is "* .o". The variable in makefile is actually a macro in C / C . If you want a wildcard to expand in the variable, that is, the value of Objects is all the collection of file names of [.o], then you can: Objects: = $ (Wildcard * .o) This method of use by keyword "Wildcard" pointed out that we will discuss later about Makefile's keywords. Fourth, the file search is in some major projects, with a large number of source files, our usual practice is to classify this many source files and store them in different directories. So, when Make needs to find the dependencies of the document, you can add a path before the file, but the best way is to tell Make with a path, let Make go automatically. The special variable "vpath" in the makefile file is to complete this feature. If this variable is not specified, Make will only find dependencies and destination files in the current directory. If this variable is defined, Make will find a file in the specified directory when the current directory is not found. VPATH = src: ../ Headers The above definition specifies two directories, "src" and "../headers", make will search in this order. The directory is separated by a "colon". (Of course, the current directory is always the highest priority search) Another way to search the file is the use of the "vPath" keyword (note, it is not a variable, this is a key " Word, this is similar to the VPath variable mentioned above, but it is more flexible. It can specify different files in different search directories. This is a very flexible function. Its usage is three: 1, vpath Specify the search directory for files that match the model .

2, vPath Clear the search directory of the file that matches the model . 3. VPath Clear all file search directories that have been set. in the VAPTH method is required to include "%" characters. "%" Means matching zero or several characters, for example, "%. H" means all files ending with ".h". Specifies the file set to search, and specifies the directory of the searcher of the . For example: vpath% .h ../headers This statement is indicated that Make is required to search all files ending with ".h" in the ".h" directory. (If a file is not found in the current directory), we can use the vPath statement in consecutive search strategies. If the same appears in a continuous vPath statement, or repeated , Make performs a search in the order of the vPath statement. Such as: vpath% .c foo vPath% blish vpath%. C bar represents ".C" ended file, first in the "foo" directory, then "BLISH", and finally the "bar" directory. VPath% .c foo: bar vPath% BLISH, the statement, ".C" ended file, first in the "foo" directory, then the "bar" directory, and finally the "blish" directory. 5. In one example of the pseudo target, we mentioned a "clean" goal, this is a "pseudo-target", clean: rm * .o Temp is like "clean" in our previous example, ie However, we have generated many file compilation files, and we should also provide a "target" to clear their "target" for completeness and use. (Use this goal with "make clean") because we do not generate this file with "Clean". "Pseudo Target" is not a file, just a label, because "pseudo-target" is not a file, so Make cannot generate its dependencies and decide whether it is to be executed. We only indicate this "goals" by displaying to take effect. Of course, "pseudo-target" is named with the file name, otherwise it will lose the meaning of "pseudo-target". Of course, in order to avoid this situation to be renowned, we can use a special tag ".phony" to display a "pseudo-target", explain to make, regardless of this file, this goal is " Pseudo-target. .Phony: Clean as long as there is this statement, whether there is a "clean" file, you want to run the "clean", only "make clean". So the whole process can be written like this: .phony: Clean Clean: rm * .o Temp pseudo-target generally has no dependencies. However, we can also specify the dependencies dependent on the pseudo target. The pseudo target can also be used as a "default target" as long as it is placed in the first one.

One example is that if your makefile needs to generate a number of executable files, you just want to simply knock an opportunity, and all the target files are written in a makefile, then you can use "PseudoT" This feature: All: PROG1 PROG2 PROG3.PHONY: ALL PROG1: PROG1.O Utils.o cc -o prog1 prog1.o utils.o prog2: prog2.o cc -o prog2.o prog3: prog3.o sort.o Utils.o cc -o prog3 prog3.o sort.o utils.o We know that the first goal in makefile will be used as its default target. We declare a "all" pseudo-target that relies on the other three goals. Since the characteristics of the pseudo objective are always being executed, the three goals depending on the dependence are always like "all". Therefore, the rules of the other three goals will always be resolution. Just achieve the goal of us to generate multiple goals. ".Phony: all" declares that "all" is "pseudo-target". Just mention, from the above example we can see that the goal can also be dependent. Therefore, the pseudo target can also be dependent. Look at the following example: .phony: CleanAll Cleanobj CleanObj Cleanall: Cleanobj: rm * .o cleandiff: rm * .diff "make clean" will clear all files to be cleared. "Cleanobj" and "Cleandiff" are a bit like "subroutine". We can enter the "make cleanl" and "make clean cleanobj" and "make cleandiff" commands to achieve the purpose of clearing different kinds of files. Sixth, the goal in the rules of multi-objective makefile can be more than one, which supports multi-objective, there is a possible number of targets to depend on one file, and the resulting command is generally similar. So we can merge them. Of course, the execution command of the generation rules of multiple targets is the same, which may have to bring trouble, but in our use of an automated variable "$ @" (about automated variables, it will be described later), this Variables show a collection of all goals in the current rules, which may be abstract, or look at an example. BIGOUTPUT LITTLEOUT: TEXT.G Generate Text.g - $ (Subst Output, $ @)> $ @ 上 规 规 等 等 价 于于: g -little> LittleOutput, "$" in-$ (subst output, $ @) means executing a MakeFile function, the function is called subst, which is the parameter. About the function will be described later. This function here is the meaning of the string, "$ @" indicates the collection of the target, just like an array, "$ @" takes out the goal, and it is committed to the command.

Seven, static mode static mode can be more easily defined for multi-objective rules, allowing us to make our rules more flexible and flexible. Let's first look at the syntax: : : ... targets defines a series of target files that can have wildcards. Is a collection of goals. Target-Parrtern is a model of Targets, that is, the target set mode. Prereq-Parrterns is the dependency mode of the target, which is defined for the mode of Target-Parrtern. This three things may still be clear, or an example to explain it. If we define "% .o", it means that our collection is ".o", if our defines "% .c "It means the secondary definition of the target set formed by , the calculation method is to take"% "in mode (that is, the end of [.o] is ended), And add [.c] this end, the new collection of formed. So, our "target mode" or "dependency mode" should have "%" characters, if you have "%" in your file name, you can use a backslash "/" to indicate, to indicate Real "%" characters. See an example: Objects = foo.o bar.o all: $ (objects):% .o:% .C $ (cc) -c $ (cflags) $ @ 上 上Indicates that our goals are got from $ Object, "%. O" indicates all the goals ending with ".o", that is, "foo.o bar.o", that is, the variable $ Object Collection mode, and Dependent mode "% .C" is "% .o" "%", which is "foo bar", and add ".c" suffix, so our dependence is "foo.c" Bar.c. The "$ <" and "$ @" are automated variables in the command, "$ <" indicates that all dependence target sets (that is, "foo.c bar.c"), "$ @" indicates the target set (also It is "foo.o bar.o"). As a result, the following rules are equivalent to the following rules: foo.o: foo.c $ (cc) -c $ (cflags) foo. c c foo.o bar.o: bar.c $ (cc) -c $ (cflags) bar.c -o bar.o, if we "% .o" has hundreds, then we can write a bunch of "Static Mode Rules" with this very simple "Static Mode Rule" Rules are really efficient. The Usage of Static Mode Rules is flexible, if you are used, it will be a very powerful feature.

Look at an example: files = foo.elc bar.o lose.o $ (Filter% .o, $ (files)):% .o:% .C $ (cc) -c $ (cflags) $ <-O $ @ $ (File% .elc, $ (files)):% .elc:% .el emacs -f batch-byte-compile $ <$ (file% .o, $ (files) indicating the Filter function called Makefile Filter the "$ FILTER" set, as long as the mode is "% .o". Its content, I don't have to say more. This example shows greater flexibility in makefile. 8. Automatic generation dependency in Makefile, our dependencies may need to include a series of headers, such as if there is a "#include" defs.h "in our main.c, then our dependency It should be: main.o: main.c defs.h However, if it is a relatively large engineering, you must know which C files contain which headers, and you need to be careful when you join or delete the header file. Modify Makefile, this is a very maintenance of work. In order to avoid this heavy and easy error, we can use a function of compilation of C / C . Most C / C compilers support a "-m" option, that is, automatically find the header files contained in the source file and generate a dependency. For example, if we perform the following command: cc -m main.c Output is: main.o: main.c defs.h is then automatically generated by the compiler, so that you don't have to manually write a number The dependencies of the document are automatically generated by the compiler. It is necessary to remind a sentence that if you use the GNU's C / C compiler, you have to use the "-mm" parameter, otherwise, "-m" parameters will also include some standard libraries' header files. The output of gcc -m main.c is: main.o: main.c defs.h /usr/include/stdio.h /usr/include/features.h //usr/include/sys/cdefs.h / usr / Include / gnu / stubs.h //usr/lib/gcc-lib/i486-suse-linux/2.95.3/include/stddef.h //usr/include/bits/types.h / usr / include / bits / PthreadTypes.h / /usr/include/bits/sched.h /usr/include/libio.h / /usr/include/_g_config.h /usr/include/wchar.h / /usr/include/bits/wchar.h /usr/include/gconv.h //usr/lib/gcc-lib/i486-suse-linux/2.95.3/include/stdarg.h //usr/include/bits/stdio_lim.h gcc -mm main.c The output is: main.o: main.c defs.h So, how the compiler is associated with our makefile.

Because in this way, our makefile should also regenerate according to these source files, let Makefile dependent on the source file? This feature is not realistic, but we can have other means to go back to this function. The GNU organization recommends putting the compiler to automatically generated dependencies of each source file in a file, generate a "name.d" Makefile file for each "name.c" file, [D] file Store the dependency of the [.c] file in place. Thus, we can write the [.c] file and [.d] file dependency, and let the make automatically update or self-contained [.d] files, and contain it in our master makefile, so we will It can automatically generate the dependence of each file. Here, we give a pattern rule to generate [.d] files:% .d:% .c @set -E; RM -F $ @; / $ (cc) -m $ (cppflags) $> $ @. $$$$; / SED 'S, / ($ * /) /. O [:] *, / 1.o $ @:, g' <$ @; $$$$> $ @; / rm -f $ @. $$$$ This rule means that all [.d] files depend on the [.c] file, "RM -F $ @" means deleting all the goals, that is, [.d ] File, the second line means that for each dependency file "$ <", it is [.c] file generation dependencies, "$ @" represents the "% .d" file, if there is a C file is Name.c, then "%" is "name", "$$$$" means a random number, the second line generated files may be "name.d.12345", the third line uses the sed command to do it. A replacement, please refer to the related use documentation about the usage of the SED command. The fourth line is to delete a temporary file. All in all, this mode is to do is to join the "dependency of the [.d] file in the dependencies generated by the compiler, which means: main.o: main.c defs.h is converted to: main.o main.d : main.c defs.h, our [.d] file will also be updated automatically, and will be automatically generated. Of course, you can also join in this [.d] file is not just dependence, including generating The command can also be added one and let each [.d] file contain a decree rule. Once we finish this job, then we have to put these automatically generated rules into our master makefile. We can use the "include" command of Makefile to introduce other makefile files (previously speaking), for example: Sources = foo.c bar.c include $ (Sources: .c = .d) in the above statement "$ ".c = .d" in ".c = .d" is to make a replacement, replace all the strings of the variable $ (Sources) to [.d], about this " Replace "content, I will have more detailed descriptions later. Of course, you have to pay attention to the order, because INCLUDE is filed as a file, the target in the [.D] file that is first loaded will become the default target. Writing Commands ---- Command Lines in each rule and the command line of the operating system shell are consistent.

Make will execute a command in order, each command must begin with the [Tab] key, unless, the command is followed by the semicolon behind the dependency rule. The space in the command line or the blank line will be ignored, but if the space or the blank line is opened with a Tab key, Make will think it is an empty command. We can use different shells under UNIX, but make the make commands are performed by the "/ Bin / SH" - UNIX standard shell. Unless you specifically specify a further shell. Makefile, "#" is an comment, very like "//" in C / C , and the subsequent bank characters are commented. First, the display command usually, make the command line to be executed before the command is executed to the screen. When we use the "@" character before the command line, then this command will not be displayed by Make, the most representative example, we use this feature to display some information on the screen. Such as: @echo is compiling XXX module ... When Make is executed, it will output "Compiling XXX Modules ..." strings, but will not output commands, if there is no "@", then, Make will output: Echo is compiling XXX module ... is compiling XXX modules ... If Make is executed, bring the Make parameter "-n" or "--just-print", then it is just Display commands, but not execute commands, this feature is very good for we debugging our makefile, see what our writing command is executed or what is the order. The Make parameter "-s" or "--slient" is a full disable command display. Second, the command execution When relying on the target is new to the target, the Make will perform a subsequent command when the target of the rules needs to be updated. It should be noted that if you want to apply the result of the previous command to the next command, you should use the semicolon to separate these two commands. For example, your first command is a CD command, you want the second command to run on the CD, then you can't write these two commands on both lines, but should write these two commands. On a row, separated by a semicolon. Such as: example 1: Exec: CD / Home / HCHEN PWD Example 2: Exec: CD / Home / Hchen; PWD When we perform "make exec", the CD in the first example does not work, and the PWD will print the current Makefile directory, and in the second example, the CD works, and the PWD will print "/ home / hcha". Make is typically executing commands using the system shell defined in the environment variable shell, by default, using UNIX standard shell - / bin / sh to execute the command. But it is a bit special under MS-DOS because there is no shell environment variable under MS-DOS, of course you can also specify. If you specify the form of a UNIX style, first, Make will find a command interpreter in the path specified by Shell. If you can't find it, you will find it in the current directory in the current drive, if you can't find it, It will be found in all paths defined in the PATH environment variable. In MS-DOS, if your defined command interpreter is not found, it will give you a command interpreter, such as ".exe", ". Com", ".", ". Sh", etc.

Third, the command error Whenever the command is running, make will detect the return code of each command. If the command returns success, then make will execute the next command. When all the commands in the rule have returned successfully, this rule is successful. . If a command in a rule is wrong (the command exits is not zero), the make will terminate the execution of the current rule, which will be possible to terminate all rules. Sometimes, the error of the command does not mean that it is wrong. For example, the mkdir command, we must build a directory, if the directory does not exist, then MKDIR will be executed successfully, and all the best, if the directory exists, then it is wrong. The reason why we use MKDIR is to have such a directory, so we do not want MKDIR to go wrong and terminate the rules. In order to do this, ignore the error of the command, we can add a minus "-" (after the Tab key) in the Makefile command line, the tag is not that the command is not wrong. Such as: clean: -rm -f * .o has a global approach to add "-i" or "--ignore-errors" parameters, then all commands in makefile ignore errors. And if a rule is ".ignore" as a target, all commands in this rule will ignore the error. These are methods of preventing an error in different levels, you can set it according to your different. There is also a "-k" or "--keep-going", which is "-k" or "--keep-going", this parameter is that if the command in a rule is wrong, then the execution of the rule, But continue to perform other rules. Fourth, nested to execute make in some big projects, we will put our different modules or different functional files in different directories, we can write a directory Makefile in each directory, this has It is good to make our makefile more concise, and not to write all things in a makefile, which will hardly maintain our makefile, this technology has a very good benefit to compile and segment compilation of our modules. For example, we have a subdirectory called subdir. There is a Makefile file in this directory to indicate the compilation rules for the files in this directory. Then our total control Makefile can be written like this: Subsystem: CD Subdir && $ (Make) Its equivalent: Subsystem: $ (MAKE) -c Subdir Definition $ (Make) macro variable means, maybe our make needs some Parameters, so defined as a variable is more conducive to maintenance. These two examples means to enter the "subdir" directory first, then execute the make command. We call this Makefile ", the total control Makefile" can be passed to the subkey Makefile (if you show the declaration), but will not cover the variable defined in the subkefile of the next layer, unless specified "-e "parameter.

If you want to pass a variable into a subordinate Makefile, you can use this statement: export If you don't want some variables to be delivered to the lower grade Makefile, then you can declare: UNEXPORT Example 1: Export variable = value Its equivalence: Variable = value export variable equals: export variable: = value It is equivalent to: variable: = value export variable example 2: Export variable = value Equivalent: Variable = Value Export Variable If you want to pass all variables, then just an export is OK. There is no need to follow, indicating that all variables are passed. It should be noted that there are two variables, one is the shell, one is makeflags, these two variables don't care if you export, it is always necessary to pass to the next Makefile, especially the makefiles variable, which contains the parameter information of Make, If we have a Make parameter or define this variable in the upper Makefile when performing "Total Makefile", the makefiles variable will be these parameters and will be transferred to the lower Makefile, which is a system-level environment variable. However, several parameters in the make command are not transmitted down, they are "-c", "- f", "- h" "- o" and "-w" (detail about the Makefile parameter will be described later. If you don't want to pass parameters to the lower layer, then you can come: Subsystem: CD Subdir && $ (Make) Makeflags = If you define environment variables makeflags, then you have to be sure that you will be used. If there are "-t", "- n", and "-q" parameters, then there will be unexpected results, perhaps you will panic unusually. There is also a more useful parameter, "- w" or "-print-directory" in "Nesting Execution", which will output some information in the opportunity of Make, so that you see the current working directory. For example, if our subordinate make directory is "/ home / hchen / gnu / make", if we use "make -w" to execute, then we will see: make: Entering Directory `/ Home / hchen / gnu / make '. When you leave the directory after completing the underlying Make, we will see: make: leaving directory `/ home / hchen / gnu / make' When you use the" -c "parameter to specify the subceline of Makefile When "- W" will be opened automatically. If there is "-s" ("- slient") or "--no-print-directory" in the parameter, "- w" is always invalid.

V. Define Command Pack If some of the same command sequences appear in Makefile, we can define a variable for these same command sequences. Defining the syntax of this command sequence begins with "Define" to end with "endef", such as: Define Run-Yacc Yacc $ (Firstword $ ^) mv y.tab.c $ @ Endef here, "Run-Yacc" is this The name of the command package, does not reintegrate with the variable in the makefile. Two lines in "define" and "endef" are command sequences. The first command in this command package is running the YACC program because the YACC program always generates "Y. Tab.c" files, so the second line command is to change this file. Or put this command to a sample to see it. Foo.c: foo.y $ (run-yacc) We can see, we want to use this command package, we seem to use the variable. In this command package, "$ ^" in the command package "Run-Yacc" is "foo.y", "$ @" is "foo.c" (related to this special variable starting with "$" We will introduce later), Make is executing each command in the command package when executing the command package. Using variables ---- The variables defined in makefile are like a macro in the C / C language. He represents a text string. When it is executed in the makefile, it will automatically start the original model. Use place. It is different from C / C that you can change its value in makefile. In Makefile, variables can be used in "target", "dependency", "command", or other parts of Makefile. The name word of the variable can contain characters, numbers, and underscore (can be digital start), but should not contain ":", "#", "=" or empty characters (spaces, Enter, etc.). Variables are sensitive, "foo", "foo", and "foo" are three different variable names. The traditional Makefile variable name is a new name method, but I recommend using a variable name with case, such as: Makeflags. This avoids conflicts with the system's variables, and accidents occur. Some variables are very strange strings, such as "$ <", "$ @", etc., these are automated variables, I will introduce later. First, the basic variable of the variable needs to give initial values ​​when the declaration is declared, and when in use, you need to add "$" symbol before using the "$" symbol, but it is best to use small brackets "()" or braces "{}" Variables are given. If you want to use a real "$" character, you need to use "$$". Variables can be used in many places, such as "depends", "dependencies", "command", and new variables.

Let's take an example: Objects = program.o foo.o utils.o program: $ (Objects) $ (Objects): Defs.h variable will be exactly exactly using it, Like the macro in C / C , for example: foo = C Prog.O: PROG. $ (Foo) $ (foo) - $ (foo) prog. $ (Foo) get: prog.o : prog.c cc -c prog.c, of course, don't do this in your makefile, here is just an example to indicate the true appearance of the variable in the Makefile. It can be seen that it is a "alternative" principle. In addition, the variable plus parentheses is completely used for more securely using this variable, in the above example, if you don't want to add parentheses, it can, but I still recommend that you add parentheses to the variable. Second, the variables in the variable When the value of the variable, we can use other variables to construct the value of the variable, there are two ways to define variables with variables in both Makefile. First, look at the first way, that is, the "=" number, "=" is the variable, the right side is the value of the variable, the value of the right variable can be defined anywhere in the file, that is, The variables in the right side are not necessarily a value that has been defined, and it can also use the value of the following definition. Such as: foo = $ (bar) bar = $ (UGH) UGH = Huh? All: Echo $ (foo) We Execute "Make All" will play the value of the variable $ (foo) is "huh?" ($ (Foo) The value of $ (bar), $ (bar) is $ (UGH), $ (UGH) value is "huh?"), And the variable can be defined using the rear variables. This feature has a good place, and there is a bad place. Well, we can push the true value of the variable to the back to define, such as: cflags = $ (incrude_dirs) -o include_dirs = -ifoo -ibar "cflags "When you are expanded in the command, it will be" -ifoo -ibar -o ". But this form is also in a bad place, that is, recursive definition, such as: cflags = $ (cflags) -o or: a = $ (b) b = $ (a) This will make Make fall into the unlimited variable expansion Go, of course, our make is the ability to detect such definitions and will report an error. There is also if you use a function in a variable, then this way makes our maket time very slow, worse, he will use two Make functions "Wildcard" and "shell" unpredictable error. Because you won't know how many times the two functions will be called. To avoid this method, we can use another variable to define variables in another variable.

This method uses ": =" operators, such as: x: = foo y: = $ (x) bar x: = late its equivalent: y: = foo bar x: = latter is worth mentioning , This method, the previous variable cannot use the rear variable, only the previously defined variables can be used. If this is true: Y: = $ (x) bar x: = foo So, Y's value is "bar" instead of "foo bar". The above is a relatively simple variable is used, let us look at a complex example, including Make's function, conditional expression and a system variable "MakeElevel": IFEQ (0, $ {MakeElevel}) CUR -dir: = $ (Shell PWD) Whoami: = $ (Shell Whoami) Host-type: = $ (shell arch) Make: = $ {host-type} why = $ {ha} Endif About the conditional expression and function, we will say later, for the system variable "MakeElevel", it means that if our make has a nested action (see "Nesting using Make", then, this The variable records our current makefile call layers. Let's introduce two definition variables, we need to know, please take an example, if we want to define a variable, its value is a space, then we can come: nullstring: = space: = $ (nullstring) # END of the line nullstring is an EMPTY variable, where there is no, and our space value is a space. Because it is difficult to describe a space on the right side of the operator, the technique used here is used, first using an EMPTY variable to indicate the value of the variable start, and the "#" comment is used to indicate the termination of the variable definition, so We can define the variables of a space. Please note that this feature of "#" is worth noting that this feature of the comment "#" is worth noting that if we define a variable: Dir: = / foo / bar # Directory to put the ferobs in dirctory value is the value of this variable is "/ Foo / bar", followed by 4 spaces, if we use this variable to specify other directories - "$ (dir) / file" then finish. There is also a more useful operator is "? =", First look at the example: foo? = Bar its meaning, if the foo is not defined, the value of the variable foo is "bar", if Foo is previously defined, Then this language will not do anything, equivalent: IFEQ ($ (Origin foo), undefined) foo = bar endif.3, the variable advanced usage is introduced here to introduce the advanced use of the two variables, the first is the variable value Alternative. We can replace the common parts in variables, "$ (var: a = b)" or "$ = b)", it means that all of the variables "VAR" "A "" A "" "A" "end" is replaced with "B" string. The "end" here means "space" or "ending".

Still watching an example: foo: = AO boity CO bar: = $ (foo: .o = .c) This example, we define a "$ (foo)" variable, and the second line means "$ (Foo)" is replaced with ".o" string "end" all replaces ".c", so our "$ (bar)" value is "AC BC CC". Another variable replacement technique is defined in "static mode" (see the previous chapter), such as: foo: = AO BO CO bar: = $ (foo:%. O =%. C) This depends on the retrieval word There is the same mode in the string, and a "%" character must be included in the mode. This example also allows the value of the $ (bar) variable to "AC BC CC". The second advanced utility is - "The value of the variable is changed as a variable." Let's take an example: x = y y = z A: = $ ($ (x)) In this example, $ (x) value is "y", so $ ($ (x)) is $ (y) The value of $ (a) is "z". (Note, "x = y", not "x = $ (y)") we can also use more levels: x = y y = z z = u A: = $ ($ ($ () )) The value of $ (a) here is "u", the relevant derivation is left to the reader to do it. Let us be more complicated, use the first way to use variables in variable definitions "to see an example: x = $ (y) y = z z = Hello A: = $ ($)) here $ ($ (X)) is replaced with $ ($ (y)) because the $ (y) value is "Z", so the end result is: A: = $ (z), that is, "Hello" . Complex again, we add a function: x = variable1 variable2: = Hello Y = $ (SUBST 1, 2, $ (x)) z = y A: = $ ($ (z))) This example is , "$ ($ ($ ($ (Z)))" Extension to "$ (Y)", and it is once again extended to "$ ($ (SUBST 1, 2, $ (x))". The value of $ (x) is "variable1", the SUBST function replaces all the "1" strings in "variable1" into "2" strings, "Variable1" becomes "variable2", then takes the value, so , Finally, the value of $ (a) is the value of $ (variable2) - "Hello". (Oh, it is difficult to "in this way, or you can use multiple variables to form a variable name, then take the value: first_second = Hello a = first b = second all = $ ($ A_ $ b) The "$ A_ $ B" here consists of "first_second", so the value of $ (all) is "Hello".

Let's take a look at the examples of the first technology: a_objects: = AO bo 1_objects: = 1.o 2.o 3.o Sources: = $ ($ (a1) _Objects: .o = .c) This example, If the value of $ (a1) is "a", then the value of $ (Sources) is "AC BC CC"; if the value of $ (a1) is "1", then $ (Sources) value is "1) .c 2.c 3.c. Take another example of this technology and "function" and "conditional statements": ifdef do_sort func: = sort else func: = Strip Endif Bar: = Adbgqc foo: = $ ($ (FUNC) $ (bar)) In this example, if "do_sort" is defined, then: foo: = $ (sort adbgqc), the value of $ (foo) is "abcdgq", and if "do_sort" is not defined, then: foo: = $ (Sort ADBGQC), calling the Strip function. Of course, "the value of the variable is variable", which can also be used on the left side of the operator: DIR = Foo $ (DIR) _Sources: = $ (Wildcard $ (DIR) / *. C) Define $ (DIR ) _Print Lpr $ ($ (DIR) _Sources) Endef This example defines three variables: "DIR", "foo_sources" and "foo_print". Fourth, additional variables We can use the " =" operator to add value to the variable, such as: Objects = main.o foo.o bar.o utils.o Objects = another.o, our $ (Objects) value Change: "Main.o foo.o bar.o utils.o noidher.o" (ANOTHER.O is added) Use the " =" operator, which can simulate this example below: Objects = main. o foo.o bar.o utils.o Objects: = $ (Objects) Another.o is different from " =" is more concise. If the variable is not defined before, " =" will automatically turn "=", if there is a variable definition in front, " =" will inherit the assassifier of the previous operation.

If the previous one is ": =", " =" will assign a value in ": =" as its assignment, such as: variable: = value variable = more equals: variable: = value variable: = $ (Variable , if this is the case: variable = value variable = more because the previous assignment is "=", " =" will be assigned as "=", then there will be no variables. Repeating the definition, this is very bad, so Make will automatically solve this problem for us, we don't have to worry about this problem. V. Override indicator If the variable is usually set, the assignment of this variable will be ignored in the Makefile. If you want to set the value of such parameters in makefile, then you can use the "OVERRIDE" indicator. Its syntax is: Override = Override : = Of course, you can also add: Override = For multi-line variable definitions, we use define indicators Before the Define indicator, Ovveride indicators can also be used, such as: Override define foo bar endef 6, multi-line variables There is also a way to set variable values ​​to use the define keyword. The value of setting the variable using the define keyword can have a wrap, which facilitates the definition of a series of commands (before we told the "command package" technology to use this keyword). The define indicator is followed by the name of the variable, and restarts the value of the defined variable, the definition is the end of the Endef keyword. Its work mode is the same as the "=" operator. The value of the variable can contain functions, commands, text, or other variables. Because the command needs to begin with the [Tab] key, if you don't start with the [Tab] button with the defined command variable, Make will not think it is a command. The following example shows the usage of define: Define TW-LINES Echo foo echo $ (bar) Endef seven, environment variables Make runtime system environment variables can be loaded into the Makefile file when Make starts running, but if Makefile This variable has been defined, or this variable is brought by the Make command line, then the value of the system's environment variable will be overwritten. (If Make specifies the "-e" parameter, the system environment variable will override the variable defined in Makefile), so we can use the "cflags" environment variable in the environment variable, then we can use in all makefiles. This variable is. This has a relatively good benefit to our compilation parameters. If you define cflags in makefile, this variable in makefile will use the value of the system environment variable, a common and personalized unity, which is very similar to the "global variable" and "local variable" if it is not defined.

When Make nested (see chapter "Nested Call chapter), the variable defined in the upper Makefile will be passed to the lower Makefile in the way system environment variables. Of course, by default, the variables set by the command line will be passed. And define the variables in the file, if you want to pass down MakeFile, you need to use the exprot keyword to declare. (See the previous chapter) Of course, I don't recommend that many variables are defined in the system environment, so that when we don't have to make Makefile, it has the same set of system variables, which may bring more trouble. 8. The variables we are talking to the target variable are all "global variables", and we can access these variables throughout the file. Of course, except "automated variables", such as "$ <", such as "$ <" belongs to the "rule variable", and the value of this variable depends on the rules and definitions of dependent targets. Of course, I can also set local variables for a target. This variable is called "target-specific variable", which can be with "global variable", because its role range is only in this rule and the joint rules Therefore, its value is only valid within the scope of action. The value of global variables other than the rule chain will not affect the rule chain. Its syntax is: : : Overide can be the various assignment expressions, such as "=" , ": =", " =" Or "? =". The second syntax is to target the variables brought by the Make command line or the system environment variable. This feature is very useful, when we set a variable, this variable will act to all rules caused by this goal. Such as: prog: cflags = -g prog: prog.o foo.o bar.o $ (cflags) prog.o foo. bar.o prog.o: prog.c $ (cc) $ (cflags ) Prog.c foo.o: foo.c $ (cc) $ (cflags) foo.c bar.o: bar.c $ (cc) $ (cflags) bar.c In this example, no matter the global $ What is the value of cflags, in the PROG target, and all the rules it triggered (Prog.o Foo. bar.o rules), the value of $ (cflags) is "-g" nine, mode variables In the GNU's Make, the pattern variable is supported. In the above target variable, we know that the variable can be defined on a target. The advantage of mode variables is that we can give a "mode" to define variables on all targets that meet this mode.

We know that Make's "mode" is generally at least one "%", so we can define target variables in [.o] at the end of [.o] in the following way:% .o: cflags = -o, mode The syntax and "target variable" of the variable are: : : Override Override is also a variable for system environment, or make Make The variable specified by the command line. Use condition judgment ------ Use condition judge, allowing Make to select different execution branches depending on the different conditions of runtime. The conditional expression can be a value of a comparison variable, or a value of comparison variables and constants. First, the example below, determines if the $ (CC) variable "GCC", if yes, use the GNU function to compile the target. Libs_for_gcc = -lgnu Normal_Libs = Foo: $ (Objects) IFEQ ($ (CC), GCC) $ (CC) -o Foo $ (Objects) $ (libs_for_gcc) ELSE $ (CC) -o Foo $ (Objects) $ ( NORMAL_LIBS) ENDIF visa We can see three keywords from the above example: IFEQ, Else, and Endif. IFEQ means the beginning of the conditional statement, and specifies a conditional expression, the expression contains two parameters, separated by commas, and the expression is enclosed in parentheses. Else indicates the condition of the conditional expression. Endif indicates the end of a conditional statement, and any conditional expression should end with ENDIF. When our variable $ (cc) value is "GCC", the rules of the target foo are: foo: $ (Objects) $ (cc) -o foo $ (objects) $ (libs_for_gcc) while our variable $ (cc) The value is not "GCC" (such as "cc"), the rules of the target foo are: foo: $ (ibjects) $ (cc) -o foo $ (objects) $ (Normal_Libs) Of course, we can also put the above Examples are more concise: libs_for_gcc = -lnu Normal_Libs = IFNU NORMAL_LIBS = IFEQ ($ (cc), gcc) Libs = $ (libs_for_gcc) Else Libs = $ (Normal_Libs) Endif Foo: $ (Objects) $ (cc) -o foo $ (Objects) $ (libs) Second, grammatical expression of the grammatical condition is: Endif and: else Endif While Indicates the condition key, such as "IFEQ". This keyword has four.

The first is what we have seen in front of our "IFEQ" IFEQ ( "" "" IFEQ "" "IFEQ" "'' IFEQ ''" "compares the value of parameters" arg1 "and" arg2 ". Of course, we can also use the Make function in the parameter. Such as: IFEQ ($ (Strip $)), "Strip" function in this example, if the return value of this function is empty, then takes effect. The second condition key is "ifneq". The syntax is: IFNEQ (, ) ifq '' '' IFNEQ "" "ifneq" " 'IFNEQ' '"" The value of the comparison parameter "arg1" and "arg2" is the same, if different, it is true. Similar to "IFEQ". The third condition key is "IFDEF". The syntax is: ifdef If the value of the variable is not empty, then the expression is true. Otherwise, the expression is false. Of course, can also be a function of a function of a function. Note that ifdef only tests if a variable has a value, it does not extends the variable to the current location. Or come to see two examples: Example 1: bar = foo = $ (bar) ifdef foo frobozz = yes else frobozz = no endif example: foo = ifdef foo frobozz = yes else frobozz = no Endif's first example, " The $ (frobozz) value is "YES", the second is "no". The fourth condition key is "ifndef". Its syntax is: ifndef I don't have much to say this, and "ifdef" is the opposite. On , excess space is allowed, but cannot be started with the [Tab] key (otherwise it is considered a command). The comment "#" is also safe. "Else" and "Endif" are the same, as long as it is not to start with the [Tab] button.

In particular, Make is the value of the conditional expression when reading Makefile, and selects the statement according to the value of the conditional expression, so don't put the automated variables (such as "$ @", etc.) In the conditional expression, since the automation variable is only running. Moreover, in order to avoid confusion, MAKE does not allow the entire condition statement into two parts in different files. Using a function ---- In Makefile, you can use a function to handle the variable, so that our commands or rules are more flexible and intelligent. The function supported by Make is not much, but it is enough for our operation. After the function is called, the return value of the function can be used as a variable. First, the function call syntax function call, very like variables, is also identified by "$", its syntax is as follows: $ ( ) or $ { } here, is a function name, and Make supports a function. is the parameter of the function, the parameters are brought by a comma, and the function names and parameters are separated by "space". The function is called "$", enclosing the function name and parameters in parentheses or curly brackets. It feels like a variable, is it? The parameters in the function can use variables. For the unity of styles, the function and variables are best, such as "$ (Subst A, B, $ (x))", rather than "subs", B, $ {x}) "form. Because the unity will be clearer, it will also reduce some unnecessary trouble. Still come and see an example: comma: =, empty: = space: = $ (empty) $ (EMPTY) foo: = ABC BAR: = $ (Subst $ (Space), $ (Comma), $ (Foo)) In this example, the value of $ (COMMA) is a comma. $ (space) Download a space, $ (foo) value is "ABC", $ (bar) defined, calling the function "subst", this is a replacement function, this function has three Parameters, the first parameter is replaced by the string, the second parameter is replacing the string, the third parameter is a string of the operation. This function is also replacing the space in $ (foo) into a comma, so the value of $ (bar) is "A, B, C". Second, string processing functions $ (Subst , , ) Name: String Replacement Function - Subst. Function: Replace the string in the string to . Returns: The function returns a string that is replaced. Example: $ (Subst Ee, EE, Feet on The Street), replacing "EE" in "Feet on The Street" into "EE", the return result is "Feet on the street". $ (PatSubst , , ) Name: Mode string replacement function - Patsubst.

Function: Find words in (word "space", "tab" or "Enter", "Separation", if you match the mode , if you match, you will replace it in . Here, can include a wildcard "%", representing a string of any length. If contains "%", then this "%" in will be the string represented by the "%" in . (You can use "/" to escape, "/%" to indicate the "%" character) of the true meaning back: the function returns a string that is replaced. Example: $ (PATSUBST% .C,%. O, XCC bar.c) Replace the string "XCC bar.c" in line with [% .o], return results "XCO BAR .o "Note: This is a bit similar to the relevant knowledge that we have said in front of the" variable chapter ". Such as: "$ (var: = )" Patsubst , , $ (VAR) ", and" $ ($ (VAR: = ) "It is equivalent to" $ (PatSubst% ,% , $ (var)). For example, it is: Objects = foo.o bar.o baz.o, then "$ (Objects: .o = .c)" and "patrsubst% .O,%. C, $ (objects))" is the same of. $ (Strip ) Name: Go to Net Gift Function - Strip. Function: Remove the empty characters that start and end in the string. Returns: Returns the string value of the removed space. Example: $ (Strip A B C) Take the string "A b C" to the beginning and end space, the result is "a b C". $ (FindString , ) Name: Find string functions - Findstring. Function: Find strings in the string . Returns: If you find it, return , otherwise you return an empty string. Example: $ (FindString A, ABC) $ (Findstring A, BC) The first function returns "A" string, the second return "" string (empty string) $ (Filter , ) Name: Filter function - Filter. Function: Filter the words in the string in mode, keep the words that match the model . There can be multiple modes. Returns: Returns a string that conforms to mode .

Example: Sourcees: = foo.c bar.c Baz.s Ugh.h foo: $ (Sources) CC $ (Filter% .C%. S, $ (Sources)) -O foo $ (file% .c%. S, $ (Sources)) The value returned is "foo.c bar.c baz.s". $ (Filter-Out , ) Name: Inverted Filter Function - Filter-Out. Function: Filter the words in the string in mode, remove words that match the model . There can be multiple modes. Returns: Returns a string that does not match the mode . Example: objects = main1.o foo.o main2.o bar.o mains = main1.o main2.o $ (Filter-Out $ (MAINS), $ (Objects)) Return value is "foo.o bar.o" . $ (Sort ) Name: Sort Function - Sort. Function: Sort by words in string (ascending). Returns: Returns the sorted string. Example: $ (Sort Foo Bar LOSE) Returns "Bar Foo Lose". Note: The Sort function removes the same words in . $ (Word , ) Name: Take a word function - Word. Function: Take the string words in . (From one start) Returns: Returns "N> words in string . If is larger than the number of words in , the empty string is returned. Example: $ (Word 2, Foo Bar Baz) Return value is "bar". $ (WordList , , ) Name: Take a string string function --wordList. Function: Take the word string from to from the string . and are a number. Returns: Returns the word string from to in string . If is larger than the number of words in , the empty string is returned. If is greater than the word number of , then return from start, to ends. Example: $ (WordList 2, 3, Foo Bar Baz) Return value is "bar baz". $ (Words ) Name: Word Number Statistics - Words. Function: Counting the number of words in strings in . Returns: Returns the number of words in . Example: $ (Words, Foo Bar Baz) Return value is "3". Note: If we want to get the last word in , we can do this: $ (Word $ (Words ), ).

$ (Firstword ) Name: First Word Function - Firstword. Function: Take the first word in string . Returns: Returns the first word of string . Example: $ (FIRSTWORD FOO BAR) The return value is "foo". Remarks: This function can be implemented with a Word function: $ (Word 1, ). The above is all string operation functions, and if mixed, you can complete a more complex function. Here, an example of a reality is given. We know that make uses the "vPath" variable to specify the search path of "dependent file". Thus, we can use this search path to specify the search path parameters of the compiler to the header file cflags, such as: Override CFLAGS = $ (PatSubst%, - I%, $ (Subst:,, $ (vpath)) if we "$ (VPath) value is" src: ./ Headers ", then" $ (PatSubst%, - I%, $ (Subst:,, $ (vPath)) "will return" -isrc -i .. / Headers, this is the parameter of the CC or GCC search header file path. Third, the file name operation function Let's introduce the function we need to process the file name. The parameter string of each function will be treated as one or a series of file names. $ (DIR ) Name: Take the directory function - DIR. Function: Take out the directory section from the file name sequence . The directory section refers to the part before the last backslash ("/"). If there is no backslash, then "back" ./ ". Returns: Returns the directory section of the file name sequence . Example: $ (Dir src / foo.c Hacks) The return value is "src / ./". $ (NOTDIR ) Name: Take the file function - NOTDIR. Function: Take an unlibular part from the file name sequence . The non-directory part refers to the part after the last backslash ("/"). Returns: Returns the non-directory part of the file name sequence . Example: $ (notdir src / foo.c Hacks) Return value is "foo.c Hacks". $ (Suffix ) Name: Take the suffix function - Suffix. Function: Take out the suffix of each file name from the file name sequence . Returns: Returns the suffix sequence of the file name sequence , if the file has no suffix, return the empty string. Example: $ (SUFFIX SRC / FOO.c SRC-1.0 / bar.c Hacks) Return Value ".c .c". $ (BaseName ) Name: Take the prefix function - Basename. Function: Take out the prefix section of each file name from the file name sequence . Returns: Returns the prefix sequence of the file name sequence , if the file is not prefix, return the empty string. Example: $ (BaseName Src / Foo.c SRC-1.0 / bar.c Hacks) Return Value is "SRC / FOO SRC-1.0 / Bar Hacks".

$ (Addsuffix , ) Name: Add the assault function - ADDSUFFIX. Function: Adding the suffix to each word in . Returns: Returns the file name sequence of the plus suffix. Example: $ (addsuffix .c, foo bar) Return value is "foo.c bar.c". $ (AddPrefix , ) Name: Add the prefix function - ADDPREFIX. Function: Adding the prefix to each word in . Returns: Returns the file name sequence of the added prefix. Example: $ (AddPRefix SRC /, FOO BAR) Return Value is "SRC / Foo Src / Bar". $ (Join , ) Name: Connection Function - Join. Function: Add the words in to the words of . If the number of words of is more than , the number of words in will remain in the original. If the word number of is more than , the word "list" will be copied to . Returns: Returns the connected string. Example: $ (Join AAA BBB, 111 222 333) Return value is "AAA111 BBB222 333". FOREACH function

The Foreach function is very different from other functions. Because this function is used for looping, the Foreach function in the makefile is almost in the FOR statement in the UNIX standard shell (/ bin / sh), or the Foreach statement in the c-shell (/ bin / csh). Built. Its syntax is:

$ (Foreach , , )

This function means that the words in the parameter are taken out one by one on the variable specified by the parameter , and then the expression included in is executed. Each time returns a string, and each character returned by is separated in a space, and finally each string returned by The entire string (separated in space) will be the return value of the foreach function.

Therefore, is preferably a variable name, can be an expression, and in is usually enumerated in ["words in [TEXT". for example:

Names: = a b c d

Files: = $ (Foreach N, $ (Names), $ (N) .o)

In the above example, the words in the $ (name) will be taken out, and save the variable "n", "$ (n) .o" calculates a value each time according to "$ (N)", these values Space separation, finally the return as a Foreach function, so (files) value is "AO BO CO DO".

Note that parameters in Foreach are a temporary local variable. After the foreach function is executed, the variables of parameter will not function, and its scope is only in the foreach function. V. IF functions

The IF function is very similar to the conditional statement supported by the GNU's Make - IFEQ (see the chapter described earlier), the syntax of the IF function is:

$ (if , )

Or

$ (if , )

It can be seen that the IF function can contain "ELSE" sections, or not. That is, the parameter of the IF function can be two or three. The parameter is an expression of IF. If it returns a non-empty string, then this expression is equivalent to returning, so will be calculated, otherwise will be calculated .

The return value of the IF function is if is a true (non-empty string), that will be the return value of the entire function, if is a false (empty string), then will be the return value of the entire function, if is not defined, the entire function returns the empty string.

Therefore, and

Sixth, Call function

The Call function is the only function that can be used to create new parameters. You can write a very complex expression. In this expression, you can define many parameters, then you can use the Call function to pass parameters to this expression. Its syntax is:

$ (Call , , , ...)

When Make performs this function, the variables in the parameter, such as $ (1), $ (2), $ (3), will be replaced in turn by parameter , , . The return value of is the return value of the Call function. For example: Reverse = $ (1) $ (2)

Foo = $ (Call Reverse, A, B)

So, the value of foo is "a b". Of course, the order of the parameters can be customized, not necessarily the order, such as:

REVERSE = $ (2) $ (1)

Foo = $ (Call Reverse, A, B)

The value of the FOO at this time is "B A".

Seven, Origin functions

The Origin function is not like other functions, he does not operate the value of the variable, he just tells you where your variable is coming? Its syntax is:

$ (Origin )

Note that is the name of the variable, should not be referenced. So you'd better use the "$" character in . The origin function tells you the "birth situation" of this variable with its return value. Below, it is the return value of the origin function:

"Undefined"

If has never defined, the origin function returns this value "undefined". Default "

If is a default definition, such as "CC" variable, this variable we will tell later.

"Environment"

If is an environment variable, the "- e" parameter is not opened when Makefile is executed.

File

If This variable is defined in the makefile.

"Command Line"

If This variable is defined by the command line.

"OVERRIDE"

If is redefined by the OVERRIDE indicator.

Automatic "

If is an automated variable in the run. About automation variables will be described later.

This information is very useful for we write makefile, for example, suppose we have a Makefile package that packs a definition file Make.def, defined a variable "Bletch" in make.def, and there is an environment variable in our environment "BLETCH", at this time, we want to judge, if the variable comes from the environment, then we will redefine it, if you come from the Make.DEF or the command line, then we don't redefine it. So, in our makefile, we can write this:

IFDEF BLETCH

Ifeq "$ (Origin Bletch)" Environment "

Bletch = BARF, GAG, ETC.

ENDIF

ENDIF

Of course, you may say that you can redefine the variables in the environment using the Override keyword? Why do you need this step? Yes, we use Override to achieve such an effect, but Override is too rude, it will overwrite the variables defined from the command line, and we just want to redefine the environment, and do not want to redefine the command line Come.

Eight, shell function

The shell function is not like other functions. As the name suggests, its parameters should be the command of the operating system shell. It and the reverse "` "are the same function. That is to say, the shell function returns the output after executing the operating system command as a function. Thus, we can generate a variable with an operating system command and a string handle command awk, sed, etc., such as:

Contents: = $ (Shell Cat Foo)

Files: = $ (shell echo * .c)

Note that this function will generate a shell program to execute the command, so you have to pay attention to its run performance, if you have some complicated rules in your makefile, and use this function, so you are harmful to your system performance. . Especially the macked rules of makefile may make your shell function to do much more than what you imagine.

Nine, control the function of MAKE

Make provides some functions to control the operation of Make. Typically, you need to detect some runtime information when running makefile, and determine this information, you let Make continue, or stop.

$ (Error )

Generate a fatal error, is an error message. Note that the Error function will not generate error messages in one use, so if you define it in a certain variable, it is also possible to use this variable in a subsequent script. For example: Example 1:

IFDef Error_001

$ (Error Error IS $ (Error_001))

ENDIF

Example 2:

Err = $ (Error Found An Error!)

.Phony: ERR

Err:; $ (ERR)

The example will generate an Error call when the variable error_001 is defined, and the example two will occur when the directory ERR is executed.

$ (WARNING )

This function is like an Error function, but it does not let Make exits, just output a warning message, and make continues. Make's run ------ Generally, the simplest is to enter the Make command directly on the command line, and the make command will find the makefile of the current directory to execute, everything is automatic. But sometimes you may just want Make to recompile certain files, not the entire project, and sometimes you have several compilation rules, you want to use different compilation rules in different times, and so on. This chapter is to tell how to use the make command. First, Make's exit code make commands have three exit codes: 0 - means successfully executed. 1 - Any error occurs if the Make is running, it returns 1. 2 - If you use the "-q" option of make, and make make some targets don't need to be updated, then returns 2. Make's related parameters we will tell in subsequent chapters. Second, the specified Makefile We said that GNU Make finds the default Makefile rules to find three files in the current directory - "gnumakefile", "makefile", and "makefile". It is found in order to find these three files, once found, start reading this file and execute. Currently, we can also assign a special name for Makefile to the Make command. To achieve this feature, we want to use the "-f" or "-file" parameter ("--makefile" parameter). For example, we have a Makefile name is "hchen.mk", then we can let Make to execute this file: make -f hchen.mk If the command line in Make is, you don't only use it once. " f "Parameters, then all specified Makefile will be delivered together to Make. Third, the specified goal is generally, MAKE's ultimate goal is the first target in Makefile, and other objectives are generally coming from this target. This is the default behavior of Make. Of course, in general, your Makefile's first goal is made up of many targets, you can indicate Make to complete the target you specify. To achieve this, it is very simple. You need to directly follow the target after the board command (as shown in the "Make Clean" form) any target in Makefile can be specified as the ultimate goal, but except "-" Head, or contains "=" target, because there is a target of these characters, will be parsed into command line parameters or variables. Even the goals we have clearly written can also become the ultimate goal of Make, that is, as long as Make can find its implicit rules, this implicit target can also be specified as the ultimate goal. There is a Make environment variable called "makecmdgoals". The list of the ultimate target you specify is stored in this variable. If you don't specify the target, this variable is null. This variable allows you to use in some particular situations. For example, the following example: Sources = foo.c bar.c ifneq ($ (Makecmdgoals), Clean) INCLUDE $ (Sources: .c = .d) Endif Based on this example, as long as the command we entered is not "Make Clean" Then Makefile automatically contains two Makefiles "foo.d" and "bar.d".

With the specified ultimate goal, you can easily compile our programs, such as the following example: .phony: all all: proG1 prog2 prog3 prog4 From this example, we can see that there are four need to compile in this makefile Program - "Prog1", "PROG2", "PROG3", and "PROG4", we can use the "Make All" command to compile all the targets (if you put all the first goals, then just execute "Make "), We can also use" make prop2 "to compile the target" prog2 "separately. Often Make can specify all the goals in all makefile, then "pseudo-target", so we can make our makefile to complete different things based on this nature. In UNIX world, when the software is released, especially the release of this open source software, its Makefile contains compilation, installation, packaging and other functions. We can refer to this rule to write the goals in our makefile. "All" pseudo-objective is the goal of all goals, and its feature is generally compiled all the goals. "Clean" pseudo-objective function is to delete all files created by Make. "Install" pseudo-objective function is to install the compiled program, in fact, copy the target execution file to the specified target. "Print" The function of this pseudo-target is to illustrate the changed source file. "TAR" pseudoactive function is to package the source package backup. That is a TAR file. "DIST" pseudo-target function is to create a compressed file, which is generally pressed into the z file. Or GZ file. "Tags" pseudo-objective function is to update all the goals for complete recompilation. "Check" and "Test" are generally used to test the process of Makefile. Of course, a project's makefile does not have to write such a goal, these things are gnu's things, but I think the GNU has a certain thing (waiting for the program files under your UNIX. You will find these features very useful), it is just a description. If you want to write this function, it is best to use this name to name your goals, so that some, the normative benefits is - do not explain, Everyone understands. And if you have these features in your makefile, one is very practical, and the other is that you can look very professional (not the work of the beginner). Fourth, the inspection rules are sometimes, we don't want our rules in our makefile, we just want to check our commands or execute the sequence. So we can use the following parameters of the make command: "-n" "--just-print" "--dry-run" "--Recon" does not execute parameters, these parameters are just print commands, regardless of the goal to update, The rules and the commands under the joint rules are printed, but they do not execute, these parameters are very useful for us to debug Makefile. "-T" "--Touch" means that the time update of the target file, but does not change the target file. That is, Make pretend to be compiled, but is not a real compilation target, just turn the target into a compiled state.

The behavior of "-q" "--question" is the meaning of finding the target, that is, if the target exists, then what else does not output, and of course, it will not perform compilation, if the target does not exist, it will print An error message. "-W " --what-if = "" --ness-new = "" --new-file = "This parameter needs to specify a file. Generally, the source file (or dependent file), Make will run according to the rule, in general, in general, can be used with the "-n" parameter to view the rule command that occurred in this dependency file. Another interesting usage is to combine "-P" and "-v" to output the information when Makefile is executed (this will be described later). V. Make's parameters list all the parameters definitions of all GNU Make 3.80. Other versions of the MAKE of the manufacturer are similar, but the specific parameters of other manufacturers make specific parameters, please refer to the respective product documents. The role of "-b" "- m" these two parameters is to ignore compatibility with other version of Make. "-B" "- always-make" thinks that all goals need to be updated (recompile). "-C

" "- directory = " Specifies the directory to read the Makefile. If there is a plurality of "-c" parameters, Make's interpretation is the rear path as the relative path as the previous directory as the specified directory. Such as: "make -c ~ hchen / test -c prog" equivalent to "make -c ~ hchen / test / prog". "-Debug [= ]" outputs the debug information of MAKE. It has several different levels to choose from, if there is no parameters, that is, the simplest debugging information is output. The following is the value of : a - that is, all, output all debugging information. (It will be very much) B - that is, Basic, only output simple debugging information. That is, the output does not require recompile. V - is also verbose, above the level of B option. The output information includes which makefile is parsed, does not need to be recompiled dependent file (or dependent target), and the like. I - that is, Implicit, the implicit rule is output. J - is also the JOBS, the output execution rules, such as the PID, return code, etc. of the command. M - is Makefile, output Make Read Makefile, update makefile, and executes Makefile information. "-D" is equivalent to "--debug = a". "-E" "- Environment-overrides" indicates the value of the value of the environment variable overrides the variable defined in the Makefile. "-F = " "- file = " - Makefile = "Specifies the Makefile you need to do. "-H" "- help" displays help information. "-I" "- ignore-errors" ignores all errors during execution. "-I " "- INCLUDE-DIR = " Specifies a search target that is included in the Makefile. You can use multiple "-i" parameters to specify multiple directories. "-J []" "" "" means the number of running commands simultaneously.

If there is no this parameter, how much can be run when Make runs the command. If there is more than one "-j" parameter, then only the last "-j" is valid. (Note This parameter is useless in MS-DOS) "-k" "- keep-going" error does not stop running. If generated a target fail, it will not be executed if the goal is dependent on it. "-L " "- max-load [= ]" Specifies the load of the Make running command. "-N" "- Just-print" "- DRY-RUN" "- Recon" only outputs the command sequence during execution, but does not execute. "-O " - Old-file = "" - Assume-old = "does not regenerate the specified , even if the dependent file of this goal is new in it. "-P" "- print-data-based" outputs all data in Makefile, including all rules and variables. This parameter will make a simple makefile output a bunch of information. If you just want to output information, you can use the "Make -QP" command without performing Makefile. If you want to see the preset variables and rules before performing makefile, you can use "make -f / dev / null". The information of this parameter output will contain the file name and line number of your makefile file, so use this parameter to debug your makefile will be very useful, especially when your environment variable is very complicated. "-Q" "- question" does not run the command, nor does it output. Just check if the specified target needs to be updated. If it is 0, it means to update, if it is 2, an error occurs. "-R" "- no-builtin-rules" is forbidden to use Make to use any implicit rules. "-R" "- no-builtin-variabes" prohibits make from using any implicit rules that do on variables. "-S" "- Silent" - Quiet "does not output the output of the command at the command. "-S" "- no-keyp-going" "- STOP" cancels the "-k" option. Because some, make inherited from the environment variable "makeflags". So you can use this parameter in the command line to make the "-k" option in the environment variables failed. "-T" "- touch" is equivalent to Unix's touch command, just turning the dates of the target into the latest, that is, blocking the command to generate the target from running. "-V" "- version" outputs the version of the Make program, copyright, etc. About Make. "-W" "- print-directory" outputs information before and after running Makefile. This parameter is useful for tracking nested calls Make. "--NO-print-Directory" prohibits "-w" option. "-W " - What-if = "" - new-file = "" - Assume-file = "Assume the target need to update, if and "-N" option is used, then this parameter outputs the running action when the target update is output. If there is no "-n", just like the "touch" command running UNIX, the modification time of is the current time. "--Warn-undefined-variables" As long as Make finds an undefined variable, then the warning message is output.

Implicit rules ---- When we use Makefile, there are some frequent uses, and how often is very high, for example, we compile the C / C source program for intermediate target files (UNIX is [.o] File, Windows is [.Obj] file). This chapter tells some "implied" in makefile, earlier, no need to write the rules. "Implied rules" is also a practice. Make will run according to this "convention" heart, even if there is no writing rules in our makefile. For example, compiling the [.c] file into the rule of [.o] file, you don't have to write it all, make it automatically derived this rule and generates the [.o] file we need. The "Implied Rule" will use some of our system variables, we can change the value of these system variables to customize the parameters of the rules of the rules. If the system variable "cflags" can control compiler parameters when compiling. We can also write down your implicit rules through the Mode Rules. There will be many restrictions with "Suffix Rules" to define implicit rules. Using Mode Rules will be more intelligent and clear, but the Suffix Rules can be used to ensure our makefile compatibility. We understand the "implicit rules", allowing us to better serve us, will let us know something "convention and customary", and not so that we feel inexplicable when we are running Makefile. Of course, anything is contradictory, water can be boat, can also come to the boat, so sometimes the "implied rules" will also cause non-small troubles. Only by knowing it, we can use it better. First, use implied rules If you want to use an implicit rule to generate the goals you need, you need to do this is not to write the rules of this goal. So, make attempts to automatically derive the rules and commands that generate this goal. If Make can automatically derive the rules and commands of this goal, then this behavior is the automatic derivation of implicit rules. Of course, the implicit rules are some things that make prior approximately. For example, we have the following Makefile: foo: foo.o bar.o cc -o foo foo.o bar.o $ (cflags) $ (ldflags) We can notice that this makefile does not write how to generate foo .o and bar.o Rules and commands of these two goals. Because Make's "Implied Rule" feature automatically automatically derives the dependence targets and generation commands of these two goals. Make will find the rules that can be used in your own Implicit Rules library. If you find it, you will use it. If you can't find it, you will report it wrong. In the example above, the implied rule called for the Make call is to set the dependency file of [.o] to [.c], and use C Compile command "CC -C $ (cflags) [.c] "To generate the goal of [.o]. In other words, we don't have to write the following two rules: foo.o: foo.c cc foo.c $ (cflags) bar.o: bar.c cc -c bar.c $ (cflags) Because this is already a "agreement", make and us set up the rules of the "CC" to generate the [.o] file with the CC ", which is implicit rules. Of course, if we write your own rules for the [.o] file, Make will not automatically derive and call the implicit rules, which will be faithfully executed in accordance with our write.

Also, in the "implied rules library" of Make, each implied rule has its order in the library, the more often used, so this will cause us to show us even if we show The target dependence is specified, and MAKE will not be tubed. As such a rule (no command): foo.o: foo.p Dependent file "foo.p" (source file of the Pascal program) is meaningless. If there is a "foo.c" file in the directory, then our implicit rules will take effect, and will generate a foo.o file through the compiler of C. Because, in the implicit rule, the rule of PASCAL appears after the rule of C, so Make finds the rules that can generate foo.o will no longer look for the next rule. If you really don't want any implicit rules to derive, then you don't just write the "dependency rules" without writing the command. Second, the implicit rule list here We will tell all the implicit rules of all pre-set (which is Make built). If we don't know the rules, Make will find the required rules and commands in these rules. Of course, we can also use Make's parameters "-r" or "--no-builtin-rules" option to cancel all pre-set implicit rules. Of course, even if we specify the "-r" parameter, some implicit rules will take effect, because there are many implicit rules that use the Suix Rules to define, so as long as there is implicit rules Suffix List (also defined in the target .Suffixes dependent target), the implicit rules will take effect. The default suffix list is: .out, .a, .ln, .o, .c, .cc, .c, .p, .f, .f, .r, .y, .l, .s, .s , .mod, .ssym, .def, .h, .info, .dvi, .tex, .texinfo, .Texi, .txinfo, .w, .ch .web, .sh, .elc, .l. For details, we will talk later. Still let's take a look at the common implicit rules. 1. Compile the implied rules of the C program. The dependent target of " .o" is automatically derived as " .c", and its generation command is "$ (cc) -c $ (cppflags) $ (cflags)" 2, compile C programs Implicit rules. The dependent target of " .o" is automatically derived as " .cc" or " .c", and its generation command is "$ (cxx) -c $ (cppflags) $ (Cflags). (It is recommended to use ".cc" as a suffix of C source files, not ".c") 3. Compile the impact rules for the Pascal program. The dependent target of " .o" is automatically derived as " .p", and its generation command is "$ (pc) -c $ (pflags)". 4, compile the implicit rules for the Fortran / RatFor program. The dependent target of " .o" is automatically derived as " .r" or " .f" or " .f", and its generation command is: ".f" "$ (Fc) -c $ (fflags)" ".f" "$ (fc) -c $ (fflags) $ (cppflags)" ".f" $ (fc) -c $ (fflags) $ (RFlags) "5, the implicit rules for preprocessing the Fortran / RatFor program. The dependent target of " .f" is automatically derived to " .r" or " .f".

This rule is just converting the Ratfor or has a pre-processed Fortran program to a standard Fortran program. The commands used are: ".f" "$ (fc) -f $ (cppflags) $ (fflags)" ".r" "$ (fc) -f $ (fflags) $ (rflags)" 6, compile MODULA The implicit rules of the program. The dependent target of " .sym" is automatically derived as " .def", and its generation command is: "$ (M2C) $ (m2flags) $ (deffflags)." The dependent target of "" is automatically derived as " .mod", and its generation command is: "$ (M2C) $ (M2FLAGS) $ (MODFLAGS)." 7, assembly and assembly pre-processing implicit rules. The dependent target of " .o" is automatically derived as " .s", the default use of the compilation "AS", and its generation command is: "$ (as) $ (asflags)". The dependent objective of " .s" will be automatically derived as " .s", the default uses C precompiled translator "CPP", and its generation command is: "$ (as) $ (asflags)" . 8, link the implicit rules for the Object file. "" target depends on " .o", running the linker generation by running the C's compiler (generally "LD"), which generates commands: "$ (cc) $ (ldflags) < n> .o $ (LOADLIBES) $ (LDLIBS). This rule is valid for only one source file project, but also valid for multiple Object files (generated by different source files). For example, if the following rules: x: yo zo, "XC", "YC", and "ZC" exist, the implicit rule will execute the following command: cc -c xc -o xo cc -c yc -o yo cc -c zc -o ZO CC XO YO ZO -OX RM -F XO RM -F YO RM -F ZO If there is no source file (such as XC in the previous example) and your target name (as X) in the above example, then, You'd better write your own generation rules, otherwise, implied rules will be wrong. 9. Implicit rules when YACC C procedures. " .c" dependent file is automatically derived as "n.y" (YACC generated file), and its generation command is: "$ (YACC) $ (YFALGS)". ("YACC" is a syntax analyzer, about the details, please check the relevant information) 10, the implicit rules when the Lex C program. " .c" dependent file is automatically derived to "N.L" (LEX generated file), which generates commands: "$ (lex) $ (lfalgs)". (For details on "Lex", please see the relevant information) 11, the implicit rules when the Lex RatFor program. " .r" dependent file is automatically derived as "N.L" (LEX generated file), and its generation command is: "$ (lex) $ (lfalgs)". 12. Create an implicit rules for the LINT library from the C program, YACC file or LEX file. The dependencies of " .ln" (LINT generated file) are automatically derived to "N.c", which generates commands: "$ (LINTFALGS) $ (cppflags) -i".

The same rule is also the same for " .y" and " .l". Third, the variables used by the implicit rules are basically used in the commands in the implicit rules, basically use some pre-set variables. You can change these variables in your makefile, or incorporate these values ​​in the command line of make, or set these values ​​in your environment variable, no matter how, just set these specific variables, Then it will work for implicit rules. Of course, you can also use Make's "-r" or "--no-builtin-variables" parameter to cancel the role of the variable you defined on the implicit rule. For example, the first implicit rule-compiling the implied rule of the C program is "$ (cc) -c $ (cflags) $ (cppflags). Make default compile command is "CC", if you redefine the variable "$ (cc)" to "GCC", turn the variable "$ (cflags)" to "-g", then implicit rules The command will be executed in "GCC -C -G $ (cppflags). We can divide the variables used in the implicit rules into two: one is a command, such as "CC"; one is the parameter phase, such as "cflags". Below is the variables used in all implicit rules: 1, the variables of the command. AR function library package program. The default command is "ar". AS assembly language compiler. The default command is "AS". CC C language compiler. The default command is "CC". CXX C language compiler. The default command is "G ". CO expands the file program from the RCS file. The default command is "CO". The preprocessor of the CPP C program (output is a standard output device). The default command is "$ (cc) -e". FC FORTRAN and RATFOR compiler and pre-processes. The default command is "F77". GET extension files from the SCCS file. The default command is "get". Lex Lex method analyzer program (for C or Ratfor). The default command is "lex". PC Pascal language compiler. The default command is "PC". YACC YACC Grammar Analyzer (for C procedures). The default command is "YACC". Yaccr Yacc Grammar Analyzer (for the Ratfor program). The default command is "Yacc -R". MakeInfo converts the TexInfo source file (.TEXI) to the INFO file program. The default command is "makeinfo". Tex creates a program from the Tex DVI file from the TEX source file. The default command is "tex". Texi2DVI creates a program from the TexInfo source file to create an army TEX DVI file. The default command is "texi2dvi". Weave converts web to tex program. The default command is "weave". CWEAVE converts C Web to TEX program. The default command is "CWEAVE". Tangle converts the web to the Pascal language program. The default command is "tangle". Ctangle converts C Web to C. The default command is "ctangle". RM deletes the file command. The default command is "RM -F". 2. These variables below the command parameters are the parameters of the relevant order. If there is no default value, its default value is empty. Arflags Function Library Package Ar Command Parameters. The default is "RV". Asflags assembly language compiler parameters. (When ".s" or ".s" file is displayed clearly). CFLAGS C language compiler parameters. CXXFLAGS C language compiler parameters. COFLAGS RCS command parameters. CPPFLAGS C Preprocessor parameters. (C and Fortran compilers are also used).

FFlags Fortran language compiler parameters. GFLAGS SCCS "Get" program parameters. LDFLAGS linker parameters. (Such as "LD") LFLAGS LEX Grammar Analyzer Parameters. Pflags Pascal language compiler parameters. The Fortran compiler parameter of the RFLAGS Ratfor program. YFLAGS YACC Grammar Analyzer Parameters. Fourth, the implicit rules chain sometimes, one goal may be rooted by a series of implicit rules. For example, an [.o] file generation may be first included with the [.y] file of YACC first [.c], then generate it again by the compiler of C. We call this series of implicit rules "implicit rules chain". In the above example, if the file [.c] exists, then directly call the implied rules of the compiler, if there is no [.c] file, but there is a [.y] file, then YACC implicit rules Will be called, generate the [.c] file, then call the impact rules for C-compilation ultimately by [.c] to generate the [.o] file to achieve the goal. We call this [.c] file (or target) called an intermediate goal. Anyway, Make will work hard to automatically derive all methods of generating the goals, regardless of the intermediate targets, they will take all implicit rules and the rules you write, and try to achieve goals, so sometimes May make you feel strange, how do my goal be generated? How is my makefile be crazy? By default, there are two places in the intermediate target, it is different from the general goals: 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 successful, then the resulting intermediate target file will be deleted in "RM -F" during the final goal. Typically, a file that is specified by Makefile to target or dependent the target cannot be treated as an intermediary. However, you can clearly illustrate a file or a target is an intermediary target, you can use pseudo-target ". InterMediate" to force the declaration. You can also prevent Make automatically delete the intermediate target. To do this, you can use the pseudo-target ". Secondary" to force the declaration (such as: .secondary: sec). You can also specify your goals to specify (eg:%. O) into the target ".precious" dependent object to save the intermediate file generated by the implicit rule. In the "Implied Rules Chain", it is forbidden to appear twice or more, so that in order to prevent unlimited recursive conditions when Make is automatically derived. Make will optimize some special implicit rules without generating an intermediate file. For example, from the file "foo.c" to generate the target program "foo", according to the truth, make it compiles the generation of the intermediate file "foo.o", then links into "foo", but in actual conditions, this action can be by one The "cc" command is completed (cc -o foo foo.c), so optimized rules will not generate an intermediate file.

Implicit rules ---- When we use Makefile, there are some frequent uses, and how often is very high, for example, we compile the C / C source program for intermediate target files (UNIX is [.o] File, Windows is [.Obj] file). This chapter tells some "implied" in makefile, earlier, no need to write the rules. "Implied rules" is also a practice. Make will run according to this "convention" heart, even if there is no writing rules in our makefile. For example, compiling the [.c] file into the rule of [.o] file, you don't have to write it all, make it automatically derived this rule and generates the [.o] file we need. The "Implied Rule" will use some of our system variables, we can change the value of these system variables to customize the parameters of the rules of the rules. If the system variable "cflags" can control compiler parameters when compiling. We can also write down your implicit rules through the Mode Rules. There will be many restrictions with "Suffix Rules" to define implicit rules. Using Mode Rules will be more intelligent and clear, but the Suffix Rules can be used to ensure our makefile compatibility. We understand the "implicit rules", allowing us to better serve us, will let us know something "convention and customary", and not so that we feel inexplicable when we are running Makefile. Of course, anything is contradictory, water can be boat, can also come to the boat, so sometimes the "implied rules" will also cause non-small troubles. Only by knowing it, we can use it better. First, use implied rules If you want to use an implicit rule to generate the goals you need, you need to do this is not to write the rules of this goal. So, make attempts to automatically derive the rules and commands that generate this goal. If Make can automatically derive the rules and commands of this goal, then this behavior is the automatic derivation of implicit rules. Of course, the implicit rules are some things that make prior approximately. For example, we have the following Makefile: foo: foo.o bar.o cc -o foo foo.o bar.o $ (cflags) $ (ldflags) We can notice that this makefile does not write how to generate foo .o and bar.o Rules and commands of these two goals. Because Make's "Implied Rule" feature automatically automatically derives the dependence targets and generation commands of these two goals. Make will find the rules that can be used in your own Implicit Rules library. If you find it, you will use it. If you can't find it, you will report it wrong. In the example above, the implied rule called for the Make call is to set the dependency file of [.o] to [.c], and use C Compile command "CC -C $ (cflags) [.c] "To generate the goal of [.o]. In other words, we don't have to write the following two rules: foo.o: foo.c cc foo.c $ (cflags) bar.o: bar.c cc -c bar.c $ (cflags) Because this is already a "agreement", make and us set up the rules of the "CC" to generate the [.o] file with the CC ", which is implicit rules. Of course, if we write your own rules for the [.o] file, Make will not automatically derive and call the implicit rules, which will be faithfully executed in accordance with our write.

Also, in the "implied rules library" of Make, each implied rule has its order in the library, the more often used, so this will cause us to show us even if we show The target dependence is specified, and MAKE will not be tubed. As such a rule (no command): foo.o: foo.p Dependent file "foo.p" (source file of the Pascal program) is meaningless. If there is a "foo.c" file in the directory, then our implicit rules will take effect, and will generate a foo.o file through the compiler of C. Because, in the implicit rule, the rule of PASCAL appears after the rule of C, so Make finds the rules that can generate foo.o will no longer look for the next rule. If you really don't want any implicit rules to derive, then you don't just write the "dependency rules" without writing the command. Second, the implicit rule list here We will tell all the implicit rules of all pre-set (which is Make built). If we don't know the rules, Make will find the required rules and commands in these rules. Of course, we can also use Make's parameters "-r" or "--no-builtin-rules" option to cancel all pre-set implicit rules. Of course, even if we specify the "-r" parameter, some implicit rules will take effect, because there are many implicit rules that use the Suix Rules to define, so as long as there is implicit rules Suffix List (also defined in the target .Suffixes dependent target), the implicit rules will take effect. The default suffix list is: .out, .a, .ln, .o, .c, .cc, .c, .p, .f, .f, .r, .y, .l, .s, .s , .mod, .ssym, .def, .h, .info, .dvi, .tex, .texinfo, .Texi, .txinfo, .w, .ch .web, .sh, .elc, .l. For details, we will talk later. Still let's take a look at the common implicit rules. 1. Compile the implied rules of the C program. The dependent target of " .o" is automatically derived as " .c", and its generation command is "$ (cc) -c $ (cppflags) $ (cflags)" 2, compile C programs Implicit rules. The dependent target of " .o" is automatically derived as " .cc" or " .c", and its generation command is "$ (cxx) -c $ (cppflags) $ (Cflags). (It is recommended to use ".cc" as a suffix of C source files, not ".c") 3. Compile the impact rules for the Pascal program. The dependent target of " .o" is automatically derived as " .p", and its generation command is "$ (pc) -c $ (pflags)". 4, compile the implicit rules for the Fortran / RatFor program. The dependent target of " .o" is automatically derived as " .r" or " .f" or " .f", and its generation command is: ".f" "$ (Fc) -c $ (fflags)" ".f" "$ (fc) -c $ (fflags) $ (cppflags)" ".f" $ (fc) -c $ (fflags) $ (RFlags) "5, the implicit rules for preprocessing the Fortran / RatFor program. The dependent target of " .f" is automatically derived to " .r" or " .f".

This rule is just converting the Ratfor or has a pre-processed Fortran program to a standard Fortran program. The commands used are: ".f" "$ (fc) -f $ (cppflags) $ (fflags)" ".r" "$ (fc) -f $ (fflags) $ (rflags)" 6, compile MODULA The implicit rules of the program. The dependent target of " .sym" is automatically derived as " .def", and its generation command is: "$ (M2C) $ (m2flags) $ (deffflags)." The dependent target of "" is automatically derived as " .mod", and its generation command is: "$ (M2C) $ (M2FLAGS) $ (MODFLAGS)." 7, assembly and assembly pre-processing implicit rules. The dependent target of " .o" is automatically derived as " .s", the default use of the compilation "AS", and its generation command is: "$ (as) $ (asflags)". The dependent objective of " .s" will be automatically derived as " .s", the default uses C precompiled translator "CPP", and its generation command is: "$ (as) $ (asflags)" . 8, link the implicit rules for the Object file. "" target depends on " .o", running the linker generation by running the C's compiler (generally "LD"), which generates commands: "$ (cc) $ (ldflags) < n> .o $ (LOADLIBES) $ (LDLIBS). This rule is valid for only one source file project, but also valid for multiple Object files (generated by different source files). For example, if the following rules: x: yo zo, "XC", "YC", and "ZC" exist, the implicit rule will execute the following command: cc -c xc -o xo cc -c yc -o yo cc -c zc -o ZO CC XO YO ZO -OX RM -F XO RM -F YO RM -F ZO If there is no source file (such as XC in the previous example) and your target name (as X) in the above example, then, You'd better write your own generation rules, otherwise, implied rules will be wrong. 9. Implicit rules when YACC C procedures. " .c" dependent file is automatically derived as "n.y" (YACC generated file), and its generation command is: "$ (YACC) $ (YFALGS)". ("YACC" is a syntax analyzer, about the details, please check the relevant information) 10, the implicit rules when the Lex C program. " .c" dependent file is automatically derived to "N.L" (LEX generated file), which generates commands: "$ (lex) $ (lfalgs)". (For details on "Lex", please see the relevant information) 11, the implicit rules when the Lex RatFor program. " .r" dependent file is automatically derived as "N.L" (LEX generated file), and its generation command is: "$ (lex) $ (lfalgs)". 12. Create an implicit rules for the LINT library from the C program, YACC file or LEX file. The dependencies of " .ln" (LINT generated file) are automatically derived to "N.c", which generates commands: "$ (LINTFALGS) $ (cppflags) -i".

The same rule is also the same for " .y" and " .l". Third, the variables used by the implicit rules are basically used in the commands in the implicit rules, basically use some pre-set variables. You can change these variables in your makefile, or incorporate these values ​​in the command line of make, or set these values ​​in your environment variable, no matter how, just set these specific variables, Then it will work for implicit rules. Of course, you can also use Make's "-r" or "--no-builtin-variables" parameter to cancel the role of the variable you defined on the implicit rule. For example, the first implicit rule-compiling the implied rule of the C program is "$ (cc) -c $ (cflags) $ (cppflags). Make default compile command is "CC", if you redefine the variable "$ (cc)" to "GCC", turn the variable "$ (cflags)" to "-g", then implicit rules The command will be executed in "GCC -C -G $ (cppflags). We can divide the variables used in the implicit rules into two: one is a command, such as "CC"; one is the parameter phase, such as "cflags". Below is the variables used in all implicit rules: 1, the variables of the command. AR function library package program. The default command is "ar". AS assembly language compiler. The default command is "AS". CC C language compiler. The default command is "CC". CXX C language compiler. The default command is "G ". CO expands the file program from the RCS file. The default command is "CO". The preprocessor of the CPP C program (output is a standard output device). The default command is "$ (cc) -e". FC FORTRAN and RATFOR compiler and pre-processes. The default command is "F77". GET extension files from the SCCS file. The default command is "get". Lex Lex method analyzer program (for C or Ratfor). The default command is "lex". PC Pascal language compiler. The default command is "PC". YACC YACC Grammar Analyzer (for C procedures). The default command is "YACC". Yaccr Yacc Grammar Analyzer (for the Ratfor program). The default command is "Yacc -R". MakeInfo converts the TexInfo source file (.TEXI) to the INFO file program. The default command is "makeinfo". Tex creates a program from the Tex DVI file from the TEX source file. The default command is "tex". Texi2DVI creates a program from the TexInfo source file to create an army TEX DVI file. The default command is "texi2dvi". Weave converts web to tex program. The default command is "weave". CWEAVE converts C Web to TEX program. The default command is "CWEAVE". Tangle converts the web to the Pascal language program. The default command is "tangle". Ctangle converts C Web to C. The default command is "ctangle". RM deletes the file command. The default command is "RM -F". 2. These variables below the command parameters are the parameters of the relevant order. If there is no default value, its default value is empty. Arflags Function Library Package Ar Command Parameters. The default is "RV". Asflags assembly language compiler parameters. (When ".s" or ".s" file is displayed clearly). CFLAGS C language compiler parameters. CXXFLAGS C language compiler parameters. COFLAGS RCS command parameters. CPPFLAGS C Preprocessor parameters. (C and Fortran compilers are also used).

FFlags Fortran language compiler parameters. GFLAGS SCCS "Get" program parameters. LDFLAGS linker parameters. (Such as "LD") LFLAGS LEX Grammar Analyzer Parameters. Pflags Pascal language compiler parameters. The Fortran compiler parameter of the RFLAGS Ratfor program. YFLAGS YACC Grammar Analyzer Parameters. Fourth, the implicit rules chain sometimes, one goal may be rooted by a series of implicit rules. For example, an [.o] file generation may be first included with the [.y] file of YACC first [.c], then generate it again by the compiler of C. We call this series of implicit rules "implicit rules chain". In the above example, if the file [.c] exists, then directly call the implied rules of the compiler, if there is no [.c] file, but there is a [.y] file, then YACC implicit rules Will be called, generate the [.c] file, then call the impact rules for C-compilation ultimately by [.c] to generate the [.o] file to achieve the goal. We call this [.c] file (or target) called an intermediate goal. Anyway, Make will work hard to automatically derive all methods of generating the goals, regardless of the intermediate targets, they will take all implicit rules and the rules you write, and try to achieve goals, so sometimes May make you feel strange, how do my goal be generated? How is my makefile be crazy? By default, there are two places in the intermediate target, it is different from the general goals: 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 successful, then the resulting intermediate target file will be deleted in "RM -F" during the final goal. Typically, a file that is specified by Makefile to target or dependent the target cannot be treated as an intermediary. However, you can clearly illustrate a file or a target is an intermediary target, you can use pseudo-target ". InterMediate" to force the declaration. You can also prevent Make automatically delete the intermediate target. To do this, you can use the pseudo-target ". Secondary" to force the declaration (such as: .secondary: sec). You can also specify your goals to specify (eg:%. O) into the target ".precious" dependent object to save the intermediate file generated by the implicit rule. In the "Implied Rules Chain", it is forbidden to appear twice or more, so that in order to prevent unlimited recursive conditions when Make is automatically derived. Make will optimize some special implicit rules without generating an intermediate file. For example, from the file "foo.c" to generate the target program "foo", according to the truth, make it compiles the generation of the intermediate file "foo.o", then links into "foo", but in actual conditions, this action can be by one The "cc" command is completed (cc -o foo foo.c), so optimized rules will not generate an intermediate file. Update the library file with the make ----------- The library file is the package file for the Object file (intermediate file compiled). Under UNIX, it is generally made by the command "AR" to complete the package. First, a function library file for the function library file consists of multiple files.

You can specify a library file and its composition in the following format: Archive (Member) This is not a command, and a target and dependence definition. In general, this usage is basically to serve "AR" commands. Such as: fooLib (Hack.o): Hack.o Ar Cr Foolib Hack.o If you want to specify multiple Member, you are separated by space, such as Foolib (Hack.o Kludge.O) equivalent: FOOLIB (HACK .o) FOOLIB (Kludge.O) You can also use the shell's file wildcard to define, such as foolib (*. o) Second, the implicit rule of the function library member When you search for an implicit rule of a goal, a special The characteristic is that if this goal is "A (m)" form, it will turn the target "(m)". So, if our member is "% .o" mode definition, and if we use "make foo.a" to call Makefile form, the implicit rule will go to "bar.o" rules. If there is no rule of bar.o, then the internal implicit rules take effect. Make will go to Bar.c file to generate bar.o. If you find it, the command executed by the make is as follows: cc -c bar.c -o bar.o ar r foo.a bar.o rm -f bar.o has a variable to pay attention to "$%", this is an automated variable for exclusive library files, and see "Automated variables" "one period. Third, the suffix rule of the library file You can use the Suffix Rules and "Include Rules" to generate a function library package file, such as: .ca: $ (cc) $ (cflags) $ (cppflags) -c $ O $ *. O $ (ar) R $ @ $ *. o $ (rm) $ *. o It is equivalent to: (% .o):% .C $ (cc) $ (cflags) $ (cppflags) -C $ <-O $ *. O $ (ar) R $ @ $ *. o $ () $ *. O III. Precautions When the library package file is generated, be careful to use the Make's parallel mechanism ( "-j" parameter). If multiple ar commands run on the same function library package at the same time, you can damage this library file. Therefore, in the future version of the Make, a mechanism should be provided to avoid parallel operations to occur on a function package file. But as far, you should not try not to use the "-j" parameter as much as possible. Subsequential - finally went to the end of the language, the above basically is all the details of the GNU Make's makefile. The Make's Make is basically like this, no matter what kind of make, it is based on the dependence of documents. It is basically following a standard.

80% of the technical details in this document apply to any make, I guess the content of the "function" may not be supported by other make, and I think different makers will have different implementations. I have no energy to view the GNU's make and VC's nmake, BCB Make, or what difference is made under other Unix, one is not enough, the second is because I basically use it under UNIX. Make, previously in Sco Unix and IBM AIX, now in Linux, Solaris, HP-UX, AIX, and Alpha, LINUX and Solaris are more. However, I can be sure that Make under UNIX, whether it is a platform, almost all the Make and CC / GCC compilers developed by Richard Stallman, and basically all GNU Make (all The UNIX machine is installed on the GNU, so there are more programs that use the GNU). The GNU's thing is still very good, especially after use, more and more sense of the power of the GNU software, and more and more feel that GNU is "killed" in the operating system (mainly Unix or even windows). For all the details of all the makers, we can not only use the Make tool to compile our programs, but also use Make to complete other work, because the commands in the rules can be under any shell, so in Unix You don't necessarily just use the compiler of the program language, you can also write other commands in Makefile, such as: Tar, AWK, Mail, Sed, CVS, Compress, LS, RM, YACC, RPM, FTP ..., etc. , Etc., to complete the function, file operation, file management, file operation, file management, file operation, and file management, such as "Program Packaging", "Program Backup", "Production Program Installation Pack", "Submit Code", "User Template", "Merge File", etc. Programming development design, or some other whimsical things. For example, when you write a bank trading process, because the bank's trading procedure is basically the same, you will see some general program templates for some transactions, and write some network communication, database operation, business operation. In one file, in these files, in these files, such as "@@ n, ### n" strange string labeled some locations, then write a transaction, just writing a specific process according to a specific rule, and finally When Make, use awk and sed to replace the "@@ n, ### n" in the template to a specific program, form a C file, and then compile. This action is very similar to the "extended C" language of the database (ie, "Exec SQL" in the C language executes the SQL statement. Before compiling CC / GCC, you need to use "extended C" translation, such as CPRE, It translates into standard C). If you have some more wonderful methods when using Make, please remember to tell me. Looking back, look at the whole document, I don't think I have just started to develop in Unix a few years ago, someone asked if I would not write Makefile, I didn't know what to say.

At first, I saw that someone turned "! Make" after writing the program in the VI, I thought it was the function of VI. Later, I learned that there was a makefile in my monster, so I checked it. At that time, I didn't want to read English, I found it. Introducing Makefile if there is no Chinese documentation, I have to see Makefile written by others, I have accumulated a little knowledge, but in many places, I don't know if I don't know. Later, I started working on UNIX product software. I saw a 400-year-old year, nearly 2,000 lines of code, I found that it is necessary to compile such a huge thing. If there is no Makefile, how horror is the same. So I came to my heart, I read a bunch of English documents, I feel that I have mastered it. But it is found that the article is still so pitiful, so I want to write such an article, share it for everyone, I hope to help you. Now I finally finished, I saw the creation time of the document, and this technical document has also been written for more than two months. I found that I know it is a matter, I have to write down, telling others is another thing, and now there is no time to study technology details, so when I write, it is difficult to explain some details. Doing rigorous and refined, and telling what you are telling what you first say, it is still referring to some foreign sites, and the language style of some technical books is completed. The outline of the entire document is written by the Outline of the GNU-based Makefile Technical Manual and combines its own work experience and its own learning. Because there is never written such a long, such a thin document, there will be many places where there is a problem, language ambiguity or error. Because of some, I am in urgent to wait to give me an indication and suggestion, as well as any feedback. Finally, use this in this back, introduce yourself. I have currently engaged in software development under all UNIX platforms, mainly to do distributed computing / grid computing system product software, and I am very interested in the next-generation computer revolution - grid computing, for distributed calculations , P2P, Web Service, J2EE technical direction is also very interesting, and at the same time, for project implementation, team management, project management is also small, I hope to fight the young generation on the "technology and management of" technology and management ", A lot of exchanges with me. My MSN is: haoel@hotmail.com (common), QQ is: 753640 (not common). (Note: Do not give me MSN's mailbox, because Hotmail's spam causes me to refuse this mailbox, I welcome any form of communication, whether discussing technology or management, or other hairdry southern. I don't care about politics and entertainment news, other things I am welcome! In the end, I also want to introduce the design and developer of the Make program. The first rush is: Richard Stallman

Open source software leaders and pioneers have never received a day of salary, never used a Windows operating system. For his deeds and his software and his thoughts, I don't have to say too much, I believe that everyone is not strange to this person, this is his home page: http://www.stallman.org/. Only a recent photo is posted here:

Computer, music, butterfly is his favorite

The second is: Roland McGrath Personal Homepage is: http://www.frob.com/~roland/, below is some of his deeds: 1) Cooperation and maintain GNU Make.

2) Write GNU Hurd with Thomas Bushnell.

3) Write and maintain GNU C Library.

4) Cooperation and maintain part of GNU Emacs.

Here, the fighter of the two open source projects is the most authentic tribute.

(Full text)

转载请注明原文地址:https://www.9cbs.com/read-104323.html

New Post(0)