FS#41883 - [java-common] Include the symlinks in the package!

Attached to Project: Arch Linux
Opened by I Said Socks (socks) - Tuesday, 09 September 2014, 03:10 GMT
Last edited by Guillaume ALAUX (galaux) - Sunday, 12 October 2014, 20:48 GMT
Task Type Bug Report
Category Packages: Extra
Status Closed
Assigned To Guillaume ALAUX (galaux)
Architecture All
Severity Medium
Priority Normal
Reported Version
Due in Version Undecided
Due Date Undecided
Percent Complete 100%
Votes 4
Private No

Details

Description:

The java-common package leaves the following (and more) symlinks untracked:

/usr/bin/java
/usr/bin/jjs
/usr/bin/keytool
/usr/bin/orbd
/usr/bin/pack200
/usr/bin/policytool
/usr/bin/rmid
/usr/bin/rmiregistry
/usr/bin/servertool
/usr/bin/tnameserv
/usr/bin/unpack200

/usr/lib/jvm/default
/usr/lib/jvm/default-runtime
/usr/lib/jvm/java-default-runtime

They're created by `/usr/bin/archlinux-java fix` in the install scriptlet.
This is a very dirty approach, and is in fact _broken_.
What if there is a existing file, for example, /usr/bin/keytool that is part of another package? It would be silently overwritten!

Also, what's the point of the /usr/lib/java-common-wrapper script? Why can't we just add /usr/lib/jvm/default to the PATH in /etc/profile.d/jre.sh and get rid of all the bin links?

Then java-common would only have to include the symlink /usr/lib/jvm/default in the package, and make the jre* packages change this symlink at install time.
This task depends upon

Closed by  Guillaume ALAUX (galaux)
Sunday, 12 October 2014, 20:48 GMT
Reason for closing:  Implemented
Additional comments about closing:  Implemented in java-runtime-common and java-environment-common 2-1
Comment by Guillaume ALAUX (galaux) - Tuesday, 09 September 2014, 08:38 GMT
> What if there is a existing file, for example, /usr/bin/keytool that is part of another package? It would be silently overwritten!
As explained in the wiki [0] packages providing JVM are asked "Not provide any link on /usr/bin, these are automatically detected and set by archlinux-java". So no existing file would be overwritten. Also pacman does not overwrites files. Insatll scriptlets would just fail!

[0] https://wiki.archlinux.org/index.php/Java#Package_pre-requisites_to_support_archlinux-java

> Also, what's the point of the /usr/lib/java-common-wrapper script
Please read the wiki page I linked especially the "One time setup" section.

> Why can't we just add /usr/lib/jvm/default to the PATH in /etc/profile.d/jre.sh and get rid of all the bin links?
This is another approach but I did not go in favor of it. This simple archlinux-java looked nicer to me. But I am still open to constructive – though late [1] – feedback.

[1] https://mailman.archlinux.org/pipermail/arch-general/2014-May/036410.html

Still, in your solution, I don't get where the "fixed" link /usr/lib/jvm/default should point at now that you include it to the java-common package. Maybe you could sum it up in a java-common version of your own and share it here?
Comment by I Said Socks (socks) - Tuesday, 09 September 2014, 10:00 GMT
> As explained in the wiki [0] packages providing JVM are asked "Not provide any link on /usr/bin, these are automatically detected and set by archlinux-java". So no existing file would be overwritten.

It's not only packages providing JVM. Some other package _may_ have installed a file under /usr/bin such as /usr/bin/keytool or /usr/bin/servertool (esp. such generic names!)

> Also pacman does not overwrites files.

Yes, but only if those files being dumped into /usr/bin are actually tracked by pacman, which is not the case.

> Insatll scriptlets would just fail!

