提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
一、关闭回显$(hide)与@
Makefile的规则:
target... : prerequisites ...
<tab> command
target: 编译目标
prerequisites: 目标的依赖
command: 使用makefile shell语句混合编写的命令,最终的command命令只包含shell语句,makefile语句在依赖构建时就被解析。例如:
1 var := a b c
2 all:
3 $(foreach m, $(var), \
4 if [ 1 ]; then \
5 echo "i am $(m)"; \
6 fi; \
7 )
实际上最终的命令:
if [ 1 ]; then echo "i am a"; fi; if [ 1 ]; then echo "i am b"; fi; if [ 1 ]; then echo "i am c"; fi;
回显:在linux下使用make进行编译时。先打印command,随后执行command。
对于上述的Makefile执行make命令,结果如下:
if [ 1 ]; then echo "i am a"; fi; if [ 1 ]; then echo "i am b"; fi; if [ 1 ]; then echo "i am c"; fi;
i am a
i am b
i am c
这种先打印command命令再执行的方式称为回显,如果只想要显示command执行结果,需要关闭回显。
在Android mk文件中经常会看到$(hide) @两种方式:
#build/make/target/product/gsi/Android.mk
64 include $(CLEAR_VARS)
65 LOCAL_MODULE := update-vndk-list.sh
66 LOCAL_LICENSE_KINDS := legacy_restricted
67 LOCAL_LICENSE_CONDITIONS := restricted
68 LOCAL_MODULE_CLASS := EXECUTABLES
69 LOCAL_MODULE_STEM := $(LOCAL_MODULE)
70 LOCAL_IS_HOST_MODULE := true
71 include $(BUILD_SYSTEM)/base_rules.mk
72 $(LOCAL_BUILT_MODULE): PRIVATE_INTERNAL_VNDK_LIB_LIST := $(INTERNAL_VNDK_LIB_LIST)
73 $(LOCAL_BUILT_MODULE): PRIVATE_LATEST_VNDK_LIB_LIST := $(LATEST_VNDK_LIB_LIST)
74 $(LOCAL_BUILT_MODULE):
75 @echo "Generate: $@"
76 @mkdir -p $(dir $@)
77 @rm -f $@
78 $(hide) echo "#!/bin/bash" > $@
79 ifeq (REL,$(PLATFORM_VERSION_CODENAME))
80 $(hide) echo "echo Updating VNDK library list is NOT allowed in API locked branches." >> $@; \
81 echo "exit 1" >> $@
82 else
83 $(hide) echo "if [ -z \"\$${ANDROID_BUILD_TOP}\" ]; then" >> $@; \
84 echo " echo Run lunch or choosecombo first" >> $@; \
85 echo " exit 1" >> $@; \
86 echo "fi" >> $@; \
87 echo "cd \$${ANDROID_BUILD_TOP}" >> $@; \
88 echo "cp $(PRIVATE_INTERNAL_VNDK_LIB_LIST) $(PRIVATE_LATEST_VNDK_LIB_LIST)" >> $@; \
89 echo "echo $(PRIVATE_LATEST_VNDK_LIB_LIST) updated." >> $@
90 endif
91 @chmod a+x $@
build/make/core/config.mk中定义:
hide := @
所以,在Android编译中,$ (hide)就等于@,但在Android 推荐使用$(hide)
下面来看一下@的使用方法和效果:
1 var := a b c
2 all:
3 @$(foreach m, $(var), \
4 if [ 1 ]; then \
5 echo "i am $(m)"; \
6 fi; \
7 )
执行后:
i am a
i am b
i am c
通过执行结果,关掉了回显。
需要注意的是:
只需要在每一句command的开头使用@,只要用 \ 则可拼接为一句command,下面这种写法是错误:
1 var := a b c
2 all:
3 $(foreach m, $(var), \
4 @if [ 1 ]; then \
5 @echo "i am $(m)"; \
6 @fi; \
7 )
二、退出命令
在Makefile的command命令中,如果想中止编译,可使用exit 1退出编译
如:
65 $(LIB): $(notdir $(LIBOBJS))
66 if [ -z "$(strip $^)" ] ; then \
67 echo "Cowardly refusing to create empty archive"; \
68 exit 1; \
69 fi
70 $(if $(AR),$(AR),ar) -rc "$@" $^
71 $(if $(RANLIB),$(RANLIB),ranlib) "$@"
三、shell中的分号
command中的shell命令是分不同进程执行,如果要保证顺序,则需要使用 ; \ 拼接为一句命令
分号在shell脚本中是用来隔离代码块的,比如:
if [ -z “$(strip $^)” ] ; then echo “abc”; fi
等价于
if [-z “$(strip $^)”]; then
echo “abc”
fi
但是在Makefile的command拼接时,使用分号对拼接的代码进行分隔。
四、filter使用
$(filter PATTERN…,TEXT)
在TEXT中过滤出PATTERN,如果存在,则返回,如果不存在则返回空
需要注意的是,makefile中""不可随便用,与python或者其他语言中不同,在其他语言中""一般用来引用字符串,而在makefile中,""也会被认为是普通的字符,例如
$(filter "yes", yes no)
则会返回空,因为不存在"yes"这五个字符。