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

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

生活随笔

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

编程问答

Makefile札记

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

Makefile:= ?= += =的區(qū)別


Makefile中我們經(jīng)常看到 = := ?= +=這幾個(gè)賦值運(yùn)算符,那么他們有什么區(qū)別呢?我們來(lái)做個(gè)簡(jiǎn)單的實(shí)驗(yàn)

新建一個(gè)Makefile,內(nèi)容為:

ifdef DEFINE_VRE

??? VRE = “Hello World!”

else

endif

ifeq ($(OPT),define)

??? VRE ?= “Hello World! First!”

endif

ifeq ($(OPT),add)

??? VRE += “Kelly!”

endif

ifeq ($(OPT),recover)

??? VRE := “Hello World! Again!”

endif

all:

??? @echo $(VRE)

敲入以下make命令:

make DEFINE_VRE=true OPT=define 輸出:Hello World!

make DEFINE_VRE=true OPT=add 輸出:Hello World! Kelly!

make DEFINE_VRE=true OPT=recover? 輸出:Hello World! Again!

make DEFINE_VRE= OPT=define?輸出:Hello World! First!

make DEFINE_VRE= OPT=add 輸出:Kelly!

make DEFINE_VRE= OPT=recover 輸出:Hello World! Again!

從上面的結(jié)果中我們可以清楚的看到他們的區(qū)別了

= 是最基本的賦值

:= 是覆蓋之前的值

?= 是如果沒(méi)有被賦值過(guò)就賦予等號(hào)后面的值

+= 是添加等號(hào)后面的值

之前一直糾結(jié)makefile“=”“:=”的區(qū)別到底有什么區(qū)別,因?yàn)榻o變量賦值時(shí),兩個(gè)符號(hào)都在使用。網(wǎng)上搜了一下,有人給出了解答,但是本人愚鈍,看不懂什么意思。幾尋無(wú)果之下,也就放下了。今天看一篇博客,無(wú)意中發(fā)現(xiàn)作者對(duì)于這個(gè)問(wèn)題做了很好的解答。解決問(wèn)題之余不免感嘆,有時(shí)候給個(gè)例子不就清楚了嗎?為什么非要說(shuō)得那么學(xué)術(shù)呢。^_^

????? 1、“=”

????? make會(huì)將整個(gè)makefile展開(kāi)后,再?zèng)Q定變量的值。也就是說(shuō),變量的值將會(huì)是整個(gè)makefile中最后被指定的值。看例子:

????????????x = foo
??????????? y = $(x) bar
??????????? x = xyz

??????在上例中,y的值將會(huì)是?xyz bar?,而不是?foo bar?。

????? 2、“:=”

????? “:=”表示變量的值決定于它在makefile中的位置,而不是整個(gè)makefile展開(kāi)后的最終值。

????????????x := foo
??????????? y := $(x) bar
??????????? x := xyz

????? 在上例中,y的值將會(huì)是?foo bar?,而不是?xyz bar?了。



makefile宏定義:EXTRA_CFLAGS += -DCONFIG_ =y


EXTRA_CFLAGS += -D CONFIG_ =y

1.

假如定義一個(gè)宏CONFIG_DEBUG

.c里面定義為:#define?CONFIG_DEBUG

makefile里定義為: CONFIG_DEBUG=y

