我們也說說Android.mk(4) - 依賴:目標編程的模式

我們也說說Android.mk(4) - 依賴:目標編程的模式

另一種范式

我一直覺得猿推,Makefile確實是C/C++程序員的良配怕轿,因為Makefile所使用的兩種范式都是C/C++程序員不熟悉的勇皇,一種是函數(shù)式的思想雕凹,一種是依賴構(gòu)成的目標鏈的模式腐宋。

Makefile從最基本上來說喇完,可以抽象成下面這樣的:

    target ... : prerequisites ...
            command
            ...
            ...

如大家所熟悉的,這段的意義是:當(dāng)prerequisites有更新的時候蹬耘,執(zhí)行command命令芝雪。如果target是一個真實的目標,也就是對應(yīng)一個真實的文件综苔,那么就生成這個文件惩系。如果是偽目標,可以被用來做為一個入口如筛,比如clean堡牡,也可以成為一個真實目標的依賴。
可以明顯地分為兩個部分:一個是target依賴鏈的范式杨刨,這與過程式語言的C語言非常不同晤柄。用蔣軍的話講,跟Prolog有點像妖胀。有著它自己的一套邏輯系統(tǒng)可免。
后面的command,我們前面講了不少了做粤,我個人是希望大家以函數(shù)式的思想來寫。

我們落地到一個實際的例子中:

$(BUILT_SYSTEMIMAGE): $(FULL_SYSTEMIMAGE_DEPS) $(INSTALLED_FILES_FILE)
    $(call build-systemimage-target,$@)

這個$(BUILT_SYSTEMIMAGE),是個真實的目標捉撮,對應(yīng)了要生成的文件system.img怕品,如下:

BUILT_SYSTEMIMAGE := $(systemimage_intermediates)/system.img

下面來看看,system.img所依賴目標巾遭,先看第一個肉康,結(jié)果這一個實際上又是兩個:

FULL_SYSTEMIMAGE_DEPS := $(INTERNAL_SYSTEMIMAGE_FILES) $(INTERNAL_USERIMAGES_DEPS)

然后闯估,我們發(fā)現(xiàn)這個依賴在一層層地擴張:

INTERNAL_SYSTEMIMAGE_FILES := $(filter $(TARGET_OUT)/%, \
    $(ALL_PREBUILT) \
    $(ALL_COPIED_HEADERS) \
    $(ALL_GENERATED_SOURCES) \
    $(ALL_DEFAULT_INSTALLED_MODULES) \
    $(PDK_FUSION_SYSIMG_FILES) \
    $(RECOVERY_RESOURCE_ZIP))

擴張還在繼續(xù),比如吼和,對于ALL_PREBUILT涨薪,各個模塊不斷地把自己的東西增加進去:

ALL_PREBUILT += $(TARGET_OUT)/bin/monkey

其他的目標原理相通,這里就不多浪費篇幅了炫乓。
總而言之刚夺,這一大套目標中,只要有任何一個有變化末捣,system.img就要重新生成了侠姑。如何生成?在下一行中寫著呢:調(diào)用build-systemimage-target啊箩做。

Makefile寫作指南

