From c17b62d93d580b1ebe9d1c24377cfe88d3feb854 Mon Sep 17 00:00:00 2001 From: Pavel Marek Date: Tue, 17 Dec 2024 18:23:55 +0100 Subject: [PATCH] Add NativeLibraryFinder --- .../interpreter/runtime/HostClassLoader.java | 25 +++++++++ .../runtime/NativeLibraryFinder.java | 53 +++++++++++++++++++ 2 files changed, 78 insertions(+) create mode 100644 engine/runtime/src/main/java/org/enso/interpreter/runtime/NativeLibraryFinder.java diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/HostClassLoader.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/HostClassLoader.java index 4c2ffb2a2b6e..bfb1d7b87017 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/HostClassLoader.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/HostClassLoader.java @@ -81,6 +81,31 @@ protected Class loadClass(String name, boolean resolve) throws ClassNotFoundE } } + /** + * Find the library with the specified name inside the {@code polyglot/lib} directory of caller's + * project. The search inside the {@code polyglot/lib} directory hierarchy is specified by NetBeans + * JNI specification. + * + *

Note: The current implementation iterates all the {@code polyglot/lib} directories of all + * the packages. + * + * @param libname The library name. Without platform-specific suffix or prefix. + * @return Absolute path to the library if found, or null. + */ + @Override + protected String findLibrary(String libname) { + var pkgRepo = EnsoContext.get(null).getPackageRepository(); + for (var pkg : pkgRepo.getLoadedPackagesJava()) { + var libPath = NativeLibraryFinder.findNativeLibrary(libname, pkg); + if (libPath != null) { + return libPath; + } + } + logger.trace("Native library {} not found in any package", libname); + return null; + } + @Override public void close() { loadedClasses.clear(); diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/NativeLibraryFinder.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/NativeLibraryFinder.java new file mode 100644 index 000000000000..3cf20d86e9b5 --- /dev/null +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/NativeLibraryFinder.java @@ -0,0 +1,53 @@ +package org.enso.interpreter.runtime; + +import com.oracle.truffle.api.TruffleFile; +import java.util.Locale; +import org.enso.pkg.Package; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Helper class to find native libraries in packages. The search algorithm complies to the NetBeans + * JNI specification. + */ +final class NativeLibraryFinder { + + private static final Logger logger = LoggerFactory.getLogger(NativeLibraryFinder.class); + + private NativeLibraryFinder() {} + + /** + * Tries to find native library in the given package. + * + * @param libName the name of the library to find, without platform specific prefix or suffix. + * @param pkg the package to search in. + * @return null if not found, absolute path otherwise. + */ + static String findNativeLibrary(String libName, Package pkg) { + var arch = System.getProperty("os.arch"); + var osName = System.getProperty("os.name").toLowerCase(Locale.ENGLISH); + var libNameWithSuffix = System.mapLibraryName(libName); + var libDir = pkg.polyglotDir().resolve("lib"); + if (!libDir.exists()) { + logger.trace("Native library directory {} does not exist", libDir); + return null; + } + var nativeLib = libDir.resolve(libNameWithSuffix); + if (nativeLib.exists()) { + logger.trace("Found native library {}", nativeLib); + return nativeLib.getAbsoluteFile().getPath(); + } + nativeLib = libDir.resolve(arch).resolve(libNameWithSuffix); + if (nativeLib.exists()) { + logger.trace("Found native library {}", nativeLib); + return nativeLib.getAbsoluteFile().getPath(); + } + nativeLib = libDir.resolve(arch).resolve(osName).resolve(libNameWithSuffix); + if (nativeLib.exists()) { + logger.trace("Found native library {}", nativeLib); + return nativeLib.getAbsoluteFile().getPath(); + } + return null; + } +}