feat: add gradle export templates, support android app/lib and simple java

This commit is contained in:
Skylot
2025-04-29 21:07:52 +01:00
parent 9981949a2b
commit e3aa49aaa9
54 changed files with 1153 additions and 570 deletions
@@ -7,16 +7,15 @@ import jadx.plugins.script.passes.JadxScriptAfterLoadPass
import jadx.plugins.script.runtime.data.JadxScriptAllOptions
class JadxScriptPlugin : JadxPlugin {
private val scriptOptions = JadxScriptAllOptions()
override fun getPluginInfo() = JadxPluginInfo("jadx-script", "Jadx Script", "Scripting support for jadx")
override fun init(init: JadxPluginContext) {
init.registerOptions(scriptOptions)
val scripts = ScriptEval().process(init, scriptOptions)
override fun init(context: JadxPluginContext) {
val scriptOptions = JadxScriptAllOptions()
context.registerOptions(scriptOptions)
val scripts = ScriptEval().process(context, scriptOptions)
if (scripts.isNotEmpty()) {
init.addPass(JadxScriptAfterLoadPass(scripts))
init.guiContext?.let { JadxScriptOptionsUI.setup(it, scriptOptions) }
context.addPass(JadxScriptAfterLoadPass(scripts))
context.guiContext?.let { JadxScriptOptionsUI.setup(it, scriptOptions) }
}
}
}
@@ -1,6 +1,7 @@
package jadx.plugins.script
import jadx.commons.app.JadxCommonFiles
import jadx.api.plugins.JadxPluginContext
import jadx.core.utils.files.FileUtils
import java.io.File
import java.security.MessageDigest
import kotlin.script.experimental.api.CompiledScript
@@ -14,11 +15,11 @@ import kotlin.script.experimental.jvmhost.saveToJar
class ScriptCache {
private val enableCache = System.getProperty("JADX_SCRIPT_CACHE_ENABLE", "true").equals("true", ignoreCase = true)
fun build(): CompiledJvmScriptsCache {
fun build(context: JadxPluginContext): CompiledJvmScriptsCache {
if (!enableCache) {
return CompiledJvmScriptsCache.NoCache
}
return JadxScriptsCache(getCacheDir())
return JadxScriptsCache(getCacheDir(context))
}
/**
@@ -38,7 +39,7 @@ class ScriptCache {
}
return file.loadScriptFromJar() ?: run {
// invalidate cache if the script cannot be loaded
cacheDir.deleteRecursively()
FileUtils.deleteDir(cacheDir)
null
}
}
@@ -60,9 +61,9 @@ class ScriptCache {
}
}
private fun getCacheDir(): File {
val cacheBaseDir = JadxCommonFiles.getCacheDir().resolve("scripts").toFile()
cacheBaseDir.mkdirs()
private fun getCacheDir(context: JadxPluginContext): File {
val cacheBaseDir = context.files().pluginCacheDir.resolve("compiled").toFile()
FileUtils.makeDirs(cacheBaseDir)
return cacheBaseDir
}
@@ -4,13 +4,12 @@ import jadx.api.plugins.JadxPluginContext
import jadx.plugins.script.runtime.JadxScriptData
import jadx.plugins.script.runtime.JadxScriptTemplate
import jadx.plugins.script.runtime.data.JadxScriptAllOptions
import kotlin.script.experimental.api.CompiledScript
import kotlin.script.experimental.api.EvaluationResult
import kotlin.script.experimental.api.ResultValue
import kotlin.script.experimental.api.ResultWithDiagnostics
import kotlin.script.experimental.api.ScriptCompilationConfiguration
import kotlin.script.experimental.api.ScriptDiagnostic.Severity
import kotlin.script.experimental.api.ScriptEvaluationConfiguration
import kotlin.script.experimental.api.SourceCode
import kotlin.script.experimental.api.constructorArgs
import kotlin.script.experimental.host.ScriptingHostConfiguration
import kotlin.script.experimental.host.toScriptSource
@@ -25,52 +24,32 @@ import kotlin.time.toDuration
class ScriptEval {
companion object {
val scriptingHost = BasicJvmScriptingHost(
baseHostConfiguration = ScriptingHostConfiguration {
jvm {
compilationCache(ScriptCache().build())
}
},
)
val compileConf = createJvmCompilationConfigurationFromTemplate<JadxScriptTemplate>()
private val baseEvalConf = createJvmEvaluationConfigurationFromTemplate<JadxScriptTemplate>()
private fun buildEvalConf(scriptData: JadxScriptData) =
ScriptEvaluationConfiguration(baseEvalConf) {
constructorArgs(scriptData)
}
}
fun process(init: JadxPluginContext, scriptOptions: JadxScriptAllOptions): List<JadxScriptData> {
val jadx = init.decompiler
fun process(context: JadxPluginContext, scriptOptions: JadxScriptAllOptions): List<JadxScriptData> {
val jadx = context.decompiler
val scripts = jadx.args.inputFiles.filter { f -> f.name.endsWith(".jadx.kts") }
if (scripts.isEmpty()) {
return emptyList()
}
val scriptingHost = buildScriptingHost(context)
val compileConf = buildCompileConf()
val scriptDataList = mutableListOf<JadxScriptData>()
for (scriptFile in scripts) {
val scriptData = JadxScriptData(jadx, init, scriptOptions, scriptFile)
val scriptData = JadxScriptData(jadx, context, scriptOptions, scriptFile)
scriptDataList.add(scriptData)
eval(scriptData)
eval(scriptingHost, compileConf, scriptData)
}
return scriptDataList
}
suspend fun compile(script: SourceCode): ResultWithDiagnostics<CompiledScript> {
return scriptingHost.compiler(script, compileConf)
}
private fun eval(scriptData: JadxScriptData) {
private fun eval(
scriptingHost: BasicJvmScriptingHost,
compileConf: ScriptCompilationConfiguration,
scriptData: JadxScriptData,
) {
scriptData.log.debug { "Loading script: ${scriptData.scriptFile.absolutePath}" }
val evalConf = buildEvalConf(scriptData)
val execTime = measureTimeMillis {
val result = scriptingHost.eval(
scriptData.scriptFile.toScriptSource(),
compileConf,
buildEvalConf(scriptData),
)
val result = scriptingHost.eval(scriptData.scriptFile.toScriptSource(), compileConf, evalConf)
processEvalResult(result, scriptData)
}
scriptData.log.debug { "Script '${scriptData.scriptName}' executed in ${execTime.toDuration(DurationUnit.MILLISECONDS)}" }
@@ -103,4 +82,21 @@ class ScriptEval {
}
}
}
fun buildScriptingHost(context: JadxPluginContext) = BasicJvmScriptingHost(
baseHostConfiguration = ScriptingHostConfiguration {
jvm {
compilationCache(ScriptCache().build(context))
}
},
)
fun buildCompileConf() = createJvmCompilationConfigurationFromTemplate<JadxScriptTemplate>()
fun buildEvalConf(scriptData: JadxScriptData): ScriptEvaluationConfiguration {
val baseEvalConf = createJvmEvaluationConfigurationFromTemplate<JadxScriptTemplate>()
return ScriptEvaluationConfiguration(baseEvalConf) {
constructorArgs(scriptData)
}
}
}