假如說(shuō)我們想在makefile里為.c文件進(jìn)入一個(gè)宏定義,就用EXTRA_CFLAGS += DCONFIG_DEBUG(等價(jià)于在.c文件里定義#define?CONFIG_DEBUG)

這時(shí)CONFIG_DEBUG=yEXTRA_CFLAGS += DCONFIG_DEBUG的區(qū)別應(yīng)該你已經(jīng)看出來(lái)的,前者是對(duì)makefile編譯時(shí)用的,比如說(shuō)obj-(CONFIG_DEBUG) += test.o,而后者則是對(duì).c源文件里的用的,比如說(shuō):

#if defined(CONFIG_DEBUG)?

...

#else

...

#endif

2.


假如定義一個(gè)宏CONFIG_DEBUG = 3

.c里面定義為:#define?CONFIG_DEBUG 3

假如說(shuō)我們想在makefile里為.c文件進(jìn)入一個(gè)宏定義,就用EXTRA_CFLAGS += -DCONFIG_DEBUG=3

此時(shí)兩者的定義完全相同。



Makefile中通配符*%的區(qū)別是什么?

此兩者均為通配符,但更準(zhǔn)確的講,%Makefile規(guī)則通配符,一般用于規(guī)則描述,如

%.o:%c

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

表示所有的目標(biāo)文件及其依賴文件,或者

$(filter %.c ,SOURCES)

此處SOURCES表示包含.c .cc .cpp等多類型源文件,該過(guò)濾器函數(shù)將c文件過(guò)濾出來(lái),而%.c即為此過(guò)濾器規(guī)則。

通配符*則不具備上述功能。尤其是在Makefile,當(dāng)變量定義或者函數(shù)調(diào)用時(shí),該通配符的展開(kāi)功能就失效了,即不能正常使用了,此時(shí)需要借助wildcard函數(shù)。二者應(yīng)用范圍不同。



Makefile有三個(gè)非常有用的變量。分別是$@$^$<代表的意義分別是:

# 這是上面那個(gè)程序的Makefile文件:?

mainmain.o?mytool1.o?mytool2.o?


gcc?-o?main?main.o?mytool1.o?mytool2.o?


main.omain.c?mytool1.h?mytool2.h?


gcc?-c?main.c?


mytool1.omytool1.c?mytool1.h?


gcc?-c?mytool1.c?


mytool2.omytool2.c?mytool2.h?


gcc?-c?mytool2.c

有了這個(gè)Makefile文件,不論我們什么時(shí)候修改了源程序當(dāng)中的什么文件,我們只要執(zhí)行make命令,我們的編譯器都只會(huì)去編譯和我們修改的文件有關(guān)的文件,其它的文件它連理都不想去理的。?下面我們學(xué)習(xí)Makefile是如何編寫(xiě)的。?Makefile中也#開(kāi)始的行都是注釋行.Makefile中最重要的是描述文件的依賴關(guān)系的說(shuō)明。一般的格式是:?

targetcomponents?

TAB rule?

第一行表示的是依賴關(guān)系。第二行是規(guī)則。?


比如說(shuō)我們上面的那個(gè)Makefile文件的第二行。?

mainmain.o mytool1.o mytool2.o?

表示我們的目標(biāo)(target)main的依賴對(duì)象(components)main.o mytool1.omytool2.o當(dāng)倚賴的對(duì)象在目標(biāo)修改后修改的話,就要去執(zhí)行規(guī)則一行所指定的命令。

就象我們的上面那個(gè)Makefile第三行所說(shuō)的一樣要執(zhí)行 gcc-o main main.o mytool1.o mytool2.o注意規(guī)則一行中的TAB表示那里是一個(gè)TAB?Makefile有三個(gè)非常有用的變量。

分別是$@$^$<代表的意義分別是:?

$@--目標(biāo)文件,$^--所有的依賴文件,$<--第一個(gè)依賴文件。?如果我們使用上面三個(gè)變量,

那么我們可以簡(jiǎn)化我們的Makefile文件為:?

# 這是簡(jiǎn)化后的Makefile?

mainmain.o mytool1.o mytool2.o?

gcc -o $@ $^?


main.omain.c mytool1.h mytool2.h?

gcc -c $<?


mytool1.omytool1.c mytool1.h?

gcc -c $<


mytool2.omytool2.c mytool2.h?

gcc -c $<?


經(jīng)過(guò)簡(jiǎn)化后,我們的Makefile是簡(jiǎn)單了一點(diǎn),不過(guò)人們有時(shí)候還想簡(jiǎn)單一點(diǎn)。這里我們學(xué)習(xí)一個(gè)Makefile的缺省規(guī)則?.c.o?gcc -c $<?這個(gè)規(guī)則表示所有的 .o文件都是依賴與相應(yīng)的.c文件的。例如mytool.o依賴于mytool.c這樣Makefile還可以變?yōu)?#xff1a;?


