Android O Jack预编译静态jar编译报错解决

1. 错误Pattern

编译错误原因:

/bin/bash -c "(mkdir -p out/target/common/obj/JAVA_LIBRARIES/TSWheelService_intermediates/classes.jack.tmpjill.res ) &&  
(unzip -qo vendor/test/scripts/static_jar/./../../prebuilt/java/static_jar/TSWheelService.jar -d out/target/common/obj/JAVA_LIBRARIES/TSWheelService_intermediates/classes.jack.tmpjill.res ) &&  
(find out/target/common/obj/JAVA_LIBRARIES/TSWheelService_intermediates/classes.jack.tmpjill.res -iname \"*.class\" -delete ) && (JACK_VERSION=4.32.CANDIDATE out/host/linux-x86/bin/jack @build/core/jack-default.args   
 -D jack.import.resource.policy=keep-first -D jack.import.type.policy=keep-first -D jack.android.min-api-level=1  
 --import vendor/chinatsp/scripts/static_jar/./../../prebuilt/java/static_jar/TSWheelService.jar --import-resource out/target/common/obj/JAVA_LIBRARIES/TSWheelService_intermediates/classes.jack.tmpjill.res --output-jack out/target/common/obj/JAVA_LIBRARIES/TSWheelService_intermediates/classes.jack ) && (rm -rf out/target/common/obj/JAVA_LIBRARIES/TSWheelService_intermediates/classes.jack.tmpjill.res )"
ERROR: src/com/test/proxy/test/TestManager.java:214: Default method void onPlayChange(int mode) not supported in Android API level less than 24

错误的位置是一个interface,使用了java1.8的default,报错是sdk小于24
@TestManager.java

public interface PlayStateChangedListener{
    default void onPlayChange(int mode) {}
}

2. 错误原理

通过上面log有发现 jack.android.min-api-level=1 而这里要求jack api level要24

源码里搜索: jack.android.min-api-level
结果发现都是来自于PRIVATE_JACK_MIN_SDK_VERSION

build/make/core/definitions.mk
2329 -D jack.android.min-api-level=$(PRIVATE_JACK_MIN_SDK_VERSION) \
2377 -D jack.android.min-api-level=$(PRIVATE_JACK_MIN_SDK_VERSION) \
2397 -D jack.android.min-api-level=$(PRIVATE_JACK_MIN_SDK_VERSION) \
2515 -D jack.android.min-api-level=$(PRIVATE_JACK_MIN_SDK_VERSION) \

搜索: PRIVATE_JACK_MIN_SDK_VERSION

从下面结果看,赋值分为了两个,一个是java.mk 一个是prebuilt_internal.mk,分别对应源码编译static java library和prebuilt java lirary,这里的区别就导致了源码编译不会报错,预编译会报错问题

