diff --git a/Benchmarks/Package.swift b/Benchmarks/Package.swift index 127e4d483..c96707e75 100644 --- a/Benchmarks/Package.swift +++ b/Benchmarks/Package.swift @@ -1,9 +1,7 @@ // swift-tools-version: 6.0 import PackageDescription - -import class Foundation.FileManager -import class Foundation.ProcessInfo +import Foundation // Note: the JAVA_HOME environment variable must be set to point to where // Java is installed, e.g., @@ -24,8 +22,56 @@ func findJavaHome() -> String { return home } + if let home = getJavaHomeFromSDKMAN() { + return home + } + + if let home = getJavaHomeFromPath() { + return home + } + fatalError("Please set the JAVA_HOME environment variable to point to where Java is installed.") } + +func getJavaHomeFromSDKMAN() -> String? { + let home = FileManager.default.homeDirectoryForCurrentUser + .appendingPathComponent(".sdkman/candidates/java/current") + + let javaBin = home.appendingPathComponent("bin/java").path + if FileManager.default.isExecutableFile(atPath: javaBin) { + return home.path + } + return nil +} + +func getJavaHomeFromPath() -> String? { + let task = Process() + task.executableURL = URL(fileURLWithPath: "/usr/bin/which") + task.arguments = ["java"] + + let pipe = Pipe() + task.standardOutput = pipe + + do { + try task.run() + task.waitUntilExit() + guard task.terminationStatus == 0 else { return nil } + + let data = pipe.fileHandleForReading.readDataToEndOfFile() + guard let javaPath = String(data: data, encoding: .utf8)? + .trimmingCharacters(in: .whitespacesAndNewlines), + !javaPath.isEmpty + else { return nil } + + let resolved = URL(fileURLWithPath: javaPath).resolvingSymlinksInPath() + return resolved + .deletingLastPathComponent() + .deletingLastPathComponent() + .path + } catch { + return nil + } +} let javaHome = findJavaHome() let javaIncludePath = "\(javaHome)/include" diff --git a/Package.swift b/Package.swift index b6a18f90e..2c57b7e9d 100644 --- a/Package.swift +++ b/Package.swift @@ -34,6 +34,14 @@ func findJavaHome() -> String { return home } + if let home = getJavaHomeFromSDKMAN() { + return home + } + + if let home = getJavaHomeFromPath() { + return home + } + if ProcessInfo.processInfo.environment["SPI_PROCESSING"] == "1" && ProcessInfo.processInfo.environment["SPI_BUILD"] == nil { // Just ignore that we're missing a JAVA_HOME when building in Swift Package Index during general processing where no Java is needed. However, do _not_ suppress the error during SPI's compatibility build stage where Java is required. @@ -80,6 +88,46 @@ func getJavaHomeFromLibexecJavaHome() -> String? { } } +func getJavaHomeFromSDKMAN() -> String? { + let home = FileManager.default.homeDirectoryForCurrentUser + .appendingPathComponent(".sdkman/candidates/java/current") + + let javaBin = home.appendingPathComponent("bin/java").path + if FileManager.default.isExecutableFile(atPath: javaBin) { + return home.path + } + return nil +} + +func getJavaHomeFromPath() -> String? { + let task = Process() + task.executableURL = URL(fileURLWithPath: "/usr/bin/which") + task.arguments = ["java"] + + let pipe = Pipe() + task.standardOutput = pipe + + do { + try task.run() + task.waitUntilExit() + guard task.terminationStatus == 0 else { return nil } + + let data = pipe.fileHandleForReading.readDataToEndOfFile() + guard let javaPath = String(data: data, encoding: .utf8)? + .trimmingCharacters(in: .whitespacesAndNewlines), + !javaPath.isEmpty + else { return nil } + + let resolved = URL(fileURLWithPath: javaPath).resolvingSymlinksInPath() + return resolved + .deletingLastPathComponent() + .deletingLastPathComponent() + .path + } catch { + return nil + } +} + let javaHome = findJavaHome() let javaIncludePath = "\(javaHome)/include" diff --git a/Plugins/PluginsShared/PluginUtils.swift b/Plugins/PluginsShared/PluginUtils.swift index 8278c6455..8f451655d 100644 --- a/Plugins/PluginsShared/PluginUtils.swift +++ b/Plugins/PluginsShared/PluginUtils.swift @@ -34,6 +34,14 @@ func findJavaHome() -> String { return home } + if let home = getJavaHomeFromSDKMAN() { + return home + } + + if let home = getJavaHomeFromPath() { + return home + } + fatalError("Please set the JAVA_HOME environment variable to point to where Java is installed.") } @@ -77,3 +85,43 @@ extension PluginContext { .appending(path: "\(swiftModule)", directoryHint: .notDirectory) } } + +func getJavaHomeFromSDKMAN() -> String? { + let home = FileManager.default.homeDirectoryForCurrentUser + .appendingPathComponent(".sdkman/candidates/java/current") + + let javaBin = home.appendingPathComponent("bin/java").path + if FileManager.default.isExecutableFile(atPath: javaBin) { + return home.path + } + return nil +} + +func getJavaHomeFromPath() -> String? { + let task = Process() + task.executableURL = URL(fileURLWithPath: "/usr/bin/which") + task.arguments = ["java"] + + let pipe = Pipe() + task.standardOutput = pipe + + do { + try task.run() + task.waitUntilExit() + guard task.terminationStatus == 0 else { return nil } + + let data = pipe.fileHandleForReading.readDataToEndOfFile() + guard let javaPath = String(data: data, encoding: .utf8)? + .trimmingCharacters(in: .whitespacesAndNewlines), + !javaPath.isEmpty + else { return nil } + + let resolved = URL(fileURLWithPath: javaPath).resolvingSymlinksInPath() + return resolved + .deletingLastPathComponent() + .deletingLastPathComponent() + .path + } catch { + return nil + } +} diff --git a/Samples/JavaDependencySampleApp/Package.swift b/Samples/JavaDependencySampleApp/Package.swift index 573a60cc2..ed88ecb1c 100644 --- a/Samples/JavaDependencySampleApp/Package.swift +++ b/Samples/JavaDependencySampleApp/Package.swift @@ -3,9 +3,7 @@ import CompilerPluginSupport import PackageDescription - -import class Foundation.FileManager -import class Foundation.ProcessInfo +import Foundation // Note: the JAVA_HOME environment variable must be set to point to where // Java is installed, e.g., @@ -26,8 +24,56 @@ func findJavaHome() -> String { return home } + if let home = getJavaHomeFromSDKMAN() { + return home + } + + if let home = getJavaHomeFromPath() { + return home + } + fatalError("Please set the JAVA_HOME environment variable to point to where Java is installed.") } + +func getJavaHomeFromSDKMAN() -> String? { + let home = FileManager.default.homeDirectoryForCurrentUser + .appendingPathComponent(".sdkman/candidates/java/current") + + let javaBin = home.appendingPathComponent("bin/java").path + if FileManager.default.isExecutableFile(atPath: javaBin) { + return home.path + } + return nil +} + +func getJavaHomeFromPath() -> String? { + let task = Process() + task.executableURL = URL(fileURLWithPath: "/usr/bin/which") + task.arguments = ["java"] + + let pipe = Pipe() + task.standardOutput = pipe + + do { + try task.run() + task.waitUntilExit() + guard task.terminationStatus == 0 else { return nil } + + let data = pipe.fileHandleForReading.readDataToEndOfFile() + guard let javaPath = String(data: data, encoding: .utf8)? + .trimmingCharacters(in: .whitespacesAndNewlines), + !javaPath.isEmpty + else { return nil } + + let resolved = URL(fileURLWithPath: javaPath).resolvingSymlinksInPath() + return resolved + .deletingLastPathComponent() + .deletingLastPathComponent() + .path + } catch { + return nil + } +} let javaHome = findJavaHome() let javaIncludePath = "\(javaHome)/include" diff --git a/Samples/JavaKitSampleApp/Package.swift b/Samples/JavaKitSampleApp/Package.swift index 082d61ac9..b4313c18f 100644 --- a/Samples/JavaKitSampleApp/Package.swift +++ b/Samples/JavaKitSampleApp/Package.swift @@ -3,9 +3,7 @@ import CompilerPluginSupport import PackageDescription - -import class Foundation.FileManager -import class Foundation.ProcessInfo +import Foundation // Note: the JAVA_HOME environment variable must be set to point to where // Java is installed, e.g., @@ -26,8 +24,56 @@ func findJavaHome() -> String { return home } + if let home = getJavaHomeFromSDKMAN() { + return home + } + + if let home = getJavaHomeFromPath() { + return home + } + fatalError("Please set the JAVA_HOME environment variable to point to where Java is installed.") } + +func getJavaHomeFromSDKMAN() -> String? { + let home = FileManager.default.homeDirectoryForCurrentUser + .appendingPathComponent(".sdkman/candidates/java/current") + + let javaBin = home.appendingPathComponent("bin/java").path + if FileManager.default.isExecutableFile(atPath: javaBin) { + return home.path + } + return nil +} + +func getJavaHomeFromPath() -> String? { + let task = Process() + task.executableURL = URL(fileURLWithPath: "/usr/bin/which") + task.arguments = ["java"] + + let pipe = Pipe() + task.standardOutput = pipe + + do { + try task.run() + task.waitUntilExit() + guard task.terminationStatus == 0 else { return nil } + + let data = pipe.fileHandleForReading.readDataToEndOfFile() + guard let javaPath = String(data: data, encoding: .utf8)? + .trimmingCharacters(in: .whitespacesAndNewlines), + !javaPath.isEmpty + else { return nil } + + let resolved = URL(fileURLWithPath: javaPath).resolvingSymlinksInPath() + return resolved + .deletingLastPathComponent() + .deletingLastPathComponent() + .path + } catch { + return nil + } +} let javaHome = findJavaHome() let javaIncludePath = "\(javaHome)/include" diff --git a/Samples/JavaSieve/Package.swift b/Samples/JavaSieve/Package.swift index c34d83318..6efcb2ed8 100644 --- a/Samples/JavaSieve/Package.swift +++ b/Samples/JavaSieve/Package.swift @@ -2,9 +2,7 @@ // The swift-tools-version declares the minimum version of Swift required to build this package. import PackageDescription - -import class Foundation.FileManager -import class Foundation.ProcessInfo +import Foundation // Note: the JAVA_HOME environment variable must be set to point to where // Java is installed, e.g., @@ -25,8 +23,56 @@ func findJavaHome() -> String { return home } + if let home = getJavaHomeFromSDKMAN() { + return home + } + + if let home = getJavaHomeFromPath() { + return home + } + fatalError("Please set the JAVA_HOME environment variable to point to where Java is installed.") } + +func getJavaHomeFromSDKMAN() -> String? { + let home = FileManager.default.homeDirectoryForCurrentUser + .appendingPathComponent(".sdkman/candidates/java/current") + + let javaBin = home.appendingPathComponent("bin/java").path + if FileManager.default.isExecutableFile(atPath: javaBin) { + return home.path + } + return nil +} + +func getJavaHomeFromPath() -> String? { + let task = Process() + task.executableURL = URL(fileURLWithPath: "/usr/bin/which") + task.arguments = ["java"] + + let pipe = Pipe() + task.standardOutput = pipe + + do { + try task.run() + task.waitUntilExit() + guard task.terminationStatus == 0 else { return nil } + + let data = pipe.fileHandleForReading.readDataToEndOfFile() + guard let javaPath = String(data: data, encoding: .utf8)? + .trimmingCharacters(in: .whitespacesAndNewlines), + !javaPath.isEmpty + else { return nil } + + let resolved = URL(fileURLWithPath: javaPath).resolvingSymlinksInPath() + return resolved + .deletingLastPathComponent() + .deletingLastPathComponent() + .path + } catch { + return nil + } +} let javaHome = findJavaHome() let javaIncludePath = "\(javaHome)/include" diff --git a/Samples/SwiftAndJavaJarSampleLib/Package.swift b/Samples/SwiftAndJavaJarSampleLib/Package.swift index f501b984e..bcfde3e67 100644 --- a/Samples/SwiftAndJavaJarSampleLib/Package.swift +++ b/Samples/SwiftAndJavaJarSampleLib/Package.swift @@ -3,9 +3,7 @@ import CompilerPluginSupport import PackageDescription - -import class Foundation.FileManager -import class Foundation.ProcessInfo +import Foundation // Note: the JAVA_HOME environment variable must be set to point to where // Java is installed, e.g., @@ -26,8 +24,56 @@ func findJavaHome() -> String { return home } + if let home = getJavaHomeFromSDKMAN() { + return home + } + + if let home = getJavaHomeFromPath() { + return home + } + fatalError("Please set the JAVA_HOME environment variable to point to where Java is installed.") } + +func getJavaHomeFromSDKMAN() -> String? { + let home = FileManager.default.homeDirectoryForCurrentUser + .appendingPathComponent(".sdkman/candidates/java/current") + + let javaBin = home.appendingPathComponent("bin/java").path + if FileManager.default.isExecutableFile(atPath: javaBin) { + return home.path + } + return nil +} + +func getJavaHomeFromPath() -> String? { + let task = Process() + task.executableURL = URL(fileURLWithPath: "/usr/bin/which") + task.arguments = ["java"] + + let pipe = Pipe() + task.standardOutput = pipe + + do { + try task.run() + task.waitUntilExit() + guard task.terminationStatus == 0 else { return nil } + + let data = pipe.fileHandleForReading.readDataToEndOfFile() + guard let javaPath = String(data: data, encoding: .utf8)? + .trimmingCharacters(in: .whitespacesAndNewlines), + !javaPath.isEmpty + else { return nil } + + let resolved = URL(fileURLWithPath: javaPath).resolvingSymlinksInPath() + return resolved + .deletingLastPathComponent() + .deletingLastPathComponent() + .path + } catch { + return nil + } +} let javaHome = findJavaHome() let javaIncludePath = "\(javaHome)/include" diff --git a/Samples/SwiftJavaExtractFFMSampleApp/Package.swift b/Samples/SwiftJavaExtractFFMSampleApp/Package.swift index 98d1bd33f..2b7abbd65 100644 --- a/Samples/SwiftJavaExtractFFMSampleApp/Package.swift +++ b/Samples/SwiftJavaExtractFFMSampleApp/Package.swift @@ -3,9 +3,7 @@ import CompilerPluginSupport import PackageDescription - -import class Foundation.FileManager -import class Foundation.ProcessInfo +import Foundation // Note: the JAVA_HOME environment variable must be set to point to where // Java is installed, e.g., @@ -26,8 +24,56 @@ func findJavaHome() -> String { return home } + if let home = getJavaHomeFromSDKMAN() { + return home + } + + if let home = getJavaHomeFromPath() { + return home + } + fatalError("Please set the JAVA_HOME environment variable to point to where Java is installed.") } + +func getJavaHomeFromSDKMAN() -> String? { + let home = FileManager.default.homeDirectoryForCurrentUser + .appendingPathComponent(".sdkman/candidates/java/current") + + let javaBin = home.appendingPathComponent("bin/java").path + if FileManager.default.isExecutableFile(atPath: javaBin) { + return home.path + } + return nil +} + +func getJavaHomeFromPath() -> String? { + let task = Process() + task.executableURL = URL(fileURLWithPath: "/usr/bin/which") + task.arguments = ["java"] + + let pipe = Pipe() + task.standardOutput = pipe + + do { + try task.run() + task.waitUntilExit() + guard task.terminationStatus == 0 else { return nil } + + let data = pipe.fileHandleForReading.readDataToEndOfFile() + guard let javaPath = String(data: data, encoding: .utf8)? + .trimmingCharacters(in: .whitespacesAndNewlines), + !javaPath.isEmpty + else { return nil } + + let resolved = URL(fileURLWithPath: javaPath).resolvingSymlinksInPath() + return resolved + .deletingLastPathComponent() + .deletingLastPathComponent() + .path + } catch { + return nil + } +} let javaHome = findJavaHome() let javaIncludePath = "\(javaHome)/include" diff --git a/Samples/SwiftJavaExtractJNISampleApp/Package.swift b/Samples/SwiftJavaExtractJNISampleApp/Package.swift index 6343e0dbd..f8174aa06 100644 --- a/Samples/SwiftJavaExtractJNISampleApp/Package.swift +++ b/Samples/SwiftJavaExtractJNISampleApp/Package.swift @@ -3,9 +3,7 @@ import CompilerPluginSupport import PackageDescription - -import class Foundation.FileManager -import class Foundation.ProcessInfo +import Foundation // Note: the JAVA_HOME environment variable must be set to point to where // Java is installed, e.g., @@ -26,8 +24,56 @@ func findJavaHome() -> String { return home } + if let home = getJavaHomeFromSDKMAN() { + return home + } + + if let home = getJavaHomeFromPath() { + return home + } + fatalError("Please set the JAVA_HOME environment variable to point to where Java is installed.") } + +func getJavaHomeFromSDKMAN() -> String? { + let home = FileManager.default.homeDirectoryForCurrentUser + .appendingPathComponent(".sdkman/candidates/java/current") + + let javaBin = home.appendingPathComponent("bin/java").path + if FileManager.default.isExecutableFile(atPath: javaBin) { + return home.path + } + return nil +} + +func getJavaHomeFromPath() -> String? { + let task = Process() + task.executableURL = URL(fileURLWithPath: "/usr/bin/which") + task.arguments = ["java"] + + let pipe = Pipe() + task.standardOutput = pipe + + do { + try task.run() + task.waitUntilExit() + guard task.terminationStatus == 0 else { return nil } + + let data = pipe.fileHandleForReading.readDataToEndOfFile() + guard let javaPath = String(data: data, encoding: .utf8)? + .trimmingCharacters(in: .whitespacesAndNewlines), + !javaPath.isEmpty + else { return nil } + + let resolved = URL(fileURLWithPath: javaPath).resolvingSymlinksInPath() + return resolved + .deletingLastPathComponent() + .deletingLastPathComponent() + .path + } catch { + return nil + } +} let javaHome = findJavaHome() let javaIncludePath = "\(javaHome)/include" diff --git a/Sources/SwiftJavaToolLib/JavaHomeSupport.swift b/Sources/SwiftJavaToolLib/JavaHomeSupport.swift index cd18f7a82..21a463b41 100644 --- a/Sources/SwiftJavaToolLib/JavaHomeSupport.swift +++ b/Sources/SwiftJavaToolLib/JavaHomeSupport.swift @@ -42,6 +42,15 @@ public func findJavaHome() -> String { return home } + if let home = getJavaHomeFromSDKMAN() { + return home + } + + if let home = getJavaHomeFromPath() { + return home + } + + if ProcessInfo.processInfo.environment["SPI_PROCESSING"] == "1" && ProcessInfo.processInfo.environment["SPI_BUILD"] == nil { @@ -90,3 +99,43 @@ public func getJavaHomeFromLibexecJavaHome() -> String? { return nil } } + +func getJavaHomeFromSDKMAN() -> String? { + let home = FileManager.default.homeDirectoryForCurrentUser + .appendingPathComponent(".sdkman/candidates/java/current") + + let javaBin = home.appendingPathComponent("bin/java").path + if FileManager.default.isExecutableFile(atPath: javaBin) { + return home.path + } + return nil +} + +func getJavaHomeFromPath() -> String? { + let task = Process() + task.executableURL = URL(fileURLWithPath: "/usr/bin/which") + task.arguments = ["java"] + + let pipe = Pipe() + task.standardOutput = pipe + + do { + try task.run() + task.waitUntilExit() + guard task.terminationStatus == 0 else { return nil } + + let data = pipe.fileHandleForReading.readDataToEndOfFile() + guard let javaPath = String(data: data, encoding: .utf8)? + .trimmingCharacters(in: .whitespacesAndNewlines), + !javaPath.isEmpty + else { return nil } + + let resolved = URL(fileURLWithPath: javaPath).resolvingSymlinksInPath() + return resolved + .deletingLastPathComponent() + .deletingLastPathComponent() + .path + } catch { + return nil + } +}