From fdd5ea207debe7da01bf97dc3a261e440e12d322 Mon Sep 17 00:00:00 2001
From: Wang Han <416810799@qq.com>
Date: Tue, 16 Jul 2024 00:12:04 +0800
Subject: [PATCH] Rework gradle and CI scripts

This generally improves building experience. Some code piece is
directly copied from 5ec1cff's zygisk-module-template.
---
 .github/workflows/android.yml |  29 +++++++--
 app/build.gradle.kts          | 109 +++++++++++++++++-----------------
 build.gradle.kts              |  24 ++++++--
 3 files changed, 99 insertions(+), 63 deletions(-)

diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml
index 0235c40..076b258 100644
--- a/.github/workflows/android.yml
+++ b/.github/workflows/android.yml
@@ -18,7 +18,7 @@ jobs:
         submodules: "recursive"
         fetch-depth: 0
 
-    - name: set up JDK 17
+    - name: Set up JDK 17
       uses: actions/setup-java@v4
       with:
         distribution: 'temurin'
@@ -28,10 +28,27 @@ jobs:
       run: chmod +x gradlew
       
     - name: Build with Gradle
-      run: ./gradlew assembleRelease
-      
-    - name: Upload KeystoreInjection.zip
+      run: |
+        ./gradlew zipRelease
+        ./gradlew zipDebug
+
+    - name: Prepare artifact
+      if: success()
+      id: prepareArtifact
+      run: |
+        releaseName=`ls out/KeystoreInjection-v*-release.zip | awk -F '(/|.zip)' '{print $5}'` && echo "releaseName=$releaseName" >> $GITHUB_OUTPUT
+        debugName=`ls out/KeystoreInjection-v*-debug.zip | awk -F '(/|.zip)' '{print $5}'` && echo "debugName=$debugName" >> $GITHUB_OUTPUT
+        unzip out/KeystoreInjection-v*-release.zip -d module-release
+        unzip out/KeystoreInjection-v*-debug.zip -d module-debug
+
+    - name: Upload release
+      uses: actions/upload-artifact@v4
+      with:
+        name: ${{ steps.prepareArtifact.outputs.releaseName }}
+        path: "./module-release/*"
+
+    - name: Upload debug
       uses: actions/upload-artifact@v4
       with:
-        name: KeystoreInjection
-        path: module/*
\ No newline at end of file
+        name: ${{ steps.prepareArtifact.outputs.debugName }}
+        path: "./module-debug/*"
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index bf6f4e4..e14467a 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -1,7 +1,13 @@
+import android.databinding.tool.ext.capitalizeUS
+
 plugins {
     id("com.android.application")
 }
 
+val verCode: Int by rootProject.extra
+val verName: String by rootProject.extra
+val commitHash: String by rootProject.extra
+
 android {
     namespace = "io.github.aviraxp.keystoreinjection"
     compileSdk = 35
@@ -16,28 +22,21 @@ android {
         applicationId = "io.github.aviraxp.keystoreinjection"
         minSdk = 30
         targetSdk = 35
-        versionCode = 10
-        versionName = "v0.1.0"
-        multiDexEnabled = false
+        versionCode = verCode
+        versionName = verName
 
         packaging {
-            jniLibs {
-                excludes += "**/liblog.so"
-            }
             resources.excludes.add("META-INF/versions/9/OSGI-INF/MANIFEST.MF")
         }
 
         externalNativeBuild {
             cmake {
                 arguments += "-DANDROID_STL=none"
-                arguments += "-DCMAKE_BUILD_TYPE=MinSizeRel"
-                arguments += "-DPlugin.Android.BionicLinkerUtil=ON"
-
-                cppFlags += "-std=c++20"
                 cppFlags += "-fno-exceptions"
                 cppFlags += "-fno-rtti"
                 cppFlags += "-fvisibility=hidden"
                 cppFlags += "-fvisibility-inlines-hidden"
+                cppFlags += "-std=c++20"
             }
         }
     }
@@ -50,7 +49,10 @@ android {
             isMinifyEnabled = true
             isShrinkResources = true
             multiDexEnabled = false
-            proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
+            proguardFiles(
+                getDefaultProguardFile("proguard-android-optimize.txt"),
+                "proguard-rules.pro"
+            )
         }
     }
 
@@ -72,50 +74,51 @@ dependencies {
     implementation("org.bouncycastle:bcpkix-jdk18on:1.78.1")
 }
 
