Bug 665576 - "build-classpath swt" fails on 64bit
Summary: "build-classpath swt" fails on 64bit
Keywords:
Status: CLOSED RAWHIDE
Alias: None
Product: Fedora
Classification: Fedora
Component: jpackage-utils
Version: 14
Hardware: Unspecified
OS: Unspecified
low
medium
Target Milestone: ---
Assignee: Deepak Bhole
QA Contact: Fedora Extras Quality Assurance
URL:
Whiteboard:
Depends On:
Blocks: 665426 734590
TreeView+ depends on / blocked
 
Reported: 2010-12-24 23:12 UTC by Hicham HAOUARI
Modified: 2014-01-21 23:17 UTC (History)
15 users (show)

Fixed In Version:
Doc Type: Bug Fix
Doc Text:
Clone Of:
: 734590 (view as bug list)
Environment:
Last Closed: 2011-10-07 14:24:33 UTC
Type: ---
Embargoed:


Attachments (Terms of Use)

Description Hicham HAOUARI 2010-12-24 23:12:32 UTC
Description of problem:
build-classpath have %{_jnidir} set to /usr/lib/java, which causes failure on 64bit fedora to find swt using "build-classpath swt"

Version-Release number of selected component (if applicable):
jpackage-utils-1.7.5-3.11.fc14.noarch

How reproducible:
Always

Steps to Reproduce:
1.Install eclipse-swt
2.exec : build-classpath swt
  
Actual results:
No swt jar location

Expected results:
Properly returns swt jar location

Additional info:
Since jpackage-utils is build on i686 on koji, JNI_LIBDIR is hardcoded to /usr/lib/java in /etc/java/java.conf

Comment 1 Andrew Overholt 2011-01-06 21:00:33 UTC
In macros.jpackage (in jpackage-utils' source), there exists these lines:

# Directory where arch-specific (JNI) version-independent jars are installed.
#
# By extension:
# %{_jnidir}-ext:
#   - version dependent jars
# %{_jnidir}-x.y.z:
#   - jars for Java standard x.y.z (usually symlinks to  %{_jnidir}-ext)
# To simplify things only %{_jnidir} is defined.
#
%_jnidir        %{_prefix}/lib/java

The thing that's confusing me is the same directory supposedly used for multiple architecture-dependent JARs of the same name.  Is this what's intended?  Nicolas/Ville/David, can you lend some expertise here?  Thanks.

Comment 2 Stanislav Ochotnicky 2011-01-12 16:25:07 UTC
It seems to me that instead of:
%_jnidir        %{_prefix}/lib/java

it should be:
%_jnidir        %{_libdir}/java

Otherwise build-classpath/find_jar are looking in the wrong place.

Comment 3 Deepak Bhole 2011-01-12 17:03:22 UTC
Using %{_libdir} is not enough since 32 bit JVMs and packages may exist on a 64 bit system, in which case they will not be seen.

Comment 4 Ville Skyttä 2011-01-12 22:07:57 UTC
I've never quite understood why it's done the way it is so I'm afraid I don't have any expertise to share here.  Anyway it doesn't matter where jpackage-utils is built, jnidir never ends up containing %{_libdir}, it's always %{_prefix}/lib.

But just guessing, this could be a relic from times when there was no 64-bit java plugin and/or web start and thus installing 32-bit VMs on 64-bit boxes was a more common real world scenario.  If you ask me, support for that (c|sh)hould be purged - there are no ix86 JVMs in the x86_64 repo anyway.

Comment 5 Nicolas Mailhot 2011-01-13 17:44:24 UTC
To actually work on a multilib system _jnidir should be defined as %{_libdir}/java

However the original build-classpath scripts were written on a 32 bit system with no access to 64 bitness (was in infancy at the time). They do not look in lib64 at all. Rather than fix it in the scripts, jnidir was re-defined as %{_prefix}/lib/java when the first 64 bit users complained. I don't see how it can work on a mixed (32+64 system)

So if you want to fix it, you need to add some shell logic in jpackage-utils to look in lib64 too if it's present, and then redefine _jnidir to its original value.

Comment 6 Ville Skyttä 2011-01-13 20:05:58 UTC
(In reply to comment #5)
> So if you want to fix it, you need to add some shell logic in jpackage-utils to
> look in lib64 too if it's present, and then redefine _jnidir to its original
> value.

I suppose a simpler alternative would be to just use %{_libdir} in /etc/rpm/macros.jpackage where appropriate, and change /etc/java/java.conf to have JNI_LIBDIR=$(rpm --eval %{_jnidir}) and JVM_ROOT=$(rpm --eval %{_jvmdir}).  But that'd require a lot of rebuilds, but would also result in cleaner/simpler end result.  This is just from quickly peeking into the scripts, not thought much at all.

Comment 7 Deepak Bhole 2011-01-13 20:18:26 UTC
(In reply to comment #6)
> (In reply to comment #5)
> > So if you want to fix it, you need to add some shell logic in jpackage-utils to
> > look in lib64 too if it's present, and then redefine _jnidir to its original
> > value.
> 
> I suppose a simpler alternative would be to just use %{_libdir} in
> /etc/rpm/macros.jpackage where appropriate, and change /etc/java/java.conf to
> have JNI_LIBDIR=$(rpm --eval %{_jnidir}) and JVM_ROOT=$(rpm --eval %{_jvmdir}).
>  But that'd require a lot of rebuilds, but would also result in cleaner/simpler
> end result.  This is just from quickly peeking into the scripts, not thought
> much at all.

Doesn't seem like all packages follow a hard and fast rule:

yum install '/usr/lib64/java/*' only brings in eclipse-swt. yum install '/usr/lib/java/*' OTOH brings in a few more:

Installing:
 brlapi-java   x86_64   0.5.5-3.fc14   fedora   27 k
 jffi          x86_64   0.6.5-4.fc14   fedora   194 k
 osutil        x86_64   1.3.1-3.fc14   fedora   25 k
 pki-symkey    x86_64   1.3.2-4.fc14   fedora   31 k

All of the above are arch specific, yet install in /usr/lib/java even on 64-bit.

Comment 8 Ville Skyttä 2011-01-13 22:44:27 UTC
Yes, that's what I meant by "that'd require a lot of rebuilds".

I believe there are three alternative ways to fix this, in no particular order:

A) Tweak jpackage-utils to look first into lib64 dirs, then fall back to lib, keep macros as is (this if I understood right was what Nicolas suggested).

B) Bite the bullet, make the dirs lib64 on x86_64 in macros etc, fix/rebuild what needs fixing (this is what I suggested).

C) Keep jpackage-utils as is, but install swt stuff to "lib" (not lib64) dirs no matter what the arch is.

My preference would be B, and I'll shut up now :)

Comment 9 Nicolas Mailhot 2011-01-19 22:22:28 UTC
B is the correct solution mid-term, but the jpackage-utils scripts probably need to fall back to lib during the transition unless someone wants to handle a mass rebuild. So I suggested the same thing as you, but with a safety fallback.

Comment 10 David Walluck 2011-01-19 22:27:02 UTC
As Deepak pointed out in comment #3, the %{_libdir} macro should fix building, but during runtime there would need to be a function in the scripts to set the libdir (-Djava.library.dir) based on the JVM arch, not the host arch.

Comment 11 David Walluck 2011-01-19 22:29:20 UTC
That should be java.library.path in comment #10. Builds that required native libs typically set this themselves in the %{_bindir} script or a config file in %{_sysconfdir}, but I doubt it took into account that scenario.

Comment 12 Stanislav Ochotnicky 2011-02-23 19:27:21 UTC
We talked about this during SIG meeting and we all agreed that B option is OK. We are doing this switch really early so we have plenty of time to fix breakages in F16 rawhide. So you can go ahead with this. 

FYI:
$ repoquery --repoid=rawhide --whatprovides /usr/lib/java/\*
tritonus-0:0.3.7-0.12.20101108cvs.fc15.x86_64
nuxwdog-client-java-0:1.0.1-2.fc15.x86_64
pki-symkey-0:9.0.3-2.fc15.x86_64
jss-0:4.2.6-14.fc15.x86_64
osutil-0:2.0.1-2.fc15.x86_64
brlapi-java-0:0.5.5-4.fc15.x86_64
symkey-0:1.3.0-4.fc13.x86_64
jffi-0:1.0.2-1.fc15.x86_64
pki-symkey-0:1.3.2-5.fc15.x86_64

Comment 13 Matthew Harmsen 2011-03-12 01:43:51 UTC
My 2 cents -- although it sounds as if you guys have already decided this - *sigh*!

I believe that what is being missed here is that first and foremost, ONLY Java applications use JNI, and Java applications are ARCHITECTURE INDEPENDENT!

Our application is one of the biggest users of JNI libraries -- in fact, members of my team own the following:

nuxwdog-client-java-0:1.0.1-2.fc15.x86_64
pki-symkey-0:9.0.3-2.fc15.x86_64
jss-0:4.2.6-15.fc15.x86_64
osutil-0:2.0.1-2.fc15.x86_64

NOTE:  symkey-0:1.3.0-4.fc13.x86_64 and pki-symkey-0:1.3.2-5.fc15.x86_64 are no
       longer valid (or soon won't be).

Being a Java application which utilizes JNI libraries basically means that requests travel through a JNI jar file to its associated native .so portion (32-bit or 64-bit) and back to the Java application -- Java drives this, NOT the underlying 32-bit/64-bit libraries.

In Linux, the way our code is constructed in our JNI libraries is to ALWAYS use CLASSPATHS which look for a JNI JAR file under /usr/lib/java (e. g. - ALWAYS specified by '%_jnidir' in the spec files).  Each JNI jar file contains the logic to look first for an associated 64-bit library under /usr/lib64/<JNI name> followed by looking for an associated 32-bit library under /usr/lib/<JNI name> (to allow for a 32-bit version of the product to be installed on a 64-bit platform).

The only obvious issue is that one cannot have BOTH 32-bit and 64-bit versions of the Java product installed on the system at the same time -- something that has never been a requirement for our product -- and seems highly questionable as to why one would want to have both 32-bit and 64-bit versions of the same architecture-independent Java application residing on the platform simultaneously.

It is my belief that our current packaging solution (already applied to osutil, pki-symkey, and jss) works quite well without any changes; it applies the Fedora rule of placing application-specific libraries (in this case, JNI libraries) under their own private directory (e. g. - /usr/lib/jss and /usr/lib64/jss):

32-bit:

/usr/lib/java/jss4.jar -> /usr/lib/jss/jss4.jar
/usr/lib/jss/jss4-4.2.6.jar
/usr/lib/jss/jss4.jar -> jss4-4.2.6.jar
/usr/lib/jss/libjss4.so

/usr/lib/java/osutil.jar -> /usr/lib/osutil/osutil.jar
/usr/lib/osutil
/usr/lib/osutil/libosutil.so
/usr/lib/osutil/osutil-2.0.1.jar
/usr/lib/osutil/osutil.jar -> osutil-2.0.1.jar

/usr/lib/java/symkey.jar -> /usr/lib/symkey/symkey.jar
/usr/lib/symkey
/usr/lib/symkey/libsymkey.so
/usr/lib/symkey/symkey-9.0.3.jar
/usr/lib/symkey/symkey.jar -> symkey-9.0.3.jar


64-bit:

/usr/lib/java/jss4.jar -> /usr/lib64/jss/jss4.jar
/usr/lib64/jss/jss4-4.2.6.jar
/usr/lib64/jss/jss4.jar -> jss4-4.2.6.jar
/usr/lib64/jss/libjss4.so

/usr/lib/java/osutil.jar -> /usr/lib64/osutil/osutil.jar
/usr/lib64/osutil
/usr/lib64/osutil/libosutil.so
/usr/lib64/osutil/osutil-2.0.1.jar
/usr/lib64/osutil/osutil.jar -> osutil-2.0.1.jar

/usr/lib/java/symkey.jar -> /usr/lib64/symkey/symkey.jar
/usr/lib64/symkey
/usr/lib64/symkey/libsymkey.so
/usr/lib64/symkey/symkey-9.0.3.jar
/usr/lib64/symkey/symkey.jar -> symkey-9.0.3.jar

Comment 14 John Dennis 2011-03-13 00:08:28 UTC
There are 4 different issues at play and I'm afraid they haven't been
clearly separated in the existing discussion. They are:

1) How the jni lib is built for a given arch

2) Where the arch specific jni is installed

