國(guó)訊之linux makefile教程跟我一起寫_第1頁(yè)
國(guó)訊之linux makefile教程跟我一起寫_第2頁(yè)
國(guó)訊之linux makefile教程跟我一起寫_第3頁(yè)
國(guó)訊之linux makefile教程跟我一起寫_第4頁(yè)
國(guó)訊之linux makefile教程跟我一起寫_第5頁(yè)
已閱讀5頁(yè),還剩72頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

跟我一起寫 TOC\o"1-2"\h\z\u概 Makefile介 五、讓make自動(dòng)推 書寫規(guī) 五、偽目 六、多目 書寫命 使用變 五、override指示 一、示 二、語 使用函 四、foreach函 make的運(yùn) 二、指定 隱含規(guī) —什么是makefile?或許很多WinodwsWindowsIDE這就好像現(xiàn)在有這么多的HTML的編輯器,但如果你想成為一個(gè)專業(yè)人士,你還是要了解HTMLUnixmakefile了,會(huì)不會(huì)寫makefile,從一個(gè)側(cè)面說明了一個(gè)人是否具備完成大型工程的能力。makefile就像一個(gè)Shell腳本一樣,其中也可以執(zhí)行操作系統(tǒng)的命令。C++nmake,LinuxGNUmake??梢?,makefile都成為了一種在工程方面的編譯方makefile的文章比較少,這是我想寫這篇文章的原因。當(dāng)然,不同產(chǎn)商的make各不相同,也有不同的語法,但其本質(zhì)都是在“文件依賴性”上做文章,這里,我僅GNUmakeRedHatLinux8.0,make3.80。必竟,這(POSIX.2GCC和CC。C、C++pas,Windows.obj文件,UNIX.o文(compile(link告訴編譯器頭文件的所在位置(C/C++文件中,應(yīng)于一個(gè)中間目標(biāo)文件(O文件或是OBJ文件。FileWindows下這種包叫“庫(kù)文件”(LibraryFile).libUNIX下,是ArchiveFile,也就是.a文件。警告,但可以生成ObjectFile。而在鏈接程序時(shí),鏈接器會(huì)在所有的ObjectFile中找尋函數(shù)ErrorLink2001錯(cuò)誤,意思說是說,鏈接器未能找到函數(shù)的實(shí)現(xiàn)。你需要指定函數(shù)的ObjectFile.MakefilemakeMakefile文件,以告訴make命令需要怎么樣的去編譯和鏈接首先,我們用一個(gè)示例來說明Makefile的書寫規(guī)則。以便給大家一個(gè)感興認(rèn)識(shí)。這個(gè)示例我們要寫一個(gè)Makefile來告訴make命令如何編譯和鏈接這幾個(gè)文件。我們的規(guī)則是:如果這個(gè)工程沒有編譯過,那么我們的所有Ctarget...:prerequisitestargetObjectFile,也可以是執(zhí)行文件。還可以是一個(gè)標(biāo)(Label這是一個(gè)文件的依賴關(guān)系,也就是說,target這一個(gè)或多個(gè)的目標(biāo)文件依賴于prerequisitestarget文件要新的話,commandMakefile的規(guī)則。也就是Makefile中最核心的內(nèi)容。說到底,Makefile的東西就是這樣一點(diǎn),好像我的這篇文檔也該結(jié)束了。呵呵。還不盡然,MakefileMakefile還不夠,我會(huì)以后面一點(diǎn)一點(diǎn)地結(jié)合)那三個(gè)規(guī)則,我們的Makefile應(yīng)該是下面的這個(gè)樣子的。edit:main.okbd.ocommand.odisplay.o\insert.osearch.ofiles.outils.occ-oeditmain.okbd.ocommand.odisplay.oinsert.osearch.ofiles.omain.o:main.ccc-ckbd.o:kbd.cdefs.hcommand.hcc-ckbd.ccommand.o:command.cdefs.hcommand.hcc-ccommand.cdisplay.o:display.cdefs.hbuffer.hcc-cdisplay.cinsert.o:insert.cdefs.hbuffer.hcc-cinsert.ccc-csearch.cfiles.o:files.cdefs.hbuffer.hcommand.hcc-cfiles.cutils.o:utils.ccc-ccleanrmeditmain.okbd.ocommand.odisplay.o\insert.osearch.ofiles.outils.o反斜杠(\)Makefile的易讀。我們可以把這個(gè)內(nèi)容保存在一下“makeclean”就可以了。(*.o件(prerequisites)就是冒號(hào)后面的那些.c文件和.h文件。每一個(gè).o文件都有一組依賴文件,而這些.o文件又是執(zhí)行文件edit的依賴文件。依賴關(guān)系的實(shí)質(zhì)上就是說明了目標(biāo)比較targets文件和prerequisitesprerequisites文件的日期要比targets文件的日期要新,或者target不存在的話,那么,make就會(huì)執(zhí)行后續(xù)定義的命令。這里要說明一點(diǎn)的是,cleanC語言中的lable一樣,其冒號(hào)后什么也沒有,那么,make就不會(huì)自動(dòng)去找文件的依賴性,也就不會(huì)自makelable(target3editedit.o4edit所依賴的.omake會(huì)在當(dāng)前文件中找目標(biāo)為.o文件的依賴性,如果找到則再根據(jù)那一個(gè)規(guī)則生成.o文件。(這有點(diǎn)像一個(gè)堆棧的過程)這就是整個(gè)make的依賴性,make會(huì)一層又一層地去找文件的依賴關(guān)系,直到最終編譯出make就會(huì)直接退出,并報(bào)錯(cuò),而對(duì)于所定義的命令的錯(cuò)誤,或是編譯不成功,make根本不file.o會(huì)被重編譯(也就是在這個(gè)依性關(guān)系后面所定義的命令)file.ofile.oedit要新,所以edit也會(huì)被重新鏈接了(詳見edit目標(biāo)文件后定義的命令。edit:main.okbd.ocommand.odisplay.occ-oeditmain.okbd.ocommand.odisplay.oinsert.osearch.ofiles.o那么我們需要在兩個(gè)地方加(應(yīng)該是三個(gè)地方,還有一個(gè)地方在clean中。當(dāng)然,我們的makefilemakefile變得復(fù)雜,那么我們就有可objects,OBJECTS,objsOBJS,obj,OBJ,反正不管什么啦,只要能夠表示obj文件就行了。我們?cè)趍akefile一開始就這樣定義:objects=main.okbd.ocommand.odisplay.o\insert.osearch.ofiles.outils.o于是我們的改良版makefile就變成下面這個(gè)樣子:objects=main.okbd.ocommand.odisplay.o\insert.osearch.ofiles.outils.oedit:cc-oedit$(objects)main.o:main.cdefs.hcc-ckbd.o:kbd.cdefs.hcommand.hcc-ckbd.ccommand.o:command.cdefs.hcommand.hcc-ccommand.cdisplay.o:display.cdefs.hbuffer.hcc-cdisplay.cinsert.o:insert.cdefs.hbuffer.hcc-cinsert.ccc-csearch.cfiles.o:files.cdefs.hbuffer.hcommand.hcc-cfiles.cutils.o:utils.ccc-ccleanrmedit.oobjects變量就可以了。GNUmake很強(qiáng)大,它可以自動(dòng)推導(dǎo)文件以及文件依賴關(guān)系后面的命令,于是我們就沒必要去在每一個(gè)[.o]make會(huì)自動(dòng)識(shí)別,并自己推make看到一個(gè)[.o]文件,它就會(huì)自動(dòng)的把[.c]make找到一whatever.owhatever.cwhatever.occcwhatever.c也會(huì)objects=main.okbd.ocommand.odisplay.o\insert.osearch.ofiles.outils.oedit:cc-oeditmain.o:kbd.o:defs.hcommand.hcommand.o:defs.hcommand.hdisplay.o:defs.hbuffer.hinsert.o:defs.hbuffer.hsearch.o:defs.hbuffer.hfiles.o:defs.hbuffer.hcommand.hutils.o:defs.hclean:rmeditmake可以自動(dòng)推導(dǎo)命令,那么我看到那堆[.o]和[.h]的依賴就有點(diǎn)不爽,那么多的重復(fù)的[.h]make來說很容易,誰叫它提供了自動(dòng)推導(dǎo)命令和文件的功能呢?來看看最新風(fēng)格的makefile吧。objects=main.okbd.ocommand.odisplay.o\insert.osearch.ofiles.outils.oedit:cc-oedit$(objects):kbd.ocommand.ofiles.o:command.hdisplay.oinsert.osearch.ofiles.o:buffer.hclean:rmedit二是如果文件一多,要加入幾個(gè)新的.o文件,那就理不清楚了。(rmeditclean:-rmedit的意思就是,也許某些文件出現(xiàn)問題,但不要管,繼續(xù)做后面的事。當(dāng)然,clean的規(guī)則不規(guī)矩是——“clean從來都是放在文件的最后”。2make有自動(dòng)推導(dǎo)的功能,所以隱晦的規(guī)則可以讓我們比較粗糙地簡(jiǎn)略地書寫Makefile,這是由make所支持的。3、變量的定義。在Makefile中我們要定義一系列的變量,變量一般都是字符串,這個(gè)有點(diǎn)你C語言中的宏,當(dāng)Makefile被執(zhí)行時(shí),其中的變量都會(huì)被擴(kuò)展到相應(yīng)的引用位置上。中的預(yù)編譯#if一樣;還有就是定義一個(gè)多行的命令。有關(guān)這一部分的內(nèi)容,我會(huì)在后續(xù)的5、注釋。MakefileUNIXShell腳本一樣,其注釋是用“#”字符,這C/C++中的“//Makefile中使用“#”字符,可以用反斜框進(jìn)行轉(zhuǎn)義,如:“akefile“GNUmakefileGNU的make識(shí)別的。有另外一些make只對(duì)全小寫的如:make-fMake.Linux或make--fileMake.AIX。被包含的文件會(huì)原模原樣的放在當(dāng)前文件的包含位置。include的語法是:件叫foo.make,以及一個(gè)變量$(bar),其包含了e.mk和f.mk,那么,下面的語句:includefoo.make*.mkincludefoo.makea.mkb.mkc.mke.mk會(huì)在當(dāng)前目錄下首先尋找,如果當(dāng)前目錄下沒有找到,那么,make還會(huì)在下面的幾個(gè)目錄2、如果目錄<prefix>;/include(一般是:/usr/local/bin或/usr/include)存在的話,make如果有文件沒有找到的話,make會(huì)生成一條警告信息,但不會(huì)馬上出現(xiàn)致命錯(cuò)誤。它會(huì)繼makefile的讀取,make會(huì)再重試這些沒有找到,或是不能讀取的文件,如果還是不行,makemake不理那些無法include前加一個(gè)減號(hào)“-”。如:include四、MAKEFILES,那么,make會(huì)把這個(gè)變量中的值做一Makefile的“目標(biāo)”不會(huì)起作用,如果環(huán)境變量中定義的文件發(fā)現(xiàn)錯(cuò)誤,make也會(huì)不理。makeMakefile都會(huì)受到它的影響,這絕不是你想看到的。在這里提這個(gè)事,只Makefile出現(xiàn)了怪事,那么你可以看看當(dāng)前環(huán)境中有沒1-5步為第一個(gè)階段,6-7為第二個(gè)階段。第一個(gè)階段中,如果定義的變量被使用了,那么,make會(huì)把其展開在使用的位置。但make并不會(huì)完全馬上展開,make使用的是拖延戰(zhàn)術(shù),———Makefile中的目標(biāo)可能會(huì)有很多,但是第一條規(guī)則中的目標(biāo)將被確立為最終的目標(biāo)。如果第一條規(guī)則中的目標(biāo)有很多個(gè),那么,第一個(gè)目標(biāo)會(huì)成為最終的目標(biāo)。make所foo.ofoo.c foocc-c-gfoo.c(期要比foo.o文件日期要新,或是foo.o不存在,那么依賴關(guān)系發(fā)生。個(gè)文件。(foo.cincludedefs.h文件)targets:prerequisitestargets:prerequisites;command如果和prerequisites在一行,那么可以用分號(hào)做為分隔。(見上)制。規(guī)則告訴make兩件事,文件的依賴關(guān)系和如何成成目標(biāo)文件。如果我們想定義一系列比較類似的文件,我們很自然地就想起使用通配符。make支持三各通配符代替了你一系列的文件,如“*.cc的文件。一個(gè)需要我們注意的rm-fprint:lpr-p$?touchprintprint依賴于所有的[.c]文件。objects=開,也就是讓objects的值是所有[.o]的文件名的集合,那么,你可以這樣:objects:=$(wildcard但最好的方法是把一個(gè)路徑告訴make,讓make在自動(dòng)去找。只會(huì)在當(dāng)前的目錄中去找尋依賴文件和目標(biāo)文件。如果定義了這個(gè)變量,那么,make就會(huì)make的“vpath”關(guān)鍵字(注意,它是全小寫的,<3、vpath%.hvpathvpath語句中出現(xiàn)了相同的<pattern>;,或是被重復(fù)了的<pattern>;,那么,makevpath語句的先后順序來執(zhí)vpath%.cfoovpath% vpath%.cbarvpath%.cfoo:barvpath rm*.o供一個(gè)清除它們的“目標(biāo)”以備完整地重編譯而用。(以“makeclean”來使用該目標(biāo)).PHONY:rm*.o個(gè)Makefile中,那么你可以使用“偽目標(biāo)”這個(gè)特性:all:prog1prog2.PHONY:prog1:prog1.occ-oprog1prog1.oprog2:cc-oprog2prog2.oprog3:prog3.osort.outils.occ-oprog3prog3.osort.o.PHONY:cleanallcleanobjcleandiffcleanall:cleanobjcleandiffrmrmrm$@(bigoutputlittleoutput:generatetext.g-$(substoutput,,$@)>;bigoutput:generatetext.g-big>;bigoutputlittleoutput:text.ggeneratetext.g-little>;其中,-$(substoutput,,$@)中的“$Makefilesubst,all:$(objects)$(objects):%.o:$(CC)-c$(CFLAGS)$<-obacofoo.o:$(CC)-c$(CFLAGS)foo.c-ofoo.obar.o:bar.c$(CC)-c$(CFLAGS)bar.c-ofiles=foo.elcbar.o$(filter%.o,$(files)):%.o:$(CC)-c$(CFLAGS)$<-oemacs-fbatch-byte-compile的內(nèi)容。其的它內(nèi)容,我就不用多說了吧。這個(gè)例字展示了Makefile中更大的彈性。main.o:main.cdefs.hC文件包含了哪些頭文件,并且,你cc-Mmain.o:main.c而由編譯器自動(dòng)生成了。需要提醒一句的是,如果你使用GNU的C/C++編譯器,你得用“-MM”參數(shù),不然,“M”參數(shù)會(huì)把一些標(biāo)準(zhǔn)庫(kù)的頭文件也包含進(jìn)來。gccMmain.c那么,編譯器的這個(gè)功能如何與我們的Makefile聯(lián)系在一起呢。因?yàn)檫@樣一來,我們的Makefile也要根據(jù)這些源文件重新生成,讓Makefile自已依賴于源文件?這個(gè)功能并不現(xiàn)實(shí),不過我們可以有其它手段來迂回地實(shí)現(xiàn)這一功能。GNU組織建議把編譯器為每一個(gè)源的Makefile文件,[.d]文件中就存放對(duì)應(yīng)[.c]文件的依賴關(guān)系。%.d:@set-e;rm-f$@;$(CC)-M$(CPPFLAGS)$<>;$@.$$$$;sed's,\($*\)\.o[:]*,\1.o$@:,g'<$@.$$$$>;$@;\rm-f$@.$$$$也就是[.d]文件,第二行的意思是,為每個(gè)依賴文件“$”,也就是[.c]文件生成依賴文件,一個(gè)替換,關(guān)于sed命令的用法請(qǐng)參看相關(guān)的使用文檔。第四行就是刪除臨時(shí)文件。main.o:main.cmain.omain.d:main.csources=foo.cbar.cgunguymadman回復(fù)于:2004-09-16———make會(huì)認(rèn)為其是一個(gè)空命令。UNIXShellmake的命令默認(rèn)是被“/bin/sh”——UNIX很像C/C++中的“”,其后的本行字符都被注釋。通常,make會(huì)把其要執(zhí)行的命令行在命令執(zhí)行前輸出到屏幕上。當(dāng)我們用“@”字符在命@echoXXX模塊 “@,echoXXX模塊當(dāng)依賴目標(biāo)新于目標(biāo)時(shí),也就是當(dāng)規(guī)則的目標(biāo)需要被更新時(shí),make會(huì)一條一條的執(zhí)行其后cd/home/hchencd/home/hchen;/hoe/hchen每當(dāng)命令運(yùn)行完后,makemake會(huì)執(zhí)則中的某個(gè)命令出錯(cuò)了(命令退出碼非零make就會(huì)終止執(zhí)行當(dāng)前規(guī)則,這將有可mkdir就成功執(zhí)行,萬事大吉,如果目錄存在,那么就出錯(cuò)了。我們之mkdirmkdir出錯(cuò)而終止Makefile的命令行前加一個(gè)減號(hào)“-(-rm-f還有一個(gè)全局的辦法是,給make加上“-i”或是“--ignore-errors”參數(shù),那么,Makefile件的編譯規(guī)則。那么我們總控的Makefile可以這樣書寫:cdsubdir&&$(MAKE)-C利于維護(hù)。這兩個(gè)例子的意思都是先進(jìn)入“subdir”目錄,然后執(zhí)行make命令。export<variableexportvariable=variable=valueexportvariableexportvariable:=variable:=valueexportvariableexportvariable+=variable+=valueexportvariableexport就行了。后面什么也不用跟,表示傳遞MAKEFILESMakefile中,這是一(cdsubdir&&$(MAKE)MAKEFLAGS,那么你得確信其中的選項(xiàng)是大家都會(huì)用到的,如果程中輸出一些信息,讓你看到目前的工作目錄。比如,如果我們的下級(jí)make目錄是slient)Makefile中出現(xiàn)一些相同命令序列,那么我們可以為這些相同的命令序列定義一個(gè)變definerun-yaccyacc$(firstword$^)mvy.tab.c$@foo.c:foo.c(gunguymadman回復(fù)于:2004-09-16———MakefileC/C++語言中的宏一樣,他代表了一個(gè)文本字串,在MakefileC/C++所不同的是,令”或是Makefile的其它部分中。個(gè)不同的變量名。傳統(tǒng)的Makefile的變量名是全大寫的命名方式,但我推薦使用大小寫搭(objects=program.ofoo.outils.oprogram:$(objects)cc-oprogram$(objects):foo=cprog.o:$(foo)$(foo)-$(foo)prog.o:cc-cMakefileMakefile中的變量在Makefile中有兩種方式來foo=$(bar)bar=$(ugh)ugh=Huh?echoHuh?(Huh?)CFLAGS=$(include_dirs)-Oinclude_dirs=-Ifoo-IbarCFLAGS=$(CFLAGS)-A=B=make運(yùn)行時(shí)非常慢,更糟糕的是,他會(huì)使用得兩個(gè)make的函數(shù)“wildcard”和“shell”發(fā)生不可預(yù)知的錯(cuò)x:=y:=$(x)barx:=latery:=foobarx:=latery:=$(x)barx:=foobarifeq :=$(shellpwd) host-type:=$(shellarch)MAKE:=${MAKE}host-type=${host-type}whoami=${whoami}會(huì)記錄了我們的當(dāng)前Makefile的調(diào)用層數(shù)。space:=$(nullstring)#endoftheEmpty變量來標(biāo)明dir:= #directorytoputthefrobsFOO?=ifeq($(originFOO),FOO=barfoo:=a.ob.oc.obar:=foo:=a.ob.obar:=x=yy=a:=x=$(y))x=y=z=a:=x=y=z=a:=“Hellox=variable1y=$(substz=a:=“Helloa=b=all=Helloa_objects:=a.ob.oc.o1_objects:=1.o2.osources:=cfunc:=sortbar:=adbgqfoo:=$($(func)dir=$(dir)_sources:=$(wildcard$(dir)/*.c)define$(dir)_print_objects=main.ofoo.obar.outils.oobjects+=another.oant.(ant.objects=main.ofoo.obar.outils.oobjects:=$(objects)another.o=variable:=valuevariable+=variable:=variable:=$(variable)variable=valuevariable+=如果你想在Makefile中設(shè)置這類參數(shù)的值,那么,你可以使用“override”指示符。其語法override<variable>;=<value>;override<variable>;+=<moreoverridedefinefoogunguymadman回復(fù)于:2004-09-16defineendef關(guān)鍵字結(jié)因?yàn)槊钚枰訹Tab]define定義的命令變量中沒有以[Tab]鍵開頭,那么make就不會(huì)把其認(rèn)為是命令。echofoomakemakeMakefile文件中,但是如果Makefilemake命令行帶入,那么系統(tǒng)的環(huán)境變量的因此,如果我們?cè)诃h(huán)境變量中設(shè)置了“CFLAGS”環(huán)境變量,那么我們就可以在所有的CFLAGSMakefile中的這個(gè)變量,如果沒有定義則使用系統(tǒng)環(huán)境變make嵌套調(diào)用時(shí)(參見前面的“嵌套調(diào)用”章節(jié)Makefile中定義的變量會(huì)以系Makefile中。當(dāng)然,默認(rèn)情況下,只有通過命令行設(shè)置的Makefileexprot當(dāng)然,我并不推薦把許多的變量都定義在系統(tǒng)環(huán)境中,這樣,在我們執(zhí)行不用的ariable<target...>;:<variable-<target...>;:overide<variable-=第二個(gè)語法是針對(duì)于make命令行帶入的變量,或是系統(tǒng)環(huán)境變量。prog:CFLAGS=-gprog:prog.ofoo.obar.o$(CC)$(CFLAGS)prog.ofoo.oprog.o:foo.o:bar.o:在這個(gè)示例中,不管全局的$(CFLAGS)prog目標(biāo),以及其所引發(fā)的所有規(guī)則中(prog.ofoo.obar.o的規(guī)則,$(CFLAGS)的值都是“-g”GNUmake中,還支持模式變量(Pattern-specificariable,通過上面的目標(biāo)變量中,我們知道,make的“模式”一般是至少含有一個(gè)“%”的,所以,我們可以以如下方式給%.o:CFLAGS=-<pattern...>;:<variable-<pattern...>;:override<variable-libs_for_gcc=-lgnunormal_libs=foo:$(objects)$(CC)-ofoo$(objects)

$(CC)-ofoo$(objects)我們可以從上面的示例中看到三個(gè)關(guān)鍵字:ifeq、elseendif。ifeq的意思表示條件語句的else表示條件表達(dá)式為假的情況。endif表示一個(gè)條件語句的結(jié)束,任何一個(gè)條件表達(dá)式都應(yīng)該以endif結(jié)束。$(CC)-ofoo$(objects)$(CC)-ofoo$(objects)libs_for_gcc=-lgnunormal_libs=ifeq($(CC),gcc)$(CC)-ofoo$(objects)ifeq(<arg1>;,ifeq'<arg1>;''<arg2>;'ifeq"<arg1>;""<arg2>;"ifeq"<arg1>;"'<arg2>;'ifeq'<arg1>;'"<arg2>;"比較參數(shù)“arg1”和“arg2make的函數(shù)。ifeq($(strip(Emptyifneq(<arg1>;,<arg2>;)ifneq'<arg1>;''<arg2>;'ifneq"<arg1>;"'<arg2>;'ifneq'<arg1>;'"<arg2>;"如果變量<variable-name>;的值非空,那到表達(dá)式為真。否則,表達(dá)式為假。當(dāng)然,<variable-name>;同樣可以是一個(gè)函數(shù)的返回值。注意,ifdef只是測(cè)試一個(gè)變量是否有值,barfoo=$(bar)ifdeffoofooifdeffoono特別注意的是,makeMakefile時(shí)就計(jì)算條件表達(dá)式的值,并根據(jù)條件表達(dá)式的值gunguymadman回復(fù)于:2004-09-16———Makefile中可以使用函數(shù)來處理變量,從而讓我們的命令或是規(guī)則更為的靈活和具有智能。make所支持的函數(shù)也不算很多,不過已經(jīng)足夠我們的操作了。函數(shù)調(diào)用后,函數(shù)的返這里,<function>;就是函數(shù)名,make支持的函數(shù)不多。<arguments>;是函數(shù)的參數(shù),參數(shù)間為了風(fēng)格的統(tǒng)一,函數(shù)和變量的括號(hào)最好一樣,如使用“$(substa,b,$(x))”這樣的形式,而不是“$(substa,b,${x})”的形式。因?yàn)榻y(tǒng)一會(huì)更清楚,也會(huì)減少一些不必要的麻煩。space:=$(empty)$(empty)foo:=abcbar:=$(substa,b,c$(subst$(substee,EE,feetonthestrEEt<ar>;,<rlaeent>;,$(ar))%eea例如有:objectsfoo.obar.o%.$(strip$(stripabc把字串“abc”去到開頭和結(jié)尾的空格,結(jié)果是“ab$(findstringa,ab$(findstringa,b$(filtersources:=foo.cbar.cbaz.sugh.hfoo:$(sources)cc$(filter%.c%.s,$(sources))-obaz.sobjects=main1.ofoo.omain2.obar.omains=main1.omain2.o)bar.o$(sort示例:$(sortfoobarlose)返回“barfoolose備注:sort函數(shù)會(huì)去掉<list>;中相同的單詞。r$(words備注:如果我們要取<text中最后的一個(gè)單詞,我們可以這樣:$(wordfoo一個(gè)現(xiàn)實(shí)中應(yīng)用的例子。我們知道,make使用“VPATH”變量來指定“依賴文件”的搜索overrideCFLAGS+=$(patsubst%,-I%,$(subst:,如果我們的“$(VPATH)”值是“src:../headers”,那么-$(dir“/)之前的部分。如果沒有反斜杠,那么返回“/./“hacks示例:$(suffixsrc/foo.csrc-1.0/bar.chacks)返回值是“.c.c示例:$(basenamesrc/foo.csrc-1.0/bar.chacks)返回值是“src/foosrc-1.0/barhacks.bar.csrc/bargunguymadman回復(fù)于:2004-09-16四、foreachforeach函數(shù)和別的函數(shù)非常的不一樣。因?yàn)檫@個(gè)函數(shù)是用來做循環(huán)用的,Makefile中的中的foreach語句而構(gòu)建的。它的語法是:成的整個(gè)字符串(以空格分隔)將會(huì)是foreach函數(shù)的返回值。names:=abcfiles:=$(foreachd.o注意,foreach中的<var>;參數(shù)是一個(gè)臨時(shí)的局部變量,foreach函數(shù)執(zhí)行完后,參數(shù)<var>;的變量將不在作用,其作用域只在foreach函數(shù)當(dāng)中。五、if,那么六、callcall函數(shù)是唯一一個(gè)可以用來創(chuàng)建新的參數(shù)化的函數(shù)。你可以寫一個(gè)非常復(fù)雜的表達(dá)式,這$(call當(dāng)make執(zhí)行這個(gè)函數(shù)時(shí),<expression>;參數(shù)中的變量,如$(1),$(2),$(3)reverse= $(1)$(2)foo=$(callreverse,a,b)reverse $(2)foo=$(calla字符。Originorigin函數(shù)的undefined這些信息對(duì)于我們編寫Makefile是非常有用的,例如,假設(shè)我們有一個(gè)Makefile其包了一Make.defMake.def中定義了一個(gè)變量“bletch”,而我們的環(huán)境中也有一個(gè)如果來源于Make.def或是命令行等非環(huán)境的,那么我們就不重新定義它。于是,在我們的Makefile中,我們可以這樣寫:ifeq"$(originbletch)""environment"bletch=barf,gag,etc.shellShell的命令。它和反于是,我們可以用操作系統(tǒng)命令以及字符串處理命令awk,sed等等命令來生成一個(gè)變量,contents:=$(shellcatfiles:=$(shellechoShell程序來執(zhí)行命令,所以你要注意其運(yùn)行性能,如果你的Makefileshell函數(shù)執(zhí)行的次數(shù)比你想像的多得多。時(shí)信息,并且根據(jù)這些信息來決定,你是讓make繼續(xù)執(zhí)行,還是停止。$(error<text產(chǎn)生一個(gè)致命的錯(cuò)誤,<text...>;是錯(cuò)誤信息。注意,error函數(shù)不會(huì)在一被使用就會(huì)產(chǎn)$(errorerroris$(ERROR_001))ERR=$(errorfoundanerr:;ERROR_001error$(warning<texterrormakegunguymadman回復(fù)于:2004-09-16make是講述如何使用make命令的。返回2。make命令指定一個(gè)特殊名字的Makefile。要達(dá)到這個(gè)功能,我們要使名字是“hchen.mk”,那么,我們可以這樣來讓make來執(zhí)行這個(gè)文件:make–fmake的命令行是,你不只一次地使用了“-fmakefile將會(huì)被連在一起傳遞給make執(zhí)行。一般來說,makemakefile中的第一個(gè)目標(biāo),而其它目標(biāo)一般是由這個(gè)目標(biāo)連make,讓其完成你所指定的目標(biāo)。要達(dá)到這一目的很簡(jiǎn)單,需在make命令后直接跟目標(biāo)的名字就可以完成(如前面提到的“makeclean”形式)make的終極目標(biāo),也就是說,只要make可以找到其隱含規(guī)則推導(dǎo)sources=foo.cifneq($(MAKECMDGOALS),clean)include$(sources:.c=.d)“foo.d”和“bar.d”這兩個(gè)makefile。all:prog1prog2prog3makefile中有四個(gè)需要編譯的程序——“prog1”,prog2makefileUnix世界中,軟件能。我們可以參照這種規(guī)則來書寫我們的makefile中的目標(biāo)。我想,GNU搞出這些東西一定有其可取之處(UNIX下的程序文件一多時(shí)你就會(huì)發(fā)是執(zhí)行的序列。于是我們可以使用make命令的下述參數(shù):“-打印出來,但不執(zhí)行,這些參數(shù)對(duì)于我們調(diào)試makefile很有用處?!?這個(gè)參數(shù)的意思就是把目標(biāo)文件的時(shí)間更新,但不更改目標(biāo)文件。也就是說,make假“-“-WMake它產(chǎn)商的make的具體參數(shù)還是請(qǐng)參考各自的產(chǎn)品文檔。“-Cmakefile的目錄。如果有多個(gè)“-C”參數(shù),make的解釋是后面的路徑以前面的作于“make–C~hchen/test/prog“—ebu=a“-I“-j指同時(shí)運(yùn)行命令的個(gè)數(shù)。如果沒有這個(gè)參數(shù),make運(yùn)行命令時(shí)能運(yùn)行多少就運(yùn)行多少。如“-l“-omakefilemakefilemakefile,你可以使用“makeqp”命令。如果你想查看執(zhí)行makefile前的預(yù)設(shè)變量和規(guī)則,你可以使用“make–p–f/dev/nullmakefile文件的文件名和行號(hào),所以,用這個(gè)參數(shù)來調(diào)試你的makefile會(huì)是很有用的,特別是當(dāng)你的環(huán)境變量很復(fù)雜的時(shí)候。取消“-k”選項(xiàng)的作用。因?yàn)橛行r(shí)候,make的選項(xiàng)是從環(huán)境變量“MAKEFLAGS”中繼“-Wgunguymadman回復(fù)于:2004-09-16———在我們使用Makefile時(shí),有一些我們會(huì)經(jīng)常使用,而且使用頻率非常高的東西,比如,我C/C++的源程序?yàn)橹虚g目標(biāo)文件(Unix下是[.o]文件,Windows下是[.obj]文件。本“隱含規(guī)則”也就是一種慣例,make會(huì)按照這種“慣例”心照不喧地來運(yùn)行,那怕我們的Makefile中沒有書寫這樣的規(guī)則。例如,把[.c]文件編譯成[.o]文件這一規(guī)則,你根本就不用寫出來,make會(huì)自動(dòng)推導(dǎo)出這種規(guī)則,并生成我們需要的[.o]文件。們Makefile的兼容性。makemake可以自動(dòng)推導(dǎo)生成這個(gè)目make事先約定好的一些東西。例如,我們有下面的一個(gè)Makefile:foo:foo.occ–ofoofoo.obar.o$(CFLAGS)Makefilefoo.obar.o這兩目標(biāo)的規(guī)則和命make會(huì)在自己的“隱含規(guī)則”庫(kù)中尋找可以用的規(guī)則,如果找到,那么就會(huì)使用。如果找不到,那么就會(huì)報(bào)錯(cuò)。在上面的那個(gè)例子中,make調(diào)用的隱含規(guī)則是,把[.o]的目標(biāo)的依賴foo.o:bar.o:bar.ccc–cbar.c當(dāng)然,如果我們?yōu)閇.o]文件書寫了自己的規(guī)則,那么make就不會(huì)自動(dòng)推導(dǎo)并調(diào)用隱含規(guī)則,foo.o:foo.p(Pascal因?yàn)?,在隱含規(guī)則中,PascalC的規(guī)則之后,所以,makefoo.o的C的規(guī)則就不再尋找下一條規(guī)則了。如果你確實(shí)不希望任何隱含規(guī)則推導(dǎo),那么,你就則,那么,make就會(huì)在這些規(guī)則中尋找所需要規(guī)則和命令。當(dāng)然,我們也可以使用make在目標(biāo).SUFFIXES的依賴目標(biāo)),那么隱含規(guī)則就會(huì)生效。默認(rèn)的后綴列表是:.out,a,ln,o,c,.cc,C,.p,.f.F.ry,l,s.Smod,.sym.defh,.info,dvi,textexinfo,.texi,txinfo,wchweb,sh,elc,el。具體的細(xì)節(jié),我們會(huì)在后面講述?!?lt;n>;.o”的目標(biāo)的依賴目標(biāo)會(huì)自動(dòng)推導(dǎo)為“<n>;.c”,并且其生成命令是“$(CC)2、編譯C++程序的隱含規(guī)則。)$(CFLAGS)是“.C”)“<n>;.o”的目標(biāo)的依賴目標(biāo)會(huì)自動(dòng)推導(dǎo)為“<n>;.p”,并且其生成命令是“$(PC)$(G) “$(FC) “$(FC) “$(FC) “$(FC)–F$(FFLAGS)且其生成命令是:“$(M2C)$(M2FLAGS)$(MODFLAGS)$(ASFLAGS)一般是“l(fā)d,其生成命令是:“$(CC$(LDFLAGS<n>;.o$(LOADLIBES$(LDLIBS)”。這個(gè)規(guī)則對(duì)于只有一個(gè)源文件的工程有效,同時(shí)也對(duì)多個(gè)Object文件(由不同的源文件生成)的也有效。x:y.occ-cx.c-ox.occ-cy.c-occ-cz.c-occx.oy.oz.o-oxrm-fx.orm-f如果沒有一個(gè)源文件(x.c)和你的目標(biāo)名字(x)相關(guān)聯(lián),那么,n.y(acc$(YGS)“accn.l(Lex$(LALGS)n.l(Lex$()在隱含規(guī)則中的命令中,基本上都是使用了一些預(yù)先設(shè)置的變量。你可以在你的makefile例如,第一條隱含規(guī)則——編譯C程序的隱含規(guī)則的命令是“$(CC)–c把變量“$(CFLAGS)”重定義成“-g”,那么,隱含規(guī)則中的命令全部會(huì)以“gcc–c-gasccg++

co

)Fortran和Ratfor的編譯器和預(yù)處理程序。默認(rèn)命令是“f77SCCS文件中擴(kuò)展文件的程序。默認(rèn)命令是“getRatforlexPascal語言編譯程序。默認(rèn)命令是“pcyaccakeinfotextexi2dviweavecweavetanglectanglervSCCS“getld)RatforFortranYacc的[.y]文件先成[.c]C的編譯器生成。我們把這一系列的隱含規(guī)則叫文件,但有一個(gè)[.y]Yacc的隱含規(guī)則會(huì)被調(diào)用,生成[.c]C我們把這種[.c]的文件(或是目標(biāo),叫做中間目標(biāo)。不管怎么樣,make會(huì)努力自動(dòng)推導(dǎo)生這樣生成?怎么我的makefile發(fā)瘋了?目標(biāo)過程中,所產(chǎn)生的中間目標(biāo)文件會(huì)被以“rm-f”刪除。makefile指定成目標(biāo)或是依賴目標(biāo)的文件不能被當(dāng)作中介。然而,你可以明顯(如:.INTERMEDIATEmid:Make會(huì)優(yōu)化一些特殊的隱含規(guī)則,而不生成中間文件。如,從文件“foo.c”生成目標(biāo)程序這一動(dòng)作可以被一條“cc”的命令完成(cc–ofoofoo.c,于是優(yōu)化過的規(guī)則就不會(huì)生成gunguymadman回復(fù)于:2004-09-16的長(zhǎng)度至少為5。%.o:%.c; b.o",那么"%c"就是"a.cb.c"。一旦依賴目標(biāo)中的"%"模式被確定,那么,make會(huì)被要求去匹配當(dāng)前目錄下所有的文件名,一旦找到,make就會(huì)規(guī)則下的命令,所以,在模式規(guī)則中,目標(biāo)可能會(huì)是多個(gè)的,如果有模式匹配出多個(gè)目標(biāo),make就會(huì)產(chǎn)生所有的模式目標(biāo),此時(shí),make關(guān)心的是依賴的文件名%.o:$(CC)-c$(CFLAGS)$(CPPFLAGS)$<-o%.tab.c%.tab.h:bison-d這條規(guī)則告訴make把所有的[.y]文件都以"bison-d<n>;.y"執(zhí)行,然后生成"<n>;.tab.c"和僅當(dāng)目標(biāo)是函數(shù)庫(kù)文件中,表示規(guī)則中的目標(biāo)成員名。例如,如果一個(gè)目標(biāo)是下是[.a],Windows下是[.lib],那么,其值為空。式是",那么,"的值就是"。這個(gè)變量對(duì)于構(gòu)造有關(guān)聯(lián)的文件名是比較有e"eUema

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論