diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 6b21c8b..09ed8a5 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -14,6 +14,45 @@ jobs: with: enable_windows_checks: true windows_swift_versions: '["nightly-main"]' + windows_pre_build_command: | + $jdkVersion = "21" + $msiUrl = "https://aka.ms/download-jdk/microsoft-jdk-$jdkVersion-windows-x64.msi" + $installerPath = "$env:TEMP\microsoft-jdk-$jdkVersion.msi" + $jdkInstallDir = "C:\Program Files\Microsoft\jdk-$jdkVersion" + + # Download the MSI + Write-Host "Downloading Microsoft OpenJDK $jdkVersion..." + Invoke-WebRequest -Uri $msiUrl -OutFile $installerPath + + # Install silently + Write-Host "Installing Microsoft OpenJDK $jdkVersion..." + Start-Process msiexec.exe -ArgumentList "/i `"$installerPath`" /quiet /norestart INSTALLDIR=`"$jdkInstallDir`"" -Wait -NoNewWindow + + # Set JAVA_HOME (system-wide, requires admin) + Write-Host "Setting JAVA_HOME..." + [System.Environment]::SetEnvironmentVariable("JAVA_HOME", $jdkInstallDir, [System.EnvironmentVariableTarget]::Machine) + + # Add to system PATH if not already present + $currentPath = [System.Environment]::GetEnvironmentVariable("PATH", [System.EnvironmentVariableTarget]::Machine) + if ($currentPath -notlike "*$jdkInstallDir\bin*") { + [System.Environment]::SetEnvironmentVariable("PATH", "$currentPath;$jdkInstallDir\bin", [System.EnvironmentVariableTarget]::Machine) + Write-Host "Added JDK bin to system PATH." + } + + # Refresh current session + $env:JAVA_HOME = $jdkInstallDir + $env:PATH = "$env:PATH;$jdkInstallDir\bin" + + # Verify + Write-Host "`nVerifying installation..." + & "$jdkInstallDir\bin\java.exe" -version + + Write-Host "`nDone! JAVA_HOME = $env:JAVA_HOME" + + # Clean up installer + Remove-Item $installerPath -Force + + Get-ChildItem Env: enable_macos_checks: true macos_pre_build_command: brew install openjdk enable_ios_checks: false diff --git a/Sources/SwiftJavaJNICore/VirtualMachine/JavaVirtualMachine.swift b/Sources/SwiftJavaJNICore/VirtualMachine/JavaVirtualMachine.swift index e5fdd3d..859d269 100644 --- a/Sources/SwiftJavaJNICore/VirtualMachine/JavaVirtualMachine.swift +++ b/Sources/SwiftJavaJNICore/VirtualMachine/JavaVirtualMachine.swift @@ -37,13 +37,8 @@ typealias JNIEnvPointer = UnsafeMutablePointer extension FileManager { #if os(Windows) static let pathSeparator = ";" - static let libraryExtension = "dll" - #elseif canImport(Darwin) - static let pathSeparator = ":" - static let libraryExtension = "dylib" #else static let pathSeparator = ":" - static let libraryExtension = "so" #endif } @@ -479,14 +474,28 @@ private func loadLibJava() throws -> DylibType { let javaHomeURL = URL(fileURLWithPath: javaHome, isDirectory: true) - let ext = FileManager.libraryExtension - let libjvmPaths = [ - // look through some standard locations relative to JAVA_HOME + // look through some standard locations relative to JAVA_HOME + let libjvmPaths: [URL] + + #if os(Windows) + libjvmPaths = [ + URL(fileURLWithPath: "bin\\server\\jvm.dll", relativeTo: javaHomeURL), + URL(fileURLWithPath: "bin\\jvm.dll", relativeTo: javaHomeURL), + URL(fileURLWithPath: "bin\\client\\jvm.dll", relativeTo: javaHomeURL), // older JDKs + ] + #else + #if canImport(Darwin) + let ext = "dylib" // macOS, etc. + #else + let ext = "so" // Linux, Android, etc. + #endif + libjvmPaths = [ URL(fileURLWithPath: "jre/lib/server/libjvm.\(ext)", relativeTo: javaHomeURL), URL(fileURLWithPath: "lib/server/libjvm.\(ext)", relativeTo: javaHomeURL), URL(fileURLWithPath: "lib/libjvm.\(ext)", relativeTo: javaHomeURL), URL(fileURLWithPath: "libexec/openjdk.jdk/Contents/Home/lib/server/libjvm.\(ext)", relativeTo: javaHomeURL), ] + #endif guard let libjvmPath = libjvmPaths.first(where: { diff --git a/Tests/SwiftJavaJNICoreTests/JavaVirtualMachineTests.swift b/Tests/SwiftJavaJNICoreTests/JavaVirtualMachineTests.swift index d2dedd5..8246be7 100644 --- a/Tests/SwiftJavaJNICoreTests/JavaVirtualMachineTests.swift +++ b/Tests/SwiftJavaJNICoreTests/JavaVirtualMachineTests.swift @@ -16,17 +16,25 @@ import Testing @testable import SwiftJavaJNICore +#if canImport(FoundationEssentials) +import class FoundationEssentials.ProcessInfo +#else +import class Foundation.ProcessInfo +#endif @Suite struct JavaVirtualMachineTests { static var isSupportedPlatform: Bool { #if os(Android) - // Android tests are not currently run within an .apk and so do not have any ambient JVM - return false + // Android tests are not currently run within an .apk and so do not have any ambient JVM. + // This can be overridden for a test harness that supports running within an .apk, like: + // skip android test --apk --env SWIFT_JAVA_JNI_TEST_JVM=1 + let testSentinel = "0" #else - // disable test when we cannot find a system Java - return systemJavaHome() != nil + // tests for every other platform should be run in an environment with Java available unless explicitly disabled + let testSentinel = "1" #endif + return (ProcessInfo.processInfo.environment["SWIFT_JAVA_JNI_TEST_JVM"] ?? testSentinel) != "0" } @Test(.enabled(if: isSupportedPlatform))