/* * This file is part of LSPosed. * * LSPosed is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * LSPosed is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with LSPosed. If not, see . * * Copyright (C) 2020 EdXposed Contributors * Copyright (C) 2021 LSPosed Contributors */ import groovy.xml.XmlUtil import org.apache.tools.ant.filters.FixCrLfFilter import org.gradle.internal.os.OperatingSystem import java.security.MessageDigest apply plugin: 'com.android.application' static def calcSha256(file) { def md = MessageDigest.getInstance("SHA-256") file.eachByte 4096, { bytes, size -> md.update(bytes, 0, size) } return md.digest().encodeHex() } ext { module_name = "LSPosed" jar_dest_dir = "${projectDir}/template_override/system/framework/" is_windows = OperatingSystem.current().isWindows() module_id = "riru_lsposed" authors = "LSPosed Developers" riruModuleId = "lsposed" moduleMinRiruApiVersion = 10 moduleMinRiruVersionName = "v23.0" moduleMaxRiruApiVersion = 10 } repositories { mavenLocal() jcenter() maven { url 'https://dl.bintray.com/rikkaw/Libraries' } } dependencies { implementation 'rikka.ndk:riru:10' implementation 'com.android.tools.build:apksig:4.1.2' implementation project(path: ':sandhook-hooklib') implementation project(path: ':service') compileOnly project(':hiddenapi-stubs') compileOnly project(':key-selector') compileOnly 'androidx.annotation:annotation:1.1.0' } android { compileSdkVersion androidCompileSdkVersion.toInteger() defaultConfig { applicationId "io.github.lsposed.lspd" minSdkVersion androidMinSdkVersion.toInteger() targetSdkVersion androidTargetSdkVersion.toInteger() multiDexEnabled false buildFeatures { prefab true } externalNativeBuild { cmake { abiFilters 'arm64-v8a', 'armeabi-v7a', 'x86', 'x86_64' cppFlags "-std=c++17 -ffixed-x18 -Qunused-arguments -frtti -fomit-frame-pointer" cFlags "-std=gnu99 -ffixed-x18 -Qunused-arguments -frtti -fomit-frame-pointer" arguments "-DRIRU_MODULE_API_VERSION=$moduleMaxRiruApiVersion", "-DRIRU_MODULE_VERSION=$rootProject.ext.versionCode", "-DRIRU_MODULE_VERSION_NAME:STRING=\"$rootProject.ext.versionName\"" } } buildConfigField("int", "API_CODE", "$apiCode") buildConfigField("String", "VERSION_NAME", "\"${rootProject.ext.versionName}\"") buildConfigField("Integer", "VERSION_CODE", String.valueOf(rootProject.ext.versionCode)) } lintOptions { abortOnError false checkReleaseBuilds false } buildTypes { debug { externalNativeBuild { cmake { cppFlags "-O0" cFlags "-O0" } } } release { minifyEnabled true proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' externalNativeBuild { cmake { cppFlags "-fvisibility=hidden -fvisibility-inlines-hidden -O2 -s -Wno-unused-value -fomit-frame-pointer" cFlags "-fvisibility=hidden -fvisibility-inlines-hidden -O2 -s -Wno-unused-value -fomit-frame-pointer" } } } } externalNativeBuild { cmake { path "src/main/cpp/CMakeLists.txt" } } ndkVersion androidCompileNdkVersion buildToolsVersion androidBuildToolsVersion compileOptions { targetCompatibility JavaVersion.VERSION_1_8 sourceCompatibility JavaVersion.VERSION_1_8 } } task cleanTemplate(type: Delete) { delete file(templateSystemx86Path) } preBuild.doLast { def imlFile = file(project.name + ".iml") try { def parsedXml = (new XmlParser()).parse(imlFile) def jdkNode = parsedXml.component[1].orderEntry.find { it.'@type' == 'jdk' } parsedXml.component[1].remove(jdkNode) def sdkString = "Android API " + android.compileSdkVersion.substring("android-".length()) + " Platform" new Node(parsedXml.component[1], 'orderEntry', ['type': 'jdk', 'jdkName': sdkString, 'jdkType': 'Android SDK']) XmlUtil.serialize(parsedXml, new FileOutputStream(imlFile)) } catch (FileNotFoundException ignored) { // nop, iml not found } } afterEvaluate { task("copyCommonProperties", type: Copy) { from file("${projectDir}/template_override/") into file(templateRootPath) } android.applicationVariants.all { variant -> def variantCapped = variant.name.capitalize() def variantLowered = variant.name.toLowerCase() def zipFileName = "${module_name}-${rootProject.ext.versionName}-${rootProject.ext.versionCode}-${variantLowered}.zip" task("copyMainDex${variantCapped}", type: Copy) { def dexOutPath = variant.name.contains("release") ? "${buildDir}/intermediates/dex/${variantLowered}/minify${variantCapped}WithR8" : "${buildDir}/intermediates/dex/${variantLowered}/mergeDex${variantCapped}" from (dexOutPath){ rename("classes.dex", "lspd.dex") } destinationDir file(zipPathMagiskReleasePath + "system/framework/") outputs.upToDateWhen { false } } delete file(zipPathMagiskReleasePath) def prepareMagiskFilesTask = task("prepareMagiskFiles${variantCapped}", type: Delete) { dependsOn "assemble${variantCapped}" dependsOn tasks.getByPath(":key-selector:copyKeySelector${variantCapped}LibraryToMagiskTemplate") doFirst { copy { from "${projectDir}/tpl/module.prop.tpl" into templateRootPath rename "module.prop.tpl", "module.prop" expand(moduleId: "$module_id", versionName: "$rootProject.ext.versionName", versionCode: "$rootProject.ext.versionCode", authorList: "$authors", apiCode: "$apiCode", minApi: "$moduleMinRiruApiVersion") filter(FixCrLfFilter.class, eol: FixCrLfFilter.CrLf.newInstance("lf")) } copy { from ("${rootProject.projectDir}/README.md") into file(zipPathMagiskReleasePath) } } def libPathRelease = "${buildDir}/intermediates/cmake/${variantLowered}/obj" def exclude_list = ["riru.sh"] doLast { def dexOutPath = variant.name.contains("release") ? "${buildDir}/intermediates/dex/${variantLowered}/minify${variantCapped}WithR8" : "${buildDir}/intermediates/dex/${variantLowered}/mergeDex${variantCapped}" copy { from (dexOutPath){ rename("classes.dex", "lspd.dex") } into file(zipPathMagiskReleasePath + "system/framework/") } copy { from "${projectDir}/template_override" into zipPathMagiskReleasePath exclude exclude_list } copy { from "${projectDir}/template_override" into zipPathMagiskReleasePath include 'util_functions.sh' filter { line -> line.replaceAll('%%%RIRU_MODULE_ID%%%', riruModuleId) .replaceAll('%%%RIRU_MIN_API_VERSION%%%', moduleMinRiruApiVersion.toString()) .replaceAll('%%%RIRU_MIN_VERSION_NAME%%%', moduleMinRiruVersionName) } filter(FixCrLfFilter.class, eol: FixCrLfFilter.CrLf.newInstance("lf")) } copy { include "libriru_lspd.so" from "$libPathRelease/armeabi-v7a" into "$zipPathMagiskReleasePath/system/lib" } copy { include "libriru_lspd.so" from "$libPathRelease/arm64-v8a" into "$zipPathMagiskReleasePath/system/lib64" } copy { include "libriru_lspd.so" from "$libPathRelease/x86" into "$zipPathMagiskReleasePath/system_x86/lib" } copy { include "libriru_lspd.so" from "$libPathRelease/x86_64" into "$zipPathMagiskReleasePath/system_x86/lib64" } // generate sha1sum fileTree(zipPathMagiskReleasePath).matching { exclude "README.md", "META-INF" }.visit { f -> if (f.directory) return file(f.file.path + ".sha256").text = calcSha256(f.file) } } } def zipTask = task("zip${variantCapped}", type: Zip) { dependsOn prepareMagiskFilesTask archiveName zipFileName destinationDir file("$projectDir/release") from "$zipPathMagiskReleasePath" } task("push${variantCapped}", type: Exec) { dependsOn zipTask workingDir "${projectDir}/release" def commands = [android.adbExecutable, "push", zipFileName, "/data/local/tmp/"] if (is_windows) { commandLine 'cmd', '/c', commands.join(" ") } else { commandLine commands } } task("flash${variantCapped}", type: Exec) { dependsOn tasks.getByPath("push${variantCapped}") workingDir "${projectDir}/release" def commands = [android.adbExecutable, "shell", "su", "-c", "magisk --install-module /data/local/tmp/${zipFileName}"] if (is_windows) { commandLine 'cmd', '/c', commands.join(" ") } else { commandLine commands } } task("flashAndReboot${variantCapped}", type: Exec) { dependsOn tasks.getByPath("flash${variantCapped}") workingDir "${projectDir}/release" def commands = [android.adbExecutable, "shell", "reboot"] if (is_windows) { commandLine 'cmd', '/c', commands.join(" ") } else { commandLine commands } } } }