From 22b8047d0fbf70661777a98a870065dc61608a1d Mon Sep 17 00:00:00 2001 From: JingMatrix Date: Sat, 12 Jul 2025 08:02:03 +0200 Subject: [PATCH 1/3] Migrate to Gradle 8.14 Gradle 8.14 has new syntax requirement, which indicates the following warning: 'task(String, noinline type.() -> Unit): type' is deprecated. Use tasks.register instead Co-authored-by: 141204703+bocchi810@users.noreply.github.com --- magisk-loader/build.gradle.kts | 192 ++++++++++++++++++++++----------- 1 file changed, 127 insertions(+), 65 deletions(-) diff --git a/magisk-loader/build.gradle.kts b/magisk-loader/build.gradle.kts index 79f588b42..ba71771d6 100644 --- a/magisk-loader/build.gradle.kts +++ b/magisk-loader/build.gradle.kts @@ -20,8 +20,13 @@ import org.apache.commons.codec.binary.Hex import org.apache.tools.ant.filters.FixCrLfFilter import org.apache.tools.ant.filters.ReplaceTokens +import org.gradle.api.DefaultTask +import org.gradle.api.tasks.StopExecutionException +import org.gradle.api.tasks.TaskAction +import org.gradle.process.ExecOperations import java.io.ByteArrayOutputStream import java.security.MessageDigest +import javax.inject.Inject plugins { alias(libs.plugins.agp.app) @@ -94,10 +99,6 @@ android { } namespace = "org.lsposed.lspd" } -abstract class Injected @Inject constructor(val magiskDir: String) { - @get:Inject - abstract val factory: ObjectFactory -} dependencies { implementation(projects.core) @@ -108,50 +109,74 @@ dependencies { compileOnly(projects.hiddenapi.stubs) } -val zipAll = task("zipAll") { +val zipAll = tasks.register("zipAll") { group = "LSPosed" } -val generateWebRoot = tasks.register("generateWebRoot") { - group = "LSPosed" - val webroottmp = File("$projectDir/build/intermediates/generateWebRoot") - val webrootsrc = File(webroottmp, "src") +abstract class GenerateWebRootTask : DefaultTask() { + @get:Inject + abstract val execOperations: ExecOperations + + @TaskAction + fun generate() { + val webroottmp = File("${project.projectDir}/build/intermediates/generateWebRoot") + val webrootsrc = File(webroottmp, "src") - onlyIf { val os = org.gradle.internal.os.OperatingSystem.current() - if (os.isWindows) { - exec { - commandLine("cmd", "/c", "where", "pnpm") - isIgnoreExitValue = true - }.exitValue == 0 + val pnpmAvailable = if (os.isWindows) { + try { + execOperations.exec { + commandLine("cmd", "/c", "where", "pnpm") + isIgnoreExitValue = true + }.exitValue == 0 + } catch (e: Exception) { + false + } } else { - exec { - commandLine("which", "pnpm") - isIgnoreExitValue = true - }.exitValue == 0 + try { + execOperations.exec { + commandLine("which", "pnpm") + isIgnoreExitValue = true + }.exitValue == 0 + } catch (e: Exception) { + false + } + } + + if (!pnpmAvailable) { + throw StopExecutionException("pnpm not found. Please install pnpm to build webroot.") } - } - doFirst { webroottmp.mkdirs() webrootsrc.mkdirs() - } - from("$projectDir/src/webroot") - into(webrootsrc) + project.copy { + from("${project.projectDir}/src/webroot") + into(webrootsrc) + } - doLast { - exec { - workingDir = webroottmp + execOperations.exec { + workingDir(webroottmp) commandLine("pnpm", "add", "-D", "parcel", "kernelsu") } - exec { - workingDir = webroottmp - commandLine("./node_modules/.bin/parcel", "build", "src/index.html") + + val parcelCommand = if (os.isWindows) { + listOf("cmd", "/c", "npx", "parcel", "build", "src/index.html") + } else { + listOf("npx", "parcel", "build", "src/index.html") + } + + execOperations.exec { + workingDir(webroottmp) + commandLine(parcelCommand) } } } +val generateWebRoot = tasks.register("generateWebRoot") { + group = "LSPosed" +} + fun afterEval() = android.applicationVariants.forEach { variant -> val variantCapped = variant.name.replaceFirstChar { it.uppercase() } val variantLowered = variant.name.lowercase() @@ -165,7 +190,7 @@ fun afterEval() = android.applicationVariants.forEach { variant -> val moduleId = "${flavorLowered}_$moduleBaseId" val zipFileName = "$moduleName-v$verName-$verCode-${flavorLowered}-$buildTypeLowered.zip" - val prepareMagiskFilesTask = task("prepareMagiskFiles$variantCapped") { + val prepareMagiskFilesTask = tasks.register("prepareMagiskFiles$variantCapped") { group = "LSPosed" dependsOn( "assemble$variantCapped", @@ -241,9 +266,8 @@ fun afterEval() = android.applicationVariants.forEach { variant -> } } - val injected = objects.newInstance(magiskDir.get().asFile.path) doLast { - injected.factory.fileTree().from(injected.magiskDir).visit { + project.fileTree(magiskDir).visit { if (isDirectory) return@visit val md = MessageDigest.getInstance("SHA-256") file.forEachBlock(4096) { bytes, size -> @@ -254,7 +278,7 @@ fun afterEval() = android.applicationVariants.forEach { variant -> } } - val zipTask = task("zip${variantCapped}") { + val zipTask = tasks.register("zip${variantCapped}") { group = "LSPosed" dependsOn(prepareMagiskFilesTask) archiveFileName = zipFileName @@ -262,16 +286,20 @@ fun afterEval() = android.applicationVariants.forEach { variant -> from(magiskDir) } - zipAll.dependsOn(zipTask) + zipAll.configure { + dependsOn(zipTask) + } val adb: String = androidComponents.sdkComponents.adb.get().asFile.absolutePath - val pushTask = task("push${variantCapped}") { + + val pushTask = tasks.register("push${variantCapped}") { group = "LSPosed" dependsOn(zipTask) workingDir("${projectDir}/release") commandLine(adb, "push", zipFileName, "/data/local/tmp/") } - val flashMagiskTask = task("flashMagisk${variantCapped}") { + + val flashMagiskTask = tasks.register("flashMagisk${variantCapped}") { group = "LSPosed" dependsOn(pushTask) commandLine( @@ -279,12 +307,14 @@ fun afterEval() = android.applicationVariants.forEach { variant -> "magisk --install-module /data/local/tmp/${zipFileName}" ) } - task("flashMagiskAndReboot${variantCapped}") { + + tasks.register("flashMagiskAndReboot${variantCapped}") { group = "LSPosed" dependsOn(flashMagiskTask) commandLine(adb, "shell", "su", "-c", "/system/bin/svc", "power", "reboot") } - val flashKsuTask = task("flashKsu${variantCapped}") { + + val flashKsuTask = tasks.register("flashKsu${variantCapped}") { group = "LSPosed" dependsOn(pushTask) commandLine( @@ -292,12 +322,14 @@ fun afterEval() = android.applicationVariants.forEach { variant -> "ksud module install /data/local/tmp/${zipFileName}" ) } - task("flashKsuAndReboot${variantCapped}") { + + tasks.register("flashKsuAndReboot${variantCapped}") { group = "LSPosed" dependsOn(flashKsuTask) commandLine(adb, "shell", "su", "-c", "/system/bin/svc", "power", "reboot") } - val flashAPatchTask = task("flashAPatch${variantCapped}") { + + val flashAPatchTask = tasks.register("flashAPatch${variantCapped}") { group = "LSPosed" dependsOn(pushTask) commandLine( @@ -305,7 +337,8 @@ fun afterEval() = android.applicationVariants.forEach { variant -> "apd module install /data/local/tmp/${zipFileName}" ) } - task("flashAPatchAndReboot${variantCapped}") { + + tasks.register("flashAPatchAndReboot${variantCapped}") { group = "LSPosed" dependsOn(flashAPatchTask) commandLine(adb, "shell", "su", "-c", "/system/bin/svc", "power", "reboot") @@ -317,55 +350,83 @@ afterEvaluate { } val adb: String = androidComponents.sdkComponents.adb.get().asFile.absolutePath -val killLspd = task("killLspd") { + +val killLspd = tasks.register("killLspd") { group = "LSPosed" commandLine(adb, "shell", "su", "-c", "killall", "lspd") isIgnoreExitValue = true } -val pushDaemon = task("pushDaemon") { + +val pushDaemon = tasks.register("pushDaemon") { group = "LSPosed" dependsOn(":daemon:assembleDebug") - workingDir(project(":daemon").layout.buildDirectory.dir("outputs/apk/debug")) + doFirst { + workingDir(project(":daemon").layout.buildDirectory.dir("outputs/apk/debug")) + } commandLine(adb, "push", "daemon-debug.apk", "/data/local/tmp/daemon.apk") } -val pushDaemonNative = task("pushDaemonNative") { + +abstract class AdbShellTask : DefaultTask() { + @get:Inject + abstract val execOperations: ExecOperations + + fun adbShell(vararg command: String): String { + val output = ByteArrayOutputStream() + execOperations.exec { + commandLine(adb, "shell", *command) + standardOutput = output + isIgnoreExitValue = true + } + return output.toString().trim() + } +} + +val getAbi = tasks.register("getAbi") { group = "LSPosed" - dependsOn(":daemon:assembleDebug") + doLast { + val abi = adbShell("getprop", "ro.product.cpu.abi") + extra["abi"] = abi + } +} + +val pushDaemonNative = tasks.register("pushDaemonNative") { + group = "LSPosed" + dependsOn(":daemon:assembleDebug", getAbi) + doFirst { - val abi: String = ByteArrayOutputStream().use { outputStream -> - exec { - commandLine(adb, "shell", "getprop", "ro.product.cpu.abi") - standardOutput = outputStream - } - outputStream.toString().trim() - } + val abi = getAbi.get().extra["abi"] as String workingDir(project(":daemon").layout.buildDirectory.dir("intermediates/stripped_native_libs/debug/stripDebugDebugSymbols/out/lib/$abi")) } + commandLine(adb, "push", "libdaemon.so", "/data/local/tmp/libdaemon.so") } -val reRunDaemon = task("reRunDaemon") { + +val reRunDaemon = tasks.register("reRunDaemon") { group = "LSPosed" dependsOn(pushDaemon, pushDaemonNative, killLspd) - // tricky to pass a minus number to avoid the injection warning commandLine( adb, "shell", "ASH_STANDALONE=1", "su", "-mm", "-pc", "/data/adb/magisk/busybox sh /data/adb/modules/*_lsposed/service.sh --system-server-max-retry=-1&" ) isIgnoreExitValue = true } + val tmpApk = "/data/local/tmp/manager.apk" -val pushApk = task("pushApk") { + +val removeOldApk = tasks.register("removeOldApk") { group = "LSPosed" - dependsOn(":app:assembleDebug") - doFirst { - exec { - commandLine(adb, "shell", "su", "-c", "rm", "-f", tmpApk) - } - } + commandLine(adb, "shell", "su", "-c", "rm", "-f", tmpApk) + isIgnoreExitValue = true +} + +val pushApk = tasks.register("pushApk") { + group = "LSPosed" + dependsOn(":app:assembleDebug", removeOldApk) workingDir(project(":app").layout.buildDirectory.dir("outputs/apk/debug")) commandLine(adb, "push", "app-debug.apk", tmpApk) } -val openApp = task("openApp") { + +val openApp = tasks.register("openApp") { group = "LSPosed" commandLine( adb, "shell", @@ -373,7 +434,8 @@ val openApp = task("openApp") { "com.android.shell/.BugreportWarningActivity" ) } -task("reRunApp") { + +tasks.register("reRunApp") { group = "LSPosed" dependsOn(pushApk) finalizedBy(reRunDaemon) From bb67e85d5005533292200c9b5e1cc4423b68ab4b Mon Sep 17 00:00:00 2001 From: bocchi810 Date: Sun, 13 Jul 2025 18:54:12 +0800 Subject: [PATCH 2/3] fix: 'task(String, noinline type.() -> Unit): type' is deprecated This change will use 'tasks.register' replace 'task' --- apache/build.gradle.kts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apache/build.gradle.kts b/apache/build.gradle.kts index 30af6ab21..2127d2f0e 100644 --- a/apache/build.gradle.kts +++ b/apache/build.gradle.kts @@ -18,14 +18,14 @@ java { val lang3Src = "commons-lang/src/main/java/org/apache/commons/lang3" val localDir = "local/generated" -task("ClassUtilsX") { +tasks.register("ClassUtilsX") { from("$lang3Src/ClassUtils.java") into(localDir) filter { line: String -> line.replace("ClassUtils", "ClassUtilsX") } rename("(.+).java", "$1X.java") } -task("SerializationUtilsX") { +tasks.register("SerializationUtilsX") { from("$lang3Src/SerializationUtils.java") into(localDir) filter { line: String -> line.replace("SerializationUtils", "SerializationUtilsX") } From 230657d176f8e4d7385c9d6b4cc3cce9deb405b1 Mon Sep 17 00:00:00 2001 From: bocchi810 Date: Sun, 13 Jul 2025 19:06:06 +0800 Subject: [PATCH 3/3] fix: 'androidResources' is deprecated This change will use 'android.androidResources.enable' replace 'androidResources' --- dex2oat/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dex2oat/build.gradle.kts b/dex2oat/build.gradle.kts index 2390988a9..7092988b1 100644 --- a/dex2oat/build.gradle.kts +++ b/dex2oat/build.gradle.kts @@ -25,7 +25,7 @@ android { namespace = "org.lsposed.dex2oat" buildFeatures { - androidResources = false + android.androidResources.enable = false buildConfig = false prefab = true prefabPublishing = true