Skip to content

Commit

Permalink
Added bundled proguard rules
Browse files Browse the repository at this point in the history
Resolves #1121
Resolves #1899
Resolves #1900
  • Loading branch information
shanshin committed Nov 8, 2022
1 parent 520eeef commit db45546
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 69 deletions.
74 changes: 5 additions & 69 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -176,40 +176,15 @@ dependencies {
### Android

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.
By default, proguard rules are supplied with the library.
[This rules](proguard-rules.pro) keeps serializers for _all_ serializable classes that are retained after shrinking.

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.
**These rules do not affect serializable 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;
}
If you want to serialize classes with named companion objects, you need to add and edit rule below to your `proguard-rules.pro` configuration.

# Keep `serializer()` on companion objects (both default and named) of serializable classes.
-if @kotlinx.serialization.Serializable class ** {
static **$* *;
}
-keepclassmembers class <2>$<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

```proguard
# 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`.
Expand All @@ -227,45 +202,6 @@ Uncomment and modify the last section in case you're serializing classes with na
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 RuntimeVisibleAnnotations,AnnotationDefault
# kotlinx-serialization-json specific. Add this if you have java.lang.NoClassDefFoundError kotlinx.serialization.json.JsonObjectSerializer
-keepclassmembers class kotlinx.serialization.json.** {
*** Companion;
}
-keepclasseswithmembers class kotlinx.serialization.json.** {
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(...);
}
# lookup for plugin generated serializable classes
-if @kotlinx.serialization.Serializable class com.yourcompany.yourpackage.**
-keepclassmembers class com.yourcompany.yourpackage.<1>$Companion {
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.
-keepattributes InnerClasses # Needed for `getDeclaredClasses`.
-keep class com.yourcompany.yourpackage.SerializableClassWithNamedCompanion$$serializer {
*** INSTANCE;
}
```
</details>

### Multiplatform (Common, JS, Native)

Most of the modules are also available for Kotlin/JS and Kotlin/Native.
Expand Down
16 changes: 16 additions & 0 deletions core/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,22 @@ kotlin {
to reject runtime if runtime's Require-Kotlin-Version is greater then the current compiler.
*/
tasks.withType(Jar).named(kotlin.jvm().artifactsTaskName) {

// adding the ProGuard rules to the jar
from(rootProject.file("proguard-rules.pro")) {
rename { "kotlinx-serialization.pro" }
into("META-INF/proguard")
}
from(rootProject.file("proguard-rules.pro")) {
rename { "kotlinx-serialization.pro" }
into("META-INF/com.android.tools/proguard")
}
from(rootProject.file("proguard-rules.pro")) {
rename { "kotlinx-serialization.pro" }
into("META-INF/com.android.tools/r8")
}


manifest {
attributes(
"Implementation-Version": version,
Expand Down
30 changes: 30 additions & 0 deletions proguard-rules.pro
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# 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 <2>$<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

# Don't print notes about potential mistakes or omissions in the configuration for kotlinx-serialization classes
# See also https://github.com/Kotlin/kotlinx.serialization/issues/1900
-dontnote kotlinx.serialization.**

0 comments on commit db45546

Please sign in to comment.