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
import org.jetbrains.skia.Bitmap
import java.io.BufferedReader
import java.io.File
import java.io.InputStreamReader
import java.nio.file.Files
import java.nio.file.StandardCopyOption
import java.util.concurrent.atomic.AtomicBoolean
......@@ -52,52 +50,72 @@ object Library {
// This function does the following: on request to load given resource,
// 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
// localization resource on platforms wher it is needed.
// localization resource on platforms where it is needed.
@Synchronized
fun load() {
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 platformName = System.mapLibraryName(name)
val icu = if (hostOs.isWindows) "icudtl.dat" else null
// First try: system property is set.
if (skikoLibraryPath != null) {
val library = File(File(skikoLibraryPath), platformName)
loadLibraryOrCopy(library)
if (icu != null && copyDir != null) {
if (icu != null && copyDir != null)
unpackIfNeeded(copyDir!!, icu, true)
return
}
} else {
// Second try: load it from the bin/ or lib/ directory relative to the JVM home.
// 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
}
// Third try: look up in or extract to a local cache directory.
// Key the cache by the hash of the library.
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 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)
}
}
}
// 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()
}
}
}
// We have to keep this tiny class in Skiko for testing purposes.
......
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