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 <[email protected]>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
版权声明:本文为博主原创文章,转载请附上博文链接!

发布了6 篇原创文章 · 获赞 44 · 访问量 11万+

猜你喜欢

转载自blog.csdn.net/sinat_29255093/article/details/83067593