zoukankan      html  css  js  c++  java
  • Android.mk(3) 宏

    https://www.jianshu.com/p/7c20b299ee63

    传统上我们一直称这种东西为makefile中的变量,其实本质上就是一个宏,只是做的是字符串替换。我们何如就把它叫做宏呢。

    宏的命名

    makefile的宏可以包含字符、数字、下划线。需要注意的一点是,宏就是宏,反正是要做字符串替换的,所以名字以数字开头是没问题的。makefile本身也不是用于数值处理的,以字符串为主。

    使用一个宏的时候需要使用$符号,所以如果字符串中要使用shell变量,需要用$$。
    从中可以看到,我们前面学到的函数,其实本质上也就是宏,只不过是带有了参数的宏。

    宏的赋值

    = 和 :=

    宏可以用其他宏的值来定义自己。最强大的是用=运算符。makefile是定义式的语言,不是按顺序一条一条执行的,所以,可以使用在这一行还没有定义的宏来为当前宏赋值,反正就是个宏展开么。

    但是,这样如果造成的循环引用,就会引发意想不到的错误。在这种情况下,使用:=运算符,它是只允许引用在它之前定义的变量的。

    ?=

    如果不知道定义没定义,可以使用?=来赋值,如果未定义,则定义。如果已经定义了,就什么也不做。

    +=

    如果之前未定义,则相当于=。如果之前有:=定义,则将新值按:=的规则添加到原值后面。

    对宏进行比较

    有4个关键字用于对宏的比较:

    • ifeq:判断相等
    • ifneq:判断不相等
    • ifdef:判断非空,相当于ifneq(<参数>,)
    • ifndef:如果为空,相当于ifeq(<参数>,)

    例:

    .PHONY : all7
    ifeq ($(DEX2OAT_HOST_INSTRUCTION_SET_FEATURES),)
    DEX2OAT_HOST_INSTRUCTION_SET_FEATURES := default
    endif
    all7 :
        @echo $(DEX2OAT_HOST_INSTRUCTION_SET_FEATURES)
    

    输出:

    $ make all7
    default
    

    请注意,ifeq, else, endif这些语句之前不能有Tab。

    上面的例子是从Android.oat.mk中改造的。其实,跟下面的是等价的:

    ifndef DEX2OAT_HOST_INSTRUCTION_SET_FEATURES
    DEX2OAT_HOST_INSTRUCTION_SET_FEATURES := default
    endif
    

    定义多行的宏

    可以通过使用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))
      endif
    endef
    

    这个宏其实是个函数了。

    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 $@.input
    endif
    

    $<

    依赖的第一个文件名,可以和$@一起共用。

    例:

    $(built_odex) : $(my_prebuilt_src_file)
        $(call dexpreopt-one-file,$<,$@)
    

    调试与错误处理

    输出消息

    makefile的命令,默认都会输出出来。可以用@来隐藏显示。
    通过echo命令,可以输出消息。一般都是用@echo,免得看见两次。

    几条命令一起执行

    如果这条命令用到上条命令的结果,需要在上条命令后面加分号

    错误处理

    如果makefile遇到命令出错,就会中止当前的依赖执行。可以通过在命令之前加上“-”来忽略错误。
    我们也可以将忽略错误的目标以.IGNORE来声明。

    如:

    .IGNORE : all7
    


    作者:Jtag特工
    链接:https://www.jianshu.com/p/7c20b299ee63
    來源:简书
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
  • 相关阅读:
    利用iframe实现ajax 跨域通信的解决方案
    C++中事件机制的简洁实现
    java远程类加载与轻客户端
    iOS开发那些事性能优化–内存泄露问题的解决
    Asp.net项目的开发流程
    LVS配置教程
    PowerShell之东扯西谈
    响应式设计专题
    2013年最值得关注的网页设计流行趋势
    HTTP Live Streaming直播技术分析与实现
  • 原文地址:https://www.cnblogs.com/onelikeone/p/8438263.html
Copyright © 2011-2022 走看看