# 這是再一次簡(jiǎn)化后的Makefile?

mainmain.o mytool1.o mytool2.o?

gcc -o $@ $^?

.c.o?

gcc -c $<?


好了,我們的Makefile 也差不多了,如果想知道更多的關(guān)于Makefile的規(guī)則,可以查看相應(yīng)的文檔。





makefilePHONY的相關(guān)介紹

PHONY 目標(biāo)并非實(shí)際的文件名:只是在顯式請(qǐng)求時(shí)執(zhí)行命令的名字。有兩種理由需要使用PHONY目標(biāo):避免和同名文件沖突,改善性能。

如果編寫(xiě)一個(gè)規(guī)則,并不產(chǎn)生目標(biāo)文件,則其命令在每次make該目標(biāo)時(shí)都執(zhí)行。例如:
  clean:
  rm *.o temp
因?yàn)?span style="line-height:normal; font-family:Helvetica">"rm"命令并不產(chǎn)生"clean"文件,則每次執(zhí)行"make clean"的時(shí)候,該命令都會(huì)執(zhí)行。如果目錄中出現(xiàn)了"clean"文件,則規(guī)則失效了:沒(méi)有依賴文件,文件"clean"始終是最新的,命令永遠(yuǎn)不會(huì)執(zhí)行;為避免這個(gè)問(wèn)題,可使用".PHONY"指明該目標(biāo)。如:
  .PHONY : clean
  這樣執(zhí)行"make clean"會(huì)無(wú)視"clean"文件存在與否。

已知phony 目標(biāo)并非是由其它文件生成的實(shí)際文件,make會(huì)跳過(guò)隱含規(guī)則搜索。這就是聲明phony目標(biāo)會(huì)改善性能的原因,即使你并不擔(dān)心實(shí)際文件存在與否。
  完整的例子如下:
  .PHONY : clean
  clean :
  rm *.o temp

phony 目標(biāo)可以有依賴關(guān)系。當(dāng)一個(gè)目錄中有多個(gè)程序,將其放在一個(gè)makefile中會(huì)更方便。因?yàn)槿笔∧繕?biāo)是makefile中的第一個(gè)目標(biāo),通常將這個(gè)phony目標(biāo)叫做"all",其依賴文件為各個(gè)程序:
  all : prog1 prog2 prog3
  .PHONY : all
  prog1 : prog1.o utils.o
   ? ? ? ? cc -o prog1 prog1.o utils.o
  prog2 : prog2.o
   ? ? ? ? cc -o prog2 prog2.o
  prog3 : prog3.o sort.o utils.o
   ? ? ? ? cc -o prog3 prog3.o sort.o utils.o

假設(shè)你的一個(gè)項(xiàng)目最后需要產(chǎn)生兩個(gè)可執(zhí)行文件。你的主要目標(biāo)是產(chǎn)生兩個(gè)可執(zhí)行文件,但這兩個(gè)文件是相互獨(dú)立的——如果一個(gè)文件需要重建,并不影響另一個(gè)。你可以使用假象目的來(lái)達(dá)到這種效果。一個(gè)假象目的跟一個(gè)正常的目的幾乎是一樣的,只是這個(gè)目的文件是不存在的。因此, make總是會(huì)假設(shè)它需要 被生成,當(dāng)把它的依賴文件更新后,就會(huì)執(zhí)行它的規(guī)則里的命令行。

如果在我們的 makefile 開(kāi)始處輸入:

all : exec1 exec2

