macOS 下编译 openjdk8

本次编译使用的系统是 macOS High Sierra,版本为 10.13.1。使用的 jdk 是 Oracle JDK,版本为 1.7.0_79

1
2
3
java version "1.7.0_79"
Java(TM) SE Runtime Environment (build 1.7.0_79-b15)
Java HotSpot(TM) 64-Bit Server VM (build 24.79-b02, mixed mode)

说明

openjdk 的模块,部分使用 C/C++ 编写实现,部分使用 Java 实现。因此除了需要 C/C++ 相关编译工具外,还需要有一个 JDK (Bootstrap JDK)。编译 openjdk8 时可使用 jdk1.7 作为 Bootstrap JDK。

openjdk8u 官方地址http://openjdk.java.net/projects/jdk8u/

准备工作

下载源码

官方的 openjdk 源码没有针对新的系统和编译工具链做处理,在编译的过程中遇到一堆问题,只能一个一个地去解决,需要花费很多时间。

在解决报错问题的时候发现 JetBrains 提供了一套 openjdk 源码

Usually, we do not modify any of the repositories except jdk module. Other repositories are needed for build purposes.

查看说明发现对 jdk 模块有修改,不过不影响研究。下载下来按说明编译,很快就可以编译成功,看来是解决了新环境下的报错问题。

1
2
3
git clone https://github.com/JetBrains/jdk8u.git
cd jdk8u/
sh ./getModules.sh

代码比较多,如果你下载比较慢,也可以从镜像下载

1
2
3
4
git clone https://gitee.com/gorden5566/jdk8u.git
cd jdk8u/
git checkout --track origin/fix
sh ./getModules.sh

目录结构

openjdk8 的目录结构如下,可对比检查下是否有遗漏模块

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
├── ASSEMBLY_EXCEPTION
├── LICENSE
├── Makefile
├── README-builds.html
├── README.md
├── THIRD_PARTY_README
├── common
├── configure
├── corba
├── hotspot
├── jaxp
├── jaxws
├── jdk
├── langtools
├── make
├── nashorn
└── test

安装依赖

FreeType

这里使用的是方法一

方法一

直接通过 brew 安装 FreeType

1
brew install freetype

执行 configure 时使用如下参数

1
--with-freetype=/usr/local --with-freetype-include=/usr/local/include/freetype2

方法二

下载并安装 XQuartz

执行 configure 时使用如下参数

1
--with-freetype=/opt/X11/lib --with-freetype-include=/usr/X11/include/freetype2

补充: linux 环境下配置

安装 libfreetype6-dev

1
sudo apt install libfreetype6-dev

查看安装路径

1
dpkg -L libfreetype6-dev

注意这两行输出的路径

1
2
/usr/include/freetype2/ft2build.h
/usr/lib/x86_64-linux-gnu/libfreetype.so

可以得到我们需要的参数

1
2
--with-freetype-include=/usr/include/freetype2/
--with-freetype-lib=/usr/lib/x86_64-linux-gnu/

Command Line Tools

执行命令安装

1
xcode-select --install

XCode

直接从 APP Store 安装最新版本的 XCode

注:经测试不安装也可以编译 release 版本的 jdk

编译 openjdk8

执行 configure

1
2
export MACOSX_DEPLOYMENT_TARGET=10.8
bash configure --with-freetype=/usr/local --with-freetype-include=/usr/local/include/freetype2

注:注意 freetype 的路径

输出结果如下 (具体路径可能会不同),已经在 build 目录下生成了 release 版本的相关配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
A new configuration has been successfully created in
/你的路径/jdk8u/build/macosx-x86_64-normal-server-release
using configure arguments '--with-freetype=/usr/local --with-freetype-include=/usr/local/include/freetype2'.

Configuration summary:
* Debug level: release
* JDK variant: normal
* JVM variants: server
* OpenJDK target: OS: macosx, CPU architecture: x86, address length: 64

Tools summary:
* Boot JDK: java version "1.7.0_79" Java(TM) SE Runtime Environment (build 1.7.0_79-b15) Java HotSpot(TM) 64-Bit Server VM (build 24.79-b02, mixed mode) (at /Library/Java/JavaVirtualMachines/jdk1.7.0_79.jdk/Contents/Home)
* C Compiler: version Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1 (at /usr/bin/gcc)
* C++ Compiler: version Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1 (at /usr/bin/g++)

编译

如果使用的是 Xcode 4.6.3 版本,可直接输入 make all 编译。使用更高的版本需指定 COMPILER_WARNINGS_FATAL=false

1
make all COMPILER_WARNINGS_FATAL=false

如果已经通过 configure 生成了多个配置 (build 目录下有多个文件夹),则会出现如下提示