3) How the jni lib is loaded

4) How class paths are resolved

Let's also declare a goal of fully supporting multilib and that
multilib support should follow the existing multilib processes and
conventions. What does multilib mean for Java applications which are
normally thought of as architecture independent? It is defined by the
JVM which loads the classes. There may be both a 32-bit and 64-bit JVM
present on the system. The following is critical, the selection of the
JVM is independent. The build/package/install/load mechanisms must be
able to correctly handle either a 32-bit JVM or a 64-bit JVM.

I do not subscribe to the assertion that a 32-bit JVM on a 64-bit
system need not be supported nor that one should not be able to switch
between 32-bit and 64-bit JVM's at will. The ability to choose between
32-bit and 64-bit JVM's is a fundamental property of any multilib
system, you're supposed to be able to make the choice.

Issue 1:

The jni lib should be built like any other arch specific rpm
component. In practice this will mean there will be both a x86 and
x86_64 package (ppc and ppc64, so forth). %{_libdir} should be
utilized during building just as any other arch specific build.

Issue 2:

Because we've set ourselves the goal of supporting multilib the arch
specific package needs to install into a matching arch specific
library. Utilizing %{_libdir}/java would make sense, it keeps 32-bit
and 64-bit libraries distinct and follows existing multilib
guidelines.

Issue 3:

This is the most interesting of the 4 issues. The version of the jni
lib which is loaded MUST match the JVM. Recall it's the JVM which
determines whether a 32-bit or 64-bit JNI library should be loaded,
32-bit JVM's need 32-bit JNI's and 64-bit JVM's need 64-bit JNI's. In
a perfect world the JVM would select the correct JNI bitness to
load. One might hope System.loadLibrary() could perform this for us
but the designers of Java and the implementers of JVM's did not
anticipate this. Plus System.loadLibrary() does not provide the
flexibility to install libraries outside of a system canonical
location. For instance app specific JNI's might wish to follow FHS
guidelines and install in app specific directories.

