diff --git a/BuildLogic/build.gradle.kts b/BuildLogic/build.gradle.kts index f64d3e946..af1bb0de2 100644 --- a/BuildLogic/build.gradle.kts +++ b/BuildLogic/build.gradle.kts @@ -12,15 +12,16 @@ // //===----------------------------------------------------------------------===// +plugins { + `kotlin-dsl` + embeddedKotlin("plugin.serialization") +} + repositories { gradlePluginPortal() mavenCentral() } dependencies { - implementation("org.jetbrains.kotlinx:kotlinx-serialization-json-jvm:1.7.3") -} - -plugins { - `kotlin-dsl` -} + implementation(libs.kotlinx.serialization.json) +} \ No newline at end of file diff --git a/BuildLogic/gradle/libs.versions.toml b/BuildLogic/gradle/libs.versions.toml new file mode 120000 index 000000000..d9b1d4e68 --- /dev/null +++ b/BuildLogic/gradle/libs.versions.toml @@ -0,0 +1 @@ +../../gradle/libs.versions.toml \ No newline at end of file diff --git a/BuildLogic/src/main/kotlin/build-logic.java-common-conventions.gradle.kts b/BuildLogic/src/main/kotlin/build-logic.java-common-conventions.gradle.kts index 1f2df6e59..1b1336f33 100644 --- a/BuildLogic/src/main/kotlin/build-logic.java-common-conventions.gradle.kts +++ b/BuildLogic/src/main/kotlin/build-logic.java-common-conventions.gradle.kts @@ -51,7 +51,7 @@ fun getSwiftRuntimeLibraryPaths(): List { /** * Find library paths for 'java.library.path' when running or testing projects inside this build. */ -// TODO: can't figure out how to share this code between BuildLogic/ and buildSrc/ +// TODO: Deduplicate this code with javaLibraryPaths.kt fun javaLibraryPaths(rootDir: File): List { val osName = System.getProperty("os.name").lowercase(Locale.getDefault()) val osArch = System.getProperty("os.arch") diff --git a/BuildLogic/src/main/kotlin/swiftPackageDescribe.kt b/BuildLogic/src/main/kotlin/swiftPackageDescribe.kt new file mode 100644 index 000000000..84c2f8d17 --- /dev/null +++ b/BuildLogic/src/main/kotlin/swiftPackageDescribe.kt @@ -0,0 +1,47 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2026 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import org.gradle.api.Project +import org.gradle.api.tasks.Exec +import org.gradle.kotlin.dsl.register +import org.gradle.kotlin.dsl.support.serviceOf +import org.gradle.process.ExecOperations +import utilities.SwiftcTargetInfo +import utilities.json +import utilities.swiftPMPackage +import java.io.ByteArrayOutputStream +import java.io.File + +fun Project.swiftProductDylibPaths(swiftBuildConfiguration: String): List { + // TODO: require that we depend on swift-java + // TODO: all the products where the targets depend on swift-java plugin + return swiftPMPackage().targets.map { + it.productMemberships + }.flatten().map { + logger.info("[swift-java] Include Swift product: '${it}' in product resource paths.") + "${layout.projectDirectory}/.build/${swiftBuildConfiguration}/lib${it}.dylib" + } +} + +fun Project.registerCleanSwift(workingDir: File = layout.projectDirectory.asFile) { + val cleanSwift = tasks.register("cleanSwift") { + this.workingDir = workingDir + commandLine("swift") + args("package", "clean") + } + tasks.named("clean").configure { + dependsOn(cleanSwift) + } +} + diff --git a/BuildLogic/src/main/kotlin/utilities/SwiftPMPackage.kt b/BuildLogic/src/main/kotlin/utilities/SwiftPMPackage.kt new file mode 100644 index 000000000..cb6a443f8 --- /dev/null +++ b/BuildLogic/src/main/kotlin/utilities/SwiftPMPackage.kt @@ -0,0 +1,36 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2026 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package utilities + +import kotlinx.serialization.Serializable +import org.gradle.api.Project +import org.gradle.kotlin.dsl.support.serviceOf +import org.gradle.process.ExecOperations +import java.io.ByteArrayOutputStream + +@Serializable +internal data class SwiftPMPackage( + val targets: List, +) + +internal fun Project.swiftPMPackage(): SwiftPMPackage { + val stdout = ByteArrayOutputStream() + serviceOf().exec { + workingDir(projectDir) + commandLine("swift", "package", "describe", "--type", "json") + standardOutput = stdout + } + return json.decodeFromString(stdout.toString()) +} \ No newline at end of file diff --git a/BuildLogic/src/main/kotlin/utilities/SwiftPMTarget.kt b/BuildLogic/src/main/kotlin/utilities/SwiftPMTarget.kt new file mode 100644 index 000000000..dfffda6ee --- /dev/null +++ b/BuildLogic/src/main/kotlin/utilities/SwiftPMTarget.kt @@ -0,0 +1,27 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2026 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package utilities + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +internal data class SwiftPMTarget( + val name: String, + @SerialName("product_dependencies") + val productDependencies: List = emptyList(), + @SerialName("product_memberships") + val productMemberships: List = emptyList(), +) \ No newline at end of file diff --git a/buildSrc/build.gradle b/BuildLogic/src/main/kotlin/utilities/SwiftcTargetInfo.kt similarity index 52% rename from buildSrc/build.gradle rename to BuildLogic/src/main/kotlin/utilities/SwiftcTargetInfo.kt index 925db83fc..ea0404d1a 100644 --- a/buildSrc/build.gradle +++ b/BuildLogic/src/main/kotlin/utilities/SwiftcTargetInfo.kt @@ -2,7 +2,7 @@ // // This source file is part of the Swift.org open source project // -// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Copyright (c) 2026 Apple Inc. and the Swift.org project authors // Licensed under Apache License v2.0 // // See LICENSE.txt for license information @@ -12,19 +12,11 @@ // //===----------------------------------------------------------------------===// -repositories { - mavenCentral() -} +package utilities -dependencies { - implementation("org.jetbrains.kotlinx:kotlinx-serialization-json-jvm:1.7.3") -} +import kotlinx.serialization.Serializable -def cleanSwift = tasks.register("cleanSwift", Exec) { - workingDir = layout.projectDirectory - commandLine "swift" - args("package", "clean") -} -tasks.clean { - dependsOn("cleanSwift") -} +@Serializable +internal data class SwiftcTargetInfo( + val paths: SwiftcTargetInfoPaths, +) \ No newline at end of file diff --git a/BuildLogic/src/main/kotlin/utilities/SwiftcTargetInfoPaths.kt b/BuildLogic/src/main/kotlin/utilities/SwiftcTargetInfoPaths.kt new file mode 100644 index 000000000..fcddc960c --- /dev/null +++ b/BuildLogic/src/main/kotlin/utilities/SwiftcTargetInfoPaths.kt @@ -0,0 +1,22 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2026 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package utilities + +import kotlinx.serialization.Serializable + +@Serializable +internal data class SwiftcTargetInfoPaths( + val runtimeLibraryPaths: List, +) \ No newline at end of file diff --git a/BuildLogic/src/main/kotlin/utilities/javaLibraryPaths.kt b/BuildLogic/src/main/kotlin/utilities/javaLibraryPaths.kt new file mode 100644 index 000000000..39cf9d110 --- /dev/null +++ b/BuildLogic/src/main/kotlin/utilities/javaLibraryPaths.kt @@ -0,0 +1,56 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2026 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package utilities + +import org.gradle.api.Project +import org.gradle.kotlin.dsl.support.serviceOf +import org.gradle.process.ExecOperations +import java.io.ByteArrayOutputStream +import java.io.File + +private fun Project.swiftRuntimeLibraryPaths(): List { + val stdout = ByteArrayOutputStream() + serviceOf().exec { + workingDir(projectDir) + commandLine("swiftc", "-print-target-info") + standardOutput = stdout + } + return json.decodeFromString(stdout.toString()).paths.runtimeLibraryPaths +} + +fun Project.javaLibraryPaths(rootDir: File?): List { + val osName = System.getProperty("os.name") + val osArch = System.getProperty("os.arch") + val isLinux = osName.lowercase().contains("linux") + val base = if (rootDir == null) "" else "${rootDir}/" + + val triple = if (isLinux) { + val arch = if (osArch == "amd64" || osArch == "x86_64") "x86_64" else osArch + "${arch}-unknown-linux-gnu" + } else { + val arch = if (osArch == "aarch64") "arm64" else osArch + "${arch}-apple-macosx" + } + + val paths: List = listOf("release", "debug").flatMap { configuration -> + listOf( + "${base}.build/${triple}/$configuration/", + "${base}../../.build/${triple}/$configuration/", + ) + } + val swiftRuntimePaths = swiftRuntimeLibraryPaths() + + return paths + swiftRuntimePaths +} \ No newline at end of file diff --git a/BuildLogic/src/main/kotlin/utilities/json.kt b/BuildLogic/src/main/kotlin/utilities/json.kt new file mode 100644 index 000000000..b1766ff89 --- /dev/null +++ b/BuildLogic/src/main/kotlin/utilities/json.kt @@ -0,0 +1,19 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2026 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package utilities + +import kotlinx.serialization.json.Json + +internal val json = Json { ignoreUnknownKeys = true } \ No newline at end of file diff --git a/BuildLogic/src/main/kotlin/utilities/registerJextractTask.kt b/BuildLogic/src/main/kotlin/utilities/registerJextractTask.kt new file mode 100644 index 000000000..f2f6605d1 --- /dev/null +++ b/BuildLogic/src/main/kotlin/utilities/registerJextractTask.kt @@ -0,0 +1,76 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2026 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package utilities + +import org.gradle.api.Project +import org.gradle.api.tasks.Exec +import org.gradle.api.tasks.TaskProvider +import org.gradle.kotlin.dsl.register +import java.io.File + +private fun Project.swiftTargetsWithJExtractPlugin(): List = swiftPMPackage().targets.filter { + it.productDependencies.contains("JExtractSwiftPlugin") +}.map { + it.name +} + +private fun Project.registerSwiftCheckValidTask(): TaskProvider<*> = tasks.register("swift-check-valid") { + commandLine("swift") + args("-version") +} + +fun Project.registerJextractTask( + arguments: () -> List = { + listOf("build", "--disable-experimental-prebuilts") + } +): TaskProvider<*> { + val swiftCheckValid = registerSwiftCheckValidTask() + return tasks.register("jextract") { + description = "Generate Java wrappers for swift target" + dependsOn(swiftCheckValid) + + // only because we depend on "live developing" the plugin while using this project to test it + inputs.file(File(rootDir, "Package.swift")) + inputs.dir(File(rootDir, "Sources")) + + // If the package description changes, we should execute jextract again, maybe we added jextract to new targets + inputs.file(File(projectDir, "Package.swift")) + + // monitor all targets/products which depend on the JExtract plugin + swiftTargetsWithJExtractPlugin().forEach { targetName -> + logger.info("[swift-java:jextract (Gradle)] Swift input target: ${targetName}") + inputs.dir(File(layout.projectDirectory.asFile, "Sources/${targetName}")) + outputs.dir( + layout.buildDirectory.dir( + "../.build/plugins/outputs/${layout.projectDirectory.asFile.getName().lowercase()}/${targetName}/destination/JExtractSwiftPlugin/src/generated/java" + ) + ) + } + + workingDir = layout.projectDirectory.asFile + commandLine("swift") + // FIXME: disable prebuilts until swift-syntax isn't broken on 6.2 anymore: https://github.com/swiftlang/swift-java/issues/418 + args(arguments()) // since Swift targets which need to be jextract-ed have the jextract build plugin, we just need to build + // If we wanted to execute a specific subcommand, we can like this: + // args("run",/* + // "swift-java", "jextract", + // "--swift-module", "MySwiftLibrary", + // // java.package is obtained from the swift-java.config in the swift module + // "--output-java", "${layout.buildDirectory.dir(".build/plugins/outputs/${layout.projectDirectory.asFile.getName().toLowerCase()}/JExtractSwiftPlugin/src/generated/java").get()}", + // "--output-swift", "${layout.buildDirectory.dir(".build/plugins/outputs/${layout.projectDirectory.asFile.getName().toLowerCase()}/JExtractSwiftPlugin/Sources").get()}", + // "--log-level", (logging.level <= LogLevel.INFO ? "debug" : */"info") + // ) + } +} \ No newline at end of file diff --git a/Samples/SwiftAndJavaJarSampleLib/build.gradle b/Samples/SwiftAndJavaJarSampleLib/build.gradle deleted file mode 100644 index e6404adb1..000000000 --- a/Samples/SwiftAndJavaJarSampleLib/build.gradle +++ /dev/null @@ -1,211 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2024 Apple Inc. and the Swift.org project authors -// Licensed under Apache License v2.0 -// -// See LICENSE.txt for license information -// See CONTRIBUTORS.txt for the list of Swift.org project authors -// -// SPDX-License-Identifier: Apache-2.0 -// -//===----------------------------------------------------------------------===// - - -import groovy.json.JsonSlurper -import org.swift.swiftkit.gradle.BuildUtils - -import java.nio.file.* - -plugins { - id("build-logic.java-library-conventions") - id "com.google.osdetector" version "1.7.3" - id("maven-publish") -} - -group = "org.swift.swiftkit" -version = "1.0-SNAPSHOT" - -def swiftBuildConfiguration() { - "release" -} - -repositories { - mavenLocal() - mavenCentral() -} - -java { - toolchain { - languageVersion.set(JavaLanguageVersion.of(25)) - } -} - -dependencies { - implementation(project(':SwiftKitCore')) - implementation(project(':SwiftKitFFM')) - - testRuntimeOnly("org.junit.platform:junit-platform-launcher") // TODO: workaround for not finding junit: https://github.com/gradle/gradle/issues/34512 - testImplementation(platform("org.junit:junit-bom:5.10.0")) - testImplementation("org.junit.jupiter:junit-jupiter") -} - -def swiftProductsWithJExtractPlugin() { - def stdout = new ByteArrayOutputStream() - def stderr = new ByteArrayOutputStream() - - def processBuilder = new ProcessBuilder('swift', 'package', 'describe', '--type', 'json') - def process = processBuilder.start() - - process.consumeProcessOutput(stdout, stderr) - process.waitFor() - - def exitValue = process.exitValue() - def jsonOutput = stdout.toString() - - if (exitValue == 0) { - def json = new JsonSlurper().parseText(jsonOutput) - def products = json.targets - .findAll { target -> - target.product_dependencies?.contains("JExtractSwiftPlugin") - } - .collectMany { target -> - target.product_memberships ?: [] - } - return products - } else { - logger.warn("Command failed: ${stderr.toString()}") - return [] - } -} - -def swiftCheckValid = tasks.register("swift-check-valid", Exec) { - commandLine "swift" - args("-version") -} - -def jextract = tasks.register("jextract", Exec) { - description = "Generate Java wrappers for swift target" - dependsOn swiftCheckValid - - // only because we depend on "live developing" the plugin while using this project to test it - inputs.file(new File(rootDir, "Package.swift")) - inputs.dir(new File(rootDir, "Sources")) - - // If the package description changes, we should execute jextract again, maybe we added jextract to new targets - inputs.file(new File(projectDir, "Package.swift")) - - // monitor all targets/products which depend on the JExtract plugin - swiftProductsWithJExtractPlugin().each { - logger.info("[swift-java:jextract (Gradle)] Swift input target: ${it}") - inputs.dir(new File(layout.projectDirectory.asFile, "Sources/${it}".toString())) - } - outputs.dir(layout.buildDirectory.dir("../.build/plugins/outputs/${layout.projectDirectory.asFile.getName().toLowerCase()}")) - - File baseSwiftPluginOutputsDir = layout.buildDirectory.dir("../.build/plugins/outputs/").get().asFile - if (!baseSwiftPluginOutputsDir.exists()) { - baseSwiftPluginOutputsDir.mkdirs() - } - Files.walk(layout.buildDirectory.dir("../.build/plugins/outputs/").get().asFile.toPath()).each { - // Add any Java sources generated by the plugin to our sourceSet - if (it.endsWith("JExtractSwiftPlugin/src/generated/java")) { - outputs.dir(it) - } - } - - workingDir = layout.projectDirectory - commandLine "swift" - // FIXME: disable prebuilts until swift-syntax isn't broken on 6.2 anymore: https://github.com/swiftlang/swift-java/issues/418 - args("build", "--disable-experimental-prebuilts") // since Swift targets which need to be jextract-ed have the jextract build plugin, we just need to build - // If we wanted to execute a specific subcommand, we can like this: - // args("run",/* - // "swift-java", "jextract", - // "--swift-module", "MySwiftLibrary", - // // java.package is obtained from the swift-java.config in the swift module - // "--output-java", "${layout.buildDirectory.dir(".build/plugins/outputs/${layout.projectDirectory.asFile.getName().toLowerCase()}/JExtractSwiftPlugin/src/generated/java").get()}", - // "--output-swift", "${layout.buildDirectory.dir(".build/plugins/outputs/${layout.projectDirectory.asFile.getName().toLowerCase()}/JExtractSwiftPlugin/Sources").get()}", - // "--log-level", (logging.level <= LogLevel.INFO ? "debug" : */"info") - // ) -} - - -// Add the java-swift generated Java sources -sourceSets { - main { - java { - srcDir(jextract) - } - } - test { - java { - srcDir(jextract) - } - } -} - -tasks.build { - dependsOn("jextract") -} - -tasks.named('test', Test) { - useJUnitPlatform() -} - - -// ==== Jar publishing - -List swiftProductDylibPaths() { - def process = ['swift', 'package', 'describe', '--type', 'json'].execute() - process.waitFor() - - if (process.exitValue() != 0) { - throw new RuntimeException("[swift describe] command failed with exit code: ${process.exitValue()}. Cannot find products! Output: ${process.err.text}") - } - - def json = new JsonSlurper().parseText(process.text) - - // TODO: require that we depend on swift-java - // TODO: all the products where the targets depend on swift-java plugin - def products = - json.targets.collect { target -> - target.product_memberships - }.flatten() - - def productDylibPaths = products.collect { - logger.info("[swift-java] Include Swift product: '${it}' in product resource paths.") - "${layout.projectDirectory}/.build/${swiftBuildConfiguration()}/lib${it}.dylib" - } - - return productDylibPaths -} - -processResources { - dependsOn "jextract" - - def dylibs = [ - "${layout.projectDirectory}/.build/${swiftBuildConfiguration()}/libSwiftKitSwift.dylib" - ] - dylibs.addAll(swiftProductDylibPaths()) - from(dylibs) -} - -jar { - archiveClassifier = osdetector.classifier -} - -base { - archivesName = "swift-and-java-jar-sample-lib" -} - -publishing { - publications { - maven(MavenPublication) { - artifactId = "swift-and-java-jar-sample-lib" - from components.java - } - } - repositories { - mavenLocal() - } -} diff --git a/Samples/SwiftAndJavaJarSampleLib/build.gradle.kts b/Samples/SwiftAndJavaJarSampleLib/build.gradle.kts new file mode 100644 index 000000000..33f77c70e --- /dev/null +++ b/Samples/SwiftAndJavaJarSampleLib/build.gradle.kts @@ -0,0 +1,101 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import utilities.registerJextractTask + +plugins { + id("build-logic.java-library-conventions") + id("com.google.osdetector") version "1.7.3" + `maven-publish` +} + +group = "org.swift.swiftkit" +version = "1.0-SNAPSHOT" + +val swiftBuildConfiguration = "release" + +repositories { + mavenLocal() + mavenCentral() +} + +java { + toolchain { + languageVersion.set(JavaLanguageVersion.of(25)) + } +} + +dependencies { + implementation(projects.swiftKitCore) + implementation(projects.swiftKitFFM) + + testRuntimeOnly(libs.junit.platform.launcher) // TODO: workaround for not finding junit: https://github.com/gradle/gradle/issues/34512 + testImplementation(platform(libs.junit.bom)) + testImplementation(libs.junit.jupiter) +} + +val jextract = registerJextractTask() + +// Add the java-swift generated Java sources +sourceSets { + main { + java { + srcDir(jextract) + } + } + test { + java { + srcDir(jextract) + } + } +} + +tasks.build { + dependsOn(jextract) +} + +tasks.named("test") { + useJUnitPlatform() +} + + +// ==== Jar publishing + +tasks.processResources.configure { + dependsOn(jextract) + val dylibs = listOf( + "${layout.projectDirectory}/.build/${swiftBuildConfiguration}/libSwiftKitSwift.dylib" + ) + swiftProductDylibPaths(swiftBuildConfiguration) + from(dylibs) +} + +tasks.jar.configure { + archiveClassifier = osdetector.classifier +} + +base { + archivesName = "swift-and-java-jar-sample-lib" +} + +publishing { + publications { + create("maven") { + artifactId = "swift-and-java-jar-sample-lib" + from(components["java"]) + } + } + repositories { + mavenLocal() + } +} diff --git a/Samples/SwiftJavaExtractFFMSampleApp/build.gradle b/Samples/SwiftJavaExtractFFMSampleApp/build.gradle deleted file mode 100644 index dcfacdd39..000000000 --- a/Samples/SwiftJavaExtractFFMSampleApp/build.gradle +++ /dev/null @@ -1,197 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2024 Apple Inc. and the Swift.org project authors -// Licensed under Apache License v2.0 -// -// See LICENSE.txt for license information -// See CONTRIBUTORS.txt for the list of Swift.org project authors -// -// SPDX-License-Identifier: Apache-2.0 -// -//===----------------------------------------------------------------------===// - -import groovy.json.JsonSlurper -import org.swift.swiftkit.gradle.BuildUtils - -import java.nio.file.* - -plugins { - id("build-logic.java-application-conventions") - id("me.champeau.jmh") version "0.7.2" -} - -group = "org.swift.swiftkit" -version = "1.0-SNAPSHOT" - -repositories { - mavenCentral() -} - -java { - toolchain { - languageVersion.set(JavaLanguageVersion.of(25)) - } -} - -def swiftProductsWithJExtractPlugin() { - def stdout = new ByteArrayOutputStream() - def stderr = new ByteArrayOutputStream() - - def processBuilder = new ProcessBuilder('swift', 'package', 'describe', '--type', 'json') - def process = processBuilder.start() - - process.consumeProcessOutput(stdout, stderr) - process.waitFor() - - def exitValue = process.exitValue() - def jsonOutput = stdout.toString() - - if (exitValue == 0) { - def json = new JsonSlurper().parseText(jsonOutput) - def products = json.targets - .findAll { target -> - target.product_dependencies?.contains("JExtractSwiftPlugin") - } - .collectMany { target -> - target.product_memberships ?: [] - } - return products - } else { - logger.warn("Command failed: ${stderr.toString()}") - return [] - } -} - - -def swiftCheckValid = tasks.register("swift-check-valid", Exec) { - commandLine "swift" - args("-version") -} - -def jextract = tasks.register("jextract", Exec) { - description = "Generate Java wrappers for swift target" - dependsOn swiftCheckValid - - // only because we depend on "live developing" the plugin while using this project to test it - inputs.file(new File(rootDir, "Package.swift")) - inputs.dir(new File(rootDir, "Sources")) - - // If the package description changes, we should execute jextract again, maybe we added jextract to new targets - inputs.file(new File(projectDir, "Package.swift")) - - // monitor all targets/products which depend on the JExtract plugin - swiftProductsWithJExtractPlugin().each { - logger.info("[swift-java:jextract (Gradle)] Swift input target: ${it}") - inputs.dir(new File(layout.projectDirectory.asFile, "Sources/${it}".toString())) - } - outputs.dir(layout.buildDirectory.dir("../.build/plugins/outputs/${layout.projectDirectory.asFile.getName().toLowerCase()}")) - - File baseSwiftPluginOutputsDir = layout.buildDirectory.dir("../.build/plugins/outputs/").get().asFile - if (!baseSwiftPluginOutputsDir.exists()) { - baseSwiftPluginOutputsDir.mkdirs() - } - Files.walk(layout.buildDirectory.dir("../.build/plugins/outputs/").get().asFile.toPath()).each { - // Add any Java sources generated by the plugin to our sourceSet - if (it.endsWith("JExtractSwiftPlugin/src/generated/java")) { - outputs.dir(it) - } - } - - workingDir = layout.projectDirectory - commandLine "swift" - // FIXME: disable prebuilts until swift-syntax isn't broken on 6.2 anymore: https://github.com/swiftlang/swift-java/issues/418 - args("build", "--disable-experimental-prebuilts") // since Swift targets which need to be jextract-ed have the jextract build plugin, we just need to build - // If we wanted to execute a specific subcommand, we can like this: - // args("run",/* - // "swift-java", "jextract", - // "--swift-module", "MySwiftLibrary", - // // java.package is obtained from the swift-java.config in the swift module - // "--output-java", "${layout.buildDirectory.dir(".build/plugins/outputs/${layout.projectDirectory.asFile.getName().toLowerCase()}/JExtractSwiftPlugin/src/generated/java").get()}", - // "--output-swift", "${layout.buildDirectory.dir(".build/plugins/outputs/${layout.projectDirectory.asFile.getName().toLowerCase()}/JExtractSwiftPlugin/Sources").get()}", - // "--log-level", (logging.level <= LogLevel.INFO ? "debug" : */"info") - // ) -} - -// Add the java-swift generated Java sources -sourceSets { - main { - java { - srcDir(jextract) - } - } - test { - java { - srcDir(jextract) - } - } - jmh { - java { - srcDir(jextract) - } - } -} - -tasks.build { - dependsOn("jextract") -} - - -def cleanSwift = tasks.register("cleanSwift", Exec) { - workingDir = layout.projectDirectory - commandLine "swift" - args("package", "clean") -} -tasks.clean { - dependsOn("cleanSwift") -} - -dependencies { - implementation(project(':SwiftKitCore')) - implementation(project(':SwiftKitFFM')) - - testRuntimeOnly("org.junit.platform:junit-platform-launcher") // TODO: workaround for not finding junit: https://github.com/gradle/gradle/issues/34512 // TODO: workaround for not finding junit: https://github.com/gradle/gradle/issues/34512 - testImplementation(platform("org.junit:junit-bom:5.10.0")) - testImplementation("org.junit.jupiter:junit-jupiter") -} - -tasks.named('test', Test) { - useJUnitPlatform() -} - -application { - mainClass = "com.example.swift.HelloJava2Swift" - - applicationDefaultJvmArgs = [ - "--enable-native-access=ALL-UNNAMED", - - // Include the library paths where our dylibs are that we want to load and call - "-Djava.library.path=" + - (BuildUtils.javaLibraryPaths(rootDir) + - BuildUtils.javaLibraryPaths(project.projectDir)).join(":"), - - - // Enable tracing downcalls (to Swift) - "-Djextract.trace.downcalls=true" - ] -} - -String jmhIncludes = findProperty("jmhIncludes") - -jmh { - if (jmhIncludes != null) { - includes = [jmhIncludes] - } - - jvmArgsAppend = [ - "--enable-native-access=ALL-UNNAMED", - - "-Djava.library.path=" + - (BuildUtils.javaLibraryPaths(rootDir) + - BuildUtils.javaLibraryPaths(project.projectDir)).join(":"), - - // Enable tracing downcalls (to Swift) - "-Djextract.trace.downcalls=false" - ] -} diff --git a/Samples/SwiftJavaExtractFFMSampleApp/build.gradle.kts b/Samples/SwiftJavaExtractFFMSampleApp/build.gradle.kts new file mode 100644 index 000000000..cd685d067 --- /dev/null +++ b/Samples/SwiftJavaExtractFFMSampleApp/build.gradle.kts @@ -0,0 +1,102 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import utilities.javaLibraryPaths +import utilities.registerJextractTask + +plugins { + id("build-logic.java-application-conventions") + id("me.champeau.jmh") version "0.7.2" +} + +group = "org.swift.swiftkit" +version = "1.0-SNAPSHOT" + +repositories { + mavenCentral() +} + +java { + toolchain { + languageVersion.set(JavaLanguageVersion.of(25)) + } +} + + +val jextract = registerJextractTask() + +// Add the java-swift generated Java sources +sourceSets { + main { + java { + srcDir(jextract) + } + } + test { + java { + srcDir(jextract) + } + } + this.jmh { + java { + srcDir(jextract) + } + } +} + +tasks.build { + dependsOn(jextract) +} + +registerCleanSwift() + +dependencies { + implementation(projects.swiftKitCore) + implementation(projects.swiftKitFFM) + + testRuntimeOnly(libs.junit.platform.launcher) // TODO: workaround for not finding junit: https://github.com/gradle/gradle/issues/34512 + testImplementation(platform(libs.junit.bom)) + testImplementation(libs.junit.jupiter) +} + +tasks.named("test") { + useJUnitPlatform() +} + +application { + mainClass = "com.example.swift.HelloJava2Swift" + + applicationDefaultJvmArgs = listOf( + "--enable-native-access=ALL-UNNAMED", + // Include the library paths where our dylibs are that we want to load and call + "-Djava.library.path=" + (javaLibraryPaths(rootDir) + javaLibraryPaths(project.projectDir)).joinToString(":"), + // Enable tracing downcalls (to Swift) + "-Djextract.trace.downcalls=true" + ) +} + +val jmhIncludes = findProperty("jmhIncludes") + +jmh { + if (jmhIncludes != null) { + includes = listOf(jmhIncludes.toString()) + } + + jvmArgsAppend = listOf( + "--enable-native-access=ALL-UNNAMED", + "-Djava.library.path=" + (javaLibraryPaths(rootDir) + javaLibraryPaths(project.projectDir)).joinToString(":"), + // Enable tracing downcalls (to Swift) + "-Djextract.trace.downcalls=false" + ) +} diff --git a/Samples/SwiftJavaExtractJNISampleApp/build.gradle b/Samples/SwiftJavaExtractJNISampleApp/build.gradle deleted file mode 100644 index 7bb64c554..000000000 --- a/Samples/SwiftJavaExtractJNISampleApp/build.gradle +++ /dev/null @@ -1,219 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2024 Apple Inc. and the Swift.org project authors -// Licensed under Apache License v2.0 -// -// See LICENSE.txt for license information -// See CONTRIBUTORS.txt for the list of Swift.org project authors -// -// SPDX-License-Identifier: Apache-2.0 -// -//===----------------------------------------------------------------------===// - -import groovy.json.JsonSlurper -import org.swift.swiftkit.gradle.BuildUtils - -import java.nio.file.* -import kotlinx.serialization.json.* - -plugins { - id("build-logic.java-application-conventions") - id("me.champeau.jmh") version "0.7.2" -} - -group = "org.swift.swiftkit" -version = "1.0-SNAPSHOT" - -repositories { - mavenCentral() -} - -java { - toolchain { - languageVersion.set(JavaLanguageVersion.of(25)) - } -} - -def swiftProductsWithJExtractPlugin() { - def stdout = new ByteArrayOutputStream() - def stderr = new ByteArrayOutputStream() - - def processBuilder = new ProcessBuilder('swift', 'package', 'describe', '--type', 'json') - def process = processBuilder.start() - - process.consumeProcessOutput(stdout, stderr) - process.waitFor() - - def exitValue = process.exitValue() - def jsonOutput = stdout.toString() - - if (exitValue == 0) { - def json = new JsonSlurper().parseText(jsonOutput) - def products = json.targets - .findAll { target -> - target.product_dependencies?.contains("JExtractSwiftPlugin") - } - .collectMany { target -> - target.product_memberships ?: [] - } - return products - } else { - logger.warn("Command failed: ${stderr.toString()}") - return [] - } -} - - -def swiftCheckValid = tasks.register("swift-check-valid", Exec) { - commandLine "swift" - args("-version") -} - -def jextract = tasks.register("jextract", Exec) { - description = "Generate Java wrappers for swift target" - dependsOn swiftCheckValid - - // only because we depend on "live developing" the plugin while using this project to test it - inputs.file(new File(rootDir, "Package.swift")) - inputs.dir(new File(rootDir, "Sources")) - - // If the package description changes, we should execute jextract again, maybe we added jextract to new targets - inputs.file(new File(projectDir, "Package.swift")) - - // monitor all targets/products which depend on the JExtract plugin - swiftProductsWithJExtractPlugin().each { - logger.info("[swift-java:jextract (Gradle)] Swift input target: ${it}") - inputs.dir(new File(layout.projectDirectory.asFile, "Sources/${it}".toString())) - } - outputs.dir(layout.buildDirectory.dir("../.build/plugins/outputs/${layout.projectDirectory.asFile.getName().toLowerCase()}")) - - File baseSwiftPluginOutputsDir = layout.buildDirectory.dir("../.build/plugins/outputs/").get().asFile - if (!baseSwiftPluginOutputsDir.exists()) { - baseSwiftPluginOutputsDir.mkdirs() - } - Files.walk(layout.buildDirectory.dir("../.build/plugins/outputs/").get().asFile.toPath()).each { - // Add any Java sources generated by the plugin to our sourceSet - if (it.endsWith("JExtractSwiftPlugin/src/generated/java")) { - outputs.dir(it) - } - } - - // FIXME: disable prebuilts until swift-syntax isn't broken on 6.2 anymore: https://github.com/swiftlang/swift-java/issues/418 - def cmdArgs = ["build", "--disable-experimental-prebuilts", "--disable-sandbox"] - - // Check if the 'swiftSdk' project property was passed - if (project.hasProperty('swiftSdk')) { - // If it was, add the --sdk argument and its value - cmdArgs.add("--swift-sdk") - cmdArgs.add(project.property('swiftSdk').toString()) - } - - workingDir = layout.projectDirectory - commandLine "swift" - args(cmdArgs) // since Swift targets which need to be jextract-ed have the jextract build plugin, we just need to build - // If we wanted to execute a specific subcommand, we can like this: - // args("run",/* - // "swift-java", "jextract", - // "--swift-module", "MySwiftLibrary", - // // java.package is obtained from the swift-java.config in the swift module - // "--output-java", "${layout.buildDirectory.dir(".build/plugins/outputs/${layout.projectDirectory.asFile.getName().toLowerCase()}/JExtractSwiftPlugin/src/generated/java").get()}", - // "--output-swift", "${layout.buildDirectory.dir(".build/plugins/outputs/${layout.projectDirectory.asFile.getName().toLowerCase()}/JExtractSwiftPlugin/Sources").get()}", - // "--log-level", (logging.level <= LogLevel.INFO ? "debug" : */"info") - // ) -} - -// Add the java-swift generated Java sources -sourceSets { - main { - java { - srcDir(jextract) - } - } - test { - java { - srcDir(jextract) - } - } - jmh { - java { - srcDir(jextract) - } - } -} - -tasks.build { - dependsOn("jextract") -} - - -def cleanSwift = tasks.register("cleanSwift", Exec) { - workingDir = layout.projectDirectory - commandLine "swift" - args("package", "clean") -} -tasks.clean { - dependsOn("cleanSwift") -} - -dependencies { - implementation(project(':SwiftKitCore')) - - testRuntimeOnly("org.junit.platform:junit-platform-launcher") // TODO: workaround for not finding junit: https://github.com/gradle/gradle/issues/34512 - testImplementation(platform("org.junit:junit-bom:5.10.0")) - testImplementation("org.junit.jupiter:junit-jupiter") -} - -tasks.named('test', Test) { - useJUnitPlatform() - - testLogging { - events "failed" - exceptionFormat "full" - } -} - -application { - mainClass = "com.example.swift.HelloJava2SwiftJNI" - - applicationDefaultJvmArgs = [ - "--enable-native-access=ALL-UNNAMED", - - // Include the library paths where our dylibs are that we want to load and call - "-Djava.library.path=" + - (BuildUtils.javaLibraryPaths(rootDir) + - BuildUtils.javaLibraryPaths(project.projectDir)).join(":"), - - - // Enable tracing downcalls (to Swift) - "-Djextract.trace.downcalls=true" - ] -} - -String jmhIncludes = findProperty("jmhIncludes") - -jmh { - if (jmhIncludes != null) { - includes = [jmhIncludes] - } - - jvmArgsAppend = [ - "--enable-native-access=ALL-UNNAMED", - - "-Djava.library.path=" + - (BuildUtils.javaLibraryPaths(rootDir) + - BuildUtils.javaLibraryPaths(project.projectDir)).join(":"), - - // Enable tracing downcalls (to Swift) - "-Djextract.trace.downcalls=false" - ] -} - -task printGradleHome { - doLast { - println "Gradle Home: ${gradle.gradleHomeDir}" - println "Gradle Version: ${gradle.gradleVersion}" - println "Gradle User Home: ${gradle.gradleUserHomeDir}" - } -} \ No newline at end of file diff --git a/Samples/SwiftJavaExtractJNISampleApp/build.gradle.kts b/Samples/SwiftJavaExtractJNISampleApp/build.gradle.kts new file mode 100644 index 000000000..2df9e3772 --- /dev/null +++ b/Samples/SwiftJavaExtractJNISampleApp/build.gradle.kts @@ -0,0 +1,122 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import utilities.javaLibraryPaths +import utilities.registerJextractTask + +plugins { + id("build-logic.java-application-conventions") + id("me.champeau.jmh") version "0.7.2" +} + +group = "org.swift.swiftkit" +version = "1.0-SNAPSHOT" + +repositories { + mavenCentral() +} + +java { + toolchain { + languageVersion.set(JavaLanguageVersion.of(25)) + } +} + +val jextract = registerJextractTask { + // FIXME: disable prebuilts until swift-syntax isn't broken on 6.2 anymore: https://github.com/swiftlang/swift-java/issues/418 + val cmdArgs = mutableListOf("build", "--disable-experimental-prebuilts", "--disable-sandbox") + if (project.hasProperty("swiftSdk")) { + // If it was, add the --sdk argument and its value + cmdArgs.add("--swift-sdk") + cmdArgs.add(project.property("swiftSdk").toString()) + } + cmdArgs +} + +// Add the java-swift generated Java sources +sourceSets { + main { + java { + srcDir(jextract) + } + } + test { + java { + srcDir(jextract) + } + } + this.jmh { + java { + srcDir(jextract) + } + } +} + +tasks.build { + dependsOn(jextract) +} + +registerCleanSwift() + +dependencies { + implementation(projects.swiftKitCore) + + testRuntimeOnly(libs.junit.platform.launcher) // TODO: workaround for not finding junit: https://github.com/gradle/gradle/issues/34512 + testImplementation(platform(libs.junit.bom)) + testImplementation(libs.junit.jupiter) +} + +tasks.named("test") { + useJUnitPlatform() + + testLogging { + events("failed") + exceptionFormat = org.gradle.api.tasks.testing.logging.TestExceptionFormat.FULL + } +} + +application { + mainClass = "com.example.swift.HelloJava2SwiftJNI" + + applicationDefaultJvmArgs = listOf( + "--enable-native-access=ALL-UNNAMED", + // Include the library paths where our dylibs are that we want to load and call + "-Djava.library.path=" + (javaLibraryPaths(rootDir) + javaLibraryPaths(project.projectDir)).joinToString(":"), + // Enable tracing downcalls (to Swift) + "-Djextract.trace.downcalls=true" + ) +} + +val jmhIncludes = findProperty("jmhIncludes") + +jmh { + if (jmhIncludes != null) { + includes = listOf(jmhIncludes.toString()) + } + + jvmArgsAppend = listOf( + "--enable-native-access=ALL-UNNAMED", + "-Djava.library.path=" + (javaLibraryPaths(rootDir) + javaLibraryPaths(project.projectDir)).joinToString(":"), + // Enable tracing downcalls (to Swift) + "-Djextract.trace.downcalls=false" + ) +} + +tasks.register("printGradleHome") { + doLast { + println("Gradle Home: ${gradle.gradleHomeDir}") + println("Gradle Version: ${gradle.gradleVersion}") + println("Gradle User Home: ${gradle.gradleUserHomeDir}") + } +} \ No newline at end of file diff --git a/SwiftKitCore/build.gradle b/SwiftKitCore/build.gradle.kts similarity index 55% rename from SwiftKitCore/build.gradle rename to SwiftKitCore/build.gradle.kts index bc6bd2794..91dea2e3f 100644 --- a/SwiftKitCore/build.gradle +++ b/SwiftKitCore/build.gradle.kts @@ -15,7 +15,7 @@ plugins { id("build-logic.java-application-conventions") id("me.champeau.jmh") version "0.7.2" - id("maven-publish") + `maven-publish` } group = "org.swift.swiftkit" @@ -31,12 +31,12 @@ repositories { publishing { publications { - maven(MavenPublication) { - groupId = group - artifactId = 'swiftkit-core' - version = '1.0-SNAPSHOT' + create("maven") { + groupId = group as? String + artifactId = "swiftkit-core" + version = "1.0-SNAPSHOT" - from components.java + from(components["java"]) } } } @@ -47,21 +47,21 @@ java { } } -tasks.withType(JavaCompile).configureEach { +tasks.withType().configureEach { // Support Java 11 options.release.set(11) } dependencies { - testRuntimeOnly("org.junit.platform:junit-platform-launcher") // TODO: workaround for not finding junit: https://github.com/gradle/gradle/issues/34512 - testImplementation(platform("org.junit:junit-bom:5.10.0")) - testImplementation("org.junit.jupiter:junit-jupiter") + testRuntimeOnly(libs.junit.platform.launcher) // TODO: workaround for not finding junit: https://github.com/gradle/gradle/issues/34512 + testImplementation(platform(libs.junit.bom)) + testImplementation(libs.junit.jupiter) } testing { suites { - test { - useJUnitJupiter('5.10.3') + val test by getting(JvmTestSuite::class) { + useJUnitJupiter() } } } @@ -75,30 +75,20 @@ tasks.test { // SwiftKit depends on SwiftRuntimeFunctions (Swift library that this Java library calls into) -def compileSwift = tasks.register("compileSwift", Exec) { - description "Compile the swift-java SwiftRuntimeFunctions dynamic library that SwiftKit (Java) calls into" +val compileSwift = tasks.register("compileSwift") { + description = "Compile the swift-java SwiftRuntimeFunctions dynamic library that SwiftKit (Java) calls into" - inputs.file(new File(rootDir, "Package.swift")) - inputs.dir(new File(rootDir, "Sources/")) // a bit generous, but better safe than sorry, and include all Swift source changes - outputs.dir(new File(rootDir, ".build")) + inputs.file(File(rootDir, "Package.swift")) + inputs.dir(File(rootDir, "Sources/")) // a bit generous, but better safe than sorry, and include all Swift source changes + outputs.dir(File(rootDir, ".build")) workingDir = rootDir - commandLine "swift" + commandLine("swift") // FIXME: disable prebuilts until swift-syntax isn't broken on 6.2 anymore: https://github.com/swiftlang/swift-java/issues/418 args("build", "--disable-experimental-prebuilts", "--target", "SwiftRuntimeFunctions") } tasks.build { - dependsOn("compileSwift") -} - - - -def cleanSwift = tasks.register("cleanSwift", Exec) { - workingDir = rootDir - commandLine "swift" - args("package", "clean") -} -tasks.clean { - dependsOn("cleanSwift") + dependsOn(compileSwift) } +registerCleanSwift(rootDir) \ No newline at end of file diff --git a/SwiftKitFFM/build.gradle b/SwiftKitFFM/build.gradle.kts similarity index 55% rename from SwiftKitFFM/build.gradle rename to SwiftKitFFM/build.gradle.kts index 08a36a3e3..973198442 100644 --- a/SwiftKitFFM/build.gradle +++ b/SwiftKitFFM/build.gradle.kts @@ -14,11 +14,12 @@ plugins { id("build-logic.java-application-conventions") - id("maven-publish") + `maven-publish` } group = "org.swift.swiftkit" version = "1.0-SNAPSHOT" + base { archivesName = "swiftkit-ffm" } @@ -30,12 +31,12 @@ repositories { publishing { publications { - maven(MavenPublication) { - groupId = group - artifactId = 'swiftkit-ffm' - version = '1.0-SNAPSHOT' + create("maven") { + groupId = group as? String + artifactId = "swiftkit-ffm" + version = "1.0-SNAPSHOT" - from components.java + from(components["java"]) } } } @@ -47,17 +48,17 @@ java { } dependencies { - implementation(project(':SwiftKitCore')) + implementation(projects.swiftKitCore) - testRuntimeOnly("org.junit.platform:junit-platform-launcher") // TODO: workaround for not finding junit: https://github.com/gradle/gradle/issues/34512 - testImplementation(platform("org.junit:junit-bom:5.10.0")) - testImplementation("org.junit.jupiter:junit-jupiter") + testRuntimeOnly(libs.junit.platform.launcher) // TODO: workaround for not finding junit: https://github.com/gradle/gradle/issues/34512 + testImplementation(platform(libs.junit.bom)) + testImplementation(libs.junit.jupiter) } testing { suites { - test { - useJUnitJupiter('5.10.3') + val test by getting(JvmTestSuite::class) { + useJUnitJupiter() } } } @@ -70,37 +71,27 @@ tasks.test { } /// Enable access to preview APIs, e.g. java.lang.foreign.* (Panama) -tasks.withType(JavaCompile).configureEach { +tasks.withType().configureEach { options.compilerArgs.add("--enable-preview") options.compilerArgs.add("-Xlint:preview") } // SwiftKit depends on SwiftRuntimeFunctions (Swift library that this Java library calls into) -def compileSwift = tasks.register("compileSwift", Exec) { - description "Compile the swift-java SwiftRuntimeFunctions dynamic library that SwiftKit (Java) calls into" +val compileSwift = tasks.register("compileSwift") { + description = "Compile the swift-java SwiftRuntimeFunctions dynamic library that SwiftKit (Java) calls into" - inputs.file(new File(rootDir, "Package.swift")) - inputs.dir(new File(rootDir, "Sources/")) // a bit generous, but better safe than sorry, and include all Swift source changes - outputs.dir(new File(rootDir, ".build")) + inputs.file(File(rootDir, "Package.swift")) + inputs.dir(File(rootDir, "Sources/")) // a bit generous, but better safe than sorry, and include all Swift source changes + outputs.dir(File(rootDir, ".build")) workingDir = rootDir - commandLine "swift" + commandLine("swift") // FIXME: disable prebuilts until swift-syntax isn't broken on 6.2 anymore: https://github.com/swiftlang/swift-java/issues/418 args("build", "--disable-experimental-prebuilts", "--target", "SwiftRuntimeFunctions") } tasks.build { - dependsOn("compileSwift") -} - - - -def cleanSwift = tasks.register("cleanSwift", Exec) { - workingDir = rootDir - commandLine "swift" - args("package", "clean") -} -tasks.clean { - dependsOn("cleanSwift") + dependsOn(compileSwift) } +registerCleanSwift(rootDir) \ No newline at end of file diff --git a/buildSrc/README.md b/buildSrc/README.md deleted file mode 100644 index f3559b800..000000000 --- a/buildSrc/README.md +++ /dev/null @@ -1 +0,0 @@ -buildSrc are shared "build library code" that is available to all sub-projects of the primary build. diff --git a/buildSrc/src/main/groovy/org/swift/swiftkit/gradle/BuildUtils.groovy b/buildSrc/src/main/groovy/org/swift/swiftkit/gradle/BuildUtils.groovy deleted file mode 100644 index 9512307f6..000000000 --- a/buildSrc/src/main/groovy/org/swift/swiftkit/gradle/BuildUtils.groovy +++ /dev/null @@ -1,60 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2024 Apple Inc. and the Swift.org project authors -// Licensed under Apache License v2.0 -// -// See LICENSE.txt for license information -// See CONTRIBUTORS.txt for the list of Swift.org project authors -// -// SPDX-License-Identifier: Apache-2.0 -// -//===----------------------------------------------------------------------===// - -package org.swift.swiftkit.gradle - -import groovy.json.JsonSlurper - -final class BuildUtils { - - static List getSwiftRuntimeLibraryPaths() { - def process = ['swiftc', '-print-target-info'].execute() - def output = new StringWriter() - process.consumeProcessOutput(output, System.err) - process.waitFor() - - def json = new JsonSlurper().parseText(output.toString()) - def runtimeLibraryPaths = json.paths.runtimeLibraryPaths - return runtimeLibraryPaths - } - - /// Find library paths for 'java.library.path' when running or testing projects inside this build. - static def javaLibraryPaths(File rootDir) { - def osName = System.getProperty("os.name") - def osArch = System.getProperty("os.arch") - def isLinux = osName.toLowerCase(Locale.getDefault()).contains("linux") - def base = rootDir == null ? "" : "${rootDir}/" - - def debugPaths = [ - isLinux ? - /* Linux */ (osArch == "amd64" || osArch == "x86_64" ? - "${base}.build/x86_64-unknown-linux-gnu/debug/" : - "${base}.build/${osArch}-unknown-linux-gnu/debug/") : - /* macOS */ (osArch == "aarch64" ? - "${base}.build/arm64-apple-macosx/debug/" : - "${base}.build/${osArch}-apple-macosx/debug/"), - isLinux ? - /* Linux */ (osArch == "amd64" || osArch == "x86_64" ? - "${base}../../.build/x86_64-unknown-linux-gnu/debug/" : - "${base}../../.build/${osArch}-unknown-linux-gnu/debug/") : - /* macOS */ (osArch == "aarch64" ? - "${base}../../.build/arm64-apple-macosx/debug/" : - "${base}../../.build/${osArch}-apple-macosx/debug/"), - ] - def releasePaths = debugPaths.collect { it.replaceAll("debug", "release") } - def swiftRuntimePaths = getSwiftRuntimeLibraryPaths() - - return releasePaths + debugPaths + swiftRuntimePaths - } -} diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml new file mode 100644 index 000000000..c85126f74 --- /dev/null +++ b/gradle/libs.versions.toml @@ -0,0 +1,23 @@ +##===----------------------------------------------------------------------===## +## +## This source file is part of the Swift.org open source project +## +## Copyright (c) 2026 Apple Inc. and the Swift.org project authors +## Licensed under Apache License v2.0 +## +## See LICENSE.txt for license information +## See CONTRIBUTORS.txt for the list of Swift.org project authors +## +## SPDX-License-Identifier: Apache-2.0 +## +##===----------------------------------------------------------------------===## + +[versions] +kotlinx-serialization = "1.7.3" +junit-version = "5.10.0" + +[libraries] +kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlinx-serialization" } +junit-platform-launcher = { module = "org.junit.platform:junit-platform-launcher" } +junit-jupiter = { module = "org.junit.jupiter:junit-jupiter" } +junit-bom = { module = "org.junit:junit-bom", version.ref = "junit-version" } \ No newline at end of file diff --git a/settings.gradle b/settings.gradle.kts similarity index 63% rename from settings.gradle rename to settings.gradle.kts index 3efb3bd6d..a360e0786 100644 --- a/settings.gradle +++ b/settings.gradle.kts @@ -18,15 +18,16 @@ pluginManagement { rootProject.name = "swift-java" -include "SwiftKitCore" -include "SwiftKitFFM" +include("SwiftKitCore") +include("SwiftKitFFM") // Include sample apps -- you can run them via `gradle Name:run` -// Can be disabled with -PskipSamples=true -if (!hasProperty('skipSamples') || skipSamples != 'true') { - new File(rootDir, "Samples").listFiles().each { - if (it.directory && new File(it, 'build.gradle').exists()) { - include ":Samples:${it.name}" +if (!(settings.providers.gradleProperty("skipSamples").orNull.toBoolean())) { + File(rootDir, "Samples").listFiles().forEach { + if (it.isDirectory && (File(it, "build.gradle").exists() || File(it, "build.gradle.kts").exists())) { + include(":Samples:${it.name}") } } } + +enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS")