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中,大功告成!

更多相关文章

  1. 箭头函数的基础使用
  2. Android(安卓)Wifi模块分析(三)
  3. android“设置”里的版本号
  4. android ndk编译x264开源(用于android的ffmpeg中进行软编码)
  5. [android]编译时出现/usr/bin/ld: skipping incompatible /usr/l
  6. 编译android的linux内核
  7. Android(安卓)命令行编译、打包生成apk文件
  8. Android热更新框架Tinker无法更新?
  9. Android架构分析之使用自定义硬件抽象层(HAL)模块

随机推荐

  1. android GridView 的使用
  2. Android中RecyclerView简单的点击事件
  3. Android的EditText控件点击虚拟键盘上的
  4. android sign签名
  5. 疯狂java讲义笔记 2.3.7
  6. Android(安卓)NDK c创建新的线程
  7. 使用Android Studio出现的一些问题解决策
  8. Android判断后台服务(Service)是否运行
  9. Android(安卓)Studio的几个Error与解决方
  10. android 游戏开发过程中让图片自适应