Skip to main content

YAOJOWBI - Yet another OpenJDK on Windows Build Instruction

Posted by simonis on October 28, 2011 at 11:00 AM PDT

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.

Getting started

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.

VisualC++ 2010 Express

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).

Windows SDK for Windows 7 and .Net

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:)

Microsoft DirectX 9.0 SDK

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=21416 but be sure to check the corresponding Microsoft DirectX section in the OpenJDK Readme in the case the required version changed.

TortoiseHg

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.

Java 7 JDK

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 (under Start->Control Panel->System->Advanced->Environment Variables->System Variables->).

Ant

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.cgi and 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.

Cygwin

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.

GNU make

Update (2012-02-09): 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 make maintainer 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 of GNU make 3.82 which supports drive letters.

Download and unpack GNU make 3.82 from http://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.

FreeType

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.7 and double click on c:\OpenJDK\freetype-2.4.7\builds\win32\vc2010\freetype.vcxproj to 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

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

Downloading the OpenJDK sources

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_proxy environment 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

JAXP and JAX_WS

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.

msvcr100.dll

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/

Building the OpenJDK

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 defined WindowsSDKDir. 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[1]: 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.

Comments

Hi! Thanks for your share! I have successfully build ...

Hi! Thanks for your share!
I have successfully build OpenJDK7 on Windows,but now I get a new question that if I just want to rebuild the "rt.jar" package,how can I do?

Hi Volker, Thanks for this post. It was really very ...

Hi Volker,
Thanks for this post. It was really very helpful. I followed the steps given in this blog and am experiencing some issues. The build works fine till it has generated the JaxWs and then gets stuck. The exact place where it gets stuck is :
BUILDTOOL generatenimbus.

I am trying this on a 64 bit windows7 vm installed on Mac.
The last few lines in the log where it gets stuck:

