在Android的mk系统中,调用dex2oat中有几处,但是真正被调用来生成目标系统上的oat的是下面这个,位于/build/core/dex_preopt_libart.mk中:
# For a single jar or APK
# $(1): the input .jar or .apk file
# $(2): the output .odex file
define dex2oat-one-file
$(hide) rm -f $(2)
$(hide) mkdir -p $(dir $(2))
$(hide) $(DEX2OAT) \
--runtime-arg -Xms$(DEX2OAT_XMS) --runtime-arg -Xmx$(DEX2OAT_XMX) \
--boot-image=$(PRIVATE_DEX_PREOPT_IMAGE_LOCATION) \
--dex-file=$(1) \
--dex-location=$(PRIVATE_DEX_LOCATION) \
--oat-file=$(2) \
--android-root=$(PRODUCT_OUT)/system \
--instruction-set=$($(PRIVATE_2ND_ARCH_VAR_PREFIX)DEX2OAT_TARGET_ARCH) \
--instruction-set-variant=$($(PRIVATE_2ND_ARCH_VAR_PREFIX)DEX2OAT_TARGET_CPU_VARIANT) \
--instruction-set-features=$($(PRIVATE_2ND_ARCH_VAR_PREFIX)DEX2OAT_TARGET_INSTRUCTION_SET_FEATURES) \
--include-patch-information --runtime-arg -Xnorelocate --no-generate-debug-info \
--abort-on-hard-verifier-error \
$(PRIVATE_DEX_PREOPT_FLAGS)
endef
这个dex2oat-one-file,是被dexpreopt-one-file调用,位于/build/core/dex_preopt.mk中:
include $(BUILD_SYSTEM)/dex_preopt_libart.mk
# Define dexpreopt-one-file based on current default runtime.
# $(1): the input .jar or .apk file
# $(2): the output .odex file
define dexpreopt-one-file
$(call dex2oat-one-file,$(1),$(2))
endef
以下根据生成的类型不同,包、库、预先编译好的应用有不同的路径。
/build/core/package_internal.mk
###############################
## Rule to build the odex file
ifdef LOCAL_DEX_PREOPT
$(built_odex): PRIVATE_DEX_FILE := $(built_dex)
# Use pattern rule - we may have multiple built odex files.
$(built_odex) : $(dir $(LOCAL_BUILT_MODULE))% : $(built_dex)
$(hide) mkdir -p $(dir $@) && rm -f $@
$(add-dex-to-package)
$(hide) mv $@ [email protected]
$(call dexpreopt-one-file,[email protected],$@)
$(hide) rm [email protected]
endif
/build/core/java_library.mk
$(built_odex): PRIVATE_MODULE := $(LOCAL_MODULE)
# Use pattern rule - we may have multiple built odex files.
$(built_odex) : $(dir $(LOCAL_BUILT_MODULE))% : $(common_javalib.jar)
@echo "Dexpreopt Jar: $(PRIVATE_MODULE) ($@)"
$(call dexpreopt-one-file,$<,$@)
###############################
## Rule to build the odex file
ifdef LOCAL_DEX_PREOPT
$(built_odex) : $(my_prebuilt_src_file)
$(call dexpreopt-one-file,$<,$@)
endif
我们再来看看,odex是如何被install到system分区下面的。
# Use pattern rule - we may have multiple installed odex files.
# Ugly syntax - See the definition get-odex-file-path.
$(installed_odex) : $(dir $(LOCAL_INSTALLED_MODULE))%$(notdir $(word 1,$(installed_odex))) \
: $(dir $(LOCAL_BUILT_MODULE))%$(notdir $(word 1,$(built_odex))) \
| $(ACP)
@echo "Install: $@"
$(copy-file-to-target)
endif
我们看一个实际的例子:
Install: out/target/product/6753_64_m/system/app/Note/oat/arm64/Note.odex
mkdir -p out/target/product/6753_64_m/system/app/Note/oat/arm64/
out/host/linux-x86/bin/acp -fp out/target/product/6753_64_m/obj/APPS/Note_intermediates/oat/arm64/package.odex out/target/product/6753_64_m/system/app/Note/oat/arm64/Note.odex
Install: out/target/product/6753_64_m/system/priv-app/Settings/oat/arm64/Settings.odex
mkdir -p out/target/product/6753_64_m/system/priv-app/Settings/oat/arm64/
out/host/linux-x86/bin/acp -fp out/target/product/6753_64_m/obj/APPS/Settings_intermediates/oat/arm64/package.odex out/target/product/6753_64_m/system/priv-app/Settings/oat/arm64/Settings.odex
除了编译之外,我们得先看一些预先定义好的函数。它们定义于/build/core/definitions.mk中。
将class文件压缩成classes*.dex
define add-dex-to-package
$(hide) zip -qj $@ $(dir $(PRIVATE_DEX_FILE))classes*.dex
endef
将依赖文件复制到目标文件
define copy-file-to-target
@mkdir -p $(dir $@)
$(hide) $(ACP) -fp $< $@
endef