Makefile 中的 foreach 和 eval 函数如何工作?

How to foreach and eval function in Makefile work?

我正在尝试了解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

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

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

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

所以从顶部开始,您展开 get-product-makefiles 并将 $(1) 设置为 $(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 设置的内容。

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