diff --git a/example/thirdparty/android-compose-samples/build.mill b/example/thirdparty/android-compose-samples/build.mill index 9d54cd11eb78..a197fd19e812 100644 --- a/example/thirdparty/android-compose-samples/build.mill +++ b/example/thirdparty/android-compose-samples/build.mill @@ -2,7 +2,6 @@ import mill.*, androidlib.*, kotlinlib.* object Versions { val kotlinVersion = "2.1.20" - val kotlinLanguageVersion = "1.9" val androidCompileSdk = 33 val androidMinSdk = 21 @@ -17,14 +16,8 @@ object JetLagged extends mill.api.Module { object app extends AndroidAppKotlinModule, AndroidR8AppModule { def kotlinVersion = Versions.kotlinVersion - def kotlinLanguageVersion = Versions.kotlinLanguageVersion - def androidIsDebug = true - // FIXME: ideally R8 should compile without erroring, but the app seems to be working - // without some reportedly missing classes. - override def androidR8Args = Seq("--map-diagnostics", "error", "warning") - override def androidDebugSettings: T[AndroidBuildTypeSettings] = Task { AndroidBuildTypeSettings( isMinifyEnabled = false, @@ -65,15 +58,8 @@ object JetLagged extends mill.api.Module { mvn"androidx.lifecycle:lifecycle-viewmodel-compose:2.9.0", mvn"androidx.lifecycle:lifecycle-viewmodel-ktx:2.9.0", mvn"androidx.navigation:navigation-compose:2.9.0", - mvn"androidx.emoji2:emoji2:1.5.0", - mvn"androidx.emoji2:emoji2-views:1.5.0", - mvn"androidx.emoji2:emoji2-bundled:1.5.0", mvn"androidx.window:window:1.4.0", - mvn"androidx.window.extensions.core:core:1.0.0", mvn"androidx.constraintlayout:constraintlayout-compose:1.1.1", - mvn"io.coil-kt:coil-compose:2.7.0", - mvn"androidx.customview:customview-poolingcontainer:1.0.0", - mvn"androidx.tracing:tracing:1.2.0", mvn"org.jetbrains.kotlinx:kotlinx-serialization-json:1.8.1", // version is resolved from compose-bom @@ -83,7 +69,6 @@ object JetLagged extends mill.api.Module { mvn"androidx.compose.ui:ui-util", mvn"androidx.compose.material3:material3", mvn"androidx.compose.animation:animation", - mvn"androidx.compose.animation:animation-tooling-internal", mvn"androidx.compose.material:material-icons-extended", mvn"androidx.compose.material:material", mvn"androidx.compose.material3:material3-window-size-class", @@ -121,10 +106,6 @@ object JetLagged extends mill.api.Module { true } - // FIXME: ideally R8 should compile without erroring, but the app seems to be working - // without some reportedly missing classes. - override def androidR8Args = Seq("--map-diagnostics", "error", "warning") - def mvnDeps = super.mvnDeps() ++ Seq( mvn"junit:junit:4.13.2", mvn"androidx.test:core:1.6.1", @@ -144,14 +125,8 @@ object JetNews extends mill.api.Module { object app extends AndroidAppKotlinModule, AndroidR8AppModule { def kotlinVersion = Versions.kotlinVersion - def kotlinLanguageVersion = Versions.kotlinLanguageVersion - def androidIsDebug = true - // FIXME: ideally R8 should compile without erroring, but the app seems to be working - // without some reportedly missing classes. - override def androidR8Args = Seq("--map-diagnostics", "error", "warning") - override def androidDebugSettings: T[AndroidBuildTypeSettings] = Task { AndroidBuildTypeSettings( isMinifyEnabled = false, @@ -191,15 +166,8 @@ object JetNews extends mill.api.Module { mvn"androidx.lifecycle:lifecycle-viewmodel-compose:2.9.0", mvn"androidx.lifecycle:lifecycle-viewmodel-ktx:2.9.0", mvn"androidx.navigation:navigation-compose:2.9.0", - mvn"androidx.emoji2:emoji2:1.5.0", - mvn"androidx.emoji2:emoji2-views:1.5.0", - mvn"androidx.emoji2:emoji2-bundled:1.5.0", mvn"androidx.window:window:1.4.0", - mvn"androidx.window.extensions.core:core:1.0.0", mvn"androidx.constraintlayout:constraintlayout-compose:1.1.1", - mvn"io.coil-kt:coil-compose:2.7.0", - mvn"androidx.customview:customview-poolingcontainer:1.0.0", - mvn"androidx.tracing:tracing:1.2.0", mvn"org.jetbrains.kotlinx:kotlinx-serialization-json:1.8.1", mvn"androidx.glance:glance-appwidget:1.2.0-alpha01", mvn"androidx.glance:glance-material3:1.2.0-alpha01", @@ -249,10 +217,6 @@ object JetNews extends mill.api.Module { true } - // FIXME: ideally R8 should compile without erroring, but the app seems to be working - // without some reportedly missing classes. - override def androidR8Args = Seq("--map-diagnostics", "error", "warning") - def mvnDeps = super.mvnDeps() ++ Seq( mvn"junit:junit:4.13.2", mvn"androidx.test:core:1.6.1", diff --git a/example/thirdparty/androidtodo/build.mill b/example/thirdparty/androidtodo/build.mill index 2b641b309372..13c72ee97c0e 100644 --- a/example/thirdparty/androidtodo/build.mill +++ b/example/thirdparty/androidtodo/build.mill @@ -77,7 +77,6 @@ object app mvn"androidx.room:room-ktx:2.7.1", mvn"androidx.activity:activity-compose:1.10.0", mvn"androidx.navigation:navigation-compose:2.8.5", - mvn"androidx.emoji2:emoji2:1.3.0", mvn"androidx.lifecycle:lifecycle-common:2.8.7", mvn"androidx.lifecycle:lifecycle-process:2.8.7", mvn"androidx.lifecycle:lifecycle-runtime-compose:2.8.7", @@ -87,8 +86,6 @@ object app mvn"com.google.dagger:hilt-android:2.56", mvn"androidx.hilt:hilt-navigation-compose:1.2.0", mvn"com.google.accompanist:accompanist-swiperefresh:0.36.0", - mvn"androidx.customview:customview-poolingcontainer:1.0.0", - mvn"androidx.tracing:tracing:1.2.0", // versions are resolved with compose-bom mvn"androidx.compose.foundation:foundation", diff --git a/libs/androidlib/resources/proguard-android-test.txt b/libs/androidlib/resources/proguard-android-test.txt new file mode 100644 index 000000000000..ca4c4a1132d7 --- /dev/null +++ b/libs/androidlib/resources/proguard-android-test.txt @@ -0,0 +1,2 @@ +#junit transitive dependency, referencing javax.lang +-dontwarn com.google.errorprone.annotations.** \ No newline at end of file diff --git a/libs/androidlib/resources/proguard-common.txt b/libs/androidlib/resources/proguard-common.txt new file mode 100644 index 000000000000..08abc76acd68 --- /dev/null +++ b/libs/androidlib/resources/proguard-common.txt @@ -0,0 +1,94 @@ +# https://android.googlesource.com/platform/tools/base/+/refs/heads/studio-master-dev/build-system/gradle-core/src/main/resources/com/android/build/gradle/proguard-common.txt +-dontusemixedcaseclassnames +-dontskipnonpubliclibraryclasses +-verbose + +# Preserve some attributes that may be required for reflection. +-keepattributes *Annotation*,Signature,InnerClasses,EnclosingMethod + +-keep public class com.google.vending.licensing.ILicensingService +-keep public class com.android.vending.licensing.ILicensingService +-keep public class com.google.android.vending.licensing.ILicensingService +-dontnote com.android.vending.licensing.ILicensingService +-dontnote com.google.vending.licensing.ILicensingService +-dontnote com.google.android.vending.licensing.ILicensingService + +# For native methods, see http://proguard.sourceforge.net/manual/examples.html#native +-keepclasseswithmembernames,includedescriptorclasses class * { + native ; +} + +# Keep setters in Views so that animations can still work. +-keepclassmembers public class * extends android.view.View { + void set*(***); + *** get*(); +} + +# We want to keep methods in Activity that could be used in the XML attribute onClick. +-keepclassmembers class * extends android.app.Activity { + public void *(android.view.View); +} + +# For enumeration classes, see http://proguard.sourceforge.net/manual/examples.html#enumerations +-keepclassmembers enum * { + public static **[] values(); + public static ** valueOf(java.lang.String); +} + +-keepclassmembers class * implements android.os.Parcelable { + public static final ** CREATOR; +} + +# Preserve annotated Javascript interface methods. +-keepclassmembers class * { + @android.webkit.JavascriptInterface ; +} + +# The support libraries contains references to newer platform versions. +# Don't warn about those in case this app is linking against an older +# platform version. We know about them, and they are safe. +-dontnote android.support.** +-dontnote androidx.** +-dontwarn android.support.** +-dontwarn androidx.** + +# This class is deprecated, but remains for backward compatibility. +-dontwarn android.util.FloatMath + +# Understand the @Keep support annotation. +-keep class android.support.annotation.Keep +-keep class androidx.annotation.Keep + +-keep @android.support.annotation.Keep class * {*;} +-keep @androidx.annotation.Keep class * {*;} + +-keepclasseswithmembers class * { + @android.support.annotation.Keep ; +} + +-keepclasseswithmembers class * { + @androidx.annotation.Keep ; +} + +-keepclasseswithmembers class * { + @android.support.annotation.Keep ; +} + +-keepclasseswithmembers class * { + @androidx.annotation.Keep ; +} + +-keepclasseswithmembers class * { + @android.support.annotation.Keep (...); +} + +-keepclasseswithmembers class * { + @androidx.annotation.Keep (...); +} + +# These classes are duplicated between android.jar and org.apache.http.legacy.jar. +-dontnote org.apache.http.** +-dontnote android.net.http.** + +# These classes are duplicated between android.jar and core-lambda-stubs.jar. +-dontnote java.lang.invoke.** diff --git a/libs/androidlib/src/mill/androidlib/AndroidAppModule.scala b/libs/androidlib/src/mill/androidlib/AndroidAppModule.scala index 0f66efe85836..9ee05478fb45 100644 --- a/libs/androidlib/src/mill/androidlib/AndroidAppModule.scala +++ b/libs/androidlib/src/mill/androidlib/AndroidAppModule.scala @@ -917,6 +917,14 @@ trait AndroidAppModule extends AndroidModule { outer => "androidx.test.runner.AndroidJUnitRunner" } + override def androidCommonProguardFiles: T[Seq[PathRef]] = Task { + val resource = "proguard-android-test.txt" + val resourceUrl = getClass.getResourceAsStream(s"/$resource") + val dest = Task.dest / resource + os.write(dest, resourceUrl) + super.androidCommonProguardFiles() :+ PathRef(dest) + } + private def androidInstrumentedTestsBaseManifest: Task[Elem] = Task.Anon { val label = s"Tests for ${outer.androidApplicationId}" val instrumentationName = testFramework() diff --git a/libs/androidlib/src/mill/androidlib/AndroidModule.scala b/libs/androidlib/src/mill/androidlib/AndroidModule.scala index 72d81da5fbb6..040465aa0a28 100644 --- a/libs/androidlib/src/mill/androidlib/AndroidModule.scala +++ b/libs/androidlib/src/mill/androidlib/AndroidModule.scala @@ -172,6 +172,19 @@ trait AndroidModule extends JavaModule { outer => rules } + /** + * Common Proguard Rules used by AGP + * + * Source: https://android.googlesource.com/platform/tools/base/+/refs/heads/studio-master-dev/build-system/gradle-core/src/main/resources/com/android/build/gradle/proguard-common.txt + */ + def androidCommonProguardFiles: T[Seq[PathRef]] = Task { + val resource = "proguard-common.txt" + val resourceUrl = getClass.getResourceAsStream(s"/$resource") + val dest = Task.dest / resource + os.write(dest, resourceUrl) + Seq(PathRef(dest)) + } + def androidProguard: T[PathRef] = Task { val globalProguardFile = Task.dest / "global-proguard.pro" os.write(globalProguardFile, "") diff --git a/libs/androidlib/src/mill/androidlib/AndroidR8AppModule.scala b/libs/androidlib/src/mill/androidlib/AndroidR8AppModule.scala index 74c2f22682e2..483abde3f2af 100644 --- a/libs/androidlib/src/mill/androidlib/AndroidR8AppModule.scala +++ b/libs/androidlib/src/mill/androidlib/AndroidR8AppModule.scala @@ -159,12 +159,14 @@ trait AndroidR8AppModule extends AndroidAppModule { val baselineOutOpt = destDir / "baseline-profile-rewritten.txt" destDir / "res" - // Create an extra ProGuard config file that instructs R8 to print seeds and usage. + // Instruct R8 to print seeds and usage. + val extraRules = Seq( + s"-printseeds $seedsOut", + s"-printusage $usageOut" + ) + // Create an extra ProGuard config file val extraRulesFile = destDir / "extra-rules.pro" - val extraRulesContent = - s"""-printseeds ${seedsOut.toString} - |-printusage ${usageOut.toString} - |""".stripMargin.trim + val extraRulesContent = extraRules.mkString("\n") os.write.over(extraRulesFile, extraRulesContent) val classpathClassFiles: Seq[PathRef] = androidPackagedClassfiles() @@ -228,8 +230,15 @@ trait AndroidR8AppModule extends AndroidAppModule { r8ArgsBuilder ++= libArgs - // ProGuard configuration files: add our extra rules file and all provided config files. - val pgArgs = Seq("--pg-conf", androidProguard().path.toString) + // ProGuard configuration files: add our extra rules file, + // all provided config files and the common rules. + val pgArgs = + Seq( + "--pg-conf", + androidProguard().path.toString, + "--pg-conf", + extraRulesFile.toString + ) ++ androidCommonProguardFiles().flatMap(pgf => Seq("--pg-conf", pgf.path.toString)) r8ArgsBuilder ++= pgArgs