This is not true. Your archlinux-java script uses `ln -sf` to force overwrite the /usr/bin/* files, there will be no warning whatsoever.

> Still, in your solution, I don't get where the "fixed" link /usr/lib/jvm/default should point at now that you include it to the java-common package.

From the wiki you linked,
> Use script archlinux-java in install functions to set the Java environment as default if no other valid Java environment is already set

This is to say whichever random jre* package is installed first gets to set the link /usr/lib/jvm/default. While I don't quite like this, to answer your question, I think the /usr/lib/jvm/default file in the java-common package can either be a symlink to /dev/null or an empty file.


Apart from the whole complication of this whole thing, my main point against the current java-common / jre* packages is the whole bunch of untracked /usr/bin/* symlinks.
Are all those "bin" names predictable? If it's possible to get an exhaustive list of them, the easy solution would be simply to add those links to the java-common package. In fact, you don't even need to get an exhaustive list, the unsupported jre* packages can ship their own additional links. This is the easiest way to make the package "correct".
Comment by Guillaume ALAUX (galaux) - Tuesday, 09 September 2014, 10:13 GMT
Hum… I still don't get many points in what you propose. Can you please put together a java-common of you own to show your solution implemented. As you can see this package is fairly simple, just the archlinux-java script and an install scriptlet (I am not event counting the java wrapper: it's one line).
Comment by I Said Socks (socks) - Tuesday, 09 September 2014, 10:40 GMT
Something like:

--- a/PKGBUILD
+++ b/PKGBUILD
@@ -31,9 +31,15 @@ check() {
./test_archlinux-java
}

-build() {
- cd "${srcdir}"

+package() {
+ ln -s /dev/null "$pkgdir"/usr/lib/jvm/default
+ ln -s /dev/null "$pkgdir"/usr/lib/jvm/default-runtime
+ local f
+ for f in java keytool pack200 rmid servertool unpack200 jjs orbd \
+ policytool rmiregistry tnameserv; do
+ ln -s /usr/lib/java-common-wrapper "$pkgdir/usr/bin/$f"
+ done
install -D -m 644 profile_jre.sh "${pkgdir}/etc/profile.d/jre.sh"
install -D -m 644 profile_jre.csh "${pkgdir}/etc/profile.d/jre.csh"
install -D -m 755 bin_java-common-wrapper "${pkgdir}/usr/lib/java-common-wrapper"


You may need to change your archlinux-java script / jre* packages' install scriptlet if they don't properly check the validity of the link already.

EDIT: If we go with this, the {,un}set_bin_links functions should be removed from the archlinux-java script, obviously.
Comment by Guillaume ALAUX (galaux) - Wednesday, 10 September 2014, 11:02 GMT
I understand you point of view but I gave up on this solution because of several reasons.

First of all it would require 3 packages (one for jre-headless, one for jre and one for jdk – see intermediate solution [0]) which in the end I found to be heavier than just one "dynamic".
But mainly this does not solve the fact that different JVM versions and vendors provide a different binary set. For instance, JDK for OpenJDK 8 has binaries jdeps and jjs that OpenJDK 7 doesn't. JDK for Oracle 8 has these but also has a jmc that none of OpenJDK 7 nor 8 has. Also in Oracle 8, jcontrol is actually named ControlPanel. As you can see on the intermediate PKGBUILD [0] I then came up with a minimum list of common binaries to be provided by JVM packages, supplementary binaries would then be provided by each JVM package. But then one could have set say OpenJDK7 but still have this jmc binary comming from Oracle 8. This would be inconsistent.

Don't take me wrong: I am not trying to invalidate your solution at all cost. I'm really considering including these links to the package if we happen to find a nice solution but I would just like to show you that there are a lot of complications that need to be addressed here.

[0] https://github.com/galaux/java-meta/blob/heftig_way/PKGBUILD
Comment by I Said Socks (socks) - Wednesday, 10 September 2014, 11:35 GMT
Looks like the plethora of JVM packages aren't compatible enough for us to get a fine list of bin symlinks.
Maybe it's better to go back and reconsider this symlink approach. Say, we simply ship a /etc/profile.d/jre.sh wherein we add a valid jre path to PATH. We should not have to consider unsupported jre/jdk packages, but merely check for known supported pathes in jre.sh, one by one starting from e.g. the latest version, and add the first present on the filesystem to PATH. The user can nevertheless choose explicitly by editing jre.sh, or set PATH temporarily.

This is not much worse than the current interface anyway -- the symlink /usr/lib/jvm/default is set by the first JVM package only, if the user wants to change the "default" path, he will have to run `archlinux-java set ...` as root, which is not much different from editing /etc/profile.d/jre.sh by hand.

EDIT: I'm proposing removing archinux-java and java-common-wrapper entirely from the java-common package, as well as removing the call to archlinux-java from the install scriptlets of the jre/jdk packages. For anyone who wants to use multiple versions of java environments, simply modify your PATH (in /etc/profile.d/jre.sh if you want it permanent). What java-common can do as a little extra "dynamic" help is something like this, in jre.sh:

# Add a valid JVM bin path to PATH
if [ -d "/usr/lib/jvm/java-8-openjdk/jre/bin" ]; then
PATH=$PATH:"/usr/lib/jvm/java-8-openjdk/jre/bin"
elif [ -d "/usr/lib/jvm/java-7-openjdk/jre/bin" ]; then
PATH=$PATH:"/usr/lib/jvm/java-7-openjdk/jre/bin"
fi

# Enable this for non-reparenting window managers
#export _JAVA_AWT_WM_NONREPARENTING=1

Add more valid paths in the same fashion, to support some more jre packages. Any comments?
Comment by Guillaume ALAUX (galaux) - Sunday, 14 September 2014, 08:30 GMT
I wanted to avoid the "PATH solution" as links from /usr/bin looked more reliable but in this situation I guess this would be usefull. It would make the java-common-wrapper disappear which actually might not be a bad idea. A lot of upstream projects try to find out where is the JVM installed and get tricked by it.
Instead of setting it by hand in jre.sh as you suggest, I could stick with PATH:$PATH:/usr/lib/jvm/default/bin and "/usr/lib/jvm/default" be set by archlinux-java. I am going to fix a package with this for test.
Comment by I Said Socks (socks) - Sunday, 14 September 2014, 08:45 GMT
Yes, that would be reasonable. The archlinux-java script needs a little adjustment, accordingly.
Comment by Guillaume ALAUX (galaux) - Sunday, 14 September 2014, 12:40 GMT
Hum… using this PATH solution, all automatic build (such as Arch Linux packages) that require a JVM will fail as they do not source jre.sh. Unless they manually set "PATH=$PATH:…" wich I would like to avoid.
Comment by I Said Socks (socks) - Sunday, 14 September 2014, 16:20 GMT
That I believe is an inherent problem with supporting all JVM versions without defaulting to an offically supported version. As discussed before, the binaries that are provided by different versions of JVM are not reasonably consistent.
BUT, on the other hand, if these relevant packages which require JVM to build only need _a_ JVM, doesn't it mean they only require a limited set of binaries to be in PATH? Maybe just `java`? You know the answer better than I. Following this line of thought, maybe java-common can ship a symlink /usr/bin/java -> /usr/lib/jvm/default/bin/java for example?

Alternatively, can't you append /usr/lib/jvm/default/bin to PATH in makepkg.conf on the buld machine?

EDIT: I think it's a good idea take perl as an analogy here. For example, some packages require `pod2man` to build man pages, but pod2man is in /usr/bin/core_perl/ -- which is only appended to PATH in /etc/profile.d/perlbin.sh. This is basically the same situation with jre.sh, except that perl is part of the base group, so you can safely expect it to be installed permanently on the build machine.
Comment by Guillaume ALAUX (galaux) - Tuesday, 23 September 2014, 19:38 GMT
There is no particular "build machine" other than every Arch env where this package should build "out of the box".

Inspired by what you described, I came up with this version [0]. Instead of only shipping a "java" link, I went for the intersection of binaries between OpenJDK and Oracle 7 and 8. I had to rename "java-common" to "java-runtime-headless-common" and create a "java-environment-common". The first one ships a "PATH=$PATH:/usr/lib/jvm/default/bin" to make extra binaries available on the next "source" of profile files. Also the java-wrapper script is abandonned as it brings more troubles than it solves.

These packages are available here [1].

[0] https://github.com/galaux/java-common
[1] http://pkgbuild.com/~guillaume/repos/jdk/x86_64/
Comment by I Said Socks (socks) - Tuesday, 23 September 2014, 20:23 GMT
Doesn't look bad.
Have you considered putting /usr/lib/jvm/default{-runtime} in the package as well? They can be empty regular files, or symlinks to /dev/null or to a (possibly non-existent) default Java directory; shouldn't have any drawback, right?
Comment by Guillaume ALAUX (galaux) - Wednesday, 24 September 2014, 12:16 GMT Comment by Guillaume ALAUX (galaux) - Wednesday, 24 September 2014, 12:33 GMT
These packages are available here [0]. To install them, you will need to

Either:
pacman -Sy --force --asdeps java-runtime-headless-common java-environment-common
archlinux-java fix

Or
before upgrading:
archlinux-java unset
then:
pacman -Syu

I see 3 other users voted for this bug: I would love to see all your feedback on testing this.

[0] http://pkgbuild.com/~guillaume/repos/jdk/
Comment by Guillaume ALAUX (galaux) - Sunday, 12 October 2014, 20:47 GMT
Thanks anyway.

Loading...