R8 混淆后接口中 Kotlin 泛型类型参数的问题
Issue with Kotlin generic's type argument in interface after R8 obfuscation
无法弄清楚如何正确设置 R8 混淆规则以保持我的界面正常工作。
我正在发布一个库。它到处都有混淆代码,除了 public API.
有一个基本接口BaseFoo
,在签名中有一个类型参数:
interface BaseFoo<D, E> {
fun handle(result: SomeOtherClass<D, E>): Boolean
}
然后有一个class Bar
,其中声明了派生接口DerivedFoo
:
class Bar {
interface DerivedFoo : BaseFoo<Alice, Bob>
}
使用 R8 混淆发布此代码后,尝试使用此库的接口 DerivedFoo
失败:
val myDerivedFoo = object : Bar.DerivedFoo {
override fun handle(result: SomeOtherClass<Alice, Bob>): Boolean {
return false
}
}
object
这里显示错误:
Object is not abstract and does not implement abstract member public abstract fun handle(result: SomeOtherClass<Alice, Bob>): Boolean defined in com.example.Bar.DerivedFoo
分别handle
方法给出了
'handle' overrides nothing
错误。如果您在此处使用自动完成创建覆盖函数,您将得到:
override fun handle(result: SomeOtherClass<D, E>): Boolean {
}
即 - 完全使用 <D, E>
通用参数(而不是 <Alice, Bob>
),尽管编译器不知道 D
和 E
是什么.
到目前为止混淆配置设置了这些规则:
-keeppackagenames com.example.**
-keep public class com.example.Bar { *; }
-keep public interface com.example.Bar$DerivedFoo { *; }
# Common rules:
-optimizationpasses 5
-dontusemixedcaseclassnames
-dontskipnonpubliclibraryclasses
-dontpreverify
-dontshrink
-verbose
-ignorewarnings
-renamesourcefileattribute SourceFile
-keepattributes SourceFile,LineNumberTable,*Annotation*,Signature,InnerClasses,EnclosingMethod,MethodParameters,Exceptions
-keepparameternames
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*,!code/allocation/variable
任何人都可以阐明如何处理这个丢失的派生接口签名吗?
更新:可以找到存在重现问题的样本here
看起来配置是正确的,一切都应该工作。但我猜这不是因为一些 Kotlin 互操作性问题。
好消息是,除了其他与 Kotlin 相关的问题外,此问题已在 2.1.42 版本中得到修复。
所以给定问题的解决方案是强制使用相应的 R8 版本:
buildscript {
repositories {
maven {
url 'https://storage.googleapis.com/r8-releases/raw'
}
}
dependencies {
classpath 'com.android.tools:r8:2.1.42' // Must be before the Gradle Plugin for Android.
classpath 'com.android.tools.build:gradle:X.Y.Z' // Your current AGP version.
}
}
致谢名单
无法弄清楚如何正确设置 R8 混淆规则以保持我的界面正常工作。
我正在发布一个库。它到处都有混淆代码,除了 public API.
有一个基本接口BaseFoo
,在签名中有一个类型参数:
interface BaseFoo<D, E> {
fun handle(result: SomeOtherClass<D, E>): Boolean
}
然后有一个class Bar
,其中声明了派生接口DerivedFoo
:
class Bar {
interface DerivedFoo : BaseFoo<Alice, Bob>
}
使用 R8 混淆发布此代码后,尝试使用此库的接口 DerivedFoo
失败:
val myDerivedFoo = object : Bar.DerivedFoo {
override fun handle(result: SomeOtherClass<Alice, Bob>): Boolean {
return false
}
}
object
这里显示错误:
Object is not abstract and does not implement abstract member public abstract fun handle(result: SomeOtherClass<Alice, Bob>): Boolean defined in com.example.Bar.DerivedFoo
分别handle
方法给出了
'handle' overrides nothing
错误。如果您在此处使用自动完成创建覆盖函数,您将得到:
override fun handle(result: SomeOtherClass<D, E>): Boolean {
}
即 - 完全使用 <D, E>
通用参数(而不是 <Alice, Bob>
),尽管编译器不知道 D
和 E
是什么.
到目前为止混淆配置设置了这些规则:
-keeppackagenames com.example.**
-keep public class com.example.Bar { *; }
-keep public interface com.example.Bar$DerivedFoo { *; }
# Common rules:
-optimizationpasses 5
-dontusemixedcaseclassnames
-dontskipnonpubliclibraryclasses
-dontpreverify
-dontshrink
-verbose
-ignorewarnings
-renamesourcefileattribute SourceFile
-keepattributes SourceFile,LineNumberTable,*Annotation*,Signature,InnerClasses,EnclosingMethod,MethodParameters,Exceptions
-keepparameternames
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*,!code/allocation/variable
任何人都可以阐明如何处理这个丢失的派生接口签名吗?
更新:可以找到存在重现问题的样本here
看起来配置是正确的,一切都应该工作。但我猜这不是因为一些 Kotlin 互操作性问题。
好消息是,除了其他与 Kotlin 相关的问题外,此问题已在 2.1.42 版本中得到修复。
所以给定问题的解决方案是强制使用相应的 R8 版本:
buildscript {
repositories {
maven {
url 'https://storage.googleapis.com/r8-releases/raw'
}
}
dependencies {
classpath 'com.android.tools:r8:2.1.42' // Must be before the Gradle Plugin for Android.
classpath 'com.android.tools.build:gradle:X.Y.Z' // Your current AGP version.
}
}
致谢名单