我们也说说Android.mk(3) - 宏
来源:互联网 发布:域名邮箱怎么做 编辑:程序博客网 时间:2024/05/02 22:51
我们也说说Android.mk(3) - 宏
传统上我们一直称这种东西为makefile中的变量,其实本质上就是一个宏,只是做的是字符串替换。我们何如就把它叫做宏呢。
宏的命名
makefile的宏可以包含字符、数字、下划线。需要注意的一点是,宏就是宏,反正是要做字符串替换的,所以名字以数字开头是没问题的。makefile本身也不是用于数值处理的,以字符串为主。
使用一个宏的时候需要使用
从中可以看到,我们前面学到的函数,其实本质上也就是宏,只不过是带有了参数的宏。
宏的赋值
= 和 :=
宏可以用其他宏的值来定义自己。最强大的是用=运算符。makefile是定义式的语言,不是按顺序一条一条执行的,所以,可以使用在这一行还没有定义的宏来为当前宏赋值,反正就是个宏展开么。
但是,这样如果造成的循环引用,就会引发意想不到的错误。在这种情况下,使用:=运算符,它是只允许引用在它之前定义的变量的。
?=
如果不知道定义没定义,可以使用?=来赋值,如果未定义,则定义。如果已经定义了,就什么也不做。
+=
如果之前未定义,则相当于=。如果之前有:=定义,则将新值按:=的规则添加到原值后面。
对宏进行比较
有4个关键字用于对宏的比较:
* ifeq:判断相等
* ifneq:判断不相等
* ifdef:判断非空,相当于ifneq(<参数>,)
* ifndef:如果为空,相当于ifeq(<参数>,)
例:
.PHONY : all7ifeq ($(DEX2OAT_HOST_INSTRUCTION_SET_FEATURES),)DEX2OAT_HOST_INSTRUCTION_SET_FEATURES := defaultendifall7 : @echo $(DEX2OAT_HOST_INSTRUCTION_SET_FEATURES)
输出:
$ make all7default
请注意,ifeq, else, endif这些语句之前不能有Tab。
上面的例子是从Android.oat.mk中改造的。其实,跟下面的是等价的:
ifndef DEX2OAT_HOST_INSTRUCTION_SET_FEATURESDEX2OAT_HOST_INSTRUCTION_SET_FEATURES := defaultendif
定义多行的宏
可以通过使用define / endef来定义多行的大宏。
我们看一个例子:
# $(1): compiler - default, optimizing, jit or interpreter. # $(2): wrapper. # $(3): dex2oat suffix.define create-core-oat-host-rule-combination $(call create-core-oat-host-rules,$(1),no-pic,,$(2),$(3)) $(call create-core-oat-host-rules,$(1),pic,,$(2),$(3)) ifneq ($(HOST_PREFER_32_BIT),true) $(call create-core-oat-host-rules,$(1),no-pic,2ND_,$(2),$(3)) $(call create-core-oat-host-rules,$(1),pic,2ND_,$(2),$(3)) endifendef
这个宏其实是个函数了。
eval函数
eval函数用于在宏定义或者是分支、循环结构中使用其他makefile语句时。
我们看一个在foreach中使用eval的例子:
$(foreach m,$(ALL_MODULES), \ $(eval r := $(ALL_MODULES.$(m).REQUIRED)) \ $(if $(r), \ $(eval r := $(call module-installed-files,$(r))) \ $(eval t_m := $(filter $(TARGET_OUT_ROOT)/%, $(ALL_MODULES.$(m).INSTALLED))) \ $(eval h_m := $(filter $(HOST_OUT_ROOT)/%, $(ALL_MODULES.$(m).INSTALLED))) \ $(eval t_r := $(filter $(TARGET_OUT_ROOT)/%, $(r))) \ $(eval h_r := $(filter $(HOST_OUT_ROOT)/%, $(r))) \ $(eval t_m := $(filter-out $(t_r), $(t_m))) \ $(eval h_m := $(filter-out $(h_r), $(h_m))) \ $(if $(t_m), $(eval $(call add-required-deps, $(t_m),$(t_r)))) \ $(if $(h_m), $(eval $(call add-required-deps, $(h_m),$(h_r)))) \ ) \ )
vpath宏
vpath宏用于指定makefile搜索源文件的目录,这个倒是有点变量的意思了
引用其他makefile
makefile基本上就是字符串替换,我们当然也可以通过include命令将一系列的其他makefile引用进当前的makefile.
例:
include art/build/Android.common_build.mk
自动宏
自动宏就是由make工具已经定义好的变量。
$@ 目标文件集
$@是指整个目标的文件集
例:
$(built_odex) : $(dir $(LOCAL_BUILT_MODULE))% : $(built_dex) $(hide) mkdir -p $(dir $@) && rm -f $@ $(add-dex-to-package) $(hide) mv $@ $@.input $(call dexpreopt-one-file,$@.input,$@) $(hide) rm $@.inputendif
$<
依赖的第一个文件名,可以和$@一起共用。
例:
$(built_odex) : $(my_prebuilt_src_file) $(call dexpreopt-one-file,$<,$@)
调试与错误处理
输出消息
makefile的命令,默认都会输出出来。可以用@来隐藏显示。
通过echo命令,可以输出消息。一般都是用@echo,免得看见两次。
几条命令一起执行
如果这条命令用到上条命令的结果,需要在上条命令后面加分号
错误处理
如果makefile遇到命令出错,就会中止当前的依赖执行。可以通过在命令之前加上“-”来忽略错误。
我们也可以将忽略错误的目标以.IGNORE来声明。
如:
.IGNORE : all7
- 我们也说说Android.mk(3) - 宏
- 我们也说说Android.mk(3)
- 我们也说说Android.mk(1)
- 我们也说说Android.mk(4)
- 我们也说说Android.mk(5)
- 我们也说说Android.mk(6)
- 我们也说说Android.mk(1) - 从函数说起
- 我们也说说Android.mk(4) - 计算怎么办?
- 我们也说说Android.mk(5) - 案例教程
- 我们也说说Android.mk(2)-函数进阶教程
- 我们也说说Android.mk(2) - 函数进阶教程 - 分支、循环、子程序
- 我也说说Emacs吧(3)
- Android.mk 宏定义
- Android.mk----------------3
- 也说说第一博客
- 我也说说房价
- 也说说代理模式
- 我也说说盗版
- 大数据技术大合集:Hadoop家族、Cloudera系列、spark、storm
- IOS学习之——实现数据源的方法(代码)
- 多线程断点下载
- 前端 简单实现应用商店list
- osgexp安装与使用
- 我们也说说Android.mk(3) - 宏
- 导入文章“Apache Spark学习:将Spark部署到Hadoop 2.2.0上”中给出的 assembly/target/scala-2.9.3/目录下的spark-assembly-0.8.
- double四舍五入并保留两位小数的方法
- PHP调用内容DES加密的SOAP接口
- tableView小技巧:让cell分割线充满整个cell,去掉多余的分割线
- mysql 分表
- Java核心知识点-JVM结构之常量池
- CocoaPods安装和使用及问题:Setting up CocoaPods master repo
- sqrt源代码问题——二分法