BUILDTOOL: generatenimbus
PACKAGE: build.tools.generatenimbus
BUILDTOOL_SOURCE_ROOT: ../../tools/src
BUILTTOOL_MAINCLASS: build.tools.generatenimbus.Generator
BUILDTOOL_JAR_FILE: c:/openJDK/output_amd641/btjars/generatenimbus.jar
=========================================================
make[4]: Leaving directory `/cygdrive/c/openJDK/jdk8/jdk/make/tools/generate_nimbus'
Done Processing SUBDIRS: addjsum buildmetaindex commentchecker compile_font_config compile_properties dir_diff dtdbuilder generate_break_iterator GenerateCharacter generatecurrencydata hasher_classes jarreorder jarsplit javazic jdwpgen makeclasslist strip_properties spp CharsetMapping generate_nimbus
make[3]: Leaving directory `/cygdrive/c/openJDK/jdk8/jdk/make/tools'
INFO: ENABLE_FULL_DEBUG_SYMBOLS=1
INFO: ZIP_DEBUGINFO_FILES=1
make[3]: Entering directory `/cygdrive/c/openJDK/jdk8/jdk/make/java'
Begin Processing SUBDIRS: version jvm redist verify fdlibm java sun_nio jli main zip security math util text net nio jar awt applet beans management npt java_crw_demo java_hprof_demo logging instrument invoke sql rmi
INFO: ENABLE_FULL_DEBUG_SYMBOLS=1
INFO: ZIP_DEBUGINFO_FILES=1
make[4]: Entering directory `/cygdrive/c/openJDK/jdk8/jdk/make/java/version'
/usr/bin/mkdir -p c:/openJDK/output_amd641/gensrc/sun/misc
rm -f c:/openJDK/output_amd641/gensrc/sun/misc/Version.java
rm -f c:/openJDK/output_amd641/gensrc/sun/misc/Version.java.temp
/usr/bin/sed -e 's/@@launcher_name@@/openjdk/g' \
-e 's/@@java_version@@/1.8.0-internal/g' \
-e 's/@@java_runtime_version@@/1.8.0-internal-amitkumar_2012_07_23_14_02-b00/g' \
-e 's/@@java_runtime_name@@/OpenJDK Runtime Environment/g' \
../../../src/share/classes/sun/misc/Version.java.template > c:/openJDK/output_amd641/gensrc/sun/misc/Version.java.temp
make[4]: Leaving directory `/cygdrive/c/openJDK/jdk8/jdk/make/java/version'
INFO: ENABLE_FULL_DEBUG_SYMBOLS=1
INFO: ZIP_DEBUGINFO_FILES=1
make[4]: Entering directory `/cygdrive/c/openJDK/jdk8/jdk/make/java/jvm'
/usr/bin/mkdir -p c:/openJDK/output_amd641/include
rm -f c:/openJDK/output_amd641/include/jni.h
/usr/bin/cp ../../../src/share/javavm/export/jni.h c:/openJDK/output_amd641/include/jni.h
/usr/bin/mkdir -p c:/openJDK/output_amd641/include/win32
rm -f c:/openJDK/output_amd641/include/win32/jni_md.h
/usr/bin/cp ../../../src/windows/javavm/export/jni_md.h c:/openJDK/output_amd641/include/win32/jni_md.h
/usr/bin/mkdir -p c:/openJDK/output_amd641/include
rm -f c:/openJDK/output_amd641/include/jvmti.h
/usr/bin/cp ../../../src/share/javavm/export/jvmti.h c:/openJDK/output_amd641/include/jvmti.h
/usr/bin/mkdir -p c:/openJDK/output_amd641/include
rm -f c:/openJDK/output_amd641/include/jvmticmlr.h
/usr/bin/cp ../../../src/share/javavm/export/jvmticmlr.h c:/openJDK/output_amd641/include/jvmticmlr.h
/usr/bin/mkdir -p c:/openJDK/output_amd641/include
rm -f c:/openJDK/output_amd641/include/classfile_constants.h
/usr/bin/cp ../../../src/share/javavm/export/classfile_constants.h c:/openJDK/output_amd641/include/classfile_constants.h
/usr/bin/mkdir -p c:/openJDK/output_amd641/lib/amd64
rm -f c:/openJDK/output_amd641/lib/amd64/jvm.cfg
/usr/bin/cp ../../../src/windows/bin/amd64/jvm.cfg c:/openJDK/output_amd641/lib/amd64/jvm.cfg
make[4]: Leaving directory `/cygdrive/c/openJDK/jdk8/jdk/make/java/jvm'
INFO: ENABLE_FULL_DEBUG_SYMBOLS=1
INFO: ZIP_DEBUGINFO_FILES=1

Any help would be greatly appreciated.

Thanks
Srilekha

Hi Srilekha, what do you mean with "get stuck" - does the ...

Hi Srilekha,
what do you mean with "get stuck" - does the build hang without any error message?

I think I observed similar problems and I think they are related to the specific combination of the Windows and Cygwin version you are using. For me these problems appeared when I switched to the new Cygwin version newer than 1.7.9 on Windows 7 (please see the mail thread "Is anyone able to build on Win 7" on the OpenJDK build-dev mailing list (http://old.nabble.com/Is-anyone-able-to-build-on-Win-7-tt33196055.html#a...)).

Unfortunately I have no real good solution for your problem. You have several options:
1. Downgrade to Cygwin 1.7.9. But be aware that this may give you other problems like fork errors (see again the mentioned mail thread for possible solutions).
2. If you have Windows in a VM running anyway, try to build on WindowsXP - for me that was easier and it seems that the Cygwin tools are still not very well suited for Windows 7.
3. Try to build with MinGW. Some time ago I've posted some patches to enable the Windows build with MinGW. Unfortunately they are still not integrated into the OpenJDK, but you may still be able to integrate them (you can google to find the corresponding mail thread, the patches are located here http://cr.openjdk.java.net/~simonis/)
4. Try the new, configure based OpenJDK build system (http://openjdk.java.net/projects/build-infra/guide.html). I don't know its exact current status on Windows, but I know that it avoids the recursive make semantics which causes your hang.

Sorry that I can not help more,
Volker

Thanks Volker. You were a great help. I was able to solve ...

Thanks Volker. You were a great help. I was able to solve and build the openjdk finally with your suggestion. I was able to build Openjdk with the configure based build system.
Thanks a lot for pointing that out to me

Regards
Srilekha