Makefile Confident Guide

xiaoxiao2021-03-06  51

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; Inference Rules (derivation rules)

Inference Rules (hereinafter referred to as IR) is a template that determines how to construct a file with another extension from a file with some extension. NMAKE determines the command to update the target of Target through IR and derive the target of Target. The advantage of IR is that it satisfies the needs of lazy people like me. As long as the correct IR is provided, the descriptive sentence block can be greatly understood. Please see the example below: foo.obj:

The above statement will work very well. Is it very surprised? In fact, when the nmake is handling the statement, it first searches for a file that is fundamentally known as FOO in the current directory (assuming a foo.c file in the current directory). Then it looks for a suffix list (SUFFIX LIST), each item contains another type of file that needs to be called from a type of file to construct another type of file that needs to be called. In the NMAKE predefined list, the constructor of foo.c to the foo.obj is CL. Finally Nmake calls CL, compile foo.c. Oh, such a long string operation is a simple statement, is it very convenient!

When one of the following conditions occurs, NMAKE will try to use IR:

l Nmake encountered a descriptive sentence block without any commands. At this point, NMAKE searches for a list of lumen, trying to find a matching command to construct Target.

l I can't find a Dependent, and the dependent does not appear as a target in other dependent line (ie it is not a Pseudotarget). At this time, NMAKE searches for a given directory and the suffix list, attempting to find an IR to construct the dependent.

l A target doesn't have Dependent, and the instruction is not given in the description block. At this time, NMAKE will try to find an IR to construct the Target.

l A Target gives a target line in the NMAKE, but there is no relevant information on the target (no makefile at the Makefile). At this time, NMAKE will try to find an IR to construct the Target.

Define the syntax of an IR as follows:

[{fromPath}]. FROMEXT [{TOPATH}].

Commands

Note that there is no space between each syntax element. Dependent's suffix name is given in FROMEXT, and the suffix name of the target is given in TOEXT. FromPath and Topath are optional and the path of search is given. A search path can only be given to each suffix name in the definition of each IR. If you want to specify a plurality of search paths, you must define multiple IRs. And, if you specify a search path for a suffix, you must also specify a search path for another suffix. That is to say, from FRMEXT and TOPATH as long as there is an existence, the other must exist. You can use {.} Or {} to represent the current directory.

Also, pay attention to that if you specify the search path in IR, you must also specify the same path in the Dependent Lien, otherwise IR will not be applied to Dependent Line, for example:

{../proj }.exe {./proj }.obj:

This IR will not be used on the following statement:

Project1.exe: Project1.obj

But it will be used on the following statements:

{../proj }Project1.exe: {../proj}Project1.obj

NMAKE itself provides a predefined suffix list, as follows:

Rule Command Default Action.asm.exe $ (AS) $ (AFLAGS) $ *. ASM ML $ *. ASM

.ASM.Obj $ (AS) $ (AFLAGS) / C $ *. ASM ML / C $ *. ASM

.c.exe $ (cc) $ (cflags) $ *. ccl $ *. c

. C.Obj $ (CC) $ (cflags) / c $ *. C CL / C $ *. c

. cpp.exe $ (cpp) $ (cppflags) $ *. CPP CL $ *. CPP

. cpp.obj $ (CPP) $ (CPPFLAGS) / C $ *. CPP CL / C $ *. CPP

.cxx.exe $ (cxx) $ (cxxflags) $ *. CXX CL $ *. CXX

.cxx.obj $ (cxx) $ (cxxflags) / c $ *. CXX CL / C $ *. CXX

.BAS.OBJ $ (BC) $ (bflags) $ *. BAS; bc $ *.

. CBL.EXE $ (COBFLAGS) $ *. CBL, $ *. EXE; COBOL $ *. CBL, $ *. EXE;

. CBL.Obj $ (COBOL) $ (COBFLAGS) $ *. CBL; COBOL $ *. CBL;

. EXE $ (for) $ (fflags) $ *. for fl $ *.

.Obj $ (for) / c $ (fflags) $ *. for fl / c $ *.

.PAS.EXE $ (PASCAL) $ (PFLAGS) $ *. PAS PL $ *. PAS

.PAS.OBJ $ (PASCAL) / C $ (pflags) $ *. PAS PL / C $ *. PAS

.rc.res $ (rc) $ (RFLAGS) / R $ * RC / R $ *

In the above table, similar AFLAG and CFLAG are not defined in parentheses, by defining these macros in Makefile, the compiler and parameters can be specified for these commands. E.g:

$ (AS) $ (AFLAGS) $ *. ASM

The AS macro is used to specify the compiler, and the NMAKE is default the ml; the AFLAGS macro is used to give the compiler parameters, and the NMAKE leaves it to the user definition, the default is empty. So the default operation is:

ML $ *. ASM

Here you can see the grammar to open the macro, that is, enclose the name of the macro with parentheses and add a dollar sign in front. It is also necessary to explain that "$ *" is a special macro predefined NMAKE predefined, which is equal to the path to Target plus the basic name of the target. Macro

This is very familiar with everyone. Great flexibility can be obtained by using macros in Makefile. Below is the syntax that defines the macro in makefile:

Macroname = String

In Makefile, Macroname is the name of the macro, which can be a combination of any letters, numbers, and underscores, up to 1024 characters. Also note that macroname is sensitive. String is a macro defined body, which can have up to 65,510 characters. Any string containing 0 characters or only a blank is considered a null string. At this time, the macro is also considered null, anywhere, will be replaced with a blank.