-tasks.register("updateModuleProp") {
-    doLast {
-        val versionName = project.android.defaultConfig.versionName
-        val versionCode = project.android.defaultConfig.versionCode
-
-        val modulePropFile = project.rootDir.resolve("module/module.prop")
-
-        var content = modulePropFile.readText()
-
-        content = content.replace(Regex("version=.*"), "version=$versionName")
-        content = content.replace(Regex("versionCode=.*"), "versionCode=$versionCode")
-
-        modulePropFile.writeText(content)
-    }
-}
-
-
-tasks.register("copyFiles") {
-    dependsOn("updateModuleProp")
-
-    doLast {
-        val moduleFolder = project.rootDir.resolve("module")
-        val dexFile = project.layout.buildDirectory.get().asFile.resolve("intermediates/dex/release/minifyReleaseWithR8/classes.dex")
-        val soDir = project.layout.buildDirectory.get().asFile.resolve("intermediates/stripped_native_libs/release/stripReleaseDebugSymbols/out/lib")
+androidComponents.onVariants { variant ->
+    afterEvaluate {
+        val variantLowered = variant.name.lowercase()
+        val variantCapped = variant.name.capitalizeUS()
+        tasks.register("updateModuleProp$variantCapped") {
+            group = "Zygisk"
+            dependsOn("assemble$variantCapped")
+            doLast {
+                val versionName = project.android.defaultConfig.versionName
+                val versionCode = project.android.defaultConfig.versionCode
+                val modulePropFile = project.rootDir.resolve("module/module.prop")
+                var content = modulePropFile.readText()
+                content = content.replace(Regex("version=.*"), "version=$versionName")
+                content = content.replace(Regex("versionCode=.*"), "versionCode=$versionCode")
+                modulePropFile.writeText(content)
+            }
+        }
 
-        dexFile.copyTo(moduleFolder.resolve("classes.dex"), overwrite = true)
+        tasks.register("copyFiles$variantCapped") {
+            group = "Zygisk"
+            dependsOn("updateModuleProp$variantCapped")
+            doLast {
+                val moduleFolder = project.rootDir.resolve("module")
+                val dexFile =
+                    if (variantLowered == "release")
+                        project.layout.buildDirectory.get().asFile.resolve("intermediates/dex/$variantCapped/minify${variantCapped}WithR8/classes.dex")
+                    else
+                        project.layout.buildDirectory.get().asFile.resolve("intermediates/dex/$variantCapped/mergeDex$variantCapped/classes.dex")
+                val soDir =
+                    project.layout.buildDirectory.get().asFile.resolve("intermediates/stripped_native_libs/$variantLowered/strip${variantCapped}DebugSymbols/out/lib")
+                dexFile.copyTo(moduleFolder.resolve("classes.dex"), overwrite = true)
+                soDir.walk().filter { it.isFile && it.extension == "so" }.forEach { soFile ->
+                    val abiFolder = soFile.parentFile.name
+                    val destination = moduleFolder.resolve("zygisk/$abiFolder.so")
+                    soFile.copyTo(destination, overwrite = true)
+                }
+            }
+        }
 
-        soDir.walk().filter { it.isFile && it.extension == "so" }.forEach { soFile ->
-            val abiFolder = soFile.parentFile.name
-            val destination = moduleFolder.resolve("zygisk/$abiFolder.so")
-            soFile.copyTo(destination, overwrite = true)
+        tasks.register<Zip>("zip$variantCapped") {
+            group = "Zygisk"
+            dependsOn("copyFiles$variantCapped")
+            archiveFileName.set("KeystoreInjection-${project.android.defaultConfig.versionName}-${project.android.defaultConfig.versionCode}-$commitHash-${variantLowered}.zip")
+            destinationDirectory.set(project.rootDir.resolve("out"))
+            from(project.rootDir.resolve("module"))
         }
     }
 }
-
-tasks.register<Zip>("zip") {
-    dependsOn("copyFiles")
-
-    archiveFileName.set("KeystoreInjection_${project.android.defaultConfig.versionName}.zip")
-    destinationDirectory.set(project.rootDir.resolve("out"))
-
-    from(project.rootDir.resolve("module"))
-}
-
-afterEvaluate {
-    tasks["assembleRelease"].finalizedBy("updateModuleProp", "copyFiles", "zip")
-}
\ No newline at end of file
diff --git a/build.gradle.kts b/build.gradle.kts
index 8d98714..2914727 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -1,6 +1,22 @@
-buildscript {
-    val agp_version by extra("8.5.1")
-}
+import java.io.ByteArrayOutputStream
+
 plugins {
     id("com.android.application") version "8.5.1" apply false
-}
\ No newline at end of file
+}
+
+fun String.execute(currentWorkingDir: File = file("./")): String {
+    val byteOut = ByteArrayOutputStream()
+    project.exec {
+        workingDir = currentWorkingDir
+        commandLine = split("\\s".toRegex())
+        standardOutput = byteOut
+    }
+    return String(byteOut.toByteArray()).trim()
+}
+
+val gitCommitCount = "git rev-list HEAD --count".execute().toInt()
+val gitCommitHash = "git rev-parse --verify --short HEAD".execute()
+
+val verName by extra("v0.1.0")
+val verCode by extra(gitCommitCount)
+val commitHash by extra(gitCommitHash)