其中 exec1 exec2是我們做為目的的兩個(gè)可執(zhí)行文件。 make把這個(gè) 'all' 做為它的主要目的,每次執(zhí)行時(shí)都會(huì)嘗試把 'all'更新。但既然這行規(guī)則里沒(méi)有哪個(gè)命令來(lái)作用在一個(gè)叫 'all'實(shí)際文件(事實(shí)上 all并不會(huì)在磁碟上實(shí)際產(chǎn)生),所以這個(gè)規(guī)則并不真的改變 'all'的狀態(tài)??杉热贿@個(gè)文件并不存在,所以 make會(huì)嘗試更新 all 規(guī)則,因此就檢查它的依靠 exec1, exec2是否需要更新,如果需要,就把它們更新,從而達(dá)到我們的目的。

假象目的也可以用來(lái)描述一組非預(yù)設(shè)的動(dòng)作。例如,你想把所有由 make產(chǎn)生的文件刪除,你可以在 makefile里設(shè)立這樣一個(gè)規(guī)則:

veryclean :
rm *.o
rm myprog

前提是沒(méi)有其它的規(guī)則依靠這個(gè) 'veryclean'目的,它將永遠(yuǎn)不會(huì)被執(zhí)行。但是,如果你明確的使用命令 'make veryclean' make會(huì)把這個(gè)目的做為它的主要目標(biāo),執(zhí)行那些 rm命令。

如果你的磁碟上存在一個(gè)叫 veryclean文件,會(huì)發(fā)生什么事?這時(shí)因?yàn)樵谶@個(gè)規(guī)則里沒(méi)有任何依靠文件,所以這個(gè)目的文件一定是最新的了(所有的依靠文件都已經(jīng)是最新的了),所以既使用戶明確命令 make重新產(chǎn)生它,也不會(huì)有任何事情發(fā)生。解決方法是標(biāo)明所有的假象目的(用 .PHONY),這就告訴 make不用檢查它們是否存在于磁碟上,也不用查找任何隱含規(guī)則,直接假設(shè)指定的目的需要被更新。在 makefile里加入下面這行包含上面規(guī)則的規(guī)則:

.PHONY : veryclean

就可以了。注意,這是一個(gè)特殊的 make規(guī)則,make知道 .PHONY是一個(gè)特殊目的,當(dāng)然你可以在它的依靠里加入你想用的任何假象目的,而 make知道它們都是假象目的。






?Makefileshell腳本區(qū)別


Makefile可以調(diào)用shell腳本,但是Makefileshell腳本是不同的。本文試著歸納一下Makefileshell腳本的不同。
1 shell中所有引用以$打頭的變量其后要加{},而在Makefile中的變量是以$打頭的后加()。實(shí)例如下:
Makefile
PATH="/data/"
SUBPATH=$(PATH)

Shell
PATH="/data/"
SUBPATH=${PATH}

2Makefile中所有以$打頭的單詞都會(huì)被解釋成Makefile中的變量。如果你需要調(diào)用shell中的變量(或者正則表達(dá)式中錨定句位$),都需要加兩個(gè)$符號(hào)($$)。實(shí)例如下:

PATH="/data/"

all:
? ? echo ${PATH}
? ? echo $$PATH

?例子中的第一個(gè)${PATH}引用的是Makefile中的變量,而不是shell中的PATH環(huán)境變量,后者引用的事Shell中的PATH環(huán)境變量。


3
、通配符區(qū)別
shell
中通配符*表示所有的字符
Makefile
中通配符%表示所有的字符

4、在Makefile中只能在某一個(gè)target下的命令中調(diào)用Shell腳本,其他地方是不能輸出的。比如如下代碼就是沒(méi)有任何輸出:

VAR="Hello"
echo "$VAR"

all:
?? .....
以上代碼任何時(shí)候都不會(huì)輸出,沒(méi)有在任何target下得命令內(nèi),如果上述代碼改為如下:

VAR="Hello"

