Skip to content

Commit 8f2542b

Browse files
committed
Factor out gradle utils. Add flag for disabling webgpu and enforcing android source level compat.
1 parent 9ae1d01 commit 8f2542b

File tree

12 files changed

+505
-185
lines changed

12 files changed

+505
-185
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,3 +124,5 @@ generated/
124124
/app/windows/obj
125125
/java/gradle/build
126126
/java/gradle/example/.processing
127+
128+
libProcessing/ffi/include/*

app/build.gradle.kts

Lines changed: 1 addition & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -1,94 +1,13 @@
11
import org.gradle.internal.jvm.Jvm
22
import org.gradle.internal.os.OperatingSystem
33
import org.gradle.nativeplatform.platform.internal.DefaultNativePlatform
4-
import org.gradle.process.ExecOperations
54
import org.jetbrains.compose.desktop.application.dsl.TargetFormat
65
import org.jetbrains.compose.desktop.application.tasks.AbstractJPackageTask
76
import org.jetbrains.compose.internal.de.undercouch.gradle.tasks.download.Download
8-
import java.io.FileOutputStream
9-
import java.util.zip.ZipEntry
10-
import java.util.zip.ZipOutputStream
11-
import javax.inject.Inject
7+
import processing.gradle.SignResourcesTask
128

139
// TODO: Update to 2.10.20 and add hot-reloading: https://github.com/JetBrains/compose-hot-reload
1410

15-
abstract class SignResourcesTask : DefaultTask() {
16-
@get:Inject
17-
abstract val execOperations: ExecOperations
18-
19-
@get:InputDirectory
20-
abstract val resourcesPath: DirectoryProperty
21-
22-
@TaskAction
23-
fun signResources() {
24-
val resourcesDir = resourcesPath.get().asFile
25-
val jars = mutableListOf<File>()
26-
27-
// Copy Info.plist if present
28-
project.fileTree(resourcesDir)
29-
.matching { include("**/Info.plist") }
30-
.singleOrNull()
31-
?.let { file ->
32-
project.copy {
33-
from(file)
34-
into(resourcesDir)
35-
}
36-
}
37-
38-
project.fileTree(resourcesDir) {
39-
include("**/*.jar")
40-
exclude("**/*.jar.tmp/**")
41-
}.forEach { file ->
42-
val tempDir = file.parentFile.resolve("${file.name}.tmp")
43-
project.copy {
44-
from(project.zipTree(file))
45-
into(tempDir)
46-
}
47-
file.delete()
48-
jars.add(tempDir)
49-
}
50-
51-
project.fileTree(resourcesDir) {
52-
include("**/bin/**")
53-
include("**/*.jnilib")
54-
include("**/*.dylib")
55-
include("**/*aarch64*")
56-
include("**/*x86_64*")
57-
include("**/*ffmpeg*")
58-
include("**/ffmpeg*/**")
59-
exclude("jdk/**")
60-
exclude("*.jar")
61-
exclude("*.so")
62-
exclude("*.dll")
63-
}.forEach { file ->
64-
execOperations.exec {
65-
commandLine("codesign", "--timestamp", "--force", "--deep", "--options=runtime", "--sign", "Developer ID Application", file)
66-
}
67-
}
68-
69-
jars.forEach { file ->
70-
FileOutputStream(File(file.parentFile, file.nameWithoutExtension)).use { fos ->
71-
ZipOutputStream(fos).use { zos ->
72-
file.walkTopDown().forEach { fileEntry ->
73-
if (fileEntry.isFile) {
74-
val zipEntryPath = fileEntry.relativeTo(file).path
75-
val entry = ZipEntry(zipEntryPath)
76-
zos.putNextEntry(entry)
77-
fileEntry.inputStream().use { input ->
78-
input.copyTo(zos)
79-
}
80-
zos.closeEntry()
81-
}
82-
}
83-
}
84-
}
85-
file.deleteRecursively()
86-
}
87-
88-
File(resourcesDir, "Info.plist").delete()
89-
}
90-
}
91-
9211
plugins{
9312
id("java")
9413
kotlin("jvm") version libs.versions.kotlin

build.gradle.kts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,23 @@ plugins {
1212
// Can be deleted after the migration to Gradle is complete
1313
layout.buildDirectory = file(".build")
1414

15+
val enableWebGPU = findProperty("enableWebGPU")?.toString()?.toBoolean() ?: true
16+
1517
allprojects {
1618
tasks.withType<JavaCompile>().configureEach {
17-
sourceCompatibility = "24"
18-
targetCompatibility = "24"
19+
val javaVersion = if (project.name == "core" && enableWebGPU) "24" else "17"
20+
sourceCompatibility = javaVersion
21+
targetCompatibility = javaVersion
1922
}
2023

2124
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile>().configureEach {
2225
compilerOptions {
23-
jvmTarget.set(org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_24)
26+
val kotlinTarget = if (project.name == "core" && enableWebGPU) {
27+
org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_24
28+
} else {
29+
org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17
30+
}
31+
jvmTarget.set(kotlinTarget)
2432
}
2533
}
2634
}

buildSrc/build.gradle.kts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
plugins {
2+
`kotlin-dsl`
3+
}
4+
5+
repositories {
6+
mavenCentral()
7+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package processing.gradle
2+
3+
import org.gradle.api.DefaultTask
4+
import org.gradle.api.file.DirectoryProperty
5+
import org.gradle.api.file.RegularFileProperty
6+
import org.gradle.api.provider.Property
7+
import org.gradle.api.tasks.*
8+
import org.gradle.process.ExecOperations
9+
import javax.inject.Inject
10+
11+
abstract class CargoBuildTask : DefaultTask() {
12+
13+
@get:Inject
14+
abstract val execOperations: ExecOperations
15+
16+
@get:InputDirectory
17+
abstract val cargoWorkspaceDir: DirectoryProperty
18+
19+
@get:Input
20+
abstract val manifestPath: Property<String>
21+
22+
@get:Input
23+
abstract val release: Property<Boolean>
24+
25+
@get:Input
26+
abstract val cargoPath: Property<String>
27+
28+
@get:OutputFile
29+
abstract val outputLibrary: RegularFileProperty
30+
31+
init {
32+
group = "rust"
33+
description = "Builds Rust library using cargo"
34+
35+
// release by default
36+
release.convention(true)
37+
}
38+
39+
@TaskAction
40+
fun build() {
41+
val buildType = if (release.get()) "release" else "debug"
42+
logger.lifecycle("Building Rust library ($buildType mode)...")
43+
44+
val args = mutableListOf("build")
45+
if (release.get()) {
46+
args.add("--release")
47+
}
48+
args.add("--manifest-path")
49+
args.add(manifestPath.get())
50+
51+
execOperations.exec {
52+
workingDir = cargoWorkspaceDir.get().asFile
53+
commandLine = listOf(cargoPath.get()) + args
54+
}
55+
}
56+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package processing.gradle
2+
3+
import org.gradle.api.DefaultTask
4+
import org.gradle.api.file.DirectoryProperty
5+
import org.gradle.api.provider.Property
6+
import org.gradle.api.tasks.*
7+
import org.gradle.process.ExecOperations
8+
import javax.inject.Inject
9+
10+
abstract class CargoCleanTask : DefaultTask() {
11+
12+
@get:Inject
13+
abstract val execOperations: ExecOperations
14+
15+
@get:InputDirectory
16+
abstract val cargoWorkspaceDir: DirectoryProperty
17+
18+
@get:Input
19+
abstract val manifestPath: Property<String>
20+
21+
@get:Input
22+
abstract val cargoPath: Property<String>
23+
24+
init {
25+
group = "rust"
26+
description = "Cleans Rust build artifacts"
27+
}
28+
29+
@TaskAction
30+
fun clean() {
31+
logger.lifecycle("Cleaning Rust build artifacts...")
32+
33+
execOperations.exec {
34+
workingDir = cargoWorkspaceDir.get().asFile
35+
commandLine(cargoPath.get(), "clean", "--manifest-path", manifestPath.get())
36+
}
37+
}
38+
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package processing.gradle
2+
3+
import org.gradle.api.DefaultTask
4+
import org.gradle.api.GradleException
5+
import org.gradle.api.file.DirectoryProperty
6+
import org.gradle.api.file.RegularFileProperty
7+
import org.gradle.api.provider.Property
8+
import org.gradle.api.tasks.*
9+
import java.net.URI
10+
11+
abstract class DownloadJextractTask : DefaultTask() {
12+
13+
@get:Input
14+
abstract val jextractVersion: Property<String>
15+
16+
@get:Input
17+
abstract val platform: Property<String>
18+
19+
@get:OutputDirectory
20+
abstract val jextractDir: DirectoryProperty
21+
22+
@get:Internal
23+
abstract val downloadTarball: RegularFileProperty
24+
25+
init {
26+
group = "rust"
27+
description = "Downloads and extracts jextract for the current platform"
28+
}
29+
30+
@TaskAction
31+
fun download() {
32+
val version = jextractVersion.get()
33+
val plat = platform.get()
34+
val fileName = "openjdk-$version" + "_${plat}_bin.tar.gz"
35+
val downloadUrl = "https://download.java.net/java/early_access/jextract/22/6/$fileName"
36+
val tarFile = downloadTarball.get().asFile
37+
38+
if (!tarFile.exists()) {
39+
logger.lifecycle("Downloading jextract from $downloadUrl")
40+
try {
41+
tarFile.outputStream().use { output ->
42+
URI.create(downloadUrl).toURL().openStream().use { input ->
43+
input.copyTo(output)
44+
}
45+
}
46+
} catch (e: Exception) {
47+
throw GradleException("Failed to download jextract: ${e.message}", e)
48+
}
49+
}
50+
51+
val extractDir = jextractDir.get().asFile
52+
logger.lifecycle("Extracting jextract to ${extractDir.parent}")
53+
project.copy {
54+
from(project.tarTree(tarFile))
55+
into(extractDir.parent)
56+
}
57+
58+
logger.lifecycle("jextract extracted to: $extractDir")
59+
}
60+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package processing.gradle
2+
3+
import org.gradle.api.DefaultTask
4+
import org.gradle.api.file.DirectoryProperty
5+
import org.gradle.api.file.RegularFileProperty
6+
import org.gradle.api.provider.Property
7+
import org.gradle.api.tasks.*
8+
import org.gradle.process.ExecOperations
9+
import javax.inject.Inject
10+
11+
abstract class GenerateJextractBindingsTask : DefaultTask() {
12+
13+
@get:Inject
14+
abstract val execOperations: ExecOperations
15+
16+
@get:InputFile
17+
abstract val headerFile: RegularFileProperty
18+
19+
@get:OutputDirectory
20+
abstract val outputDirectory: DirectoryProperty
21+
22+
@get:Input
23+
abstract val targetPackage: Property<String>
24+
25+
@get:Input
26+
abstract val jextractPath: Property<String>
27+
28+
init {
29+
group = "rust"
30+
description = "Generates Java Panama FFM bindings from C headers"
31+
}
32+
33+
@TaskAction
34+
fun generate() {
35+
val outDir = outputDirectory.get().asFile
36+
outDir.mkdirs()
37+
38+
logger.lifecycle("Generating Java bindings from ${headerFile.get().asFile}...")
39+
40+
execOperations.exec {
41+
commandLine(
42+
jextractPath.get(),
43+
"--output", outDir.absolutePath,
44+
"--target-package", targetPackage.get(),
45+
headerFile.get().asFile.absolutePath
46+
)
47+
}
48+
}
49+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package processing.gradle
2+
3+
object JextractUtils {
4+
fun findUserJextract(): String? {
5+
val jextractHome = System.getenv("JEXTRACT_HOME") ?: return null
6+
7+
val isWindows = System.getProperty("os.name").lowercase().contains("windows")
8+
val path = if (isWindows) {
9+
"$jextractHome/bin/jextract.bat"
10+
} else {
11+
"$jextractHome/bin/jextract"
12+
}
13+
14+
val file = java.io.File(path)
15+
if (file.exists()) {
16+
return path
17+
}
18+
19+
return null
20+
}
21+
22+
fun getExecutableName(): String {
23+
return if (System.getProperty("os.name").lowercase().contains("windows")) {
24+
"jextract.bat"
25+
} else {
26+
"jextract"
27+
}
28+
}
29+
}

0 commit comments

Comments
 (0)