目標式和函數(shù)式兩種范式都學(xué)好了莽红,下面是我們?nèi)绾谓M織材料來完成我們的工程的時候了。

  1. 先定義總目標
    Makefile的總的目的是輸出一個或多個結(jié)果文件邦邦,先把總的目標定義好安吁。
    然后假設(shè)子目標都已經(jīng)構(gòu)建好了,下面寫一個將這些中間產(chǎn)品變成最終目標的腳本燃辖。
    比如編譯一個簡單的C程序鬼店,總的目標是一個可執(zhí)行文件,最終加工時的材料是已經(jīng)編譯好的.o文件和輸入的第三方的庫文件等郭赐,我們先不管它們是如何編譯的薪韩,假設(shè)它們已經(jīng)做好了,我們只要寫一個鏈接的腳本就好了捌锭。
    像我們上面的system.img的例子俘陷,反正依賴多,就分門別類的列吧观谦,最終我們只需要把它們打個包就好了拉盾。
  2. 層層分解,逐步完成
    然后去尋找豁状,構(gòu)成這個大目標的第一層的構(gòu)件是什么捉偏,像上面我們所看過的一樣,逐層擴張泻红。
    對于C文件夭禽,這時候才考慮每一個.o是如何從源文件編譯的。
  3. 模塊化谊路、函數(shù)化
    上面兩步都是目標模式的讹躯,這一步開始搞函數(shù)模式了。將各目標中可重用的函數(shù)抽象出來,該分文件就分文件潮梯,該整理代碼就整理代碼等
  4. 測試調(diào)優(yōu)
    當(dāng)一個工程大到一定程度的時候骗灶,Makefile的可讀性會嚴重下降。
    這時候我們還是按目標式和函數(shù)式兩條主線來降低復(fù)雜度秉馏。目標是層次式的耙旦,我們可以一層一層地調(diào)試,比如先調(diào)從.c到.o的編譯過程萝究,再調(diào)將.o鏈接起來的總裝部分.
    哪一個子模塊出問題免都,就專門調(diào)那一部分的。
    對于功能部分糊肤,我們一直強調(diào)函數(shù)式思想就是希望琴昆,對于某一個確實性的輸入,能有一個確定性的輸出馆揉,沒有副作用业舍,這樣能夠?qū)⒄{(diào)試的難度降低,我們可以一個函數(shù)一個函數(shù)地調(diào)試升酣。
    Makefile的調(diào)試以打日志為主舷暮,還可以通過make -p來輸出完整的變量和目標列表。

make -p噩茄,看看make都做了些什么

下面是我在cygwin下的make -p的輸出結(jié)果的節(jié)選

Make工具的信息

首先是Make工具匯報下自己的基礎(chǔ)情況:

The files is:main.cpp
# GNU Make 4.1
# Built for x86_64-unknown-cygwin
# Copyright (C) 1988-2014 Free Software Foundation, Inc.
# License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
# This is free software: you are free to change and redistribute it.
# There is NO WARRANTY, to the extent permitted by law.

# make 數(shù)據(jù)基礎(chǔ)下面,打印在 Tue May  3 17:54:36 2016

變量

下面是變量的列表,包含我們自己定義的绩聘,也包含make自動為我們生成的沥割。

# 變量

# 'override' directive
GNUMAKEFLAGS := 
# 自動
<D = $(patsubst %/,%,$(dir $<))
# 自動
?F = $(notdir $?)
# 默認
.SHELLFLAGS := -c
# makefile (from 'Makefile', line 30)
result_findString2 := 
# makefile
MAKEFLAGS = p
# 默認
CWEAVE = cweave
# 自動
?D = $(patsubst %/,%,$(dir $?))
# 環(huán)境
!:: = ::\
# 自動
@D = $(patsubst %/,%,$(dir $@))
# 環(huán)境
HOMEDRIVE = C:
# 自動
@F = $(notdir $@)
# 自動
^D = $(patsubst %/,%,$(dir $^))
# makefile
CURDIR := /cygdrive/d/working/codeBlocks/Hello
# makefile
SHELL = /bin/sh
# 默認
RM = rm -f
# 默認
CO = co
...

目錄信息

# 目錄

# SCCS:無法對其進行 stat 操作。
# . (設(shè)備 114478965凿菩,i-節(jié)點 1688849860268365):10 文件机杜, 19 不可能.
# RCS:無法對其進行 stat 操作。

# 10 文件衅谷, 19 不可能在 3 目錄中椒拗。

隱含規(guī)則信息

# 隱含規(guī)則。

%.out:

%.a:

%.ln:

%.o:

%: %.o
#  recipe to execute (內(nèi)置):
    $(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -o $@

%.c:

%: %.c
#  recipe to execute (內(nèi)置):
    $(LINK.c) $^ $(LOADLIBES) $(LDLIBS) -o $@

%.ln: %.c
#  recipe to execute (內(nèi)置):
    $(LINT.c) -C$* $<

%.o: %.c
#  recipe to execute (內(nèi)置):
    $(COMPILE.c) $(OUTPUT_OPTION) $<

%.cc:

%: %.cc
#  recipe to execute (內(nèi)置):
    $(LINK.cc) $^ $(LOADLIBES) $(LDLIBS) -o $@

%.o: %.cc
#  recipe to execute (內(nèi)置):
    $(COMPILE.cc) $(OUTPUT_OPTION) $<

%.C:

%: %.C
#  recipe to execute (內(nèi)置):
    $(LINK.C) $^ $(LOADLIBES) $(LDLIBS) -o $@

%.o: %.C
#  recipe to execute (內(nèi)置):
    $(COMPILE.C) $(OUTPUT_OPTION) $<

%.cpp:

%: %.cpp
#  recipe to execute (內(nèi)置):
    $(LINK.cpp) $^ $(LOADLIBES) $(LDLIBS) -o $@

%.o: %.cpp
#  recipe to execute (內(nèi)置):
    $(COMPILE.cpp) $(OUTPUT_OPTION) $<

%.p:

%: %.p
#  recipe to execute (內(nèi)置):
    $(LINK.p) $^ $(LOADLIBES) $(LDLIBS) -o $@

%.o: %.p
#  recipe to execute (內(nèi)置):
    $(COMPILE.p) $(OUTPUT_OPTION) $<
...

文件目標和假目標

# 文件

# 不是一個目標:
.web.p:
#  Builtin rule
#  對隱含規(guī)則的搜索尚未完成获黔。
#  從不檢查修改時間蚀苛。
#  文件尚未被更新。
#  recipe to execute (內(nèi)置):
    $(TANGLE) $<

# 不是一個目標:
.l.r:
#  Builtin rule
#  對隱含規(guī)則的搜索尚未完成玷氏。
#  從不檢查修改時間堵未。
#  文件尚未被更新。
#  recipe to execute (內(nèi)置):
    $(LEX.l) $< > $@ 
     mv -f lex.yy.r $@

all8:
#  假目標 (.PHONY的前提)盏触。
#  對隱含規(guī)則的搜索尚未完成渗蟹。
#  文件不存在侦厚。
#  文件尚未被更新。
#  recipe to execute (from 'Makefile', line 66):
    @echo $(filter-out default interpreter jit optimizing,xoc)
    @echo $(filter-out default interpreter jit optimizing,default)

all9:
#  假目標 (.PHONY的前提)拙徽。
#  對隱含規(guī)則的搜索尚未完成。
#  文件不存在诗宣。
#  文件尚未被更新膘怕。
#  recipe to execute (from 'Makefile', line 75):
    $(eval ARCH_OF_BOOT_OAT := $(lastword $(subst /, ,$(dir $(BOOT_ART_SRC)))))
    $(eval OAT_TEMP := $(PRODUCT_OUT)/data/dalvik-cache/temp-oat/system/framework/$(ARCH_OF_BOOT_OAT))
    $(eval OAT_SRC := $(patsubst %.art,%.oat,$(BOOT_ART_SRC)))
    $(eval OAT_DIST := $(patsubst %.art,%.oat,$(BOOT_ART_DST)))
    @echo $(ARCH_OF_BOOT_OAT)
    @echo $(OAT_TEMP)
    @echo $(OAT_SRC)
    @echo $(OAT_DIST)
...
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市召庞,隨后出現(xiàn)的幾起案子岛心,更是在濱河造成了極大的恐慌,老刑警劉巖篮灼,帶你破解...
    沈念sama閱讀 212,884評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件忘古,死亡現(xiàn)場離奇詭異,居然都是意外死亡诅诱,警方通過查閱死者的電腦和手機髓堪,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,755評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來娘荡,“玉大人干旁,你說我怎么就攤上這事∨阢澹” “怎么了争群?”我有些...
    開封第一講書人閱讀 158,369評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長大年。 經(jīng)常有香客問我换薄,道長翔试,這世上最難降的妖魔是什么轻要? 我笑而不...
    開封第一講書人閱讀 56,799評論 1 285
  • 正文 為了忘掉前任,我火速辦了婚禮遏餐,結(jié)果婚禮上伦腐,老公的妹妹穿的比我還像新娘。我一直安慰自己失都,他們只是感情好柏蘑,可當(dāng)我...
    茶點故事閱讀 65,910評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著粹庞,像睡著了一般咳焚。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上庞溜,一...
    開封第一講書人閱讀 50,096評論 1 291
  • 那天革半,我揣著相機與錄音碑定,去河邊找鬼。 笑死又官,一個胖子當(dāng)著我的面吹牛延刘,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播六敬,決...
    沈念sama閱讀 39,159評論 3 411
  • 文/蒼蘭香墨 我猛地睜開眼碘赖,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了外构?” 一聲冷哼從身側(cè)響起普泡,我...
    開封第一講書人閱讀 37,917評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎审编,沒想到半個月后撼班,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,360評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡垒酬,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,673評論 2 327
  • 正文 我和宋清朗相戀三年砰嘁,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片伤溉。...
    茶點故事閱讀 38,814評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡般码,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出乱顾,到底是詐尸還是另有隱情板祝,我是刑警寧澤,帶...
    沈念sama閱讀 34,509評論 4 334
  • 正文 年R本政府宣布走净,位于F島的核電站券时,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏伏伯。R本人自食惡果不足惜橘洞,卻給世界環(huán)境...
    茶點故事閱讀 40,156評論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望说搅。 院中可真熱鬧炸枣,春花似錦、人聲如沸弄唧。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,882評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽候引。三九已至侯养,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間澄干,已是汗流浹背逛揩。 一陣腳步聲響...
    開封第一講書人閱讀 32,123評論 1 267
  • 我被黑心中介騙來泰國打工柠傍, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人辩稽。 一個月前我還...
    沈念sama閱讀 46,641評論 2 362
  • 正文 我出身青樓惧笛,卻偏偏與公主長得像,于是被迫代替她去往敵國和親逞泄。 傳聞我的和親對象是個殘疾皇子徐紧,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,728評論 2 351

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

  • 來自陳浩的一片老文,但絕對營養(yǎng)炭懊。 示例工程:3 個頭文件*.h,和 8 個 C 文件*.c拂檩。 初 編譯過程侮腹,源文件...
    周筱魯閱讀 4,692評論 0 17
  • makefile關(guān)系到整個工程的編譯規(guī)則,一個工程中的源文件不計其數(shù)稻励,按其類型父阻、功能、模塊分別放在若干的目錄當(dāng)中望抽,...
    Joe_HUST閱讀 1,876評論 0 3
  • @(linux 編程)[開發(fā)技能, 工具使用] What is GNU Make Make 是控制工程中通過源碼生...
    orientlu閱讀 11,331評論 0 26
  • 本文章介紹了makefile跟kconfig文件加矛,包括編譯過程與makefile編碼規(guī)則。 編譯過程:我們在進行l(wèi)...
    超低空閱讀 17,431評論 0 5
  • 我以前因為喜歡嚴蕊煤篙,討厭朱熹斟览,真的,那時候也就上高中辑奈,偶然間看到一首詞苛茂,是這樣寫的: 不是愛風(fēng)塵,似被前緣誤 花開...
    秋倏閱讀 883評論 1 2