diff --git a/CHANGELOG.md b/CHANGELOG.md index 4cd30de..54f9bb5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,38 @@ called out explicitly even when nothing else did. release notes, so a version with no entry here does not release. Write the entry in the same PR that syncs the contract, while the diff is still in front of you. +## 0.3.0 + +No contract change. `ocp.lock` points at the same upstream commit as `0.2.0`, and the generated +Kotlin and Swift are unchanged. Swift consumers have nothing to gain from this release. + +### Added + +- The Kotlin artifact now ships R8 keep rules, at `META-INF/proguard/ocp-client-protocol.pro`: + + ```proguard + -keepclassmembers class * extends com.google.protobuf.GeneratedMessageLite { + ; + } + ``` + + protobuf-javalite ships no keep rules of its own, so until now every Android consumer had to + write one, and the obvious `-keep class * extends GeneratedMessageLite { *; }` is far wider + than javalite needs. javalite resolves *fields* reflectively — the schema built from + `newMessageInfo` looks up `java.lang.reflect.Field` by the generated `_` field — while + builders and message methods are reached from ordinary call sites, so R8 traces those without + help. `-keepclassmembers` also does not keep the class, so a message type nothing references is + still removed entirely. + + On upgrading, an Android consumer can delete its own protobuf keep rules. Dropping the wide + pair from `code-android-app` cut 25,542 live methods and 568 live classes, and moved its R8 + optimization score from 89.3% to 96.3%. + + The rule is deliberately not scoped to `com.codeinc.opencode.gen.**`. The well-known types (`Any`, `Timestamp`, + `Duration`, `Struct`) come from protobuf-javalite itself, and other dependencies ship generated + messages with no rules of their own, so a package-scoped rule would leave those broken under R8 + full mode. Both contract packages ship identical rule text; R8 collapses them into one entry. + ## 0.2.0 Synced to [`ocp-protobuf-api@ea6418c5`](https://github.com/code-payments/ocp-protobuf-api/commit/ea6418c5561e16771d456062be2fcbd3ddeb9caf). diff --git a/README.md b/README.md index 80b1d72..e48ff62 100644 --- a/README.md +++ b/README.md @@ -15,17 +15,20 @@ They are separate packages because the contracts are: flipcash2 does not import ## Install ```kotlin -implementation("com.flipcash:ocp-client-protocol:0.1.0") +implementation("com.flipcash:ocp-client-protocol:0.3.0") ``` ```swift -.package(url: "https://github.com/code-payments/ocp-client-protocol", from: "0.1.0") +.package(url: "https://github.com/code-payments/ocp-client-protocol", from: "0.3.0") ``` `code-android-app` pins the version in `gradle/libs.versions.toml`. `code-ios-app` pins it in `FlipcashAPI/Package.swift` and re-exports the module, so app code still reaches these types through `import FlipcashAPI`. +The Kotlin artifact ships its own R8 keep rules, so an Android consumer needs no protobuf keep +rule of its own. + ## What it contains Four services — `Account`, `Currency`, `Messaging`, `Transaction` — plus the shared @@ -38,6 +41,8 @@ this package was generated from. proto/ contract, synced from upstream at the SHA in ocp.lock proto_deps/validate/ include-path dependency, never generated Sources/OCPClientProtocol/ generated Swift, committed (SPM ships source) +src/main/resources/ + META-INF/proguard/ R8 keep rules, shipped to Kotlin consumers build.gradle.kts Kotlin generation + publishing scripts/ sync-protos.sh pull upstream at a pinned SHA, re-namespace diff --git a/src/main/resources/META-INF/proguard/ocp-client-protocol.pro b/src/main/resources/META-INF/proguard/ocp-client-protocol.pro new file mode 100644 index 0000000..5a0c877 --- /dev/null +++ b/src/main/resources/META-INF/proguard/ocp-client-protocol.pro @@ -0,0 +1,19 @@ +# R8/ProGuard rules for the generated protobuf messages in this artifact. +# +# protobuf-javalite ships no keep rules of its own, so without this every consumer +# app has to write it. javalite resolves fields reflectively: the schema built from +# newMessageInfo looks up java.lang.reflect.Field by the generated `_` field. +# Methods and builders are reached from ordinary call sites, so R8 traces them +# without help and they are deliberately not kept here. +# +# -keepclassmembers does not keep the class, so a message type nothing references +# is still removed entirely. The rule only applies to messages that survive on +# their own merit. +# +# Deliberately not scoped to this artifact's own package. The well-known types +# (Any, Timestamp, Duration, Struct) come from protobuf-javalite itself, and other +# dependencies ship generated messages with no rules of their own; a rule scoped to +# the generated package would leave those broken under R8 full mode. +-keepclassmembers class * extends com.google.protobuf.GeneratedMessageLite { + ; +}