• <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>

            makefile info!

            Posted on 2008-06-28 00:05 T.S Liu 閱讀(2066) 評(píng)論(0)  編輯 收藏 引用 所屬分類: makefile
            Make工程管理器
            到此為止,讀者已了解了如何在Linux下使用編輯器編寫(xiě)代碼,如何使用Gcc把代碼編譯成可執(zhí)行文檔,還學(xué)習(xí)了如何使用Gdb來(lái)調(diào)試程式,那么,任何的工作看似已完成了,為什么還需要Make這個(gè)工程管理器呢?
            所謂工程管理器,顧名思義,是指管理較多的文檔的。讀者能夠試想一下,有一個(gè)上百個(gè)文檔的代碼構(gòu)成的項(xiàng)目,假如其中只有一個(gè)或少數(shù)幾個(gè)文檔進(jìn)行了修改,按照之前所學(xué)的Gcc編譯工具,就不得不把這任何的文檔重新編譯一遍,因?yàn)榫幾g器并不知道哪些文檔是最近更新的,而只知道需要包含這些文檔才能把源代碼編譯成可執(zhí)行文檔,于是,程式員就不能不再重新輸入數(shù)目如此龐大的文檔名以完成最后的編譯工作。
            但是,請(qǐng)讀者仔細(xì)回想一下本書(shū)在3.1.2節(jié)
            中所闡述的編譯過(guò)程,編譯過(guò)程是分為編譯、匯編、鏈接不同階段的,其中編譯階段僅檢查語(yǔ)法錯(cuò)誤連同函數(shù)和變量的聲明是否正確聲明了,在鏈接階段則主要完成
            是函數(shù)鏈接和全局變量的鏈接。因此,那些沒(méi)有改變的源代碼根本無(wú)需重新編譯,而只要把他們重新鏈接進(jìn)去就能夠了。所以,人們就希望有一個(gè)工程管理器能夠
            自動(dòng)識(shí)別更新了的文檔代碼,同時(shí)又無(wú)需重復(fù)輸入冗長(zhǎng)的命令行,這樣,Make工程管理器也就應(yīng)運(yùn)而生了。
            實(shí)際上,Make工程管理器也就是個(gè)“自動(dòng)編譯管理器”,這里的“自動(dòng)”是指他能夠根據(jù)文檔時(shí)間戳自動(dòng)發(fā)現(xiàn)更新過(guò)的文檔而減少編譯的工作量,同時(shí),他通過(guò)讀入Makefile文檔的內(nèi)容來(lái)執(zhí)行大量的編譯工作。用戶只需編寫(xiě)一次簡(jiǎn)單的編譯語(yǔ)句就能夠了。他大大提高了實(shí)際項(xiàng)目的工作效率,而且?guī)缀跞魏蜭inux下的項(xiàng)目編程均會(huì)涉及到他,希望讀者能夠認(rèn)真學(xué)習(xí)本節(jié)內(nèi)容。
            3.6.1  Makefile基本結(jié)構(gòu)
            Makefile是Make讀入的惟一配置文檔,因此本節(jié)的內(nèi)容實(shí)際就是講述Makefile的編寫(xiě)規(guī)則。在一個(gè)Makefile中通常包含如下內(nèi)容:
            ·  需要由make工具創(chuàng)建的目標(biāo)體(target),通常是目標(biāo)文檔或可執(zhí)行文檔;
            ·  要?jiǎng)?chuàng)建的目標(biāo)體所依賴的文檔(dependency_file);
            ·  創(chuàng)建每個(gè)目標(biāo)體時(shí)需要運(yùn)行的命令(command)。
            他的格式為:

            target: dependency_files
                   command

            例如,有兩個(gè)文檔分別為hello.c和hello.h,創(chuàng)建的目標(biāo)體為hello.o,執(zhí)行的命令為gcc編譯指令:gcc –c hello.c,那么,對(duì)應(yīng)的Makefile就能夠?qū)憺椋?br>
            #The simplest example
            hello.o: hello.c hello.h
                   gcc –c hello.c –o hello.o

            接著就能夠使用make了。使用make的格式為:make target,這樣make就會(huì)自動(dòng)讀入Makefile(也能夠是首字母小寫(xiě)makefile)并執(zhí)行對(duì)應(yīng)target的command語(yǔ)句,并會(huì)找到相應(yīng)的依賴文檔。如下所示:

            [root@localhost makefile]# make hello.o
            gcc –c hello.c –o hello.o
            [root@localhost makefile]# ls
            hello.c  hello.h  hello.o  Makefile

            能夠看到,Makefile執(zhí)行了“hello.o”對(duì)應(yīng)的命令語(yǔ)句,并生成了“hello.o”目標(biāo)體。


            注意
            在Makefile中的每一個(gè)command前必須有“Tab”符,否則在運(yùn)行make命令時(shí)會(huì)出錯(cuò)。
            3.6.2  Makefile變量
            上面示例的Makefile在實(shí)際中是幾乎不存在的,因?yàn)樗^(guò)于簡(jiǎn)單,僅包含兩個(gè)文檔和一個(gè)命令,在這種情況下完全不必要編寫(xiě)Makefile而只需在Shell中直接輸入即可,在實(shí)際中使用的Makefile往往是包含很多的文檔和命令的,這也是Makefile產(chǎn)生的原因。下面就可給出稍微復(fù)雜一些的Makefile進(jìn)行講解:

            sunq:kang.o yul.o
            Gcc kang.o bar.o -o myprog
            kang.o : kang.c kang.h head.h
            Gcc –Wall –O -g –c kang.c -o kang.o
            yul.o : bar.c head.h
            Gcc - Wall –O -g –c yul.c -o yul.o

            在這個(gè)Makefile中有三個(gè)目標(biāo)體(target),分別為sunq、kang.o和yul.o,其中第一個(gè)目標(biāo)體的依賴文檔就是后兩個(gè)目標(biāo)體。假如用戶使用命令“make sunq”,則make管理器就是找到sunq目標(biāo)體開(kāi)始執(zhí)行。
            這時(shí),make會(huì)自動(dòng)檢查相關(guān)文檔的時(shí)間戳。首先,在檢查“kang.o”、“yul.o”和“sunq”三個(gè)文檔的時(shí)間戳之前,他會(huì)向下查找那些把“kang.o”或“yul.o”做為目標(biāo)文檔的時(shí)間戳。比如,“kang.o”的依賴文檔為:“kang.c”、“kang.h”、“head.h”。假如這些文檔中任何一個(gè)的時(shí)間戳比“kang.o”新,則命令“gcc –Wall –O -g –c kang.c -o kang.o”將會(huì)執(zhí)行,從而更新文檔“kang.o”。在更新完“kang.o”或“yul.o”之后,make會(huì)檢查最初的“kang.o”、“yul.o”和“sunq”三個(gè)文檔,只要文檔“kang.o”或“yul.o”中的任比文檔時(shí)間戳比“sunq”新,則第二行命令就會(huì)被執(zhí)行。這樣,make就完成了自動(dòng)檢查時(shí)間戳的工作,開(kāi)始執(zhí)行編譯工作。這也就是Make工作的基本流程。
            接下來(lái),為了進(jìn)一步簡(jiǎn)化編輯和維護(hù)Makefile,make允許在Makefile中創(chuàng)建和使用變量。變量是在Makefile中定義的名字,用來(lái)代替一個(gè)文本字符串,該文本字符串稱為該變量的值。在具體需要下,這些值能夠代替目標(biāo)體、依賴文檔、命令連同makefile文檔中其他部分。在Makefile中的變量定義有兩種方式:一種是遞歸展開(kāi)方式,另一種是簡(jiǎn)單方式。
            遞歸展開(kāi)方式定義的變量是在引用在該變量時(shí)進(jìn)行替換的,即假如該變量包含了對(duì)其他變量的應(yīng)用,則在引用該變量時(shí)一次性將內(nèi)嵌的變量全部展開(kāi),雖然這種類型的變量能夠很好地完成用戶的指令,但是他也有嚴(yán)重的缺點(diǎn),如不能在變量后追加內(nèi)容(因?yàn)檎Z(yǔ)句:CFLAGS = $(CFLAGS) -O在變量擴(kuò)展過(guò)程中可能導(dǎo)致無(wú)窮循環(huán))。
            為了避免上述問(wèn)題,簡(jiǎn)單擴(kuò)展型變量的值在定義處展開(kāi),并且只展開(kāi)一次,因此他不包含任何對(duì)其他變量的引用,從而消除變量的嵌套引用。
            遞歸展開(kāi)方式的定義格式為:VAR=var
            簡(jiǎn)單擴(kuò)展方式的定義格式為:VAR:=var
            Make中的變量使用均使用格式為:$(VAR)


            注意
            變量名是不包括“:”、“#”、“=”結(jié)尾空格的任何字符串。同時(shí),變量名中包含字母、數(shù)字連同下劃線以外的情況應(yīng)盡量避免,因?yàn)樗麄兛赡茉趯?lái)被賦予特別的含義。
            變量名是大小寫(xiě)敏感的,例如變量名“foo”、“FOO”、和“Foo”代表不同的變量。
            推薦在makefile內(nèi)部使用小寫(xiě)字母作為變量名,預(yù)留大寫(xiě)字母作為控制隱含規(guī)則參數(shù)或用戶重載命令選項(xiàng)參數(shù)的變量名。

            下面給出了上例中用變量替換修改后的Makefile,這里用OBJS代替kang.o和yul.o,用CC代替Gcc,用CFLAGS代替“-Wall -O –g”。這樣在以后修改時(shí),就能夠只修改變量定義,而無(wú)需修改下面的定義實(shí)體,從而大大簡(jiǎn)化了Makefile維護(hù)的工作量。
            經(jīng)變量替換后的Makefile如下所示:

            OBJS = kang.o yul.o
            CC = Gcc
            CFLAGS = -Wall -O -g
            sunq : $(OBJS)
                   $(CC) $(OBJS) -o sunq
            kang.o : kang.c kang.h
                   $(CC) $(CFLAGS) -c kang.c -o kang.o
            yul.o : yul.c yul.h
                   $(CC) $(CFLAGS) -c yul.c -o yul.o

            能夠看到,此處變量是以遞歸展開(kāi)方式定義的。
            Makefile中的變量分為用戶自定義變量、預(yù)定義變量、自動(dòng)變量及環(huán)境變量。如上例中的OBJS就是用戶自定義變量,自定義變量的值由用戶自行設(shè)定,而預(yù)定義變量和自動(dòng)變量為通常在Makefile都會(huì)出現(xiàn)的變量,其中部分有默認(rèn)值,也就是常見(jiàn)的設(shè)定值,當(dāng)然用戶能夠?qū)ζ溥M(jìn)行修改。
            預(yù)定義變量包含了常見(jiàn)編譯器、匯編器的名稱及其編譯選項(xiàng)。下表3.14列出了Makefile中常見(jiàn)預(yù)定義變量及其部分默認(rèn)值。
            表3.14                                                  Makefile中常見(jiàn)預(yù)定義變量
            命 令 格 式
            含    義
            AR
            庫(kù)文檔維護(hù)程式的名稱,默認(rèn)值為ar
            AS
            匯編程式的名稱,默認(rèn)值為as
            CC
            C編譯器的名稱,默認(rèn)值為cc
            CPP
            C預(yù)編譯器的名稱,默認(rèn)值為$(CC) –E
            CXX
            C++編譯器的名稱,默認(rèn)值為g++
            FC
            FORTRAN編譯器的名稱,默認(rèn)值為f77
            RM
            文檔刪除程式的名稱,默認(rèn)值為rm –f
            ARFLAGS
            庫(kù)文檔維護(hù)程式的選項(xiàng),無(wú)默認(rèn)值
            ASFLAGS
            匯編程式的選項(xiàng),無(wú)默認(rèn)值
            CFLAGS
            C編譯器的選項(xiàng),無(wú)默認(rèn)值
            CPPFLAGS
            C預(yù)編譯的選項(xiàng),無(wú)默認(rèn)值
            CXXFLAGS
            C++編譯器的選項(xiàng),無(wú)默認(rèn)值
            FFLAGS
            FORTRAN編譯器的選項(xiàng),無(wú)默認(rèn)值

            能夠看出,上例中的CC和CFLAGS是預(yù)定義變量,其中由于CC沒(méi)有采用默認(rèn)值,因此,需要把“CC=Gcc”明確列出來(lái)。
            由于常見(jiàn)的Gcc編譯語(yǔ)句中通常包含了目標(biāo)文檔和依賴文檔,而這些文檔在Makefile文檔中目標(biāo)體的一行已有所體現(xiàn),因此,為了進(jìn)一步簡(jiǎn)化Makefile的編寫(xiě),就引入了自動(dòng)變量。自動(dòng)變量通常能夠代表編譯語(yǔ)句中出現(xiàn)目標(biāo)文檔和依賴文檔等,并且具備本地含義(即下一語(yǔ)句中出現(xiàn)的相同變量代表的是下一語(yǔ)句的目標(biāo)文檔和依賴文檔)。下表3.15列出了Makefile中常見(jiàn)自動(dòng)變量。
            表3.15                                                    Makefile中常見(jiàn)自動(dòng)變量
            命令格式
            含    義
            $*
            不包含擴(kuò)展名的目標(biāo)文檔名稱
            $+
            任何的依賴文檔,以空格分開(kāi),并以出現(xiàn)的先后為序,可能包含重復(fù)的依賴文檔
            $
            第一個(gè)依賴文檔的名稱
            $?
            任何時(shí)間戳比目標(biāo)文檔晚的依賴文檔,并以空格分開(kāi)
            命令格式
            含    義
            $@
            目標(biāo)文檔的完整名稱
            $^
            任何不重復(fù)的依賴文檔,以空格分開(kāi)
            $%
            假如目標(biāo)是歸檔成員,則該變量表示目標(biāo)的歸檔成員名稱

            自動(dòng)變量的書(shū)寫(xiě)比較難記,但是在熟練了之后會(huì)很的方便,請(qǐng)讀者結(jié)合下例中的自動(dòng)變量改寫(xiě)的Makefile進(jìn)行記憶。

            OBJS = kang.o yul.o
            CC = Gcc
            CFLAGS = -Wall -O -g
            sunq : $(OBJS)
                  $(CC) $^ -o $@
            kang.o : kang.c kang.h
                  $(CC) $(CFLAGS) -c $
            yul.o : yul.c yul.h
                  $(CC) $(CFLAGS) -c $

            另外,在Makefile中還能夠使用環(huán)境變量。使用環(huán)境變量的方法相對(duì)比較簡(jiǎn)單,make在啟動(dòng)時(shí)會(huì)自動(dòng)讀取系統(tǒng)當(dāng)前已定義了的環(huán)境變量,并且會(huì)創(chuàng)建和之具備相同名稱和數(shù)值的變量。但是,假如用戶在Makefile中定義了相同名稱的變量,那么用戶自定義變量將會(huì)覆蓋同名的環(huán)境變量。
            3.6.3  Makefile規(guī)則
            Makefile的規(guī)則是Make進(jìn)行處理的依據(jù),他包括了目標(biāo)體、依賴文檔及其之間的命令語(yǔ)句。一般的,Makefile中的一條語(yǔ)句就是個(gè)規(guī)則。在上面的例子中,都顯示地指出了Makefile中的規(guī)則關(guān)系,如“$(CC) $(CFLAGS) -c $”,但為了簡(jiǎn)化Makefile的編寫(xiě),make還定義了隱式規(guī)則和模式規(guī)則,下面就分別對(duì)其進(jìn)行講解。
            1.隱式規(guī)則
            隱含規(guī)則能夠告訴make怎樣使用傳統(tǒng)的技術(shù)完成任務(wù),這樣,當(dāng)用戶使用他們時(shí)就不必周詳指定編譯的具體細(xì)節(jié),而只需把目標(biāo)文檔列出即可。Make會(huì)自動(dòng)搜索隱式規(guī)則目錄來(lái)確定如何生成目標(biāo)文檔。如上例就能夠?qū)懗桑?br>
            OBJS = kang.o yul.o
            CC = Gcc
            CFLAGS = -Wall -O -g
            sunq : $(OBJS)
                  $(CC) $^ -o $@

            為什么能夠省略后兩句呢?因?yàn)镸ake的隱式規(guī)則指出:任何“.o”文檔都可自動(dòng)由“.c”文檔使用命令“$(CC) $(CPPFLAGS) $(CFLAGS) -c file.c –o file.o”生成。這樣“kang.o”和“yul.o”就會(huì)分別調(diào)用“$(CC) $(CFLAGS) -c kang.c -o kang.o”和“$(CC) $(CFLAGS) -c yul.c -o yul.o”生成。


            注意
            在隱式規(guī)則只能查找到相同文檔名的不同后綴名文檔,如”kang.o”文檔必須由”kang.c”文檔生成。

            下表3.16給出了常見(jiàn)的隱式規(guī)則目錄:
            表3.16                                                Makefile中常見(jiàn)隱式規(guī)則目錄
            對(duì)應(yīng)語(yǔ)言后綴名
            規(guī)    則
            C編譯:.c變?yōu)?o
            $(CC) –c $(CPPFLAGS) $(CFLAGS)
            C++編譯:.cc或.C變?yōu)?o
            $(CXX) -c $(CPPFLAGS) $(CXXFLAGS)
            Pascal編譯:.p變?yōu)?o
            $(PC) -c $(PFLAGS)
            Fortran編譯:.r變?yōu)?o
            $(FC) -c $(FFLAGS)
            2.模式規(guī)則
            模式規(guī)則是用來(lái)定義相同處理規(guī)則的多個(gè)文檔的。他不同于隱式規(guī)則,隱式規(guī)則僅僅能夠用make默認(rèn)的變量來(lái)進(jìn)行操作,而模式規(guī)則還能引入用戶自定義變量,為多個(gè)文檔建立相同的規(guī)則,從而簡(jiǎn)化Makefile的編寫(xiě)。
            模式規(guī)則的格式類似于普通規(guī)則,這個(gè)規(guī)則中的相關(guān)文檔前必須用“%”標(biāo)明。使用模式規(guī)則修改后的Makefile的編寫(xiě)如下:

            OBJS = kang.o yul.o
            CC = Gcc
            CFLAGS = -Wall -O -g
            sunq : $(OBJS)
                  $(CC) $^ -o $@
            %.o : %.c
                  $(CC) $(CFLAGS) -c $

            3.6.4  Make使用
            使用make管理器很簡(jiǎn)單,只需在make命令的后面鍵入目標(biāo)名即可建立指定的目標(biāo),假如直接運(yùn)行make,則建立Makefile中的第一個(gè)目標(biāo)。
            此外make更有豐富的命令行選項(xiàng),能夠完成各種不同的功能。下表3.17列出了常用的make命令行選項(xiàng)。
            表3.17                                                        make的命令行選項(xiàng)
            命令格式
            含    義
            -C dir
            讀入指定目錄下的Makefile
            -f file
            讀入當(dāng)前目錄下的file文檔作為Makefile
            命令格式
            含    義
            -i
            忽略任何的命令執(zhí)行錯(cuò)誤
            -I dir
            指定被包含的Makefile所在目錄
            -n
            只打印要執(zhí)行的命令,但不執(zhí)行這些命令
            -p
            顯示make變量數(shù)據(jù)庫(kù)和隱含規(guī)則
            -s
            在執(zhí)行命令時(shí)不顯示命令
            -w
            假如make在執(zhí)行過(guò)程中改變目錄,則打印當(dāng)前目錄名
            3.7  使用autotools
            在上一小節(jié),讀者已了解到了make項(xiàng)目管理器的強(qiáng)大功能。的確,Makefile能夠幫助make完成他的使命,但要承認(rèn)的是,編寫(xiě)Makefile確實(shí)不是一件輕松的事,尤其對(duì)于一個(gè)較大的項(xiàng)目而言更是如此。那么,有沒(méi)有一種輕松的手段生成Makefile而同時(shí)又能讓用戶享受make的優(yōu)越性呢?本節(jié)要講的autotools系列工具正是為此而設(shè)的,他只需用戶輸入簡(jiǎn)單的目標(biāo)文檔、依賴文檔、文檔目錄等就能夠輕松地生成Makefile了,這無(wú)疑是廣大用戶的所希望的。另外,這些工具還能夠完成系統(tǒng)配置信息的收集,從而能夠方便地處理各種移植性的問(wèn)題。也正是基于此,現(xiàn)在Linux上的軟件研發(fā)一般都用autotools來(lái)制作Makefile,讀者在后面的講述中就會(huì)了解到。
            3.7.1  autotools使用流程
            正如前面所言,autotools是系列工具,讀者首先要確認(rèn)系統(tǒng)是否裝了以下工具(能夠用which命令進(jìn)行查看)。
            ·  aclocal
            ·  autoscan
            ·  autoconf
            ·  autoheader
            ·  automake
            使用autotools主要就是利用各個(gè)工具的腳本文檔以生成最后的Makefile。其總體流程是這樣的:
            ·  使用aclocal生成一個(gè)“aclocal.m4”文檔,該文檔主要處理本地的宏定義;
            ·  改寫(xiě)“configure.scan”文檔,并將其重命名為“configure.in”,并使用autoconf文檔生成configure文檔。
            接下來(lái),筆者將通過(guò)一個(gè)簡(jiǎn)單的hello.c例子帶領(lǐng)讀者熟悉autotools生成makefile的過(guò)程,由于在這過(guò)程中有涉及到較多的腳本文檔,為了更清楚地了解相互之間的關(guān)系,強(qiáng)烈建議讀者實(shí)際動(dòng)手操作以體會(huì)其整個(gè)過(guò)程。
            1.a(chǎn)utoscan
            他會(huì)在給定目錄及其子目錄樹(shù)中檢查源文檔,若沒(méi)有給出目錄,就在當(dāng)前目錄及其子目錄樹(shù)中進(jìn)行檢查。他會(huì)搜索源文檔以尋找一般的移植性問(wèn)題并創(chuàng)建一個(gè)文檔“configure.scan”,該文檔就是接下來(lái)autoconf要用到的“configure.in”原型。如下所示:

            [root@localhost automake]# autoscan
            autom4te: configure.ac: no such file or directory
            autoscan: /usr/bin/autom4te failed with exit status: 1
            [root@localhost automake]# ls
            autoscan.log  configure.scan  hello.c

            如上所示,autoscan首先會(huì)嘗試去讀入“configure.ac”(同configure.in的配置文檔)文檔,此時(shí)還沒(méi)有創(chuàng)建該配置文檔,于是他會(huì)自動(dòng)生成一個(gè)“configure.in”的原型文檔“configure.scan”。
            2.a(chǎn)utoconf
            configure.in是autoconf的腳本配置文檔,他的原型文檔“configure.scan”如下所示:

            #                                               -*- Autoconf -*-
            # Process this file with autoconf to produce a configure script.
            AC_PREREQ(2.59)
            #The next one is modified by sunq
            #AC_INIT(FULL-PACKAGE-NAME,VERSION,BUG-REPORT-ADDRESS)
            AC_INIT(hello,1.0)
            # The next one is added by sunq
            AM_INIT_AUTOMAKE(hello,1.0)
            AC_CONFIG_SRCDIR([hello.c])
            AC_CONFIG_HEADER([config.h])
            # Checks for programs.
            AC_PROG_CC
            # Checks for libraries.
            # Checks for header files.
            # Checks for typedefs, structures, and compiler characteristics.
            # Checks for library functions.
            AC_CONFIG_FILES([Makefile])
            AC_OUTPUT

            下面對(duì)這個(gè)腳本文檔進(jìn)行解釋:
            ·  以“#”號(hào)開(kāi)始的行為注釋。
            ·  AC_PREREQ宏聲明本文檔需要的autoconf版本,如本例使用的版本2.59。
            · AC_INIT宏用來(lái)定義軟件的名稱和版本等信息,在本例中省略了BUG-REPORT-ADDRESS,一般為作者的e-mail。
            ·  AM_INIT_AUTOMAKE是筆者另加的,他是automake所必備的宏,也同前面相同,PACKAGE是所要產(chǎn)生軟件套件的名稱,VERSION是版本編號(hào)。
            ·  AC_CONFIG_SRCDIR宏用來(lái)偵測(cè)所指定的源碼文檔是否存在,來(lái)確定源碼目錄的有
            效性。在此處為當(dāng)前目錄下的hello.c。
            ·  AC_CONFIG_HEADER宏用于生成config.h文檔,以便autoheader使用。
            ·  AC_CONFIG_FILES宏用于生成相應(yīng)的Makefile文檔。
            ·  中間的注釋間能夠添加分別用戶測(cè)試程式、測(cè)試函數(shù)庫(kù)、測(cè)試頭文檔等宏定義。
            接下來(lái)首先運(yùn)行aclocal,生成一個(gè)“aclocal.m4”文檔,該文檔主要處理本地的宏定義。如下所示:

            [root@localhost automake]# aclocal

            再接著運(yùn)行autoconf,生成“configure”可執(zhí)行文檔。如下所示:

            [root@localhost automake]# autoconf
            [root@localhost automake]# ls
            aclocal.m4  autom4te.cache  autoscan.log  configure  configure.in  hello.c
            3.a(chǎn)utoheader
            接著使用autoheader命令,他負(fù)責(zé)生成config.h.in文檔。該工具通常會(huì)從“acconfig.h”文檔中復(fù)制用戶附加的符號(hào)定義,因此此處沒(méi)有附加符號(hào)定義,所以無(wú)需創(chuàng)建“acconfig.h”文檔。如下所示:

            [root@localhost automake]# autoheader
            4.a(chǎn)utomake
            這一步是創(chuàng)建Makefile很重要的一步,automake要用的腳本配置文檔是Makefile.am,用戶需要自己創(chuàng)建相應(yīng)的文檔。之后,automake工具轉(zhuǎn)換成Makefile.in。在該例中,筆者創(chuàng)建的文檔為Makefile.am如下所示:

            AUTOMAKE_OPTIONS=foreign
            bin_PROGRAMS= hello
            hello_SOURCES= hello.c

            下面對(duì)該腳本文檔的對(duì)應(yīng)項(xiàng)進(jìn)行解釋。
            ·  其中的AUTOMAKE_OPTIONS為配置automake的選項(xiàng)。由于GNU(在第1章中已有所介紹)對(duì)自己發(fā)布的軟件有嚴(yán)格的規(guī)范,比如必須附帶許可證聲明文檔COPYING等,否則automake執(zhí)行時(shí)會(huì)報(bào)錯(cuò)。automake提供了三種軟件等級(jí):foreign、gnu和gnits,讓用戶選擇采用,默認(rèn)等級(jí)為gnu。在本例使用foreign等級(jí),他只檢測(cè)必須的文檔。
            ·  bin_PROGRAMS定義要產(chǎn)生的執(zhí)行文檔名。假如要產(chǎn)生多個(gè)執(zhí)行文檔,每個(gè)文檔名用空格隔開(kāi)。
            ·  hello_SOURCES定義“hello”這個(gè)執(zhí)行程式所需要的原始文檔。假如”hello”這個(gè)程式是由多個(gè)原始文檔所產(chǎn)生的,則必須把他所用到的任何原始文檔都列出來(lái),并用空格隔開(kāi)。例如:若目標(biāo)體“hello”需要“hello.c”、“sunq.c”、“hello.h”三個(gè)依賴文檔,則定義hello_SOURCES=hello.c sunq.c hello.h。要注意的是,假如要定義多個(gè)執(zhí)行文檔,則對(duì)每個(gè)執(zhí)行程式都要定義相應(yīng)的file_SOURCES。
            接下來(lái)能夠使用automake對(duì)其生成“configure.in”文檔,在這里使用選項(xiàng)“—adding-missing”能夠讓automake自動(dòng)添加有一些必需的腳本文檔。如下所示:

            [root@localhost automake]# automake --add-missing
            configure.in: installing './install-sh'
            configure.in: installing './missing'
            Makefile.am: installing 'depcomp'
            [root@localhost automake]# ls
            aclocal.m4      autoscan.log  configure.in  hello.c     Makefile.am  missing
            autom4te.cache  configure     depcomp    install-sh  Makefile.in  config.h.in

            能夠看到,在automake之后就能夠生成configure.in文檔。
            5.運(yùn)行configure
            在這一步中,通過(guò)運(yùn)行自動(dòng)配置配置文檔configure,把Makefile.in變成了最終的Makefile。如下所示:

            [root@localhost automake]# ./configure
            checking for a BSD-compatible install... /usr/bin/install -c
            checking whether build enVironment is sane... yes
            checking for gawk... gawk
            checking whether make sets $(MAKE)... yes
            checking for Gcc... Gcc
            checking for C compiler default output file name... a.out
            checking whether the C compiler works... yes
            checking whether we are cross compiling... no
            checking for suffix of executables...
            checking for suffix of object files... o
            checking whether we are using the GNU C compiler... yes
            checking whether Gcc accepts -g... yes
            checking for Gcc option to accept ANSI C... none needed
            checking for style of include used by make... GNU
            checking dependency style of Gcc... Gcc3
            configure: creating ./config.status
            config.status: creating Makefile
            config.status: executing depfiles commands
            能夠看到,在運(yùn)行configure時(shí)收集了系統(tǒng)的信息,用戶能夠在configure命令中對(duì)其進(jìn)行方便地配置。在./configure的自定義參數(shù)有兩種,一種是開(kāi)關(guān)式(--enable-XXX或--disable-XXX),另一種是開(kāi)放式,即后面要填入一串字符(--with-XXX=yyyy)參數(shù)。讀者能夠自行嘗試其使用方法。另外,讀者能夠查看同一目錄下的”config.log”文檔,以方便調(diào)試之用。
            到此為止,makefile就能夠自動(dòng)生成了。回憶整個(gè)步驟,用戶不再需要定制不同的規(guī)則,而只需要輸入簡(jiǎn)單的文檔及目錄名即可,這樣就大大方便了用戶的使用。下面的圖3.9總結(jié)了上述過(guò)程:

            圖3.9  autotools生成Makefile流程圖
            3.7.2  使用autotools所生成的Makefile
            autotools生成的Makefile除具備普通的編譯功能外,還具備以下主要功能(感興趣的讀者能夠查看這個(gè)簡(jiǎn)單的hello.c程式的makefile):
            1.make
            鍵入make默認(rèn)執(zhí)行”make all”命令,即目標(biāo)體為all,其執(zhí)行情況如下所示:

            [root@localhost automake]# make
            if Gcc
            -DPACKAGE_NAME=\"\" -DPACKAGE_TARNAME=\"\" -DPACKAGE_VERSION=\"\"
            -DPACKAGE_STRING=\"\" -DPACKAGE_BUGREPORT=\"\" -DPACKAGE=\"hello\"
            -DVERSION=\"1.0\"  -I. -I.     -g -O2 -MT hello.o -MD -MP -MF
            ".deps/hello.Tpo" -c -o hello.o hello.c; \
            then mv -f ".deps/hello.Tpo" ".deps/hello.Po"; else rm -f ".deps/hello.Tpo"; exit 1; fi
            Gcc  -g -O2   -o hello  hello.o
            此時(shí)在本目錄下就生成了可執(zhí)行文檔“hello”,運(yùn)行“./hello”能出現(xiàn)正常結(jié)果,如下所示:

            [root@localhost automake]# ./hello
            Hello!Autoconf!
            2.make install
            此時(shí),會(huì)把該程式安裝到系統(tǒng)目錄中去,如下所示:

            [root@localhost automake]# make install
            if Gcc
            -DPACKAGE_NAME=\"\" -DPACKAGE_TARNAME=\"\" -DPACKAGE_VERSION=\"\"
            -DPACKAGE_STRING=\"\" -DPACKAGE_BUGREPORT=\"\" -DPACKAGE=\"hello\"
            -DVERSION=\"1.0\"  -I. -I.     -g -O2 -MT hello.o -MD -MP -MF
            ".deps/hello.Tpo" -c -o hello.o hello.c; \
            then mv -f ".deps/hello.Tpo" ".deps/hello.Po"; else rm -f ".deps/hello.Tpo"; exit 1; fi
            Gcc  -g -O2   -o hello  hello.o
            make[1]: Entering directory '/root/workplace/automake'
            test -z "/usr/local/bin" || mkdir -p -- "/usr/local/bin"
              /usr/bin/install -c 'hello' '/usr/local/bin/hello'
            make[1]: Nothing to be done for 'install-data-am'.
            make[1]: LeaVing directory '/root/workplace/automake'

            此時(shí),若直接運(yùn)行hello,也能出現(xiàn)正確結(jié)果,如下所示:

            [root@localhost automake]# hello
            Hello!Autoconf!
            3.make clean
            此時(shí),make會(huì)清除之前所編譯的可執(zhí)行文檔及目標(biāo)文檔(object file, *.o),如下所示:

            [root@localhost automake]# make clean
            test -z "hello" || rm -f hello
            rm -f *.o
            4.make dist
            此時(shí),make將程式和相關(guān)的文檔打包為一個(gè)壓縮文檔以供發(fā)布,如下所示:

            [root@localhost automake]# make dist
            [root@localhost automake]# ls hello-1.0-tar.gz
            hello-1.0-tar.gz

            可見(jiàn)該命令生成了一個(gè)hello-1.0-tar.gz的壓縮文檔。
            由上面的講述讀者不難看出,autotools確實(shí)是軟件維護(hù)和發(fā)布的必備工具,也鑒于此,如今GUN的軟件一般都是由automake來(lái)制作的。


            想一想
            對(duì)于automake制作的這類軟件,應(yīng)如何安裝呢?
            3.8.3  編寫(xiě)包含多文檔的Makefile
            1.實(shí)驗(yàn)?zāi)康?br>通過(guò)對(duì)包含多文檔的Makefile的編寫(xiě),熟悉各種形式的Makefile,并且進(jìn)一步加深對(duì)Makefile中用戶自定義變量、自動(dòng)變量及預(yù)定義變量的理解。
            2.實(shí)驗(yàn)過(guò)程
            (1)用Vi在同一目錄下編輯兩個(gè)簡(jiǎn)單的Hello程式,如下所示:

            #hello.c
            #include "hello.h"
            int main()
            {
                   printf("Hello everyone!\n");
            }
            #hello.h
            #include

            (2)仍在同一目錄下用Vi編輯Makefile,且不使用變量替換,用一個(gè)目標(biāo)體實(shí)現(xiàn)(即直接將hello.c和hello.h編譯成hello目標(biāo)體)。然后用make驗(yàn)證所編寫(xiě)的Makefile是否正確。
            (3)將上述Makefile使用變量替換實(shí)現(xiàn)。同樣用make驗(yàn)證所編寫(xiě)的Makefile是否正確
            (4)用編輯另一Makefile,取名為Makefile1,不使用變量替換,但用兩個(gè)目標(biāo)體實(shí)現(xiàn)(也就是首先將hello.c和hello.h編譯為hello.o,再將hello.o編譯為hello),再用make的”-f”選項(xiàng)驗(yàn)證這個(gè)Makefile1的正確性。
            (5)將上述Makefile1使用變量替換實(shí)現(xiàn)。
            3.實(shí)驗(yàn)步驟
            (1)用Vi打開(kāi)上述兩個(gè)代碼文檔“hello.c”和“hello.h”。
            (2)在shell命令行中用Gcc嘗試編譯,使用命令:”Gcc hello.c –o hello”,并運(yùn)行hello可執(zhí)行文檔查看結(jié)果。
            (3)刪除此次編譯的可執(zhí)行文檔:rm hello。
            (4)用Vi編輯Makefile,如下所示:

            hello:hello.c hello.h
                   Gcc hello.c -o hello

            (5)退出保存,在shell中鍵入:make,查看結(jié)果。
            (6)再次用Vi打開(kāi)Makefile,用變量進(jìn)行替換,如下所示:

            OBJS :=hello.o
            CC :=Gcc
            hello:$(OBJS)
                   $(CC) $^ -o $@

            (7)退出保存,在shell中鍵入:make,查看結(jié)果。
            (8)用Vi編輯Makefile1,如下所示:

            hello:hello.o
                   Gcc hello.o -o hello
            hello.o:hello.c hello.h
                   Gcc -c hello.c -o hello.o

            (9)退出保存,在shell中鍵入:make -f Makefile1,查看結(jié)果。
            (10)再次用Vi編輯Makefile1,如下所示:

            OBJS1 :=hello.o
            OBJS2 :=hello.c hello.h
            CC :=Gcc
            hello:$(OBJS1)
                   $(CC) $^ -o $@
            $(OBJS1):$(OBJS2)
                   $(CC) -c $

            在這里請(qǐng)注意區(qū)別“$^”和“$”。
            (11)退出保存,在shell中鍵入:make -f Makefile1,查看結(jié)果
            4.實(shí)驗(yàn)結(jié)果
            各種不同形式的makefile都能完成其正確的功能。
            3.8.4  使用autotools生成包含多文檔的Makefile
            1.實(shí)驗(yàn)?zāi)康?br>通過(guò)使用autotools生成包含多文檔的Makefile,進(jìn)一步掌控autotools的正確使用方法。同時(shí),掌控Linux下安裝軟件的常用方法。
            2.實(shí)驗(yàn)過(guò)程
            (1)在原目錄下新建文檔夾auto。
            (2)利用上例的兩個(gè)代碼文檔“hello.c”和“hello.h”,并將他們復(fù)制到該目錄下。
            (3)使用autoscan生成configure.scan。
            (4)編輯configure.scan,修改相關(guān)內(nèi)容,并將其重命名為configure.in。
            (5)使用aclocal生成aclocal.m4。
            (6)使用autoconf生成configure。
            (7)使用autoheader生成config.in.h。
            (8)編輯Makefile.am。
            (9)使用automake生成Makefile.in。
            (10)使用configure生成Makefile。
            (11)使用make生成hello可執(zhí)行文檔,并在當(dāng)前目錄下運(yùn)行hello查看結(jié)果。
            (12)使用make install將hello安裝到系統(tǒng)目錄下,并運(yùn)行,查看結(jié)果。
            (13)使用make dist生成hello壓縮包。
            (14)解壓hello壓縮包。
            (15)進(jìn)入解壓目錄。
            (16)在該目錄下安裝hello軟件。
            3.實(shí)驗(yàn)步驟
            (1)mkdir ./auto。
            (2)cp hello.* ./auto(假定原先在“hello.c”文檔目錄下)。
            (3)命令:autoscan。
            (4)使用Vi編輯configure.scan為:

            #                                               -*- Autoconf -*-
            # Process this file with autoconf to produce a configure script.

            AC_PREREQ(2.59)
            AC_INIT(hello, 1.0)
            AM_INIT_AUTOMAKE(hello,1.0)
            AC_CONFIG_SRCDIR([hello.h])
            AC_CONFIG_HEADER([config.h])
            # Checks for programs.
            AC_PROG_CC
            # Checks for libraries.
            # Checks for header files.
            # Checks for typedefs, structures, and compiler characteristics.
            # Checks for library functions.
            AC_OUTPUT(Makefile)

            (5)保存退出,并重命名為configure.in。
            (6)運(yùn)行:aclocal。
            (7)運(yùn)行:autoconf,并用ls查看是否生成了configure可執(zhí)行文檔。
            (8)運(yùn)行:autoheader。
            (9)用Vi編輯Makefile.am文檔為:

            AUTOMAKE_OPTIONS=foreign
            bin_PROGRAMS=hello
            hello_SOURCES=hello.c hello.h

            (10)運(yùn)行:automake。
            (11)運(yùn)行:./configure。
            (12)運(yùn)行:make。
            (13)運(yùn)行:./hello,查看結(jié)果是否正確。
            (14)運(yùn)行:make install。
            (15)運(yùn)行:hello,查看結(jié)果是否正確。
            (16)運(yùn)行:make dist。
            (17)在當(dāng)前目錄下解壓hello-1.0.tar.gz:tar –zxvf hello-1.0.tar.gz。
            (18)進(jìn)入解壓目錄:cd ./hello-1.0。
            (19)下面開(kāi)始Linux下常見(jiàn)的安裝軟件步驟:./configure。
            (20)運(yùn)行:make。
            (21)運(yùn)行:./hello(在正常安裝時(shí)這一步可省略)。
            (22)運(yùn)行:make install。
            (23)運(yùn)行:hello,查看結(jié)果是否正確。
            4.實(shí)驗(yàn)結(jié)果
            能夠正確使用autotools生成Makefile,并且能夠安裝成功短小的Hello軟件。
            精品一久久香蕉国产线看播放| 久久精品无码午夜福利理论片| 26uuu久久五月天| 久久se这里只有精品| 一97日本道伊人久久综合影院| 久久久无码精品亚洲日韩京东传媒| 久久午夜福利无码1000合集| 精品人妻久久久久久888| 7777久久亚洲中文字幕| 久久精品二区| 色诱久久久久综合网ywww| 91久久九九无码成人网站 | 日产精品久久久久久久| 精品久久久久久久久中文字幕| 观看 国产综合久久久久鬼色 欧美 亚洲 一区二区 | 女人高潮久久久叫人喷水| 99久久精品国产高清一区二区 | 久久久噜噜噜www成人网| 久久国产精品无码网站| 久久精品a亚洲国产v高清不卡| 精品久久久无码中文字幕| 久久精品中文字幕无码绿巨人| 精品久久久久久无码人妻蜜桃| 久久久久久国产精品无码超碰| 国产免费久久久久久无码| 久久国产色AV免费看| 久久精品视频一| 一级A毛片免费观看久久精品| 91久久九九无码成人网站| 久久A级毛片免费观看| 色欲久久久天天天综合网精品| 一本久道久久综合狠狠躁AV| 99热成人精品免费久久| 久久久精品免费国产四虎| 狠狠色婷婷久久一区二区三区 | 精品久久久久久久久午夜福利| 三级三级久久三级久久| 伊人久久大香线蕉综合网站| 日本亚洲色大成网站WWW久久 | 色偷偷91久久综合噜噜噜噜| 久久精品国产亚洲精品|