Mac 环境使用 clang 编译 OpenJDK8

经历

搞了 3 个晚上,终于搞定了。在 mac 上各种版本不适配,也是很有意思的~需要折腾,需要折腾~


参看博客:

主要参照
主要参照的补充: 编译 debug 版 openjdk
R大的答案
很好的博客
重点!对 mac 下 libiconv 的操作
调试你的 openjdk


历程

按照主要参照的 github 上边的过程一步步来,注意要使用 clang 而不是 gcc。其实在 mac 就应该使用 clang,因为 gcc 不知道会引发什么潜在的隐患那…… 而且 clang 生成的调试信息貌似要比 gcc 好些吧。但是要注意:如果你想要调试的话,就要看看主要参照的补充那个博客了。因为 sh configure 后边需要有参数。我将会列在下边。


各种版本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
> clang -v
Apple LLVM version 8.1.0 (clang-802.0.42)
Target: x86_64-apple-darwin16.7.0
Thread model: posix
InstalledDir: /usr/bin
> clang++ -v
Apple LLVM version 8.1.0 (clang-802.0.42)
Target: x86_64-apple-darwin16.7.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
> java -version
java version "1.8.0_111"
Java(TM) SE Runtime Environment (build 1.8.0_111-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.111-b14, mixed mode)
  1. 以上即是各种 tools 的信息。注意,最好开着 VPN 进行 hg 的 pull 操作。因为这样下载速度会飙得很快~ 而且用 hg 貌似易于更新的话说。
  2. 其中,XQuartz 请下载最新的官网版本。不要用主要参照给出的链接,请自行使用 brew cask install XQuartz 来进行 brew 安装。因为链接给出的 XQuartz 版本太老了,是 SnowLeopard 版本的 mac 才适配的。
  3. xcode-select -install 在我这里已经没用了。不过貌似工具链完整,也不需要安装了。
  4. 编译开始之前,请一定要把 /usr/bin/gcc/usr/bin/g++ 改成 clangclang++!因为 ./configure 的时候会搜索这两个路径确认编译器 gcc 以及 g++。当然,如果你原先没有做过交叉编译啥的修改过 /usr/bin/gcc/usr/bin/g++ 的话,那么请忽略我这些话。
  5. 我的 shell 脚本,参照了一堆人的脚本,列举如下。我自己略加修改:
    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
    # 设定语言选项,必须设置
    export LANG=C
    # Mac平台,C编译器不再是GCC,是clang
    export CC=gcc
    # 跳过clang的一些严格的语法检查,不然会将N多的警告作为Error
    export COMPILER_WARNINGS_FATAL=false
    # 链接时使用的参数
    export LFLAGS='-Xlinker -lstdc++'
    # 是否使用clang
    export USE_CLANG=true
    # 使用64位数据模型
    export LP64=1
    # 告诉编译平台是64位,不然会按32位来编译
    export ARCH_DATA_MODEL=64
    # 允许自动下载依赖
    export ALLOW_DOWNLOADS=true
    # 并行编译的线程数,编译时间长,为了不影响其他工作,我选择为2
    export HOTSPOT_BUILD_JOBS=6
    export ALT_PARALLEL_COMPILE_JOBS=6
    # 是否跳过与先前版本的比较
    export SKIP_COMPARE_IMAGES=true
    # 是否使用预编译头文件,加快编译速度
    export USE_PRECOMPILED_HEADER=true
    # 是否使用增量编译
    export INCREMENTAL_BUILD=true
    # 编译内容
    export BUILD_LANGTOOLS=true
    export BUILD_JAXP=false
    export BUILD_JAXWS=false
    export BUILD_CORBA=false
    export BUILD_HOTSPOT=true
    export BUILD_JDK=true
    # 编译版本
    export SKIP_DEBUG_BUILD=true
    export SKIP_FASTDEBUG_BUILD=false
    export DEBUG_NAME=debug
    # 避开javaws和浏览器Java插件之类的部分的build
    export BUILD_DEPLOY=false
    export BUILD_INSTALL=false
    # 加上产生调试信息时需要的 objcopy
    # export OBJCOPY=gobjcopy

把它命名为 jvm.sh 的话,我们只需要执行 source ./jvm.sh 即可把临时环境变量设置好。

  1. 主要参照 的所有问题都遇到了。不得不说这是十分良心的经验~
  2. 不过,如果你要进行调试的话,需要把一开始的 sh configure 变成:sh configure --with-target-bits=64 --with-debug-level=slowdebug --enable-debug-symbols ZIP_DEBUGINFO_FILES=0。这样就会产生足够多数量的调试信息,方便调试~
  3. 如果你遵循了第 6 条,那么最后会提示你缺少 objcopy。那么请使用 brew install binutils 来安装 GNU 的组件,并且把 jvm.sh 的最后一行取消注释才行!
  4. 然后愉快地 make all 即可!

坑们

在我这里只出现了一个大坑,然而弄到了半夜QAQ。就是当编译 make all 的时候,到了编译 jdk 的时候,编译了一半出现了诡异的

1
2
3
4
5
6
7
Undefined symbols for architecture x86_64:
"_libiconv", referenced from:
......
"_libiconv_close", referenced from:
......
"_libiconv_open", referenced from:
......

这种狗血的错误。然后一看名就知道了……分明应该是 libiconv 的问题……然而特么一查,电脑中有各种 libiconv.dylib 包,还有各种花式的 libiconv.2.dylib 以及 libiconv.2.4.0.dylib…… 而且散布在不同目录下……我都不知道链接哪个才是正确的……于是不得不上网查,谷歌谷不出来还是百度百出来的(逃,(因为可能是谷歌不支持特殊字符的原因吧……),然后就查到了有一个回答支持,链接也贴出来了:重点!对 mac 下 libiconv 的操作。这个回答只要做第一步就好。即,把 /usr/lib/libiconv.dylib 变成 /usr/lib/libiconv1.dylib 即可,让链接库找不到就 ok。结果链接的是 /usr/bin 目录下的这个文件……其实 /usr/local/bin/ 里边还有同名的一套 libiconv 呢……
不过改完之后就能碰到 主要参照 的第三个错误了,照改不误就可以。对于这份 github 的经验实在是感激不尽!帮了大忙。


世界的终结

打开你自己的 build/macosx-x86_64-normal-server-slowdebug/jdk/bin 目录,然后 ./java,出现

1
2
3
4
5
6
用法: java [-options] class [args...]
(执行类)
或 java [-options] -jar jarfile [args...]
(执行 jar 文件)
其中选项包括:
......

就算大功告成!
但是,如果没有出现这,而是出现什么类似 某个文件800行有问题,提示你编译不完全 的错误提示的话,那你怕是要返工了。当时在 Docker 下 的 ubuntu 虚拟机编译的(其实我就把它当轻量的虚拟机来用HAHA,当时就出现了这个错误。而且错误信息中显示时间戳不对,肯定是编译的过程中出了些岔子吧。

如果你产生了调试信息,那么可以参见 调试你的 openjdk 的最后方,有调试的方法,很简单~

Enjoy it!