Skip to content
Merged
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
13 changes: 7 additions & 6 deletions BuildLogic/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
1 change: 1 addition & 0 deletions BuildLogic/gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ fun getSwiftRuntimeLibraryPaths(): List<String> {
/**
* 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<String> {
val osName = System.getProperty("os.name").lowercase(Locale.getDefault())
val osArch = System.getProperty("os.arch")
Expand Down
47 changes: 47 additions & 0 deletions BuildLogic/src/main/kotlin/swiftPackageDescribe.kt
Original file line number Diff line number Diff line change
@@ -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<String> {
// 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<Exec>("cleanSwift") {
this.workingDir = workingDir
commandLine("swift")
args("package", "clean")
}
tasks.named("clean").configure {
dependsOn(cleanSwift)
}
}

36 changes: 36 additions & 0 deletions BuildLogic/src/main/kotlin/utilities/SwiftPMPackage.kt
Original file line number Diff line number Diff line change
@@ -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<SwiftPMTarget>,
)

internal fun Project.swiftPMPackage(): SwiftPMPackage {
val stdout = ByteArrayOutputStream()
serviceOf<ExecOperations>().exec {
workingDir(projectDir)
commandLine("swift", "package", "describe", "--type", "json")
standardOutput = stdout
}
return json.decodeFromString<SwiftPMPackage>(stdout.toString())
}
27 changes: 27 additions & 0 deletions BuildLogic/src/main/kotlin/utilities/SwiftPMTarget.kt
Original file line number Diff line number Diff line change
@@ -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<String> = emptyList(),
@SerialName("product_memberships")
val productMemberships: List<String> = emptyList(),
)
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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,
)
22 changes: 22 additions & 0 deletions BuildLogic/src/main/kotlin/utilities/SwiftcTargetInfoPaths.kt
Original file line number Diff line number Diff line change
@@ -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<String>,
)
56 changes: 56 additions & 0 deletions BuildLogic/src/main/kotlin/utilities/javaLibraryPaths.kt
Original file line number Diff line number Diff line change
@@ -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<String> {
val stdout = ByteArrayOutputStream()
serviceOf<ExecOperations>().exec {
workingDir(projectDir)
commandLine("swiftc", "-print-target-info")
standardOutput = stdout
}
return json.decodeFromString<SwiftcTargetInfo>(stdout.toString()).paths.runtimeLibraryPaths
}

fun Project.javaLibraryPaths(rootDir: File?): List<String> {
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<String> = listOf("release", "debug").flatMap { configuration ->
listOf(
"${base}.build/${triple}/$configuration/",
"${base}../../.build/${triple}/$configuration/",
)
}
val swiftRuntimePaths = swiftRuntimeLibraryPaths()

return paths + swiftRuntimePaths
}
19 changes: 19 additions & 0 deletions BuildLogic/src/main/kotlin/utilities/json.kt
Original file line number Diff line number Diff line change
@@ -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 }
76 changes: 76 additions & 0 deletions BuildLogic/src/main/kotlin/utilities/registerJextractTask.kt
Original file line number Diff line number Diff line change
@@ -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<String> = swiftPMPackage().targets.filter {
it.productDependencies.contains("JExtractSwiftPlugin")
}.map {
it.name
}

private fun Project.registerSwiftCheckValidTask(): TaskProvider<*> = tasks.register<Exec>("swift-check-valid") {
commandLine("swift")
args("-version")
}

fun Project.registerJextractTask(
arguments: () -> List<String> = {
listOf("build", "--disable-experimental-prebuilts")
}
): TaskProvider<*> {
val swiftCheckValid = registerSwiftCheckValidTask()
return tasks.register<Exec>("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")
// )
}
}
Loading
Loading