Skip to content

Commit

Permalink
Easier to configure ProGuard rules (#1721)
Browse files Browse the repository at this point in the history
These rules only require modification when serializable classed with named companion objects are used, and even then, less than the previous rules.
  • Loading branch information
Whathecode committed Oct 29, 2021
1 parent b746ba8 commit f6a3432
Showing 1 changed file with 56 additions and 6 deletions.
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 **
-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`.
# 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
-dontnote kotlinx.serialization.AnnotationsKt # core serialization annotations
-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

0 comments on commit f6a3432

Please sign in to comment.