@build/make/core/
host_dalvik_java_library.mk	
    173 $(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_JACK_MIN_SDK_VERSION := $(PLATFORM_JACK_MIN_SDK_VERSION) macro 
prebuilt_internal.mk	
    630 $(intermediates.COMMON)/classes.jack : PRIVATE_JACK_MIN_SDK_VERSION := $(if $(strip $(LOCAL_MIN_SDK_VERSION)),$(LOCAL_MIN_SDK_VERSION),1) macro 
java.mk	
    409 $(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_JACK_MIN_SDK_VERSION := $(my_jack_min_sdk_version) macro 
definitions.mk	
    2329 -D jack.android.min-api-level=$(PRIVATE_JACK_MIN_SDK_VERSION) \
    2377 -D jack.android.min-api-level=$(PRIVATE_JACK_MIN_SDK_VERSION) \
    2397 -D jack.android.min-api-level=$(PRIVATE_JACK_MIN_SDK_VERSION) \
    2515 -D jack.android.min-api-level=$(PRIVATE_JACK_MIN_SDK_VERSION) \

从源码里看,LOCAL_MIN_SDK_VERSION不指定的话,PRIVATE_JACK_MIN_SDK_VERSION就为1,就导致jack.android.min-api-level=1 ,因此修改方法是在预编译时候把LOCAL_MIN_SDK_VERSION改为24就可以

ifdef LOCAL_JACK_ENABLED
//add log
$(warning william PRIVATE_JACK_MIN_SDK_VERSION LOCAL_MIN_SDK_VERSION $(LOCAL_MIN_SDK_VERSION))

# We may be building classes.jack from a host jar for host dalvik Java library.
$(intermediates.COMMON)/classes.jack : PRIVATE_JACK_FLAGS:=$(LOCAL_JACK_FLAGS)
$(intermediates.COMMON)/classes.jack : PRIVATE_JACK_MIN_SDK_VERSION := $(if $(strip $(LOCAL_MIN_SDK_VERSION)),$(LOCAL_MIN_SDK_VERSION),1)
$(intermediates.COMMON)/classes.jack : PRIVATE_JACK_PLUGIN_PATH := $(LOCAL_JACK_PLUGIN_PATH)
$(intermediates.COMMON)/classes.jack : PRIVATE_JACK_PLUGIN := $(LOCAL_JACK_PLUGIN)
$(intermediates.COMMON)/classes.jack : $(LOCAL_JACK_PLUGIN_PATH) $(my_src_jar) \
        $(LOCAL_ADDITIONAL_DEPENDENCIES) $(JACK_DEFAULT_ARGS) $(JACK) \
        | setup-jack-server
	$(transform-jar-to-jack)
	@echo "william Building with Jack PRIVATE_JACK_MIN_SDK_VERSION : $(PRIVATE_JACK_MIN_SDK_VERSION) -$(LOCAL_MIN_SDK_VERSION)-"

3. 修改方法

首先在预编译里面添加 LOCAL_MIN_SDK_VERSION := 24 结果还是报错

include $(CLEAR_VARS)
LOCAL_CERTIFICATE := platform
LOCAL_MIN_SDK_VERSION := 24
LOCAL_MODULE_TAGS := optional
LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES := SWheelService:./SWheelService.jack
include $(BUILD_MULTI_PREBUILT)

查看log,发现prebuilt_internal.mk里面LOCAL_MIN_SDK_VERSION是null,导致没有赋值成功

BUILD_MULTI_PREBUILT:= $(BUILD_SYSTEM)/multi_prebuilt.mk

auto-prebuilt-boilerplate方法中的第一步,就是执行CLEAR_VARS,就把LOCAL_MIN_SDK_VERSION清空了,后面的参数没有sdk,因此BUILD_MULTI_PREBUILT就失效,不起作用

@build/make/core/prebuilt_internal.mk

# $(1): file list
# $(2): IS_HOST_MODULE
# $(3): MODULE_CLASS
# $(4): MODULE_TAGS
# $(5): OVERRIDE_BUILT_MODULE_PATH
# $(6): UNINSTALLABLE_MODULE
# $(7): BUILT_MODULE_STEM
# $(8): LOCAL_STRIP_MODULE
#
# Elements in the file list may be bare filenames,
# or of the form "<modulename>:<filename>".
# If the module name is not specified, the module
# name will be the filename with the suffix removed.
#
define auto-prebuilt-boilerplate
$(if $(filter %: :%,$(1)), \
  $(error $(LOCAL_PATH): Leading or trailing colons in "$(1)")) \
$(foreach t,$(1), \
  $(eval include $(CLEAR_VARS)) \
  $(eval LOCAL_IS_HOST_MODULE := $(2)) \
  $(eval LOCAL_MODULE_CLASS := $(3)) \
  $(eval LOCAL_MODULE_TAGS := $(4)) \
  $(eval OVERRIDE_BUILT_MODULE_PATH := $(5)) \
  $(eval LOCAL_UNINSTALLABLE_MODULE := $(6)) \
  $(eval tw := $(subst :, ,$(strip $(t)))) \
  $(if $(word 3,$(tw)),$(error $(LOCAL_PATH): Bad prebuilt filename '$(t)')) \
  $(if $(word 2,$(tw)), \
    $(eval LOCAL_MODULE := $(word 1,$(tw))) \
    $(eval LOCAL_SRC_FILES := $(word 2,$(tw))) \
   , \
    $(eval LOCAL_MODULE := $(basename $(notdir $(t)))) \
    $(eval LOCAL_SRC_FILES := $(t)) \
   ) \
  $(if $(7), \
    $(eval LOCAL_BUILT_MODULE_STEM := $(7)) \
   , \
    $(if $(word 2,$(tw)), \
      $(eval LOCAL_BUILT_MODULE_STEM := $(LOCAL_MODULE)$(suffix $(LOCAL_SRC_FILES))) \
     , \
      $(eval LOCAL_BUILT_MODULE_STEM := $(notdir $(LOCAL_SRC_FILES))) \
     ) \
   ) \
  $(eval LOCAL_MODULE_SUFFIX := $(suffix $(LOCAL_SRC_FILES))) \
  $(eval LOCAL_STRIP_MODULE := $(8)) \
  $(eval include $(BUILD_PREBUILT)) \
 )
endef

最终写法是把BUILD_MULTI_PREBUILT改为BUILD_PREBUILT,从上面代码看,BUILD_MULTI_PREBUILT也是循环使用BUILD_PREBUILT的,使用BUILD_PREBUILTlog就显示为24,可以编译通过

include $(CLEAR_VARS)
LOCAL_MODULE               := TSWheelService
LOCAL_MODULE_TAGS          := optional
LOCAL_MODULE_CLASS         := JAVA_LIBRARIES
LOCAL_MODULE_SUFFIX        := $(COMMON_JAVA_PACKAGE_SUFFIX)
LOCAL_SRC_FILES            := ./TSWheelService.jack
LOCAL_UNINSTALLABLE_MODULE := true
LOCAL_MIN_SDK_VERSION := 24
include $(BUILD_PREBUILT)

4.源码没有报错原理

上面有说源码使用的地方不一样,下面看最终使用的是PLATFORM_JACK_MIN_SDK_VERSION为o-b1,从注释看只是都是PLATFORM_SDK_VERSION := 27,因此不会报错

@build/make/core/java.mk
  ifeq ($(LOCAL_SDK_VERSION),current)
    my_jack_min_sdk_version := $(PLATFORM_JACK_MIN_SDK_VERSION)
  else ifeq ($(LOCAL_SDK_VERSION),system_current)
    my_jack_min_sdk_version := $(PLATFORM_JACK_MIN_SDK_VERSION)
  else ifeq ($(LOCAL_SDK_VERSION),test_current)
    my_jack_min_sdk_version := $(PLATFORM_JACK_MIN_SDK_VERSION)
  else
    my_jack_min_sdk_version := $(LOCAL_SDK_VERSION)
  endif

$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_JACK_MIN_SDK_VERSION := $(my_jack_min_sdk_version)
@build/make/core/version_defaults.mk
ifndef PLATFORM_SDK_VERSION
  PLATFORM_SDK_VERSION := 27
endif

ifndef PLATFORM_JACK_MIN_SDK_VERSION
  # This is definition of the min SDK version given to Jack for the current
  # platform. For released version it should be the same as
  # PLATFORM_SDK_VERSION. During development, this number may be incremented
  # before PLATFORM_SDK_VERSION if the platform starts to add new java
  # language supports.
  PLATFORM_JACK_MIN_SDK_VERSION := o-b1
endif
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值