• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            拂曉·明月·彎刀

            觀望,等待只能讓出現(xiàn)的機(jī)會(huì)白白溜走

              C++博客 :: 首頁(yè) ::  :: 聯(lián)系 :: 聚合  :: 管理 ::
            先說(shuō)幾句廢話
              以前看書時(shí)經(jīng)常遇到makefile,nmake這幾個(gè)名詞,然后隨之而來(lái)的就是一大段莫名其妙的代碼,把我看得云里霧里的。在圖書館和google上搜了半天,也只能找到一些零零星星的資料,把我一直郁悶得不行。最近因緣巧合,被我搞到了一份傳說(shuō)中的MASM6手冊(cè),終于揭開(kāi)了NMAKE的廬山真面目。想到那些可能正遭受著同樣苦難的同志以及那些看到E文就頭暈的兄弟,所以就寫了這篇文章。假如大家覺(jué)得有幫助的話,記得回復(fù)一下,當(dāng)作鼓勵(lì)!如果覺(jué)得很白癡,也請(qǐng)扔幾個(gè)雞蛋.本文是總結(jié)加翻譯,對(duì)于一些關(guān)鍵詞以及一些不是很確定的句子,保留了英文原版,然后再在括號(hào)里給出自己的理解以作參考。由于水平有限,加上使用NMAKE的經(jīng)驗(yàn)尚淺,有不對(duì)的地方大家記得要指正唷。MASM6手冊(cè)在AOGO(好像是)可以download,在我的BLOG上有到那的鏈接。
              關(guān)于NMAKE
              Microsoft Program Maintenance Utility,外號(hào)NMAKE,顧名思義,是用來(lái)管理程序的工具。其實(shí)說(shuō)白了,就是一個(gè)解釋程序。它處理一種叫做makefile的文件(以mak為后綴),解釋里面的語(yǔ)句并執(zhí)行相應(yīng)的指令。我們編寫makefile文件,按照規(guī)定的語(yǔ)法描述文件之間的依賴關(guān)系,以及與該依賴關(guān)系相關(guān)聯(lián)的一系列操作。然后在調(diào)用NMAKE時(shí),它會(huì)檢查所有相關(guān)的文件,如果目標(biāo)文件(target file,下文簡(jiǎn)稱target,即依賴于其它文件的文件)的time stamp(就是文件最后一次被修改的時(shí)間,一個(gè)32位數(shù),表示距離1980年以來(lái)經(jīng)過(guò)的時(shí)間,以2秒為單位)小于依賴文件(dependent file,下文簡(jiǎn)稱dependent,即被依賴的文件)的time stamp,NMAKE就執(zhí)行與該依賴關(guān)系相關(guān)聯(lián)的操作。請(qǐng)看下面這個(gè)例子:
              foo.exe : first.obj second.obj
              link first.obj,second.obj
              第一行定義了依賴關(guān)系,稱為dependency line;第二行給出了與該依賴關(guān)系相關(guān)聯(lián)的操作,稱為command line。因?yàn)閒oo.exe由first.obj和second.obj連接而成,所以說(shuō)foo.exe依賴于first.ogj和second.obj,即foo.exe為target,first.obj和second.obj為dependent。如果first.obj和second.obj中的任何一個(gè)被修改了(其time stamp更大),則調(diào)用link.exe,重新連接生成foo.exe。這就是NMAKE的執(zhí)行邏輯。
              綜上,NMAKE的核心就是這3個(gè)家伙——依賴關(guān)系,操作和判定邏輯(target.timestamp < dependent.timestamp,如果為true,就執(zhí)行相應(yīng)操作)。
              MAKEFILE的語(yǔ)法
              現(xiàn)在詳細(xì)討論一下makefile的語(yǔ)法。makefile就像一個(gè)玩具型的程序語(yǔ)言,麻雀雖小,但五臟具全。makefile的組成部分包括:描述語(yǔ)句(description block),inference rules(推導(dǎo)規(guī)則),宏和指令(directive)。描述語(yǔ)句就是dependent lines和command lines的組合;inference rules就是預(yù)先定義好的或用戶自己定義的依賴關(guān)系和關(guān)聯(lián)命令;宏就不用說(shuō)了吧;指令就是內(nèi)定的一些可以被NMAKE識(shí)別的控制命令,提供了很多有用的功能。
              另外,makefile中使用以下幾個(gè)具有特殊意義的符號(hào):
              ^ # \ ( ) { } ! @ - : ; $
              ^(caret):用于關(guān)閉某些字符所具有的特殊意義,使其只表示字面上的意義。例如:^#abc表示#abc這個(gè)字符串,而#abc則用于在makefile中加入注釋,#在這里為注釋標(biāo)志,就像C++中的//。另外,在一行的末尾加上^,可以使行尾的回車換行符成為字串的一部分。
              #(number sign):為注釋標(biāo)志,NMAKE會(huì)忽略所有從#開(kāi)始到下一個(gè)換行符之間的所有文本。這里要注意的是:在command lines中不能存在注釋。因?yàn)閷?duì)于command lines,NMAKE是將其整行傳遞給OS的。通常對(duì)于command lines的注釋都是放在行與行之間。
              \(backslash):用于將兩行合并為一行。將其放在行尾,NMAKE就會(huì)將行尾的回車換行符解釋為空格(space)。
              %(percent symbol):表示其后的字符串為一文件名。用法較復(fù)雜,在講dependent lines的時(shí)候再詳細(xì)討論。
              !(exclamation symbol):命令修飾符,在下面會(huì)有詳細(xì)的討論。
              @(at sign):命令修飾符,在下面會(huì)有詳細(xì)的討論。
              :(colon):用于dependent lines和inference rules中,用于分隔target和dependent。
              ;(semicolon):如果對(duì)于一個(gè)dependent line只有一條命令,則可以將該命令放在dependent line的后面,二者之間用“;”分隔。
              $(dolor sign):用于調(diào)用宏,在下面講宏的時(shí)候再詳細(xì)討論。
              在makefile中還可以使用DOS通配符(wildcard)來(lái)描述文件:*和?。作用相信大家都很熟悉了,在此就不再浪費(fèi)口水了。
              如果要將中間有空格或制表符的字符串作為整體對(duì)待,則應(yīng)該用雙引號(hào)將之括起來(lái),例如,在指定一個(gè)中間有空格的長(zhǎng)文件名的時(shí)候:
              “My Document”
              或在定義一個(gè)宏的時(shí)候:
               MYMACRO=”copy a:\foo.exe c:\”
              描述語(yǔ)句塊(Description Blocks)
               描述語(yǔ)句塊為makefile主體的基本組成單元,其典型結(jié)構(gòu)如下:
               target : dependents
               commands block
              Dependent Line
               每一個(gè)描述語(yǔ)句塊中只有一個(gè)dependent line,其定義了一個(gè)依賴關(guān)系。該行的開(kāi)頭不能有任何空白(空格或制表符)。冒號(hào)兩邊的target和dependent都可以有多個(gè),之間以空格分隔。NMAKE在分析makefile時(shí)首先會(huì)從頭到尾掃描每一個(gè)dependent line,然后根據(jù)依賴關(guān)系建立起一棵依賴關(guān)系樹(dependent tree)。例如對(duì)于依賴關(guān)系:
               foo.exe : first.obj second.obj
               first.obj : first.cpp
               second.obj : second.cpp
              則在其依賴關(guān)系樹中,foo.exe為first.obj和second.obj的父親,而first.obj則是first.cpp的父親,second.obj是second.cpp的父親。如果second.cpp被更新了,則second.obj會(huì)被重新構(gòu)造,從而導(dǎo)致foo.exe被重新構(gòu)造。NMAKE就是這樣由下而上地對(duì)整棵樹中的結(jié)點(diǎn)進(jìn)行評(píng)估的。
               雖然makefile中可以有很多的dependent lines,但NMAKE只會(huì)構(gòu)造出現(xiàn)在它的命令行中的targets,或者,如果命令行中沒(méi)有給出targets,就構(gòu)造第一個(gè)dependent line中的第一個(gè)target。其他所有無(wú)關(guān)的targets都不會(huì)被構(gòu)造。例如:
               foo1.exe foo2.exe : first.obj
               first.obj : first.cpp
               second.obj : second.cpp
              假設(shè)上面的第一行語(yǔ)句為makefile中出現(xiàn)的第一個(gè)dependent line,且命令行中沒(méi)有給出target。當(dāng)first.cpp被更新后,first.obj和foo1.exe都會(huì)被重新構(gòu)造,而foo2.exe和second.obj則不會(huì)。
               當(dāng)在一個(gè)dependent line中出現(xiàn)多個(gè)target時(shí),例如:
               boy.exe girl.exe : first.obj
               echo Hello
               該語(yǔ)句相當(dāng)于:
               boy.exe : first.obj
               echo Hello
               girl.exe : first.obj
               echo Hello
              (注:echo是一條控制臺(tái)命令,用于在STDOUT上顯示一行信息)
               同一個(gè)target也可以出現(xiàn)在多個(gè)dependent lines中。在這種情況下,如果只有一個(gè)dependent line后跟有command line,則它們會(huì)被合并為一個(gè)描述語(yǔ)句塊,例如:
               foo.exe : first.obj
               echo Building foo.exe…
               …
               foo.exe : second.obj
              NMAKE會(huì)將其處理為:
               foo.exe : first.obj second.obj
               echo Building foo.exe…
               如果每一個(gè)dependent line后都有command line,則它們會(huì)被作為兩個(gè)描述語(yǔ)句塊處理。
              如果在dependent line中使用雙冒號(hào)(::)來(lái)分隔target和dependent,并且同一個(gè)target出現(xiàn)在多個(gè)描述語(yǔ)句塊中,此時(shí),NMAKE將會(huì)匹配最合適的語(yǔ)句塊,以構(gòu)造該target。
              例如:
               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同時(shí)出現(xiàn)在兩個(gè)描述語(yǔ)句塊中,此時(shí),NMAKE在處理該makefile時(shí),將會(huì)選擇其中一個(gè)描述語(yǔ)句塊中的命令來(lái)執(zhí)行。如果任何asm文件被更新了,NMAKE就調(diào)用ML重新編譯之,然后再調(diào)用LIB(但CL以及之后的命令都不會(huì)被調(diào)用);類似地,如果任何C文件被更新了,NMAKE就會(huì)調(diào)用CL。
               在通常情況下,target和dependent都是文件名。NMAKE會(huì)首先在當(dāng)前目錄下搜索dependent,如果沒(méi)有找到,就到用戶指定的目錄下搜索。指定搜索路徑的語(yǔ)法如下:
               {directory1;directory2;…}dependent
              搜索路徑放在{}之中,如果有多個(gè),就用“;”分開(kāi)。注意,在各個(gè)語(yǔ)法成分之間是不能有空白的。
               Target和dependent也可以不是一個(gè)文件,而是一個(gè)標(biāo)號(hào)(label)。這時(shí),就稱之為pseudotarget(偽文件)。Pseudotarget的名字不能與當(dāng)前目錄下的任何文件名相同。一個(gè)pseudotarget如果要作為dependent,那么它必須要作為target出現(xiàn)在某個(gè)dependent line中。當(dāng)使用pseudotarget作為target時(shí),與之關(guān)聯(lián)的commands block一定會(huì)被執(zhí)行,同時(shí)NMAKE會(huì)賦予它一個(gè)假想的time stamp。該time stamp等于它的dependents中最大的time stamp,或者,如果它沒(méi)有dependent,就等于當(dāng)前時(shí)間。該假想的time stamp在pseudotarget作為dependent時(shí)會(huì)被用來(lái)進(jìn)行有效性評(píng)估。這個(gè)特性最大的好處就是,你可以讓NMAKE構(gòu)造多個(gè)target,而不用將每個(gè)target都在NMAKE的命令行中列出來(lái),例如:
               all : setenv project1.exe project2.exe
              project1.exe : project1.obj
              LINK project1;
              project2.exe : project2.obj
              LINK project2;
              setenv :
              set LIB=\project\lib
              上例中有兩個(gè)pseudotarget,一個(gè)是all,另一個(gè)是setenv。首先是setenv被評(píng)估,其作用是設(shè)置環(huán)境變量LIB,然后project1.exe和project2.exe依次被更新.
              Commands Block
               第二行開(kāi)始到下一個(gè)dependent line之間為commands block,其給出了當(dāng)dependents中的任何一個(gè)的time stamp大于target時(shí),需要執(zhí)行的指令序列(commadns block也可以為空,此時(shí),NMAKE什么也不干)。command line必須以空白開(kāi)頭(剛好與dependent line相反,NMAKE就是通過(guò)該特征來(lái)分辨二者的),并且在dependent line和commands block中的第一條語(yǔ)句之間不能有空白行(就是除了一個(gè)換行符,什么也沒(méi)有的行。所以只有一個(gè)空格或制表符的行是合法的,此時(shí)NMAKE將其解釋為一個(gè)null command),但在command lines之間可以有空白行。Commands block中的每一條命令可以是在控制臺(tái)中合法的任何命令。事實(shí)上大可將commands block當(dāng)成一個(gè)由控制臺(tái)命令序列組成的批處理文件。
               此外,對(duì)commands block中的命令,還可以在其前面添加一個(gè)或多個(gè)所謂的命令修飾符(command modifier),以實(shí)現(xiàn)對(duì)命令的一些額外的控制。命令修飾符有以下3種:
              1) @command
              消除該命令的所有到STDOUT的輸出。
              2) –[number]command
              關(guān)掉對(duì)該命令返回值的檢測(cè)。在默認(rèn)的情況下,如果一條命令返回非0值,則NMAKE將會(huì)停止執(zhí)行。但如果在命令前加上一“-”,則NMAKE將會(huì)忽略該命令的返回值。如果“-”緊接著一個(gè)整數(shù),則NMAKE會(huì)忽略掉任何大于該整數(shù)的返回值。
              3) !command
              如果該命令的執(zhí)行對(duì)象為$**或$?(這兩個(gè)都是預(yù)定義的宏,前者表示相應(yīng)的dependent line中所有的dependent,后者表示所有比target具有更大的time stamp的dependent),則該“!”修飾符將會(huì)使該命令施行于這兩個(gè)宏所描述的每一個(gè)獨(dú)立的文件上。
               NMAKE還提供了一些語(yǔ)法可以在commands block中表示相應(yīng)的dependent line中第一個(gè)dependent的文件名組成。例如:
               foo.exe : c:\sample\first.obj c:\sample\second.obj
               link %s
              NMAKE將“link %s”解釋為:
               link c:\sample\first.obj
              如果將命令改為“link %|pfF.exe”,則NMAKE將之解釋為:
               link c:\sample\first.exe
              %s表示全文件名,%|[part]F表示文件名中的某個(gè)部分,part可以是下列字符中的一個(gè)或多個(gè),如果part為空,%|F與%s的意思相同:
              1) d:盤符;
              2) p:路徑;
              3) f:文件基本名;
              4) e:文件擴(kuò)展名;
            Inference Rules(推導(dǎo)規(guī)則)
               Inference rules(下文簡(jiǎn)稱IR)是一個(gè)模板,它用于決定如何從一個(gè)具有某種擴(kuò)展名的文件構(gòu)造出一個(gè)具有另一種擴(kuò)展名的文件。NMAKE通過(guò)IR來(lái)確定用來(lái)更新target的命令以及推導(dǎo)target的dependents。IR的好處在于它滿足了像我這樣的懶人的需要。只要提供了正確的IR,則描述語(yǔ)句塊就可以極大地化簡(jiǎn)。請(qǐng)看下面的例子:
               foo.obj :
              上面的語(yǔ)句將會(huì)運(yùn)作得很好。是不是覺(jué)得很吃驚呢?事實(shí)上,NMAKE在處理該語(yǔ)句的時(shí)候,它首先在當(dāng)前目錄下搜索基本名為foo的文件(假設(shè)當(dāng)前目錄下有一個(gè)foo.c文件)。然后它查找一個(gè)后綴列表(suffix list),里面的每一項(xiàng)包含了從一種類型的文件構(gòu)造另一種類型的文件需要調(diào)用的命令和參數(shù)的相關(guān)信息。在NMAKE預(yù)定義的列表中,foo.c到foo.obj的構(gòu)造命令為CL。最后NMAKE調(diào)用CL,編譯foo.c。呵呵,這么一長(zhǎng)串的操作一條簡(jiǎn)單的語(yǔ)句就搞定了,是不是很方便呢!
               當(dāng)出現(xiàn)下列情況之一時(shí),NMAKE就會(huì)嘗試使用IR:
              l NMAKE遇到一個(gè)沒(méi)有任何命令的描述語(yǔ)句塊。此時(shí)NMAKE就會(huì)搜索后綴列表,試圖找到一個(gè)匹配的命令來(lái)構(gòu)造target。
              l 無(wú)法找到某個(gè)dependent,并且該dependent沒(méi)有作為target出現(xiàn)在其它dependent line中(即它不是一個(gè)pseudotarget)。此時(shí)NMAKE就會(huì)搜索給定的目錄以及后綴列表,試圖找到一個(gè)IR來(lái)構(gòu)造出該dependent。
              l 一個(gè)target沒(méi)有dependent,并且描述語(yǔ)句塊中沒(méi)有給出指令。此時(shí)NMAKE就會(huì)試圖找出一個(gè)IR來(lái)構(gòu)造出該target。
              l 一個(gè)target在NMAKE的命令行中給出,但在makefile里沒(méi)有該target的相關(guān)信息(或根本就沒(méi)有makefile)。此時(shí)NMAKE就會(huì)試圖找出一個(gè)IR來(lái)構(gòu)造出該target。
              定義一個(gè)IR的語(yǔ)法如下:
               [{frompath}].fromext[{topath}].toext;
               commands
              注意,各語(yǔ)法元素之間不能有任何空格。Dependent的后綴名在fromext中給出,target的后綴名在toext中給出。Frompath和topath是可選的,分別給出了搜索的路徑。在每個(gè)IR的定義中只能分別為每一個(gè)后綴名給出一個(gè)搜索路徑。如果想要指定多個(gè)搜索路徑,就必須定義多個(gè)IR。并且,如果你為一個(gè)后綴指定了搜索路徑,那么你也必須為另一個(gè)后綴指定搜索路徑。即是說(shuō),fromext和topath只要有一個(gè)存在,則另一個(gè)也必須存在。你可以使用{.}或{}來(lái)表示當(dāng)前目錄。
              另外,要注意的是,如果你在IR中指定了搜索路徑,則在dependent lien中也必須指定同樣的路徑,否則IR將不會(huì)應(yīng)用于dependent line上,例如:
               {..\proj}.exe{..\proj}.obj:
              該IR不會(huì)用于下列語(yǔ)句上:
              project1.exe : project1.obj
              但會(huì)用于下列語(yǔ)句上:
              {..\proj}project1.exe : {..\proj}project1.obj
              NMAKE本身提供了一個(gè)預(yù)定義的后綴列表,內(nèi)容如下:
               Rule Command Default Action
               .asm.exe $(AS)$(AFLAGS) $*.asm ML $*.ASM
              .asm.obj $(AS)$(AFLAGS) /c $*.asm ML /c $*.ASM
              .c.exe $(CC)$(CFLAGS) $*.c CL $*.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 $*.BAS;
              .cbl.exe $(COBOL) $(COBFLAGS) $*.cbl, $*.exe; COBOL $*.CBL, $*.EXE;
              .cbl.obj $(COBOL) $(COBFLAGS) $*.cbl; COBOL $*.CBL;
              .for.exe $(FOR) $(FFLAGS) $*.for FL $*.FOR
              .for.obj $(FOR) /c $(FFLAGS) $*.for FL /c $*.FOR
              .pas.exe $(PASCAL) $(PFLAGS) $*.pas PL $*.PAS
              .pas.obj $(PASCAL) /c $(PFLAGS) $*.pas PL /c $*.PAS
              .rc.res $(RC) $(RFLAGS) /r $* RC /r $*
               在上表中,類似AFLAG和CFLAG這種被包含在括號(hào)里面的是未定義的宏,通過(guò)在makefile中對(duì)這些宏給出定義,可以為這些命令指定編譯器和參數(shù)。例如:
               $(AS)$(AFLAGS) $*.asm
              AS宏用于指定編譯器,NMAKE中默認(rèn)為ML;AFLAGS宏用于給出編譯器參數(shù),NMAKE將之留給用戶定義,默認(rèn)為空。所以默認(rèn)的操作為:
              ML $*.asm
              這里可以看到將宏展開(kāi)的語(yǔ)法,就是將宏的名字用圓括號(hào)括起來(lái),然后在前面加上一個(gè)美元符號(hào)。另外需要說(shuō)明的是,”$*”是NMAKE預(yù)定義的一個(gè)特殊的宏,其等于target的路徑加上target的基本名。
              宏(MARCRO)
               這個(gè)相信大家都十分熟悉了。在makefile中通過(guò)使用宏將可以獲得很大的靈活性。下面就是在makefile中定義宏的語(yǔ)法:
               macroname=string
              在makefile中,macroname是宏的名字,其可以是任何字母,數(shù)字和下劃線的組合,最多可以有1024個(gè)字符。另外要注意的是,macroname是大小寫敏感的。string是宏的定義體,可以有高達(dá)65510個(gè)字符。任何包含0個(gè)字符或只包含空白的字符串都被視為空字串(null string),此時(shí),該宏也被視為NULL,任何其出現(xiàn)的地方,都會(huì)被替換為空白。
               在使用宏時(shí),還應(yīng)知道以下幾個(gè)具有特殊意義的符號(hào):
              l # 用于注釋,例如:
              command=ML # compile asm file
              l \ 將宏定義分作多行來(lái)寫,例如:
              LINKCMD = link myapp
              another, , NUL, mylib, myapp
              “\”后面的回車換行符會(huì)被空格替換,上面兩行相當(dāng)于:
              LINKCMD = link myapp another, , NUL, mylib, myapp
              l $ 將宏展開(kāi),用法在后面介紹。
              l ^ 如果要在宏中包含以上符號(hào),但又不使用它們的特殊語(yǔ)義,則可以這樣:
              dir=c:\windows^
              此時(shí),dir相當(dāng)于字符串”c:\windows\”。
               以下是一些語(yǔ)法上的細(xì)節(jié):
              1) 在定義宏時(shí),宏名字的第一個(gè)字符必須是該行的第一個(gè)字符;
              2) 每行只能定義一個(gè)宏;
              3) 在”=”兩邊可以有空格,但它們都會(huì)被忽略;
              4) 在宏定義體中可以有空格,它們都會(huì)被視為宏的一部分;
              除了可以在makefile中定義宏之外,宏定義也可以出現(xiàn)在NMAKE命令行中。此時(shí),如果在宏定義中有任何空白,則必須用雙引號(hào)將之括起來(lái),例如:
              NMAKE "LINKCMD = LINK /MAP"
              NMAKE LINKCMD="LINK /MAP"
              而像下面這樣則是不允許的(等號(hào)兩邊有空格):
               NMAKE LINKCMD = "LINK /MAP"
               使用宏的語(yǔ)法如下(注意,整個(gè)語(yǔ)句中不能有任何空格):
               $(macroname)
               NMAKE會(huì)將整個(gè)語(yǔ)句用宏替換掉。如果宏未定義,NMAKE會(huì)用空白替換之,不會(huì)產(chǎn)生任何錯(cuò)誤。如果宏的名字只有一個(gè)字符,則括號(hào)可以省略,例如:$L和$(L)是等價(jià)的。
               NMAKE為宏的使用還提供了一個(gè)很有用的特性,那就是substitution(子替換)。即是在展開(kāi)宏的時(shí)候,你還可以指明將展開(kāi)的宏中的某部分文本用另外的文本替換掉。例如:
               SOURCE=one.c two.c
              foo.exe : $(SOURCE:.c=.obj)
               LINK $**;
              展開(kāi)來(lái)就是這樣:
              SOURCE=one.c two.c
              foo.exe : one.obj two.obj
               LINK one.obj two.obj;
              語(yǔ)句$(SOURCE:.c=.obj)表示將SOURCE中出現(xiàn)的所有”.c”替換為”.obj”。
              由以上的例子可以看出,substitution的語(yǔ)法如下(注意,沒(méi)有空格):
              $(macroname:str1=str2)
               此外,NMAKE還提供了4組預(yù)定義的宏,它們分別是文件名宏,遞歸宏,命令宏和參數(shù)宏。它們都可以被重新定義,但可能會(huì)引起一些不必要的麻煩,因?yàn)樗鼈儽粡V泛使用。正所謂“動(dòng)一發(fā)而牽全身”,一個(gè)小小的改動(dòng),甚至有可能會(huì)影響到太陽(yáng)黑子的運(yùn)動(dòng)(蝴蝶效應(yīng)),這就是使用宏的最大的弊端。
              文件名宏
              在commands block中使用,以表示特定的文件名,包括:
              1) $@ 用來(lái)表示相關(guān)聯(lián)的dependent line中第一個(gè)target的全名(包括路徑)。
              2) $$@ 同上,但只能用在dependent line中。
              3) $* target的路徑加基本名。
              4) $** 相應(yīng)的dependent line中的所有dependent。
              5) $? 相應(yīng)的dependent line中的所有time stamp大于target的dependent。
              6) $< 同上,但只能用在IR中。
              下面是一個(gè)例子:
              DIR = c:\objects
              $(DIR)\a.obj : a.obj
              COPY a.obj $@
               最后一句展開(kāi)來(lái)就相當(dāng)于:copy a.obj c:\objects\a.obj
               另外,在使用以上這些宏的時(shí)候,還可以通過(guò)以下的字符來(lái)提取文件名中的某一個(gè)部分:
               D 路徑
               B 基本名
               F 基本名加擴(kuò)展名
               R 路徑加基本名
               例如:如果$@表示c:\objects\a.object,則
               $(@D) c:\objects
               $(@B) a
               $(@F) a.obj
               $(@R) c:\objects\a
              遞歸宏
               有3個(gè),它們都是用來(lái)在makefile中方便地進(jìn)行NMAKE的遞歸調(diào)用,它們分別是:
              1) MAKE
              表示運(yùn)行當(dāng)前makefile的NMAKE程序的名字。例如,如果你在控制臺(tái)用以下語(yǔ)句運(yùn)行makefile:
              NMAKE her.mak
              則MAKE就等于NMAKE。
              但如果你將NMAKE.EXE改名為FUCK.EXE,那么你運(yùn)行makefile的命令就應(yīng)該改為:
              FUCK her.mak
              此時(shí),MAKE就等于FUCK。
              2) MAKEDIR
              表示你調(diào)用NMAKE時(shí)所在的目錄。
              3) MAKEFLAGS
              表示你運(yùn)行當(dāng)前makefile時(shí)使用的NMAKE參數(shù)。
               這幾個(gè)宏在build程序的不同版本時(shí)特別有用,例如:
               all : vers1 vers2
              vers1 :
              cd \vers1
              $(MAKE)
              cd ..
              vers2 :
              cd \vers2
              $(MAKE) /F vers2.mak
              cd ..
               NMAKE會(huì)分別在.\vers1和.\vers2目錄下運(yùn)行vers1.mak和vers2.mak。
              命令宏和參數(shù)宏
               命令宏表示Microsoft的編譯程序(真的很會(huì)做生意,任何時(shí)候都不忘自己的產(chǎn)品),而參數(shù)宏則是表示傳遞給這些編譯器的參數(shù),在默認(rèn)情況下,參數(shù)宏都是未定義的。當(dāng)然,你可以重新定義它們,讓它們表示Boland的編譯程序和參數(shù)。
               命令宏 對(duì)應(yīng)的參數(shù)宏
              1) AS ml,M的匯編編譯器。 AFLAGS
              2) BC bc,M的BASIC編譯器。 BFLAGS
              3) CC cl,M的C編譯器。 CFLAGS
              4) COBOL cobol,M的COBOL編譯器。 COBFLAGS
              5) CPP cl,M的C++編譯器。 CPPFLAGS
              6) CXX cl,M的C++編譯器。 CXXFLAGS
              7) FOR fl,M的FORTRAN編譯器。 FFLAGS
              8) PASCAL pl,M的PASCAL編譯器。 PFLAGS
              9) RC rc,M的資源編譯器。 RFLAGS
            posted on 2008-02-26 22:02 一路風(fēng)塵 閱讀(531) 評(píng)論(0)  編輯 收藏 引用

            只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。
            網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問(wèn)   Chat2DB   管理


            久久久久久亚洲AV无码专区| 久久精品国产精品亚洲艾草网美妙| 思思久久99热免费精品6| 午夜精品久久久久久| 久久精品无码午夜福利理论片| www.久久热.com| 日韩电影久久久被窝网| 精品无码久久久久久午夜| 久久av免费天堂小草播放| 久久久精品2019免费观看| 激情综合色综合久久综合| 久久亚洲私人国产精品vA| 久久九九久精品国产| 久久精品无码午夜福利理论片| 久久强奷乱码老熟女网站| 久久精品国产亚洲av麻豆色欲| 久久强奷乱码老熟女网站| 成人午夜精品久久久久久久小说| 国产成人久久精品一区二区三区 | 99久久做夜夜爱天天做精品| 久久成人精品视频| 亚洲国产精品无码成人片久久| 久久久精品久久久久特色影视| 久久久久免费看成人影片| 久久精品国产亚洲AV影院| 久久国产成人午夜AV影院| 国产精品成人99久久久久 | 精品久久久久一区二区三区| 国产亚洲综合久久系列| 久久亚洲精品成人AV| 一本色道久久综合狠狠躁 | 国产精品久久久天天影视| 国产精品99久久免费观看| 精品久久人妻av中文字幕| 无遮挡粉嫩小泬久久久久久久| 伊人久久大香线蕉亚洲五月天| 久久综合九色综合网站| 久久亚洲精品无码VA大香大香| 香蕉久久影院| 久久精品中文无码资源站| 国产精品一区二区久久|