diff --git a/build-logic/ide/src/main/java/FDroidConfig.kt b/build-logic/ide/src/main/java/FDroidConfig.kt index 1b29165a65..58f116da41 100644 --- a/build-logic/ide/src/main/java/FDroidConfig.kt +++ b/build-logic/ide/src/main/java/FDroidConfig.kt @@ -1,6 +1,3 @@ -import org.gradle.api.Project -import java.io.File - /* * This file is part of AndroidIDE. * @@ -18,6 +15,9 @@ import java.io.File * along with AndroidIDE. If not, see . */ +import org.gradle.api.Project +import java.io.File + /** * @author Akash Yadav */ @@ -28,6 +28,10 @@ object FDroidConfig { var isFDroidBuild: Boolean = false private set + get() = hasRead && field + + var fDroidBuildArch: String? = null + private set var fDroidVersionName: String? = null private set @@ -35,9 +39,14 @@ object FDroidConfig { var fDroidVersionCode: Int? = null private set + var fDroidAapt2File: String? = null + private set + const val PROP_FDROID_BUILD = "ide.build.fdroid" + const val PROP_FDROID_BUILD_ARCH = "ide.build.fdroid.arch" const val PROP_FDROID_BUILD_VERSION = "ide.build.fdroid.version" const val PROP_FDROID_BUILD_VERCODE = "ide.build.fdroid.vercode" + const val PROP_FDROID_AAPT2FILE = "ide.build.fdroid.aapt2File" fun load(project: Project) { val propsFile = File(project.rootDir, "fdroid.properties") @@ -56,7 +65,9 @@ object FDroidConfig { hasRead = true isFDroidBuild = properties.getProperty(PROP_FDROID_BUILD, null).toBoolean() + fDroidBuildArch = properties.getProperty(PROP_FDROID_BUILD_ARCH, null) fDroidVersionName = properties.getProperty(PROP_FDROID_BUILD_VERSION, null) fDroidVersionCode = properties.getProperty(PROP_FDROID_BUILD_VERCODE, null)?.toInt() + fDroidAapt2File = properties.getProperty(PROP_FDROID_AAPT2FILE, null) } } \ No newline at end of file diff --git a/build-logic/ide/src/main/java/com/itsaky/androidide/plugins/AndroidIDEAssetsPlugin.kt b/build-logic/ide/src/main/java/com/itsaky/androidide/plugins/AndroidIDEAssetsPlugin.kt index 5dd1bb2f3e..4777f5aa62 100644 --- a/build-logic/ide/src/main/java/com/itsaky/androidide/plugins/AndroidIDEAssetsPlugin.kt +++ b/build-logic/ide/src/main/java/com/itsaky/androidide/plugins/AndroidIDEAssetsPlugin.kt @@ -18,9 +18,11 @@ package com.itsaky.androidide.plugins import BuildConfig +import FDroidConfig import VersionUtils import com.android.build.api.variant.AndroidComponentsExtension import com.android.build.gradle.BaseExtension +import com.itsaky.androidide.plugins.conf.flavorsAbis import com.itsaky.androidide.plugins.tasks.AddAndroidJarToAssetsTask import com.itsaky.androidide.plugins.tasks.AddFileToAssetsTask import com.itsaky.androidide.plugins.tasks.DownloadAapt2Task @@ -31,6 +33,7 @@ import org.gradle.api.Plugin import org.gradle.api.Project import org.gradle.api.tasks.TaskProvider import org.gradle.configurationcache.extensions.capitalized +import java.io.File /** * Handles asset copying and generation. @@ -57,15 +60,7 @@ class AndroidIDEAssetsPlugin : Plugin { val androidComponentsExtension = extensions.getByType(AndroidComponentsExtension::class.java) val baseExtension = extensions.getByType(BaseExtension::class.java) - val aapt2Tasks = mutableMapOf>() - baseExtension.productFlavors.forEach { flavor -> - aapt2Tasks[flavor.name] = tasks.register("downloadAapt2${flavor.name.capitalized()}", - DownloadAapt2Task::class.java) { - arch.set(flavor.name) - checksum.set(AAPT2_CHECKSUMS[flavor.name] ?: throw IllegalStateException( - "Checksum for aapt2-${flavor.name} not found!")) - } - } + val aapt2Tasks = getAapt2DownloadTasks(baseExtension) val addAndroidJarTaskProvider = tasks.register("addAndroidJarToAssets", AddAndroidJarToAssetsTask::class.java) { @@ -74,9 +69,17 @@ class AndroidIDEAssetsPlugin : Plugin { androidComponentsExtension.onVariants { variant -> - val downloadAapt2TaskProvider = aapt2Tasks[variant.flavorName] - ?: throw IllegalStateException( - "'aapt2' task not registered for flavor '${variant.flavorName}'") + if (aapt2Tasks.isNotEmpty()) { + val downloadAapt2TaskProvider = aapt2Tasks[variant.flavorName] + ?: throw IllegalStateException( + "'aapt2' task not registered for flavor '${variant.flavorName}'") + + variant.sources.assets?.addGeneratedSourceDirectory(downloadAapt2TaskProvider, + DownloadAapt2Task::outputDirectory) + } else { + variant.sources.assets?.addStaticSourceDirectory( + getStaticFDroidAapt2Dir(variant.flavorName!!)) + } val variantNameCapitalized = variant.name.capitalized() @@ -86,9 +89,6 @@ class AndroidIDEAssetsPlugin : Plugin { variant.sources.assets?.addGeneratedSourceDirectory(addAndroidJarTaskProvider, AddAndroidJarToAssetsTask::outputDirectory) - variant.sources.assets?.addGeneratedSourceDirectory(downloadAapt2TaskProvider, - DownloadAapt2Task::outputDirectory) - // Init script generator val generateInitScript = tasks.register( "generate${variantNameCapitalized}InitScript", @@ -126,5 +126,64 @@ class AndroidIDEAssetsPlugin : Plugin { } } } + + private fun Project.getStaticFDroidAapt2Dir(flavorName: String): String { + val fdroidArch = FDroidConfig.fDroidBuildArch!! + val fdroidAapt2 = FDroidConfig.fDroidAapt2File!! + + require(fdroidArch in flavorsAbis.keys) { + "F-Droid arch '${fdroidArch}' is not supported!" + } + + + val inFile = File(fdroidAapt2) + require(inFile.exists() && inFile.isFile) { + "F-Droid AAPT2 file does not exist or is not a file: $inFile" + } + + val assetDir = project.layout.buildDirectory.dir("intermediates/fdroid-aapt2-${flavorName}") + .get().asFile + + if (assetDir.exists()) { + assetDir.deleteRecursively() + } + + assetDir.mkdirs() + + val outFile = File(assetDir, "data/$flavorName/aapt2") + outFile.parentFile.mkdirs() + + inFile.copyTo(outFile, overwrite = true) + + return assetDir.absolutePath + } + + private fun Project.getAapt2DownloadTasks( + baseExtension: BaseExtension + ): Map> { + + if (FDroidConfig.isFDroidBuild) { + // Do not download AAPT2 when building for F-Droid + return emptyMap() + } + + val aapt2Tasks = mutableMapOf>() + + baseExtension.productFlavors.forEach { flavor -> + + val task = tasks.register( + "downloadAapt2${flavor.name.capitalized()}", + DownloadAapt2Task::class.java + ) { + arch.set(flavor.name) + checksum.set(AAPT2_CHECKSUMS[flavor.name] ?: throw IllegalStateException( + "Checksum for aapt2-${flavor.name} not found!")) + } + + aapt2Tasks[flavor.name] = task + } + + return aapt2Tasks + } } diff --git a/build-logic/ide/src/main/java/com/itsaky/androidide/plugins/conf/AndroidModuleConf.kt b/build-logic/ide/src/main/java/com/itsaky/androidide/plugins/conf/AndroidModuleConf.kt index 77c033652b..79c6de81d0 100644 --- a/build-logic/ide/src/main/java/com/itsaky/androidide/plugins/conf/AndroidModuleConf.kt +++ b/build-logic/ide/src/main/java/com/itsaky/androidide/plugins/conf/AndroidModuleConf.kt @@ -33,9 +33,7 @@ import projectVersionCode * For example, if the base version code of the IDE is 270 (for v2.7.0), then for arm64-v8a * flavor, the version code will be `100 * 270 + 1` i.e. `2701` */ -// IMPORTANT: When changing the configuration here, make sure to update the following file: -// - /scripts/setup_fdroid_build.sh -private val flavorsAbis = mapOf("arm64-v8a" to 1, "armeabi-v7a" to 2, "x86_64" to 3) +internal val flavorsAbis = mapOf("arm64-v8a" to 1, "armeabi-v7a" to 2, "x86_64" to 3) private val disableCoreLibDesugaringForModules = arrayOf(":logsender", ":logger") fun Project.configureAndroidModule( diff --git a/build.gradle.kts b/build.gradle.kts index 5f1ce1a638..457cae3bab 100755 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -41,6 +41,9 @@ buildscript { } subprojects { + // Always load the F-Droid config + FDroidConfig.load(project) + afterEvaluate { apply { plugin(AndroidIDEPlugin::class.java) } }