1
2
3
4
5
6
Available configurations:
* macosx-x86_64-normal-server-fastdebug
* macosx-x86_64-normal-server-release
* macosx-x86_64-normal-server-slowdebug
Please retry building with CONF=<config pattern> (or SPEC=<specfile>)
Makefile:55: *** Cannot continue. Stop.

可通过 CONF=<config pattern> 指定要编译的版本,例如编译 release 版本

1
make all COMPILER_WARNINGS_FATAL=false CONF=release

自动匹配到对应的配置

1
Building 'macosx-x86_64-normal-server-release' (matching CONF=release)

编译完会输出各个模块的耗时,第一次编译耗时会比较长。如果中间有报错,修改后再次执行会跳过已编译好的模块。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
----- Build times -------
Start 2017-12-03 16:28:38
End 2017-12-03 16:32:22
00:00:01 corba
00:00:02 demos
00:02:32 docs
00:00:24 hotspot
00:00:22 images
00:00:02 jaxp
00:00:03 jaxws
00:00:12 jdk
00:00:05 langtools
00:00:00 nashorn
00:03:44 TOTAL
-------------------------
Finished building OpenJDK for target 'all'

检查 java 版本

编译生成的结果保存在 build 目录下,release 版本的目录为 macosx-x86_64-normal-server-release,目录结构如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
├── Makefile
├── bootcycle-spec.gmk
├── build.log
├── compare.sh
├── config.h
├── config.log
├── config.status
├── configure-arguments
├── corba
├── hotspot
├── hotspot-spec.gmk
├── images
├── jaxp
├── jaxws
├── jdk
├── langtools
├── nashorn
├── source_tips
├── spec.gmk
├── spec.sh
└── tmp

切换到 ./jdk/bin/ 目录下,执行命令查看 java 版本

1
2
3
4
./java -version
openjdk version "1.8.0-internal"
OpenJDK Runtime Environment (build 1.8.0-internal-gorden5566_2017_11_27_22_44-b00)
OpenJDK 64-Bit Server VM (build 25.71-b00, mixed mode)

测试一下

新建一个 HelloWorld.java 的测试文件

1
2
3
4
5
6
7
8
9
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello World");

int count = 0;
count = count + 3;
System.out.println("count = " + count);
}
}

编译并执行

1
2
./javac HelloWorld.java
./java HelloWorld

结果显示正常

1
2
Hello World
count = 3

编译参数

默认情况下编译的是 release 版本的 jdk,可通过参数指定编译为 fastdebug 或 slowdebug 版本

编译 fastdebug 版本

  1. 执行 configure 时带上 --with-debug-level=fastdebug 参数
  2. 执行 make 时指定选择 fastdebug 配置,需加上 CONF=fastdebug 参数

编译 slowdebug 版本

  1. 执行 configure 时带上 --with-debug-level=slowdebug 参数
  2. 执行 make 时指定选择 slowdebug 配置,需加上 CONF=slowdebug 参数

编译选项

执行 make help 查看可用的选项。如 make images 表示只编译 images 部分

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
OpenJDK Makefile help
=====================

Common make targets
. make [default] # Compile all product in langtools, hotspot, jaxp, jaxws,
. # corba and jdk
. make all # Compile everything, all repos and images
. make images # Create complete j2sdk and j2re images
. make docs # Create javadocs
. make overlay-images # Create limited images for sparc 64 bit platforms
. make profiles # Create complete j2re compact profile images
. make bootcycle-images # Build images twice, second time with newly build JDK
. make install # Install the generated images locally
. make clean # Remove all files generated by make, but not those
. # generated by configure
. make dist-clean # Remove all files, including configuration
. make help # Give some help on using make
. make test # Run tests, default is all tests (see TEST below)

Targets for specific components
(Component is any of langtools, corba, jaxp, jaxws, hotspot, jdk, nashorn, images, overlay-images, docs or test)
. make <component> # Build <component> and everything it depends on.
. make <component>-only # Build <component> only, without dependencies. This
. # is faster but can result in incorrect build results!
. make clean-<component> # Remove files generated by make for <component>

Useful make variables
. make CONF= # Build all configurations (note, assignment is empty)
. make CONF=<substring> # Build the configuration(s) with a name matching
. # <substring>

. make LOG=<loglevel> # Change the log level from warn to <loglevel>
. # Available log levels are:
. # 'warn' (default), 'info', 'debug' and 'trace'
. # To see executed command lines, use LOG=debug

. make JOBS=<n> # Run <n> parallel make jobs
. # Note that -jN does not work as expected!

. make test TEST=<test> # Only run the given test or tests, e.g.
. # make test TEST="jdk_lang jdk_net"

make: Nothing to be done for `help'.

参考

周志明. 深入理解Java虚拟机