762a573ef1
Reviewed-by: erikj, ihse
2493 lines
120 KiB
HTML
2493 lines
120 KiB
HTML
<!DOCTYPE html>
|
||
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
|
||
<head>
|
||
<meta charset="utf-8" />
|
||
<meta name="generator" content="pandoc" />
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
|
||
<title>Building the JDK</title>
|
||
<style>
|
||
code{white-space: pre-wrap;}
|
||
span.smallcaps{font-variant: small-caps;}
|
||
div.columns{display: flex; gap: min(4vw, 1.5em);}
|
||
div.column{flex: auto; overflow-x: auto;}
|
||
div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
|
||
ul.task-list{list-style: none;}
|
||
ul.task-list li input[type="checkbox"] {
|
||
width: 0.8em;
|
||
margin: 0 0.8em 0.2em -1.6em;
|
||
vertical-align: middle;
|
||
}
|
||
.display.math{display: block; text-align: center; margin: 0.5rem auto;}
|
||
</style>
|
||
<link rel="stylesheet" href="../make/data/docs-resources/resources/jdk-default.css" />
|
||
<style type="text/css">pre, code, tt { color: #1d6ae5; }</style>
|
||
<!--[if lt IE 9]>
|
||
<script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
|
||
<![endif]-->
|
||
</head>
|
||
<body>
|
||
<header id="title-block-header">
|
||
<h1 class="title">Building the JDK</h1>
|
||
</header>
|
||
<nav id="TOC" role="doc-toc">
|
||
<ul>
|
||
<li><a href="#tldr-instructions-for-the-impatient"
|
||
id="toc-tldr-instructions-for-the-impatient">TL;DR (Instructions for the
|
||
Impatient)</a></li>
|
||
<li><a href="#introduction" id="toc-introduction">Introduction</a></li>
|
||
<li><a href="#getting-the-source-code"
|
||
id="toc-getting-the-source-code">Getting the Source Code</a>
|
||
<ul>
|
||
<li><a href="#special-considerations"
|
||
id="toc-special-considerations">Special Considerations</a></li>
|
||
</ul></li>
|
||
<li><a href="#build-hardware-requirements"
|
||
id="toc-build-hardware-requirements">Build Hardware Requirements</a>
|
||
<ul>
|
||
<li><a href="#building-on-x86" id="toc-building-on-x86">Building on
|
||
x86</a></li>
|
||
<li><a href="#building-on-aarch64" id="toc-building-on-aarch64">Building
|
||
on aarch64</a></li>
|
||
<li><a href="#building-on-32-bit-arm"
|
||
id="toc-building-on-32-bit-arm">Building on 32-bit ARM</a></li>
|
||
</ul></li>
|
||
<li><a href="#operating-system-requirements"
|
||
id="toc-operating-system-requirements">Operating System Requirements</a>
|
||
<ul>
|
||
<li><a href="#windows" id="toc-windows">Windows</a></li>
|
||
<li><a href="#macos" id="toc-macos">macOS</a></li>
|
||
<li><a href="#linux" id="toc-linux">Linux</a></li>
|
||
<li><a href="#aix" id="toc-aix">AIX</a></li>
|
||
</ul></li>
|
||
<li><a href="#native-compiler-toolchain-requirements"
|
||
id="toc-native-compiler-toolchain-requirements">Native Compiler
|
||
(Toolchain) Requirements</a>
|
||
<ul>
|
||
<li><a href="#gcc" id="toc-gcc">gcc</a></li>
|
||
<li><a href="#clang" id="toc-clang">clang</a></li>
|
||
<li><a href="#apple-xcode" id="toc-apple-xcode">Apple Xcode</a></li>
|
||
<li><a href="#microsoft-visual-studio"
|
||
id="toc-microsoft-visual-studio">Microsoft Visual Studio</a></li>
|
||
<li><a href="#ibm-open-xl-cc" id="toc-ibm-open-xl-cc">IBM Open XL
|
||
C/C++</a></li>
|
||
</ul></li>
|
||
<li><a href="#boot-jdk-requirements" id="toc-boot-jdk-requirements">Boot
|
||
JDK Requirements</a>
|
||
<ul>
|
||
<li><a href="#getting-jdk-binaries"
|
||
id="toc-getting-jdk-binaries">Getting JDK Binaries</a></li>
|
||
</ul></li>
|
||
<li><a href="#external-library-requirements"
|
||
id="toc-external-library-requirements">External Library Requirements</a>
|
||
<ul>
|
||
<li><a href="#freetype" id="toc-freetype">FreeType</a></li>
|
||
<li><a href="#fontconfig" id="toc-fontconfig">Fontconfig</a></li>
|
||
<li><a href="#cups" id="toc-cups">CUPS</a></li>
|
||
<li><a href="#x11" id="toc-x11">X11</a></li>
|
||
<li><a href="#alsa" id="toc-alsa">ALSA</a></li>
|
||
<li><a href="#libffi" id="toc-libffi">libffi</a></li>
|
||
</ul></li>
|
||
<li><a href="#build-tools-requirements"
|
||
id="toc-build-tools-requirements">Build Tools Requirements</a>
|
||
<ul>
|
||
<li><a href="#autoconf" id="toc-autoconf">Autoconf</a></li>
|
||
<li><a href="#gnu-make" id="toc-gnu-make">GNU Make</a></li>
|
||
<li><a href="#gnu-bash" id="toc-gnu-bash">GNU Bash</a></li>
|
||
<li><a href="#graphviz-and-pandoc" id="toc-graphviz-and-pandoc">Graphviz
|
||
and Pandoc</a></li>
|
||
</ul></li>
|
||
<li><a href="#running-configure" id="toc-running-configure">Running
|
||
Configure</a>
|
||
<ul>
|
||
<li><a href="#common-configure-arguments"
|
||
id="toc-common-configure-arguments">Common Configure Arguments</a></li>
|
||
<li><a href="#configure-control-variables"
|
||
id="toc-configure-control-variables">Configure Control
|
||
Variables</a></li>
|
||
</ul></li>
|
||
<li><a href="#running-make" id="toc-running-make">Running Make</a>
|
||
<ul>
|
||
<li><a href="#common-make-targets" id="toc-common-make-targets">Common
|
||
Make Targets</a></li>
|
||
<li><a href="#make-control-variables"
|
||
id="toc-make-control-variables">Make Control Variables</a></li>
|
||
</ul></li>
|
||
<li><a href="#running-tests" id="toc-running-tests">Running
|
||
Tests</a></li>
|
||
<li><a href="#signing" id="toc-signing">Signing</a>
|
||
<ul>
|
||
<li><a href="#macos-1" id="toc-macos-1">macOS</a></li>
|
||
</ul></li>
|
||
<li><a href="#cross-compiling"
|
||
id="toc-cross-compiling">Cross-Compiling</a>
|
||
<ul>
|
||
<li><a href="#specifying-the-target-platform"
|
||
id="toc-specifying-the-target-platform">Specifying the Target
|
||
Platform</a></li>
|
||
<li><a href="#boot-jdk-and-build-jdk"
|
||
id="toc-boot-jdk-and-build-jdk">Boot JDK and Build JDK</a></li>
|
||
<li><a href="#toolchain-considerations"
|
||
id="toc-toolchain-considerations">Toolchain Considerations</a></li>
|
||
<li><a href="#native-libraries" id="toc-native-libraries">Native
|
||
Libraries</a></li>
|
||
<li><a href="#verifying-the-build"
|
||
id="toc-verifying-the-build">Verifying the Build</a></li>
|
||
<li><a href="#cross-compiling-the-easy-way"
|
||
id="toc-cross-compiling-the-easy-way">Cross-Compiling the Easy
|
||
Way</a></li>
|
||
<li><a href="#considerations-for-specific-targets"
|
||
id="toc-considerations-for-specific-targets">Considerations for Specific
|
||
Targets</a></li>
|
||
</ul></li>
|
||
<li><a href="#build-performance" id="toc-build-performance">Build
|
||
Performance</a>
|
||
<ul>
|
||
<li><a href="#disk-speed" id="toc-disk-speed">Disk Speed</a></li>
|
||
<li><a href="#virus-checking" id="toc-virus-checking">Virus
|
||
Checking</a></li>
|
||
<li><a href="#ccache" id="toc-ccache">Ccache</a></li>
|
||
<li><a href="#precompiled-headers"
|
||
id="toc-precompiled-headers">Precompiled Headers</a></li>
|
||
<li><a href="#icecc-icecream" id="toc-icecc-icecream">Icecc /
|
||
Icecream</a></li>
|
||
<li><a href="#using-the-javac-server"
|
||
id="toc-using-the-javac-server">Using the javac Server</a></li>
|
||
<li><a href="#building-the-right-target"
|
||
id="toc-building-the-right-target">Building the Right Target</a></li>
|
||
</ul></li>
|
||
<li><a href="#troubleshooting"
|
||
id="toc-troubleshooting">Troubleshooting</a>
|
||
<ul>
|
||
<li><a href="#locating-the-source-of-the-error"
|
||
id="toc-locating-the-source-of-the-error">Locating the Source of the
|
||
Error</a></li>
|
||
<li><a href="#fixing-unexpected-build-failures"
|
||
id="toc-fixing-unexpected-build-failures">Fixing Unexpected Build
|
||
Failures</a></li>
|
||
<li><a href="#specific-build-issues"
|
||
id="toc-specific-build-issues">Specific Build Issues</a></li>
|
||
<li><a href="#getting-help" id="toc-getting-help">Getting Help</a></li>
|
||
</ul></li>
|
||
<li><a href="#reproducible-builds"
|
||
id="toc-reproducible-builds">Reproducible Builds</a></li>
|
||
<li><a href="#hints-and-suggestions-for-advanced-users"
|
||
id="toc-hints-and-suggestions-for-advanced-users">Hints and Suggestions
|
||
for Advanced Users</a>
|
||
<ul>
|
||
<li><a href="#bash-completion" id="toc-bash-completion">Bash
|
||
Completion</a></li>
|
||
<li><a href="#using-multiple-configurations"
|
||
id="toc-using-multiple-configurations">Using Multiple
|
||
Configurations</a></li>
|
||
<li><a href="#handling-reconfigurations"
|
||
id="toc-handling-reconfigurations">Handling Reconfigurations</a></li>
|
||
<li><a href="#using-fine-grained-make-targets"
|
||
id="toc-using-fine-grained-make-targets">Using Fine-Grained Make
|
||
Targets</a></li>
|
||
</ul></li>
|
||
<li><a href="#understanding-the-build-system"
|
||
id="toc-understanding-the-build-system">Understanding the Build
|
||
System</a>
|
||
<ul>
|
||
<li><a href="#configurations"
|
||
id="toc-configurations">Configurations</a></li>
|
||
<li><a href="#build-output-structure"
|
||
id="toc-build-output-structure">Build Output Structure</a></li>
|
||
<li><a href="#fixpath" id="toc-fixpath">Fixpath</a></li>
|
||
<li><a href="#native-debug-symbols" id="toc-native-debug-symbols">Native
|
||
Debug Symbols</a></li>
|
||
<li><a href="#autoconf-details" id="toc-autoconf-details">Autoconf
|
||
Details</a></li>
|
||
<li><a href="#developing-the-build-system-itself"
|
||
id="toc-developing-the-build-system-itself">Developing the Build System
|
||
Itself</a></li>
|
||
</ul></li>
|
||
<li><a href="#contributing-to-the-jdk"
|
||
id="toc-contributing-to-the-jdk">Contributing to the JDK</a></li>
|
||
<li><a href="#editing-this-document"
|
||
id="toc-editing-this-document">Editing This Document</a></li>
|
||
</ul>
|
||
</nav>
|
||
<h2 id="tldr-instructions-for-the-impatient">TL;DR (Instructions for the
|
||
Impatient)</h2>
|
||
<p>If you are eager to try out building the JDK, these simple steps work
|
||
most of the time. They assume that you have installed Git (and Cygwin,
|
||
MSYS2 or WSL if running on Windows), and want to clone the main-line JDK
|
||
repository.</p>
|
||
<ol type="1">
|
||
<li><p><a href="#getting-the-source-code">Get the complete source
|
||
code</a>:<br />
|
||
<code>git clone https://git.openjdk.org/jdk</code></p></li>
|
||
<li><p><a href="#running-configure">Run configure</a>:<br />
|
||
<code>bash configure</code></p>
|
||
<p>If <code>configure</code> fails due to missing dependencies (to
|
||
either the <a
|
||
href="#native-compiler-toolchain-requirements">toolchain</a>, <a
|
||
href="#build-tools-requirements">build tools</a>, <a
|
||
href="#external-library-requirements">external libraries</a> or the <a
|
||
href="#boot-jdk-requirements">boot JDK</a>), most of the time it prints
|
||
a suggestion on how to resolve the situation on your platform. Follow
|
||
the instructions, and try running <code>bash configure</code>
|
||
again.</p></li>
|
||
<li><p><a href="#running-make">Run make</a>:<br />
|
||
<code>make images</code></p></li>
|
||
<li><p>Verify your newly built JDK:<br />
|
||
<code>./build/*/images/jdk/bin/java -version</code></p></li>
|
||
<li><p><a href="#running-tests">Run basic tests</a>:<br />
|
||
<code>make test-tier1</code></p></li>
|
||
</ol>
|
||
<p>If any of these steps failed, or if you want to know more about build
|
||
requirements or build functionality, please continue reading this
|
||
document.</p>
|
||
<h2 id="introduction">Introduction</h2>
|
||
<p>The JDK is a complex software project. Building it requires a certain
|
||
amount of technical expertise, a fair number of dependencies on external
|
||
software, and reasonably powerful hardware.</p>
|
||
<p>If you just want to use the JDK and not build it yourself, this
|
||
document is not for you. See for instance <a
|
||
href="https://openjdk.org/install">OpenJDK installation</a> for some
|
||
methods of installing a prebuilt JDK.</p>
|
||
<h2 id="getting-the-source-code">Getting the Source Code</h2>
|
||
<p>Make sure you are getting the correct version. At the <a
|
||
href="https://git.openjdk.org/">OpenJDK Git site</a> you can see a list
|
||
of all available repositories. Commonly used repositories are:</p>
|
||
<ul>
|
||
<li><p>The <a href="https://openjdk.org/projects/jdk">JDK Project</a>
|
||
(the main-line currently in development):
|
||
https://git.openjdk.org/jdk</p></li>
|
||
<li><p>The <a href="https://openjdk.org/projects/jdk-updates/">JDK
|
||
Updates Project</a>, which has one repository per update release, e.g.
|
||
https://git.openjdk.org/jdk17u for JDK 17.</p></li>
|
||
</ul>
|
||
<p>If you want to build an older version, e.g. JDK 17, it is strongly
|
||
recommended that you use the JDK Updates repository, e.g. the
|
||
<code>jdk17u</code>, which contains incremental updates, instead of the
|
||
JDK Project repository <code>jdk17</code>, which was frozen at JDK 17
|
||
GA.</p>
|
||
<p>If you are new to Git, a good place to start is the book <a
|
||
href="https://git-scm.com/book/en/v2">Pro Git</a>. The rest of this
|
||
document assumes a working knowledge of Git.</p>
|
||
<h3 id="special-considerations">Special Considerations</h3>
|
||
<p>For a smooth building experience, it is recommended that you follow
|
||
these rules on where and how to check out the source code.</p>
|
||
<ul>
|
||
<li><p>Do not check out the source code in a path which contains spaces.
|
||
Chances are the build will not work. This is most likely to be an issue
|
||
on Windows systems.</p></li>
|
||
<li><p>Do not check out the source code in a path which has a very long
|
||
name or is nested many levels deep. Chances are you will hit an OS
|
||
limitation during the build.</p></li>
|
||
<li><p>Put the source code on a local disk, not a network share. If
|
||
possible, use an SSD. The build process is very disk intensive, and
|
||
having slow disk access will significantly increase build times. If you
|
||
need to use a network share for the source code, see below for
|
||
suggestions on how to keep the build artifacts on a local disk.</p></li>
|
||
<li><p>On Windows, if using <a href="#cygwin">Cygwin</a>, extra care
|
||
must be taken to make sure the environment is consistent. It is
|
||
recommended that you follow this procedure:</p>
|
||
<ul>
|
||
<li><p>Create the directory that is going to contain the top directory
|
||
of the JDK clone by using the <code>mkdir</code> command in the Cygwin
|
||
bash shell. That is, do <em>not</em> create it using Windows Explorer.
|
||
This will ensure that it will have proper Cygwin attributes, and that
|
||
it's children will inherit those attributes.</p></li>
|
||
<li><p>Do not put the JDK clone in a path under your Cygwin home
|
||
directory. This is especially important if your user name contains
|
||
spaces and/or mixed upper and lower case letters.</p></li>
|
||
<li><p>You need to install a git client. You have two choices, Cygwin
|
||
git or Git for Windows. Unfortunately there are pros and cons with each
|
||
choice.</p>
|
||
<ul>
|
||
<li><p>The Cygwin <code>git</code> client has no line ending issues and
|
||
understands Cygwin paths (which are used throughout the JDK build
|
||
system). However, it does not currently work well with the Skara CLI
|
||
tooling. Please see the <a
|
||
href="https://wiki.openjdk.org/display/SKARA/Skara#Skara-Git">Skara wiki
|
||
on Git clients</a> for up-to-date information about the Skara git client
|
||
support.</p></li>
|
||
<li><p>The <a href="https://gitforwindows.org">Git for Windows</a>
|
||
client has issues with line endings, and do not understand Cygwin paths.
|
||
It does work well with the Skara CLI tooling, however. To alleviate the
|
||
line ending problems, make sure you set <code>core.autocrlf</code> to
|
||
<code>false</code> (this is asked during installation).</p></li>
|
||
</ul></li>
|
||
</ul>
|
||
<p>Failure to follow this procedure might result in hard-to-debug build
|
||
problems.</p></li>
|
||
</ul>
|
||
<h2 id="build-hardware-requirements">Build Hardware Requirements</h2>
|
||
<p>The JDK is a massive project, and require machines ranging from
|
||
decent to powerful to be able to build in a reasonable amount of time,
|
||
or to be able to complete a build at all.</p>
|
||
<p>We <em>strongly</em> recommend usage of an SSD disk for the build,
|
||
since disk speed is one of the limiting factors for build
|
||
performance.</p>
|
||
<h3 id="building-on-x86">Building on x86</h3>
|
||
<p>At a minimum, a machine with 2-4 cores is advisable, as well as 2-4
|
||
GB of RAM. (The more cores to use, the more memory you need.) At least 6
|
||
GB of free disk space is required.</p>
|
||
<p>Even for 32-bit builds, it is recommended to use a 64-bit build
|
||
machine, and instead create a 32-bit target using
|
||
<code>--with-target-bits=32</code>.</p>
|
||
<p>Note: The Windows 32-bit x86 port is deprecated and may be removed in
|
||
a future release.</p>
|
||
<h3 id="building-on-aarch64">Building on aarch64</h3>
|
||
<p>At a minimum, a machine with 8 cores is advisable, as well as 8 GB of
|
||
RAM. (The more cores to use, the more memory you need.) At least 6 GB of
|
||
free disk space is required.</p>
|
||
<p>If you do not have access to sufficiently powerful hardware, it is
|
||
also possible to use <a href="#cross-compiling">cross-compiling</a>.</p>
|
||
<h4 id="branch-protection">Branch Protection</h4>
|
||
<p>In order to use Branch Protection features in the VM,
|
||
<code>--enable-branch-protection</code> must be used. This option
|
||
requires C++ compiler support (GCC 9.1.0+ or Clang 10+). The resulting
|
||
build can be run on both machines with and without support for branch
|
||
protection in hardware. Branch Protection is only supported for Linux
|
||
targets.</p>
|
||
<h3 id="building-on-32-bit-arm">Building on 32-bit ARM</h3>
|
||
<p>This is not recommended. Instead, see the section on <a
|
||
href="#cross-compiling">Cross-compiling</a>.</p>
|
||
<h2 id="operating-system-requirements">Operating System
|
||
Requirements</h2>
|
||
<p>The mainline JDK project supports Linux, macOS, AIX and Windows.
|
||
Support for other operating system, e.g. BSD, exists in separate "port"
|
||
projects.</p>
|
||
<p>In general, the JDK can be built on a wide range of versions of these
|
||
operating systems, but the further you deviate from what is tested on a
|
||
daily basis, the more likely you are to run into problems.</p>
|
||
<p>This table lists the OS versions used by Oracle when building the
|
||
JDK. Such information is always subject to change, but this table is up
|
||
to date at the time of writing.</p>
|
||
<table>
|
||
<thead>
|
||
<tr class="header">
|
||
<th>Operating system</th>
|
||
<th>Vendor/version used</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr class="odd">
|
||
<td>Linux/x64</td>
|
||
<td>Oracle Enterprise Linux 6.4 / 8.x</td>
|
||
</tr>
|
||
<tr class="even">
|
||
<td>Linux/aarch64</td>
|
||
<td>Oracle Enterprise Linux 7.6 / 8.x</td>
|
||
</tr>
|
||
<tr class="odd">
|
||
<td>macOS</td>
|
||
<td>macOS 13.x (Ventura)</td>
|
||
</tr>
|
||
<tr class="even">
|
||
<td>Windows</td>
|
||
<td>Windows Server 2016</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<p>The double version numbers for Linux are due to the hybrid model used
|
||
at Oracle, where header files and external libraries from an older
|
||
version are used when building on a more modern version of the OS.</p>
|
||
<p>The Build Group has a wiki page with <a
|
||
href="https://wiki.openjdk.org/display/Build/Supported+Build+Platforms">Supported
|
||
Build Platforms</a>. From time to time, this is updated by contributors
|
||
to list successes or failures of building on different platforms.</p>
|
||
<h3 id="windows">Windows</h3>
|
||
<p>Windows XP is not a supported platform, but all newer Windows should
|
||
be able to build the JDK. (Note: The Windows 32-bit x86 port is
|
||
deprecated and may be removed in a future release.)</p>
|
||
<p>On Windows, it is important that you pay attention to the
|
||
instructions in the <a href="#special-considerations">Special
|
||
Considerations</a>.</p>
|
||
<p>Windows is the only non-POSIX OS supported by the JDK, and as such,
|
||
requires some extra care. A POSIX support layer is required to build on
|
||
Windows. Currently, the supported such layers are Cygwin, MSYS2 and
|
||
Windows Subsystem for Linux (WSL). Of these, Cygwin is the one that has
|
||
received the most real-world testing and is likely to cause least
|
||
trouble.</p>
|
||
<p>Internally in the build system, all paths are represented as
|
||
Unix-style paths, e.g. <code>/cygdrive/c/git/jdk/Makefile</code> rather
|
||
than <code>C:\git\jdk\Makefile</code>. This rule also applies to input
|
||
to the build system, e.g. in arguments to <code>configure</code>. So,
|
||
use <code>--with-msvcr-dll=/cygdrive/c/msvcr100.dll</code> rather than
|
||
<code>--with-msvcr-dll=c:\msvcr100.dll</code>. For details on this
|
||
conversion, see the section on <a href="#fixpath">Fixpath</a>.</p>
|
||
<h4 id="locale-requirements">Locale Requirements</h4>
|
||
<p>Building and testing the JDK requires a well-defined locale to be
|
||
guaranteed to run correctly. On non-Windows operating systems, this is
|
||
achieved using the <code>LC_*</code> variables, which propagate to all
|
||
child processes of the build. Unfortunately, there is no way to set the
|
||
locale for a specific process like this in Windows. Instead, changes to
|
||
locale can only be made globally, which will affect all applications run
|
||
by the user. Furthermore, Windows makes a difference between user locale
|
||
and system locale, where the latter determines e.g. the file path
|
||
encoding. Both this locale settings affect building and testing the
|
||
JDK.</p>
|
||
<p>The <strong>recommended</strong> and <strong>supported</strong> way
|
||
of building the JDK on Windows is to set both the system locale and the
|
||
user locale to <strong>US English</strong>. The system setting can be
|
||
changed by going to the Control Panel, choosing "Regional Settings"
|
||
-> "Administrative" and then pressing on the "Change System Locale"
|
||
button.</p>
|
||
<p>Since this is annoying for users who prefer another locale, we strive
|
||
to get the building and testing to work on other locales as well. This
|
||
is on a "best effort" level, so beware! You might get odd results in
|
||
both building and testing. If you do, remember that locales other than
|
||
US English are not supported nor recommended.</p>
|
||
<p>It is also imperative to install the US English language pack in
|
||
Visual Studio. For details, see <a
|
||
href="#microsoft-visual-studio">Microsoft Visual Studio</a>.</p>
|
||
<h4 id="cygwin">Cygwin</h4>
|
||
<p>Install <a href="https://www.cygwin.com/">Cygwin</a> as instructed on
|
||
the home page. It is strongly recommended to use the 64-bit version of
|
||
Cygwin.</p>
|
||
<p><strong>Note:</strong> Cygwin has a model of continuously updating
|
||
all packages without any easy way to install or revert to a specific
|
||
version of a package. This means that whenever you add or update a
|
||
package in Cygwin, you might (inadvertently) update tools that are used
|
||
by the JDK build process, and that can cause unexpected build
|
||
problems.</p>
|
||
<p>The JDK requires GNU Make 4.0 or greater in Cygwin. This is usually
|
||
not a problem, since Cygwin currently only distributes GNU Make at a
|
||
version above 4.0.</p>
|
||
<p>Apart from the basic Cygwin installation, the following packages must
|
||
also be installed:</p>
|
||
<ul>
|
||
<li><code>autoconf</code></li>
|
||
<li><code>make</code></li>
|
||
<li><code>zip</code></li>
|
||
<li><code>unzip</code></li>
|
||
</ul>
|
||
<p>Often, you can install these packages using the following command
|
||
line:</p>
|
||
<pre><code><path to Cygwin setup>/setup-x86_64 -q -P autoconf -P make -P unzip -P zip</code></pre>
|
||
<p>Unfortunately, Cygwin can be unreliable in certain circumstances. If
|
||
you experience build tool crashes or strange issues when building on
|
||
Windows, please check the Cygwin FAQ on the <a
|
||
href="https://cygwin.com/faq/faq.html#faq.using.bloda">"BLODA" list</a>
|
||
and the section on <a
|
||
href="https://cygwin.com/faq/faq.html#faq.using.fixing-fork-failures">fork()
|
||
failures</a>.</p>
|
||
<h4 id="msys2">MSYS2</h4>
|
||
<p>Install <a href="https://www.msys2.org/">MSYS2</a> as instructed on
|
||
the home page.</p>
|
||
<p>Apart from the basic MSYS2 installation, the following packages must
|
||
also be installed:</p>
|
||
<ul>
|
||
<li><code>autoconf</code></li>
|
||
<li><code>tar</code></li>
|
||
<li><code>make</code></li>
|
||
<li><code>zip</code></li>
|
||
<li><code>unzip</code></li>
|
||
</ul>
|
||
<p>You can install these packages using the following command line:</p>
|
||
<pre><code>pacman -S autoconf tar make zip unzip</code></pre>
|
||
<h4 id="windows-subsystem-for-linux-wsl">Windows Subsystem for Linux
|
||
(WSL)</h4>
|
||
<p>WSL comes in two flavors, WSL1 and WSL2. These are drastically
|
||
different under the hood. WSL1 runs the binaries natively by translating
|
||
Linux kernel calls into Windows kernel calls, while WSL2 runs Linux in a
|
||
virtual machine. Both solutions have their pros and cons, and you might
|
||
need to test both before deciding which works best for you. Both WSL1
|
||
and WSL2 are supported, but to varying degrees.</p>
|
||
<p>To use WSL for building the JDK, you will need Windows 10 version
|
||
1809 or later, and you will need to install an Ubuntu guest.</p>
|
||
<p>It is possible to build both Windows and Linux binaries from WSL. To
|
||
build Windows binaries, you must use a Windows boot JDK (located in a
|
||
Windows-accessible directory). To build Linux binaries, you must use a
|
||
Linux boot JDK. The default behavior is to build for Windows. To build
|
||
for Linux, pass
|
||
<code>--build=x86_64-unknown-linux-gnu --openjdk-target=x86_64-unknown-linux-gnu</code>
|
||
to <code>configure</code>.</p>
|
||
<p>If building Windows binaries, the source code must be located in a
|
||
Windows- accessible directory. This is because Windows executables (such
|
||
as Visual Studio and the boot JDK) must be able to access the source
|
||
code. Also, the drive where the source is stored must be mounted as
|
||
case-insensitive by changing either /etc/fstab or /etc/wsl.conf in WSL.
|
||
Individual directories may be corrected using the fsutil tool in case
|
||
the source was cloned before changing the mount options.</p>
|
||
<p>Note that while it's possible to build on WSL, testing is still not
|
||
fully supported.</p>
|
||
<h3 id="macos">macOS</h3>
|
||
<p>Apple is using a quite aggressive scheme of pushing OS updates, and
|
||
coupling these updates with required updates of Xcode. Unfortunately,
|
||
this makes it difficult for a project such as the JDK to keep pace with
|
||
a continuously updated machine running macOS. See the section on <a
|
||
href="#apple-xcode">Apple Xcode</a> on some strategies to deal with
|
||
this.</p>
|
||
<p>It is recommended that you use at least macOS 13 (Ventura) and Xcode
|
||
14, but earlier versions may also work.</p>
|
||
<p>The standard macOS environment contains the basic tooling needed to
|
||
build, but for external libraries a package manager is recommended. The
|
||
JDK uses <a href="https://brew.sh/">homebrew</a> in the examples, but
|
||
feel free to use whatever manager you want (or none).</p>
|
||
<h3 id="linux">Linux</h3>
|
||
<p>It is often not much problem to build the JDK on Linux. The only
|
||
general advice is to try to use the compilers, external libraries and
|
||
header files as provided by your distribution.</p>
|
||
<p>The basic tooling is provided as part of the core operating system,
|
||
but you will most likely need to install developer packages.</p>
|
||
<p>For apt-based distributions (Debian, Ubuntu, etc), try this:</p>
|
||
<pre><code>sudo apt-get install build-essential autoconf</code></pre>
|
||
<p>For rpm-based distributions (Fedora, Red Hat, etc), try this:</p>
|
||
<pre><code>sudo yum groupinstall "Development Tools"</code></pre>
|
||
<p>For Alpine Linux, aside from basic tooling, install the GNU versions
|
||
of some programs:</p>
|
||
<pre><code>sudo apk add build-base bash grep zip</code></pre>
|
||
<h3 id="aix">AIX</h3>
|
||
<p>Please consult the AIX section of the <a
|
||
href="https://wiki.openjdk.org/display/Build/Supported+Build+Platforms">Supported
|
||
Build Platforms</a> OpenJDK Build Wiki page for details about which
|
||
versions of AIX are supported.</p>
|
||
<h2 id="native-compiler-toolchain-requirements">Native Compiler
|
||
(Toolchain) Requirements</h2>
|
||
<p>Large portions of the JDK consists of native code, that needs to be
|
||
compiled to be able to run on the target platform. In theory, toolchain
|
||
and operating system should be independent factors, but in practice
|
||
there's more or less a one-to-one correlation between target operating
|
||
system and toolchain.</p>
|
||
<table>
|
||
<thead>
|
||
<tr class="header">
|
||
<th>Operating system</th>
|
||
<th>Supported toolchain</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr class="odd">
|
||
<td>Linux</td>
|
||
<td>gcc, clang</td>
|
||
</tr>
|
||
<tr class="even">
|
||
<td>macOS</td>
|
||
<td>Apple Xcode (using clang)</td>
|
||
</tr>
|
||
<tr class="odd">
|
||
<td>AIX</td>
|
||
<td>IBM Open XL C/C++</td>
|
||
</tr>
|
||
<tr class="even">
|
||
<td>Windows</td>
|
||
<td>Microsoft Visual Studio</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<p>Please see the individual sections on the toolchains for version
|
||
recommendations. As a reference, these versions of the toolchains are
|
||
used, at the time of writing, by Oracle for the daily builds of the JDK.
|
||
It should be possible to compile the JDK with both older and newer
|
||
versions, but the closer you stay to this list, the more likely you are
|
||
to compile successfully without issues.</p>
|
||
<table>
|
||
<thead>
|
||
<tr class="header">
|
||
<th>Operating system</th>
|
||
<th>Toolchain version</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr class="odd">
|
||
<td>Linux</td>
|
||
<td>gcc 13.2.0</td>
|
||
</tr>
|
||
<tr class="even">
|
||
<td>macOS</td>
|
||
<td>Apple Xcode 14.3.1 (using clang 14.0.3)</td>
|
||
</tr>
|
||
<tr class="odd">
|
||
<td>Windows</td>
|
||
<td>Microsoft Visual Studio 2022 version 17.6.5</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<p>All compilers are expected to be able to handle the C11 language
|
||
standard for C, and C++14 for C++.</p>
|
||
<h3 id="gcc">gcc</h3>
|
||
<p>The minimum accepted version of gcc is 10.0. Older versions will not
|
||
be accepted by <code>configure</code>.</p>
|
||
<p>The JDK is currently known to compile successfully with gcc version
|
||
13.2 or newer.</p>
|
||
<p>In general, any version between these two should be usable.</p>
|
||
<h3 id="clang">clang</h3>
|
||
<p>The minimum accepted version of clang is 13. Older versions will not
|
||
be accepted by <code>configure</code>.</p>
|
||
<p>To use clang instead of gcc on Linux, use
|
||
<code>--with-toolchain-type=clang</code>.</p>
|
||
<h3 id="apple-xcode">Apple Xcode</h3>
|
||
<p>The oldest supported version of Xcode is 13.0.</p>
|
||
<p>You will need to download Xcode either from the App Store or specific
|
||
versions can be easily located via the <a
|
||
href="https://xcodereleases.com">Xcode Releases</a> website.</p>
|
||
<p>When updating Xcode, it is advisable to keep an older version for
|
||
building the JDK. To use a specific version of Xcode you have multiple
|
||
options:</p>
|
||
<ul>
|
||
<li>Use <code>xcode-select -s</code> before running
|
||
<code>configure</code>, e.g.
|
||
<code>xcode-select -s /Applications/Xcode13.1.app</code>. The drawback
|
||
is that the setting is system wide and you may have to revert it after a
|
||
JDK build.</li>
|
||
<li>Use configure option <code>--with-xcode-path</code>, e.g.
|
||
<code>configure --with-xcode-path=/Applications/Xcode13.1.app</code>
|
||
This allows using a specific Xcode version for a JDK build,
|
||
independently of the active Xcode version by
|
||
<code>xcode-select</code>.</li>
|
||
</ul>
|
||
<p>If you have recently (inadvertently) updated your OS and/or Xcode
|
||
version, and the JDK can no longer be built, please see the section on
|
||
<a href="#problems-with-the-build-environment">Problems with the Build
|
||
Environment</a>, and <a href="#getting-help">Getting Help</a> to find
|
||
out if there are any recent, non-merged patches available for this
|
||
update.</p>
|
||
<h3 id="microsoft-visual-studio">Microsoft Visual Studio</h3>
|
||
<p>The minimum accepted version is Visual Studio 2019 version 16.8.
|
||
(Note that this version is often presented as "MSVC 14.28", and reported
|
||
by cl.exe as 19.28.) Older versions will not be accepted by
|
||
<code>configure</code> and will not work. The maximum accepted version
|
||
of Visual Studio is 2022.</p>
|
||
<p>If you have multiple versions of Visual Studio installed,
|
||
<code>configure</code> will by default pick the latest. You can request
|
||
a specific version to be used by setting
|
||
<code>--with-toolchain-version</code>, e.g.
|
||
<code>--with-toolchain-version=2022</code>.</p>
|
||
<p>If you have Visual Studio installed but <code>configure</code> fails
|
||
to detect it, it may be because of <a href="#spaces-in-path">spaces in
|
||
path</a>.</p>
|
||
<p>You must install the US English locale, otherwise the build system
|
||
might not be able to interact properly with the compiler. You can add
|
||
additional language packs when installing Visual Studio.</p>
|
||
<p>If you have already installed Visual Studio without the US English
|
||
language pack, you can modify the installation to add this. You can
|
||
either do this via a GUI like this:</p>
|
||
<ul>
|
||
<li>Click on "Visual Studio Installer" in Start menu.</li>
|
||
<li>Click "Modify".</li>
|
||
<li>Select the tab "Language packs".</li>
|
||
<li>Choose "English".</li>
|
||
<li>Click "Modify".</li>
|
||
</ul>
|
||
<p>or you can run it on the command line. For this to work, you need to
|
||
start <code>cmd.exe</code> using "Run as Administrator". Then execute
|
||
the following line: (note that the " characters are essential)</p>
|
||
<pre><code>"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vs_installer.exe" modify --channelId VisualStudio.16.Release --productId Microsoft.VisualStudio.Product.BuildTools --addProductLang en-us -p</code></pre>
|
||
<p><code>VisualStudio.16.Release</code> represent VS 2019, so adjust the
|
||
version number accordingly. If you have not installed the
|
||
<code>BuildTools</code>, but e.g. <code>Professional</code>, adjust the
|
||
product ID accordingly.</p>
|
||
<h3 id="ibm-open-xl-cc">IBM Open XL C/C++</h3>
|
||
<p>The minimum accepted version of Open XL is 17.1.1.4. This is in
|
||
essence clang 15, and will be treated as such by the OpenJDK build
|
||
system.</p>
|
||
<h2 id="boot-jdk-requirements">Boot JDK Requirements</h2>
|
||
<p>Paradoxically, building the JDK requires a pre-existing JDK. This is
|
||
called the "boot JDK". The boot JDK does not, however, have to be a JDK
|
||
built directly from the source code available in the OpenJDK Community.
|
||
If you are porting the JDK to a new platform, chances are that there
|
||
already exists another JDK for that platform that is usable as boot
|
||
JDK.</p>
|
||
<p>The rule of thumb is that the boot JDK for building JDK major version
|
||
<em>N</em> should be a JDK of major version <em>N-1</em>, so for
|
||
building JDK 18 a JDK 17 would be suitable as boot JDK. However, the JDK
|
||
should be able to "build itself", so an up-to-date build of the current
|
||
JDK source is an acceptable alternative. If you are following the
|
||
<em>N-1</em> rule, make sure you've got the latest update version, since
|
||
e.g. JDK 8 GA might not be able to build JDK 9 on all platforms.</p>
|
||
<p>Early in the release cycle, version <em>N-1</em> may not yet have
|
||
been released. In that case, the preferred boot JDK will be version
|
||
<em>N-2</em> until version <em>N-1</em> is available.</p>
|
||
<p>The <code>configure</code> scripts tries to locate a suitable boot
|
||
JDK automatically, but due to the lack of standard installation
|
||
locations on most platforms, this heuristics has a high likelihood to
|
||
fail. If the boot JDK is not automatically detected, or the wrong JDK is
|
||
picked, use <code>--with-boot-jdk</code> to point to the JDK to use.</p>
|
||
<h3 id="getting-jdk-binaries">Getting JDK Binaries</h3>
|
||
<p>An overview of common ways to download and install prebuilt JDK
|
||
binaries can be found on https://openjdk.org/install. An alternative is
|
||
to download the <a
|
||
href="https://www.oracle.com/java/technologies/downloads">Oracle
|
||
JDK</a>. Another is <a href="https://adoptium.net/">Adoptium</a>, which
|
||
publishes prebuilt binaries for various platforms.</p>
|
||
<p>On Linux you can also get a JDK from the Linux distribution. On
|
||
apt-based distros (like Debian and Ubuntu),
|
||
<code>sudo apt-get install openjdk-<VERSION>-jdk</code> is
|
||
typically enough to install a JDK <VERSION>. On rpm-based distros
|
||
(like Fedora and Red Hat), try
|
||
<code>sudo yum install java-<VERSION>-openjdk-devel</code>.</p>
|
||
<h2 id="external-library-requirements">External Library
|
||
Requirements</h2>
|
||
<p>Different platforms require different external libraries. In general,
|
||
libraries are not optional - that is, they are either required or not
|
||
used.</p>
|
||
<p>If a required library is not detected by <code>configure</code>, you
|
||
need to provide the path to it. There are two forms of the
|
||
<code>configure</code> arguments to point to an external library:
|
||
<code>--with-<LIB>=<path></code> or
|
||
<code>--with-<LIB>-include=<path to include> --with-<LIB>-lib=<path to lib></code>.</p>
|
||
<p>The first variant is more concise, but require the include files and
|
||
library files to reside in a default hierarchy under this directory. In
|
||
most cases, it works fine. As a fallback, the second version allows you
|
||
to point to the include directory and the lib directory separately.</p>
|
||
<h3 id="freetype">FreeType</h3>
|
||
<p>FreeType2 from <a href="https://www.freetype.org/">The FreeType
|
||
Project</a> is not required on any platform. The exception is on
|
||
Unix-based platforms when configuring such that the build artifacts will
|
||
reference a system installed library, rather than bundling the JDK's own
|
||
copy.</p>
|
||
<ul>
|
||
<li>To install on an apt-based Linux, try running
|
||
<code>sudo apt-get install libfreetype6-dev</code>.</li>
|
||
<li>To install on an rpm-based Linux, try running
|
||
<code>sudo yum install freetype-devel</code>.</li>
|
||
<li>To install on Alpine Linux, try running
|
||
<code>sudo apk add freetype-dev</code>.</li>
|
||
<li>To install on macOS, try running
|
||
<code>brew install freetype</code>.</li>
|
||
</ul>
|
||
<p>Use <code>--with-freetype-include=<path></code> and
|
||
<code>--with-freetype-lib=<path></code> if <code>configure</code>
|
||
does not automatically locate the platform FreeType files.</p>
|
||
<h3 id="fontconfig">Fontconfig</h3>
|
||
<p>Fontconfig from <a href="https://fontconfig.org">freedesktop.org
|
||
Fontconfig</a> is required on all platforms except Windows and
|
||
macOS.</p>
|
||
<ul>
|
||
<li>To install on an apt-based Linux, try running
|
||
<code>sudo apt-get install libfontconfig-dev</code>.</li>
|
||
<li>To install on an rpm-based Linux, try running
|
||
<code>sudo yum install fontconfig-devel</code>.</li>
|
||
<li>To install on Alpine Linux, try running
|
||
<code>sudo apk add fontconfig-dev</code>.</li>
|
||
</ul>
|
||
<p>Use <code>--with-fontconfig-include=<path></code> and
|
||
<code>--with-fontconfig=<path></code> if <code>configure</code>
|
||
does not automatically locate the platform Fontconfig files.</p>
|
||
<h3 id="cups">CUPS</h3>
|
||
<p>CUPS, <a href="https://www.cups.org">Common UNIX Printing System</a>
|
||
header files are required on all platforms, except Windows. Often these
|
||
files are provided by your operating system.</p>
|
||
<ul>
|
||
<li>To install on an apt-based Linux, try running
|
||
<code>sudo apt-get install libcups2-dev</code>.</li>
|
||
<li>To install on an rpm-based Linux, try running
|
||
<code>sudo yum install cups-devel</code>.</li>
|
||
<li>To install on Alpine Linux, try running
|
||
<code>sudo apk add cups-dev</code>.</li>
|
||
</ul>
|
||
<p>Use <code>--with-cups=<path></code> if <code>configure</code>
|
||
does not properly locate your CUPS files.</p>
|
||
<h3 id="x11">X11</h3>
|
||
<p>Certain <a href="https://www.x.org/">X11</a> libraries and include
|
||
files are required on Linux.</p>
|
||
<ul>
|
||
<li>To install on an apt-based Linux, try running
|
||
<code>sudo apt-get install libx11-dev libxext-dev libxrender-dev libxrandr-dev libxtst-dev libxt-dev</code>.</li>
|
||
<li>To install on an rpm-based Linux, try running
|
||
<code>sudo yum install libXtst-devel libXt-devel libXrender-devel libXrandr-devel libXi-devel</code>.</li>
|
||
<li>To install on Alpine Linux, try running
|
||
<code>sudo apk add libx11-dev libxext-dev libxrender-dev libxrandr-dev libxtst-dev libxt-dev</code>.</li>
|
||
</ul>
|
||
<p>Use <code>--with-x=<path></code> if <code>configure</code> does
|
||
not properly locate your X11 files.</p>
|
||
<h3 id="alsa">ALSA</h3>
|
||
<p>ALSA, <a href="https://www.alsa-project.org/">Advanced Linux Sound
|
||
Architecture</a> is required on Linux. At least version 0.9.1 of ALSA is
|
||
required.</p>
|
||
<ul>
|
||
<li>To install on an apt-based Linux, try running
|
||
<code>sudo apt-get install libasound2-dev</code>.</li>
|
||
<li>To install on an rpm-based Linux, try running
|
||
<code>sudo yum install alsa-lib-devel</code>.</li>
|
||
<li>To install on Alpine Linux, try running
|
||
<code>sudo apk add alsa-lib-dev</code>.</li>
|
||
</ul>
|
||
<p>Use <code>--with-alsa=<path></code> if <code>configure</code>
|
||
does not properly locate your ALSA files.</p>
|
||
<h3 id="libffi">libffi</h3>
|
||
<p>libffi, the <a href="https://sourceware.org/libffi">Portable Foreign
|
||
Function Interface Library</a> is required when building the Zero
|
||
version of Hotspot.</p>
|
||
<ul>
|
||
<li>To install on an apt-based Linux, try running
|
||
<code>sudo apt-get install libffi-dev</code>.</li>
|
||
<li>To install on an rpm-based Linux, try running
|
||
<code>sudo yum install libffi-devel</code>.</li>
|
||
<li>To install on Alpine Linux, try running
|
||
<code>sudo apk add libffi-dev</code>.</li>
|
||
</ul>
|
||
<p>Use <code>--with-libffi=<path></code> if <code>configure</code>
|
||
does not properly locate your libffi files.</p>
|
||
<h2 id="build-tools-requirements">Build Tools Requirements</h2>
|
||
<h3 id="autoconf">Autoconf</h3>
|
||
<p>The JDK build requires <a
|
||
href="https://www.gnu.org/software/autoconf">Autoconf</a> on all
|
||
platforms. At least version 2.69 is required.</p>
|
||
<ul>
|
||
<li>To install on an apt-based Linux, try running
|
||
<code>sudo apt-get install autoconf</code>.</li>
|
||
<li>To install on an rpm-based Linux, try running
|
||
<code>sudo yum install autoconf</code>.</li>
|
||
<li>To install on Alpine Linux, try running
|
||
<code>sudo apk add autoconf</code>.</li>
|
||
<li>To install on macOS, try running
|
||
<code>brew install autoconf</code>.</li>
|
||
<li>To install on Windows, try running
|
||
<code><path to Cygwin setup>/setup-x86_64 -q -P autoconf</code>.</li>
|
||
</ul>
|
||
<p>If <code>configure</code> has problems locating your installation of
|
||
autoconf, you can specify it using the <code>AUTOCONF</code> environment
|
||
variable, like this:</p>
|
||
<pre><code>AUTOCONF=<path to autoconf> configure ...</code></pre>
|
||
<h3 id="gnu-make">GNU Make</h3>
|
||
<p>The JDK build requires <a
|
||
href="https://www.gnu.org/software/make">GNU Make</a>. No other flavors
|
||
of make are supported.</p>
|
||
<p>At least version 3.81 of GNU Make must be used. For distributions
|
||
supporting GNU Make 4.0 or above, we strongly recommend it. GNU Make 4.0
|
||
contains useful functionality to handle parallel building (supported by
|
||
<code>--with-output-sync</code>) and speed and stability
|
||
improvements.</p>
|
||
<p>Note that <code>configure</code> locates and verifies a properly
|
||
functioning version of <code>make</code> and stores the path to this
|
||
<code>make</code> binary in the configuration. If you start a build
|
||
using <code>make</code> on the command line, you will be using the
|
||
version of make found first in your <code>PATH</code>, and not
|
||
necessarily the one stored in the configuration. This initial make will
|
||
be used as "bootstrap make", and in a second stage, the make located by
|
||
<code>configure</code> will be called. Normally, this will present no
|
||
issues, but if you have a very old <code>make</code>, or a non-GNU Make
|
||
<code>make</code> in your path, this might cause issues.</p>
|
||
<p>If you want to override the default make found by
|
||
<code>configure</code>, use the <code>MAKE</code> configure variable,
|
||
e.g. <code>configure MAKE=/opt/gnu/make</code>.</p>
|
||
<h3 id="gnu-bash">GNU Bash</h3>
|
||
<p>The JDK build requires <a
|
||
href="https://www.gnu.org/software/bash">GNU Bash</a>. No other shells
|
||
are supported.</p>
|
||
<p>At least version 3.2 of GNU Bash must be used.</p>
|
||
<h3 id="graphviz-and-pandoc">Graphviz and Pandoc</h3>
|
||
<p>In order to build the full docs (see the
|
||
<code>--enable-full-docs</code> configure option) <a
|
||
href="https://www.graphviz.org">Graphviz</a> and <a
|
||
href="https://pandoc.org">Pandoc</a> are required. Any recent versions
|
||
should work. For reference, and subject to change, Oracle builds use
|
||
Graphviz 9.0.0 and Pandoc 2.19.2.</p>
|
||
<h2 id="running-configure">Running Configure</h2>
|
||
<p>To build the JDK, you need a "configuration", which consists of a
|
||
directory where to store the build output, coupled with information
|
||
about the platform, the specific build machine, and choices that affect
|
||
how the JDK is built.</p>
|
||
<p>The configuration is created by the <code>configure</code> script.
|
||
The basic invocation of the <code>configure</code> script looks like
|
||
this:</p>
|
||
<pre><code>bash configure [options]</code></pre>
|
||
<p>This will create an output directory containing the configuration and
|
||
setup an area for the build result. This directory typically looks like
|
||
<code>build/linux-x64-server-release</code>, but the actual name depends
|
||
on your specific configuration. (It can also be set directly, see <a
|
||
href="#using-multiple-configurations">Using Multiple
|
||
Configurations</a>). This directory is referred to as
|
||
<code>$BUILD</code> in this documentation.</p>
|
||
<p><code>configure</code> will try to figure out what system you are
|
||
running on and where all necessary build components are. If you have all
|
||
prerequisites for building installed, it should find everything. If it
|
||
fails to detect any component automatically, it will exit and inform you
|
||
about the problem.</p>
|
||
<p>Some command line examples:</p>
|
||
<ul>
|
||
<li><p>Create a 32-bit build for Windows with FreeType2 in
|
||
<code>C:\freetype-i586</code>:</p>
|
||
<pre><code>bash configure --with-freetype=/cygdrive/c/freetype-i586 --with-target-bits=32</code></pre></li>
|
||
<li><p>Create a debug build with the <code>server</code> JVM and DTrace
|
||
enabled:</p>
|
||
<pre><code>bash configure --enable-debug --with-jvm-variants=server --enable-dtrace</code></pre></li>
|
||
</ul>
|
||
<h3 id="common-configure-arguments">Common Configure Arguments</h3>
|
||
<p>Here follows some of the most common and important
|
||
<code>configure</code> argument.</p>
|
||
<p>To get up-to-date information on <em>all</em> available
|
||
<code>configure</code> argument, please run:</p>
|
||
<pre><code>bash configure --help</code></pre>
|
||
<p>(Note that this help text also include general autoconf options, like
|
||
<code>--dvidir</code>, that is not relevant to the JDK. To list only
|
||
JDK-specific features, use <code>bash configure --help=short</code>
|
||
instead.)</p>
|
||
<h4 id="configure-arguments-for-tailoring-the-build">Configure Arguments
|
||
for Tailoring the Build</h4>
|
||
<ul>
|
||
<li><code>--enable-debug</code> - Set the debug level to
|
||
<code>fastdebug</code> (this is a shorthand for
|
||
<code>--with-debug-level=fastdebug</code>)</li>
|
||
<li><code>--with-debug-level=<level></code> - Set the debug level,
|
||
which can be <code>release</code>, <code>fastdebug</code>,
|
||
<code>slowdebug</code> or <code>optimized</code>. Default is
|
||
<code>release</code>. <code>optimized</code> is variant of
|
||
<code>release</code> with additional Hotspot debug code.</li>
|
||
<li><code>--with-native-debug-symbols=<method></code> - Specify if
|
||
and how native debug symbols should be built. Available methods are
|
||
<code>none</code>, <code>internal</code>, <code>external</code>,
|
||
<code>zipped</code>. Default behavior depends on platform. See <a
|
||
href="#native-debug-symbols">Native Debug Symbols</a> for more
|
||
details.</li>
|
||
<li><code>--with-version-string=<string></code> - Specify the
|
||
version string this build will be identified with.</li>
|
||
<li><code>--with-version-<part>=<value></code> - A group of
|
||
options, where <code><part></code> can be any of <code>pre</code>,
|
||
<code>opt</code>, <code>build</code>, <code>major</code>,
|
||
<code>minor</code>, <code>security</code> or <code>patch</code>. Use
|
||
these options to modify just the corresponding part of the version
|
||
string from the default, or the value provided by
|
||
<code>--with-version-string</code>.</li>
|
||
<li><code>--with-jvm-variants=<variant>[,<variant>...]</code>
|
||
- Build the specified variant (or variants) of Hotspot. Valid variants
|
||
are: <code>server</code>, <code>client</code>, <code>minimal</code>,
|
||
<code>core</code>, <code>zero</code>, <code>custom</code>. Note that not
|
||
all variants are possible to combine in a single build.</li>
|
||
<li><code>--enable-jvm-feature-<feature></code> or
|
||
<code>--disable-jvm-feature-<feature></code> - Include (or
|
||
exclude) <code><feature></code> as a JVM feature in Hotspot. You
|
||
can also specify a list of features to be enabled, separated by space or
|
||
comma, as
|
||
<code>--with-jvm-features=<feature>[,<feature>...]</code>.
|
||
If you prefix <code><feature></code> with a <code>-</code>, it
|
||
will be disabled. These options will modify the default list of features
|
||
for the JVM variant(s) you are building. For the <code>custom</code> JVM
|
||
variant, the default list is empty. A complete list of valid JVM
|
||
features can be found using <code>bash configure --help</code>.</li>
|
||
<li><code>--with-target-bits=<bits></code> - Create a target
|
||
binary suitable for running on a <code><bits></code> platform. Use
|
||
this to create 32-bit output on a 64-bit build platform, instead of
|
||
doing a full cross-compile. (This is known as a <em>reduced</em>
|
||
build.)</li>
|
||
</ul>
|
||
<p>On Linux, BSD and AIX, it is possible to override where Java by
|
||
default searches for runtime/JNI libraries. This can be useful in
|
||
situations where there is a special shared directory for system JNI
|
||
libraries. This setting can in turn be overridden at runtime by setting
|
||
the <code>java.library.path</code> property.</p>
|
||
<ul>
|
||
<li><code>--with-jni-libpath=<path></code> - Use the specified
|
||
path as a default when searching for runtime libraries.</li>
|
||
</ul>
|
||
<h4 id="configure-arguments-for-native-compilation">Configure Arguments
|
||
for Native Compilation</h4>
|
||
<ul>
|
||
<li><code>--with-devkit=<path></code> - Use this devkit for
|
||
compilers, tools and resources</li>
|
||
<li><code>--with-sysroot=<path></code> - Use this directory as
|
||
sysroot</li>
|
||
<li><code>--with-extra-path=<path>[;<path>]</code> - Prepend
|
||
these directories to the default path when searching for all kinds of
|
||
binaries</li>
|
||
<li><code>--with-toolchain-path=<path>[;<path>]</code> -
|
||
Prepend these directories when searching for toolchain binaries
|
||
(compilers etc)</li>
|
||
<li><code>--with-extra-cflags=<flags></code> - Append these flags
|
||
when compiling JDK C files</li>
|
||
<li><code>--with-extra-cxxflags=<flags></code> - Append these
|
||
flags when compiling JDK C++ files</li>
|
||
<li><code>--with-extra-ldflags=<flags></code> - Append these flags
|
||
when linking JDK libraries</li>
|
||
</ul>
|
||
<h4 id="configure-arguments-for-external-dependencies">Configure
|
||
Arguments for External Dependencies</h4>
|
||
<ul>
|
||
<li><code>--with-boot-jdk=<path></code> - Set the path to the <a
|
||
href="#boot-jdk-requirements">Boot JDK</a></li>
|
||
<li><code>--with-freetype=<path></code> - Set the path to <a
|
||
href="#freetype">FreeType</a></li>
|
||
<li><code>--with-cups=<path></code> - Set the path to <a
|
||
href="#cups">CUPS</a></li>
|
||
<li><code>--with-x=<path></code> - Set the path to <a
|
||
href="#x11">X11</a></li>
|
||
<li><code>--with-alsa=<path></code> - Set the path to <a
|
||
href="#alsa">ALSA</a></li>
|
||
<li><code>--with-libffi=<path></code> - Set the path to <a
|
||
href="#libffi">libffi</a></li>
|
||
<li><code>--with-jtreg=<path></code> - Set the path to JTReg. See
|
||
<a href="#running-tests">Running Tests</a></li>
|
||
</ul>
|
||
<p>Certain third-party libraries used by the JDK (libjpeg, giflib,
|
||
libpng, lcms and zlib) are included in the JDK repository. The default
|
||
behavior of the JDK build is to use the included ("bundled") versions of
|
||
libjpeg, giflib, libpng and lcms. For zlib, the system lib (if present)
|
||
is used except on Windows and AIX. However the bundled libraries may be
|
||
replaced by an external version. To do so, specify <code>system</code>
|
||
as the <code><source></code> option in these arguments. (The
|
||
default is <code>bundled</code>).</p>
|
||
<ul>
|
||
<li><code>--with-libjpeg=<source></code> - Use the specified
|
||
source for libjpeg</li>
|
||
<li><code>--with-giflib=<source></code> - Use the specified source
|
||
for giflib</li>
|
||
<li><code>--with-libpng=<source></code> - Use the specified source
|
||
for libpng</li>
|
||
<li><code>--with-lcms=<source></code> - Use the specified source
|
||
for lcms</li>
|
||
<li><code>--with-zlib=<source></code> - Use the specified source
|
||
for zlib</li>
|
||
</ul>
|
||
<p>On Linux, it is possible to select either static or dynamic linking
|
||
of the C++ runtime. The default is static linking, with dynamic linking
|
||
as fallback if the static library is not found.</p>
|
||
<ul>
|
||
<li><code>--with-stdc++lib=<method></code> - Use the specified
|
||
method (<code>static</code>, <code>dynamic</code> or
|
||
<code>default</code>) for linking the C++ runtime.</li>
|
||
</ul>
|
||
<h3 id="configure-control-variables">Configure Control Variables</h3>
|
||
<p>It is possible to control certain aspects of <code>configure</code>
|
||
by overriding the value of <code>configure</code> variables, either on
|
||
the command line or in the environment.</p>
|
||
<p>Normally, this is <strong>not recommended</strong>. If used
|
||
improperly, it can lead to a broken configuration. Unless you're well
|
||
versed in the build system, this is hard to use properly. Therefore,
|
||
<code>configure</code> will print a warning if this is detected.</p>
|
||
<p>However, there are a few <code>configure</code> variables, known as
|
||
<em>control variables</em> that are supposed to be overridden on the
|
||
command line. These are variables that describe the location of tools
|
||
needed by the build, like <code>MAKE</code> or <code>GREP</code>. If any
|
||
such variable is specified, <code>configure</code> will use that value
|
||
instead of trying to autodetect the tool. For instance,
|
||
<code>bash configure MAKE=/opt/gnumake4.0/bin/make</code>.</p>
|
||
<p>If a configure argument exists, use that instead, e.g. use
|
||
<code>--with-jtreg</code> instead of setting <code>JTREGEXE</code>.</p>
|
||
<p>Also note that, despite what autoconf claims, setting
|
||
<code>CFLAGS</code> will not accomplish anything. Instead use
|
||
<code>--with-extra-cflags</code> (and similar for <code>cxxflags</code>
|
||
and <code>ldflags</code>).</p>
|
||
<h2 id="running-make">Running Make</h2>
|
||
<p>When you have a proper configuration, all you need to do to build the
|
||
JDK is to run <code>make</code>. (But see the warning at <a
|
||
href="#gnu-make">GNU Make</a> about running the correct version of
|
||
make.)</p>
|
||
<p>When running <code>make</code> without any arguments, the default
|
||
target is used, which is the same as running <code>make default</code>
|
||
or <code>make jdk</code>. This will build a minimal (or roughly minimal)
|
||
set of compiled output (known as an "exploded image") needed for a
|
||
developer to actually execute the newly built JDK. The idea is that in
|
||
an incremental development fashion, when doing a normal make, you should
|
||
only spend time recompiling what's changed (making it purely
|
||
incremental) and only do the work that's needed to actually run and test
|
||
your code.</p>
|
||
<p>The output of the exploded image resides in <code>$BUILD/jdk</code>.
|
||
You can test the newly built JDK like this:
|
||
<code>$BUILD/jdk/bin/java -version</code>.</p>
|
||
<h3 id="common-make-targets">Common Make Targets</h3>
|
||
<p>Apart from the default target, here are some common make targets:</p>
|
||
<ul>
|
||
<li><code>hotspot</code> - Build all of hotspot (but only hotspot)</li>
|
||
<li><code>hotspot-<variant></code> - Build just the specified jvm
|
||
variant</li>
|
||
<li><code>images</code> or <code>product-images</code> - Build the JDK
|
||
image</li>
|
||
<li><code>docs</code> or <code>docs-image</code> - Build the
|
||
documentation image</li>
|
||
<li><code>test-image</code> - Build the test image</li>
|
||
<li><code>all</code> or <code>all-images</code> - Build all images
|
||
(product, docs and test)</li>
|
||
<li><code>bootcycle-images</code> - Build images twice, second time with
|
||
newly built JDK (good for testing)</li>
|
||
<li><code>clean</code> - Remove all files generated by make, but not
|
||
those generated by configure</li>
|
||
<li><code>dist-clean</code> - Remove all files, including
|
||
configuration</li>
|
||
</ul>
|
||
<p>Run <code>make help</code> to get an up-to-date list of important
|
||
make targets and make control variables.</p>
|
||
<p>It is possible to build just a single module, a single phase, or a
|
||
single phase of a single module, by creating make targets according to
|
||
these following patterns. A phase can be either of <code>gensrc</code>,
|
||
<code>gendata</code>, <code>copy</code>, <code>java</code>,
|
||
<code>launchers</code>, or <code>libs</code>. See <a
|
||
href="#using-fine-grained-make-targets">Using Fine-Grained Make
|
||
Targets</a> for more details about this functionality.</p>
|
||
<ul>
|
||
<li><code><phase></code> - Build the specified phase and
|
||
everything it depends on</li>
|
||
<li><code><module></code> - Build the specified module and
|
||
everything it depends on</li>
|
||
<li><code><module>-<phase></code> - Compile the specified
|
||
phase for the specified module and everything it depends on</li>
|
||
</ul>
|
||
<p>Similarly, it is possible to clean just a part of the build by
|
||
creating make targets according to these patterns:</p>
|
||
<ul>
|
||
<li><code>clean-<outputdir></code> - Remove the subdir in the
|
||
output dir with the name</li>
|
||
<li><code>clean-<phase></code> - Remove all build results related
|
||
to a certain build phase</li>
|
||
<li><code>clean-<module></code> - Remove all build results related
|
||
to a certain module</li>
|
||
<li><code>clean-<module>-<phase></code> - Remove all build
|
||
results related to a certain module and phase</li>
|
||
</ul>
|
||
<h3 id="make-control-variables">Make Control Variables</h3>
|
||
<p>It is possible to control <code>make</code> behavior by overriding
|
||
the value of <code>make</code> variables, either on the command line or
|
||
in the environment.</p>
|
||
<p>Normally, this is <strong>not recommended</strong>. If used
|
||
improperly, it can lead to a broken build. Unless you're well versed in
|
||
the build system, this is hard to use properly. Therefore,
|
||
<code>make</code> will print a warning if this is detected.</p>
|
||
<p>However, there are a few <code>make</code> variables, known as
|
||
<em>control variables</em> that are supposed to be overridden on the
|
||
command line. These make up the "make time" configuration, as opposed to
|
||
the "configure time" configuration.</p>
|
||
<h4 id="general-make-control-variables">General Make Control
|
||
Variables</h4>
|
||
<ul>
|
||
<li><code>JOBS</code> - Specify the number of jobs to build with. See <a
|
||
href="#build-performance">Build Performance</a>.</li>
|
||
<li><code>LOG</code> - Specify the logging level and functionality. See
|
||
<a href="#checking-the-build-log-file">Checking the Build Log
|
||
File</a></li>
|
||
<li><code>CONF</code> and <code>CONF_NAME</code> - Selecting the
|
||
configuration(s) to use. See <a
|
||
href="#using-multiple-configurations">Using Multiple
|
||
Configurations</a></li>
|
||
</ul>
|
||
<h4 id="test-make-control-variables">Test Make Control Variables</h4>
|
||
<p>These make control variables only make sense when running tests.
|
||
Please see <strong>Testing the JDK</strong> (<a
|
||
href="testing.html">html</a>, <a href="testing.md">markdown</a>) for
|
||
details.</p>
|
||
<ul>
|
||
<li><code>TEST</code></li>
|
||
<li><code>TEST_JOBS</code></li>
|
||
<li><code>TEST_OPTS</code></li>
|
||
<li><code>TEST_VM_OPTS</code></li>
|
||
<li><code>JTREG</code></li>
|
||
<li><code>GTEST</code></li>
|
||
<li><code>MICRO</code></li>
|
||
</ul>
|
||
<h4 id="advanced-make-control-variables">Advanced Make Control
|
||
Variables</h4>
|
||
<p>These advanced make control variables can be potentially unsafe. See
|
||
<a href="#hints-and-suggestions-for-advanced-users">Hints and
|
||
Suggestions for Advanced Users</a> and <a
|
||
href="#understanding-the-build-system">Understanding the Build
|
||
System</a> for details.</p>
|
||
<ul>
|
||
<li><code>SPEC</code></li>
|
||
<li><code>CONF_CHECK</code></li>
|
||
<li><code>COMPARE_BUILD</code></li>
|
||
<li><code>JDK_FILTER</code></li>
|
||
<li><code>SPEC_FILTER</code></li>
|
||
</ul>
|
||
<h2 id="running-tests">Running Tests</h2>
|
||
<p>Most of the JDK tests are using the <a
|
||
href="https://openjdk.org/jtreg">JTReg</a> test framework. Make sure
|
||
that your configuration knows where to find your installation of JTReg.
|
||
If this is not picked up automatically, use the
|
||
<code>--with-jtreg=<path to jtreg home></code> option to point to
|
||
the JTReg framework. Note that this option should point to the JTReg
|
||
home, i.e. the top directory, containing <code>lib/jtreg.jar</code>
|
||
etc.</p>
|
||
<p>The <a href="https://wiki.openjdk.org/display/Adoption">Adoption
|
||
Group</a> provides recent builds of jtreg <a
|
||
href="https://ci.adoptium.net/view/Dependencies/job/dependency_pipeline/lastSuccessfulBuild/artifact/jtreg/">here</a>.
|
||
Download the latest <code>.tar.gz</code> file, unpack it, and point
|
||
<code>--with-jtreg</code> to the <code>jtreg</code> directory that you
|
||
just unpacked.</p>
|
||
<p>Building of Hotspot Gtest suite requires the source code of Google
|
||
Test framework. The top directory, which contains both
|
||
<code>googletest</code> and <code>googlemock</code> directories, should
|
||
be specified via <code>--with-gtest</code>. The minimum supported
|
||
version of Google Test is 1.14.0, whose source code can be obtained:</p>
|
||
<ul>
|
||
<li>by downloading and unpacking the source bundle from <a
|
||
href="https://github.com/google/googletest/releases/tag/v1.14.0">here</a>,
|
||
or</li>
|
||
<li>by checking out <code>v1.14.0</code> tag of <code>googletest</code>
|
||
project:
|
||
<code>git clone -b v1.14.0 https://github.com/google/googletest</code></li>
|
||
</ul>
|
||
<p>To execute the most basic tests (tier 1), use:</p>
|
||
<pre><code>make test-tier1</code></pre>
|
||
<p>For more details on how to run tests, please see <strong>Testing the
|
||
JDK</strong> (<a href="testing.html">html</a>, <a
|
||
href="testing.md">markdown</a>).</p>
|
||
<h2 id="signing">Signing</h2>
|
||
<h3 id="macos-1">macOS</h3>
|
||
<p>Modern versions of macOS require applications to be signed and
|
||
notarized before distribution. See Apple's documentation for more
|
||
background on what this means and how it works. To help support this,
|
||
the JDK build can be configured to automatically sign all native
|
||
binaries, and the JDK bundle, with all the options needed for successful
|
||
notarization, as well as all the entitlements required by the JDK. To
|
||
enable <code>hardened</code> signing, use configure parameter
|
||
<code>--with-macosx-codesign=hardened</code> and configure the signing
|
||
identity you wish to use with
|
||
<code>--with-macosx-codesign-identity=<identity></code>. The
|
||
identity refers to a signing identity from Apple that needs to be
|
||
preinstalled on the build host.</p>
|
||
<p>When not signing for distribution with the hardened option, the JDK
|
||
build will still attempt to perform <code>adhoc</code> signing to add
|
||
the special entitlement <code>com.apple.security.get-task-allow</code>
|
||
to each binary. This entitlement is required to be able to dump core
|
||
files from a process. Note that adding this entitlement makes the build
|
||
invalid for notarization, so it is only added when signing in
|
||
<code>debug</code> mode. To explicitly enable this kind of ad hoc
|
||
signing, use configure parameter
|
||
<code>--with-macosx-codesign=debug</code>. It will be enabled by default
|
||
in most cases.</p>
|
||
<p>It's also possible to completely disable any explicit codesign
|
||
operations done by the JDK build using the configure parameter
|
||
<code>--without-macosx-codesign</code>. The exact behavior then depends
|
||
on the architecture. For macOS on x64, it (at least at the time of this
|
||
writing) results in completely unsigned binaries that should still work
|
||
fine for development and debugging purposes. On aarch64, the Xcode
|
||
linker will apply a default "ad hoc" signing, without any entitlements.
|
||
Such a build does not allow dumping core files.</p>
|
||
<p>The default mode "auto" will try for <code>hardened</code> signing if
|
||
the debug level is <code>release</code> and either the default identity
|
||
or the specified identity is valid. If hardened isn't possible, then
|
||
<code>debug</code> signing is chosen if it works. If nothing works, the
|
||
codesign build step is disabled.</p>
|
||
<h2 id="cross-compiling">Cross-Compiling</h2>
|
||
<p>Cross-compiling means using one platform (the <em>build</em>
|
||
platform) to generate output that can ran on another platform (the
|
||
<em>target</em> platform).</p>
|
||
<p>The typical reason for cross-compiling is that the build is performed
|
||
on a more powerful desktop computer, but the resulting binaries will be
|
||
able to run on a different, typically low-performing system. Most of the
|
||
complications that arise when building for embedded is due to this
|
||
separation of <em>build</em> and <em>target</em> systems.</p>
|
||
<p>This requires a more complex setup and build procedure. This section
|
||
assumes you are familiar with cross-compiling in general, and will only
|
||
deal with the particularities of cross-compiling the JDK. If you are new
|
||
to cross-compiling, please see the <a
|
||
href="https://en.wikipedia.org/wiki/Cross_compiler#External_links">external
|
||
links at Wikipedia</a> for a good start on reading materials.</p>
|
||
<p>Cross-compiling the JDK requires you to be able to build both for the
|
||
build platform and for the target platform. The reason for the former is
|
||
that we need to build and execute tools during the build process, both
|
||
native tools and Java tools.</p>
|
||
<p>If all you want to do is to compile a 32-bit version, for the same
|
||
OS, on a 64-bit machine, consider using
|
||
<code>--with-target-bits=32</code> instead of doing a full-blown
|
||
cross-compilation. (While this surely is possible, it's a lot more work
|
||
and will take much longer to build.)</p>
|
||
<p>Setting up a cross-compilation environment by hand is time-consuming
|
||
and error prone. It is highly recommended that you use one of the
|
||
automated methods described in <a
|
||
href="#cross-compiling-the-easy-way">Cross compiling the easy
|
||
way</a>.</p>
|
||
<h3 id="specifying-the-target-platform">Specifying the Target
|
||
Platform</h3>
|
||
<p>You <em>must</em> specify the target platform when cross-compiling.
|
||
Doing so will also automatically turn the build into a cross-compiling
|
||
mode. The simplest way to do this is to use the
|
||
<code>--openjdk-target</code> argument, e.g.
|
||
<code>--openjdk-target=arm-linux-gnueabihf</code>. or
|
||
<code>--openjdk-target=aarch64-oe-linux</code>. This will automatically
|
||
set the <code>--host</code> and <code>--target</code> options for
|
||
autoconf, which can otherwise be confusing. (In autoconf terminology,
|
||
the "target" is known as "host", and "target" is used for building a
|
||
Canadian cross-compiler.)</p>
|
||
<p>If <code>--build</code> has not been explicitly passed to configure,
|
||
<code>--openjdk-target</code> will autodetect the build platform and
|
||
internally set the flag automatically, otherwise the platform that was
|
||
explicitly passed to <code>--build</code> will be used instead.</p>
|
||
<h3 id="boot-jdk-and-build-jdk">Boot JDK and Build JDK</h3>
|
||
<p>When cross-compiling, make sure you use a boot JDK that runs on the
|
||
<em>build</em> system, and not on the <em>target</em> system.</p>
|
||
<p>To be able to build, we need a "Build JDK", which is a JDK built from
|
||
the current sources (that is, the same as the end result of the entire
|
||
build process), but able to run on the <em>build</em> system, and not
|
||
the <em>target</em> system. (In contrast, the Boot JDK should be from an
|
||
older release, e.g. JDK 8 when building JDK 9.)</p>
|
||
<p>The build process will create a minimal Build JDK for you, as part of
|
||
building. To speed up the build, you can use
|
||
<code>--with-build-jdk</code> to <code>configure</code> to point to a
|
||
pre-built Build JDK. Please note that the build result is unpredictable,
|
||
and can possibly break in subtle ways, if the Build JDK does not
|
||
<strong>exactly</strong> match the current sources.</p>
|
||
<h3 id="toolchain-considerations">Toolchain Considerations</h3>
|
||
<p>You will need two copies of your toolchain, one which generates
|
||
output that can run on the target system (the normal, or
|
||
<em>target</em>, toolchain), and one that generates output that can run
|
||
on the build system (the <em>build</em> toolchain).</p>
|
||
<p>If you are cross-compiling using gcc, it is recommended to use the
|
||
gcc standard where you prefix cross-compiling tools with the target
|
||
denominator. If you follow this standard, <code>configure</code> is
|
||
likely to pick up the toolchain correctly.</p>
|
||
<p>The <em>build</em> toolchain will be auto-detected just the same way
|
||
the normal <em>build</em>/<em>target</em> toolchain will be
|
||
auto-detected when not cross-compiling. If this is not what you want, or
|
||
if the auto-detection fails, you can specify a devkit containing the
|
||
<em>build</em> toolchain using <code>--with-build-devkit</code> to
|
||
<code>configure</code>, or by giving <code>BUILD_CC</code> and
|
||
<code>BUILD_CXX</code> arguments.</p>
|
||
<p>It is often helpful to locate the cross-compilation tools, headers
|
||
and libraries in a separate directory, outside the normal path, and
|
||
point out that directory to <code>configure</code>. Do this by setting
|
||
the sysroot (<code>--with-sysroot</code>) and appending the directory
|
||
when searching for cross-compilations tools
|
||
(<code>--with-toolchain-path</code>). As a compact form, you can also
|
||
use <code>--with-devkit</code> to point to a single directory, if it is
|
||
correctly setup. (See <code>make/autoconf/basics.m4</code> for
|
||
details.)</p>
|
||
<h3 id="native-libraries">Native Libraries</h3>
|
||
<p>You will need copies of external native libraries for the
|
||
<em>target</em> system present on the <em>build</em> machine while
|
||
building.</p>
|
||
<p>Take care not to replace the <em>build</em> system's version of these
|
||
libraries by mistake, as that can render the <em>build</em> machine
|
||
unusable.</p>
|
||
<p>Make sure that the libraries you point to (ALSA, X11, etc) are for
|
||
the <em>target</em> platform, not the <em>build</em> platform.</p>
|
||
<h4 id="alsa-1">ALSA</h4>
|
||
<p>You will need alsa libraries suitable for your <em>target</em>
|
||
system. In most cases, using Debian's pre-built libraries work fine.</p>
|
||
<p>Note that alsa is needed even if you only want to build a headless
|
||
JDK.</p>
|
||
<ul>
|
||
<li><p>Go to <a href="https://www.debian.org/distrib/packages">Debian
|
||
Package Search</a>, search for the <code>libasound2</code> and
|
||
<code>libasound2-dev</code> packages for your <em>target</em> system,
|
||
and download them to /tmp.</p></li>
|
||
<li><p>Install the libraries into the cross-compilation toolchain. For
|
||
instance:</p>
|
||
<pre><code>cd /tools/gcc-linaro-arm-linux-gnueabihf-raspbian-2012.09-20120921_linux/arm-linux-gnueabihf/libc
|
||
dpkg-deb -x /tmp/libasound2_1.0.25-4_armhf.deb .
|
||
dpkg-deb -x /tmp/libasound2-dev_1.0.25-4_armhf.deb .</code></pre></li>
|
||
<li><p>If alsa is not properly detected by <code>configure</code>, you
|
||
can specify it by <code>--with-alsa</code>.</p></li>
|
||
</ul>
|
||
<h4 id="x11-1">X11</h4>
|
||
<p>You will need X11 libraries suitable for your <em>target</em> system.
|
||
In most cases, using Debian's pre-built libraries work fine.</p>
|
||
<p>Note that X11 is needed even if you only want to build a headless
|
||
JDK.</p>
|
||
<ul>
|
||
<li><p>Go to <a href="https://www.debian.org/distrib/packages">Debian
|
||
Package Search</a>, search for the following packages for your
|
||
<em>target</em> system, and download them to /tmp/target-x11:</p>
|
||
<ul>
|
||
<li><code>libxi</code></li>
|
||
<li><code>libxi-dev</code></li>
|
||
<li><code>x11proto-core-dev</code></li>
|
||
<li><code>x11proto-input-dev</code></li>
|
||
<li><code>x11proto-kb-dev</code></li>
|
||
<li><code>x11proto-render-dev</code></li>
|
||
<li><code>x11proto-xext-dev</code></li>
|
||
<li><code>libice-dev</code></li>
|
||
<li><code>libxrender</code></li>
|
||
<li><code>libxrender-dev</code></li>
|
||
<li><code>libxrandr-dev</code></li>
|
||
<li><code>libsm-dev</code></li>
|
||
<li><code>libxt-dev</code></li>
|
||
<li><code>libx11</code></li>
|
||
<li><code>libx11-dev</code></li>
|
||
<li><code>libxtst</code></li>
|
||
<li><code>libxtst-dev</code></li>
|
||
<li><code>libxext</code></li>
|
||
<li><code>libxext-dev</code></li>
|
||
</ul></li>
|
||
<li><p>Install the libraries into the cross-compilation toolchain. For
|
||
instance:</p>
|
||
<pre><code>cd /tools/gcc-linaro-arm-linux-gnueabihf-raspbian-2012.09-20120921_linux/arm-linux-gnueabihf/libc/usr
|
||
mkdir X11R6
|
||
cd X11R6
|
||
for deb in /tmp/target-x11/*.deb ; do dpkg-deb -x $deb . ; done
|
||
mv usr/* .
|
||
cd lib
|
||
cp arm-linux-gnueabihf/* .</code></pre>
|
||
<p>You can ignore the following messages, since these libraries are not
|
||
needed to successfully complete a full JDK build.</p>
|
||
<pre><code>cp: cannot stat `arm-linux-gnueabihf/libICE.so': No such file or directory
|
||
cp: cannot stat `arm-linux-gnueabihf/libSM.so': No such file or directory
|
||
cp: cannot stat `arm-linux-gnueabihf/libXt.so': No such file or directory</code></pre></li>
|
||
<li><p>If the X11 libraries are not properly detected by
|
||
<code>configure</code>, you can point them out by
|
||
<code>--with-x</code>.</p></li>
|
||
</ul>
|
||
<h3 id="verifying-the-build">Verifying the Build</h3>
|
||
<p>The build will end up in a directory named like
|
||
<code>build/linux-arm-normal-server-release</code>.</p>
|
||
<p>Inside this build output directory, the <code>images/jdk</code> will
|
||
contain the newly built JDK, for your <em>target</em> system.</p>
|
||
<p>Copy these folders to your <em>target</em> system. Then you can run
|
||
e.g. <code>images/jdk/bin/java -version</code>.</p>
|
||
<h3 id="cross-compiling-the-easy-way">Cross-Compiling the Easy Way</h3>
|
||
<p>Setting up a proper cross-compilation environment can be a lot of
|
||
work. Fortunately there are ways that more or less automate this
|
||
process. Here are two recommended methods, using the "devkits" that can
|
||
be generated by the JDK build system, or by using the
|
||
<code>debootstrap</code> command in Debian. The former works on all
|
||
Linux distributions, the latter only on Debian and derivatives. Both
|
||
solution only work for gcc.</p>
|
||
<p>The devkit method is regularly used for testing by Oracle, and the
|
||
debootstrap method is regularly used in GitHub Actions testing.</p>
|
||
<h4 id="using-openjdk-devkits">Using OpenJDK Devkits</h4>
|
||
<p>The JDK build system provides out-of-the box support for creating and
|
||
using so called devkits. A <code>devkit</code> is basically a collection
|
||
of a cross-compiling toolchain and a sysroot environment which can
|
||
easily be used together with the <code>--with-devkit</code> configure
|
||
option to cross compile the JDK. On Linux/x86_64, the following
|
||
command:</p>
|
||
<pre><code>bash configure --with-devkit=<devkit-path> --openjdk-target=ppc64-linux-gnu && make</code></pre>
|
||
<p>will configure and build the JDK for Linux/ppc64 assuming that
|
||
<code><devkit-path></code> points to a Linux/x86_64 to Linux/ppc64
|
||
devkit.</p>
|
||
<p>Devkits can be created from the <code>make/devkit</code> directory by
|
||
executing:</p>
|
||
<pre><code>make [ TARGETS="<TARGET_TRIPLET>+" ] [ BASE_OS=<OS> ] [ BASE_OS_VERSION=<VER> ]</code></pre>
|
||
<p>where <code>TARGETS</code> contains one or more
|
||
<code>TARGET_TRIPLET</code>s of the form described in <a
|
||
href="https://sourceware.org/autobook/autobook/autobook_17.html">section
|
||
3.4 of the GNU Autobook</a>. If no targets are given, a native toolchain
|
||
for the current platform will be created. Currently, at least the
|
||
following targets are known to work:</p>
|
||
<table>
|
||
<thead>
|
||
<tr class="header">
|
||
<th>Supported devkit targets</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr class="odd">
|
||
<td>x86_64-linux-gnu</td>
|
||
</tr>
|
||
<tr class="even">
|
||
<td>aarch64-linux-gnu</td>
|
||
</tr>
|
||
<tr class="odd">
|
||
<td>arm-linux-gnueabihf</td>
|
||
</tr>
|
||
<tr class="even">
|
||
<td>ppc64-linux-gnu</td>
|
||
</tr>
|
||
<tr class="odd">
|
||
<td>ppc64le-linux-gnu</td>
|
||
</tr>
|
||
<tr class="even">
|
||
<td>s390x-linux-gnu</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<p><code>BASE_OS</code> must be one of "OEL6" for Oracle Enterprise
|
||
Linux 6 or "Fedora" (if not specified "OEL6" will be the default). If
|
||
the base OS is "Fedora" the corresponding Fedora release can be
|
||
specified with the help of the <code>BASE_OS_VERSION</code> option (with
|
||
"27" as default version). If the build is successful, the new devkits
|
||
can be found in the <code>build/devkit/result</code> subdirectory:</p>
|
||
<pre><code>cd make/devkit
|
||
make TARGETS="ppc64le-linux-gnu aarch64-linux-gnu" BASE_OS=Fedora BASE_OS_VERSION=21
|
||
ls -1 ../../build/devkit/result/
|
||
x86_64-linux-gnu-to-aarch64-linux-gnu
|
||
x86_64-linux-gnu-to-ppc64le-linux-gnu</code></pre>
|
||
<p>Notice that devkits are not only useful for targeting different build
|
||
platforms. Because they contain the full build dependencies for a system
|
||
(i.e. compiler and root file system), they can easily be used to build
|
||
well-known, reliable and reproducible build environments. You can for
|
||
example create and use a devkit with GCC 7.3 and a Fedora 12 sysroot
|
||
environment (with glibc 2.11) on Ubuntu 14.04 (which doesn't have GCC
|
||
7.3 by default) to produce JDK binaries which will run on all Linux
|
||
systems with runtime libraries newer than the ones from Fedora 12 (e.g.
|
||
Ubuntu 16.04, SLES 11 or RHEL 6).</p>
|
||
<h4 id="using-debian-debootstrap">Using Debian debootstrap</h4>
|
||
<p>On Debian (or a derivative like Ubuntu), you can create sysroots for
|
||
foreign architectures with tools provided by the OS. You can use
|
||
<code>debootstrap</code> to create a <em>target</em> system chroot
|
||
directory, which would have the native libraries and headers specific to
|
||
that <em>target</em> system. After that, you can use the cross-compiler
|
||
on the <em>build</em> system, pointing into the chroot to get the build
|
||
dependencies right. This allows building for foreign architectures with
|
||
native compilation speed.</p>
|
||
<p>For example, cross-compiling to AArch64 from x86_64 could be done
|
||
like this:</p>
|
||
<ul>
|
||
<li><p>Install cross-compiler on the <em>build</em> system:</p>
|
||
<pre><code>apt install g++-aarch64-linux-gnu gcc-aarch64-linux-gnu</code></pre></li>
|
||
<li><p>Create chroot on the <em>build</em> system, configuring it for
|
||
<em>target</em> system:</p>
|
||
<pre><code>sudo debootstrap \
|
||
--arch=arm64 \
|
||
--verbose \
|
||
--include=fakeroot,symlinks,build-essential,libx11-dev,libxext-dev,libxrender-dev,libxrandr-dev,libxtst-dev,libxt-dev,libcups2-dev,libfontconfig1-dev,libasound2-dev,libfreetype6-dev,libpng-dev,libffi-dev \
|
||
--resolve-deps \
|
||
buster \
|
||
~/sysroot-arm64 \
|
||
https://httpredir.debian.org/debian/</code></pre></li>
|
||
<li><p>To create an Ubuntu-based chroot:</p>
|
||
<pre><code>sudo debootstrap \
|
||
--arch=arm64 \
|
||
--verbose \
|
||
--components=main,universe \
|
||
--include=fakeroot,symlinks,build-essential,libx11-dev,libxext-dev,libxrender-dev,libxrandr-dev,libxtst-dev,libxt-dev,libcups2-dev,libfontconfig1-dev,libasound2-dev,libfreetype6-dev,libpng-dev,libffi-dev \
|
||
--resolve-deps \
|
||
jammy \
|
||
~/sysroot-arm64 \
|
||
http://ports.ubuntu.com/ubuntu-ports/</code></pre>
|
||
<p>Note that <code>symlinks</code> is in the universe
|
||
repository.</p></li>
|
||
<li><p>Make sure the symlinks inside the newly created chroot point to
|
||
proper locations:</p>
|
||
<pre><code>sudo chroot ~/sysroot-arm64 symlinks -cr .</code></pre></li>
|
||
<li><p>Configure and build with newly created chroot as
|
||
sysroot/toolchain-path:</p>
|
||
<pre><code>sh ./configure \
|
||
--openjdk-target=aarch64-linux-gnu \
|
||
--with-sysroot=~/sysroot-arm64
|
||
make images
|
||
ls build/linux-aarch64-server-release/</code></pre></li>
|
||
</ul>
|
||
<p>The build does not create new files in that chroot, so it can be
|
||
reused for multiple builds without additional cleanup.</p>
|
||
<p>The build system should automatically detect the toolchain paths and
|
||
dependencies, but sometimes it might require a little nudge with:</p>
|
||
<ul>
|
||
<li><p>Native compilers: override <code>CC</code> or <code>CXX</code>
|
||
for <code>./configure</code></p></li>
|
||
<li><p>Freetype lib location: override <code>--with-freetype-lib</code>,
|
||
for example <code>${sysroot}/usr/lib/${target}/</code></p></li>
|
||
<li><p>Freetype includes location: override
|
||
<code>--with-freetype-include</code> for example
|
||
<code>${sysroot}/usr/include/freetype2/</code></p></li>
|
||
<li><p>X11 libraries location: override <code>--x-libraries</code>, for
|
||
example <code>${sysroot}/usr/lib/${target}/</code></p></li>
|
||
</ul>
|
||
<p>Architectures that are known to successfully cross-compile like this
|
||
are:</p>
|
||
<table>
|
||
<colgroup>
|
||
<col style="width: 13%" />
|
||
<col style="width: 13%" />
|
||
<col style="width: 15%" />
|
||
<col style="width: 27%" />
|
||
<col style="width: 29%" />
|
||
</colgroup>
|
||
<thead>
|
||
<tr class="header">
|
||
<th>Target</th>
|
||
<th>Debian tree</th>
|
||
<th>Debian arch</th>
|
||
<th><code>--openjdk-target=...</code></th>
|
||
<th><code>--with-jvm-variants=...</code></th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr class="odd">
|
||
<td>x86</td>
|
||
<td>buster</td>
|
||
<td>i386</td>
|
||
<td>i386-linux-gnu</td>
|
||
<td>(all)</td>
|
||
</tr>
|
||
<tr class="even">
|
||
<td>arm</td>
|
||
<td>buster</td>
|
||
<td>armhf</td>
|
||
<td>arm-linux-gnueabihf</td>
|
||
<td>(all)</td>
|
||
</tr>
|
||
<tr class="odd">
|
||
<td>aarch64</td>
|
||
<td>buster</td>
|
||
<td>arm64</td>
|
||
<td>aarch64-linux-gnu</td>
|
||
<td>(all)</td>
|
||
</tr>
|
||
<tr class="even">
|
||
<td>ppc64le</td>
|
||
<td>buster</td>
|
||
<td>ppc64el</td>
|
||
<td>powerpc64le-linux-gnu</td>
|
||
<td>(all)</td>
|
||
</tr>
|
||
<tr class="odd">
|
||
<td>s390x</td>
|
||
<td>buster</td>
|
||
<td>s390x</td>
|
||
<td>s390x-linux-gnu</td>
|
||
<td>(all)</td>
|
||
</tr>
|
||
<tr class="even">
|
||
<td>mipsle</td>
|
||
<td>buster</td>
|
||
<td>mipsel</td>
|
||
<td>mipsel-linux-gnu</td>
|
||
<td>zero</td>
|
||
</tr>
|
||
<tr class="odd">
|
||
<td>mips64le</td>
|
||
<td>buster</td>
|
||
<td>mips64el</td>
|
||
<td>mips64el-linux-gnueabi64</td>
|
||
<td>zero</td>
|
||
</tr>
|
||
<tr class="even">
|
||
<td>armel</td>
|
||
<td>buster</td>
|
||
<td>arm</td>
|
||
<td>arm-linux-gnueabi</td>
|
||
<td>zero</td>
|
||
</tr>
|
||
<tr class="odd">
|
||
<td>ppc</td>
|
||
<td>sid</td>
|
||
<td>powerpc</td>
|
||
<td>powerpc-linux-gnu</td>
|
||
<td>zero</td>
|
||
</tr>
|
||
<tr class="even">
|
||
<td>ppc64be</td>
|
||
<td>sid</td>
|
||
<td>ppc64</td>
|
||
<td>powerpc64-linux-gnu</td>
|
||
<td>(all)</td>
|
||
</tr>
|
||
<tr class="odd">
|
||
<td>m68k</td>
|
||
<td>sid</td>
|
||
<td>m68k</td>
|
||
<td>m68k-linux-gnu</td>
|
||
<td>zero</td>
|
||
</tr>
|
||
<tr class="even">
|
||
<td>alpha</td>
|
||
<td>sid</td>
|
||
<td>alpha</td>
|
||
<td>alpha-linux-gnu</td>
|
||
<td>zero</td>
|
||
</tr>
|
||
<tr class="odd">
|
||
<td>sh4</td>
|
||
<td>sid</td>
|
||
<td>sh4</td>
|
||
<td>sh4-linux-gnu</td>
|
||
<td>zero</td>
|
||
</tr>
|
||
<tr class="even">
|
||
<td>riscv64</td>
|
||
<td>sid</td>
|
||
<td>riscv64</td>
|
||
<td>riscv64-linux-gnu</td>
|
||
<td>(all)</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h3 id="considerations-for-specific-targets">Considerations for Specific
|
||
Targets</h3>
|
||
<h4 id="building-for-arm32">Building for ARM32</h4>
|
||
<p>A common cross-compilation target is the ARM CPU. When building for
|
||
ARM, it is recommended to set the ABI profile. A number of pre-defined
|
||
ABI profiles are available using <code>--with-abi-profile</code>:
|
||
<code>arm-vfp-sflt</code>, <code>arm-vfp-hflt</code>,
|
||
<code>arm-sflt</code>, <code>armv5-vfp-sflt</code> and
|
||
<code>armv6-vfp-hflt</code>. Note that soft-float ABIs are no longer
|
||
properly supported by the JDK.</p>
|
||
<h4 id="building-for-risc-v">Building for RISC-V</h4>
|
||
<p>The RISC-V community provides a basic <a
|
||
href="https://github.com/riscv-collab/riscv-gnu-toolchain">GNU compiler
|
||
toolchain</a>, but the <a href="#external-library-requirements">external
|
||
libraries</a> required by the JDK complicate the building process. The
|
||
placeholder <code><toolchain-installed-path></code> shown below is
|
||
the path where you want to install the toolchain.</p>
|
||
<ul>
|
||
<li><p>Install the RISC-V GNU compiler toolchain:</p>
|
||
<pre><code>git clone --recursive https://github.com/riscv-collab/riscv-gnu-toolchain
|
||
cd riscv-gnu-toolchain
|
||
./configure --prefix=<toolchain-installed-path>
|
||
make linux
|
||
export PATH=<toolchain-installed-path>/bin:$PATH</code></pre></li>
|
||
<li><p>Cross-compile all the required libraries:</p>
|
||
<pre><code># An example for libffi
|
||
git clone https://github.com/libffi/libffi
|
||
cd libffi
|
||
./configure --host=riscv64-unknown-linux-gnu --prefix=<toolchain-installed-path>/sysroot/usr
|
||
make
|
||
make install</code></pre></li>
|
||
<li><p>Configure and build the JDK:</p>
|
||
<pre><code>bash configure \
|
||
--with-boot-jdk=$BOOT_JDK \
|
||
--openjdk-target=riscv64-linux-gnu \
|
||
--with-sysroot=<toolchain-installed-path>/sysroot \
|
||
--with-toolchain-path=<toolchain-installed-path>/bin \
|
||
--with-extra-path=<toolchain-installed-path>/bin
|
||
make images</code></pre></li>
|
||
</ul>
|
||
<h4 id="building-for-musl">Building for musl</h4>
|
||
<p>Just like it's possible to cross-compile for a different CPU, it's
|
||
possible to cross-compile for <code>musl</code> libc on a glibc-based
|
||
<em>build</em> system. A devkit suitable for most target CPU
|
||
architectures can be obtained from <a
|
||
href="https://musl.cc">musl.cc</a>. After installing the required
|
||
packages in the sysroot, configure the build with
|
||
<code>--openjdk-target</code>:</p>
|
||
<pre><code>sh ./configure --with-jvm-variants=server \
|
||
--with-boot-jdk=$BOOT_JDK \
|
||
--with-build-jdk=$BUILD_JDK \
|
||
--openjdk-target=x86_64-unknown-linux-musl \
|
||
--with-devkit=$DEVKIT \
|
||
--with-sysroot=$SYSROOT</code></pre>
|
||
<p>and run <code>make</code> normally.</p>
|
||
<h2 id="build-performance">Build Performance</h2>
|
||
<p>Building the JDK requires a lot of horsepower. Some of the build
|
||
tools can be adjusted to utilize more or less of resources such as
|
||
parallel threads and memory. The <code>configure</code> script analyzes
|
||
your system and selects reasonable values for such options based on your
|
||
hardware. If you encounter resource problems, such as out of memory
|
||
conditions, you can modify the detected values with:</p>
|
||
<ul>
|
||
<li><p><code>--with-num-cores</code> -- number of cores in the build
|
||
system, e.g. <code>--with-num-cores=8</code>.</p></li>
|
||
<li><p><code>--with-memory-size</code> -- memory (in MB) available in
|
||
the build system, e.g. <code>--with-memory-size=1024</code></p></li>
|
||
</ul>
|
||
<p>You can also specify directly the number of build jobs to use with
|
||
<code>--with-jobs=N</code> to <code>configure</code>, or
|
||
<code>JOBS=N</code> to <code>make</code>. Do not use the <code>-j</code>
|
||
flag to <code>make</code>. In most cases it will be ignored by the
|
||
makefiles, but it can cause problems for some make targets.</p>
|
||
<p>It might also be necessary to specify the JVM arguments passed to the
|
||
Boot JDK, using e.g. <code>--with-boot-jdk-jvmargs="-Xmx8G"</code>.
|
||
Doing so will override the default JVM arguments passed to the Boot
|
||
JDK.</p>
|
||
<p>At the end of a successful execution of <code>configure</code>, you
|
||
will get a performance summary, indicating how well the build will
|
||
perform. Here you will also get performance hints. If you want to build
|
||
fast, pay attention to those!</p>
|
||
<p>If you want to tweak build performance, run with
|
||
<code>make LOG=info</code> to get a build time summary at the end of the
|
||
build process.</p>
|
||
<h3 id="disk-speed">Disk Speed</h3>
|
||
<p>If you are using network shares, e.g. via NFS, for your source code,
|
||
make sure the build directory is situated on local disk (e.g. by
|
||
<code>ln -s /localdisk/jdk-build $JDK-SHARE/build</code>). The
|
||
performance penalty is extremely high for building on a network share;
|
||
close to unusable.</p>
|
||
<p>Also, make sure that your build tools (including Boot JDK and
|
||
toolchain) is located on a local disk and not a network share.</p>
|
||
<p>As has been stressed elsewhere, do use SSD for source code and build
|
||
directory, as well as (if possible) the build tools.</p>
|
||
<h3 id="virus-checking">Virus Checking</h3>
|
||
<p>The use of virus checking software, especially on Windows, can
|
||
<em>significantly</em> slow down building of the JDK. If possible, turn
|
||
off such software, or exclude the directory containing the JDK source
|
||
code from on-the-fly checking.</p>
|
||
<h3 id="ccache">Ccache</h3>
|
||
<p>The JDK build supports building with ccache when using gcc or clang.
|
||
Using ccache can radically speed up compilation of native code if you
|
||
often rebuild the same sources. Your mileage may vary however, so we
|
||
recommend evaluating it for yourself. To enable it, make sure it's on
|
||
the path and configure with <code>--enable-ccache</code>.</p>
|
||
<h3 id="precompiled-headers">Precompiled Headers</h3>
|
||
<p>By default, the Hotspot build uses pre-compiled headers (PCH) on the
|
||
toolchains were it is properly supported (clang, gcc, and Visual
|
||
Studio). Normally, this speeds up the build process, but in some
|
||
circumstances, it can actually slow things down.</p>
|
||
<p>You can experiment by disabling pre-compiled headers using
|
||
<code>--disable-precompiled-headers</code>.</p>
|
||
<h3 id="icecc-icecream">Icecc / Icecream</h3>
|
||
<p><a href="https://github.com/icecc/icecream">icecc/icecream</a> is a
|
||
simple way to setup a distributed compiler network. If you have multiple
|
||
machines available for building the JDK, you can drastically cut
|
||
individual build times by utilizing it.</p>
|
||
<p>To use, setup an icecc network, and install icecc on the build
|
||
machine. Then run <code>configure</code> using
|
||
<code>--enable-icecc</code>.</p>
|
||
<h3 id="using-the-javac-server">Using the javac Server</h3>
|
||
<p>To speed up compilation of Java code, especially during incremental
|
||
compilations, the javac server is automatically enabled in the
|
||
configuration step by default. To explicitly enable or disable the javac
|
||
server, use either <code>--enable-javac-server</code> or
|
||
<code>--disable-javac-server</code>.</p>
|
||
<h3 id="building-the-right-target">Building the Right Target</h3>
|
||
<p>Selecting the proper target to build can have dramatic impact on
|
||
build time. For normal usage, <code>jdk</code> or the default target is
|
||
just fine. You only need to build <code>images</code> for shipping, or
|
||
if your tests require it.</p>
|
||
<p>See also <a href="#using-fine-grained-make-targets">Using
|
||
Fine-Grained Make Targets</a> on how to build an even smaller subset of
|
||
the product.</p>
|
||
<h2 id="troubleshooting">Troubleshooting</h2>
|
||
<p>If your build fails, it can sometimes be difficult to pinpoint the
|
||
problem or find a proper solution.</p>
|
||
<h3 id="locating-the-source-of-the-error">Locating the Source of the
|
||
Error</h3>
|
||
<p>When a build fails, it can be hard to pinpoint the actual cause of
|
||
the error. In a typical build process, different parts of the product
|
||
build in parallel, with the output interlaced.</p>
|
||
<h4 id="build-failure-summary">Build Failure Summary</h4>
|
||
<p>To help you, the build system will print a failure summary at the
|
||
end. It looks like this:</p>
|
||
<pre><code>ERROR: Build failed for target 'hotspot' in configuration 'linux-x64' (exit code 2)
|
||
|
||
=== Output from failing command(s) repeated here ===
|
||
* For target hotspot_variant-server_libjvm_objs_psMemoryPool.o:
|
||
/src/jdk/hotspot/src/share/vm/services/psMemoryPool.cpp:1:1: error: 'failhere' does not name a type
|
||
... (rest of output omitted)
|
||
|
||
* All command lines available in /src/jdk/build/linux-x64/make-support/failure-logs.
|
||
=== End of repeated output ===
|
||
|
||
=== Make failed targets repeated here ===
|
||
lib/CompileJvm.gmk:207: recipe for target '/src/jdk/build/linux-x64/hotspot/variant-server/libjvm/objs/psMemoryPool.o' failed
|
||
make/Main.gmk:263: recipe for target 'hotspot-server-libs' failed
|
||
=== End of repeated output ===
|
||
|
||
HELP: Try searching the build log for the name of the first failed target.
|
||
HELP: Run 'make doctor' to diagnose build problems.</code></pre>
|
||
<p>Let's break it down! First, the selected configuration, and the
|
||
top-level target you entered on the command line that caused the failure
|
||
is printed.</p>
|
||
<p>Then, between the
|
||
<code>Output from failing command(s) repeated here</code> and
|
||
<code>End of repeated output</code> the first lines of output (stdout
|
||
and stderr) from the actual failing command is repeated. In most cases,
|
||
this is the error message that caused the build to fail. If multiple
|
||
commands were failing (this can happen in a parallel build), output from
|
||
all failed commands will be printed here.</p>
|
||
<p>The path to the <code>failure-logs</code> directory is printed. In
|
||
this file you will find a <code><target>.log</code> file that
|
||
contains the output from this command in its entirety, and also a
|
||
<code><target>.cmd</code>, which contain the complete command line
|
||
used for running this command. You can re-run the failing command by
|
||
executing <code>. <path to failure-logs>/<target>.cmd</code>
|
||
in your shell.</p>
|
||
<p>Another way to trace the failure is to follow the chain of make
|
||
targets, from top-level targets to individual file targets. Between
|
||
<code>Make failed targets repeated here</code> and
|
||
<code>End of repeated output</code> the output from make showing this
|
||
chain is repeated. The first failed recipe will typically contain the
|
||
full path to the file in question that failed to compile. Following
|
||
lines will show a trace of make targets why we ended up trying to
|
||
compile that file.</p>
|
||
<p>Finally, some hints are given on how to locate the error in the
|
||
complete log. In this example, we would try searching the log file for
|
||
"<code>psMemoryPool.o</code>". Another way to quickly locate make errors
|
||
in the log is to search for "<code>] Error</code>" or
|
||
"<code>***</code>".</p>
|
||
<p>Note that the build failure summary will only help you if the issue
|
||
was a compilation failure or similar. If the problem is more esoteric,
|
||
or is due to errors in the build machinery, you will likely get empty
|
||
output logs, and <code>No indication of failed target found</code>
|
||
instead of the make target chain.</p>
|
||
<h4 id="checking-the-build-log-file">Checking the Build Log File</h4>
|
||
<p>The output (stdout and stderr) from the latest build is always stored
|
||
in <code>$BUILD/build.log</code>. The previous build log is stored as
|
||
<code>build.log.old</code>. This means that it is not necessary to
|
||
redirect the build output yourself if you want to process it.</p>
|
||
<p>You can increase the verbosity of the log file, by the
|
||
<code>LOG</code> control variable to <code>make</code>. If you want to
|
||
see the command lines used in compilations, use
|
||
<code>LOG=cmdlines</code>. To increase the general verbosity, use
|
||
<code>LOG=info</code>, <code>LOG=debug</code> or <code>LOG=trace</code>.
|
||
Both of these can be combined with <code>cmdlines</code>, e.g.
|
||
<code>LOG=info,cmdlines</code>. The <code>debug</code> log level will
|
||
show most shell commands executed by make, and <code>trace</code> will
|
||
show all. Beware that both these log levels will produce a massive build
|
||
log!</p>
|
||
<h3 id="fixing-unexpected-build-failures">Fixing Unexpected Build
|
||
Failures</h3>
|
||
<p>Most of the time, the build will fail due to incorrect changes in the
|
||
source code.</p>
|
||
<p>Sometimes the build can fail with no apparent changes that have
|
||
caused the failure. If this is the first time you are building the JDK
|
||
on this particular computer, and the build fails, the problem is likely
|
||
with your build environment. But even if you have previously built the
|
||
JDK with success, and it now fails, your build environment might have
|
||
changed (perhaps due to OS upgrades or similar). But most likely, such
|
||
failures are due to problems with the incremental rebuild.</p>
|
||
<h4 id="running-make-doctor">Running "make doctor"</h4>
|
||
<p>The build system comes with a built-in problem diagnosing system. If
|
||
you encounter unexpected build failures, you are highly encouraged to
|
||
run <code>make doctor</code>. The build system will check for common
|
||
sources of build problems and suggest suitable actions to take to fix
|
||
those problems.</p>
|
||
<p>These checks are not done during normal build time since they are
|
||
either too expensive performance-wise to perform, or since they are not
|
||
conclusive and just an indication about a potential problem.</p>
|
||
<p>The output from <code>make doctor</code> can look like this:</p>
|
||
<pre><code>"make doctor" will help you analyze your build environment. It can highlight
|
||
certain well-known problems, but it can never find all possible errors.
|
||
|
||
* Verifying that configure has picked up git...
|
||
|
||
* Checking for warnings from configure...
|
||
---
|
||
The following warnings were produced. Repeated here for convenience:
|
||
WARNING: pandoc is version 3.1.9, not the recommended version 2.19.2
|
||
---
|
||
! Inspect the warnings, fix any problems, and re-run configure
|
||
|
||
* Checking for left-over core files...
|
||
Found these potential core files. They might interfere with the build process:
|
||
---
|
||
src/hotspot/core.1337
|
||
---
|
||
! Remove left-over core files
|
||
|
||
* Checking for untracked files with illegal names...
|
||
|
||
* If all else fails, try removing the entire build directory and re-creating
|
||
the same configuration using:
|
||
---
|
||
configure_command_line=$(make print-configuration)
|
||
make dist-clean
|
||
bash configure $configure_command_line
|
||
---
|
||
|
||
* The build README (doc/building.md) is a great source of information,
|
||
especially the chapter "Fixing Unexpected Build Failures". Check it out!
|
||
|
||
* If you still need assistance please contact build-dev@openjdk.org.</code></pre>
|
||
<h4 id="problems-with-the-build-environment">Problems with the Build
|
||
Environment</h4>
|
||
<p>Make sure your configuration is correct. Re-run
|
||
<code>configure</code>, and look for any warnings. Warnings that appear
|
||
in the middle of the <code>configure</code> output is also repeated at
|
||
the end, after the summary. The entire log is stored in
|
||
<code>$BUILD/configure.log</code>.</p>
|
||
<p>Verify that the summary at the end looks correct. Are you indeed
|
||
using the Boot JDK and native toolchain that you expect?</p>
|
||
<p>By default, the JDK has a strict approach where warnings from the
|
||
compiler is considered errors which fail the build. For very new or very
|
||
old compiler versions, this can trigger new classes of warnings, which
|
||
thus fails the build. Run <code>configure</code> with
|
||
<code>--disable-warnings-as-errors</code> to turn of this behavior. (The
|
||
warnings will still show, but not make the build fail.)</p>
|
||
<h4 id="problems-with-incremental-rebuilds">Problems with Incremental
|
||
Rebuilds</h4>
|
||
<p>Incremental rebuilds mean that when you modify part of the product,
|
||
only the affected parts get rebuilt. While this works great in most
|
||
cases, and significantly speed up the development process, from time to
|
||
time complex interdependencies will result in an incorrect build result.
|
||
This is the most common cause for unexpected build problems.</p>
|
||
<p>Here are a suggested list of things to try if you are having
|
||
unexpected build problems. Each step requires more time than the one
|
||
before, so try them in order. Most issues will be solved at step 1 or
|
||
2.</p>
|
||
<ol type="1">
|
||
<li><p>Make sure your repository is up-to-date</p>
|
||
<p>Run <code>git pull origin master</code> to make sure you have the
|
||
latest changes.</p></li>
|
||
<li><p>Clean build results</p>
|
||
<p>The simplest way to fix incremental rebuild issues is to run
|
||
<code>make clean</code>. This will remove all build results, but not the
|
||
configuration or any build system support artifacts. In most cases, this
|
||
will solve build errors resulting from incremental build
|
||
mismatches.</p></li>
|
||
<li><p>Completely clean the build directory.</p>
|
||
<p>If this does not work, the next step is to run
|
||
<code>make dist-clean</code>, or removing the build output directory
|
||
(<code>$BUILD</code>). This will clean all generated output, including
|
||
your configuration. You will need to re-run <code>configure</code> after
|
||
this step. A good idea is to run <code>make print-configuration</code>
|
||
before running <code>make dist-clean</code>, as this will print your
|
||
current <code>configure</code> command line. Here's a way to do
|
||
this:</p>
|
||
<pre><code>make print-configuration > current-configuration
|
||
make dist-clean
|
||
bash configure $(cat current-configuration)
|
||
make</code></pre></li>
|
||
<li><p>Re-clone the Git repository</p>
|
||
<p>Sometimes the Git repository gets in a state that causes the product
|
||
to be un-buildable. In such a case, the simplest solution is often the
|
||
"sledgehammer approach": delete the entire repository, and re-clone it.
|
||
If you have local changes, save them first to a different location using
|
||
<code>git format-patch</code>.</p></li>
|
||
</ol>
|
||
<h3 id="specific-build-issues">Specific Build Issues</h3>
|
||
<h4 id="clock-skew">Clock Skew</h4>
|
||
<p>If you get an error message like this:</p>
|
||
<pre><code>File 'xxx' has modification time in the future.
|
||
Clock skew detected. Your build may be incomplete.</code></pre>
|
||
<p>then the clock on your build machine is out of sync with the
|
||
timestamps on the source files. Other errors, apparently unrelated but
|
||
in fact caused by the clock skew, can occur along with the clock skew
|
||
warnings. These secondary errors may tend to obscure the fact that the
|
||
true root cause of the problem is an out-of-sync clock.</p>
|
||
<p>If you see these warnings, reset the clock on the build machine, run
|
||
<code>make clean</code> and restart the build.</p>
|
||
<h4 id="out-of-memory-errors">Out of Memory Errors</h4>
|
||
<p>On Windows, you might get error messages like this:</p>
|
||
<pre><code>fatal error - couldn't allocate heap
|
||
cannot create ... Permission denied
|
||
spawn failed</code></pre>
|
||
<p>This can be a sign of a Cygwin problem. See the information about
|
||
solving problems in the <a href="#cygwin">Cygwin</a> section. Rebooting
|
||
the computer might help temporarily.</p>
|
||
<h4 id="spaces-in-path">Spaces in Path</h4>
|
||
<p>On Windows, when configuring, <code>fixpath.sh</code> may report that
|
||
some directory names have spaces. Usually, it assumes those directories
|
||
have <a
|
||
href="https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/fsutil-8dot3name">short
|
||
paths</a>. You can run <code>fsutil file setshortname</code> in
|
||
<code>cmd</code> on directories to assign arbitrary short paths so
|
||
<code>configure</code> can access them. If the result says "Access
|
||
denied", it may be that there are processes running in that directory;
|
||
in this case, you can reboot Windows in safe mode and run the command on
|
||
those directories again.</p>
|
||
<p>The only directories required to have short paths are
|
||
<code>Microsoft Visual Studio</code> and <code>Windows Kits</code>; the
|
||
rest of the "contains space" warnings from <code>configure</code>, such
|
||
as <code>IntelliJ IDEA</code>, can be ignored. You can choose any short
|
||
name; once it is set, <code>configure</code>'s tools like
|
||
<code>cygpath</code> can convert the directory with spaces to your
|
||
chosen short name and pass it to the build system.</p>
|
||
<h3 id="getting-help">Getting Help</h3>
|
||
<p>If none of the suggestions in this document helps you, or if you find
|
||
what you believe is a bug in the build system, please contact the Build
|
||
Group by sending a mail to <a
|
||
href="mailto:build-dev@openjdk.org">build-dev@openjdk.org</a>. Please
|
||
include the relevant parts of the configure and/or build log.</p>
|
||
<p>If you need general help or advice about developing for the JDK, you
|
||
can also contact the Adoption Group. See the section on <a
|
||
href="#contributing-to-the-jdk">Contributing to OpenJDK</a> for more
|
||
information.</p>
|
||
<h2 id="reproducible-builds">Reproducible Builds</h2>
|
||
<p>Build reproducibility is the property of getting exactly the same
|
||
bits out when building, every time, independent on who builds the
|
||
product, or where. This is for many reasons a harder goal than it
|
||
initially appears, but it is an important goal, for security reasons and
|
||
others. Please see <a
|
||
href="https://reproducible-builds.org">Reproducible Builds</a> for more
|
||
information about the background and reasons for reproducible
|
||
builds.</p>
|
||
<p>Currently, it is not possible to build the JDK fully reproducibly,
|
||
but getting there is an ongoing effort.</p>
|
||
<p>An absolute prerequisite for building reproducible is to specify a
|
||
fixed build time, since time stamps are embedded in many file formats.
|
||
This is done by setting the <code>SOURCE_DATE_EPOCH</code> environment
|
||
variable, which is an <a
|
||
href="https://reproducible-builds.org/docs/source-date-epoch/">industry
|
||
standard</a>, that many tools, such as gcc, recognize, and use in place
|
||
of the current time when generating output.</p>
|
||
<p>To generate reproducible builds, you must set
|
||
<code>SOURCE_DATE_EPOCH</code> before running <code>configure</code>.
|
||
The value in <code>SOURCE_DATE_EPOCH</code> will be stored in the
|
||
configuration, and used by <code>make</code>. Setting
|
||
<code>SOURCE_DATE_EPOCH</code> before running <code>make</code> will
|
||
have no effect on the build.</p>
|
||
<p>You must also make sure your build does not rely on
|
||
<code>configure</code>'s default ad hoc version strings. Default ad hoc
|
||
version strings <code>OPT</code> segment include user name and source
|
||
directory. You can either override just the <code>OPT</code> segment
|
||
using <code>--with-version-opt=<any fixed string></code>, or you
|
||
can specify the entire version string using
|
||
<code>--with-version-string=<your version></code>.</p>
|
||
<p>This is a typical example of how to build the JDK in a reproducible
|
||
way:</p>
|
||
<pre><code>export SOURCE_DATE_EPOCH=946684800
|
||
bash configure --with-version-opt=adhoc
|
||
make</code></pre>
|
||
<p>Note that regardless of whether you specify a source date for
|
||
<code>configure</code> or not, the JDK build system will set
|
||
<code>SOURCE_DATE_EPOCH</code> for all build tools when building. If
|
||
<code>--with-source-date</code> has the value <code>current</code>
|
||
(which is the default unless <code>SOURCE_DATE_EPOCH</code> is found by
|
||
in the environment by <code>configure</code>), the source date value
|
||
will be determined at configure time.</p>
|
||
<p>There are several aspects of reproducible builds that can be
|
||
individually adjusted by <code>configure</code> arguments. If any of
|
||
these are given, they will override the value derived from
|
||
<code>SOURCE_DATE_EPOCH</code>. These arguments are:</p>
|
||
<ul>
|
||
<li><code>--with-source-date</code></li>
|
||
</ul>
|
||
<p>This option controls how the JDK build sets
|
||
<code>SOURCE_DATE_EPOCH</code> when building. It can be set to a value
|
||
describing a date, either an epoch based timestamp as an integer, or a
|
||
valid ISO-8601 date.</p>
|
||
<p>It can also be set to one of the special values <code>current</code>,
|
||
<code>updated</code> or <code>version</code>. <code>current</code> means
|
||
that the time of running <code>configure</code> will be used.
|
||
<code>version</code> will use the nominal release date for the current
|
||
JDK version. <code>updated</code>, which means that
|
||
<code>SOURCE_DATE_EPOCH</code> will be set to the current time each time
|
||
you are running <code>make</code>. All choices, except for
|
||
<code>updated</code>, will set a fixed value for the source date
|
||
timestamp.</p>
|
||
<p>When <code>SOURCE_DATE_EPOCH</code> is set, the default value for
|
||
<code>--with-source-date</code> will be the value given by
|
||
<code>SOURCE_DATE_EPOCH</code>. Otherwise, the default value is
|
||
<code>current</code>.</p>
|
||
<ul>
|
||
<li><code>--with-hotspot-build-time</code></li>
|
||
</ul>
|
||
<p>This option controls the build time string that will be included in
|
||
the hotspot library (<code>libjvm.so</code> or <code>jvm.dll</code>). If
|
||
the source date is fixed (e.g. by setting
|
||
<code>SOURCE_DATE_EPOCH</code>), the default value for
|
||
<code>--with-hotspot-build-time</code> will be an ISO 8601
|
||
representation of that time stamp. Otherwise the default value will be
|
||
the current time when building hotspot.</p>
|
||
<ul>
|
||
<li><code>--with-copyright-year</code></li>
|
||
</ul>
|
||
<p>This option controls the copyright year in some generated text files.
|
||
When the source date is fixed (e.g. by setting
|
||
<code>SOURCE_DATE_EPOCH</code>), the default value for
|
||
<code>--with-copyright-year</code> will be the year of that time stamp.
|
||
Otherwise the default is the current year at the time of running
|
||
configure. This can be overridden by
|
||
<code>--with-copyright-year=<year></code>.</p>
|
||
<ul>
|
||
<li><code>--enable-reproducible-build</code></li>
|
||
</ul>
|
||
<p>This option controls additional behavior needed to make the build
|
||
reproducible. When the source date is fixed (e.g. by setting
|
||
<code>SOURCE_DATE_EPOCH</code>), this flag will be turned on by default.
|
||
Otherwise, the value is determined by heuristics. If it is explicitly
|
||
turned off, the build might not be reproducible.</p>
|
||
<h2 id="hints-and-suggestions-for-advanced-users">Hints and Suggestions
|
||
for Advanced Users</h2>
|
||
<h3 id="bash-completion">Bash Completion</h3>
|
||
<p>The <code>configure</code> and <code>make</code> commands try to play
|
||
nice with bash command-line completion (using <code><tab></code>
|
||
or <code><tab><tab></code>). To use this functionality, make
|
||
sure you enable completion in your <code>~/.bashrc</code> (see
|
||
instructions for bash in your operating system).</p>
|
||
<p>Make completion will work out of the box, and will complete valid
|
||
make targets. For instance, typing <code>make jdk-i<tab></code>
|
||
will complete to <code>make jdk-image</code>.</p>
|
||
<p>The <code>configure</code> script can get completion for options, but
|
||
for this to work you need to help <code>bash</code> on the way. The
|
||
standard way of running the script, <code>bash configure</code>, will
|
||
not be understood by bash completion. You need <code>configure</code> to
|
||
be the command to run. One way to achieve this is to add a simple helper
|
||
script to your path:</p>
|
||
<pre><code>cat << EOT > /tmp/configure
|
||
#!/bin/bash
|
||
if [ \$(pwd) = \$(cd \$(dirname \$0); pwd) ] ; then
|
||
echo >&2 "Abort: Trying to call configure helper recursively"
|
||
exit 1
|
||
fi
|
||
|
||
bash \$PWD/configure "\$@"
|
||
EOT
|
||
chmod +x /tmp/configure
|
||
sudo mv /tmp/configure /usr/local/bin</code></pre>
|
||
<p>Now <code>configure --en<tab>-dt<tab></code> will result
|
||
in <code>configure --enable-dtrace</code>.</p>
|
||
<h3 id="using-multiple-configurations">Using Multiple
|
||
Configurations</h3>
|
||
<p>You can have multiple configurations for a single source repository.
|
||
When you create a new configuration, run
|
||
<code>configure --with-conf-name=<name></code> to create a
|
||
configuration with the name <code><name></code>. Alternatively,
|
||
you can create a directory under <code>build</code> and run
|
||
<code>configure</code> from there, e.g.
|
||
<code>mkdir build/<name> && cd build/<name> && bash ../../configure</code>.</p>
|
||
<p>Then you can build that configuration using
|
||
<code>make CONF=<selector></code>, where
|
||
<code><selector></code> is interpreted as follows:</p>
|
||
<ul>
|
||
<li>If <code><selector></code> exacly matches the name of a
|
||
configuration, this and only this configuration will be selected.</li>
|
||
<li>If <code><selector></code> matches (i.e. is a substring of)
|
||
the names of several configurations, then all these configurations will
|
||
be selected.</li>
|
||
<li>If <code><selector></code> is empty (i.e. <code>CONF=</code>),
|
||
then all configurations will be selected.</li>
|
||
<li>If <code><selector></code> begins with <code>!</code>, then
|
||
all configurations <strong>not</strong> matching the string following
|
||
<code>!</code> will be selected.</li>
|
||
</ul>
|
||
<p>A more specialized version, <code>CONF_NAME=<name></code> also
|
||
exists, which will only match if the given <code><name></code>
|
||
exactly matches a single configuration.</p>
|
||
<p>Alternatively, you can execute <code>make</code> in the configuration
|
||
directory, e.g. <code>cd build/<name> && make</code>.</p>
|
||
<p><code>make CONF_NAME=<name></code> or</p>
|
||
<h3 id="handling-reconfigurations">Handling Reconfigurations</h3>
|
||
<p>If you update the repository and part of the configure script has
|
||
changed, the build system will force you to re-run
|
||
<code>configure</code>.</p>
|
||
<p>Most of the time, you will be fine by running <code>configure</code>
|
||
again with the same arguments as the last time, which can easily be
|
||
performed by <code>make reconfigure</code>. To simplify this, you can
|
||
use the <code>CONF_CHECK</code> make control variable, either as
|
||
<code>make CONF_CHECK=auto</code>, or by setting an environment
|
||
variable. For instance, if you add <code>export CONF_CHECK=auto</code>
|
||
to your <code>.bashrc</code> file, <code>make</code> will always run
|
||
<code>reconfigure</code> automatically whenever the configure script has
|
||
changed.</p>
|
||
<p>You can also use <code>CONF_CHECK=ignore</code> to skip the check for
|
||
a needed configure update. This might speed up the build, but comes at
|
||
the risk of an incorrect build result. This is only recommended if you
|
||
know what you're doing.</p>
|
||
<p>From time to time, you will also need to modify the command line to
|
||
<code>configure</code> due to changes. Use
|
||
<code>make print-configuration</code> to show the command line used for
|
||
your current configuration.</p>
|
||
<h3 id="using-fine-grained-make-targets">Using Fine-Grained Make
|
||
Targets</h3>
|
||
<p>The default behavior for make is to create consistent and correct
|
||
output, at the expense of build speed, if necessary.</p>
|
||
<p>If you are prepared to take some risk of an incorrect build, and know
|
||
enough of the system to understand how things build and interact, you
|
||
can speed up the build process considerably by instructing make to only
|
||
build a portion of the product.</p>
|
||
<h4 id="building-individual-modules">Building Individual Modules</h4>
|
||
<p>The safe way to use fine-grained make targets is to use the module
|
||
specific make targets. All source code in the JDK is organized so it
|
||
belongs to a module, e.g. <code>java.base</code> or
|
||
<code>jdk.jdwp.agent</code>. You can build only a specific module, by
|
||
giving it as make target: <code>make jdk.jdwp.agent</code>. If the
|
||
specified module depends on other modules (e.g. <code>java.base</code>),
|
||
those modules will be built first.</p>
|
||
<p>You can also specify a set of modules, just as you can always specify
|
||
a set of make targets:
|
||
<code>make jdk.crypto.cryptoki jdk.crypto.ec jdk.crypto.mscapi</code></p>
|
||
<h4 id="building-individual-module-phases">Building Individual Module
|
||
Phases</h4>
|
||
<p>The build process for each module is divided into separate phases.
|
||
Not all modules need all phases. Which are needed depends on what kind
|
||
of source code and other artifact the module consists of. The phases
|
||
are:</p>
|
||
<ul>
|
||
<li><code>gensrc</code> (Generate source code to compile)</li>
|
||
<li><code>gendata</code> (Generate non-source code artifacts)</li>
|
||
<li><code>copy</code> (Copy resource artifacts)</li>
|
||
<li><code>java</code> (Compile Java code)</li>
|
||
<li><code>launchers</code> (Compile native executables)</li>
|
||
<li><code>libs</code> (Compile native libraries)</li>
|
||
</ul>
|
||
<p>You can build only a single phase for a module by using the notation
|
||
<code>$MODULE-$PHASE</code>. For instance, to build the
|
||
<code>gensrc</code> phase for <code>java.base</code>, use
|
||
<code>make java.base-gensrc</code>.</p>
|
||
<p>Note that some phases may depend on others, e.g. <code>java</code>
|
||
depends on <code>gensrc</code> (if present). Make will build all needed
|
||
prerequisites before building the requested phase.</p>
|
||
<h4 id="skipping-the-dependency-check">Skipping the Dependency
|
||
Check</h4>
|
||
<p>When using an iterative development style with frequent quick
|
||
rebuilds, the dependency check made by make can take up a significant
|
||
portion of the time spent on the rebuild. In such cases, it can be
|
||
useful to bypass the dependency check in make.</p>
|
||
<p><strong>Note that if used incorrectly, this method can lead to a
|
||
broken build!</strong></p>
|
||
<p>To achieve this, append <code>-only</code> to the build target. For
|
||
instance, <code>make jdk.jdwp.agent-java-only</code> will <em>only</em>
|
||
build the <code>java</code> phase of the <code>jdk.jdwp.agent</code>
|
||
module. If the required dependencies are not present, the build can
|
||
fail. On the other hand, the execution time measures in
|
||
milliseconds.</p>
|
||
<p>A useful pattern is to build the first time normally (e.g.
|
||
<code>make jdk.jdwp.agent</code>) and then on subsequent builds, use the
|
||
<code>-only</code> make target.</p>
|
||
<h4 id="rebuilding-part-of-java.base-jdk_filter">Rebuilding Part of
|
||
java.base (JDK_FILTER)</h4>
|
||
<p>In older versions of the JDK, inefficiencies when building
|
||
<code>java.base</code> (by far the largest module in the JDK) could be
|
||
overcome by using the make control variable <code>JDK_FILTER</code>.
|
||
This is not needed anymore for performance reasons, but the
|
||
functionality is still present.</p>
|
||
<p>To use this, set the make control variable <code>JDK_FILTER</code> to
|
||
specify a pattern that will be used to limit the set of files being
|
||
recompiled. For instance,
|
||
<code>make java.base JDK_FILTER=javax/crypto</code> will limit the
|
||
compilation to files in the <code>javax.crypto</code> package.</p>
|
||
<h2 id="understanding-the-build-system">Understanding the Build
|
||
System</h2>
|
||
<p>This section will give you a more technical description on the
|
||
details of the build system.</p>
|
||
<h3 id="configurations">Configurations</h3>
|
||
<p>The build system expects to find one or more configuration. These are
|
||
technically defined by the <code>spec.gmk</code> in a subdirectory to
|
||
the <code>build</code> subdirectory. The <code>spec.gmk</code> file is
|
||
generated by <code>configure</code>, and contains in principle the
|
||
configuration (directly or by files included by
|
||
<code>spec.gmk</code>).</p>
|
||
<p>You can, in fact, select a configuration to build by pointing to the
|
||
<code>spec.gmk</code> file with the <code>SPEC</code> make control
|
||
variable, e.g. <code>make SPEC=$BUILD/spec.gmk</code>. While this is not
|
||
the recommended way to call <code>make</code> as a user, it is what is
|
||
used under the hood by the build system.</p>
|
||
<h3 id="build-output-structure">Build Output Structure</h3>
|
||
<p>The build output for a configuration will end up in
|
||
<code>build/<configuration name></code>, which we refer to as
|
||
<code>$BUILD</code> in this document. The <code>$BUILD</code> directory
|
||
contains the following important directories:</p>
|
||
<pre><code>buildtools/
|
||
configure-support/
|
||
hotspot/
|
||
images/
|
||
jdk/
|
||
make-support/
|
||
support/
|
||
test-results/
|
||
test-support/</code></pre>
|
||
<p>This is what they are used for:</p>
|
||
<ul>
|
||
<li><p><code>images</code>: This is the directory were the output of the
|
||
<code>*-image</code> make targets end up. For instance,
|
||
<code>make jdk-image</code> ends up in <code>images/jdk</code>.</p></li>
|
||
<li><p><code>jdk</code>: This is the "exploded image". After
|
||
<code>make jdk</code>, you will be able to launch the newly built JDK by
|
||
running <code>$BUILD/jdk/bin/java</code>.</p></li>
|
||
<li><p><code>test-results</code>: This directory contains the results
|
||
from running tests.</p></li>
|
||
<li><p><code>support</code>: This is an area for intermediate files
|
||
needed during the build, e.g. generated source code, object files and
|
||
class files. Some noteworthy directories in <code>support</code> is
|
||
<code>gensrc</code>, which contains the generated source code, and the
|
||
<code>modules_*</code> directories, which contains the files in a
|
||
per-module hierarchy that will later be collapsed into the
|
||
<code>jdk</code> directory of the exploded image.</p></li>
|
||
<li><p><code>buildtools</code>: This is an area for tools compiled for
|
||
the build platform that are used during the rest of the build.</p></li>
|
||
<li><p><code>hotspot</code>: This is an area for intermediate files
|
||
needed when building hotspot.</p></li>
|
||
<li><p><code>configure-support</code>, <code>make-support</code> and
|
||
<code>test-support</code>: These directories contain files that are
|
||
needed by the build system for <code>configure</code>, <code>make</code>
|
||
and for running tests.</p></li>
|
||
</ul>
|
||
<h3 id="fixpath">Fixpath</h3>
|
||
<p>Windows path typically look like <code>C:\User\foo</code>, while Unix
|
||
paths look like <code>/home/foo</code>. Tools with roots from Unix often
|
||
experience issues related to this mismatch when running on Windows.</p>
|
||
<p>In the JDK build, we always use Unix paths internally, and only just
|
||
before calling a tool that does not understand Unix paths do we convert
|
||
them to Windows paths.</p>
|
||
<p>This conversion is done by the <code>fixpath.sh</code> tool, which is
|
||
a small wrapper that modifies Unix-style paths to Windows-style paths.
|
||
The fixpath tool is called with the first argument as a sub-command
|
||
describing the action it should take. Available actions are
|
||
<code>import</code>, <code>exec</code>, <code>print</code> and
|
||
<code>verify</code>.</p>
|
||
<ul>
|
||
<li><p><code>import</code> is called at configure time to convert a path
|
||
given by the user and that might be in Windows format to Unix path,
|
||
which is used internally.</p></li>
|
||
<li><p><code>exec</code> is called at build time. This will take the
|
||
command line provided, complete with arguments, converting the paths in
|
||
the command line, and then execute the command.</p></li>
|
||
<li><p><code>print</code> is called at build time, in the rare cases
|
||
where a path might be needed in Windows format, but not as an argument
|
||
to a command to execute.</p></li>
|
||
<li><p><code>verify</code> is called at configure time to check that a
|
||
path is correctly specified and reachable by Windows.</p></li>
|
||
</ul>
|
||
<p>The fixpath tool uses a somewhat complex heuristic to infer which
|
||
part of the command line arguments refer to paths, and converts those.
|
||
In some circumstances, these heuristics can fail.</p>
|
||
<p>If you are having strange build issues related to path conversion,
|
||
you might need to debug how fixpath treats your paths. Here are some
|
||
ways to do this.</p>
|
||
<p>One way is to define the environment variable
|
||
<code>DEBUG_FIXPATH</code>, e.g. <code>DEBUG_FIXPATH=1 make jdk</code>.
|
||
When set, any call to <code>fixpath exec</code> will result in an output
|
||
like this:</p>
|
||
<pre><code>fixpath: debug: input: ls /mnt/c/windows
|
||
fixpath: debug: output: ls c:\windows</code></pre>
|
||
<p>You can also call fixpath yourself manually with your paths to see
|
||
how they are translated. For this, use <code>print</code> and
|
||
<code>import</code>. For example:</p>
|
||
<pre><code>$ bash make/scripts/fixpath.sh print /mnt/c/windows
|
||
c:\windows
|
||
$ bash make/scripts/fixpath.sh import "c:\\windows"
|
||
/mnt/c/windows</code></pre>
|
||
<p>Remember that backslash is used as an escape character in the shell,
|
||
and needs to be doubled when used in Windows paths.</p>
|
||
<h3 id="native-debug-symbols">Native Debug Symbols</h3>
|
||
<p>Native libraries and executables can have debug symbol (and other
|
||
debug information) associated with them. How this works is very much
|
||
platform dependent, but a common problem is that debug symbol
|
||
information takes a lot of disk space, but is rarely needed by the end
|
||
user.</p>
|
||
<p>The JDK supports different methods on how to handle debug symbols.
|
||
The method used is selected by <code>--with-native-debug-symbols</code>,
|
||
and available methods are <code>none</code>, <code>internal</code>,
|
||
<code>external</code>, <code>zipped</code>.</p>
|
||
<ul>
|
||
<li><p><code>none</code> means that no debug symbols will be generated
|
||
during the build.</p></li>
|
||
<li><p><code>internal</code> means that debug symbols will be generated
|
||
during the build, and they will be stored in the generated
|
||
binary.</p></li>
|
||
<li><p><code>external</code> means that debug symbols will be generated
|
||
during the build, and after the compilation, they will be moved into a
|
||
separate <code>.debuginfo</code> file. (This was previously known as
|
||
FDS, Full Debug Symbols).</p></li>
|
||
<li><p><code>zipped</code> is like <code>external</code>, but the
|
||
.debuginfo file will also be zipped into a <code>.diz</code>
|
||
file.</p></li>
|
||
</ul>
|
||
<p>When building for distribution, <code>zipped</code> is a good
|
||
solution. Binaries built with <code>internal</code> is suitable for use
|
||
by developers, since they facilitate debugging, but should be stripped
|
||
before distributed to end users.</p>
|
||
<h3 id="autoconf-details">Autoconf Details</h3>
|
||
<p>The <code>configure</code> script is using the autoconf framework,
|
||
but it has grown to deviate quite a lot from a traditional autoconf
|
||
<code>configure</code> script.</p>
|
||
<p>The <code>configure</code> script in the top level directory of the
|
||
JDK is just a thin wrapper that calls
|
||
<code>make/autoconf/configure</code>. This in turn will run
|
||
<code>autoconf</code> to create the runnable (generated) configure
|
||
script, as <code>.build/generated-configure.sh</code>. Apart from being
|
||
responsible for the generation of the runnable script, the
|
||
<code>configure</code> script also provides functionality that is not
|
||
easily expressed in the normal Autoconf framework. As part of this
|
||
functionality, the generated script is called.</p>
|
||
<p>The build system will detect if the Autoconf source files have
|
||
changed, and will trigger a regeneration of the generated script if
|
||
needed. You can also manually request such an update by
|
||
<code>bash configure autogen</code>.</p>
|
||
<h3 id="developing-the-build-system-itself">Developing the Build System
|
||
Itself</h3>
|
||
<p>This section contains a few remarks about how to develop for the
|
||
build system itself. It is not relevant if you are only making changes
|
||
in the product source code.</p>
|
||
<p>While technically using <code>make</code>, the make source files of
|
||
the JDK does not resemble most other Makefiles. Instead of listing
|
||
specific targets and actions (perhaps using patterns), the basic modus
|
||
operandi is to call a high-level function (or properly, macro) from the
|
||
API in <code>make/common</code>. For instance, to compile all classes in
|
||
the <code>jdk.internal.foo</code> package in the <code>jdk.foo</code>
|
||
module, a call like this would be made:</p>
|
||
<pre><code>$(eval $(call SetupJavaCompilation, BUILD_FOO_CLASSES, \
|
||
SETUP := GENERATE_OLDBYTECODE, \
|
||
SRC := $(TOPDIR)/src/jkd.foo/share/classes, \
|
||
INCLUDES := jdk/internal/foo, \
|
||
BIN := $(SUPPORT_OUTPUTDIR)/foo_classes, \
|
||
))</code></pre>
|
||
<p>By encapsulating and expressing the high-level knowledge of
|
||
<em>what</em> should be done, rather than <em>how</em> it should be done
|
||
(as is normal in Makefiles), we can build a much more powerful and
|
||
flexible build system.</p>
|
||
<p>Correct dependency tracking is paramount. Sloppy dependency tracking
|
||
will lead to improper parallelization, or worse, race conditions.</p>
|
||
<p>To test for/debug race conditions, try running
|
||
<code>make JOBS=1</code> and <code>make JOBS=100</code> and see if it
|
||
makes any difference. (It shouldn't).</p>
|
||
<p>To compare the output of two different builds and see if, and how,
|
||
they differ, run <code>$BUILD1/compare.sh -o $BUILD2</code>, where
|
||
<code>$BUILD1</code> and <code>$BUILD2</code> are the two builds you
|
||
want to compare.</p>
|
||
<p>To automatically build two consecutive versions and compare them, use
|
||
<code>COMPARE_BUILD</code>. The value of <code>COMPARE_BUILD</code> is a
|
||
set of variable=value assignments, like this:</p>
|
||
<pre><code>make COMPARE_BUILD=CONF=--enable-new-hotspot-feature:MAKE=hotspot</code></pre>
|
||
<p>See <code>make/InitSupport.gmk</code> for details on how to use
|
||
<code>COMPARE_BUILD</code>.</p>
|
||
<p>To analyze build performance, run with <code>LOG=trace</code> and
|
||
check <code>$BUILD/build-trace-time.log</code>. Use <code>JOBS=1</code>
|
||
to avoid parallelism.</p>
|
||
<p>Please check that you adhere to the <a
|
||
href="https://openjdk.org/groups/build/doc/code-conventions.html">Code
|
||
Conventions for the Build System</a> before submitting patches.</p>
|
||
<h2 id="contributing-to-the-jdk">Contributing to the JDK</h2>
|
||
<p>So, now you've built your JDK, and made your first patch, and want to
|
||
contribute it back to the OpenJDK Community.</p>
|
||
<p>First of all: Thank you! We gladly welcome your contribution.
|
||
However, please bear in mind that the JDK is a massive project, and we
|
||
must ask you to follow our rules and guidelines to be able to accept
|
||
your contribution.</p>
|
||
<p>The official place to start is the <a
|
||
href="https://openjdk.org/guide/">OpenJDK Developers’ Guide</a>.</p>
|
||
<h2 id="editing-this-document">Editing This Document</h2>
|
||
<p>If you want to contribute changes to this document, edit
|
||
<code>doc/building.md</code> and then run
|
||
<code>make update-build-docs</code> to generate the same changes in
|
||
<code>doc/building.html</code>.</p>
|
||
</body>
|
||
</html>
|