Since the JNI to be loaded is a function of the JVM and
System.loadLibrary() isn't an option we're forced to utilize
System.load(). The pure Java component will need to determine the
bitness of the JVM. There would appear to be no direct Java query for
this, but fortunately System.getProperty("os.arch") returns the arch
of the JVM not the OS, which because it's JVM specific meets our
needs. Thus the pure Java component will need to call
System.getProperty("os.arch") and modify it's library path
accordingly.

But what is the library path? At this point I do not know if the
java.library.path property is reliable or whether one should just
follow the packaging conventions of the Linux distribution, in which
case the pure Java could would need to perform some other
environmental property query. Or the library path could be hardcoded
into the pure Java code as the PKI classes currently do. Or the path
could be substituted during the build step, I think this is probably
the preferred and most robust approach. As an aside it's too bad that
not all Linux distributions follow the same library path conventions.

Issue 4:

Classpath resolution is what began this whole discussion. Classpaths
are independent of the JVM. Thus classpaths cannot be sensitive to the
arch of a JNI library. build-classpath is not at fault. To my mind the
problem is the bundling of the arch independent pure Java component of
a JNI jar in the same location as the arch specific JNI library. Why?
The answer is described in Issue 3, it's the pure Java code which
queries the JVM it's running it to determine which arch specific JNI
library to load via System.load(). If the arch independent pure Java
is located in the same class path locations then build-classpath is
not going to fail.

But what happens when an arch specific JNI library is not installed
and thus not available for loading via System.load()? It should throw
an exception just like everything else. Recall that passing CLASSPATH
to a JVM which does not contain a required class is a common problem,
there is nothing which says the link requirements are guaranteed to
be resolvable prior to execution, thus we have not violated any
assumptions. 

Summary:

Use %{_libdir}/java as %{jnidir} for building. Use System.load() to
select the jnidir matched to the JVM. Install the Java component of a
JNI library in the standard Java classpath instead of bundling with
the arch specific jni .so

Comment 15 Matthew Harmsen 2011-03-15 00:46:55 UTC
Additional information:

My comments in Comment 13 above were based upon the following document:

* http://fedoraproject.org/wiki/Packaging/Java#Packaging_JAR_files_that_use_JNI

Specifically, the sentence "JAR files that require JNI shared objects MUST be
installed in %{_libdir}/%{name}."

NOTE:  What may have not been clear was that the JAR file components of both
       the 32-bit and 64-bit versions of each JNI package are identical.


The sentence "If the JNI-using code calls System.loadLibrary you'll have to
patch it to use System.load, passing it the full path to the dynamic shared
object." is currently addressed thusly (using 'osutil' as an example):

    static boolean tryLoad( String filename )
    {
        try {
            System.load( filename );
        } catch( Exception e ) {
            return false;
        } catch( UnsatisfiedLinkError e ) {
            return false;
        }

        return true;
    }

    // Load native library
    static {
        boolean mNativeLibrariesLoaded = false;
        String os = System.getProperty( "os.name" );
        if( ( os.equals( "Linux" ) ) ) {
            // Check for 64-bit library availability
            // prior to 32-bit library availability.
            mNativeLibrariesLoaded =
                tryLoad( "/usr/lib64/osutil/libosutil.so" );
            if( mNativeLibrariesLoaded ) {
                System.out.println( "64-bit osutil library loaded" );
            } else {
                // REMINDER:  May be trying to run a 32-bit app
                //            on 64-bit platform.
                mNativeLibrariesLoaded =
                    tryLoad( "/usr/lib/osutil/libosutil.so" );
                if( mNativeLibrariesLoaded ) {
                    System.out.println( "32-bit osutil library loaded");
                } else {
                    System.out.println( "FAILED loading osutil library!");
                    System.exit( -1 );
                }
            }
        } else {
            try {
                System.loadLibrary( "osutil" );
                System.out.println( "osutil library loaded" );
                mNativeLibrariesLoaded = true;
            } catch( Throwable t ) {
                // This is bad news, the program is doomed at this point
                t.printStackTrace();
            }
        }
    }

We deviated from Fedora instructions only insomuch as that for all of the
wrapper scripts within our server that use CLASSPATH, we simply included
/usr/lib/java (as defined by %_jnidir) which contains the appropriate symlink
rather than the sentence "If the package installs a wrapper script you'll
need to manually add %{_libdir}/%{name}/<jar filename> to CLASSPATH. If you
are depending on a JNI-using JAR file, you'll need to add it manually
-- build-classpath will not find it.".

==============================================================================

In order to comply with what Fedora already suggests, what is being proposed by the bug, what is proposed in Comment #14, and still trying to maintain minimal
disruption to the existing packages, I propose the following:

Verifying "os.arch" from Comment #14 on a 64-bit VM:

    class WhatOS 
    {
      public static void main( String args[] ) 
      {
        System.out.println( System.getProperty("os.name") );
        System.out.println( System.getProperty("os.version") );
        System.out.println( System.getProperty("os.arch") );
      }
    }


    # /usr/lib/jvm/jre-1.6.0-openjdk.x86_64/bin/java WhatOS
    Linux
    2.6.38-0.rc4.git0.2.fc15.x86_64
    amd64


    # /usr/lib/jvm/jre-1.6.0-openjdk/bin/java WhatOS
    Linux
    2.6.38-0.rc4.git0.2.fc15.x86_64
    i386


would imply changing existing JNI code to something like this (again, using
'osutil' as an example):

    static boolean tryLoad( String filename )
    {
        try {
            System.load( filename );
        } catch( Exception e ) {
            return false;
        } catch( UnsatisfiedLinkError e ) {
            return false;
        }

        return true;
    }

    // Load native library
    static {
        boolean mNativeLibrariesLoaded = false;
        String os = System.getProperty( "os.name" );
        String jre_arch = System.getProperty( "os.arch" );
        String load_lib = null;
        if( ( os.equals( "Linux" ) ) ) {
            if( ( jre_arch.equals( "x86_64" ) ) ||
                ( jre_arch.equals( "amd64" ) ) ) {
                // Check for 64-bit library availability
                load_lib = "64-bit";
                mNativeLibrariesLoaded =
                    tryLoad( "/usr/lib64/osutil/libosutil.so" );
            } else if( ( jre_arch.equals( "i386" ) ) ||
                       ( jre_arch.equals( "i486" ) ) ||
                       ( jre_arch.equals( "i586" ) ) ||
                       ( jre_arch.equals( "i686" ) ) ) {
                  // Check for 32-bit library availability
                  load_lib = "32-bit";
                  mNativeLibrariesLoaded =
                      tryLoad( "/usr/lib/osutil/libosutil.so" );
            }

            if( mNativeLibrariesLoaded ) {
                System.out.println( load_lib + " osutil library loaded" );
            } else {
                System.out.println( "FAILED loading " +
                                    load_lib +
                                    " osutil library!");
                System.exit( -1 );
            }
        } else {
            try {
                System.loadLibrary( "osutil" );
                System.out.println( "osutil library loaded" );
                mNativeLibrariesLoaded = true;
            } catch( Throwable t ) {
                // This is bad news, the program is doomed at this point
                t.printStackTrace();
            }
        }
    }


