又有好久没有写点偏重实战类型的博客了,最近一直都在捣鼓源码分析和项目相关事情,是时候来点偏重实战类型的博客了。捯饬点啥实战的呢,正好最近在迁移项目到Android 11上面,发现了一些不少Android 11相较于以前Android版本的一些特性,这里我就分析一个在Android 11上面预编译不支持错误的解决小实战。其错误吗如下:
build/make/core/main.mk:368: warning: "Compile using modified AOSP tree supporting full vendor value-adds"
[ 75% 1088/1440] including FAKE_TEST/Android.mk ...
FAILED:
In file included from out/soong/Android-bengal.mk:1047859:
In file included from FAKE_TEST/Android.mk:9:
In file included from build/make/core/prebuilt.mk:26:
build/make/core/prebuilt_internal.mk:62: error: fake_out : unexpected LOCAL_MODULE_CLASS for prebuilts: FAKE.
09:23:43 ckati failed with: exit status 1
注意:本篇的介绍是基于Android 11平台为基础的!
也许读者看到这里就会心里想了,既然Android 11不支持LOCAL_MODULE_CLASS为FAKE类型的,那不用它不就是了换一个方式实现吗,譬如PRODUCT_COPY_FILES关键词来实现不就好了,读者提出了这个解决方法那么证明是对Android的编译是有一定理解的。但是由于历史原因(我们的一套代码需要适配从Android 4.2到Android 11的整个编译环境),且由于我们的很多地方都使用到了FAKE的这种LOCAL_MODULE_CLASS所以此种办法不能采纳。那么我是怎么解决的呢!让我为大家徐徐展开慢慢分析!
由于源码牵涉到公司,所以这里我自己编写了一个非常简单的Android.mk来还原现场(不要问我为啥不用Android.bp历史包袱啊),其Android.mk定义如下:
LOCAL_PATH := $(call my-dir)
###############################################
include $(CLEAR_VARS)
LOCAL_MODULE := fake_out
LOCAL_MODULE_PATH := $(TARGET_OUT)/preinstall/undetermined
LOCAL_SRC_FILES := fake
LOCAL_MODULE_CLASS := FAKE
include $(BUILD_PREBUILT)
非常简单的mk配置文件,这个我就不过多解释了!我们执行mm编译的时候机会报文章开头说的错误了,如下:
build/make/core/main.mk:368: warning: "Compile using modified AOSP tree supporting full vendor value-adds"
[ 75% 1088/1440] including FAKE_TEST/Android.mk ...
FAILED:
In file included from out/soong/Android-bengal.mk:1047859:
In file included from FAKE_TEST/Android.mk:9:
In file included from build/make/core/prebuilt.mk:26:
build/make/core/prebuilt_internal.mk:62: error: fake_out : unexpected LOCAL_MODULE_CLASS for prebuilts: FAKE.
09:23:43 ckati failed with: exit status 1
上面我们看到错误的最终产生位置在prebuilt_internal.mk的62行,我们用编辑器看看为啥会产生这个原因!
//build/make/core/prebuilt.mk
53 ifeq (APPS,$(LOCAL_MODULE_CLASS))
54 include $(BUILD_SYSTEM)/app_prebuilt_internal.mk
55 else ifeq (JAVA_LIBRARIES,$(LOCAL_MODULE_CLASS))
56 include $(BUILD_SYSTEM)/java_prebuilt_internal.mk
57 else ifneq ($(filter STATIC_LIBRARIES SHARED_LIBRARIES EXECUTABLES NATIVE_TESTS,$(LOCAL_MODULE_CLASS)),)
58 include $(BUILD_SYSTEM)/cc_prebuilt_internal.mk
59 else ifneq ($(filter SCRIPT ETC DATA RENDERSCRIPT_BITCODE,$(LOCAL_MODULE_CLASS)),)
60 include $(BUILD_SYSTEM)/misc_prebuilt_internal.mk
61 else
62 $(error $(LOCAL_MODULE) : unexpected LOCAL_MODULE_CLASS for prebuilts: $(LOCAL_MODULE_CLASS))
63 endif
可以看到在62明显标出了不支持FAKE类型的LOCAL_MODULE_CLASS了,i看到这里当时我心里快速的产生了如下的几个解决方案:
既然Android 11以前的版本支持FAKE类型的是否可以移植过来,此方法由于功力有限没有找到怎么直接支持的方法
忽略此错误,实时证明也不行,编译时不会生成对应的LOCAL_MODULE模块而是直接报错
FAILED: ninja: unknown target 'MODULES-IN-FAKE_TEST'
10:01:27 ninja failed with: exit status 1
难道我们就此被这个简单的问题打到了吗,当然不是!任何困难都是难不倒我们伟大的工程师的,这里我反思了下其实FAKE和ETC的功能是差不多的,只是它们默认的指定的LOCAL_MODULE_PATH不同而已(即编译产生的文件生成位置),如下:
TARGET_OUT_ETC := $(TARGET_OUT)/etc
TARGET_OUT_FAKE := $(PRODUCT_OUT)/fake_packages
而恰好我们的mk文件都有指定了LOCAL_MODULE_PATH,所以就不需要担心这个了,所以我在这里决定来一个偷天换日解决错误,即当我们检测到有编译配置文件指定了LOCAL_MODULE_CLASS为FAKE我们强制转换为ETC,如下所示:
#Android 11 deprecated FAKE so use ETC replace it
ifeq (FAKE,$(LOCAL_MODULE_CLASS))
LOCAL_MODULE_CLASS := ETC
endif
ifeq (APPS,$(LOCAL_MODULE_CLASS))
include $(BUILD_SYSTEM)/app_prebuilt_internal.mk
else ifeq (JAVA_LIBRARIES,$(LOCAL_MODULE_CLASS))
include $(BUILD_SYSTEM)/java_prebuilt_internal.mk
else ifneq ($(filter STATIC_LIBRARIES SHARED_LIBRARIES EXECUTABLES NATIVE_TESTS,$(LOCAL_MODULE_CLASS)),)
include $(BUILD_SYSTEM)/cc_prebuilt_internal.mk
else ifneq ($(filter SCRIPT ETC DATA RENDERSCRIPT_BITCODE,$(LOCAL_MODULE_CLASS)),)
include $(BUILD_SYSTEM)/misc_prebuilt_internal.mk
else
#$(error $(LOCAL_MODULE) : unexpected LOCAL_MODULE_CLASS for prebuilts: $(LOCAL_MODULE_CLASS))
endif
见证奇迹的时候到了,我们来编译一把!编译结果如下:
[100% 357/357] Install: out/target/product/bengal/system/preinstall/undetermined/fake_out
#### build completed successfully (01:39 (mm:ss)) ####
这里通过偷天换日的方法巧妙的将FAKE替换成ETC的前提是,有指定了LOCAL_MODULE_PATH的路径,否则虽然能达到目的,但是如果没有在编译配置文件指定LOCAL_MODULE_PATH就会使用默认的,只能达到一半的效果。
好了今天的博客Android 11 unexpected LOCAL_MODULE_CLASS for prebuilts: FAKE就到这里了。总之,青山不改绿水长流先到这里了。如果本博客对你有所帮助,麻烦关注或者点个赞,如果觉得很烂也可以踩一脚!谢谢各位了!!