Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import com.google.common.io.Closer
import org.gradle.api.DefaultTask
import org.gradle.api.file.ConfigurableFileCollection
import org.gradle.api.file.RegularFileProperty
import org.gradle.api.provider.Property
import org.gradle.api.tasks.*
import org.objectweb.asm.ClassReader
import org.objectweb.asm.tree.ClassNode
Expand All @@ -33,22 +34,27 @@ abstract class CompileDexTask : DefaultTask() {
@get:OutputFile
abstract val pluginClassFile: RegularFileProperty

@TaskAction
fun compileDex() {
val android = project.extensions.getByName("android") as BaseExtension
@get:Internal
abstract val pluginClassName: Property<String?>

@get:Input
abstract val minSdk: Property<Int>

val minSdk = android.defaultConfig.minSdk ?: 21
@get:InputFiles
abstract val bootClasspath: ConfigurableFileCollection

@TaskAction
fun compileDex() {
val dexOutputDir = outputFile.get().asFile.parentFile

Closer.create().use { closer ->
val dexBuilder = DexArchiveBuilder.createD8DexBuilder(
DexParameters(
minSdkVersion = minSdk,
minSdkVersion = minSdk.get(),
debuggable = true,
dexPerClass = false,
withDesugaring = true, // Make all plugins work on lower android versions
desugarBootclasspath = ClassFileProviderFactory(android.bootClasspath.map(File::toPath))
desugarBootclasspath = ClassFileProviderFactory(bootClasspath.files.map(File::toPath))
.also { closer.register(it) },
desugarClasspath = ClassFileProviderFactory(listOf<Path>()).also {
closer.register(
Expand Down Expand Up @@ -86,14 +92,13 @@ abstract class CompileDexTask : DefaultTask() {

for (annotation in classNode.visibleAnnotations.orEmpty() + classNode.invisibleAnnotations.orEmpty()) {
if (annotation.desc == "Lcom/lagradost/cloudstream3/plugins/CloudstreamPlugin;") {
val cloudstream = project.extensions.getCloudstream()

require(cloudstream.pluginClassName == null) {
require(pluginClassName.orNull == null) {
"Only 1 active plugin class per project is supported"
}

cloudstream.pluginClassName = classNode.name.replace('/', '.')
.also { pluginClassFile.asFile.orNull?.writeText(it) }
val detectedName = classNode.name.replace('/', '.')
pluginClassFile.asFile.orNull?.writeText(detectedName)
pluginClassName.set(detectedName)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import org.gradle.api.DefaultTask
import org.gradle.api.file.RegularFileProperty
import org.gradle.api.provider.Property
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.InputFile
import org.gradle.api.tasks.Internal
import org.gradle.api.tasks.OutputFile
import org.gradle.api.tasks.TaskAction

abstract class CompilePluginJarTask : DefaultTask() {

@get:Input
abstract val hasCrossPlatformSupport: Property<Boolean>

@get:InputFile
abstract val pluginClassFile: RegularFileProperty

@get:Internal
abstract val pluginClassName: Property<String?>

@get:Internal
abstract val jarFileSize: Property<Long?>

@get:InputFile
abstract val jarInputFile: RegularFileProperty

@get:OutputFile
abstract val targetJarFile: RegularFileProperty

@TaskAction
fun compileJar() {
if (pluginClassName.orNull == null) {
val file = pluginClassFile.get().asFile
if (file.exists()) {
pluginClassName.set(file.readText())
}
}

if (!hasCrossPlatformSupport.get()) return

val jarFile = jarInputFile.get().asFile
val targetFile = targetJarFile.get().asFile

jarFile.copyTo(targetFile, overwrite = true)
jarFileSize.set(jarFile.length())
logger.lifecycle("Made Cloudstream cross-platform package at ${targetFile.absolutePath}")
}
}
Original file line number Diff line number Diff line change
@@ -1,38 +1,23 @@
package com.lagradost.cloudstream3.gradle.tasks

import com.lagradost.cloudstream3.gradle.findCloudstream
import com.lagradost.cloudstream3.gradle.makePluginEntry
import com.lagradost.cloudstream3.gradle.entities.PluginEntry
import groovy.json.JsonBuilder
import groovy.json.JsonGenerator
import org.gradle.api.DefaultTask
import org.gradle.api.file.RegularFileProperty
import org.gradle.api.provider.Property
import org.gradle.api.tasks.OutputFile
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.TaskAction
import java.util.LinkedList
import java.lang.Thread

abstract class MakePluginsJsonTask : DefaultTask() {
@get:OutputFile
abstract val outputFile: RegularFileProperty

@get:Input
abstract val pluginEntriesJson: Property<String>

@TaskAction
fun makePluginsJson() {
val lst = LinkedList<PluginEntry>()

for (subproject in project.allprojects) {
subproject.extensions.findCloudstream() ?: continue

lst.add(subproject.makePluginEntry())
}

outputFile.asFile.get().writeText(
JsonBuilder(
lst,
JsonGenerator.Options()
.excludeNulls()
.build()
).toPrettyString()
pluginEntriesJson.get()
)

logger.lifecycle("Created ${outputFile.asFile.get()}")
Expand Down
96 changes: 46 additions & 50 deletions src/main/kotlin/com/lagradost/cloudstream3/gradle/tasks/Tasks.kt
Original file line number Diff line number Diff line change
Expand Up @@ -22,41 +22,50 @@ fun registerTasks(project: Project) {
val intermediates = project.buildDir.resolve("intermediates")

if (project.rootProject.tasks.findByName("makePluginsJson") == null) {
project.rootProject.tasks.register("makePluginsJson", MakePluginsJsonTask::class.java) {
it.group = TASK_GROUP

it.outputs.upToDateWhen { false }

it.outputFile.set(it.project.buildDir.resolve("plugins.json"))
project.rootProject.tasks.register("makePluginsJson", MakePluginsJsonTask::class.java) { task ->
task.group = TASK_GROUP
task.outputs.upToDateWhen { false }
task.outputFile.set(task.project.layout.buildDirectory.file("plugins.json"))
task.pluginEntriesJson.set(
task.project.provider {
val lst = task.project.allprojects.mapNotNull { sub ->
sub.extensions.findCloudstream()?.let { sub.makePluginEntry() }
}
JsonBuilder(lst, JsonGenerator.Options().excludeNulls().build()).toPrettyString()
}
)
}
}

project.tasks.register("genSources", GenSourcesTask::class.java) {
it.group = TASK_GROUP
}

val pluginClassFile = intermediates.resolve("pluginClass")
val pluginClassFile = intermediatesDir.map { it.file("pluginClass") }

val compileDex = project.tasks.register("compileDex", CompileDexTask::class.java) {
it.group = TASK_GROUP
val compileDex = project.tasks.register("compileDex", CompileDexTask::class.java) { task ->
task.group = TASK_GROUP

it.pluginClassFile.set(pluginClassFile)
task.pluginClassFile.set(pluginClassFile)
task.outputFile.set(intermediatesDir.map { dir -> dir.file("classes.dex") })

val android = project.extensions.findByName("android") as? BaseExtension
?: error("Android plugin not found")
task.minSdk.set(android.defaultConfig.minSdk ?: 21)
task.bootClasspath.from(android.bootClasspath)

val extension = project.extensions.getCloudstream()
task.pluginClassName.set(extension.pluginClassName)

val kotlinTask = project.tasks.findByName("compileDebugKotlin") as KotlinCompile?
if (kotlinTask != null) {
it.dependsOn(kotlinTask)
it.input.from(kotlinTask.destinationDirectory)
task.dependsOn(kotlinTask)
task.input.from(kotlinTask.destinationDirectory)
}

// This task does not seem to be required for a successful cs3 file

// val javacTask = project.tasks.findByName("compileDebugJavaWithJavac") as AbstractCompile?
// if (javacTask != null) {
// it.dependsOn(javacTask)
// it.input.from(javacTask.destinationDirectory)
// }

it.outputFile.set(intermediates.resolve("classes.dex"))
task.doLast {
extension.pluginClassName = task.pluginClassName.orNull
}
}

val compileResources =
Expand Down Expand Up @@ -86,35 +95,22 @@ fun registerTasks(project: Project) {
}
}

val compilePluginJar = project.tasks.register("compilePluginJar") {
it.group = TASK_GROUP
it.dependsOn("createFullJarDebug") // Ensure JAR is built before copying

it.doFirst {
if (extension.pluginClassName == null) {
if (pluginClassFile.exists()) {
extension.pluginClassName = pluginClassFile.readText()
}
}
}

it.doLast {
if (!extension.isCrossPlatform) {
return@doLast
}

val jarTask = project.tasks.findByName("createFullJarDebug") ?: return@doLast
val jarFile =
jarTask.outputs.files.singleFile // Output directory of createFullJarDebug
if (jarFile != null) {
val targetDir = project.buildDir // Top-level build directory
val targetFile = targetDir.resolve("${project.name}.jar")
jarFile.copyTo(targetFile, overwrite = true)
extension.jarFileSize = jarFile.length()
it.logger.lifecycle("Made Cloudstream cross-platform package at ${targetFile.absolutePath}")
} else {
it.logger.warn("Could not find JAR file!")
}
val compilePluginJar = project.tasks.register("compilePluginJar", CompilePluginJarTask::class.java) { task ->
task.group = TASK_GROUP
task.dependsOn("createFullJarDebug") // Ensure JAR is built before copying
task.dependsOn("compileDex") // compileDex creates pluginClass
val jarTask = project.tasks.named("createFullJarDebug")

task.hasCrossPlatformSupport.set(extension.isCrossPlatform)
task.pluginClassFile.set(pluginClassFile)
task.pluginClassName.set(extension.pluginClassName)
task.jarInputFile.fileProvider(jarTask.map { it.outputs.files.singleFile })
task.targetJarFile.set(project.layout.buildDirectory.file("${project.name}.jar"))
task.jarFileSize.set(extension.jarFileSize)

task.doLast {
extension.pluginClassName = task.pluginClassName.orNull
extension.jarFileSize = task.jarFileSize.orNull
}
}

Expand Down