User:Aslantis/Cross compiling openjdk
I really recommend you to read the following pages before proceeding: Official OpenJDK building documentation & Arthurzam's guide to boostrapping OpenJDK
This is a guide to cross compile openjdk to a new architecture or libc. First, make sure your architecture/OS combo is supported by openjdk and by the specific version of openjdk you're building (TODO: more on that). This guide will use openjdk-11 for sparc64/linux as an example. In fact, if you copy this guide verbatim, you should have a working sparc64 build \o/. You can follow this guide on any gentoo install that has easy access to a pre built jdk, but for this example I used a fresh amd64 stage3.
We will be using crossdev to install our cross compilation toolchains.
emerge dev-java/openjdk-bin:11 sys-devel/crossdev
crossdev -S -t sparc64-unknown-linux-gnu
This will install our cross compilation toolchains. Note that when building java normally, you can build with one lower version, but when cross compiling, try to have the build and target versions as close as possible.
Next, we clone the source. The most convenient way to get the same source gentoo's ebuilds use (including our patches!) is with the `ebuild` command.
ebuild /var/db/repos/gentoo/dev-java/openjdk/openjdk-11.0.15_p10-r1.ebuild prepare
TODO: use the proper env vars instead of default path
Starting the build
Like I said in the banner above, read the official documentation on cross compiling. I won't explain what I'm doing here, as you should take a look at that anyways. And remember, for your 'tuple', use the exact same string that you gave to crossdev above ;p
bash configure --openjdk-target=sparc64-unknown-linux-gnu --disable-warnings-as-errors
bash configure --openjdk-target=sparc64-unknown-linux-gnu --disable-warnings-as-errors #idk why but when trying to put in a code block it shows an error
I also recommend you to read the help page for additional options. For example, you can change c/c++ flags, or you can build a more bare bones JDK if you like. The less code you have to compile, the less chance to run into a build error ;)
bash configure --help
If it fails on configure, figure out why. Crossdev should have installed a full toolchain prefixed by your specified tuple. Try compiling a hello world with it, and see if it runs on the target.
Next, we're on to the exciting part! :D
Chances are, you are going to run into build failures. These should be minimized using the source provided by ebuild prepare: you will be working with a branch that gets backports upstream, in addition to any gentoo specific patches. But regardless, errors happen. Google is your friend. For this example of building openjdk-11 to sparc64, I did need to apply a patch from this bug: https://bugs.openjdk.org/browse/JDK-8230708
mv 9fba708740d6 sparcy.patch
patch -p1 <sparcy.patch
Both openjdk and other distributions likely have patches attached to their bugtrackers. If you need help, feel free to hop onto our IRC and we'll try to help :)
Ngl, I have no idea, but if you copy over the whole build/linux-sparcv9-normal-server-release folder to your target, everything seems to work. I bet you there's a better way tho :p
Using this to emerge the real deal
You can add the jdk/bin folder into your $PATH. Set $JAVA_HOME to the location of jdk. Then, accept the keywords for openjdk (and its deps!). Note that this worked for me: your mileage may vary.
- Install all the deps of openjdk EXCEPT eselect-java with --onlydeps
- Run ebuild /path/of/openjdk/ebuild prepare
- Re apply any patches you had to apply for the original bootstrap
- Run ebuild /path/of/openjdk/ebuild install
That does not install it to the system, just a prefix. Check it out and see if it has any problems, before running ebuild merge :D
If it worked, emerge eselect-java.
Sending patches upstream
You have no idea how annoying this was. TLDR: to submit a patch, it has to be tied to a bug on the JBS (Jdk Bug System). You cannot open a bug on the JBS: Only registered java developers can. Want to report a bug?? Your best chance is in the OpenJDK mailing lists. To actually submit a patch for an unresolved bug, or backport a patch for a resolved bug to an earlier version of the JDK, here are the steps:
- The right repo to send a PR in is <https://github.com/openjdk/jdk11u-dev/>. Replace the '11' with the JDK version you want.
- You have to sign the OCA (Oracle Contributor Agreement). Yes, even if you're backporting an existing patch. This requires an Oracle account and can be done (here).
- They will make you re-send your PR if your PR is based off of the 'master' branch in your fork. Create a new branch named whatever you like.
- The name of your bug must be the name of your bug number suffixed by the name of the bug in the JBS. Example: " 8230708: Hotspot fails to build on linux-sparc with gcc-9"
- If backporting an existing patch, find the sha1 of the commit for that patch. What I did was clone openjdk/jdk and use this command:
git log --all --grep='8230708'. Then rename your PR
Backportthen the sha1 of that commit.
- You will need to sign an additional terms of service to comment on a PR (including your own).
- Follow the instructions from the bot. You will need a sponsor to look-over your PR and merge it.
Hopefully everything goes well, I know this can be an irritating process, but keep with it!
Creating a bootstrap tarball
Now it should be easy to create a bootstrap tarball. If the bootstrap tarball is created before your patch is included in a new version of openjdk, you will have to replace the SRC_URI in the ebuild to one that has your patch applied. With github you can get a tarball for almost every commit, so this isn't too difficult.
Make sure to change your C/C++ flags to remove -march/-mcpu! It is also probably a good idea to stick with -O2.
A full guide is located here. I will just outline the exact commands I used:
I may have forgotten to document some steps I took, or link some resources I used. Regardless, I need sleep, will update eta soon. Ping me on IRC if you need any help :D