Android(安卓)BOOTCLASSPATH详解
BOOTCLASSPATH被赋值流程分析
system/core/rootdir/init.environ.rc.in
# set up the global environmenton init export PATH /sbin:/vendor/bin:/system/sbin:/system/bin:/system/xbin export LD_LIBRARY_PATH /vendor/lib:/system/lib export ANDROID_BOOTLOGO 1 export ANDROID_ROOT /system export ANDROID_ASSETS /system/app export ANDROID_DATA /data export ANDROID_STORAGE /storage export ASEC_MOUNTPOINT /mnt/asec export LOOP_MOUNTPOINT /mnt/obb export BOOTCLASSPATH %BOOTCLASSPATH%
通过上面的代码我们知道BOOTCLASSPATH环境变量等于%BOOTCLASSPATH%,那%BOOTCLASSPATH%是谁赋的值呢?往下看。
system/core/rootdir/Android.mk
$(LOCAL_BUILT_MODULE): $(LOCAL_PATH)/init.environ.rc.in FORCE @echo "Generate: $< -> $@" @mkdir -p $(dir $@) $(hide) sed -e 's?%BOOTCLASSPATH%?$(PRODUCT_BOOTCLASSPATH)?g' $< >$@
语法解释
FORCE 表示目标文件每次编译的时候都会重新生成$< 表示依赖文件, 即$(LOCAL_PATH)/init.environ.rc.in, 等于system/core/rootdir/init.environ.rc.in$@ 表示目标文件, 即$(LOCAL_BUILT_MODULE), 等于out/target/product/imx6/obj/ETC/init.environ.rc_intermediates/init.environ.rc$(hide) = @, @加命令 表示只显示命令结果, 不显示命令本身sed -e 's?%BOOTCLASSPATH%?$(PRODUCT_BOOTCLASSPATH)?g' $< > $@ 这条命令表示将$<文件里面的%BOOTCLASSPATH%替换为$(PRODUCT_BOOTCLASSPATH),并将结果输出到$@中。
通过对上面这个mk文件的分析,我们知道%BOOTCLASSPATH%
将被$(PRODUCT_BOOTCLASSPATH)
替换掉,那$(PRODUCT_BOOTCLASSPATH)
又是谁赋值的呢?继续往下分析。先看下hide被赋值的地方。
ndk/build/core/definitions.mk
# -----------------------------------------------------------------------------# Macro : hide# Returns : nothing# Usage : $(hide)# Rationale: To be used as a prefix for Make build commands to hide them# by default during the build. To show them, set V=1 in your# environment or command-line.## For example:## foo.o: foo.c# -->|$(hide) ## Where '-->|' stands for a single tab character.## -----------------------------------------------------------------------------ifeq ($(V),1)hide = $(empty)elsehide = @endif
hide的赋值就不多说了,主要看下PRODUCT_BOOTCLASSPATH是怎么被赋值的。
build/core/dex_preopt.mk
DEXPREOPT_BOOT_JARS := $(PRODUCT_BOOT_JARS)DEXPREOPT_BOOT_JARS_MODULES := $(subst :, ,$(DEXPREOPT_BOOT_JARS))PRODUCT_BOOTCLASSPATH := $(subst $(space),:,$(foreach m,$(DEXPREOPT_BOOT_JARS_MODULES),/system/framework/$(m).jar))
语法解释
$(foreach VAR, LIST, TEXT) 表示将LIST中以空格分割的单词赋值给VAR,然后执行TEXT表达式,TEXT可能存在对VAR的引用。返回以空格分割的TEXT的执行结果。$(subst FROM,TO,TEXT) 表示把字串TEXT中的FROM字符替换为TO。返回替换后的新字符串。
通过上面两个语法的分析,我们知道DEXPREOPT_BOOT_JARS_MODULES会将DEXPREOPT_BOOT_JARS里的:替换为空格。然后PRODUCT_BOOTCLASSPATH会将DEXPREOPT_BOOT_JARS_MODULES里的值轮询,并赋值给到/system/framework/x.jar,最后将这些.jar之间的空格替换会:。所以PRODUCT_BOOTCLASSPATH最终的显示值应该是/system/framework/x.jar:/system/framework/y.jar:/system/framework/z.jar类似这样的形式。PRODUCT_BOOT_JARS又是在哪赋值的呢?
build/target/product/core_base.mk
PRODUCT_BOOT_JARS := core:conscrypt:okhttp:core-junit:bouncycastle:ext:framework:framework2:telephony-common:voip-common:mms-common:android.policy:services:apache-xml:webviewchromium
小节
通过上面的分析,我们知道BOOTCLASSPATH的赋值其实是通过PRODUCT_BOOT_JARS来的。如果我们想添加自定义的jar包,我们只需要在PRODUCT_BOOT_JARS添加相应的jar就行了。
实战操作
1.将相关自定义的java文件编译到自定义模块
Android.mk
LOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)LOCAL_SRC_FILES := \ $(call all-java-files-under, java) \LOCAL_MODULE:= customLOCAL_MODULE_TAGS := optional# List of classes and interfaces which should be loaded by the Zygote.include $(BUILD_JAVA_LIBRARY)
这样我们自定义的custom.jar就会被编译到/system/framework/custom.jar中。
2.将自定义模块编译到系统中
接下来我们需要系统在编译的时候能将custom.jar模块编译到系统中。我们需要添加如下代码:
device/xxx/yyy.mk
PRODUCT_PACKAGES += custom
3.在PRODUCT_BOOT_JARS中添加自定义模块
build/target/product/core_base.mk
PRODUCT_BOOT_JARS := core:conscrypt:okhttp:core-junit:bouncycastle:ext:framework:framework2:telephony-common:voip-common:mms-common:android.policy:services:apache-xml:webviewchromium:custom
通过上面的3步,就可以将custom.jar编译到/system/framewrok/custom.jar中。同时,在BOOTCLASSPATH中也添加了custom.jar。
4.验证BOOTCLASSPATH是否添加了自定义模块
在PC端使用adb shell $BOOTCLASSPATH就可以查看BOOTCLASSPATH的值了。
C:\Users\Steven>adb shell $BOOTCLASSPATH/system/bin/sh: /system/framework/core.jar:/system/framework/conscrypt.jar:/system/framework/okhttp.jar:/system/framework/core-junit.jar:/system/framework/bouncycastle.jar:/system/framework/ext.jar:/system/framework/framework.jar:/system/framework/framework2.jar:/system/framework/telephony-common.jar:/system/framework/voip-common.jar:/system/framework/mms-common.jar:/system/framework/android.policy.jar:/system/framework/services.jar:/system/framework/apache-xml.jar:/system/framework/webviewchromium.jar:/system/framework/custom.jar: not found
上面我们可以到custom.jar成功添加到了BOOTCLASSPATH中,大功告成!
更多相关文章
- 箭头函数的基础使用
- Android(安卓)Wifi模块分析(三)
- android“设置”里的版本号
- android ndk编译x264开源(用于android的ffmpeg中进行软编码)
- [android]编译时出现/usr/bin/ld: skipping incompatible /usr/l
- 编译android的linux内核
- Android(安卓)命令行编译、打包生成apk文件
- Android热更新框架Tinker无法更新?
- Android架构分析之使用自定义硬件抽象层(HAL)模块