diff options
author | Sven Gothel <[email protected]> | 2014-07-11 03:05:41 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2014-07-11 03:05:41 +0200 |
commit | f5c48efcf546ba4e08e197ccced6df83b57e1755 (patch) | |
tree | add2ce9506acb35ce3a34c763afb6d2b91a5081e | |
parent | be61c7f33ec8e4f3214e8d2969ee88cd327fce9d (diff) |
Bug 1024: Add fallback for native-jar-file location via classpath
In situations, where the native-jar file is not located within
the same parent URI as it's java-jar file, our location mechanism fails.
This patch adds a classloader based native-jar file location mechanism as a fallback,
requiring the native jar file to be included in the users CLASSPATH.
Classloader based location algorithm in JNILibLoaderBase.addNativeJarLibsImpl(..):
- Extract the 'module-name' from the given classFromJavaJar's package name,
i.e. the last package-part: 'jogamp.common.Debug' -> 'common'
Hence it is important to pass a 'classFromJavaJar',
which last package segment reflects the module-name!
- <os.and.arch> -> <os_and_arch_dot>, e.g. linux-amd64 -> linux.amd64 (linux/amd64)
- Locate class 'jogamp.nativetag.<module-name>.<os_and_arch_dot>.TAG',
e.g. 'jogamp.nativetag.common.linux.amd64.TAG'
- Use located class's JarFile URI .. continue as usual
Injection of above mentioned TAG class via gluegen-cpptasks-base.xml macro 'native.tag.jar':
- Creates dummy TAG.java code
- Compiles TAG.java
- Creates the native-jar file
Example:
<native.tag.jar objdir="${build}/obj"
nativejarfile="${build}/gluegen-rt-natives-${os.and.arch}.jar"
manifestfile="${build}/Manifest-rt-natives.temp"
module="common"
includelibs="*gluegen-rt.${native.library.suffix}" />
Note that the manifest file uses a matching Extension-Name:
Extension-Name: jogamp.nativetag.common
-rwxr-xr-x | make/Manifest-rt-natives | 2 | ||||
-rw-r--r-- | make/build.xml | 19 | ||||
-rwxr-xr-x | make/gluegen-cpptasks-base.xml | 64 | ||||
-rwxr-xr-x | make/scripts/runtest.sh | 4 | ||||
-rw-r--r-- | src/java/com/jogamp/common/jvm/JNILibLoaderBase.java | 58 | ||||
-rw-r--r-- | src/java/com/jogamp/common/os/Platform.java | 2 |
6 files changed, 131 insertions, 18 deletions
diff --git a/make/Manifest-rt-natives b/make/Manifest-rt-natives index d95830e..90c5590 100755 --- a/make/Manifest-rt-natives +++ b/make/Manifest-rt-natives @@ -11,7 +11,7 @@ Implementation-Commit: @SCM_COMMIT@ Implementation-Vendor: JogAmp Community Implementation-Vendor-Id: com.jogamp Implementation-URL: http://jogamp.org/ -Extension-Name: com.jogamp.common +Extension-Name: jogamp.nativetag.common Trusted-Library: true Permissions: all-permissions Application-Library-Allowable-Codebase: * diff --git a/make/build.xml b/make/build.xml index 0df5cf6..534f122 100644 --- a/make/build.xml +++ b/make/build.xml @@ -484,11 +484,12 @@ <antcall target="c.manifest" inheritRefs="true" /> - <jar destfile="${build}/gluegen-rt-natives-${os.and.arch}.jar" manifest="${build}/Manifest-rt-natives.temp"> - <fileset dir="${build}/obj"> - <include name="*gluegen-rt.${native.library.suffix}" /> - </fileset> - </jar> + <native.tag.jar objdir="${build}/obj" + nativejarfile="${build}/gluegen-rt-natives-${os.and.arch}.jar" + manifestfile="${build}/Manifest-rt-natives.temp" + module="common" + includelibs="*gluegen-rt.${native.library.suffix}" /> + <!-- Produce duplicates for different configurations, since non-native-jar aliasing (Bug 1023/Bug 1024) --> <copy file="${build}/gluegen-rt-natives-${os.and.arch}.jar" tofile="${build}/gluegen-rt-android-natives-${os.and.arch}.jar"/> </target> @@ -752,7 +753,7 @@ </copy> <!-- Build gluegen.jar. --> - <jar destfile="${build}/gluegen.jar" manifest="${build}/Manifest.temp"> + <jar destfile="${build}/gluegen.jar" manifest="${build}/Manifest.temp" filesonly="true"> <service type="javax.annotation.processing.Processor"> <provider classname="com.jogamp.gluegen.structgen.CStructAnnotationProcessor"/> </service> @@ -805,7 +806,7 @@ </copy> <!-- Build gluegen-rt.jar. --> - <jar destfile="${build}/gluegen-rt.jar" manifest="${build}/Manifest-rt.temp"> + <jar destfile="${build}/gluegen-rt.jar" manifest="${build}/Manifest-rt.temp" filesonly="true"> <fileset dir="${classes}"> <include name="com/jogamp/gluegen/runtime/*.class" /> <include name="com/jogamp/common/**" /> @@ -880,7 +881,7 @@ </copy> <!-- Build gluegen-rt-android.jar. --> - <jar destfile="${build}/gluegen-rt-android.jar" manifest="${build}/Manifest-rt-android.temp"> + <jar destfile="${build}/gluegen-rt-android.jar" manifest="${build}/Manifest-rt-android.temp" filesonly="true"> <fileset dir="${classes}"> <include name="com/jogamp/gluegen/runtime/*.class" /> <include name="com/jogamp/common/**" /> @@ -938,7 +939,7 @@ </filterset> </copy> - <jar destfile="${build}/jogamp-android-launcher.jar" manifest="${build}/Manifest-android-launcher.temp"> + <jar destfile="${build}/jogamp-android-launcher.jar" manifest="${build}/Manifest-android-launcher.temp" filesonly="true"> <fileset dir="${classes}"> <include name="${jogamp-android-launcher.classes}" /> </fileset> diff --git a/make/gluegen-cpptasks-base.xml b/make/gluegen-cpptasks-base.xml index 8b8b82e..911df8a 100755 --- a/make/gluegen-cpptasks-base.xml +++ b/make/gluegen-cpptasks-base.xml @@ -177,6 +177,10 @@ <echo message="os.version=${os.version}" /> <echo message="os.arch=${os.arch}" /> + <property name="nativejartag.package" value="jogamp.nativetag" /> + <property name="nativejartag.prefix" value="jogamp/nativetag" /> + <echo message="nativejartag.prefix = ${nativejartag.prefix}" /> + <!-- NOTE: the value of the debug attribute will not be overridden if already set externally --> <property name="c.compiler.debug" value="false" /> <condition property="c.compiler.use-debug"><istrue value="${c.compiler.debug}"/></condition> @@ -707,7 +711,19 @@ </target> <target name="gluegen.cpptasks.detect.os.2" depends="gluegen.cpptasks.detect.os.refine,gluegen.cpptasks.detect.os.freebsd,gluegen.cpptasks.detect.os.hpux,gluegen.cpptasks.detect.os.linux,gluegen.cpptasks.detect.os.osx,gluegen.cpptasks.detect.os.solaris,gluegen.cpptasks.detect.os.unix,gluegen.cpptasks.detect.os.windows" unless="gluegen.cpptasks.detected.os.2"> - <echo message="os and arch: ${os.and.arch}" /> + <propertyregex property="os.and.arch.dot" + input="${os.and.arch}" + regexp="-" + replace="." + global="true" /> + <propertyregex property="os.and.arch.slash" + input="${os.and.arch}" + regexp="-" + replace="/" + global="true" /> + <echo message="os and arch: ${os.and.arch}" /> + <echo message="os and arch.dot: ${os.and.arch.dot}" /> + <echo message="os and arch.slash: ${os.and.arch.slash}" /> </target> <target name="gluegen.cpptasks.detect.os" depends="gluegen.properties.load.user,gluegen.cpptasks.detect.os.custom,gluegen.cpptasks.detect.os.1,gluegen.cpptasks.detect.os.2"> @@ -1539,4 +1555,50 @@ </exec> </sequential> </macrodef> + + <macrodef name="native.tag.jar"> + <attribute name="objdir" /> + <attribute name="nativejarfile" /> + <attribute name="manifestfile" /> + <attribute name="module" /> + <attribute name="includelibs" /> + <attribute name="excludelibs" default="" /> + <sequential> + + <var name="nativejarfile.basename" unset="true"/> + <var name="nativejarfile.tmpdir" unset="true"/> + <var name="nativejarfile.tmpdir.natives" unset="true"/> + <basename property="nativejarfile.basename" file="@{nativejarfile}"/> + <property name="nativejarfile.tmpdir" value="@{objdir}/${nativejarfile.basename}.d" /> + <property name="nativejarfile.tmpdir.natives" value="${nativejarfile.tmpdir}/jar" /> + <!-- In case we like to switch to a natives subfolder 'natives/${os.and.arch}' use the following --> + <!-- property name="nativejarfile.tmpdir.natives" value="${nativejarfile.tmpdir}/jar/natives/${os.and.arch}" /--> + + <mkdir dir="${nativejarfile.tmpdir}/java" /> + <mkdir dir="${nativejarfile.tmpdir.natives}" /> + <copy todir="${nativejarfile.tmpdir.natives}"> + <fileset dir="@{objdir}" + includes="@{includelibs}" + excludes="@{excludelibs}"/> + </copy> + <echo message='package ${nativejartag.package}.@{module}.${os.and.arch.dot}; public final class TAG { }' file="${nativejarfile.tmpdir}/java/${nativejartag.prefix}/@{module}/${os.and.arch.slash}/TAG.java"/> + <javac destdir="${nativejarfile.tmpdir}/jar" + includes="${nativejartag.prefix}/@{module}/**" + includeAntRuntime="false" + encoding="UTF-8" + source="${target.sourcelevel}" + target="${target.targetlevel}" + bootclasspath="${target.rt.jar}"> + <src path="${nativejarfile.tmpdir}/java" /> + </javac> + <jar destfile="@{nativejarfile}" manifest="@{manifestfile}" filesonly="true"> + <fileset dir="${nativejarfile.tmpdir}/jar"> + <include name="**" /> + </fileset> + </jar> + <delete includeEmptyDirs="true"> + <fileset dir="${nativejarfile.tmpdir}" /> + </delete> + </sequential> + </macrodef> </project> diff --git a/make/scripts/runtest.sh b/make/scripts/runtest.sh index b1089c5..ccdae48 100755 --- a/make/scripts/runtest.sh +++ b/make/scripts/runtest.sh @@ -48,6 +48,7 @@ rm -f $LOG #D_ARGS="-Djogamp.debug.IOUtil -Djogamp.debug.JNILibLoader -Djogamp.debug.TempFileCache -Djogamp.debug.JarUtil -Djava.io.tmpdir=/run/tmp" #D_ARGS="-Djogamp.debug.IOUtil -Djogamp.debug.JNILibLoader -Djogamp.debug.TempFileCache -Djogamp.debug.JarUtil -Djogamp.debug.TempJarCache" #D_ARGS="-Djogamp.debug.JNILibLoader -Djogamp.gluegen.UseTempJarCache=false" +#D_ARGS="-Djogamp.debug.JNILibLoader -Djogamp.debug.TempJarCache" #D_ARGS="-Djogamp.debug.JNILibLoader" #D_ARGS="-Djogamp.debug.Lock" #D_ARGS="-Djogamp.debug.Lock -Djogamp.debug.Lock.TraceLock" @@ -57,7 +58,8 @@ rm -f $LOG #D_ARGS="-Djogamp.debug=all" function onetest() { - USE_CLASSPATH=lib/junit.jar:$ANT_JARS:lib/semantic-versioning/semver.jar:"$builddir"/../make/lib/TestJarsInJar.jar:"$builddir"/gluegen-rt.jar:"$builddir"/gluegen.jar:"$builddir"/gluegen-test-util.jar:"$builddir"/test/build/gluegen-test.jar + #USE_CLASSPATH=lib/junit.jar:$ANT_JARS:lib/semantic-versioning/semver.jar:"$builddir"/../make/lib/TestJarsInJar.jar:"$builddir"/gluegen-rt.jar:"$builddir"/gluegen.jar:"$builddir"/gluegen-test-util.jar:"$builddir"/test/build/gluegen-test.jar + USE_CLASSPATH=lib/junit.jar:$ANT_JARS:lib/semantic-versioning/semver.jar:"$builddir"/../make/lib/TestJarsInJar.jar:"$builddir"/gluegen-rt.jar:"$builddir"/gluegen.jar:"$builddir"/gluegen-test-util.jar:"$builddir"/test/build/gluegen-test.jar:"$builddir"/gluegen-rt-natives.jar #USE_CLASSPATH=lib/junit.jar:$ANT_JARS:lib/semantic-versioning/semver.jar:"$builddir"/../make/lib/TestJarsInJar.jar:"$builddir"/gluegen-rt-alt.jar:"$builddir"/gluegen.jar:"$builddir"/gluegen-test-util.jar:"$builddir"/test/build/gluegen-test.jar libspath="$builddir"/test/build/natives #USE_CLASSPATH=lib/junit.jar:$ANT_JARS:"$builddir"/../make/lib/TestJarsInJar.jar:"$builddir"/classes:"$builddir"/test/build/classes diff --git a/src/java/com/jogamp/common/jvm/JNILibLoaderBase.java b/src/java/com/jogamp/common/jvm/JNILibLoaderBase.java index f69ddd1..4bb68d3 100644 --- a/src/java/com/jogamp/common/jvm/JNILibLoaderBase.java +++ b/src/java/com/jogamp/common/jvm/JNILibLoaderBase.java @@ -150,6 +150,8 @@ public class JNILibLoaderBase { loaderAction = action; } + private static final String nativeJarTagPackage = "jogamp.nativetag"; // TODO: sync with gluegen-cpptasks-base.xml + /** * * @param classFromJavaJar @@ -200,10 +202,17 @@ public class JNILibLoaderBase { // We probably have one big-fat jar file, containing java classes // and all native platform libraries under 'natives/os.and.arch'! final URI nativeJarURI = JarUtil.getJarFileURI(jarUriRoot_s+jarBasename); - if( TempJarCache.addNativeLibs(classFromJavaJar, nativeJarURI, nativeLibraryPath) ) { - ok = true; - if (DEBUG) { - System.err.printf("JNILibLoaderBase: addNativeJarLibsImpl: fat: %s -> %s\n", jarBasename, nativeJarURI); + try { + if( TempJarCache.addNativeLibs(classFromJavaJar, nativeJarURI, nativeLibraryPath) ) { + ok = true; + if (DEBUG) { + System.err.printf("JNILibLoaderBase: addNativeJarLibsImpl: fat: %s -> %s%n", jarBasename, nativeJarURI); + } + } + } catch(final Exception e) { + if(DEBUG) { + System.err.printf("JNILibLoaderBase: addNativeJarLibsImpl: Caught %s%n", e.getMessage()); + e.printStackTrace(); } } } @@ -215,7 +224,46 @@ public class JNILibLoaderBase { System.err.printf("JNILibLoaderBase: addNativeJarLibsImpl: module: %s -> %s%n", nativeJarBasename, nativeJarURI); } - ok = TempJarCache.addNativeLibs(classFromJavaJar, nativeJarURI, null /* nativeLibraryPath */); + try { + ok = TempJarCache.addNativeLibs(classFromJavaJar, nativeJarURI, null /* nativeLibraryPath */); + } catch(final Exception e) { + if(DEBUG) { + System.err.printf("JNILibLoaderBase: addNativeJarLibsImpl: Caught %s%n", e.getMessage()); + e.printStackTrace(); + } + } + } + if (!ok) { + // Attempt to find via ClassLoader and Native-Jar-Tag, + // assuming one slim native jar file per 'os.and.arch'! + final String moduleName; + { + final String packageName = classFromJavaJar.getPackage().getName(); + final int idx = packageName.lastIndexOf('.'); + if( 0 <= idx ) { + moduleName = packageName.substring(idx+1); + } else { + moduleName = packageName; + } + } + final String os_and_arch_dot = PlatformPropsImpl.os_and_arch.replace('-', '.'); + final String nativeJarTagClassName = nativeJarTagPackage + "." + moduleName + "." + os_and_arch_dot + ".TAG" ; // TODO: sync with gluegen-cpptasks-base.xml + try { + if(DEBUG) { + System.err.printf("JNILibLoaderBase: addNativeJarLibsImpl: ClassLoader/TAG: Locating module %s, os.and.arch %s: %s%n", + moduleName, os_and_arch_dot, nativeJarTagClassName); + } + final URI nativeJarTagClassJarURI = JarUtil.getJarURI(nativeJarTagClassName, cl); + if (DEBUG) { + System.err.printf("JNILibLoaderBase: addNativeJarLibsImpl: ClassLoader/TAG: %s -> %s%n", nativeJarTagClassName, nativeJarTagClassJarURI); + } + ok = TempJarCache.addNativeLibs(classFromJavaJar, nativeJarTagClassJarURI, null /* nativeLibraryPath */); + } catch (final Exception e ) { + if(DEBUG) { + System.err.printf("JNILibLoaderBase: addNativeJarLibsImpl: Caught %s%n", e.getMessage()); + e.printStackTrace(); + } + } } if (DEBUG) { diff --git a/src/java/com/jogamp/common/os/Platform.java b/src/java/com/jogamp/common/os/Platform.java index b8e3385..12122a2 100644 --- a/src/java/com/jogamp/common/os/Platform.java +++ b/src/java/com/jogamp/common/os/Platform.java @@ -200,7 +200,7 @@ public class Platform extends PlatformPropsImpl { // load GluegenRT native library if(_USE_TEMP_JAR_CACHE[0] && TempJarCache.initSingleton()) { try { - JNILibLoaderBase.addNativeJarLibs(new Class<?>[] { Platform.class }, null); + JNILibLoaderBase.addNativeJarLibs(new Class<?>[] { jogamp.common.Debug.class }, null); } catch (final Exception e0) { // IllegalArgumentException, IOException System.err.println("Caught "+e0.getClass().getSimpleName()+": "+e0.getMessage()+", while JNILibLoaderBase.addNativeJarLibs(..)"); |