指定编译文件
指定特定的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
版权声明:本文为博主原创文章,转载请附上博文链接!