From f6931a687874190bb6f5cbc927da2bdc97a18b38 Mon Sep 17 00:00:00 2001 From: Asim Shankar Date: Thu, 9 Nov 2017 23:29:56 -0800 Subject: [PATCH] Java/OS X: Workaround for how the framework library is packaged in the .jar by the release process. See #13872 PiperOrigin-RevId: 175261983 --- .../java/org/tensorflow/NativeLibrary.java | 43 ++++++++++++++----- 1 file changed, 32 insertions(+), 11 deletions(-) diff --git a/tensorflow/java/src/main/java/org/tensorflow/NativeLibrary.java b/tensorflow/java/src/main/java/org/tensorflow/NativeLibrary.java index 2b431eebf5f..499757e8cf4 100644 --- a/tensorflow/java/src/main/java/org/tensorflow/NativeLibrary.java +++ b/tensorflow/java/src/main/java/org/tensorflow/NativeLibrary.java @@ -43,7 +43,6 @@ final class NativeLibrary { private static final boolean DEBUG = System.getProperty("org.tensorflow.NativeLibrary.DEBUG") != null; private static final String JNI_LIBNAME = "tensorflow_jni"; - private static final String FRAMEWORK_LIBNAME = "tensorflow_framework"; public static void load() { if (isLoaded() || tryLoadLibrary()) { @@ -59,12 +58,15 @@ final class NativeLibrary { } // Native code is not present, perhaps it has been packaged into the .jar file containing this. // Extract the JNI library itself - final String jniResourceName = makeResourceName(JNI_LIBNAME); + final String jniLibName = System.mapLibraryName(JNI_LIBNAME); + final String jniResourceName = makeResourceName(jniLibName); log("jniResourceName: " + jniResourceName); final InputStream jniResource = NativeLibrary.class.getClassLoader().getResourceAsStream(jniResourceName); // Extract the JNI's dependency - final String frameworkResourceName = makeResourceName(FRAMEWORK_LIBNAME); + final String frameworkLibName = + maybeAdjustForMacOS(System.mapLibraryName("tensorflow_framework")); + final String frameworkResourceName = makeResourceName(frameworkLibName); log("frameworkResourceName: " + frameworkResourceName); final InputStream frameworkResource = NativeLibrary.class.getClassLoader().getResourceAsStream(frameworkResourceName); @@ -88,12 +90,15 @@ final class NativeLibrary { tempPath.deleteOnExit(); final String tempDirectory = tempPath.toString(); if (frameworkResource != null) { - extractResource(frameworkResource, FRAMEWORK_LIBNAME, tempDirectory); + extractResource(frameworkResource, frameworkLibName, tempDirectory); } else { - log(frameworkResourceName + " not found. This is fine assuming " + jniResourceName - + " is not built to depend on it."); + log( + frameworkResourceName + + " not found. This is fine assuming " + + jniResourceName + + " is not built to depend on it."); } - System.load(extractResource(jniResource, JNI_LIBNAME, tempDirectory)); + System.load(extractResource(jniResource, jniLibName, tempDirectory)); } catch (IOException e) { throw new UnsatisfiedLinkError( String.format( @@ -121,9 +126,27 @@ final class NativeLibrary { } } + private static String maybeAdjustForMacOS(String libFilename) { + if (!System.getProperty("os.name").contains("OS X")) { + return libFilename; + } + // This is macOS, and the TensorFlow release process might have setup dependencies on + // libtensorflow_framework.so instead of libtensorflow_framework.dylib. Adjust for that. + final ClassLoader cl = NativeLibrary.class.getClassLoader(); + if (cl.getResource(makeResourceName(libFilename)) != null) { + return libFilename; + } + // liftensorflow_framework.dylib not found, try libtensorflow_framework.so + final String suffix = ".dylib"; + if (!libFilename.endsWith(suffix)) { + return libFilename; + } + return libFilename.substring(0, libFilename.length() - suffix.length()) + ".so"; + } + private static String extractResource( InputStream resource, String resourceName, String extractToDirectory) throws IOException { - final File dst = new File(extractToDirectory, System.mapLibraryName(resourceName)); + final File dst = new File(extractToDirectory, resourceName); dst.deleteOnExit(); final String dstPath = dst.toString(); log("extracting native library to: " + dstPath); @@ -157,9 +180,7 @@ final class NativeLibrary { } private static String makeResourceName(String baseName) { - return "org/tensorflow/native/" - + String.format("%s-%s/", os(), architecture()) - + System.mapLibraryName(baseName); + return "org/tensorflow/native/" + String.format("%s-%s/", os(), architecture()) + baseName; } private static long copy(InputStream src, File dstFile) throws IOException {