all:
? ? echo "$VAR"
? ? .....以上代碼,在make all的時(shí)候?qū)?huì)執(zhí)行echo命令。

5、在Makefile中執(zhí)行shell命令,一行創(chuàng)建一個(gè)進(jìn)程來(lái)執(zhí)行。這也是為什么很多Makefile中有很多行的末尾都是“;? \”,以此來(lái)保證代碼是一行而不是多行,這樣Makefile可以在一個(gè)進(jìn)程中執(zhí)行,例如:

SUBDIR=src example
all:
? ? @for subdir in $(SUBDIR); \
? ? do\
? ? ? ? echo "building "; \
? ? done上述可以看出for循環(huán)中每行都是以”; \”結(jié)尾的。

6、獲取當(dāng)前目錄

PATH=`pwd` 注意是``,不是’'







?Makefile中的shell2009-12-24 09:27:05

分類:


一下摘錄Makefile中調(diào)用shell的一段


install:

? ? ? ? -if [ ! -e xxx ]; then sudo mkdir xxx; fi


注意,將上面的if語(yǔ)句寫(xiě)到一行的話,必須在fi前面加上分號(hào),否則會(huì)出現(xiàn)下面錯(cuò)誤

unexpected end of file


下面轉(zhuǎn)一個(gè)相關(guān)文章

MakefileShell的問(wèn)題

?

大概只要知道Makefile的人,都知道Makefile可以調(diào)用Shell腳本。但是在實(shí)際使用時(shí),并不那么簡(jiǎn)單,一些模棱兩可的地方可能會(huì)讓你抓狂。你若不信,可以先看幾個(gè)例子,想象一下這些這些例子會(huì)打印什么內(nèi)容,記下你想象的結(jié)果,然后在計(jì)算機(jī)上運(yùn)行這些例子,對(duì)照看一下。

?

?

示例一:

if [ "$(BUILD)" = "debug" ]; then? echo "build debug"; else echo "build release"; fi

all:

? ? echo "done"

示例二:

all:

? ? @CC=arm-linux-gcc

? ? @echo $(CC)

示例三:

CC=arm-linux-gcc

all:

? ? @echo $(CC)

示例四:

SUBDIR=src example

all:

? ? @for subdir in $(SUBDIR); \

? ? do\

? ? ? ? echo "building " $(subdir); \

? ? done

?

?

說(shuō)明:

1. ? ? ? ? Shell腳本在target里才有效,其它地方都被忽略掉了。所以示例一中,”build debug”之類的字符串根本打印不出來(lái)。示例一的正確寫(xiě)法是:

?

示例一:

all:

? ? if [ "$(BUILD)" = "debug" ]; then? echo "build debug"; else echo "build release"; fi

? ? echo "done"

?

2. ? ? ? ? make把每一行Shell腳本當(dāng)作一個(gè)獨(dú)立的單元,它們?cè)趩为?dú)的進(jìn)程中運(yùn)行。示例二中,兩行Shell腳本在兩個(gè)莫不相干的進(jìn)程里運(yùn)行,第一個(gè)進(jìn)程把CC設(shè)置為arm-linux-gcc,第二個(gè)進(jìn)程是不知道的,所以打印的結(jié)果自然不是arm-linux-gcc了。示例二的正確寫(xiě)法是:

?

示例二:

all:

? ? @CC=arm-linux-gcc; echo $(CC)

或者:

all:

@CC=arm-linux-gcc; \

echo $(CC)

?

3. ? ? ? ? make在調(diào)用Shell之前先進(jìn)行預(yù)處理,即展開(kāi)所有Makefile的變量和函數(shù)。這些變量和函數(shù)都以$開(kāi)頭。示例三中,Shell拿的腳本實(shí)際上是echo arm-linux-gcc,所以打印結(jié)果正確。

?

