Unverified Commit 6d773d5e authored by Mike Hearn's avatar Mike Hearn Committed by GitHub

Look for the skiko library in the libs directory of the JVM. (#328)

In some packagings, Skiko (+its data file) will be placed alongside
the other shared libraries used by the JVM. This has some advantages
with respect to code signing, and also avoids a .skiko directory
littering the user's home directory. That's especially important on
Windows where dotfiles/dotdirs don't work.

The system property still overrides this.
Co-authored-by: 's avatarMike Hearn <mike@hydraulic.software>
parent 549de5ab
package org.jetbrains.skiko package org.jetbrains.skiko
import org.jetbrains.skia.Bitmap import org.jetbrains.skia.Bitmap
import java.io.BufferedReader
import java.io.File import java.io.File
import java.io.InputStreamReader
import java.nio.file.Files import java.nio.file.Files
import java.nio.file.StandardCopyOption import java.nio.file.StandardCopyOption
import java.util.concurrent.atomic.AtomicBoolean import java.util.concurrent.atomic.AtomicBoolean
...@@ -52,50 +50,70 @@ object Library { ...@@ -52,50 +50,70 @@ object Library {
// This function does the following: on request to load given resource, // This function does the following: on request to load given resource,
// it checks if resource with given name is found in content-derived directory // it checks if resource with given name is found in content-derived directory
// in Skiko's home, and if not - unpacks it. Also, it could load additional // in Skiko's home, and if not - unpacks it. Also, it could load additional
// localization resource on platforms wher it is needed. // localization resource on platforms where it is needed.
@Synchronized @Synchronized
fun load() { fun load() {
if (loaded.compareAndExchange(false, true)) return if (loaded.compareAndExchange(false, true)) return
// Find/unpack a usable copy of the native library.
findAndLoad()
// TODO move properties to SkikoProperties
Setup.init()
try {
// Init code executed after library was loaded.
org.jetbrains.skia.impl.Library._nAfterLoad()
} catch (t: Throwable) {
t.printStackTrace()
}
}
private fun findAndLoad() {
val name = "skiko-$hostId" val name = "skiko-$hostId"
val platformName = System.mapLibraryName(name) val platformName = System.mapLibraryName(name)
val icu = if (hostOs.isWindows) "icudtl.dat" else null val icu = if (hostOs.isWindows) "icudtl.dat" else null
// First try: system property is set.
if (skikoLibraryPath != null) { if (skikoLibraryPath != null) {
val library = File(File(skikoLibraryPath), platformName) val library = File(File(skikoLibraryPath), platformName)
loadLibraryOrCopy(library) loadLibraryOrCopy(library)
if (icu != null && copyDir != null) { if (icu != null && copyDir != null)
unpackIfNeeded(copyDir!!, icu, true) unpackIfNeeded(copyDir!!, icu, true)
} return
} else {
val hashResourceStream = Library::class.java.getResourceAsStream(
"/$platformName.sha256"
) ?: throw LibraryLoadException(
"Cannot find $platformName.sha256, proper native dependency missing."
)
val hash = hashResourceStream.use {
BufferedReader(InputStreamReader(it)).lines().toArray()[0] as String
}
val cacheDir = File(File(cacheRoot), hash)
cacheDir.mkdirs()
val library = unpackIfNeeded(cacheDir, platformName, false)
loadLibraryOrCopy(library)
if (icu != null) {
if (copyDir != null) {
unpackIfNeeded(copyDir!!, icu, true)
} else {
unpackIfNeeded(cacheDir, icu, false)
}
}
} }
// TODO move properties to SkikoProperties // Second try: load it from the bin/ or lib/ directory relative to the JVM home.
Setup.init() // The user might have placed the native files alongside the other JVM libraries
// for signing purposes, so we'll find it here if so.
val jvmFiles = File(System.getProperty("java.home"), if (hostOs.isWindows) "bin" else "lib")
val pathInJvm = jvmFiles.resolve(platformName)
if (pathInJvm.exists() && icu?.let { (jvmFiles.resolve(it)).exists() } != false) {
loadLibraryOrCopy(pathInJvm)
return
}
try { // Third try: look up in or extract to a local cache directory.
// Init code executed after library was loaded. // Key the cache by the hash of the library.
org.jetbrains.skia.impl.Library._nAfterLoad() val hashResourceStream = Library::class.java.getResourceAsStream(
} catch (t: Throwable) { "/$platformName.sha256"
t.printStackTrace() ) ?: throw LibraryLoadException(
"Cannot find $platformName.sha256, proper native dependency missing."
)
val hash = hashResourceStream.use { it.bufferedReader().readLine() }
val cacheDir = File(File(cacheRoot), hash)
cacheDir.mkdirs()
val library = unpackIfNeeded(cacheDir, platformName, false)
loadLibraryOrCopy(library)
if (icu != null) {
if (copyDir != null) {
// We made a duplicate to resolve classloader conflicts.
unpackIfNeeded(copyDir!!, icu, true)
} else {
// Normal path where Skiko is loaded only once.
unpackIfNeeded(cacheDir, icu, false)
}
} }
} }
} }
...@@ -106,4 +124,4 @@ internal class LibraryTestImpl() { ...@@ -106,4 +124,4 @@ internal class LibraryTestImpl() {
val bitmap = Bitmap() val bitmap = Bitmap()
return bitmap._ptr return bitmap._ptr
} }
} }
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment