Makefile 淺析 (1)

據(jù)說(shuō)從事嵌入式系統(tǒng)開(kāi)發(fā)的, 如果不能駕馭好 Makefile, 會(huì)很難做到游刃有余. 看到這句話, 不禁讓我涼了好一陣.

一直以來(lái), 都是在別人搭建好的平臺(tái)上做應(yīng)用, 即使有時(shí)需要自己動(dòng)手來(lái)寫(xiě), 也只是寫(xiě)些特別簡(jiǎn)單的. 今天就想認(rèn)真的學(xué)習(xí)下 Makefile.

概念

學(xué)習(xí) Makefile 需要掌握兩個(gè)重要的概念, 一個(gè)是目標(biāo)(target), 還有一個(gè)是依賴(dependency)

規(guī)則

# 規(guī)則語(yǔ)法
targets : prerequisites
    command
    ...(可以有多個(gè)命令)
1. 命令前面必須只有 Tab 鍵, 目標(biāo)和依賴的格式為 target:dependency, 置于命令前面蚂斤。
# makefile 
# all:
#   echo "Hello world!"
[root@ ~]$ make
echo "Hello world!"
Hello world!

在這里存捺,all 是目標(biāo),沒(méi)有依賴曙蒸“浦危可以運(yùn)行 make 或者 make all

  • 一個(gè) Makefile 中可以定義多個(gè)目標(biāo)纽窟。
  • 調(diào)用 make 命令時(shí)肖油,我們得告訴它我們的目標(biāo)是什么,即要它干什么臂港。當(dāng)沒(méi)有指明具體的目標(biāo)是什么時(shí)森枪,那么 make 以 Makefile 文件中定義的第一個(gè)目標(biāo)作為這次運(yùn)行的目標(biāo)。這“第一個(gè)”目標(biāo)也稱之為默認(rèn)目標(biāo)审孽。
  • 當(dāng) make 得到目標(biāo)后县袱,先找到定義目標(biāo)的規(guī)則,然后運(yùn)行規(guī)則中的命令來(lái)達(dá)到構(gòu)建目標(biāo)的目的佑力。規(guī)則可以有多條式散。
2. 上面的例子太簡(jiǎn)單了,沒(méi)用到依賴搓萧。下面增加一個(gè)依賴(在命令前面加 @ 可以屏蔽命令的顯示)
[root@ ~]$ cat makefile 
all: test
    @echo "Hello world!"
test:
    @echo "I am test!"
[root@ ~]$ make test
I am test!
[root@ ~]$ make
I am test!
Hello world!

這里杂数,添加了 test 作為 all 的依賴宛畦,在 make 或者 make all 時(shí)瘸洛,make 將先檢查 all:后面的依賴 test,再找到目標(biāo) test次和,先執(zhí)行 echo “I am test反肋!”,然后再回到 all 規(guī)則執(zhí)行下面的命令 echo “Hello world踏施!”

要點(diǎn)

1. 命令前面必須只有 Tab 鍵
2. := 簡(jiǎn)單擴(kuò)展變量, 對(duì)變量只進(jìn)行一次掃描和替換

x = val_1
y := $(x) test
x = val_2

.PHONY: all
all:
    @echo "x = $(x), y = $(y)"
    
# 輸出
# x = val_2, y = val_1 test

3. ?= 條件賦值, 當(dāng)變量以前沒(méi)有定義時(shí),就定義它并且將左邊的值賦值給
它,如果已經(jīng)定義了那么就不再改變其值

x = val
x ?= test
y ?= test

.PHONY: all
all:
    @echo "x = $(x), y = $(y)"
# 輸出
# x = val, y = test

4. = 遞歸擴(kuò)展變量, 與簡(jiǎn)單擴(kuò)展變量不同的是, 會(huì)找到變量最后一次賦的值

x = val_1
y = $(x) test
x = val_2

.PHONY: all
all:
    @echo "x = $(x), y = $(y)"
    
# 輸出
# x = val_2, y = val_2 test

5. 自動(dòng)變量

a. $@ 表示一個(gè)規(guī)則的目標(biāo), 當(dāng)有多個(gè)目標(biāo)時(shí), $@所指的是其中任何造成命令被運(yùn)行的目標(biāo)  

b. $^ 表示規(guī)則中的所有先決條件  

c. $< 表示規(guī)則中的第一個(gè)先決條件  
.PHONY: all

all: 1st 2nd 3rd
    @echo "\$$@ = $@"
    @echo "\$$^ = $^"
    @echo "\$$< = $<"

1st 2nd 3rd:

[taylorpc@ test02]$ make
$@ = all
$^ = 1st 2nd 3rd
$< = 1st

6. 特殊變量

a. MAKE, 表示 make 的命令是什么  
b. MAKECMDGOALS, 表示 make 的目標(biāo)是什么  
PHONY: all

all:    
    @echo "MAKE = $(MAKE)"
    @echo "MAKECMDGOALS = $(MAKECMDGOALS)"
    
[taylorpc@ test02]$ make
MAKE = make
MAKECMDGOALS = 
[taylorpc@ test02]$ make all
MAKE = make
MAKECMDGOALS = all

7. 變量與值的來(lái)源

a. 自動(dòng)變量, 是在每一個(gè)規(guī)則中根據(jù)上下文自動(dòng)獲取的  
b. 可以在 make 時(shí)定義, 如 `make value=99`, 這樣子當(dāng) `echo $(value)` 時(shí)輸出的就是 99 了.  
c. 可以從 shell 環(huán)境中獲得, 如 `export test=val`  
d. 還可以在 makefile 直接賦值, 如 "=", "+="  

8. 高級(jí)變量引用 (或 patsubst): 在賦值的同時(shí)完成后綴替換

.PHONY: all

src = a.o \
      b.o \
      c.o

dst = $(src:.o=.c)

all:
    @echo "dst = $(dst)"
    
[taylorpc@ test03]$ make
dst = a.c b.c c.c

9. override 指令: 覆蓋用戶自定義的變量 (上面第 7 點(diǎn)的 b 小點(diǎn))

.PHONY: all
override test = 0
all:
    @echo $(test)
    
$ make test=9999
# output: 0

10. 模式: 型如 %.o:%.c

這樣做的好處是, 當(dāng)需要編譯多個(gè)相同類型的文件時(shí), 不需要每個(gè)文件都編寫(xiě)一個(gè)對(duì)應(yīng)的規(guī)則, 只需要下面這一條就可以了:  
%.o: %.c
    $(CC) -o $@ -c $^

11. 函數(shù)(wildcard, patsubst)

a. wildcard: 擴(kuò)展通配符  
b. notdir: 去除路徑  
c. patsubst: 替換通配符  
* 這一點(diǎn)應(yīng)該是在第 10 小點(diǎn)的模式之前使用, 這樣方便列出所有源文件和依賴文件
src = $(wildcard ./*.c ./sub/*.c)  # 獲取當(dāng)前目錄下和 sub 目錄下的所有 .c 文件, 展開(kāi)并以空格分隔
nodir = $(notdir $(src)) # 去除路徑
obj = $(patsubst %.c, %.o, $(nodir)) # 將所有的 .c 替換成 .o

all:
    @echo "src: $(src)"
    @echo "nodir: $(nodir)"
    @echo "obj: $(obj)"
    
# output
src: ./test.c ./sub/test2.c ./sub/test3.c  
nodir: test.c test2.c test3.c 
obj:  test.o  test2.o  test3.o 

12. 函數(shù) (addprefix 在字符串前添加前綴)

[taylorpc@ test03]$ cat makefile
.PHONY: all

src = test1.c \
      test2.c \
      test3.c

src_dir = $(addprefix myprefix/, $(src))

all:
    @echo "src: $(src)"
    @echo "src_dir: $(src_dir)"
    
[taylorpc@ test03]$ make
src: test1.c test2.c test3.c
src_dir: myprefix/test1.c myprefix/test2.c myprefix/test3.c

13. 函數(shù) (filter 過(guò)濾, 獲取想要的內(nèi)容/文件)

.PHONY: all 

src = test.c test.o test.h value.c value.h
res = $(filter %.c %.h, $(src))

all: 
    @echo "res: $(res)"
    
$ make  # output 
src: test.c test.o test.h value.c value.h
res: test.c test.h value.c value.h

14. 函數(shù) (filter-out 過(guò)濾, 濾除不想要的內(nèi)容)

.PHONY: all

src = main.c main.o test.c test.o test.h
res = $(filter-out main%c %.o, $(src))

all:
    @echo "src: $(src)"
    @echo "res: $(res)"
    
# output
src: main.c main.o test.c test.o test.h
res: test.c test.h

15. 函數(shù) (strip 去除多余空格)

.PHONY: all

src = test.c     ok.h data.dat
res = $(strip $(src))

all:
    @echo "src = $(src)"
    @echo "res = $(res)"
    
# output
src = test.c     ok.h data.dat
res = test.c ok.h data.dat

[1] 至簡(jiǎn)李云. 駕馭Makefile(準(zhǔn)完整版) 2009.08.25

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末石蔗,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子畅形,更是在濱河造成了極大的恐慌养距,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,430評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件日熬,死亡現(xiàn)場(chǎng)離奇詭異棍厌,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,406評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門耘纱,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)敬肚,“玉大人,你說(shuō)我怎么就攤上這事束析⊙蘼” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 167,834評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵员寇,是天一觀的道長(zhǎng)弄慰。 經(jīng)常有香客問(wèn)我,道長(zhǎng)蝶锋,這世上最難降的妖魔是什么曹动? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,543評(píng)論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮牲览,結(jié)果婚禮上墓陈,老公的妹妹穿的比我還像新娘。我一直安慰自己第献,他們只是感情好贡必,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,547評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著庸毫,像睡著了一般仔拟。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上飒赃,一...
    開(kāi)封第一講書(shū)人閱讀 52,196評(píng)論 1 308
  • 那天利花,我揣著相機(jī)與錄音,去河邊找鬼载佳。 笑死炒事,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的蔫慧。 我是一名探鬼主播挠乳,決...
    沈念sama閱讀 40,776評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼姑躲!你這毒婦竟也來(lái)了睡扬?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,671評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤黍析,失蹤者是張志新(化名)和其女友劉穎卖怜,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體阐枣,經(jīng)...
    沈念sama閱讀 46,221評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡马靠,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,303評(píng)論 3 340
  • 正文 我和宋清朗相戀三年牍戚,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片虑粥。...
    茶點(diǎn)故事閱讀 40,444評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡如孝,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出娩贷,到底是詐尸還是另有隱情第晰,我是刑警寧澤,帶...
    沈念sama閱讀 36,134評(píng)論 5 350
  • 正文 年R本政府宣布彬祖,位于F島的核電站茁瘦,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏储笑。R本人自食惡果不足惜甜熔,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,810評(píng)論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望突倍。 院中可真熱鬧腔稀,春花似錦、人聲如沸羽历。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,285評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)秕磷。三九已至诵闭,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間澎嚣,已是汗流浹背疏尿。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,399評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留易桃,地道東北人褥琐。 一個(gè)月前我還...
    沈念sama閱讀 48,837評(píng)論 3 376
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像颈抚,于是被迫代替她去往敵國(guó)和親踩衩。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,455評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容

  • 來(lái)自陳浩的一片老文贩汉,但絕對(duì)營(yíng)養(yǎng)。 示例工程:3 個(gè)頭文件*.h锚赤,和 8 個(gè) C 文件*.c匹舞。 初 編譯過(guò)程,源文件...
    周筱魯閱讀 4,700評(píng)論 0 17
  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理线脚,服務(wù)發(fā)現(xiàn)赐稽,斷路器叫榕,智...
    卡卡羅2017閱讀 134,695評(píng)論 18 139
  • makefile關(guān)系到整個(gè)工程的編譯規(guī)則,一個(gè)工程中的源文件不計(jì)其數(shù)姊舵,按其類型晰绎、功能、模塊分別放在若干的目錄當(dāng)中括丁,...
    Joe_HUST閱讀 1,883評(píng)論 0 3
  • 文件編譯過(guò)程 源文件首先經(jīng)過(guò)compile荞下,生成.o文件(linux下),object file史飞, 再把大量obj...
    暗黑破壞球嘿哈閱讀 1,648評(píng)論 0 0
  • 還有三四天的時(shí)間馬上就要過(guò)完2016年了构资,回想一下自己的2016年抽诉,有沒(méi)有實(shí)現(xiàn)自己年初制定的計(jì)劃呢?2016年國(guó)民...
    導(dǎo)圖知識(shí)卡片閱讀 560評(píng)論 0 4