日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

makefile文件简要介绍

發(fā)布時(shí)間:2025/3/21 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 makefile文件简要介绍 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

到此為止,讀者已經(jīng)了解了如何在Linux下使用編輯器編寫(xiě)代碼,如何使用Gcc把代碼編譯成可執(zhí)行文件,還學(xué)習(xí)了如何使用Gdb來(lái)調(diào)試程序,那么,所有的工作看似已經(jīng)完成了,為什么還需要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)有改動(dòng)的源代碼根本不需要重新編譯,而只要把它們重新鏈接進(jìn)去就可以了。所以,人們就希望有一個(gè)工程管理器能夠自動(dòng)識(shí)別更新了的文件代碼,同時(shí)又不需要重復(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í)行大量的編譯工作。用戶(hù)只需編寫(xiě)一次簡(jiǎn)單的編譯語(yǔ)句就可以了。它大大提高了實(shí)際項(xiàng)目的工作效率,而且?guī)缀跛蠰inux下的項(xiàng)目編程均會(huì)涉及到它,希望讀者能夠認(rèn)真學(xué)習(xí)本節(jié)內(nèi)容。

?

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)體所依賴(lài)的文件(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就可以寫(xiě)為:

?

#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)的依賴(lài)文件。如下所示:

?

[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ò)。

?

?

?

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)體的依賴(lài)文件就是后兩個(gè)目標(biāo)體。如果用戶(hù)使用命令“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”的依賴(lài)文件為:“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è)文本字符串,該文本字符串稱(chēng)為該變量的值。在具體要求下,這些值可以代替目標(biāo)體、依賴(lài)文件、命令以及makefile文件中其它部分。在Makefile中的變量定義有兩種方式:一種是遞歸展開(kāi)方式,另一種是簡(jiǎn)單方式。

遞歸展開(kāi)方式定義的變量是在引用在該變量時(shí)進(jìn)行替換的,即如果該變量包含了對(duì)其他變量的應(yīng)用,則在引用該變量時(shí)一次性將內(nèi)嵌的變量全部展開(kāi),雖然這種類(lèi)型的變量能夠很好地完成用戶(hù)的指令,但是它也有嚴(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ù)字以及下劃線(xiàn)以外的情況應(yīng)盡量避免,因?yàn)樗鼈兛赡茉趯?lái)被賦予特別的含義。

變量名是大小寫(xiě)敏感的,例如變量名“foo”、“FOO”、和“Foo”代表不同的變量。

推薦在makefile內(nèi)部使用小寫(xiě)字母作為變量名,預(yù)留大寫(xiě)字母作為控制隱含規(guī)則參數(shù)或用戶(hù)重載命令選項(xiàng)參數(shù)的變量名。

?

?