Similar code would need to be applied to 'pki-symkey', 'jss', and
'nuxwdog-client'.

The corresponding 32-bit and 64-bit 'osutil' RPMS would then be re-packaged to
contain:

32-bit:

/usr/lib/java/osutil.jar -> /usr/lib/osutil/osutil.jar
/usr/lib/osutil/
/usr/lib/osutil/libosutil.so
/usr/lib/osutil/osutil-2.0.1.jar
/usr/lib/osutil/osutil.jar -> osutil-2.0.1.jar
/usr/share/doc/osutil-2.0.1/
/usr/share/doc/osutil-2.0.1/LICENSE


64-bit:

/usr/lib64/java/osutil.jar -> /usr/lib64/osutil/osutil.jar
/usr/lib64/osutil/
/usr/lib64/osutil/libosutil.so
/usr/lib64/osutil/osutil-2.0.1.jar
/usr/lib64/osutil/osutil.jar -> osutil-2.0.1.jar
/usr/share/doc/osutil-2.0.1/
/usr/share/doc/osutil-2.0.1/LICENSE


IMPORTANT:  Within Dogtag, wrappers using CLASSPATH would need to be changed to
            determine which JRE architecture was being invoked PRIOR to setting
            CLASSPATH, as one would need to distinguish between "/usr/lib/java"
            and "/usr/lib64/java" in the CLASSPATH.

CAVEAT:  While this would address being able to simultaneously install and
         distinguish between 32-bit and 64-bit versions of JNI (although both
         packages still contain the identical directory
         "/usr/share/doc/osutil-2.0.1" and the file
         "/usr/share/doc/osutil-2.0.1/LICENSE"?), it is highly unlikely
         that Dogtag could be simultaneously installed as both a 32-bit
         application and a 64-bit application, due to other portions of
         the server never having been required to be simultaneously
         multi-arch aware.

Comment 16 Matthew Harmsen 2011-03-15 01:13:51 UTC
The "revised" code in Comment 15 above still needs appropriate error handling for platforms that are not supported in Linux.

Comment 17 Nicolas Mailhot 2011-03-15 09:57:27 UTC
While it is certainly possible to write add code to jni jars so they call different libs depending on the bit-ness of the jvm they're executed in, it will play major havoc rpm dependencies-side.

I honestly can not see how such a scenario can work safely without requiring both 32 and 64 bit libs in the rpm containing the jar file, which will annoy users tremendously. It would be much easier and safer to generate one 32 bit and one 64 bit jni jar, as it's how the rest of the platform work.

Please do not forget the result needs to be deployed before adding code to support a mode others part of the stack can not work with

Comment 18 Nicolas Mailhot 2011-03-15 10:05:13 UTC
Adding Seth and Pati to have an informed opinion on whether it is possible to express sanely "foo depends on arch-lib, where arch depends on the arch of the jvm it's invoqued from"

Comment 19 Nicolas Mailhot 2011-03-15 10:08:04 UTC
Though thinking a bit more about it, it may work if you create two arched-rpms, containing the same file in the same location but with different rpm architectures and depending on different libraries (good luck to whoever will write the spec template for this)

But at this point, is it really worth it to multiplex the jni glue in a single file?

Comment 20 John Dennis 2011-03-15 14:15:00 UTC
re comment #17 and comment #19

Couldn't the packaging issue be simply solved with virtual provides/requires?

The noarch pure java package requires a package which provides the virtual jni lib.

Each arch specific jni lib package offers a virtual provides for the jni lib.

Comment 21 Matthew Harmsen 2011-03-15 16:43:52 UTC
Additional information:

All JNI packages mentioned are "architecture-specific".

JNI consists of two parts:
* an architecture-independent JAR file required by Java,
* an architecture-dependent shared object.

Since JNI was first placed into RPMS spanning multiple releases of Dogtag and RHCS, separate architecture-dependent RPMS have always been issued which contained an architecture-independent JAR, an architecture-dependent shared object, and an architecture-independent LICENSE file.  Both the LICENSE and the JAR were identical across all RPMS.

Comment 22 Andrew Wnuk 2011-03-15 17:09:16 UTC
JNI is convenience interface allowing to reuse native code,
providing performance or functionally not available in Java,
so why impose artificial bit-rules restricting this convenience. 

Most Java users are annoyed just by facing necessity of using JNI,
since it comes with extra maintenance hassles. 
In many cases they face limited choices due to the functionality
they need to provide. Those limited choices may force them to mix
native code types. Restricting their limited options by imposing
additional bit-rules is not going to help them.

Comment 23 John Dennis 2011-03-15 17:25:35 UTC
re comment #22

Andrew I didn't follow your point, could you rephrase it please?

FWIW, we're trying to simplify JNI usage for users and allow JNI to be more flexible. It complicates the packaging a bit, but not the user experience. What inconvenient "artificial" bit-rules are being imposed?