When using the macro, you should also know the following symbols with special meaning:

L # for comments, for example:

Command = ml # Compile ASM File

l / write macro definitions to write, for example:

Linkcmd = link myapp /

Another, NUL, MYLIB, MyApp

"/" The back-on-return line will be replaced by the space, and the above two lines are equivalent to:

Linkcmd = link myapp Another, NUL, MYLIB, MyApp

L $ will open the macro and use it later.

L ^ If you want to include the above symbols in the macro, you can use the special semantics, you can:

DIR = C: / windows ^ /

At this point, DIR is equivalent to the string "C: / Windows /".

Here are some details of some syntax:

1) When defining a macro, the first character of the macro name must be the first character of the line;

2) You can only define a macro per line;

3) There may be spaces on both sides of "=", but they will be ignored;

4) There can be space in the macro definition body, which will be considered part of the macro;

In addition to defining macros in Makefile, macro definitions can also appear in the nmake command line. At this point, if there is any blank in the macro definition, you must have a double quotation mark, for example:

Nmake "linkcmd = link / map"

Nmake linkcmd = "link / map"

In this way, it is not allowed (the equal sign is spaced):

Nmake linkcmd = "link / map"

The syntax using the macro is as follows (note that there is no space in the entire statement):

$ (Macroname)

NMAKE will replace the entire statement with macro. If the macro is not defined, NMAKE will replace it with blank, and no error will occur. If the name of the macro has only one character, the parentheses can be omitted, for example, $ 1 and $ (L) are equivalent.

Nmake has also provided a very useful feature for macros, that is, Substitution. That is, when the macro is expanded, you can specify that some of the text in the unfolded macro is replaced with additional text. For example: Source = one.c two.c

Foo.exe: $ (Source: .c = .obj)

LINK $ **;

This is this:

Source = one.c two.c

Foo.exe: one.obj tour.obj

Link one.obj two.obj;

Statements $ (source: .c = .Obj) indicates that all ".c" that appears in Source is ".Obj".

As can be seen from the above example, the syntax of the substection is as follows (note, no space):

$ (Macroname: str1 = str2)

In addition, NMAKE also provides 4 sets of predefined macros, which are file name macros, recursive macros, command macros, and parameter macros. They can be redefined, but may cause some unnecessary trouble because they are widely used. The so-called "moving one-to-hammer", a small change, and even affect the movement of the sun, the butterfly effect), which is the largest drawback of the use of macros.

File name Hong

Use in Commands Block to represent a specific file name, including:

1) $ @ used to indicate the full name of the first Target in the associated Dependent Line (including path).

2) $$ @ 同, but only in Dependent Line.

3) $ * Target's path plus basic name.

4) $ ** All dependents in the corresponding Dependent Line.

5) $? All TIME stamps in the corresponding Dependent Line are greater than the target of Target.

6) $ 同 同, but only in IR.

Below is an example:

DIR = C: / Objects

$ (DIR) /A.OBJ: A.OBJ

Copy a.obj $ @ @ @

The last sentence is equivalent to: Copy a.obj C: /Objects/a.obj

In addition, when using these macros, you can also extract one of the file names by the following characters:

D path

B basic name

F basic name plus extension

R path plus basic name

For example: if $ @ means C: /Objects/a.object,

$ (@ D) C: / Objects

$ (@ B) a

$ (@ F) a.obj

$ (@ R) c: / Objects / a

Recursive

There are 3, they are all used to easily call the NMAKE in makefile, they are:

1) MAKE

Indicates the name of the NMAKE program running the current Makefile. For example, if you run your Makefile in the console:

NMAKE HER.MAK

Then Make is equal to NMAKE.

But if you rename nmake.exe for fuck.exe, then you run makefile commands should be changed to: fuck Her.mak

At this point, MAKE is equal to Fuck.

2) Makedir

Indicates the directory where you call NMAKE.

3) Makeflags

Indicates the NMAKE parameters you run when you run the current makefile.

These macros are particularly useful at different versions of the Build program, such as:

All: VERS1 VERS2

VERS1:

CD / VERS1

$ (Make)

CD ..

Vers2:

CD / VERS2

$ (MAKE) / f Vers2.mak

CD ..

NMAKE will run Vers1.mak and Vers2.mak in ./vers1 and ./vers2 directory.

Command macro and parameter macro

Command macro indicates Microsoft's compiler (really will do business, do not forget your own product at any time), and parameter macro is the parameter passed to these compilers. In the default, the parameter macro is undefined. of. Of course, you can redefine them and let them represent Boland's compiler and parameters.

Command macro corresponding parameter macro

1) As ML, M assembly compiler. Aflags

2) BASIC compiler of BC BC and M. Bflags

3) C compiler of CC CL, M. Cflags

4) COBOL COBOL compiler of Cobol Cobol. Cobflags

5) C compiler of CPP CL, M. CPPFlags

6) C compiler of CXX CL, M. CXXFlags

7) For fl, m's Fortran compiler. Fflags

8) PASCAL compiler of PASCAL PL, M. Pflags

9) Resource compiler of RC RC and M. Rflags

Author Blog:

http://blog.9cbs.net/diaoni/

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

New Post(0)