android开发笔记之Makefile(一)
指定編譯文件
指定特定的Makefile,你可以使用make的“-f”和“–file”參數,如:make -f Make.Linux或make –file Make.AIX
?
?make -f test.mk1
有這個命令后,我們就可以調試我們的命令了。
?
注釋
Makefile中,“#”是注釋符
?
# -------------------------------------------------------------
#???????????????????? START
# -------------------------------------------------------------123
?
變量
變量的定義:在Makefile中我們要定義一系列的變量,變量一般都是字符串,這個有點你C語言中的宏,當Makefile被執行時,其中的變量都會被擴展到相應的引用位置上。
變量是大小寫敏感的,“foo”、“Foo”和“FOO”是三個不同的變量名。傳統的Makefile的變量名是全大寫的命名方式,但我推薦使用大小寫搭配的變量名,如:MakeFlags。這樣可以避免和系統的變量沖突,而發生意外的事情。有一些變量是很奇怪字串,如“<”、“ <”、“<”、“@”等,這些是自動化變量,我會在后面介紹。
?
變量基礎
變量在聲明時需要給予初值,而在使用時,需要給在變量名前加上“$”符號,但最好用小括號“()”或是大括號“{}”把變量給包括起來。如果你要使用真實的“$”字符,那么你需要用“$$”來表示。
以下是依賴或定義的變量列表,可以定義其他變量為自己使用,但是NDK編譯系統保留下列變量名:
以 LOCAL_開頭的名字(例如 LOCAL_MODULE)?
以 PRIVATE_, NDK_ 或 APP_開頭的名字(內部使用)
小寫名字(內部使用,例如‘my-dir’)
如果為了方便在 Android.mk 中定義自己的變量,建議使用 MY_前綴:
?
#-----------------start----------------
my_value = hello
$(warning ----my_value:$(my_value))
#-----------------end----------------1234
輸出:
?
test.mk:4: ----my_value:hello1
注意:?
‘:=’是賦值的意思;’+=’是追加的意思;‘$’表示引用某變量的值
?
變量中的變量
在定義變量的值時,我們可以使用其它變量來構造變量的值,在Makefile中有兩種方式來在用變量定義變量的值。
先看第一種方式,也就是簡單的使用“=”號,在“=”左側是變量,右側是變量的值,右側變量的值可以定義在文件的任何一處,也就是說,右側中的變量不一定非要是已定義好的值,其也可以使用后面定義的值。如:
?
#-----------------start----------------
foo = $(bar)
bar = $(ugh)
ugh = Huh
$(warning -----foo:$(foo))
#-----------------end----------------1234567
輸出:
?
test.mk:6: -----foo:Huh1
可見,變量是可以使用后面的變量來定義的,這個功能有好的地方,也有不好的地方,好的地方是,我們可以把變量的真實值推到后面來定義,但這種形式也有不好的地方,那就是遞歸定義,如:
?
A = $(B)
B = $(A)12
這會讓make陷入無限的變量展開過程中去,當然,我們的make是有能力檢測這樣的定義,并會報錯。還有就是如果在變量中使用函數,那么,這種方式會讓我們的make運行時非常慢,更糟糕的是,他會使用得兩個make的函數“wildcard”和“shell”發生不可預知的錯誤。因為你不會知道這兩個函數會被調用多少次。
為了避免上面的這種方法,我們可以使用make中的另一種用變量來定義變量的方法。這種方法使用的是“:=”操作符
?
冒號等于操作符–”:=“
這種方法,前面的變量不能使用后面的變量,只能使用前面已定義好了的變量。
?
#-----------------start----------------
x := foo
y := $(x) bar
x := later
$(warning -----y:$(y))
$(warning -----x:$(x))
y_02 := $(x_02) bar
x_02 := foo
$(warning -----y_02:$(y_02))
$(warning -----x_02:$(x_02))
#-----------------end----------------12345678910111213
輸出:
?
test.mk:6: -----y:foo bar
test.mk:7: -----x:later
test.mk:11: -----y_02: bar
test.mk:12: -----x_02:foo1234
?
問等于操作符–“?=”
還有一個比較有用的操作符是“?=”,先看示例:
?
FOO ?= bar1
其含義是,如果FOO沒有被定義過,那么變量FOO的值就是“bar”,如果FOO先前被定義過,那么這條語將什么也不做,其等價于:
?
ifeq ($(origin FOO), undefined)
FOO = bar
endif123
?
#-----------------start----------------
x ?= test
$(warning -----x:$(x))
x=hello
x ?= 100
$(warning -----x:$(x))
#-----------------end----------------1234567
輸出:
?
test.mk:3: -----x:test
test.mk:6: -----x:hello12
?
變量值的替換
?
$(var:a=b)
${var:a=b}12
替換變量中的共有的部分,其意思是,把變量“var”中所有以“a”字串“結尾”的“a”替換成“b”字串。這里的“結尾”意思是“空格”或是“結束符”。
?
#-----------------start----------------
var=a.o b.o c.o
bar=$(var:.o=.t)
$(warning -----bar:$(bar))
#-----------------end----------------12345
輸出:
?
test.mk:4: -----bar:a.t b.t c.t1
?
變量替換的技術–“靜態模式”
這依賴于被替換字串中的有相同的模式,模式中必須包含一個“%”字符
?
#-----------------start----------------
var=a.o b.o c.o
bar=$(var:%.o=%.t)
$(warning -----bar:$(bar))
#-----------------end----------------12345
輸出:
?
test.mk:4: -----bar:a.t b.t c.t1
?
追加變量值–+=
我們可以使用“+=”操作符給變量追加值。
?
#-----------------start----------------
var=aaa bbb ccc
var+=ddd
$(warning -----var:$(var))
#-----------------end----------------12345
輸出:
?
test.mk:4: -----var:aaa bbb ccc ddd1
?
override 指示符
如果有變量是通常make的命令行參數設置的,那么Makefile中對這個變量的賦值會被忽略。如果你想在Makefile中設置這類參數的值,那么,你可以使用“override”指示符。其語法是:
?
override <variable> = <value>
override <variable> := <value>
override <variable> += <more text>123
./build/kati/testcase/override_define.mk
?
override CC := gcc
override? AS = as12
?
#-----------------start----------------
$(warning -----var_01:$(var_01))
var_01 = test_01
$(warning -----var_01:$(var_01))
override var_01 = test_01
$(warning -----var_01:$(var_01))
#-----------------end----------------1234567
編譯命令
?
make var_01=test?? -f test.mk 1
輸出:
?
test.mk:2: -----var_01:test
test.mk:4: -----var_01:test
test.mk:6: -----var_01:test_01123
?
輸出:
error,warning 和 info
使用方式:
?
$(error string)
$(warningstring)
$(info string) 123
error:直接讓make報錯停止,并打出信息
warning :這個函數很像error函數,只是它并不會讓make退出,只是輸出一段警告信息,而make繼續執行
Info和warning類似。
樣例:
?
#-----------------start----------------
my_value = hello
$(warning ---warning-my_value:$(my_value))
$(info ----info-my_value:$(my_value))
$(error ----error-my_value:$(my_value))
#-----------------end----------------123456
測試結果:
?
test.mk:3: ---warning-my_value:hello
----info-my_value:hello
test.mk:5: *** ----error-my_value:hello。 停止。123
從測試結果來看,我們建議一般輸出信息使用warning,因為這會打印輸出信息的具體文件位置,而特別重要的變量,關系到編譯的結果的信息,我們才使用error打印信息。
?
條件判斷
?
ifeq ifneq
ifeq 比較參數“arg1”和“arg2”的值是否相同,如果相同則為真。
?
ifeq (<arg1>, <arg2> )
ifeq '<arg1>' '<arg2>'
ifeq "<arg1>" "<arg2>"
ifeq "<arg1>" '<arg2>'
ifeq '<arg1>' "<arg2>"12345
ifneq和ifeq類似:
?
ifneq (<arg1>, <arg2> )
ifneq '<arg1>' '<arg2>'
ifneq "<arg1>" "<arg2>"
ifneq "<arg1>" '<arg2>'
ifneq '<arg1>' "<arg2>"12345
使用格式為:
?
ifeq (arg1,arg2)
$(warning ----)
else
$(warning ----)
endif12345
?
ifeq (arg1,arg2)
$(warning ----)
else ifeq (arg3,arg4)
$(warning ----)
endif12345
測試樣例:
?
#-----------------start----------------
my_value_01 = hello_1
my_value_02 = hello_2
ifeq ($(my_value_01),$(my_value_02))
$(warning ----my_value_01==my_value_02)
else
$(warning ----my_value_01!=my_value_02)
endif
my_value_02 = hello_1
ifeq ($(my_value_01),$(my_value_02))
$(warning ----my_value_01==my_value_02)
else
$(warning ----my_value_01!=my_value_02)
endif
#-----------------end----------------1234567891011121314151617
輸出:
?
test.mk:8: ----my_value_01!=my_value_02
test.mk:13: ----my_value_01==my_value_0212
如果定義TINNO_LANIX_DATACON_ALERT為true,就內置LanixDataconAlert:
?
TINNO_LANIX_DATACON_ALERT := true
ifeq ($(strip $(TINNO_LANIX_DATACON_ALERT)),true)
? PRODUCT_PACKAGES += LanixDataconAlert
endif1234
如果定義PRODUCT_PREBUILT_WEBVIEWCHROMIUM為yes,就包含vendor/google/gms/apps/WebViewGoogle/overlay。
?
PRODUCT_PREBUILT_WEBVIEWCHROMIUM := yes
ifeq ($(PRODUCT_PREBUILT_WEBVIEWCHROMIUM),yes)
PRODUCT_PACKAGES += WebViewGoogle
# The following framework overlay must be included if prebuilt WebViewGoogle.apk is used
PRODUCT_PACKAGE_OVERLAYS += vendor/google/gms/apps/WebViewGoogle/overlay
endif123456
如果為eng版本就不內置SetupWizard,如果不為eng就內置SetupWizard。
?
ifeq ($(strip $(TARGET_BUILD_VARIANT)),eng)
#$(warning ----eng---no--need---setupwizard----)
else
PRODUCT_PACKAGES += \
??? SetupWizard
endif123456
如果TARGET_USES_QTIC為空,就將TARGET_USES_QTIC置為true
?
ifeq ($(strip $(TARGET_USES_QTIC)),)
?TARGET_USES_QTIC := true
?endif123
如果PROJECT_NAME不為空,就復制對應vendor/tinno/(TARGETPRODUCT)/(PROJECT_NAME)/copy_custom_files文件,如果PROJECT_NAME為空,就對應復制vendor/tinno/$(TARGET_PRODUCT)/trunk/copy_custom_files文件
?
#wangyanhui add for custom copy_files
ifneq ($(strip $(PROJECT_NAME)),)
COPY_FILES_PATH := vendor/tinno/$(TARGET_PRODUCT)/$(PROJECT_NAME)/copy_custom_files
$(shell cp -rf? $(COPY_FILES_PATH)/*?? .)
else
COPY_FILES_PATH := vendor/tinno/$(TARGET_PRODUCT)/trunk/copy_custom_files
$(shell cp -rf? $(COPY_FILES_PATH)/*?? .)
endif
#copy_files end123456789
?
ifdef ifndef
?
ifdef <variable-name>1
如果變量的值非空,那到表達式為真。否則,表達式為假。當然,同樣可以是一個函數的返回值。
注意,ifdef只是測試一個變量是否有值,其并不會把變量擴展到當前位置。還是來看例子:
?
#-----------------start----------------
bar =
foo = $(bar)
ifdef foo
frobozz = yes
else
frobozz = no
endif
$(warning ----frobozz=$(frobozz))
foo =
ifdef foo
frobozz = yes
else
frobozz = no
endif
$(warning ----frobozz=$(frobozz))
#-----------------end----------------123456789101112131415161718
輸出:
?
test.mk:9: ----frobozz=yes
test.mk:17: ----frobozz=no12
在*.c文件中定義:
?
#ifndef WIFI_SDIO_IF_DRIVER_MODULE_PATH
#define WIFI_SDIO_IF_DRIVER_MODULE_PATH "/system/lib/modules/librasdioif.ko"
#endif123
在mk文件中:
?
ifdef WIFI_DRIVER_MODULE_PATH
LOCAL_CFLAGS += -DWIFI_DRIVER_MODULE_PATH=\"$(WIFI_DRIVER_MODULE_PATH)\"
endif123
?
foreach 循環函數
?
$(foreach <var>,<list>,<text> )1
這個函數的意思是,把參數中的單詞逐一取出放到參數所指定的變量中,然后再執行所包含的表達式。每一次會返回一個字符串,循環過程中,的所返回的每個字符串會以空格分隔,最后當整個循環結束時,所返回的每個字符串所組成的整個字符串(以空格分隔)將會是foreach函數的返回值。
所以,最好是一個變量名,可以是一個表達式,而中一般會使用這個參數來依次枚舉中的單詞。
?
#-----------------start----------------
name:=a b c d
file:=$(foreach i,$(name),$(i).java)
$(warning -----file:$(file))
#-----------------end----------------12345
輸出:
?
test.mk:4: -----file:a.java b.java c.java d.java1
?
include–引用其它的Makefile
在Makefile使用include關鍵字可以把別的Makefile包含進來,這很像C語言的#include,被包含的文件會原模原樣的放在當前文件的包含位置。
?
include $(LOCAL_PATH)/models/Android.mk
include foo.make a.mk b.mk c.mk e.mk f.mk12
?
Makefile 書寫命令
? 每條規則中的命令和操作系統Shell的命令行是一致的。make會一按順序一條一條的執行命令,每條命令的開頭必須以[Tab]鍵開頭,除非,命令是緊跟在依賴規則后面的分號后的。在命令行之間中的空格或是空行會被忽略,但是如果該空格或空行是以Tab鍵開頭的,那么make會認為其是一個空命令。
1
?
顯示命令–”@”
通常,make會把其要執行的命令行在命令執行前輸出到屏幕上。當我們用“@”字符在命令行前,那么,這個命令將不被make顯示出來。
如果make執行時,帶入make參數“-n”或“–just-print”,那么其只是顯示命令,但不會執行命令,這個功能很有利于我們調試我們的Makefile,看看我們書寫的命令是執行起來是什么樣子的或是什么順序的。
而make參數“-s”或“–slient”則是全面禁止命令的顯示。
例如:
?
#-----------------start----------------
.PHONY: clean
clean:
??? @echo "make clean start"
??? @mkdir test_temp.mk
??? @rm -rf test_temp.mk
??? @echo "make clean success"
#-----------------end----------------12345678
注意,@前一定要是TAB鍵
輸出:
?
android@tesdt-Precision-T1700:/SSD/test$ make -f test.mk
make clean start
make clean success
android@tesdt-Precision-T1700:/SSD/test$ make -n? -f test.mk
echo "make clean start"
mkdir test_temp.mk
rm -rf test_temp.mk
echo "make clean success"
12345678910
/build/core/main.mk
?
.PHONY: clean
clean:
??? @rm -rf $(OUT_DIR)/*
??? @rm -rf $(PWD)/vendor/myos/common/*
??? @echo "Entire build directory removed."12345
?
命令出錯
每當命令運行完后,make會檢測每個命令的返回碼,如果命令返回成功,那么make會執行下一條命令,當規則中所有的命令成功返回后,這個規則就算是成功完成了。如果一個規則中的某個命令出錯了(命令退出碼非零),那么make就會終止執行當前規則,這將有可能終止所有規則的執行。
??? 有些時候,命令的出錯并不表示就是錯誤的。例如mkdir命令,我們一定需要建立一個目錄,如果目錄不存在,那么mkdir就成功執行,萬事大吉,如果目錄存在,那么就出錯了。我們之所以使用mkdir的意思就是一定要有這樣的一個目錄,于是我們就不希望mkdir出錯而終止規則的運行。
?? 為了做到這一點,忽略命令的出錯,我們可以在Makefile的命令行前加一個減號“-”(在Tab鍵之后),標記為不管命令出不出錯都認為是成功的。如:
?
clean:
??? -rm -f *.o12
還有一個全局的辦法是,給make加上“-i”或是“–ignore-errors”參數,那么,Makefile中所有命令都會忽略錯誤。而如果一個規則是以“.IGNORE”作為目標的,那么這個規則中的所有命令將會忽略錯誤。這些是不同級別的防止命令出錯的方法,你可以根據你的不同喜歡設置。
還有一個要提一下的make的參數的是“-k”或是“–keep-going”,這個參數的意思是,如果某規則中的命令出錯了,那么就終目該規則的執行,但繼續執行其它規則。
?
使用函數
在Makefile中可以使用函數來處理變量,從而讓我們的命令或是規則更為的靈活和具有智能。make所支持的函數也不算很多,不過已經足夠我們的操作了。函數調用后,函數的返回值可以當做變量來使用。
函數調用,很像變量的使用,也是以“$”來標識的,其語法如下:
?
$(<function> <arguments> )
${<function> <arguments>}12
這里,就是函數名,make支持的函數不多。是函數的參數,參數間以逗號“,”分隔,而函數名和參數之間以“空格”分隔。函數調用以“”開頭,以圓括號或花括號把函數名和參數括起。感覺很像一個變量,是不是?函數中的參數可以使用變量,為了風格的統一,函數和變量的括號最好一樣,如使用“ ”開頭,以圓括號或花括號把函數名和參數括起。感覺很像一個變量,是不是?函數中的參數可以使用變量,為了風格的統一,函數和變量的括號最好一樣,如使用“”開頭,以圓括號或花括號把函數名和參數括起。感覺很像一個變量,是不是?函數中的參數可以使用變量,為了風格的統一,函數和變量的括號最好一樣,如使用“(subst a,b,(x))”這樣的形式,而不是“ (x))”這樣的形式,而不是“(x))”這樣的形式,而不是“(subst a,b,${x})”的形式。因為統一會更清楚,也會減少一些不必要的麻煩。
?
字符串處理函數
?
strip 去空格函數
?
$(strip string)1
功能:去掉字串中開頭和結尾的空字符。?
返回:返回被去掉空格的字符串值。
?
#-----------------start----------------
my_value = hello
$(warning ----my_value:$(strip $(my_value)))
#-----------------end----------------1234
輸出:
?
test.mk:3: ----my_value:hello1
?
$(strip a b c )1
把字串“a b c ”去到開頭和結尾的空格,結果是“a b c”。
?
#-----------------start----------------
my_value_01 = hello_1
my_value_02 = hello_2
my_value_03 = hello_3
$(warning ----:$(strip $(my_value_01) $(my_value_02) $(my_value_03)))
#-----------------end----------------1234567
輸出:
?
test.mk:6: ----:hello_1 hello_2 hello_31
?
findstring–查找字符串函數
?
findstring string_a, string_Src1
功能:從string_Src中查找string_a?
返回:如果查找到string_a,返回string_a,如果沒有查找到,返回空字符串。
樣例:
?
#-----------------start----------------
$(warning ----$(findstring a,a b c))
$(warning ----$(findstring a,b c))
#-----------------end----------------1234
輸出:
?
test.mk:2: ----a
test.mk:3: ----12
?
WIKO_SOUND_VERSION:=wiko_sound_1_3
ifneq ($(strip $(WIKO_SOUND_VERSION)),)
$(warning $(WIKO_SOUND_VERSION))
ifeq ($(findstring _1_0, $(strip $(WIKO_SOUND_VERSION))),_1_0)
else ifeq ($(findstring _1_1, $(strip $(WIKO_SOUND_VERSION))),_1_1)
findstring 7731g,$(CONFIGURE_SRC)123456789
?
filter 和 filter-out–過濾函數和反過濾函數
filter
?
$(filter word1 word2,$(VARIANTS))1
判斷變量VARIANTS中是否包含word1和 word2,如果包含就把VARIANTS中包含的word1和word2之外的過濾掉
?
VARIANTS := mon tue wed thu fri sat sun
DAY := $(filter sat sun,$(VARIANTS))
$(info $(DAY))123
輸出結果為:
?
sat sun1
filter-out
?
$(filter-out word1 word2,$(VARIANTS))1
判斷變量VARIANTS中是否包含word1和 word2,如果包含就把VARIANTS中包含的word1和word2過濾掉,其余的全部保留
示例:
?
VARIANTS := mon tue wed thu fri sat sun
DAY := $(filter-out sat sun,$(VARIANTS))
$(info $(DAY))123
輸出結果為:
?
mon tue wed thu fri1
?
subst -字符串替換
?
$(subst <from>,<to>,<text> )1
名稱:字符串替換函數——subst。
功能:把字串中的字符串替換成。
返回:函數返回被替換過后的字符串。
?
#-----------------start----------------
$(warning ----$(subst o,e,football))
#-----------------end----------------123
輸出:
?
test.mk:2: ----feetball1
?
patsubst–模式字符串替換函數
?
$(patsubst <pattern>,<replacement>,<text> )1
功能:查找中的單詞(單詞以“空格”、“Tab”或“回車”“換行”分隔)是否符合模式,如果匹配的話,則以替換。這里,可以包括通配符“%”,表示任意長度的字串。如果中也包含“%”,那么,中的這個“%”將是中的那個“%”所代表的字串。(可以用“\”來轉義,以“\%”來表示真實含義的“%”字符)返回:函數返回被替換過后的字符串。
?
#-----------------start----------------
$(warning ----$(patsubst %.c,%.o,x.c.c bar.c)))
#-----------------end----------------123
輸出:
?
test.mk:2: ----x.c.o bar.o1
?
sort–排序函數
?
$(sort <list> )1
功能:給字符串中的單詞排序(升序)。
返回:返回排序后的字符串。
備注:sort函數會去掉中相同的單詞。
?
#-----------------start----------------
$(warning ----$(sort foo bar lose))
$(warning ----$(sort foo bar bar lose))
#-----------------end----------------1234
輸出:
?
test.mk:2: ----bar foo lose
test.mk:3: ----bar foo lose12
?
word–取單詞函數
?
$(word <n>,<text> )1
功能:取字符串中第個單詞。(從一開始)
返回:返回字符串中第個單詞。如果比中的單詞數要大,那么返回空
?
#-----------------start----------------
$(warning ----$(word 1, foo bar baz))
#-----------------end----------------123
輸出:
?
test.mk:2: ----foo1
?
wordlist–取單詞串函數
?
$(wordlist <s>,<e>,<text> )1
功能:從字符串中取從開始到的單詞串。和是一個數字。
返回:返回字符串中從到的單詞字串。如果比中的單詞數要大,那么返回空字符串。如果大于的單詞數,那么返回從開始,到結束的單詞串。
?
#-----------------start----------------
$(warning ----$(wordlist 2, 3, foo bar2 bar3))
#-----------------end----------------123
輸出:
?
test.mk:2: ----bar2 bar31
?
words–單詞個數統計函數
?
$(words <text> )1
功能:統計中字符串中的單詞個數。
返回:返回中的單詞數。
備注:如果我們要取中最后的一個單詞,我們可以這樣:(word (word(word (words??
), )。
?
#-----------------start----------------
string = foo bar baz
$(warning ----$(words $(string)))
$(warning ----$(word $(words $(string)),$(string)))
#-----------------end----------------12345
輸出:
?
test.mk:3: ----3
test.mk:4: ----baz12
?
firstword–首單詞函數
?
$(firstword <text> )1
功能:取字符串中的第一個單詞。
返回:返回字符串的第一個單詞。
?
#-----------------start----------------
string = foo bar baz
$(warning ----$(firstword? $(string)))
#-----------------end----------------1234
輸出:
?
test.mk:3: ----foo1
?
文件名操作函數
?
取目錄函數——dir
?
$(dir <names...> )1
功能:從文件名序列中取出目錄部分。目錄部分是指最后一個反斜杠(“/”)之前的部分。如果沒有反斜杠,那么返回“./”。
返回:返回文件名序列的目錄部分。
示例: $(dir src/foo.c hacks)返回值是“src/ ./”。
?
#-----------------start----------------
$(warning -----dir:$(dir src/hellp.java test.sh))
#-----------------end----------------123
輸出:
?
test.mk:3: -----dir:src/ ./1
?
取文件函數——notdir
?
$(notdir <names...> )1
功能:從文件名序列中取出非目錄部分。非目錄部分是指最后一個反斜杠(“/”)之后的部分。
返回:返回文件名序列的非目錄部分。
?
#-----------------start----------------
$(warning -----notdir:$(notdir src/hellp.java test.sh))
#-----------------end----------------123
輸出:
?
test.mk:2: -----notdir:hellp.java test.sh1
?
取后綴函數——suffix
?
$(suffix <names...> )1
功能:從文件名序列中取出各個文件名的后綴。
返回:返回文件名序列的后綴序列,如果文件沒有后綴,則返回空字串。
?
#-----------------start----------------
$(warning -----suffix:$(suffix src/hellp.java test.sh))
#-----------------end----------------123
輸出:
?
test.mk:2: -----suffix:.java .sh1
?
取前綴函數——basename
?
$(basename <names...> )1
功能:從文件名序列中取出各個文件名的前綴部分。
返回:返回文件名序列的前綴序列,如果文件沒有前綴,則返回空字串。
?
#-----------------start----------------
$(warning -----basename:$(basename src/hellp.java test.sh))
#-----------------end----------------123
輸出:
?
test.mk:2: -----basename:src/hellp test1
?
加后綴函數——addsuffix
?
$(addsuffix <suffix>,<names...> )1
功能:把后綴加到中的每個單詞后面。
返回:返回加過后綴的文件名序列。
?
#-----------------start----------------
$(warning -----addsuffix:$(addsuffix .java, src/hellp test))
#-----------------end----------------123
輸出:
?
test.mk:2: -----addsuffix:src/hellp.java test.java1
?
加前綴函數——addprefix
?
$(addprefix <prefix>,<names...> )1
功能:把前綴加到中的每個單詞后面。
返回:返回加過前綴的文件名序列。
?
#-----------------start----------------
$(warning -----addprefix:$(addprefix src/, hellp.java test.java))
#-----------------end----------------123
輸出:
?
test.mk:2: -----addprefix:src/hellp.java src/test.java1
?
連接函數——join
?
$(join <list1>,<list2> )1
功能:把中的單詞對應地加到的單詞后面。
返回:返回連接過后的字符串。
?
#-----------------start----------------
$(warning -----join:$(join aaa, b))
$(warning -----join:$(join a, bbb))
$(warning -----join:$(join aaabbb,1112222333444))
#-----------------end----------------123456
輸出:
?
test.mk:2: -----join:aaab
test.mk:3: -----join:abbb
test.mk:5: -----join:aaabbb1112222333444123
?
call函數
call函數是唯一一個可以用來創建新的參數化的函數。你可以寫一個非常復雜的表達式,這個表達式中,你可以定義許多參數,然后你可以用call函數來向這個表達式傳遞參數。其語法是:
?
$(call <expression>,<parm1>,<parm2>,<parm3>...)1
當 make執行這個函數時,參數中的變量,如(1), (1),(1),(2),$(3)等,會被參數,,依次取代。而的返回值就是 call函數的返回值。
?
#-----------------start----------------
reverse=$(1)$(2)
result=$(call reverse,a,b)
$(warning -----result:$(result))
#-----------------end----------------12345
輸出:
?
test.mk:4: -----result:ab1
?
shell函數
shell 函數也不像其它的函數。顧名思義,它的參數應該就是操作系統Shell的命令。它和反引號“`”是相同的功能。這就是說,shell函數把執行操作系統命令后的輸出作為函數返回。于是,我們可以用操作系統命令以及字符串處理命令awk,sed等等命令來生成一個變量。
?
#-----------------start----------------
result=$(shell cat test.mk)
$(warning -----result:$(result))
result=$(shell echo *.mk)
$(warning -----result:$(result))
#-----------------end----------------123456
輸出:
?
test.mk:3: -----result:#-----------------start---------------- result=$(shell cat test.mk) $(warning -----result:$(result)) result=$(shell echo *.mk) $(warning -----result:$(result)) #-----------------end----------------
test.mk:5: -----result:test _02.mk test.mk12
注意,這個函數會新生成一個Shell程序來執行命令,所以你要注意其運行性能,如果你的Makefile中有一些比較復雜的規則,并大量使用了這個函數,那么對于你的系統性能是有害的。特別是Makefile的隱晦的規則可能會讓你的shell函數執行的次數比你想像的多得多。
?
make 的運行
一般來說,最簡單的就是直接在命令行下輸入make命令,make命令會找當前目錄的makefile來執行,一切都是自動的。但也有時你也許只想讓 make重編譯某些文件,而不是整個工程,而又有的時候你有幾套編譯規則,你想在不同的時候使用不同的編譯規則,等等。本章節就是講述如何使用make命令的。
?
make的退出碼
make命令執行后有三個退出碼:
0 —— 表示成功執行。
1 —— 如果make運行時出現任何錯誤,其返回1。
2 —— 如果你使用了make的“-q”選項,并且make使得一些目標不需要更新,那么返回2。
?
指定Makefile
GNU make找尋默認的Makefile的規則是在當前目錄下依次找三個文件–“GNUmakefile”,“makefile”和“Makefile”。其按順序找這三個文件,一旦找到,就開始讀取這個文件并執行。
當前,我們也可以給make命令指定一個特殊名字的Makefile。要達到這個功能,我們要使用make的“-f”或是“–file”參數(“– makefile”參數也行)。
例如,我們有個makefile的名字是“hchen.mk”,那么,我們可以這樣來讓make來執行這個文件:
?
make –f hchen.mk1
如果在make的命令行是,你不只一次地使用了“-f”參數,那么,所有指定的makefile將會被連在一起傳遞給make執行。
?
make的參數
?
make -h
用法:make [選項] [目標] ...
選項:
? -b, -m????????????????????? 忽略兼容性。
? -B, --always-make?????????? Unconditionally make all targets.
? -C 目錄, --directory=目錄
????????????????????????????? 在所有操作前切換到“目錄”。
? -d????????????????????????? 打印大量調試信息。
? --debug[=FLAGS]???????????? 打印各種調試信息
? -e, --environment-overrides
????????????????????????????? 指定替代makefile中默認設置的環境變量
? -f FILE, --file=FILE, --makefile=FILE
????????????????????????????? 讀取 FILE 作為一個 makefile.
? -h, --help????????????????? 打印該消息并退出。
? -i, --ignore-errors???????? Ignore errors from commands.
? -I DIRECTORY, --include-dir=DIRECTORY
????????????????????????????? 搜索 DIRECTORY 為包含的 makefiles.
? -j [N], --jobs[=N]????????? 同時允許 N 個任務;無參數表明允許無限個任務。
? -k, --keep-going??????????? 當某些目標無法創建時仍然繼續。
? -l [N], --load-average[=N], --max-load[=N]
????????????????????????????? 不開始多線程工作除非系統負載低于N
? -L, --check-symlink-times?? Use the latest mtime between symlinks and target.
? -n, --just-print, --dry-run, --recon
????????????????????????????? 不要實際運行任何命令;僅僅輸出他們
? -o FILE, --old-file=FILE, --assume-old=FILE
????????????????????????????? 將FILE認作非常老,不要重新make它.
? -p, --print-data-base?????? 打印 make 的內部數據庫。
? -q, --question?????????????? 不運行任何命令;退出狀態說明是否已全部更新。
? -r, --no-builtin-rules????? 禁用內置隱含規則。
? -R, --no-builtin-variables?? 禁用內置變量設置。
? -s, --silent, --quiet?????? 不顯示命令。
? -S, --no-keep-going, --stop
????????????????????????????? 關閉 -k.
? -t, --touch???????????????? touch 目標而不是重新創建它們
? -v, --version?????????????? 打印 make 的版本號并退出。
? -w, --print-directory?????? 打印當前目錄。
? --no-print-directory??????? 即使 -w 隱式開啟,也要關閉 -w。
? -W FILE, --what-if=FILE, --new-file=FILE, --assume-new=FILE
????????????????????????????? 將FILE認作無限新.
? --warn-undefined-variables? Warn when an undefined variable is referenced.
這個程序創建為 i686-pc-linux-gnu
Report bugs to <bug-make@gnu.org>12345678910111213141516171819202122232425262728293031323334353637383940414243
參考資料
1.Makefile經典教程(掌握這些足夠)
http://blog.csdn.net/ruglcc/article/details/7814546/
2.android開發筆記之mk文件
http://blog.csdn.net/hfreeman2008/article/details/46792693#t23
---------------------
作者:hfreeman2008
來源:CSDN
原文:https://blog.csdn.net/hfreeman2008/article/details/71418693?utm_source=copy
版權聲明:本文為博主原創文章,轉載請附上博文鏈接!
總結
以上是生活随笔為你收集整理的android开发笔记之Makefile(一)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 蓝桥杯 作物杂交 DFS搜索
- 下一篇: 28335的CAN总线学习笔记