Comment 24 Andrew Wnuk 2011-03-15 19:59:48 UTC
(In reply to comment #23)

JNI has its own limitations and I would like to avoid imposing new ones. If JNI allows me to use 32 and 64 bit native libraries, I would like to be able to use either of them or both of them if I need to. We should not add restrictions based on JVM architecture other than the ones set by JVM itself.

Comment 25 John Dennis 2011-03-15 20:13:43 UTC
re comment #24

> If JNI allows me to use 32 and 64 bit native libraries, I would like 
> to be able to use either of them or both of them if I need to. 

Good that's my goal too.

> We should not add restrictions based on JVM architecture other than
> the ones set by JVM itself.

That's where you lost me. We're not adding any new restrictions. It's a fact of life 32-bit JVM's can only load 32-bit JNI libraries and 64-bit JVM's can only load 64-bit libraries. 32-bit JNI libraries can only link with 32-bit libraries, 64-bit JNI libraries can only link with 64-bit libraries.

Which JNI you load (32-bit vs. 64-bit) is function of the JVM.

Comment 26 Andrew Wnuk 2011-03-15 22:35:28 UTC
(In reply to comment #25)

> > We should not add restrictions based on JVM architecture other than
> > the ones set by JVM itself.
> 
> That's where you lost me. We're not adding any new restrictions. It's a fact of
> life 32-bit JVM's can only load 32-bit JNI libraries and 64-bit JVM's can only
> load 64-bit libraries. 32-bit JNI libraries can only link with 32-bit
> libraries, 64-bit JNI libraries can only link with 64-bit libraries.
> 
> Which JNI you load (32-bit vs. 64-bit) is function of the JVM.

Sorry for confusion. Since JNI documentation is bit vague, I falsely draw conclusions based on my Smalltalk experience. That other VM was able to access 64-bit and 32-bit libraries at the same time.

Comment 27 Matthew Harmsen 2011-03-16 05:26:31 UTC
Another proposal:

Our current model is detailed in Comment #13 which we believe basically conforms to existing Fedora JNI requirements detailed in http://fedoraproject.org/wiki/Packaging/Java#Packaging_JAR_files_that_use_JNI (but does not provide for simultaneous multi-arch capability):

* osutil-2.0.1-2.fc15.i686.rpm
  /usr/lib/java/osutil.jar -> /usr/lib/osutil/osutil.jar
  /usr/lib/osutil
  /usr/lib/osutil/libosutil.so
  /usr/lib/osutil/osutil-2.0.1.jar
  /usr/lib/osutil/osutil.jar -> osutil-2.0.1.jar
  /usr/share/doc/osutil-2.0.1
  /usr/share/doc/osutil-2.0.1/LICENSE

* osutil-2.0.1-2.fc15.x86_64.rpm
  /usr/lib/java/osutil.jar -> /usr/lib64/osutil/osutil.jar
  /usr/lib64/osutil
  /usr/lib64/osutil/libosutil.so
  /usr/lib64/osutil/osutil-2.0.1.jar
  /usr/lib64/osutil/osutil.jar -> osutil-2.0.1.jar
  /usr/share/doc/osutil-2.0.1
  /usr/share/doc/osutil-2.0.1/LICENSE

My initial proposal was outlined in Comment #15, and would produce the following two RPMS which would, for the most part, satisfy the desire for simultaneous multi-arch RPMS (except for potentially the LICENSE issue):

* osutil-2.0.1-2.fc15.i686.rpm
  /usr/lib/java/osutil.jar -> /usr/lib/osutil/osutil.jar
  /usr/lib/osutil/
  /usr/lib/osutil/libosutil.so
  /usr/lib/osutil/osutil-2.0.1.jar
  /usr/lib/osutil/osutil.jar -> osutil-2.0.1.jar
  /usr/share/doc/osutil-2.0.1/
  /usr/share/doc/osutil-2.0.1/LICENSE

* osutil-2.0.1-2.fc15.x86_64.rpm
  /usr/lib64/java/osutil.jar -> /usr/lib64/osutil/osutil.jar
  /usr/lib64/osutil/
  /usr/lib64/osutil/libosutil.so
  /usr/lib64/osutil/osutil-2.0.1.jar
  /usr/lib64/osutil/osutil.jar -> osutil-2.0.1.jar
  /usr/share/doc/osutil-2.0.1/
  /usr/share/doc/osutil-2.0.1/LICENSE

If we are allowed to change the existing Fedora requirement of "JAR files that require JNI shared objects MUST be installed in %{_libdir}/%{name}.", we could separate packages to allow for simultaneous multi-arch without compromising existing solutions which have effectively utilized "%{_jnidir}":

* osutil-2.0.1-2.fc15.noarch.rpm
  /usr/lib/java/osutil-2.0.1.jar
  /usr/lib/java/osutil.jar -> osutil-2.0.1.jar
  /usr/share/doc/osutil-2.0.1/
  /usr/share/doc/osutil-2.0.1/LICENSE

* osutil-jni-native-2.0.1-2.fc15.i686.rpm
  /usr/lib/osutil/
  /usr/lib/osutil/libosutil.so

* osutil-jni-native-2.0.1-2.fc15.x86_64.rpm
  /usr/lib64/osutil/
  /usr/lib64/osutil/libosutil.so

This proposal basically requires:
* a change to the source code as detailed in Comment #15 above
  (with the necessary error handling),
* changes to the spec file which separates the packages as detailed above:

  * osutil.spec
    . . .
    BuildRequires:    cmake
    BuildRequires:    java-devel >= 1:1.6.0
    BuildRequires:    jpackage-utils
    BuildRequires:    nspr-devel
    BuildRequires:    nss-devel
    BuildRequires:    pkgconfig
    . . .
    %package -n       osutil
    BuildArch:        noarch
    Requires:         java >= 1:1.6.0
    Requires:         jpackage-utils
    %ifarch i686
    Requires:         osutil-jni-native.i686
    %endif
    %ifarch x86_64
    Requires:         osutil-jni-native.i686
    Requires:         osutil-jni-native.x86_64
    %endif
    . . .
    %package -n       osutil-jni-native
    Requires:         nss
    . . .
    %files -n         osutil
    %defattr(-,root,root,-)
    %doc LICENSE
    %{_jnidir}/osutil.jar
    . . .
    %files -n         osutil-jni-native    
    %{_libdir}/osutil/

Comment 28 Stanislav Ochotnicky 2011-03-16 07:42:48 UTC
(In reply to comment #27)
> If we are allowed to change the existing Fedora requirement of "JAR files that
> require JNI shared objects MUST be installed in %{_libdir}/%{name}.", we could
> separate packages to allow for simultaneous multi-arch without compromising
> existing solutions which have effectively utilized "%{_jnidir}":
> 
> * osutil-2.0.1-2.fc15.noarch.rpm
>   /usr/lib/java/osutil-2.0.1.jar
>   /usr/lib/java/osutil.jar -> osutil-2.0.1.jar

Is there a technical problem why this couldn't be placed in /usr/share/java/osutil.jar ?

Note that current guidelines don't have versioned jar files (osutil-2.0.1.jar shouldn't exist).

As for requiring both i686 and x86_64 libraries on x86_64 system. I don't particularly like this (unnecessary dependency if someone has x86_64 only system with no 32bit java), I don't really have a better solution.

Also please don't consider JNI packaging documentation binding at all at this time. Consider this a place to discuss how to fix it properly. If we come up with a good solution, we are going to update the guidelines to reflect this change. We knew JNI guidelines were in need of an update badly for some time, but there were not enough people who really understood what was going on (I certainly didn't). It seems to me you are those people so let's fix it up once and for all :-)

Comment 29 Nicolas Mailhot 2011-03-16 11:18:01 UTC
(In reply to comment #20)
> re comment #17 and comment #19
> 
> Couldn't the packaging issue be simply solved with virtual provides/requires?
> 
> The noarch pure java package requires a package which provides the virtual jni
> lib.

Not really because you need the bit-ness of the jni lib and of the jvm to match

One can not really express in a packaging system

needs (64 bit jvm and 64 bit lib) or (32 bit jvm and 32 bit lib)

The only simple robust solution IMHO is a 32 bit package with the jni jar that requires (32 bit jvm and 32 bit lib), and another 64 bit package that requires (64 bit jvm and 64 bit lib)

That may seem simplistic but if rpm/deb/whatever can handle very complex systems, it's because the dependency rules have been simplified to the point it is possible to compute them automatically.

The situation on windows is very different. Here you can do all sorts of if-defing in the installation package, but the result is too complex to be integrated system-wide.

Comment 30 John Dennis 2011-03-16 14:40:20 UTC
re comment #29

> The only simple robust solution IMHO is a 32 bit package with the jni jar that
> requires (32 bit jvm and 32 bit lib), and another 64 bit package that requires
> (64 bit jvm and 64 bit lib)

Yes that works and is the most robust. It's OK for the 32-bit and 64-bit versions of the rpm to contain the same noarch files as long as they are identical.

The only minor issue in your proposal is that java is a virtual provides. This makes sense because there are many packages which provide java (not only different vendors/implementations but also different bitness within a vendor/implementation). We would probably need to augment the java virtual provides in the java* packages with a virtual provides for the bitness, maybe something like jre-32bit and jre-64bit. Then the jni 32-bit package would require jre-32bit and the 64-bit jni package would require jre-64bit. A number of different rpms could provide either.

One thing I've ignored in the discussion so far is whether jni .so's have a dependency on the specific jvm loading it. In other words can a Sun jvm and an OpenJDK jvm both load the same jni.so?

Comment 31 Nicolas Mailhot 2011-03-16 16:14:04 UTC
(In reply to comment #30)
> re comment #29
> 
> > The only simple robust solution IMHO is a 32 bit package with the jni jar that
> > requires (32 bit jvm and 32 bit lib), and another 64 bit package that requires
> > (64 bit jvm and 64 bit lib)
> 
> Yes that works and is the most robust. It's OK for the 32-bit and 64-bit
> versions of the rpm to contain the same noarch files as long as they are
> identical.

There might be a problem however if you try to automate jni dependency extraction later (now that dependency extractors have been split from rpm itself)

Comment 32 John Dennis 2011-03-16 17:10:33 UTC
re comment #31

I'm at a loss for how one would handle jni depedencies in all combinations, I don't think the rpm dependency model is rich enough. However it should work in the default cases. In other words each multi-arch platform has a defined arch preference, as long as the dependencies are evaluated in the context of the preferred default arch I believe everything works out.

If you start installing non-preferred arches for jni components then yum/rpm isn't going to be able to determine the dependency set, you'll have to manually install some packages. I just don't see a way around this if unless you want to include both 32-bit and 64-bit .so in one package (but that's in conflict with the existing packaging model and an earlier goal, plus I don't even know how you would do such a package build).

The essential problem is that the jvm is a transitive run time dependency, rpm has no facility for determining dependencies which are only known at run time.

I guess the best way to sum this up is that Java JNI is a weird corner case not supported by the existing models.

If you want to be brutally honest I think it would be fair to say multi-arch on Fedora is a bit of a hack which only works by virtue of adopted conventions and special case processing introduced into yum and rpm. We've been forced to use a packaging system which never was designed to support multi-arch.

This explanation from Bill Nottingham is an interesting read:

http://lists.fedoraproject.org/pipermail/devel/2010-January/129725.html

Comment 33 Matthew Harmsen 2011-03-16 21:38:29 UTC
(In reply to comment #28)
> Is there a technical problem why this couldn't be placed in
> /usr/share/java/osutil.jar ?
>

While there may be no "technical" reason, it has been common and traditional for us to place the JAR portion of a JNI into /usr/lib/java (%{_jnidir}) to distinguish JNI JARS which require a native .so component versus Pure Java JARS that require no .so component (/usr/share/java).  For previous products, we delivered these same JNI JARS to Solaris systems using the same separation mechanism (/usr/lib/java and /usr/share/java).  By maintaining this separate location, one can always easily understand that they are looking at a JNI JAR versus Pure Java JAR.

> Note that current guidelines don't have versioned jar files (osutil-2.0.1.jar
> shouldn't exist).
> 

While guidelines may not exist for this for JNI JARS, once again, it is commmon usage for Pure Java JARS located under /usr/share/java to use this convention, and consequently, we mimic this convention for JNI JARS.

> As for requiring both i686 and x86_64 libraries on x86_64 system. I don't
> particularly like this (unnecessary dependency if someone has x86_64 only
> system with no 32bit java), I don't really have a better solution.
> 

This was merely an attempt at addressing the following portion of jdennis comment #14:

> Let's also declare a goal of fully supporting multilib and that
> multilib support should follow the existing multilib processes and
> conventions. What does multilib mean for Java applications which are
> normally thought of as architecture independent? It is defined by the
> JVM which loads the classes. There may be both a 32-bit and 64-bit JVM
> present on the system. The following is critical, the selection of the
> JVM is independent. The build/package/install/load mechanisms must be
> able to correctly handle either a 32-bit JVM or a 64-bit JVM.

> I do not subscribe to the assertion that a 32-bit JVM on a 64-bit
> system need not be supported nor that one should not be able to switch
> between 32-bit and 64-bit JVM's at will. The ability to choose between
> 32-bit and 64-bit JVM's is a fundamental property of any multilib
> system, you're supposed to be able to make the choice.

Comment 34 Stanislav Ochotnicky 2011-03-17 09:11:32 UTC
(In reply to comment #33)
> (In reply to comment #28)
> > Is there a technical problem why this couldn't be placed in
> > /usr/share/java/osutil.jar ?
> >
> 
> While there may be no "technical" reason, it has been common and traditional
> for us to place the JAR portion of a JNI into /usr/lib/java (%{_jnidir}) to
> distinguish JNI JARS which require a native .so component versus Pure Java JARS
> that require no .so component (/usr/share/java).  For previous products, we
> delivered these same JNI JARS to Solaris systems using the same separation
> mechanism (/usr/lib/java and /usr/share/java).  By maintaining this separate
> location, one can always easily understand that they are looking at a JNI JAR
> versus Pure Java JAR.

OK, history and backward compatibility aside...FHS requires architecture independent files to be in /usr/share. I guess what I would like best is something like /usr/share/java-jni. Still makes it clear it's JNI, but there is nice separation between native and noarch part, plus all the jars are close.

If we are already changing this, I'd like to really get it right. We are already doing major changes so I we'll have to fix packages one way or the other.

> > Note that current guidelines don't have versioned jar files (osutil-2.0.1.jar
> > shouldn't exist).
> > 
> 
> While guidelines may not exist for this for JNI JARS, once again, it is commmon
> usage for Pure Java JARS located under /usr/share/java to use this convention,
> and consequently, we mimic this convention for JNI JARS.

Ok, let me rephrase. We recently (~3-4 months ago) changed the guidelines so we wouldn't have to deal with versioned/unversioned symlinks etc. We only install unversioned jar files. There is no real value as far as I can see in having both. In fact it hinders performance in certain scenarios where tools are walking the filesystem tree (double the amount of work they need to do). It also makes spec files more complicated. Since jars are from rpm files we can still easily query version of each and every file. I would be against reintroducing versioned/unversioned symlinks into the mix. 

> > As for requiring both i686 and x86_64 libraries on x86_64 system. I don't
> > particularly like this (unnecessary dependency if someone has x86_64 only
> > system with no 32bit java), I don't really have a better solution.
> > 
> 
> This was merely an attempt at addressing the following portion of jdennis
> comment #14:

Yes, I understand that and again...not really a big problem IMO.

Comment 35 Matthew Harmsen 2011-03-18 00:00:26 UTC
(In reply to comment #34)
> 
> OK, history and backward compatibility aside...FHS requires architecture
> independent files to be in /usr/share. I guess what I would like best is
> something like /usr/share/java-jni. Still makes it clear it's JNI, but there is
> nice separation between native and noarch part, plus all the jars are close.
> 
> If we are already changing this, I'd like to really get it right. We are
> already doing major changes so I we'll have to fix packages one way or the
> other.
> 

I have no problems with this as it does not complicate placing architecture-independent jars in multiple architecture-dependent locations as was previously suggested.

One question -- could/should the %{_jnidir} macro be changed on Fedora 16 and later to reflect the new location (e. g. - /usr/share/java-jni), or could/should a new macro (e. g. - %{_javajnidir}) be introduced so as to not conflict with the historic use of %{_jnidir} (e. g. - on RHEL platforms)?

> 
> Ok, let me rephrase. We recently (~3-4 months ago) changed the guidelines so we
> wouldn't have to deal with versioned/unversioned symlinks etc. We only install
> unversioned jar files. There is no real value as far as I can see in having
> both. In fact it hinders performance in certain scenarios where tools are
> walking the filesystem tree (double the amount of work they need to do). It
> also makes spec files more complicated. Since jars are from rpm files we can
> still easily query version of each and every file. I would be against
> reintroducing versioned/unversioned symlinks into the mix. 
> 

Sorry, I was unaware that the java jar naming guidelines had been changed.  Do these revised guidelines only correspond to Fedora 16 and later?

Comment 36 Andrew Haley 2011-03-28 11:19:11 UTC
(In reply to comment #30)

> One thing I've ignored in the discussion so far is whether jni .so's have a
> dependency on the specific jvm loading it. In other words can a Sun jvm and an
> OpenJDK jvm both load the same jni.so?

Maybe, because they're the same VM inside, but it would be foolish to depend on it.

Comment 37 Mat Booth 2011-03-28 11:27:13 UTC
(In reply to comment #35)
> > Ok, let me rephrase. We recently (~3-4 months ago) changed the guidelines so we
> > wouldn't have to deal with versioned/unversioned symlinks etc. We only install
> > unversioned jar files. There is no real value as far as I can see in having
> > both. In fact it hinders performance in certain scenarios where tools are
> > walking the filesystem tree (double the amount of work they need to do). It
> > also makes spec files more complicated. Since jars are from rpm files we can
> > still easily query version of each and every file. I would be against
> > reintroducing versioned/unversioned symlinks into the mix. 
> > 
> 
> Sorry, I was unaware that the java jar naming guidelines had been changed.  Do
> these revised guidelines only correspond to Fedora 16 and later?


There are packages in Fedora 15 that follow the new guidelines. It's not enforced with an iron fist, just the next time you update your packages is fine. :-)

Comment 38 Stanislav Ochotnicky 2011-07-04 14:36:20 UTC
So I decided to bite the bullet and did changes that will break things I am sure:

%_jnidir is now %_libdir/java
%_javajnidir is new addition for noarch jars using arch-specific bits from %_jnidir

build-classpath has been changed to resolve from this new directory as well. 
Maven is also resolving from _jnidir and _javajnidir (it didn't before). 

This change will break builds and in a few cases patches will need to be created to fix them. I've tested with osutil. I had to fix cmake->
-    "${CMAKE_INSTALL_PREFIX}/lib/java"
+    "${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}/java"

And that was it. I would be really interested how many things broke because of these changes. 

If we can make this work (which I believe shouldn't be that hard), we can modify our current guidelines to reflect these changes. In next 2 weeks I'll go through packages that have files in /usr/lib/java and rebuild them, and also look at packages that depend on these. I won't be around much because of holidays for next few days, so if anyone would look into it before me: great!

Comment 39 Matthew Harmsen 2011-08-30 21:55:31 UTC
(In reply to comment #38)
> So I decided to bite the bullet and did changes that will break things I am
> sure:
> 
> %_jnidir is now %_libdir/java
> %_javajnidir is new addition for noarch jars using arch-specific bits from
> %_jnidir
> 
> build-classpath has been changed to resolve from this new directory as well. 
> Maven is also resolving from _jnidir and _javajnidir (it didn't before). 
> 
> This change will break builds and in a few cases patches will need to be
> created to fix them. I've tested with osutil. I had to fix cmake->
> -    "${CMAKE_INSTALL_PREFIX}/lib/java"
> +    "${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}/java"
> 
> And that was it. I would be really interested how many things broke because of
> these changes. 
> 
> If we can make this work (which I believe shouldn't be that hard), we can
> modify our current guidelines to reflect these changes. In next 2 weeks I'll go
> through packages that have files in /usr/lib/java and rebuild them, and also
> look at packages that depend on these. I won't be around much because of
> holidays for next few days, so if anyone would look into it before me: great!

QUESTION:  So, using 'osutil' with your proposed 'cmake' change as an example
           for Fedora 16 and later, are you expecting "Layout A", "Layout B",
           "Layout C", "Layout D", or something else?

Original Layout:

    32-bit:
    
    /usr/lib/java/osutil.jar -> /usr/lib/osutil/osutil.jar
    /usr/lib/osutil/
    /usr/lib/osutil/libosutil.so
    /usr/lib/osutil/osutil-2.0.1.jar
    /usr/lib/osutil/osutil.jar -> osutil-2.0.1.jar


    64-bit:
    
    /usr/lib/java/osutil.jar -> /usr/lib64/osutil/osutil.jar
    /usr/lib64/osutil/
    /usr/lib64/osutil/libosutil.so
    /usr/lib64/osutil/osutil-2.0.1.jar
    /usr/lib64/osutil/osutil.jar -> osutil-2.0.1.jar


Layout A (identical for 32-bit;
          relocates jar symlink for 64-bit;
          no java code changes):

    32-bit:
    
    /usr/lib/java/osutil.jar -> /usr/lib/osutil/osutil.jar
    /usr/lib/osutil/
    /usr/lib/osutil/libosutil.so
    /usr/lib/osutil/osutil-2.0.1.jar
    /usr/lib/osutil/osutil.jar -> osutil-2.0.1.jar


    64-bit:
    
    /usr/lib64/java/osutil.jar -> /usr/lib64/osutil/osutil.jar
    /usr/lib64/osutil/
    /usr/lib64/osutil/libosutil.so
    /usr/lib64/osutil/osutil-2.0.1.jar
    /usr/lib64/osutil/osutil.jar -> osutil-2.0.1.jar


Layout B (replaces jar symlink with jar;
          relocates jar for 64-bit;
          removes versioned jar + jar symlink;
          no java code changes):

    32-bit:
    
    /usr/lib/java/osutil.jar
    /usr/lib/osutil/
    /usr/lib/osutil/libosutil.so


    64-bit:
    
    /usr/lib64/java/osutil.jar
    /usr/lib64/osutil/
    /usr/lib64/osutil/libosutil.so


Layout C (adds javajnidir symlink;
          replaces jar symlink with jar;
          relocates jar for 64-bit;
          removes versioned jar + jar symlink;
          no java code changes):

    32-bit:
    
    /usr/share/java-jni/osutil.jar -> /usr/lib/osutil/osutil.jar
    /usr/lib/java/osutil.jar
    /usr/lib/osutil/
    /usr/lib/osutil/libosutil.so


    64-bit:
    
    /usr/share/java-jni/osutil.jar -> /usr/lib64/osutil/osutil.jar
    /usr/lib64/java/osutil.jar
    /usr/lib64/osutil/
    /usr/lib64/osutil/libosutil.so


Layout D (adds javajnidir symlink;
          relocates jar symlink for 64-bit;
          removes versioned jar;
          replaces jar symlink with jar;
          no java code changes):

    32-bit:

    /usr/share/java-jni/osutil.jar -> /usr/lib/osutil/osutil.jar    
    /usr/lib/java/osutil.jar -> /usr/lib/osutil/osutil.jar
    /usr/lib/osutil/
    /usr/lib/osutil/libosutil.so
    /usr/lib/osutil/osutil.jar


    64-bit:

    /usr/share/java-jni/osutil.jar -> /usr/lib64/osutil/osutil.jar    
    /usr/lib64/java/osutil.jar -> /usr/lib64/osutil/osutil.jar
    /usr/lib64/osutil/
    /usr/lib64/osutil/libosutil.so
    /usr/lib64/osutil/osutil.jar

Comment 40 Stanislav Ochotnicky 2011-08-31 09:29:23 UTC
Since %{_javajnidir} (/usr/share/java-jni/) is supposed to be used for jar files that use JNI jars and they are not using JNI themselves and are architecture agnostic, options C and D are not good. That's because osutil.jar directly uses JNI calls. 

It should therefore place jar file into %{_jnidir} (/usr/lib[64]/java). I like option B better because it has less clutter, but both A and B could be used, depending on the wishes of maintainer. That's because they both keep multilib OK. Personally I'd prefer B since it has less work for packager I'd say (no symlinks to deal with).

Does this make sense at all? Best example of javajnidir I've seen is jansi-native package. The package has 2 jars: one is completely noarch, the other contains *so file inside. But the noarch jar is still useless without the arch jar.

FYI I later found out it was enough to do:
-%cmake -DBUILD_OSUTIL:BOOL=ON ..
+%cmake -DBUILD_OSUTIL:BOOL=ON -DJAVA_LIB_INSTALL_DIR=%{_jnidir} ..

when building osutil to fix jar placing.

Comment 41 Matthew Harmsen 2011-08-31 18:09:54 UTC
(In reply to comment #40)
> Since %{_javajnidir} (/usr/share/java-jni/) is supposed to be used for jar
> files that use JNI jars and they are not using JNI themselves and are
> architecture agnostic, options C and D are not good. That's because osutil.jar
> directly uses JNI calls. 
> 
> It should therefore place jar file into %{_jnidir} (/usr/lib[64]/java). I like
> option B better because it has less clutter, but both A and B could be used,
> depending on the wishes of maintainer. That's because they both keep multilib
> OK. Personally I'd prefer B since it has less work for packager I'd say (no
> symlinks to deal with).
> 

B is fine -- this means that these legacy packages will not use %{_javajnidir} at all -- and hopefully everything will work -- although I think that I may need to alter some wrappers that we use for some of our command line tools to perform the search correctly, as I believe that these may not use "build-classpath".

> Does this make sense at all? Best example of javajnidir I've seen is
> jansi-native package. The package has 2 jars: one is completely noarch, the
> other contains *so file inside. But the noarch jar is still useless without the
> arch jar.
> 
> FYI I later found out it was enough to do:
> -%cmake -DBUILD_OSUTIL:BOOL=ON ..
> +%cmake -DBUILD_OSUTIL:BOOL=ON -DJAVA_LIB_INSTALL_DIR=%{_jnidir} ..
> 
> when building osutil to fix jar placing.

Awesome.  This is far more elegant and easier to implement.

Comment 42 Matthew Harmsen 2011-09-02 22:21:09 UTC
(In reply to comment #38)
> So I decided to bite the bullet and did changes that will break things I am
> sure:
> 
> %_jnidir is now %_libdir/java
> %_javajnidir is new addition for noarch jars using arch-specific bits from
> %_jnidir
> 
> build-classpath has been changed to resolve from this new directory as well. 
> Maven is also resolving from _jnidir and _javajnidir (it didn't before). 
> 
> This change will break builds and in a few cases patches will need to be
> created to fix them. I've tested with osutil. I had to fix cmake->
> -    "${CMAKE_INSTALL_PREFIX}/lib/java"
> +    "${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}/java"
> 
> And that was it. I would be really interested how many things broke because of
> these changes. 
> 
> If we can make this work (which I believe shouldn't be that hard), we can
> modify our current guidelines to reflect these changes. In next 2 weeks I'll go
> through packages that have files in /usr/lib/java and rebuild them, and also
> look at packages that depend on these. I won't be around much because of
> holidays for next few days, so if anyone would look into it before me: great!

rmeggins discovered that this broke the old behavior of a JNI jar located under '/usr/lib/java' on a 64-bit platform;  although he was able to manually move the 'jss4.jar' file that he needed under '/usr/lib64/java' to make it work, shouldn't the correct behavior of this fix be to first look in the new '/usr/lib/java-jni' directory, followed by looking in the "/usr/lib64/java" directory, AND then finally in "/usr/lib/java" for JNI jars?

I believe that this method would allow things to continue to work until such time as all JNI packages can be changed to conform with this new layout.

Comment 43 Matthew Harmsen 2011-09-02 22:25:25 UTC
(In reply to comment #42)
> (In reply to comment #38)
> > So I decided to bite the bullet and did changes that will break things I am
> > sure:
> > 
> > %_jnidir is now %_libdir/java
> > %_javajnidir is new addition for noarch jars using arch-specific bits from
> > %_jnidir
> > 
> > build-classpath has been changed to resolve from this new directory as well. 
> > Maven is also resolving from _jnidir and _javajnidir (it didn't before). 
> > 
> > This change will break builds and in a few cases patches will need to be
> > created to fix them. I've tested with osutil. I had to fix cmake->
> > -    "${CMAKE_INSTALL_PREFIX}/lib/java"
> > +    "${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}/java"
> > 
> > And that was it. I would be really interested how many things broke because of
> > these changes. 
> > 
> > If we can make this work (which I believe shouldn't be that hard), we can
> > modify our current guidelines to reflect these changes. In next 2 weeks I'll go
> > through packages that have files in /usr/lib/java and rebuild them, and also
> > look at packages that depend on these. I won't be around much because of
> > holidays for next few days, so if anyone would look into it before me: great!
> 
> rmeggins discovered that this broke the old behavior of a JNI jar located under
> '/usr/lib/java' on a 64-bit platform;  although he was able to manually move
> the 'jss4.jar' file that he needed under '/usr/lib64/java' to make it work,
> shouldn't the correct behavior of this fix be to first look in the new
> '/usr/lib/java-jni' directory, followed by looking in the "/usr/lib64/java"
> directory, AND then finally in "/usr/lib/java" for JNI jars?
> 
> I believe that this method would allow things to continue to work until such
> time as all JNI packages can be changed to conform with this new layout.

Also, wouldn't this be necessary anyway in case an individual is running a 32-bit JVM on a 64-bit platform, or does jpackage-utils check for the bitness of the JVM?

Comment 44 Alexander Kurtakov 2011-10-07 14:24:33 UTC
Closing the bug as build-classpath swt works now. Please open other bugs to keep bugs on topic, there is simply too much in this one.


Note You need to log in before you can comment on or make changes to this bug.