如何在模块中生成代码,并让生成的代码加入到当前模块编译?
在bootable/recovery/updater/Android.mk 中有这么一段
inc := $(call local-generated-sources-dir)/register.inc
$(inc) : libs := $(TARGET_RECOVERY_UPDATER_LIBS)
$(inc) :
$(call generate-register-inc,$@,$(libs))
LOCAL_GENERATED_SOURCES := $(inc)
inc :=
$(call local-generated-sources-dir) 这是系统自动生成路径的一个宏定义,位于out/target/product/generic_arm64/obj下面,比如本例子是编译一个EXECUTABLES,名字为updater,那么inc := out/target/product/generic_arm64/gen/EXECUTABLES/updater_intermediates/register.inc。
再来看看生成上述文件的宏定义:
define generate-register-inc
$(hide) mkdir -p $(dir $(1))
$(hide) echo "" > $(1)
$(hide) $(foreach lib,$(2),echo "extern void Register_$(lib)(void);" >> $(1);)
$(hide) echo "void RegisterDeviceExtensions() {" >> $(1)
$(hide) $(foreach lib,$(2),echo " Register_$(lib)();" >> $(1);)
$(hide) echo "}" >> $(1)
endef
明显这里是生成一个头文件。将生成的文件加入到模块编译就是使用:LOCAL_GENERATED_SOURCES := $(inc) 这一句。
注意:在使用时,这些代码需要放在LOCAL_PATH与LOCAL_MODULE之后,因为里面的local-generated-sources-dir会用到这两个变量。
Android官方推荐的方法
Using Custom Tools
If you have a tool that generates source files for you, it's possible to have the build system get the dependencies correct for it. Here are a couple of examples. $@
is the make built-in variable for "the current target." The red parts are the parts you'll need to change.
You need to put this after you have declared LOCAL_PATH
and LOCAL_MODULE
, because the $(local-generated-sources-dir)
and $(local-host-generated-sources-dir)
macros use these variables to determine where to put the files.
Example 1
Here, there is one generated file, called chartables.c, which doesn't depend on anything. And is built by the tool built to $(HOST_OUT_EXECUTABLES)/dftables. Note on the second to last line that a dependency is created on the tool.
intermediates:= $(local-generated-sources-dir) GEN := $(intermediates)/chartables.c $(GEN): PRIVATE_CUSTOM_TOOL = $(HOST_OUT_EXECUTABLES)/dftables $@ $(GEN): $(HOST_OUT_EXECUTABLES)/dftables $(transform-generated-source) LOCAL_GENERATED_SOURCES += $(GEN)
Example 2
Here as a hypothetical example, we use use cat as if it were to transform a file. Pretend that it does something useful. Note how we use a target-specific variable called PRIVATE_INPUT_FILE to store the name of the input file.
intermediates:= $(local-generated-sources-dir) GEN := $(intermediates)/file.c $(GEN): PRIVATE_INPUT_FILE := $(LOCAL_PATH)/input.file $(GEN): PRIVATE_CUSTOM_TOOL = cat $(PRIVATE_INPUT_FILE) > $@ $(GEN): $(LOCAL_PATH)/input.file $(transform-generated-source) LOCAL_GENERATED_SOURCES += $(GEN)
Example 3
If you have several files that are all similar in name, and use the same tool, you can combine them. (here the *.lut.h files are the generated ones, and the *.cpp files are the input files)
intermediates:= $(local-generated-sources-dir) GEN := $(addprefix $(intermediates)/kjs/, \ array_object.lut.h \ bool_object.lut.h \ ) $(GEN): PRIVATE_CUSTOM_TOOL = perl libs/WebKitLib/WebKit/JavaScriptCore/kjs/create_hash_table $< -i > $@ $(GEN): $(intermediates)/%.lut.h : $(LOCAL_PATH)/%.cpp $(transform-generated-source) LOCAL_GENERATED_SOURCES += $(GEN)