下面給出了上例中用變量替換修改后的Makefile,這里用OBJS代替kang.o和yul.o,用CC代替Gcc,用CFLAGS代替“-Wall -O –g”。這樣在以后修改時(shí),就可以只修改變量定義,而不需要修改下面的定義實(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中的變量分為用戶(hù)自定義變量、預(yù)定義變量、自動(dòng)變量及環(huán)境變量。如上例中的OBJS就是用戶(hù)自定義變量,自定義變量的值由用戶(hù)自行設(shè)定,而預(yù)定義變量和自動(dòng)變量為通常在Makefile都會(huì)出現(xiàn)的變量,其中部分有默認(rèn)值,也就是常見(jiàn)的設(shè)定值,當(dāng)然用戶(hù)可以對(duì)其進(jìn)行修改。

預(yù)定義變量包含了常見(jiàn)編譯器、匯編器的名稱(chēng)及其編譯選項(xiàng)。下表3.14列出了Makefile中常見(jiàn)預(yù)定義變量及其部分默認(rèn)值。

表3.14????????????????????????????????????????????????? Makefile中常見(jiàn)預(yù)定義變量

?

命?令?格?式

含????義

AR

庫(kù)文件維護(hù)程序的名稱(chēng),默認(rèn)值為ar

AS

匯編程序的名稱(chēng),默認(rèn)值為as

CC

C編譯器的名稱(chēng),默認(rèn)值為cc

CPP

C預(yù)編譯器的名稱(chēng),默認(rèn)值為$(CC) –E

CXX

C++編譯器的名稱(chēng),默認(rèn)值為g++

FC

FORTRAN編譯器的名稱(chēng),默認(rèn)值為f77

RM

文件刪除程序的名稱(chēng),默認(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)文件和依賴(lài)文件,而這些文件在Makefile文件中目標(biāo)體的一行已經(jīng)有所體現(xiàn),因此,為了進(jìn)一步簡(jiǎn)化Makefile的編寫(xiě),就引入了自動(dòng)變量。自動(dòng)變量通常可以代表編譯語(yǔ)句中出現(xiàn)目標(biāo)文件和依賴(lài)文件等,并且具有本地含義(即下一語(yǔ)句中出現(xiàn)的相同變量代表的是下一語(yǔ)句的目標(biāo)文件和依賴(lài)文件)。下表3.15列出了Makefile中常見(jiàn)自動(dòng)變量。

表3.15??????????????????????????????????????????????????? Makefile中常見(jiàn)自動(dòng)變量

?

命令格式

含????義

$*

不包含擴(kuò)展名的目標(biāo)文件名稱(chēng)

$+

所有的依賴(lài)文件,以空格分開(kāi),并以出現(xiàn)的先后為序,可能包含重復(fù)的依賴(lài)文件

$<

第一個(gè)依賴(lài)文件的名稱(chēng)

$?

所有時(shí)間戳比目標(biāo)文件晚的依賴(lài)文件,并以空格分開(kāi)

命令格式

含????義

$@

目標(biāo)文件的完整名稱(chēng)

$^

所有不重復(fù)的依賴(lài)文件,以空格分開(kāi)

$%

如果目標(biāo)是歸檔成員,則該變量表示目標(biāo)的歸檔成員名稱(chēng)

?

?

自動(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?$<?-o?$@

yul.o : yul.c yul.h

??????$(CC) $(CFLAGS) -c?$<?-o?$@

?

另外,在Makefile中還可以使用環(huán)境變量。使用環(huán)境變量的方法相對(duì)比較簡(jiǎn)單,make在啟動(dòng)時(shí)會(huì)自動(dòng)讀取系統(tǒng)當(dāng)前已經(jīng)定義了的環(huán)境變量,并且會(huì)創(chuàng)建與之具有相同名稱(chēng)和數(shù)值的變量。但是,如果用戶(hù)在Makefile中定義了相同名稱(chēng)的變量,那么用戶(hù)自定義變量將會(huì)覆蓋同名的環(huán)境變量。

?

3??Makefile規(guī)則

?

?

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)前目錄名

?

?

Makefile的規(guī)則是Make進(jìn)行處理的依據(jù),它包括了目標(biāo)體、依賴(lài)文件及其之間的命令語(yǔ)句。一般的,Makefile中的一條語(yǔ)句就是一個(gè)規(guī)則。在上面的例子中,都顯示地指出了Makefile中的規(guī)則關(guān)系,如“$(CC) $(CFLAGS) -c $< -o $@”,但為了簡(jiǎn)化Makefile的編寫(xiě),make還定義了隱式規(guī)則和模式規(guī)則,下面就分別對(duì)其進(jìn)行講解。

1.隱式規(guī)則

隱含規(guī)則能夠告訴make怎樣使用傳統(tǒng)的技術(shù)完成任務(wù),這樣,當(dāng)用戶(hù)使用它們時(shí)就不必詳細(xì)指定編譯的具體細(xì)節(jié),而只需把目標(biāo)文件列出即可。Make會(huì)自動(dòng)搜索隱式規(guī)則目錄來(lái)確定如何生成目標(biāo)文件。如上例就可以寫(xiě)成:

?

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)?strong>.o

$(CC) –c $(CPPFLAGS) $(CFLAGS)

C++編譯:.cc或.C變?yōu)?strong>.o

$(CXX) -c $(CPPFLAGS) $(CXXFLAGS)

Pascal編譯:.p變?yōu)?strong>.o

$(PC) -c $(PFLAGS)

Fortran編譯:.r變?yōu)?strong>-o

$(FC) -c $(FFLAGS)

?

2.模式規(guī)則

模式規(guī)則是用來(lái)定義相同處理規(guī)則的多個(gè)文件的。它不同于隱式規(guī)則,隱式規(guī)則僅僅能夠用make默認(rèn)的變量來(lái)進(jìn)行操作,而模式規(guī)則還能引入用戶(hù)自定義變量,為多個(gè)文件建立相同的規(guī)則,從而簡(jiǎn)化Makefile的編寫(xiě)。

模式規(guī)則的格式類(lèi)似于普通規(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?$<?-o?$@

總結(jié)

以上是生活随笔為你收集整理的makefile文件简要介绍的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。