This blog describes how to build both, a 64-bit and a 32-bit version of OpenJDK 8 on a plain, vanilla WindowsXP 64-bit operating system using only free (as in free beer) tools.
There are several tutorials out there which explain in more or less detail how to build OpenJDK on Windows. The problem with most of them is that they are either outdated (will happen with this blog as well:) or they use compilers which either aren't available anymore or which are not free. This blog will describe how to build both, a 64-bit and a 32-bit version of OpenJDK 8 on a plain, vanilla WindowsXP 64-bit operating system using only free (as in free beer) tools.
Unfortunately, building OpenJDK on Windows is still far away from being straightforward as can be seen from the regular desperate help requests on the OpenJDK mailing lists. This has many reasons and I neither want to discuss them nor do I want to blame anybody for this fact. Instead I hope this post can help to improve the OpenJDK build documentation and perhaps even the build process itself.
As stated above, I started with a fresh, 64-bit WindowsXP installation. In fact I used a VmWare-Image in Oracle VirtualBox 4.1.4 on 64-bit Ubuntu 10.04 and in the VmWare Player 3.1.4 on 64-bit Windows 7. The first step was to install the free Microsoft C/C++ compilers and various dependencies required by OpenJDK. If not mentioned otherwise, I've installed all the packages mentioned here in the default location that was suggested by the respective installers.
Download and install the free VisualC++ 2010 Express compilers from: http://www.microsoft.com/visualstudio/en-us/products/2010-editions/visual-cpp-express. Notice that this will require the installation of the "Windows Imaging Component (64-bit)" which is not present in a clean XP installation, but the VisualC++ installer will point you to the right URL from where you can get it (just for any case, here's where I finally downloaded it from: http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=1385).
Unfortunately, the "VisualC++ 2010 Express" package only contains 32-bit compilers. So if we want to build a 64-bit JVM we have to additionally install the "Windows SDK for Windows 7 and .Net" from http://www.microsoft.com/download/en/details.aspx?id=8279. (Notice that the Windows SDK now also contains the Itanium cross compiler. So should there be a native IA64 port in the OpenJDK anytime soon, it will be possible to build it with this setup as well:)
Another build requirement is the "Microsoft DirectX 9.0 SDK header files and libraries". It can be easily installed from http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=21416but be sure to check the corresponding Microsoft DirectX section in the OpenJDK Readme in the case the required version changed.
To get the OpenJDK source code, we need a Mercurial client. TortoiseHg is an easy to install Mercurial distribution for Windows which can be downloaded from http://tortoisehg.bitbucket.org/download. The installation step will updated the system path automatically.
As bootstrap JDK for a JDK8 build we need at least a JDK7. So download and install a Java 7 JDK from http://www.oracle.com/technetwork/java/javase/downloads/index.html. Notice that it is very important to install the JDK into a directory WITHOUT spaces (for this blog I'll use c:\OpenJDK\jdk1.7.0_01)!!! It is not necessary to install an extra JRE as part of the JDK installation! After the installation add the path to the java executable to the PATH environment variable (underStart->Control Panel->System->Advanced->Environment Variables->System Variables->).
The Ant build system is needed for parts of the JDK class library build. It can be downloaded (as .zip file) from http://ant.apache.org/bindownload.cgiand simply unpacked into a directory which contains no white space (for this blog I use c:\OpenJDK\apache-ant-1.8.2). Afterwards, the path to the ant executable (c:\OpenJDK\apache-ant-1.8.2\bin) should be added to the system wide PATH environment variable as explained in the previous step.
Now comes the little tricky part of the setup. Because the JDK was initially developed in a Unix kind of environment, its build still relies on that. In order to build it on Windows we have to emulate such an environment with the help of the Cygwin system.
Cygwin can be installed by launching the http://cygwin.com/setup.exe from the Cygwin home page. Choose the default base installation plus the packages described in the OpenJDK Readme (ar.exe, make.exe, m4.exe, cpio.exe, gawk.exe,file.exe, zip.exe, unzip.exe, free.exe, ). Notice that they can be easily located by typing their names into the Search field of the Cygwin Setup program.
In addition we also have to install the GCC-base package to compile GNU make in the next step.
Cygwin now comes with GNU make 3.82.90 which should compile OpenJDK just fine, but of course you can still comile the newest version yourself because There's an issue with GNU make 3.81 and the new 3.82.90 which is included in the current Cygwin distribution. It has problems with drive letters in Windows path names and to make a long story short - it will not work with the current OpenJDK build. For some unknown reasons the Cygwin GNU makemaintainer refuses to has integrate the new version 3.82 of GNU make into the standard Cygwin distribution, but it is configured in such a way that it still doesn't support drive letters in path names. Fortunately it is however very easy to compile a private version ofGNU make 3.82 which supports drive letters.
Download and unpack GNU make 3.82 fromhttp://ftp.gnu.org/gnu/make/(for this tutorial I'll put it to c:\OpenJDK\make-3.82). Then execute the following commands in a Windows command shell:
c:\cygwin\bin\bash.exe cd /cygdrive/c/OpenJDK/make-3.82 ./configure make
The last command will build c:\OpenJDK\make-3.82\make.exe.
The OpenJDK build depends on the FreeType library. Unfortunately there are now binary development packages available for Windows but building FreeType is not hard at all.
Download FreeType from http://www.freetype.org/download.html, extract it to c:\OpenJDK\freetype-2.4.7and double click on c:\OpenJDK\freetype-2.4.7\builds\win32\vc2010\freetype.vcxprojto open the FreeType project in "VisualC++ Express 2010".
From the projects properties do the following:
- Configuration Manager -> Active Solution Manager -> Type or select the new Platform -> x64
- Configuration -> Release Multithreaded
- Platform -> x64
- Output Directory -> rename ".\..\..\..\objs\win32\vc2010\" to ".\..\..\..\objs\win64\vc2010\"
- Intermediate Directory -> rename ".\..\..\..\objs\release_mt\" to ".\..\..\..\objs\release_mt_64\"
- Target Name -> rename to "freetype"
- Platform Toolset -> Windows7.1SDK
Then choose "Release Multithreaded"/"x64" in the menu bar and Build the project by choosing "Build" from the project menu. This will create the 64-bit freetype.lib in the corresponding output directory. Now change the "Configuration Type" to "dll" in the project properties and build again. Now the 64-bit freetype.dll will be build in the output directory.
For the 32-bit build we have to go back to the project properties and do the following changes:
- Configuration -> Release Multithreaded
- Platform -> win32
- Target Name -> rename to "freetype"
- Platform Toolset -> v100
Now we can choose "Release Multithreaded"/"Win32" in the menu bar and start the build to create the 32-bit freetype.lib in the output directory. After we've changed the "Configuration Type" to "dll" in the project properties the next build will finally create the 32-bit freetype.dll in the corresponding output directory.
Path handling is very sensitive and the root cause of many build problems! Actually we have to deal with three different path categories: the default Windows System PATH setting (which now also contains the path of the JDK and the Mercurial client), the path setting for the Microsoft compiler and build tools which will be set up right before the build (see next step) and finally the path to the Cygwin tools which are needed for the build.
In general, the system path part should be before the compiler path part which in turn should come before the Cygwin path. But there are a few exceptions - for now exactly two: the Cygwin find.exe utility should be found before the one from the Windows system path and our newly compiled make.exe should be find before the one from the Cygwin path.
To solve this problem I created an extra directory c:\OpenJDK\PATH_PREPEND to which I copied the respective executables:
mkdir c:\OpenJDK\PATH_PREPEND copy c:\cygwin\bin\find.exe c:\OpenJDK\PATH_PREPEND copy c:\OpenJDK\make-3.82\make.exe c:\OpenJDK\PATH_PREPEND
Before we can start the actual build, we have to set the correct compiler environment by calling SetEnv.cmd from the Windows SDK with the right parameters. For this task I created two shortcuts which start a command shell for a 64 and a 32-bit environment respectively:
C:\WINDOWS\system32\cmd.exe /E:ON /V:ON /K "C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\SetEnv.cmd" /Release /xp /x64 C:\WINDOWS\system32\cmd.exe /E:ON /V:ON /K "C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\SetEnv.cmd" /Release /xp /x86
In such command shell we can now start a bash-shell and export the final path settings:
c:\cygwin\bin\bash $ export PATH=/cygdrive/c/OpenJDK/PATH_PREPEND:$PATH:/cygdrive/c/cygwin/bin
We will use Mercurial to get the latest (and greatest OpenJDK 8 sources from http://hg.openjdk.java.net/jdk8/jdk8. Notice that we have to set the http_proxyenvironment variable if your machine does not have direct access to the Internet.
$ export http_proxy=http://proxy:8080 $ hg clone http://hg.openjdk.java.net/jdk8/jdk8
The previous command will only fetch the JDK 8 base directory along with some README and script files. In order to get the full blown source tree you can either clone the sub-repositories manually or better use the handy get_source.sh script:
$ cd jdk8 $ ./get_source.sh
The OpenJDK Mercurial repositories do not contain the JAXP and JAX_WS sources because they are developed in different projects. It is therefore necessary to download these sources and place them into a directory which is passed the the OpenJDK build trough the ALT_DROPS_DIR environment variable.
Of course it is necessary to get the right version of the sources for a successful build. The exact file names and download URLs can be found in the respective ANT build files:
mkdir c:\OpenJDK\ALT_DROPS_DIR c:\cygwin\bin\bash.exe cd /cygdrive/c/OpenJDK/jdk8/ grep -E "jaxp_src.bundle.name|jaxp_src.master.bundle.url.base" jaxp/jaxp.properties jaxp_src.bundle.name=jaxp145_01.zip jaxp_src.master.bundle.url.base=http://download.java.net/jaxp/1.4.5 grep -E "jaxws_src.master.bundle.url.base|jaxws_src.bundle.name|jaf_src.bundle.name|jaf_src.master.bundle.url.base" jaxws/jaxws.properties jaxws_src.bundle.name=jdk7-jaxws2_2_4-b03-2011_05_27.zip jaxws_src.master.bundle.url.base=http://download.java.net/glassfish/components/jax-ws/openjdk/jdk7 jaf_src.bundle.name=jdk7-jaf-2010_08_19.zip jaf_src.master.bundle.url.base=https://java.net/downloads/jax-ws/JDK7
So I downloaded jaxp145_01.zip, jdk7-jaxws2_2_4-b03-2011_05_27.zip and jdk7-jaf-2010_08_19.zip from the respective URLs and stored them into the newly created directory c:\OpenJDK\ALT_DROPS_DIR
Notice that it is also possible to let the make process automatically download these source drops by adding the ALLOW_DOWNLOADS=true parameter to the make command line. But first of all it is not recommended in the OpenJDK Readme and second it didn't work for me (probably just because I haven't properly configured the proxy settings for ANT.
The build system also needs to find the msvcr100.dll runtime library. Because it couldn't automatically detect it on my system and because I wanted to pass it's location to the build (through ALT_MSVCRNN_DLL_PATH) as a path without spaces I copied the DLL to c:\OpenJDK\ALT_DROPS_DIR as well:
c:\cygwin\bin\bash.exe cp /cygdrive/c/Program\ Files\ \(x86\)/Microsoft\ Visual\ Studio\ 10.0/Common7/Packages/Debugger/X64/msvcr100.dll \ /cygdrive/c/OpenJDK/ALT_DROPS_DIR/
This is finally the last step of this tutorial and building the OpenJDK is just two commands away! Before we start the actual build we, set the environment variable WINDOWSSDKDIR. Normally, this is already done by the compiler setup script SetEnv.cmd which we've called before, but on my machine, the script actually definedWindowsSDKDir. While this is no problem in a Windows command shell where environment variables are case insensitive, the GNU makefile used for the OpenJDK build only looks for WINDOWSSDKDIR and will not find WindowsSDKDir. (Unfortunately setting ALT_WINDOWSSDKDIR on the make command line doesn't seem to work either (at least for me). I therefore think this is definitely a point that should be fixed in the Makefiles!)
$ export WINDOWSSDKDIR=$WindowsSDKDir
Now we can ultimately fire up the make command along with several configuration variables. We want to build a 64-bit VM first so we set ARCH_DATA_MODEL to 64. We choose a different output directory so we set ALT_OUTPUTDIR to c:/OpenJDK/output_amd64. With ALT_FREETYPE_LIB_PATH and ALT_FREETYPE_HEADERS_PATH we specify where the FreeType libraries and headers are located (be careful and use the path to the 64-bit libraries that you've build before). ALT_BOOTDIR denotes the location of the bootstrap JDK and ALT_DROPS_DIR the directory where we've stored the JAXP and JAX_WS sources. Finally,ALT_MSVCRNN_DLL_PATH indicates where a copy of msvcr100.dll library can be found. This will be copied into the newly created JDK images.
The build can be speed up considerably by setting HOTSPOT_BUILD_JOBS (for the HotSpot build) and PARALLEL_COMPILE_JOBS (for the JDK build) to the number of CPUs if you are building on a multi core machine. In my experience it may even help to set the numbers slightly higher than the actual number of CPUs because on new machines the build time is usually IO and not CPU bound.
I also like to save the whole build logs into a file so I end the make command line with '2>&1 | tee c:/OpenJDK/output_amd64.log'. This will print the build logs to the console and save them to c:/OpenJDK/output_amd64.log at the same time. Also notice that I use path names with DOS-style drive letters but Unix-like forward slashes as path separators on the make command line. This is advised in the OpenJDK Readme and gave the best results for me.
$ make ARCH_DATA_MODEL=64 \ ALT_OUTPUTDIR=c:/OpenJDK/output_amd64 \ ALT_FREETYPE_LIB_PATH=c:/OpenJDK/freetype-2.4.7/objs/win64/vc2010 \ ALT_FREETYPE_HEADERS_PATH=c:/OpenJDK/freetype-2.4.7/include \ ALT_BOOTDIR=c:/OpenJDK/jdk1.7.0_01 \ ALT_DROPS_DIR=c:/OpenJDK/ALT_DROPS_DIR \ ALT_MSVCRNN_DLL_PATH=c:/OpenJDK/ALT_DROPS_DIR \ HOTSPOT_BUILD_JOBS=4 \ PARALLEL_COMPILE_JOBS=4 \ 2>&1 | tee c:/OpenJDK/output_amd64.log
If you closely followed my instructions and if I've made no mistake while I was writing this down you should see this wonderful success message after a few hours:
######################################################################## ##### Leaving jdk for target(s) sanity all docs images ##### ######################################################################## ##### Build time 05:17:03 jdk for target(s) sanity all docs images ##### ######################################################################## -- Build times ---------- Target all_product_build Start 2011-10-27 09:15:08 End 2011-10-27 14:41:50 00:03:54 hotspot 00:01:28 jaxp 00:01:47 jaxws 05:17:03 jdk 00:01:13 langtools 05:26:43 TOTAL ------------------------- make: Leaving directory `/cygdrive/c/OpenJDK/jdk8'
Congratulations - you've successfully build OpenJDK 8 on Windows!!!
Now, building a 32-bit JDK is just a few commands away. First we have to start the right command shell with the settings for the 32-bit compiler and build tools (SetEnv.cmd /Release /xp /x86). Then we type (parameters which have changed with respect to the 64-bit build are printed in bold):
c:\cygwin\bin\bash $ export PATH=/cygdrive/c/OpenJDK/PATH_PREPEND:$PATH:/cygdrive/c/cygwin/bin $ export WINDOWSSDKDIR=$WindowsSDKDir $ make ARCH_DATA_MODEL=32 \ ALT_OUTPUTDIR=c:/OpenJDK/output_x86 \ ALT_FREETYPE_LIB_PATH=c:/OpenJDK/freetype-2.4.7/objs/win32/vc2010 \ ALT_FREETYPE_HEADERS_PATH=c:/OpenJDK/freetype-2.4.7/include \ ALT_BOOTDIR=c:/OpenJDK/jdk1.7.0_01 \ ALT_DROPS_DIR=c:/OpenJDK/ALT_DROPS_DIR \ ALT_MSVCRNN_DLL_PATH=c:/OpenJDK/ALT_DROPS_DIR \ HOTSPOT_BUILD_JOBS=4 \ PARALLEL_COMPILE_JOBS=4 \ NO_DOCS=true \ 2>&1 | tee c:/OpenJDK/output_x86.log
Notice that it is a known problem that building the JavaDoc documentation during a 32-bit build on a 64-bit system (actually with a 64-bit bootstrap JDK) will fail. To workaround this issue we use the additional parameter NO_DOCS=true.