Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Easier to configure ProGuard rules #1721

Merged
merged 11 commits into from Oct 29, 2021
59 changes: 31 additions & 28 deletions README.md
Expand Up @@ -175,46 +175,49 @@ dependencies {

### Android

Library should work on Android "as is". If you're using proguard, you need
to add this to your `proguard-rules.pro`:
The library works on Android, but, if you're using ProGuard, you need
to add the following rules to your `proguard-rules.pro` configuration.
Uncomment and modify the relevant section in case you're serializing classes with named companion objects.

```proguard
-keepattributes *Annotation*, InnerClasses
shanshin marked this conversation as resolved.
Show resolved Hide resolved
-dontnote kotlinx.serialization.AnnotationsKt # core serialization annotations
Whathecode marked this conversation as resolved.
Show resolved Hide resolved
# Keep `Companion` object fields of serializable classes.
# This avoids serializer lookup through `getDeclaredClasses` as done for named companion objects.
-if @kotlinx.serialization.Serializable class **
shanshin marked this conversation as resolved.
Show resolved Hide resolved
-keepclassmembers class <1> {
public static <1>$Companion Companion;
Whathecode marked this conversation as resolved.
Show resolved Hide resolved
}

# kotlinx-serialization-json specific. Add this if you have java.lang.NoClassDefFoundError kotlinx.serialization.json.JsonObjectSerializer
-keepclassmembers class kotlinx.serialization.json.** {
*** Companion;
# Serializer for classes with named companion objects are retrieved using `getDeclaredClasses`.
shanshin marked this conversation as resolved.
Show resolved Hide resolved
# If you have any, uncomment and replace classes with those containing named companion objects.
#-keepattributes InnerClasses # Needed for `getDeclaredClasses`.
#-if @kotlinx.serialization.Serializable class
#com.example.myapplication.HasNamedCompanion, # <-- List serializable classes with named companions.
#com.example.myapplication.HasNamedCompanion2
#{
# public static **$* *;
Whathecode marked this conversation as resolved.
Show resolved Hide resolved
#}
#-keepnames class <1>$$serializer {
Whathecode marked this conversation as resolved.
Show resolved Hide resolved
# public static <1>$$serializer INSTANCE;
Whathecode marked this conversation as resolved.
Show resolved Hide resolved
#}

# Keep `serializer()` on companion objects of serializable classes.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please indicate in this comment that this rule applies to default (Companion) and named companions. This makes the rules easier to read.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As a small side effect, this rule will keep the serializer function for all nested classes, but this is a very rare case and this rule is the easiest way to support named companions.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this rule will keep the serializer function for all nested classes

It actually doesn't, because of the pattern matching. It will pass beyond the if check, but the <3> in -keepclassmembers class <1>$<3> will be the static field name defined in the if condition.

I tried with the following:

@Serializable
class HasSimpleCompanion( val output: String )
{
    class Test
    {
        fun answer() = 42
        fun serializer(): KSerializer<*> = HasSimpleCompanion.serializer()
    }
}

This would translate to -keepclassmembers class HasSimpleCompanion$Companion, not -keepclassmembers class HasSimpleCompanion$Test. There is no static field for normal inner classes.

serializer is still removed (answer() is used so the full class isn't removed) as shown in the usage.txt output:

com.example.myapplication.HasSimpleCompanion$Test:
public final kotlinx.serialization.KSerializer serializer()

-if @kotlinx.serialization.Serializable class ** {
public static **$* *;
Whathecode marked this conversation as resolved.
Show resolved Hide resolved
}
-keepclasseswithmembers class kotlinx.serialization.json.** {
-keepclassmembers class <1>$<3> {
kotlinx.serialization.KSerializer serializer(...);
}

# Application rules

# Change here com.yourcompany.yourpackage
-keepclassmembers @kotlinx.serialization.Serializable class com.yourcompany.yourpackage.** {
# lookup for plugin generated serializable classes
*** Companion;
# lookup for serializable objects
*** INSTANCE;
kotlinx.serialization.KSerializer serializer(...);
# Keep `INSTANCE.serializer()` of serializable objects.
-if @kotlinx.serialization.Serializable class ** {
Whathecode marked this conversation as resolved.
Show resolved Hide resolved
public static ** INSTANCE;
}
# lookup for plugin generated serializable classes
-if @kotlinx.serialization.Serializable class com.yourcompany.yourpackage.**
-keepclassmembers class com.yourcompany.yourpackage.<1>$Companion {
-keepclassmembers class <1> {
public static <1> INSTANCE;
kotlinx.serialization.KSerializer serializer(...);
}

# Serialization supports named companions but for such classes it is necessary to add an additional rule.
# This rule keeps serializer and serializable class from obfuscation. Therefore, it is recommended not to use wildcards in it, but to write rules for each such class.
-keep class com.yourcompany.yourpackage.SerializableClassWithNamedCompanion$$serializer {
*** INSTANCE;
}
```

You may also want to keep all custom serializers you've defined.

### Multiplatform (Common, JS, Native)

Most of the modules are also available for Kotlin/JS and Kotlin/Native.
Expand Down