-
makefile 中 .PYONY 的目的是什么
默認(rèn)情況下铣揉,Makefile
目標(biāo)是「文件目標(biāo)」- 它們用于從其他文件構(gòu)建文件. 假設(shè)它的目標(biāo)是一個(gè)文件哪审,這使得編寫Makefile
相對(duì)容易.foo: bar create_one_from_the_other foo bar
但是蛾魄,有時(shí)你希望
Makefile
運(yùn)行一些命令而不是構(gòu)建一個(gè)在文件系統(tǒng)中的實(shí)際文件. 例如常用的目標(biāo)文件:clean
,all
.
但有時(shí)情況并非如此,你可能在主目錄中有一個(gè)名為clean
的文件湿滓,這時(shí)候Make
會(huì)被混淆滴须,因?yàn)槟J(rèn)情況下,clean
目標(biāo)將與此文件關(guān)聯(lián)叽奥,而Make
只會(huì)在這個(gè)文件根據(jù)它的依賴發(fā)現(xiàn)不是最新的時(shí)候才會(huì)執(zhí)行.這些特殊目標(biāo)稱為「虛假目標(biāo)」扔水,你可以明確告訴
Make
它們與文件無關(guān)..PHONY: clean clean: rm -rf *.o
現(xiàn)在
make clean
將按預(yù)期運(yùn)行,即使你有一個(gè)名為clean
的文件.就
Make
而言朝氓,「虛假目標(biāo)」是一個(gè)總是過時(shí)的目標(biāo)魔市,因此無論何時(shí)make <pyony_target>
, 它都會(huì)運(yùn)行,獨(dú)立于文件系統(tǒng)的狀態(tài).
一些常用的「虛假目標(biāo)」:all
,install
,clean
,distclean
,TAGS
,info
,check
. -
GNU Makefile 變量賦值 =, ?=, := 和 += 之間有什么區(qū)別
Lazy Set
VARIABLE = value
變量的正常設(shè)置 - 當(dāng)使用變量時(shí)膀篮,變量會(huì)「遞歸擴(kuò)展」嘹狞,而不是在聲明變量的時(shí)候擴(kuò)展.
Immediate Set
VARIABLE := value
通過簡單擴(kuò)展內(nèi)部值來設(shè)置變量 - 其中的值在聲明時(shí)擴(kuò)展.(不會(huì)「遞歸擴(kuò)展」).
Set If Absent
VARIABLE ?= value
如果變量沒有定義則設(shè)置變量.
Append
VARIABLE += value
將提供的值附加到現(xiàn)有的值(如果變量不存在,則設(shè)置為該值).
-
從命令行傳遞其他變量給 make
你有幾個(gè)選擇可以從makefile
外部設(shè)置變量.-
環(huán)境變量 - 每一個(gè)環(huán)境變量都轉(zhuǎn)化為具有相同名稱和值的
makefile
變量.
你可能還想設(shè)置
-e
選項(xiàng)(或者--environments-override
)誓竿,并且你的環(huán)境變量會(huì)覆蓋makefile
中的賦值(除非這些賦值本身使用override
)
指令. 但是不推薦使用它.
而是推薦使用更好更靈活的?=
條件賦值(只有在尚沒定義變量時(shí)才有效).FOO ?= default_value_if_not_set_in_environment
注意磅网,某些變量不是從環(huán)境變量繼承的
-
MAKE
從腳本的名字得到的 -
SHELL
要么設(shè)置在makefile
中,要么默認(rèn)為/bin/sh
-
從命令行 -
make
可以將變量賦值作為命令行的一部分筷屡,與目標(biāo)混合.
make target FOO=bar
但是涧偷,除非在賦值中使用
override
指令,否則忽略makefile
中FOO
變量的所有值.-
從父 make 導(dǎo)出 - 如果從
makefile
調(diào)用make
, 通常不應(yīng)該這樣顯式地寫這樣的變量賦值
# Don't do this! target: $(MAKE) -C target CC=$(CC) CFLAGS=$(CFLAGS)
相反毙死,更好的方法是導(dǎo)出這些變量.
導(dǎo)出變量使其進(jìn)入每個(gè)shell
調(diào)用的環(huán)境燎潮,并且使用這些命令將會(huì)調(diào)用這些環(huán)境變量,如上所述.# Do like this CFLAGS=-g export CFLAGS target: $(MAKE) -C target
你也可以導(dǎo)出全部變量扼倘,直接使用
export
不帶參數(shù). -
環(huán)境變量 - 每一個(gè)環(huán)境變量都轉(zhuǎn)化為具有相同名稱和值的
-
makefile 中 $@ 和 $^ 是什么意思
$@
是要生成的目標(biāo)文件的名稱确封,而$^
是第一個(gè)先決條件(通常是源文件). 例如:all: library.cpp main.cpp
$@
相當(dāng)于all
$<
相當(dāng)于library.cpp
$^
相當(dāng)于library.cpp main.cpp
-
makefile:4: *** missing separator. Stop
makefile
與制表符有非常愚蠢的關(guān)系.
每個(gè)規(guī)則的所有操作都由制表符標(biāo)識(shí)除呵,而不是4個(gè)空格,只有tab
才能標(biāo)識(shí)為制表符.
去檢查是否使用制表符爪喘,使用cat -e -t -v makefile_name
.
它顯示了帶有^I
的tab
和帶有$
的行結(jié)尾颜曾,兩者確保了依賴關(guān)系正確結(jié)束以及制表符標(biāo)識(shí)規(guī)則的操作以使它們易于識(shí)別為make
實(shí)用程序起到至關(guān)重要的作用.Kaizen ~/so_test $ cat -e -t -v mk.t all:ll$ ## here the $ is end of line ... $ ll:ll.c $ ^Igcc -c -Wall -Werror -02 c.c ll.c -o ll $@ $<$ ## the ^I above means a tab was there before the action part, so this line is ok . $ clean :$ \rm -fr ll$ ## see here there is no ^I which means , tab is not present .... ## in this case you need to open the file again and edit/ensure a tab ## starts the action part
-
什么是 Makefile.am 和 Makefile.in
Makefile.am
是程序員定義的文件,由automake
用于生成Makefile.in
文件(.am
代表automake
).
通常在源碼包中可以看到configure
腳本使用Makefile.in
生成Makefile
.configure
腳本本身是從名為configure.ac
或configure.in
(不建議使用)的程序員定義的文件生成的.
我更喜歡.ac
(用于autoconf
)秉剑,因?yàn)樗鼘⑴c生成的Makefile.in
文件區(qū)分開來泛豪,這樣我就可以使用make dist-clean
等規(guī)則來運(yùn)行
rm -f *.in
.
由于它是生成的文件,因此通常不會(huì)存儲(chǔ)在版本系統(tǒng)(Git侦鹏,Svn)中诡曙,而是存儲(chǔ)在.ac
文件中. -
如何在 makefile 中編寫 cd 命令
它實(shí)際上是執(zhí)行命令,將目錄更改為some_directory
, 但是略水,這是在子進(jìn)程shell
中執(zhí)行的价卤,并且既不影響make
也不影響你正在使用的shell
.如果你想在
some_directory
中執(zhí)行更多任務(wù),則需要添加分號(hào)并附加其他命令.
請注意聚请,你不能使用換行符荠雕,因?yàn)樗鼈儽?make
解釋為規(guī)則的結(jié)尾,因此為清晰起見而使用的任何換行都需要通過反斜杠進(jìn)行轉(zhuǎn)義.all: cd some_dir; echo "I'm in some_dir"; \ gcc -Wall -o myTest myTest.c
一個(gè)常見的用法是在子目錄中調(diào)用
make
. 這有一個(gè)命令行選項(xiàng)驶赏,所以你不必自己調(diào)用cd
.all: $(MAKE) -C some_dir all
將更改為
some_dir
目錄并執(zhí)行目標(biāo)為all
的Makefile
.
作為最佳實(shí)踐,使用$(MAKE)
而不是直接調(diào)用make
, 因?yàn)樗鼤?huì)注意調(diào)用正確的make
實(shí)例(例如既鞠,如果你為構(gòu)建環(huán)境使用特殊的make
版本)煤傍,并提供使用某些開關(guān)(例如,-t
)運(yùn)行時(shí)略有不同的行為. -
如何在 makefile 中打印變量
你可以使用此方法(使用名為var
的變量)在讀取makefile
時(shí)打印出變量.$(info $$var is [${var}])
你可以將此構(gòu)造添加到任何配方中嘱蛋,以查看將傳遞給
shell
的內(nèi)容.PYONY: all all: ; $(info $$var is [${var}])echo Hello World
現(xiàn)在蚯姆,這里發(fā)生的是將整個(gè)配方(
$(info $$var is [${var}])echo Hello World
)存儲(chǔ)為單個(gè)遞歸擴(kuò)展變量. 當(dāng)make
決定運(yùn)行配方時(shí)(例如,當(dāng)你告訴它構(gòu)建all
時(shí))洒敏,它會(huì)擴(kuò)展變量龄恋,然后將每個(gè)結(jié)果行分別傳遞給shell
.所以,令人懊惱的細(xì)節(jié):
- 擴(kuò)展
$(info $$var is [${var}])echo Hello World
- 要做到這點(diǎn)凶伙,首先擴(kuò)展
$(info $$var is [${var}])
-
$$
擴(kuò)展成$
-
${var}
擴(kuò)展成:)
(取決你變量本身的值) - 副作用是
$var is [:)]
出現(xiàn)在標(biāo)準(zhǔn)輸出(屏幕)上 -
$(info ...)
擴(kuò)展成空
-
-
Make
還剩下echo Hello World
-
Make
首先輸出echo Hello World
到標(biāo)準(zhǔn)輸出(屏幕)郭毕,讓你知道它要求shell
做什么
-
-
shell
輸出Hello World
到標(biāo)準(zhǔn)輸出(屏幕)上
- 擴(kuò)展
-
如何在 makefile 中編寫循環(huán)
假設(shè)你使用的是UNIX
類型平臺(tái),如果運(yùn)行./a.out
.for number in 1 2 3 4 ; do \ ./a.out $$number ; \ done
測試如下
target: for number in 1 2 3 4 ; do \ echo $$number ; \ done
輸出
1 2 3 4
對(duì)于更大的范圍函荣,使用
target: number=1 ; while [[ $$number -le 10 ]] ; do \ echo $$number ; \ ((number = number + 1)) ; \ done
嵌套循環(huán)
target: num1=1 ; while [[ $$num1 -le 4 ]] ; do \ num2=1 ; while [[ $$num2 -le 3 ]] ; do \ echo $$num1 $$num2 ; \ ((num2 = num2 + 1)) ; \ done ; \ ((num1 = num1 + 1)) ; \ done
輸出
1 1 1 2 1 3 2 1 2 2 2 3 3 1 3 2 3 3 4 1 4 2 4 3
在 Unix 中显押,我可以在一個(gè)目錄中運(yùn)行 make 而不先 cd 到那個(gè)目錄嗎
make -C /path/to/dir
-
如何將命令的輸出分配給 Makefile 變量
使用Make
內(nèi)建函數(shù)shell
, 例如:MY_VAR = $(shell echo whatever)
$ make MY_VAR IS whatever
$ cat Makefile MY_VAR := $(shell echo whatever) all: @echo MY_VAR IS $(MY_VAR)
-
如何配置 makefile 為調(diào)試和發(fā)布版本
使用特定于目標(biāo)的變量值,例如CXXFLAGS = -g3 -gdwarf2 CCFLAGS = -g3 -gdwarf2 all: executable debug: CXXFLAGS += -DDEBUG -g debug: CCFLAGS += -DDEBUG -g debug: executable executable: CommandParser.tab.o CommandParser.yy.o Command.o $(CXX) -o output CommandParser.yy.o CommandParser.tab.o Command.o -lfl CommandParser.yy.o: CommandParser.l flex -o CommandParser.yy.c CommandParser.l $(CC) -c CommandParser.yy.c
請記住使用
$(CXX)
或$(CC)
作為編譯命令.
然后傻挂,make debug
將會(huì)有額外的標(biāo)識(shí)乘碑,如:-DDEBUG
和-g
, 而make
不會(huì)有. -
如何獲取 Makefile 的當(dāng)前相對(duì)目錄
你可以使用shell
函數(shù):current_dir = $(shell pwd)
.
或者你需要絕對(duì)路徑,可以shell
結(jié)合notdir
使用,current_dir = $(notdir $(shell pwd))
.
上面的方法金拒,僅make
在Makefile
當(dāng)前目錄執(zhí)行有效.注意: 這將返回當(dāng)前工作目錄兽肤,而不是
Makefile
的父目錄.
例如,如果運(yùn)行cd /; make -f /home/username/project/Makefile
,current_dir
返回的是/
而不是/home/username/project/
以下代碼適用于任何目錄調(diào)用的
Makefile
mkfile_path := $(abspath $(lastword $(MAKEFILE_LIST))) current_dir := $(notdir $(patsubst %/,%,$(dir $(mkfile_path))))
-
如果沒有指定目標(biāo),make 如何知道要構(gòu)建的默認(rèn)目標(biāo)
默認(rèn)情況下资铡,make
首先處理不以.
開頭的第一個(gè)目標(biāo)(又叫「默認(rèn)目標(biāo)」).
也可以使用.DEFAULT_GOAL
指定默認(rèn)目標(biāo)(make
<= 3.80 將不起作用).DEFAULT_GOAL := mytarget
問題集錦
最后編輯于 :
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
- 文/潘曉璐 我一進(jìn)店門腋么,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人亥揖,你說我怎么就攤上這事珊擂。” “怎么了费变?”我有些...
- 文/不壞的土叔 我叫張陵摧扇,是天一觀的道長。 經(jīng)常有香客問我挚歧,道長扛稽,這世上最難降的妖魔是什么? 我笑而不...
- 正文 為了忘掉前任滑负,我火速辦了婚禮在张,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘矮慕。我一直安慰自己帮匾,他們只是感情好,可當(dāng)我...
- 文/花漫 我一把揭開白布痴鳄。 她就那樣靜靜地躺著瘟斜,像睡著了一般。 火紅的嫁衣襯著肌膚如雪夏跷。 梳的紋絲不亂的頭發(fā)上哼转,一...
- 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼勇凭!你這毒婦竟也來了疚膊?” 一聲冷哼從身側(cè)響起,我...
- 序言:老撾萬榮一對(duì)情侶失蹤虾标,失蹤者是張志新(化名)和其女友劉穎寓盗,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體璧函,經(jīng)...
- 正文 獨(dú)居荒郊野嶺守林人離奇死亡傀蚌,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
- 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了蘸吓。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片善炫。...
- 正文 年R本政府宣布艺谆,位于F島的核電站,受9級(jí)特大地震影響雨膨,放射性物質(zhì)發(fā)生泄漏擂涛。R本人自食惡果不足惜,卻給世界環(huán)境...
- 文/蒙蒙 一聊记、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧恢暖,春花似錦排监、人聲如沸。這莊子的主人今日做“春日...
- 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至嫁佳,卻和暖如春挨队,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背蒿往。 一陣腳步聲響...
- 正文 我出身青樓腾夯,卻偏偏與公主長得像颊埃,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子蝶俱,可洞房花燭夜當(dāng)晚...