4. ? ? ? ? make預(yù)處理時(shí),所有以$開(kāi)頭的,它都不會(huì)放過(guò)。要想引用Shell自己的變量,應(yīng)該以$$開(kāi)頭。另外要注意,Shell自己的變量是不需要括號(hào)的。示例四的正確寫(xiě)法是:

?

示例四:

SUBDIR=src example

all:

? ? @for subdir in $(SUBDIR); \

? ? do\

? ? ? ? echo "building " $$subdir; \

? ? done

感謝,Thanks




?linux Makefile obj-m obj-y ..

分類: Linux

2013-02-20 14:01 1773人閱讀 評(píng)論(0) 收藏 舉報(bào)

目標(biāo)定義是Kbuild Makefile的主要部分,也是核心部分。主要是定義了要編 譯的文件,所有的選項(xiàng),以及到哪些子目錄去執(zhí)行遞歸操作。 最簡(jiǎn)單的Kbuild makefile 只包含一行: 例子: obj-y += foo.o 該例子告訴Kbuild在這目錄里,有一個(gè)名為foo.o的目標(biāo)文件。foo.o將從foo.c foo.S文件編譯得到。 如果foo.o要編譯成一模塊,那就要用obj-m了。所采用的形式如下: 例子: obj-$(CONFIG_FOO) += foo.o $(CONFIG_FOO)可以為y(編譯進(jìn)內(nèi)核) m(編譯成模塊)。如果CONFIG_FOO不是y m,那么該文件就不會(huì)被編譯聯(lián)接了


Linux各級(jí)內(nèi)核源代碼的子目錄下都有Makefile,大多數(shù)Makefile要嵌入主目錄下的Rule.makeRule.make將識(shí)別各個(gè)Makefile中所定義的一些變量。變量obj-y表示需要編繹到內(nèi)核中的目標(biāo)文件名集合,定義O_TARGET表示將obj-y連接為一個(gè)O_TARGET名稱的目標(biāo)文件,定義L_TARGET表示將obj-y合并為一個(gè)L_TARGET名稱的庫(kù)文件。同樣obj-m表示需要編繹成模塊的目標(biāo)文件名集合。如果還需進(jìn)行子目錄make,則需要定義subdir-ysubdir-m。在Makefile中,用"obj-$(CONFIG_BINFMT_ELF) += binfmt_elf.o"和"subdir-$(CONFIG_EXT2_FS) += ext2"這種形式自動(dòng)為obj-y、obj-m、subdir-ysubdir-m添加文件名。有時(shí),情況沒(méi)有這么單純,還需要使用條件語(yǔ)句個(gè)別對(duì)待。Makefile中還有其它一些變量,如mod-subdirs定義了subdir-m以外的所有模塊子目錄。?


Rules.make是如何使make進(jìn)入子目錄的呢? 先來(lái)看subdir-y是如何處理的,在Rules.make中,先對(duì)subdir-y中的每一個(gè)文件名加上前綴"_subdir_"再進(jìn)行排序生成subdir-list集合,再以它作為目標(biāo)集,對(duì)其中每一個(gè)目標(biāo)產(chǎn)生一個(gè)子make,同時(shí)將目標(biāo)名的前綴去掉得到子目錄名,作為子make的起始目錄參數(shù)。subdir-msubdir-y類似,但情況稍微復(fù)雜一些。由于subdir-y中可能有模塊定義,因此利用mod-subdirs變量將subdir-y中模塊目錄提取出來(lái),再與subdir-m合成一個(gè)大的MOD_SUB_DIRS集合。subdir-m的目標(biāo)所用的前綴是"_modsubdir_"。?


一點(diǎn)說(shuō)明,子目錄中的MakefileRules.make都沒(méi)有嵌入.config文件,它是通過(guò)主Makefile向下傳遞MAKEFILES變量完成的。MAKEFILESmake自已識(shí)別的一個(gè)變量,在執(zhí)行新的Makefile之前,make會(huì)首先加載MAKEFILES所指的文件。在主Makefile中它即指向.config。?

總結(jié)

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

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