import com.android.build.api.dsl.ApplicationExtension import com.android.build.api.variant.ApplicationAndroidComponentsExtension import com.android.build.gradle.BaseExtension import org.eclipse.jgit.api.Git import org.eclipse.jgit.internal.storage.file.FileRepository plugins { id("com.android.application") apply false id("com.android.library") apply false } buildscript { repositories { google() mavenCentral() } dependencies { classpath("org.eclipse.jgit:org.eclipse.jgit:6.3.0.202209071007-r") classpath(kotlin("gradle-plugin", version = "1.7.20")) } } val commitCount = run { val repo = FileRepository(rootProject.file(".git")) val refId = repo.refDatabase.exactRef("refs/remotes/origin/master").objectId!! Git(repo).log().add(refId).call().count() } val coreCommitCount = run { val repo = FileRepository(rootProject.file(".git/modules/core")) val refId = repo.refDatabase.exactRef("HEAD").objectId!! Git(repo).log().add(refId).call().count() } // sync from https://github.com/LSPosed/LSPosed/blob/master/build.gradle.kts val defaultManagerPackageName by extra("org.lsposed.lspatch") val apiCode by extra(93) val verCode by extra(commitCount) val verName by extra("0.5.1") val coreVerCode by extra(coreCommitCount + 4200) val coreVerName by extra( file("$rootDir/core/build.gradle.kts").readLines() .find { it.startsWith("val verName by extra") }!! .split('"')[1] ) val androidMinSdkVersion by extra(28) val androidTargetSdkVersion by extra(33) val androidCompileSdkVersion by extra(33) val androidCompileNdkVersion by extra("25.1.8937393") val androidBuildToolsVersion by extra("32.0.0") val androidSourceCompatibility by extra(JavaVersion.VERSION_11) val androidTargetCompatibility by extra(JavaVersion.VERSION_11) tasks.register("clean") { delete(rootProject.buildDir) } listOf("Debug", "Release").forEach { variant -> tasks.register("build$variant") { description = "Build LSPatch with $variant" dependsOn(projects.jar.dependencyProject.tasks["build$variant"]) dependsOn(projects.manager.dependencyProject.tasks["build$variant"]) } } tasks.register("buildAll") { dependsOn("buildDebug", "buildRelease") } fun Project.configureBaseExtension() { extensions.findByType(BaseExtension::class)?.run { compileSdkVersion(androidCompileSdkVersion) ndkVersion = androidCompileNdkVersion buildToolsVersion = androidBuildToolsVersion externalNativeBuild.cmake { version = "3.22.1+" } defaultConfig { minSdk = androidMinSdkVersion targetSdk = androidTargetSdkVersion versionCode = verCode versionName = verName signingConfigs.create("config") { val androidStoreFile = project.findProperty("androidStoreFile") as String? if (!androidStoreFile.isNullOrEmpty()) { storeFile = rootProject.file(androidStoreFile) storePassword = project.property("androidStorePassword") as String keyAlias = project.property("androidKeyAlias") as String keyPassword = project.property("androidKeyPassword") as String } } externalNativeBuild { cmake { arguments += "-DEXTERNAL_ROOT=${File(rootDir.absolutePath, "core/external")}" arguments += "-DCORE_ROOT=${File(rootDir.absolutePath, "core/core/src/main/jni")}" abiFilters("arm64-v8a", "armeabi-v7a", "x86", "x86_64") val flags = arrayOf( "-Wall", "-Qunused-arguments", "-Wno-gnu-string-literal-operator-template", "-fno-rtti", "-fvisibility=hidden", "-fvisibility-inlines-hidden", "-fno-exceptions", "-fno-stack-protector", "-fomit-frame-pointer", "-Wno-builtin-macro-redefined", "-Wno-unused-value", "-D__FILE__=__FILE_NAME__", ) cppFlags("-std=c++20", *flags) cFlags("-std=c18", *flags) arguments( "-DANDROID_STL=none", "-DVERSION_CODE=$verCode", "-DVERSION_NAME=$verName", ) } } } compileOptions { targetCompatibility(androidTargetCompatibility) sourceCompatibility(androidSourceCompatibility) } buildTypes { all { signingConfig = if (signingConfigs["config"].storeFile != null) signingConfigs["config"] else signingConfigs["debug"] } named("debug") { externalNativeBuild { cmake { arguments.addAll( arrayOf( "-DCMAKE_CXX_FLAGS_DEBUG=-Og", "-DCMAKE_C_FLAGS_DEBUG=-Og", ) ) } } } named("release") { externalNativeBuild { cmake { val flags = arrayOf( "-Wl,--exclude-libs,ALL", "-ffunction-sections", "-fdata-sections", "-Wl,--gc-sections", "-fno-unwind-tables", "-fno-asynchronous-unwind-tables", "-flto=thin", "-Wl,--thinlto-cache-policy,cache_size_bytes=300m", "-Wl,--thinlto-cache-dir=${buildDir.absolutePath}/.lto-cache", ) cppFlags.addAll(flags) cFlags.addAll(flags) val configFlags = arrayOf( "-Oz", "-DNDEBUG" ).joinToString(" ") arguments.addAll( arrayOf( "-DCMAKE_CXX_FLAGS_RELEASE=$configFlags", "-DCMAKE_CXX_FLAGS_RELWITHDEBINFO=$configFlags", "-DCMAKE_C_FLAGS_RELEASE=$configFlags", "-DCMAKE_C_FLAGS_RELWITHDEBINFO=$configFlags", "-DDEBUG_SYMBOLS_PATH=${buildDir.absolutePath}/symbols", ) ) } } } } } extensions.findByType(ApplicationExtension::class)?.lint { abortOnError = true checkReleaseBuilds = false } extensions.findByType(ApplicationAndroidComponentsExtension::class)?.let { androidComponents -> val optimizeReleaseRes = task("optimizeReleaseRes").doLast { val aapt2 = File( androidComponents.sdkComponents.sdkDirectory.get().asFile, "build-tools/${androidBuildToolsVersion}/aapt2" ) val zip = java.nio.file.Paths.get( project.buildDir.path, "intermediates", "optimized_processed_res", "release", "resources-release-optimize.ap_" ) val optimized = File("${zip}.opt") val cmd = exec { commandLine( aapt2, "optimize", "--collapse-resource-names", "--enable-sparse-encoding", "-o", optimized, zip ) isIgnoreExitValue = false } if (cmd.exitValue == 0) { delete(zip) optimized.renameTo(zip.toFile()) } } tasks.whenTaskAdded { if (name == "optimizeReleaseResources") { finalizedBy(optimizeReleaseRes) } } } } subprojects { plugins.withId("com.android.application") { configureBaseExtension() } plugins.withId("com.android.library") { configureBaseExtension() } }