Wednesday, 24 December 2008
Building 32-bit OpenJDK on 64-bit Red Hat Enterprise Linux 5.2
In the next few weeks, I’ll be posting some shorter, more technical entries like this one—more related to Linux/Java/Python stuff rather than the Mac, as I’m spending most of my time in that world. As I’ll soon be embarking on dissertation writing, I can use the practice.
Our research machines were recently updated to 64-bit Red Hat Enterprise Linux 5.2. I used this opportunity to get rid of a bunch of locally built software sitting in my home directory, though I still must install my own Python, Emacs and (32-bit) Java.
On the day of the upgrade, everything moved over smoothly, to my surprise. Several weeks passed. Then a few days ago I promptly crashed the machine with OpenJDK on it by trying to reboot it in uniprocessor mode. Nobody’s around to poke the power button and I’m not back for a few weeks, so I have to rebuild all of OpenJDK, not just HotSpot, on another machine. This, like previous adventures building OpenJDK, has not exactly been fun.
Now, OpenJDK doesn’t really do cross-compilation—at least, it’s not well-tested. The best reference I found online was this message from last December, which provides a bizarrely formatted patch (what kind of pathname style is that?). Some files have moved around since then and some newer pieces of OpenJDK doesn’t seem to reference any of the variables set by it. I therefore used a combination of an updated patch and some brute force workarounds to get OpenJDK built.
The following packages provide libraries OpenJDK links against:
glibc-devel.i386 libstdc++-devel.i386 alsa-lib-devel.i386 libXi-devel.i386
You’ll also need a 32-bit bootstrap JDK; I used Sun Java 6 Update 11 installed with JPackage (which required hacking the spec file because the RPM version on RHEL5 doesn’t support architecture specification…).
Finally, I needed to build a 32-bit FreeType 2.3.x, which was a simple
CC="gcc -m32" ./configure --prefix=../freetype; make install
away.
Since I build OpenJDK somewhat often, I defined a shell alias which sets up all the necessary variables:
njobs=$(( 3 * $(grep -c processor /proc/cpuinfo) / 2 )) alias ojmake='LANG=C JAVA_HOME= LD_LIBRARY_PATH= CPPFLAGS= LDFLAGS= '\ 'ALT_FREETYPE_LIB_PATH='$SCRATCH'/openjdk/freetype/lib '\ 'ALT_FREETYPE_HEADERS_PATH='$SCRATCH'/openjdk/freetype/include '\ 'make DEV_ONLY=true BUILD_DEPLOY=false '\ 'ALT_PARALLEL_COMPILE_JOBS='$njobs' HOTSPOT_BUILD_JOBS='$njobs
Note I’m mostly sanitizing my environment there so it doesn’t try to link against software installed in my home directory. You’ll need to substitute the paths to the FreeType version you built.
OpenJDK then compiles with this patch and ojmake ARCH_DATA_MODEL=32 CC="gcc -m32" CXX="g++ -m32". The latter two variables should not be necessary, but certain bits of OpenJDK (such as the new FreeType-based font renderer) don’t seem to listen to ARCH_DATA_MODEL=32.
If you get a message such as:
ERROR: FreeType version 2.3.0 or higher is required. make[2]: Entering directory `.../openjdk/jdk7/jdk/make/tools/freetypecheck' Required version of freetype: 2.3.0 Detected freetype headers: 2.3.7 Detected freetype library: 2.2.1 Failed: too old library.
despite the fact that you do have these versions installed, you need to make clean (make sure to do so with the right flags otherwise it’ll just clean the 64-bit object dir!). Otherwise, freetype_versioncheck won’t be rebuilt, instead reporting the same wrong answer.
Bonus: the zsh function I used to generate the patch above from a Mercurial forest.
fdiff() { local -a trees trees=($(hg ftrees)) local prefix=${trees[0]} for i ("" ${trees/$prefix}) ( # substitution collapses empty items cd $prefix/$i hg di --no-color | perl -pe 's|( [ab])/|$1'$i'/|g if /^(diff|---|\+\+\+)/' ) }