From 300851e31c831aa934688242020991222578685c Mon Sep 17 00:00:00 2001 From: oakkitten Date: Fri, 9 Feb 2024 18:57:58 +0000 Subject: [PATCH 1/7] Update Gradle & AGP to version 8 The changes in gradle.properties were made by the migration tool. This also disables the weaving of Cats, as transform API were disabled in AGP. Note that somehow the classes are still present, but actually triggering transformation results in an error. Cat weaving is fixed in a different way in the next commit. --- app/build.gradle.kts | 4 ++-- build.gradle.kts | 2 +- gradle.properties | 5 ++++- gradle/wrapper/gradle-wrapper.properties | 2 +- 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 157213ea..fcc04d68 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -184,7 +184,7 @@ fun weave(classPath: Iterable, aspectPath: Iterable, input: Iterable if (runInAProcess) { javaexec { classpath = weaving - main = "org.aspectj.tools.ajc.Main" + mainClass.set("org.aspectj.tools.ajc.Main") args = arguments } } else { @@ -290,7 +290,7 @@ dependencies { } } -android.registerTransform(TransformCats()) +//android.registerTransform(TransformCats()) val Iterable.asArgument get() = joinToString(File.pathSeparator) diff --git a/build.gradle.kts b/build.gradle.kts index 085d08ef..e531b971 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -27,7 +27,7 @@ buildscript { } dependencies { - classpath("com.android.tools.build:gradle:7.4.2") + classpath("com.android.tools.build:gradle:8.2.2") classpath("org.aspectj:aspectjtools:1.9.20.1") // updating to 1.9.21 leads to dexing errors classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.20") classpath("org.jetbrains.kotlin:kotlin-serialization:1.9.20") diff --git a/gradle.properties b/gradle.properties index b21b4399..3b695261 100644 --- a/gradle.properties +++ b/gradle.properties @@ -54,4 +54,7 @@ kapt.incremental.apt=true # The binary version of its metadata is 1.9.0, expected version is 1.7.1. # See answer by the_jk: https://stackoverflow.com/q/76690078/#76763654 # TODO Remove this after updating to AGP 8 -android.experimental.lint.version=8.3.0-alpha18 \ No newline at end of file +android.experimental.lint.version=8.3.0-alpha18 +android.defaults.buildfeatures.buildconfig=true +android.nonTransitiveRClass=false +android.nonFinalResIds=false \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 5fc5c88b..b80c76c0 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-all.zip From 43e41a159f5940176f5d44bc7911e362d0e50499 Mon Sep 17 00:00:00 2001 From: oakkitten Date: Sat, 10 Feb 2024 23:01:34 +0000 Subject: [PATCH 2/7] Use Android AspectJ Gradle Plugin to keep Cats We should be really moving away from AspectJ. However, for now there are no ready replacements for Cats, unless we are willing to get rid of annotation-based logging. Perhaps in the future Krang could be an option. Meanwhile, Android AspectJ Gradle Plugin seems to be actually working with AGP 8. Unfortunately, it is no longer maintained, but hopefully it can serve us at least until the next major version bump of AGP. AAGP: https://github.com/Ibotta/gradle-aspectj-pipeline-plugin Krang: https://github.com/milis92/Krang --- app/build.gradle.kts | 161 +++--------------------------------------- build.gradle.kts | 4 +- cats/build.gradle.kts | 2 +- 3 files changed, 15 insertions(+), 152 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index fcc04d68..7e2956db 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -1,11 +1,3 @@ -import com.android.build.api.transform.* -import com.android.build.api.variant.VariantInfo -import com.android.utils.FileUtils -import org.gradle.internal.os.OperatingSystem -import org.aspectj.bridge.IMessage -import org.aspectj.bridge.MessageHandler -import org.aspectj.tools.ajc.Main - plugins { id("com.android.application") kotlin("android") @@ -55,7 +47,7 @@ dependencies { implementation("org.greenrobot:eventbus:3.3.1") - debugImplementation("org.aspectj:aspectjrt:1.9.20.1") + debugImplementation("org.aspectj:aspectjrt:1.9.21") debugImplementation("com.squareup.leakcanary:leakcanary-android:2.12") testImplementation("org.junit.jupiter:junit-jupiter:5.10.1") @@ -157,148 +149,17 @@ fun versionBanner(): String { /////////////////////////////////////////////////////////////////////////////////////////////// cats //////////////////////////////////////////////////////////////////////////////////////////////////// -// ajc gets hold of some files such as R.jar, and on Windows it leads to errors such as: -// The process cannot access the file because it is being used by another process -// to avoid these, weave in a process, which `javaexec` will helpfully launch for us. - -fun weave(classPath: Iterable, aspectPath: Iterable, input: Iterable, output: File) { - val runInAProcess = OperatingSystem.current().isWindows - val bootClassPath = android.bootClasspath - - println(if (runInAProcess) ":: weaving in a process..." else ":: weaving...") - println(":: boot class path: $bootClassPath") - println(":: class path: $classPath") - println(":: aspect path: $aspectPath") - println(":: input: $input") - println(":: output: $output") - - val arguments = listOf("-showWeaveInfo", - "-1.8", - "-preserveAllLocals", - "-bootclasspath", bootClassPath.asArgument, - "-classpath", classPath.asArgument, - "-aspectpath", aspectPath.asArgument, - "-inpath", input.asArgument, - "-d", output.absolutePath) - - if (runInAProcess) { - javaexec { - classpath = weaving - mainClass.set("org.aspectj.tools.ajc.Main") - args = arguments - } - } else { - val handler = MessageHandler(true) - Main().run(arguments.toTypedArray(), handler) - - val log = project.logger - for (message in handler.getMessages(null, true)) { - when (message.kind) { - IMessage.DEBUG -> log.debug("DEBUG " + message.message, message.thrown) - IMessage.INFO -> log.info("INFO: " + message.message, message.thrown) - IMessage.WARNING -> log.warn("WARN: " + message.message, message.thrown) - IMessage.FAIL, - IMessage.ERROR, - IMessage.ABORT -> log.error("ERROR: " + message.message, message.thrown) - } - } - } -} - -// the only purpose of the following is to get a hold of aspectjtools jar -// this jar is already on build script classpath, but that classpath is impossible to get -// see https://discuss.gradle.org/t/how-do-i-determine-buildscript-classpath/37973/3 - -val weaving: Configuration by configurations.creating - -dependencies { - weaving("org.aspectj:aspectjtools:1.9.20.1") -} - -// historical note: the problem with weaving Kotlin and Java in-place is that: -// * Java is compiled by task compileDebugJavaWithJavac -// * gradle can run either one of these tasks, or both of them -// * compileDebugJavaWithJavac depends on compileDebugKotlin -// * weaving Kotlin requires Java classes +// This is hacky but it makes the AspectJ weaving only happen on debug builds. +// Note that `apply(plugin = ...)` prevents us from configuring a filter, +// which seems to require the unconditional syntax `plugin { id(...) }`. +// However, the filter somehow doesn't seem to work either way, even if we simplify it to this: // -// a transformation is a poorly advertised feature that works on merged code, and also has its own -// inputs and outputs, so this fixes all of our problems... - - class TransformCats : Transform() { - override fun getName(): String = TransformCats::class.simpleName!! - - override fun getInputTypes() = setOf(QualifiedContent.DefaultContentType.CLASSES) - - // only look for annotations in app classes - // transformation will consume these and put woven classes in the output dir - override fun getScopes() = mutableSetOf(QualifiedContent.Scope.PROJECT) - - // but also have the rest on our class path - // these will not be touched by the transformation - override fun getReferencedScopes() = mutableSetOf(QualifiedContent.Scope.SUB_PROJECTS, - QualifiedContent.Scope.EXTERNAL_LIBRARIES) - - override fun isIncremental() = false +// aopWeave { +// filter = "ubergeek42" +// } - // only run on debug builds - override fun applyToVariant(variant: VariantInfo) = variant.isDebuggable +val taskRequests = getGradle().startParameter.taskRequests.flatMap { it.args } - override fun transform(invocation: TransformInvocation) { - if (!invocation.isIncremental) { - invocation.outputProvider.deleteAll() - } - - val output = invocation.outputProvider.getContentLocation(name, outputTypes, - scopes, Format.DIRECTORY) - if (output.isDirectory) FileUtils.deleteDirectoryContents(output) - FileUtils.mkdirs(output) - - val input = mutableListOf() - val classPath = mutableListOf() - val aspectPath = mutableListOf() - - invocation.inputs.forEach { source -> - source.directoryInputs.forEach { dir -> - input.add(dir.file) - classPath.add(dir.file) - } - - source.jarInputs.forEach { jar -> - input.add(jar.file) - classPath.add(jar.file) - } - } - - invocation.referencedInputs.forEach { source -> - source.directoryInputs.forEach { dir -> - classPath.add(dir.file) - } - - source.jarInputs.forEach { jar -> - classPath.add(jar.file) - // this used to read `if (jar.name == ":cats") ...`, - // but with android gradle plugin 4.2.0 jar names contain garbage - // this is a very simple but a bit fragile workaround. todo improve - if (jar.file.directoriesInsideRootProject().contains("cats")) { - aspectPath.add(jar.file) - } - } - - } - - weave(classPath, aspectPath, input, output) - } -} - -//android.registerTransform(TransformCats()) - -val Iterable.asArgument get() = joinToString(File.pathSeparator) - -fun File.directoriesInsideRootProject() = sequence { - var file = this@directoriesInsideRootProject - while (true) { - yield(file.name) - file = file.parentFile ?: break - if (file == rootProject.projectDir) break - } +if (taskRequests.isNotEmpty() && taskRequests.all { "Debug" in it }) { + apply(plugin = "com.ibotta.gradle.aop") } diff --git a/build.gradle.kts b/build.gradle.kts index e531b971..b0c2b07f 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -24,13 +24,15 @@ buildscript { repositories { mavenCentral() google() + maven("https://plugins.gradle.org/m2/") } dependencies { classpath("com.android.tools.build:gradle:8.2.2") - classpath("org.aspectj:aspectjtools:1.9.20.1") // updating to 1.9.21 leads to dexing errors + classpath("org.aspectj:aspectjtools:1.9.21") classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.20") classpath("org.jetbrains.kotlin:kotlin-serialization:1.9.20") + classpath("com.ibotta:plugin:1.4.1") } } diff --git a/cats/build.gradle.kts b/cats/build.gradle.kts index ce0a5f1b..75885604 100644 --- a/cats/build.gradle.kts +++ b/cats/build.gradle.kts @@ -7,7 +7,7 @@ plugins { } dependencies { - implementation("org.aspectj:aspectjrt:1.9.20.1") + implementation("org.aspectj:aspectjrt:1.9.21") implementation("androidx.annotation:annotation:1.7.1") testImplementation("org.junit.jupiter:junit-jupiter:5.10.1") From 38fa6bbaabdf60fcf45be4d857a1f0464f316128 Mon Sep 17 00:00:00 2001 From: oakkitten Date: Sun, 11 Feb 2024 12:50:02 +0000 Subject: [PATCH 3/7] Remove explicit Kotlin linter version pin This is obsolete with AGP 8 --- gradle.properties | 7 ------- 1 file changed, 7 deletions(-) diff --git a/gradle.properties b/gradle.properties index 3b695261..321e7128 100644 --- a/gradle.properties +++ b/gradle.properties @@ -48,13 +48,6 @@ android.useAndroidX=true # kapt is the annotation processor for Kotlin kapt.incremental.apt=true -# Linter that comes with AGP 7.4.2 doesn't support Kotlin 1.9, so force a newer version. -# Suppresses messages like: -# Module was compiled with an incompatible version of Kotlin. -# The binary version of its metadata is 1.9.0, expected version is 1.7.1. -# See answer by the_jk: https://stackoverflow.com/q/76690078/#76763654 -# TODO Remove this after updating to AGP 8 -android.experimental.lint.version=8.3.0-alpha18 android.defaults.buildfeatures.buildconfig=true android.nonTransitiveRClass=false android.nonFinalResIds=false \ No newline at end of file From 05713fb4786e024a3355dbff476c68a4004c5a3a Mon Sep 17 00:00:00 2001 From: oakkitten Date: Sun, 11 Feb 2024 12:48:53 +0000 Subject: [PATCH 4/7] Disable Jetifier No longer needed as EventBus apparently supports AndroidX since 3.3 --- gradle.properties | 9 --------- 1 file changed, 9 deletions(-) diff --git a/gradle.properties b/gradle.properties index 321e7128..03afd360 100644 --- a/gradle.properties +++ b/gradle.properties @@ -18,19 +18,10 @@ org.gradle.jvmargs=-Xmx1024m -XX:MaxMetaspaceSize=512m android.enableR8.fullMode=true -# These are set by “Migrate to AndroidX” refactor -# When set to true, the Android plugin uses the appropriate AndroidX library instead of a Support -# Library. The flag is false by default if it is not specified. -android.enableJetifier=true - -# https://issuetracker.google.com/issues/159151549#comment7 -android.jetifier.ignorelist = bcprov-jdk15on-1.70.jar - # When set to true, the Android plugin automatically migrates existing third-party libraries to use # AndroidX by rewriting their binaries. The flag is false by default if it is not specified. android.useAndroidX=true - # Add the following to ~/.gradle/gradle.properties to build dev/release # Key info for creating the development release in the android market From 6f1d8ad43a81419343bf89a9b5f333efe3212989 Mon Sep 17 00:00:00 2001 From: oakkitten Date: Sun, 11 Feb 2024 13:12:57 +0000 Subject: [PATCH 5/7] Fix warning about `android.defaults.buildfeatures.buildconfig=true` This fixes the following warning warning: The option setting 'android.defaults.buildfeatures.buildconfig=true' is deprecated. The current default is 'false'. It will be removed in version 9.0 of the Android Gradle plugin. You can resolve this warning in Android Studio via `Refactor` > `Migrate BuildConfig to Gradle Build Files` --- app/build.gradle.kts | 1 + cats/build.gradle.kts | 4 ++++ gradle.properties | 1 - 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 7e2956db..1875d5be 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -133,6 +133,7 @@ android { buildFeatures { viewBinding = true + buildConfig = true } } diff --git a/cats/build.gradle.kts b/cats/build.gradle.kts index 75885604..8ff2fb99 100644 --- a/cats/build.gradle.kts +++ b/cats/build.gradle.kts @@ -38,6 +38,10 @@ android { targetSdk = 34 minSdk = 16 } + + buildFeatures { + buildConfig = true + } } tasks.withType { diff --git a/gradle.properties b/gradle.properties index 03afd360..2a4422fe 100644 --- a/gradle.properties +++ b/gradle.properties @@ -39,6 +39,5 @@ android.useAndroidX=true # kapt is the annotation processor for Kotlin kapt.incremental.apt=true -android.defaults.buildfeatures.buildconfig=true android.nonTransitiveRClass=false android.nonFinalResIds=false \ No newline at end of file From 80f623b16297b62b00c24c41b16f4f1bfbc42dd1 Mon Sep 17 00:00:00 2001 From: oakkitten Date: Sun, 11 Feb 2024 13:20:55 +0000 Subject: [PATCH 6/7] Use non-transitive R classes See https://blog.blundellapps.co.uk/speed-up-your-build-non-transitive-r-files/ --- .../java/androidx/preference/FullScreenEditTextPreference.java | 2 +- app/src/main/java/com/ubergeek42/WeechatAndroid/service/P.java | 2 +- gradle.properties | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/androidx/preference/FullScreenEditTextPreference.java b/app/src/main/java/androidx/preference/FullScreenEditTextPreference.java index bf2b91c1..bc3b6250 100644 --- a/app/src/main/java/androidx/preference/FullScreenEditTextPreference.java +++ b/app/src/main/java/androidx/preference/FullScreenEditTextPreference.java @@ -46,7 +46,7 @@ public FullScreenEditTextPreference(Context context) { @SuppressWarnings("WeakerAccess") public FullScreenEditTextPreference(Context context, AttributeSet attrs) { - this(context, attrs, R.attr.editTextPreferenceStyle); + this(context, attrs, androidx.preference.R.attr.editTextPreferenceStyle); } @SuppressWarnings("WeakerAccess") diff --git a/app/src/main/java/com/ubergeek42/WeechatAndroid/service/P.java b/app/src/main/java/com/ubergeek42/WeechatAndroid/service/P.java index c43495d1..5384156f 100644 --- a/app/src/main/java/com/ubergeek42/WeechatAndroid/service/P.java +++ b/app/src/main/java/com/ubergeek42/WeechatAndroid/service/P.java @@ -88,7 +88,7 @@ public class P implements SharedPreferences.OnSharedPreferenceChangeListener{ public static void storeThemeOrColorSchemeColors(Context context) { ColorScheme scheme = ColorScheme.get(); TypedArray colors = context.obtainStyledAttributes( - new int[] {R.attr.colorPrimary, R.attr.colorPrimaryDark, R.attr.toolbarIconColor}); + new int[] {androidx.appcompat.R.attr.colorPrimary, androidx.appcompat.R.attr.colorPrimaryDark, R.attr.toolbarIconColor}); colorPrimary = scheme.colorPrimary != ColorScheme.NO_COLOR ? scheme.colorPrimary : colors.getColor(0, ColorScheme.NO_COLOR); colorPrimaryDark = scheme.colorPrimaryDark != ColorScheme.NO_COLOR ? diff --git a/gradle.properties b/gradle.properties index 2a4422fe..9f932517 100644 --- a/gradle.properties +++ b/gradle.properties @@ -39,5 +39,5 @@ android.useAndroidX=true # kapt is the annotation processor for Kotlin kapt.incremental.apt=true -android.nonTransitiveRClass=false +android.nonTransitiveRClass=true android.nonFinalResIds=false \ No newline at end of file From da63de36025af26116e4a2a747b0bcedd2c126ef Mon Sep 17 00:00:00 2001 From: oakkitten Date: Sun, 11 Feb 2024 13:37:00 +0000 Subject: [PATCH 7/7] Add comment on `android.nonFinalResIds=false` --- gradle.properties | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/gradle.properties b/gradle.properties index 9f932517..5d67e82e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -40,4 +40,12 @@ android.useAndroidX=true kapt.incremental.apt=true android.nonTransitiveRClass=true + +# Using non-final resource IDs is supposed to improve compilation performance. +# The idea is that they must be unique among libraries, +# so in case of a collision recompilation is reqiured. +# However, in practice, after switching this to true (now default) I see +# * no difference in incremental build times, and +# * slight increase in a full build time, +# so let's leave it as it is for now. android.nonFinalResIds=false \ No newline at end of file