Let a few nonsense first
I often encountered Makefile, nmake when I read the book, and then followed the inexplicable code, I saw me in the fog. Since the library and Google, I can only find some of the zero star's information, and I can't do it. Recently, I have been in the same way, I have met a legendary Masm6 manual, and finally unveiled the true face of NMAKE. Those who may be suffering from the same suffering, and those who have dizzy, I have written this article. If you feel helpful, remember to reply, as an encouragement! If you feel very idiot, please throw a few eggs. This article is summarizing the translation, for some keywords and some sentences that are not a very certain sentence, retain the English original, and then give your own understanding in parentheses. Due to the limited level, plus the experience of using nmake, there is not a place to remember to refer to it. The Masm6 manual can be Download Link on my blog in AOGO (like).
About NMAKE
Microsoft Program Maintenance Utility, Outer NMAKE, as the name suggests, is a tool for managing the program. In fact, it is a explanation. It handles a file called makefile (in MAK suffix), explains the statement inside and performs the corresponding instruction. We write the Makefile file, depending on the dependencies between the specified grammar description files, and a series of operations associated with the dependency. Then when you call NMAKE, it checks all related files, if the target file (Target file, the following is a TARGET, the file depends on other files) of the Time Stamp (that is, the file last modified time, one 32 digits) It is a TIME STAMP that is less than the dependency file (Dependent File, the Dependent File, the Dependent file), and the dependent file. Please see the following example:
FOO.EXE: first.obj second.obj
Link first.obj, second.obj
The first line defines dependencies, called Dependency Line; the second line gives the operation associated with the dependency, called Command Line. Because foo.exe is connected by first.obj and second.obj, saying foo.exe relies on first.ogj and second.obj, ie foo.exe is target, first.obj, and second.obj for Dependent. If any one of first.obj and second.obj is modified (its Time Stamp is larger), call Link.exe, reconnect to generate foo.exe. This is the logic of NMAKE.
In summary, NMAKE's core is these three guys - dependencies, operations and determination logic (TRUESTAMP, if TRUE is performed).
Makefile's grammar
Now discuss the grammar of Makefile. Makefile is like a toy program language, although the sparrow is small, but the five dirt is full. Makefile components include: Description Block, Inference Block, Inference Rules, Macros, and Directive. The description statement is the combination of Dependent Lines and Command Lines; Inference Rules is a predefined or user-defined dependency and association command; macro does not have to say it; instructions are some of the internal control commands that can be identified by NMAKE, provide A lot of useful features. In addition, Makefile uses the following aspects of the following symbols:
^ # / () {}! @ -:; $
^ (CARET): It is used to close the specific meaning of certain characters, making it only means the meaning of the literal. For example: ^ # ABC represents #abc this string, and #abc is used to add comments in Makefile, # here as a comment sign, like C //. In addition, adding ^ at the end of a line, can make the row of carriage return to a part of the string.
# (Number Sign): For the comment sign, nmake will ignore all the text from # starting to the next newline. It should be noted here that there is no comment in Command Lines. Because for Command Lines, NMAKE is passed to OS. It is usually placed between the rows and rows for CommmanD Lines.
/ (Backslash): It is used to combine both lines into a line. Place it in the tail, NMAKE will explain the return of the routine to space (Space).
% (Percent Symbol): Indicates that the following string is a document name. The usage is more complicated, and it will be discussed in detail when talking in Dependent Lines.
! (EXCLAMATION SYMBOL): Command modifiers, which will be discussed in detail below.
@ (At Sign): Command modifier, which will be discussed in detail below.
: (COLON): For Dependent Lines and Inference Rules, it is used to secure Target and Dependent.
(SEMICOLON): If there is only one command for a Dependent Line, you can place the command behind the deprondent line, and use ";";
$ (DOLOR SIGN): Used to call the macro, discuss in detail when you talk about the macro below.
You can also use the DOS Wildcard (Wildcard) in makefile: * and? . It is very familiar to everyone, there is no longer waste of water.
If you want to treat a string with spaces or tabs as an overall string, you should have a double quotation number, for example, when you specify a long text name with spaces in an intermediate:
"My document"
Or when defining a macro:
MyMacro = "Copy A: /FOO.EXE C: /"
Description Diction Blocks Description Slote Block The basic composition unit of the Makefile body, the typical structure is as follows:
Target: Dependents
Commands Block
Dependent Line
There is only one dependent line in each describing sentence block that defines a dependency. The opening of the line cannot have any blank (spaces or tab). Targets and Dependents on both sides of the colon can have multiple, separated by spaces. NMAKE first scans every Dependent Line from head to tail, and then establishes a dependent tree according to the dependency. For example, dependencies:
FOO.EXE: first.obj second.obj
First.Obj: first.cpp
SECOND.OBJ: Second.cpp.cpp
In its dependence tree, foo.exe is first.obj and second.obj's father, and first.obj is first.cpp's father, second.obj is the father of Second.cpp. If second.cpp is updated, second.obj will be reconstructed, resulting in foo.exe to be re-constructed. NMAKE is the result of the node of the whole tree by this.
Although Makefile can have a lot of Dependent Lines, nmake will only construct a targets in its command line, or if there is no Targets in the command line, construct the first target in Dependent Line. All other non-related targets will not be constructed. E.g:
Foo1.exe foo2.exe: first.obj
First.Obj: first.cpp
SECOND.OBJ: Second.cpp.cpp
Assume that the first line statement above is the first Dependent Line that appears in the makefile, and the Target is not given in the command line. When first.cpp is updated, first.obj and foo1.exe will be re-constructed, and foo2.exe and second.obj will not.
When multiple Targets appear in a Dependent Line, for example:
Boy.exe girl.exe: first.obj
echo hello
This statement is equivalent to:
Boy.exe: first.obj
echo hello
Girl.exe: first.obj
echo hello
(Note: Echo is a console command to display a line of information on STDOUT)
The same Target can also appear in multiple Dependent Lines. In this case, if there is only one dependent line follows COMMAND LINE, they will be merged into a descriptive sentence block, for example:
FOO.EXE: FIRST.OBJ
Echo building foo.exe ...
...
foo.exe: second.obj
NMAKE will handle it as:
FOO.EXE: first.obj second.obj
Echo building foo.exe ...
If each Dependent Line has Command Line, they will be handled as two descriptors.
If you use a double colon (: :) in Dependent Line to secure Target and Depend, and the same target appears in multiple descriptive sentence blocks. At this time, NMAKE will match the most appropriate statement block to construct the target. E.g:
Target.lib :: One.asm Two.asm Three.asm
Ml one.asm two.asm three.asm
Lib Target - One.obj - TWO.OBJ - Three.obj;
Target.lib :: four.c Five.c
CL / C Four.c Five.c
LIB Target - Four.obj - Five.obj;
Target.lib simultaneously appears in two descriptive sentences, at this time, NMAKE will select the command in one of the descriptors blocks in the descriptor block when processing the makefile. If any ASM file is updated, NMAKE calls ML to recompile, then call lib (but CL, and after the command will not be called); Similarly, if any C file is updated, Nmake will call CL .
Under normal circumstances, Target and Dependent are file names. Nmake will first search for Depend in the current directory. If you are not found, you can search for the user specified by the user. Specifies the syntax of the search path as follows:
{Directory1; Directory2; ...} Dependent
Search path is placed in {}, if there are multiple, use ";" separate. Note that there is no blank between each syntax component.
Target and Dependent are also not a file, but a label. At this time, it is called a Pseudotarget. The name of the PSeudotarget cannot be the same as any file name in the current directory. A Pseudotarget If you want to use as Dependent, it must appear as a Target in a dependent line. When using Pseudotarget as target, the associated Commands Block will be executed, and NMAKE will give it an imaginary TIME STAMP. This time stamp is equal to its largest time stamp in its Dependents, or if it doesn't have Dependent, it is equal to the current time. This imaginary Time Stamp is used to perform validity assessments when Pseudotarget is used as Dependent. The greatest advantage of this feature is that you can make NMake construct multiple Targets without listed each Target in the command line of NMAKE, for example:
All: SetENV Project1.exe Project2.exe
Project1.exe: Project1.obj
LINK Project1;
Project2.exe: Project2.obj
LINK Project2;
Stenv:
Set lib = / project / lib
There are two Pseudotargets in the above example, one is all, and the other is setenv. The first is STENV being evaluated, and its role is to set the environment variable lib, then Project1.exe and Project2.exe are later updated.
Commands Block
The second row starts to the next debnds block between the next deprondent line, which gives the Time Stamp when any of Dependents are greater than Target, and the command sequence (Commadns Block can also be empty, what is nmake Not dry). Command Line must begin with blank (just in contrast to Dependent Line, NMAKE is distinguished by this feature), and there is no blank line between the first statement in Dependent Line and Commands Block (that is, in addition to a newline " And there is no row. So only one space or tab is legal. At this time, NMAKE explains it as a null command, but there can be blank lines between Command Lines. Each command in Commands Block can be any command legally in the console. In fact, the Commands Block is a batch file consisting of a console command sequence. In addition, the commands in the Commands Block can also add one or more so-called command modifiers in front to implement some additional controls for the command. The command modifier has three types:
1) @Command
Eliminate all the outputs of this command to stdout.
2) - [Number] Command
Turn off the detection of the return value of the command. In the default, if a command returns a non-0 value, NMAKE will stop execution. But if you add a "-" before command, NMAKE will ignore the return value of the command. If "-" is immediately an integer, NMAKE ignores any return value greater than the integer.
3)! Command
If the execution object of the command is $ ** or $? (These two are predefined macros, the former represents all the dependent in the corresponding Dependent Line, indicating that all Time Stamp's dependent is more than TARGET) Then, the "!" Modifier will make the command on each individual file described in these two macros.
NMAKE also provides some syntax to indicate the file name consisting of the first Dependent in the corresponding Dependent Line in the Commands Block. E.g:
Foo.exe: c: /sample/first.obj c: /sample/second.obj
LINK% S
NMAKE explains "LINK% S" as:
Link c: /sample/first.obj
If the command is changed to "link% | PFF.exe", the NMAKE will be explained in:
Link c: /sample/first.exe
% s represents a full file name,% | [part] f indicates some of the file name, and the Part can be one or more of the following characters. If Part is empty,% | f is the same as% S:
1) D: drive letter;
2) P: path;
3) F: The file is based;
4) E: File extension;