首页 > 解决方案 > 如何在 Makefile 工作中使用 foreach 和 eval 函数?

问题描述

我正在尝试了解 AOSP 的 Makefile 语法和 Makefile 系统。但是,像我这样的初学者很难。我了解 fereach 函数的工作原理,但不了解何时与 eval 函数一起使用,如下所示。有人可以解释下面的 Makefile 代码吗?它是如何一步一步工作的以及每一步的输出?变量的最终值all_product_configs?非常感谢!

all_product_configs := $(call get-product-makefiles,\
    $(SRC_TARGET_DIR)/product/AndroidProducts.mk)

这是get-product-makefiles函数的定义:

define get-product-makefiles
$(sort \
  $(foreach f,$(1), \
    $(eval PRODUCT_MAKEFILES :=) \
    $(eval LOCAL_DIR := $(patsubst %/,%,$(dir $(f)))) \
    $(eval include $(f)) \
    $(PRODUCT_MAKEFILES) \
   ) \
  $(eval PRODUCT_MAKEFILES :=) \
  $(eval LOCAL_DIR :=) \
 )
endef

标签: makefilegnu-makeandroid-source

解决方案


eval接受它的参数并将其评估为 Makefile 语法——变量和规则的定义,以及任何其他 GNUmake 语法——并扩展为空(一个空字符串)

foreach接受它的第三个参数并为第二个参数中的每个单词重复一次,每次将第一个参数定义为相应的单词。结果是那个(大)字符串。

call将其第一个参数作为变量的名称,并将该变量扩展为$(1),$(2)等设置为call

因此,从顶部开始,您get-product-makefiles使用$(1)set to扩展$(SRC_TARGET_DIR)/product/AndroidProducts.mk 这实际上是 foreach 的第二个参数,并且只有一个单词,因此foreach将扩展第三个参数一次,$(f)设置为该字符串 ( $(SRC_TARGET_DIR)/product/AndroidProducts.mk)。所以这只是

$(eval PRODUCT_MAKEFILES :=) \
$(eval LOCAL_DIR := $(patsubst %/,%,$(dir $(SRC_TARGET_DIR)/product/AndroidProducts.mk))) \
$(eval include $(SRC_TARGET_DIR)/product/AndroidProducts.mk) \
$(PRODUCT_MAKEFILES) \

所以它运行那些定义这些变量(PRODUCT_MAKEFILESLOCAL_DIR)的评估,然后包含另一个makefile(推测定义PRODUCT_MAKEFILES为非空的东西,可能会附加一些东西)。然后它扩展为任何内容,然后是最后两个eval命令,清除这两个变量并扩展为空。因此,最终结果将只是$(PRODUCT_MAKEFILES)AndroidProducts.mk 中定义的任何内容,而该变量本身实际上不再设置。然后它对其进行排序(sort命令——在排序后偶然删除重复的单词),这就是整个事情的最终结果——这就是all_product_configs设置的内容。

如果命令中有多个 makefile,这会更有趣call。然后它最终会读取所有这些并提取它们在 中定义的所有内容PRODUCT_MAKEFILES,连接并排序该批次。


推荐阅读