Skip to content

use -print-target-info to get swift library paths reliably #178

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Nov 15, 2024
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
1 change: 1 addition & 0 deletions .licenseignore
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,4 @@ gradlew.bat
**/gradlew
**/gradlew.bat
**/ci-validate.sh
**/DO_NOT_EDIT.txt
5 changes: 5 additions & 0 deletions BuildLogic/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@

repositories {
gradlePluginPortal()
mavenCentral()
}

dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json-jvm:1.7.3")
}

plugins {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@

import java.util.*
import java.io.*
import kotlin.system.exitProcess
import kotlinx.serialization.json.*

plugins {
java
Expand Down Expand Up @@ -44,41 +46,60 @@ tasks.withType(JavaCompile::class).forEach {
}


// FIXME: cannot share definition with 'buildSrc' so we duplicated the impl here
fun javaLibraryPaths(dir: File): List<String> {
val osName = System.getProperty("os.name")
fun getSwiftRuntimeLibraryPaths(): List<String> {
val process = ProcessBuilder("swiftc", "-print-target-info")
.redirectError(ProcessBuilder.Redirect.INHERIT)
.start()

val output = process.inputStream.bufferedReader().use { it.readText() }
val exitCode = process.waitFor()
if (exitCode != 0) {
System.err.println("Error executing swiftc -print-target-info")
exitProcess(exitCode)
}

val json = Json.parseToJsonElement(output)
val runtimeLibraryPaths = json.jsonObject["paths"]?.jsonObject?.get("runtimeLibraryPaths")?.jsonArray
return runtimeLibraryPaths?.map { it.jsonPrimitive.content } ?: emptyList()
}

/**
* 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/
fun javaLibraryPaths(rootDir: File): List<String> {
val osName = System.getProperty("os.name").lowercase(Locale.getDefault())
val osArch = System.getProperty("os.arch")
val isLinux = osName.lowercase(Locale.getDefault()).contains("linux")
val isLinux = osName.contains("linux")
val base = rootDir.path.let { "$it/" }

return listOf(
if (isLinux) {
if (osArch.equals("x86_64") || osArch.equals("amd64")) {
"$dir/.build/x86_64-unknown-linux-gnu/debug/"
} else {
"$dir/.build/$osArch-unknown-linux-gnu/debug/"
}
} else {
if (osArch.equals("aarch64")) {
"$dir/.build/arm64-apple-macosx/debug/"
} else {
"$dir/.build/$osArch-apple-macosx/debug/"
}
},
val projectBuildOutputPath =
if (isLinux) {
"/usr/lib/swift/linux"
if (osArch == "amd64" || osArch == "x86_64")
"$base.build/x86_64-unknown-linux-gnu"
else
"$base.build/${osArch}-unknown-linux-gnu"
} else {
// assume macOS
"/usr/lib/swift/"
},
if (isLinux) {
System.getProperty("user.home") + "/.local/share/swiftly/toolchains/6.0.2/usr/lib/swift/linux"
} else {
// assume macOS
"/usr/lib/swift/"
if (osArch == "aarch64")
"$base.build/arm64-apple-macosx"
else
"$base.build/${osArch}-apple-macosx"
}
val parentParentBuildOutputPath =
"../../$projectBuildOutputPath"


val swiftBuildOutputPaths = listOf(
projectBuildOutputPath,
parentParentBuildOutputPath
)
}

val debugBuildOutputPaths = swiftBuildOutputPaths.map { "$it/debug" }
val releaseBuildOutputPaths = swiftBuildOutputPaths.map { "$it/release" }
val swiftRuntimePaths = getSwiftRuntimeLibraryPaths()

return debugBuildOutputPaths + releaseBuildOutputPaths + swiftRuntimePaths
}

// Configure paths for native (Swift) libraries
tasks.test {
Expand Down
4 changes: 4 additions & 0 deletions buildSrc/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ repositories {
mavenCentral()
}

dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json-jvm:1.7.3")
}

def cleanSwift = tasks.register("cleanSwift", Exec) {
workingDir = layout.projectDirectory
commandLine "swift"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,21 @@

package org.swift.swiftkit.gradle

import groovy.json.JsonSlurper

final class BuildUtils {

static List<String> 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")
Expand All @@ -40,19 +53,8 @@ final class BuildUtils {
"${base}../../.build/${osArch}-apple-macosx/debug/"),
]
def releasePaths = debugPaths.collect { it.replaceAll("debug", "release") }
def systemPaths =
// system paths
isLinux ?
[
"/usr/lib/swift/linux",
// TODO: should we be Swiftly aware and then use the currently used path?
System.getProperty("user.home") + "/.local/share/swiftly/toolchains/6.0.2/usr/lib/swift/linux"
] :
[
// assume macOS
"/usr/lib/swift/"
]

return releasePaths + debugPaths + systemPaths
def swiftRuntimePaths = getSwiftRuntimeLibraryPaths()

return releasePaths + debugPaths + swiftRuntimePaths
}
}