Android 11 unexpected LOCAL_MODULE_CLASS for prebuilts: FAKE

 unexpected LOCAL_MODULE_CLASS for prebuilts: FAKE


引言

  又有好久没有写点偏重实战类型的博客了,最近一直都在捣鼓源码分析和项目相关事情,是时候来点偏重实战类型的博客了。捯饬点啥实战的呢,正好最近在迁移项目到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所以此种办法不能采纳。那么我是怎么解决的呢!让我为大家徐徐展开慢慢分析!


1.1 错误的产生

由于源码牵涉到公司,所以这里我自己编写了一个非常简单的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

1.2 偷天换日,解决错误

上面我们看到错误的最终产生位置在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

1.3 收获成果

见证奇迹的时候到了,我们来编译一把!编译结果如下:

[100% 357/357] Install: out/target/product/bengal/system/preinstall/undetermined/fake_out

#### build completed successfully (01:39 (mm:ss)) ####

1.4 小结

这里通过偷天换日的方法巧妙的将FAKE替换成ETC的前提是,有指定了LOCAL_MODULE_PATH的路径,否则虽然能达到目的,但是如果没有在编译配置文件指定LOCAL_MODULE_PATH就会使用默认的,只能达到一半的效果。




写在最后

  好了今天的博客Android 11 unexpected LOCAL_MODULE_CLASS for prebuilts: FAKE就到这里了。总之,青山不改绿水长流先到这里了。如果本博客对你有所帮助,麻烦关注或者点个赞,如果觉得很烂也可以踩一脚!谢谢各位了!!

你可能感兴趣的:(Android实战开发指南,理解Android,build系统,FAKE,prebuilts,Android预编译)