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
62 changes: 56 additions & 6 deletions README.md
Expand Up @@ -175,12 +175,62 @@ 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 rules to your `proguard-rules.pro` configuration to cover all classes that are serialized at runtime.

The following configuration keeps serializers for _all_ serializable classes that are retained after shrinking.
Uncomment and modify the last section in case you're serializing classes with named companion objects.

```proguard
# 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> {
static <1>$Companion Companion;
}

# Keep `serializer()` on companion objects (both default and named) of serializable classes.
-if @kotlinx.serialization.Serializable class ** {
static **$* *;
}
-keepclassmembers class <1>$<3> {
kotlinx.serialization.KSerializer serializer(...);
}

# Keep `INSTANCE.serializer()` of serializable objects.
-if @kotlinx.serialization.Serializable class ** {
public static ** INSTANCE;
}
-keepclassmembers class <1> {
public static <1> INSTANCE;
kotlinx.serialization.KSerializer serializer(...);
}

# @Serializable and @Polymorphic are used at runtime for polymorphic serialization.
-keepattributes RuntimeVisibleAnnotations,AnnotationDefault

# 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
#{
# static **$* *;
#}
#-keepnames class <1>$$serializer { # -keepnames suffices; class is kept when serializer() is kept.
# static <1>$$serializer INSTANCE;
#}
```

In case you want to exclude serializable classes that are used, but never serialized at runtime,
you will need to write custom rules with narrower [class specifications](https://www.guardsquare.com/manual/configuration/usage).

<details>
<summary>Example of custom rules</summary>

```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
-keepattributes RuntimeVisibleAnnotations,AnnotationDefault

# kotlinx-serialization-json specific. Add this if you have java.lang.NoClassDefFoundError kotlinx.serialization.json.JsonObjectSerializer
-keepclassmembers class kotlinx.serialization.json.** {
Expand Down Expand Up @@ -208,12 +258,12 @@ to add this to your `proguard-rules.pro`:

# 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.
-keepattributes InnerClasses # Needed for `getDeclaredClasses`.
-keep class com.yourcompany.yourpackage.SerializableClassWithNamedCompanion$$serializer {
*** INSTANCE;
}
```

You may also want to keep all custom serializers you've defined.
</details>

### Multiplatform (Common, JS, Native)

Expand Down