NMAKE Guide——中文版本(二)

   
NMAKE Guide
-------------------------------------------------------------copy right------------------------------------------
哥哥原创!
转载请附上哥哥的链接!!!

blog写作缘由:
项目突然需要使用到NMAKE来编译一个工程文件,于是开始找NMAKE相关资料,寻觅良久,仍末见中文版本(GNU的makefile有比较多的中文资料)。所以呢,只好自己开始死磕MSDN相关英文资料。此时刚好找到一英文版的NMAKE Guide,就拿来瞅瞅了。貌似用点心看,磕起来不太累。看到一半,突然想起一个问题,哥哥以后要是再想查相关资料,岂不是还得死嗑英文呢。所以就有了将该英文版本翻译一下的冲动。于是乎,就有了它了。

PS:哥哥英文不太好哦,大学很幸运地将六级“睡”过去了呢。之后就一直没瞅英文了,外加哥哥的语文好像不太好呢,所以大伙看到一些晦涩的地方,笑笑就可以了,因为哥哥实在不知道怎么翻了或是不晓得用啥中文来表述原意。

Guide写完后附上英文版,我这没看懂的可以查英文原版哦!!!
希望写出来可以帮助到一些人哦!!反正哥哥以后是可以看中文版的喽!!

(英文版本大概有59页,大概预计得二周内翻译完。)
-------------------------------------------------------------end-------------------------------------------------


     NMAKE 命令文件
  您可以一列命令行参数保存在一个文本文件中,并将该文件名作为命令行参数传递给NMAKE。NMAKE打开命令文件,读取文件中的命令作为命令行参数。
  您可以使用一个命令文件来克服在操作系统在命令行参数长度的限制(在MS-DOS系统中是128个字符)。
  使用命令文件作为NMAKE的参数输入,按如下格式键入:
  NMAKE @commandfile

  commandfile是命令文件的文件名,命令文件中含有NMAKE希望的命令行参数的信息。在输入命令时在命令文件名之前加个@字符。
  当然,您可以输入完整的文件路径。

  NMAKE将命令文件当成是一个单一的一列参数来处理。它用空格代替命令文件的每个换行。宏定义中有包含空格的须写在一对双引号中,详情请查阅552页的“如何定义宏定义”章节。

  您也可以分开命令行和一个命令文件输入。将@commandfile放置于您希望其在命令行中位置。命令行参数可以放在命令文件之前或是跟随其后。当然,您可以指定不只一个命令文件。

  例子1.
  如果一个名为UPDATE的文件中包含这么一行内容:
  /S "program=sample" sort.exe search.exe
  您可如下方式启动NMAKE程序:
  NMAKE @update
  上面语句的作用就相当于在命令行中输入如下的命令:
  NMAKE /S "program=sample" sort.exe search.exe

  例子2.
  下面是另一版本的update文件的内容:
  /S "program /
  = samplet" sort.exe search.exe
  使用(/)可以将上面的定义写在两行中。

  例子3.
  如果命令文件update的内容如下:
  /S "program=sample" sort.exe
  您可使用按下面的方式启动NMAKE来生成目标search.exe:
  NMAKE @update search.exe

    TOOLS.INI配置文件
  您可以通过在初始化文件TOOLS.INI中放置您通常使用的信息的方式来客制化您的NMAKE。NMAKE的设置须以标签[NMAKE]开始。该标签并不区分大小写。
  在该标签段内的文件内容可以包括任何makefile信息。NMAKE将会在其运行的每个会话过程使用其中的信息,除非你以/R选项启动NMAKE。NMAKE首先在当前目录搜索TOOLS.INI文件,其次在环境变量INIT指定的路径中进行搜索。
  您可以TOOLS.INI文件中使用!CMDSWITCHES指令来指定命令行选项。采用这种方式设置的命令行选项将会在每个NMAKE的会话期间都会起作用。这与环境变量起着同样的作用,环境变量是一个可供其他公用实体使用的功能。
  更多关于!CMDSWITCHES指令的信息,请查阅572页。

  在TOOLS.INI中出现的宏定义和推导规则可以被覆盖。详情请查阅563页的“宏定义的优先性”一节和570页的“推导规则的优先性”章节。
  NMAKE会在其读取makefile文件之前获取TOOLS.INI文件在的内容。举个例子,在TOOLS.INI出现的描述块将会被作为makefile的第一个出现的描述块来处理,这同样适用于NMAKE的每个会话过程,除非/R选项被指定。

  在TOOLS.INI文件中可如下添加注释,另起一行以”;“开始,”;“后面的内容将会被作为注释。当然您也可以使用在makefile文件中写注释的方法,那就是以"#"作为一行的开始。更多详情见536页的”注释“一节。

    TOOLS.INI例子
  下面是一个TOOLS.INI的例子:
  [NMAKE]
  ; macros
  AS = masm
  AFLAGS = /FR /LA /ML /MX /W2
  ; inference rule
  .asm.obj:
  $(AS) /ZD ZI $(AFLAGS) $.asm
  NMAKE读取并应用[NMAKE]标签以下的行内容。在本例中,其重新定义了AS宏来关联微软的宏汇编器功能(MASM.EXE);重新定义了AFLAGS宏,并重新定义了由.asm源文件到.obj文件的推导规则。
  这些NMAKE的功能将会在本文中有详细的介绍。

    MAKEFILE文件的内容
  一个NMAKE的makefile文件包含描述块、宏定义、推导规则和指令。本章描述了makefile文件的通常写法。剩下的章节详细地描述了makefile的每个元素。

    特殊字符的文字用法
  您或许会需要将特殊字符当做文字字符来处理。NMAKE使用一些字符作为特殊字符用作特定的目的,这些特殊字符包括:
  : ; # ( ) $ ^ / { } ! @ -

  若要使用这些字符与不作特定用途,请在使用这些字符时在其位置之前插入符号(^)。NMAKE忽略在字符之前的插入符号而不将其当做先前列的特殊字符。用引号包含插入字符的一段符串被当作文本插入字符。

  您也可以在一行的末尾使用一个插入字符在一个字符串或宏定义中插入文字换行符。插入符号让NMAKE将换行符的字符解释为宏的一部分,而不是一个换行。
  注意:这与使用”/“来继续宏定义的行并不一样。跟随在反斜杠后的换行符被替换为一个空格。更多的信息可以查看551页的"用户自定义宏”一节。

  在命令中,用“%”符号来表示一个文件说明符的开始。(可以查看546页“文件名字语法”章节。)NMAKE将“%s"解释为一个文件名,同时其也将在“%|"后跟随字符"d",”e", “f", ”p“ 或是"F"一段字符序列当作是部分或完整的文件或路径名。
  如果您需要在命令中从字面上表示这些字符,请使用双百分号(%%)来替代单一百分号(%)。在所有其他情况下,NMAKE将单一"%"字符当做文字字符。
  然而,NMAKE总是将双百分号%%解释成单一百分号%文字字符。因此想要表达双百分号%%的文字字符,您可以使用三个百分号来表示(%%%)或是四个百分号来表示(%%%)。

  想要在命令中使用美元文字字符($),您必须使用两个美元字符($$);这种方式同样可以使用在"^$”也使用的情形下。

  更多的信息关于宏定义中的文字字符,请查阅“宏定义中的特殊字符”章节,在551页。

    通配符
  您可以MS-DOS的通配符(*和?)来指定目标和依赖的名字。NMAKE会展开依赖行上的通配符。命令中的通配符将会传递到命令当中,NMAKE并不将其展开。

    例子
  在下面的描述块中,通配符“*”使用了两次。
  project.exe : *.asm
   ml *.asm /Feproject.exe
  NMAKE将会在当前目录中查找所有以.asm为后缀名的文件并展开其在依赖行上。如果其中任意的.asm文件过期了,ML命令将会展开*.c同时编译和链接所有的文件。

    注释 
  在makefile文件中写注释,请在注释之前加数字符号(#)。如果整行都是注释,那么#必须出现在该行的开始位置;否则#以下的内容将会当做注释。
  NMAKE将会忽略所有从数字符号#到下一个换行符之间的文本内容。

  命令行中不能包含注释,即使命令是作为依赖项或是推导规则写在同一行上。这是因为NMAKE并不解析命令,相反它把整个命令都传递给操作系统。但是,注释可以出现在命令块的行之间。
  想要注释掉一个命令,那么在该命令行的开始插入#。

  您可以在下列情形中使用注释:
  # Comment on line by itself

  OPTIONS = /MAP # Comment on macro definition line

  all.exe : one.obj two.obj # Comment on dependency line
   link one.obj two.obj;
  # Comment in commands block
   copy *.obj /objects
 
  .obj.exe : # Comment in inference rule

  想要描述一个文字#字符,在其前面插入^符号,就像下面一样:

  DEF = ^#define #Marcro representing a C preprocessing directive

  注释同样可以出现在TOOLS.INI文件中。TOOLS.INI允许额外的一种方式来添加注释,那就是使用;字符。可以查看534页的"TOOLS.INI文件“章节。


    长文件名
  您可以在makefile文件中使用长文件名如果您的文件系统支持的话。但是您必须将文件包含在一对双引号中,就像下面的依赖行的写法:

  all : "VeryLongFileName.exe"

    描述块
  描述块是makefile文件的核心组成部分。下面是一个经典的NMAKE描述块:


  图16.1 NMAKE 描述块

  描述块中的第一行是依赖行。在本例中,依赖关系包含一个目标和三个依赖项。跟在依赖行后的是命令块,命令块中列了一条或多条命令。
  接下来的章节讨论依赖关系、目标和依赖项。命令块的内容在543页的”命令“章节中有详细介绍。

    依赖行
  一个描述块以依赖行作为开始。依赖行指定了一个或多个目标然后又列出了零个或多个依赖文件。
  如果某个目标块不存在,或是其时间戳比依赖项的时间戳早,那么NMAKE执行命令块命令来生成该目标文件。
  下面是一个依赖行的例子:

  myapp.exe : myapp.obj another.obj myapp.def

  上面的依赖行告诉NMAKE去重新生成目标文件MYAPP.EXE当MYAPP.OBJ、ANOTHER.OB或是MYAPP.DEF文件比MYAPP.EXE有了最新的改变。
  依赖行不能有缩进(它可以以空格或是制表符开始)。第一个目标必须指定在依赖行的开始。目标文件和依赖文件被一冒号隔开,539页中“目标在多个描述块中的使用”章节中描述的目标除外。
  冒号之前可以有零个或多个空格或是制表符。完整的依赖必须全部写在一行中;但您可以在目标或是依赖项后放置一(/)符号来扩充当前行,然后在下一行中继续描述依赖。

  在执行任何命令之前,NMAKE通过所有依赖关系和适用的推理规则来建立一个“依赖树”,依赖树指定了完整更新目标的所需的所有步骤。
  NMAKE检查依赖项本身是否其他依赖关系列表的目标,或者任何这些依赖关系列表里的依赖项又是其他依赖的目标,等等。
  NMAKE建立依赖树之后,它开始检查时间戳。如果依赖树中的任一依赖项比目标要新,那么NMAKE将编译生成目标。

    目标
  依赖行中的目标段列出了一个或多个目标名字。至少须指定一个目标。多个目标之间用一个或多个空格或是制表符隔开。
  当然您可以指定文件的路径。目标名字并不区分大小写。一个目标(包含路径)名不能超过256个字符。如果在":"前的最后一个目标的名是单一字符,那么在最后一个目标名和冒号之前必须有一个空格;否则NMAKE会将单一字符和冒号联合解释成一个磁盘说明符。

  通常目标是使用描述块中命令生成的文件的名字。但是,目标可以是任何有效的文件名,甚至可以是一个伪目标。(关于伪目标请查阅540页的“伪目标”章节。)
  NMAKE生成NMAKE命令行中指定的目标。如果NMAKE没有在命令行中指定目标,那么NMAKE将生成makefile文件中第一个依赖关系的第一个目标。

  上一章节中的例子告诉NMAKE如何去生成单一目标文件MYAPP.EXE如果其不存在或是过期了。

    在多描述块目标的使用
  一个目标文件只能出现一个描述块中如果使用单一冒号来分开目标和依赖项。想要使用多个描述块来更新一个目标,那么使用两个连续的冒号来区分目标和依赖项。
  该功能的一种用例是一个复杂目标的创建,目标包含了多个由不同的命令创建的组件。

    例子
  下面的makefile用来更新一个库:

  target.lib :: one.asm tow.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

 如果任意一个汇编文件比库文件有更新,那么NMAKE汇编源文件然后更新库文件。同样的,如果任意一个C文件有改变,那么NMAKE编译C文件然后更新库文件。

   积累目标的依赖关系
 依赖行是积累的当同一目标多次出现在一个简单的描述块内。举个例子:

 bounce.exe : jump.obj
 bounce.exe : up.obj
  echo Building bounce.exe...

 上面的依赖将会被NMAKE改进为:

 bounce.exe : jump.obj up.obj
  echo Building bounce.exe...

 这种改进有几个方面的影响。。由于NMAKE一次只生成一个目标的依赖树,所以在依赖行中可以包括其他目标,就像下面:

 bounce.exe leap.exe : jump.obj
 bounce.xe climb.exe : up.obj
  echo Building bounce.exe...

 上面的例子将会被NMAKE改进为:

 bounce.exe : jump.obj
 leap.exe : jump.obj
 bounce.exe : up.obj
 climb.exe : up.obj
  echo Building bounce.exe...

 NMAKE为三个目标依次评估依赖树就像他们是在单独的描述块是指定的。如果bounce.exe或是climb.exe过期,NMAKE执行给定的命令。
 如果leap.exe过期了,给定的命令并不执行,同时NMAKE尝试使用一条推导规则。如果同一目标在makefile文件是不同地方的两个使用单一冒号的依赖行中被指定,
 且只有一个依赖行后有出现命令,那么NMAKE将两依赖行解释为相邻或是合并的。这会引起不必要的副效应:NMAKE并不调用推导规则为那条没有命令的依赖行(详情请查阅563页的"推导规则“章节)。
 相反,NMAKE假设两个依赖行归属同一描述块然后执行另一依赖指定的命令。

 下面的makefile将会解释成和之前的例子一样:

 bounce.exe : jump.obj
  echo Building bounce.exe...
 .
 .
 .
 bounce.exe : up.obj
 不必要的副效应不会产生如果那个重复的目标是用双冒号(::)来分隔的。一个双冒号的没有命令块的依赖关系调用推导规则,即使别一个使用双冒号的依赖关系包含同样的目标且有提供命令块。


   伪目标
 一个伪目标是目标,没有指定文件,但却为执行一组命令命名了一个标签。NMAKE认为伪目标为一个不存在的文件但却是永远是过期的。
 当NMAKE评估一个伪目标,它永远执行伪目标的命令块。确保当前目标下并不存在一个名字与伪目标名字一致的文件。

 一个伪目标的名字必须遵循文件名的语法规则。和文件目标一样,伪目标名字是不区分大小写的。但是,如果名字并不包含一个后缀(确实,它并没有包含”."),它可以超越8 -字符的文件名限制,最多可以有256个字符长。
 一个伪目标可以被列为依赖项。这种方式下,伪目标必须作为目标出现在另一依赖关系中,但是该依赖关系可以不需要命令块。

 作为一个目标使用的一个伪目标有一个假设的时间戳,该时间戳是其所有依赖项时间戳中最早的。如果一个伪目标没有依赖项,那么假设其时间戳为当前时间。
 NMAKE对伪目标使用该假设的时间戳如果该伪目标出现在makefile的依赖项的任何地方。

 伪目标在您想自动编译多个目标时是非常有用的。NMAKE只生成命令行中指定的目标或是当命令行中没有指定目标时,它只生成makefile文件中第一个依赖关系中第一个目标。
 想让NMAKE生成多个目标而不想在命令行中指定它们,写这样一个描述块,该描述块目标为一伪目标,然后将您想编译的目标作为伪目标的依赖项。
 之后将该描述块放置在makefile文件中的第一个依赖关系位置或是在NMAKE命令行中指定该伪目标。这样NMAKE就会帮您自动编译您想生成的多个目标了。

   例子1
 在下面的例子中,UPDATAE是个伪目标。

 UPDATE : *.*
  !COPY $** a:/product

 如果UPDATE被评估,NMAKE将拷贝当前目录下的所有文件到指定的磁盘目录。

   例子2
 在下面的makefile中,伪状态ALL编译PROJECT1.EXE和PROJECT2.EXE如果all或是没有目标在命令行中被指定。
 伪目标setenv在所有的.exe文件更新之前将修改环境变量LIB:

 all : setenv project1.exe project2.exe

 project1.exe : project1.obj
 LINK project1;

 project2.exe : project2.obj
 LINK project2;

 setenv :
 set LIB=/project/lib
  依赖项
 依赖行中的依赖段列出了零个或是多个依赖项名字。通常一个依赖项是一个用来生成目标的一个文件。但是,一个依赖项可以是任何有效的文件名,甚至它也可以是伪目标。
 当然您也可以指定文件名字的同时指定路径。依赖项名字不区分大小写。每个依赖项之前有一个或多个空格或是制表符隔开。用一个或是两个冒号来分开目标和依赖项。

 连同您明确列在依赖行中的依赖项,NMAKE可以假设一个推导的依赖。一个推导的依赖是从一条推导规则继承而来的。
 (更多的详情,请查阅563页的“推导规则”章节。)NMAKE认为推导依赖比明确依赖项较早地出现在依赖列表中。
 NMAKE将推导依赖生成到依赖树中。值得注意的是,当一个依赖关系中的一个推导依赖相比于目标来说过期了,那么NMAKE将
 调用依赖关系关联的命令块,就好像其是一个被明确声明的依赖项。

 NMAKE依靠依赖树来确保依赖项是更新的在其更新他们的目标时。如果一个依赖项文件不存在,NMAKE找寻方法生成该文件;如果该文件存在,
 NMAKE找寻方法来确保其是最新的。如果该依赖项被声明为另一依赖关系的目标,或是其被应用为一个推导规则的目标,NMAKE检查该依赖项相比其自己的依赖项的是最新的。
 如果该依赖项是过期的或并不存在,那么NMAKE执行该依赖项的命令块来更新该该依赖项。
 下面的例子在目标MYAPP.EXE之后列出了其三个依赖项:

 myapp.exe : myapp.obj another.obj myapp.def

   指定依赖项的搜索路径
 您可以指定NMAKE查找依赖项的搜索路径。指定搜索路径的语法:

 {directoy[;directory...]}dependent

 在大括号中包含一个或多个目录名字。多个目录之间用分号";"间隔。不允许有空格。
 您可以使用一宏定义来指定一个搜索路径的部分或全部。NMAKE首先搜索当前目录,然后再按指定顺序搜索指定的目录。
 一个搜索路径只应用于一个简单的依赖项。

   例子
 下面的依赖行指定了一个搜索路径:

 forward.exe : {/src/alpha;d:/proj}pass.obj

 目标文件forward.exe有一个依赖项pass.obj。目录列指定了两个目录。NMAKE首先在当前目录搜索pass.obj,如果没有找到pass.obj,那么NMAKE搜索/src/alpha目录,然后是d:/proj目录。


PS:
     (今天比昨天翻得快了一点,基本是昨天的两倍哦!!不过一样是快到二点了!!
       算算已经翻了18页了呢,快到三分之一了,按这样了速度是否再奋斗四晚就可以搞定了呢!!
       嘿嘿。。。好困呢。。明天再说!!)
 

Comments

Popular posts from this blog

How to fix error : no module named sendgrid when try to use sendgrid python lib in PHP.

react-native run-android : sun.security.provider.cert path.SunCertPathBuilderException : unable to find valid certification path to req uested target

react-native run-android : do not build/update modified code(App.js)