0x00 前言

《深入理解JVM》这本书都看了大半了,但是里面的实验还没真正动手操作过,于是趁这段时间一一操作一遍。

首当其冲的当然是编译JVM了,似乎所有的坑都被我都趟了一遍,就写篇文来记录一下,顺便告诫大家,不要试图在新版本的macOS中编译OpenJDK7!

0x01 编译环境

macOS Catalina 10.15.2
Xcode 11.6
Command Line Tools MacOSX10.15.sdk

0x02 准备工作

1. 下载源码

在macOS中,先用brew安装mercurial代码版本管理工具

brew install mercurial

获取源码:

hg clone http://hg.openjdk.java.net/jdk7u/jdk7u-dev
cd jdk7u-dev
chmod 755 get_source.sh
./get_source.sh

而国内的网络到了./get_source.sh这一步,下载过程中总是会网络异常中断,所以我是在国外的vps上面下载好之后,再压缩拉回来的。

2. 安装XCode和Command Line Tools for XCode

由于我之前已经安装了,所以这一步跳过,具体的版本可以看0x01编译环境中的描述

3. 准备一个Bootstrap SDK

书中说到,“如果编译OpenJDK 7,Bootstrap JDK必须使用JDK6 Update 14或之后的版本”,而我用的是JDK1.7.80版本。

4. 安装Apache Ant

Apache Ant 对版本有要求,1.7.1以上即可。 同时,Apache Ant 官网上有一句话必须要看一下:
“The 1.9.x releases require Java5 at runtime and 1.10.x requires Java8 at runtime. ”
大意就是1.9.x版本的ant 要求Java5以上版本的jre,而1.10.x版本的ant则要求Java8以上版本的jre。

0x03 编译

书中作者给出的编译脚本如下:

#语言选项,这个必须设置,否则编译好后会出现一个HashTable的NPE错
export LANG=C
#Bootstrap JDK的安装路径。必须设置
export ALT_BOOTDIR=/Library/Java/JavaVirtualMachines/jdk1.7.0_04.jdk/Contents/Home
#允许自动下载依赖
export ALLOW_DOWNLOADS=true
#并行编译的线程数,设置为和CPU内核数量一致即可
export HOTSPOT_BUILD_JOBS=6
export ALT_PARALLEL_COMPILE_JOBS=6
#比较本次build出来的映像与先前版本的差异。这对我们来说没有意义,
#必须设置为false,否则sanity检查会报缺少先前版本JDK的映像的错误提示。
#如果已经设置dev或者DEV_ONLY=true,这个不显式设置也行
export SKIP_COMPARE_IMAGES=true
#使用预编译头文件,不加这个编译会更慢一些
export USE_PRECOMPILED_HEADER=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=false
#export SKIP_FASTDEBUG_BUILD=true
#export DEBUG_NAME=debug
#把它设置为false可以避开javaws和浏览器Java插件之类的部分的build
BUILD_DEPLOY=false
#把它设置为false就不会build出安装包。因为安装包里有些奇怪的依赖,
#但即便不build出它也已经能得到完整的JDK映像,所以还是别build它好了
BUILD_INSTALL=false
#编译结果所存放的路径
export ALT_OUTPUTDIR=/Users/IcyFenix/Develop/JVM/jdkBuild/openjdk_7u4/build
#这两个环境变量必须去掉,不然会有很诡异的事情发生(我没有具体查过这些"诡异的
#事情",Makefile脚本检查到有这2个变量就会提示警告)
unset JAVA_HOME
unset CLASSPATH
make 2>&1|tee $ALT_OUTPUTDIR/build.log

0x04 坑

1.llvm-gcc 缺失导致的freetype_versioncheck的编译错误

首先最底下出现的是:

ERROR: The Compiler version is undefined. 
 
ERROR: FreeType version  2.3.0  or higher is required. 
 /bin/mkdir -p /Users/jackietsoi/Documents/develop/jdk7u-dev/JVM/jdkBuild/openjdk_7u4/build/btbins
rm -f /Users/jackietsoi/Documents/develop/jdk7u-dev/JVM/jdkBuild/openjdk_7u4/build/btbins/freetype_versioncheck
Failed to build freetypecheck.  

Exiting because of the above error(s).

上网搜了一下,还以为是缺失FreeType,于是根据网友说的安装XQuartz(http://xquartz.macosforge.org/landing/),因为XQuartz里面自带了freetype2,但是安装之后并没有解决问题,于是继续往上看输出:

make[2]: /Applications/Xcode.app/Contents/Developer/usr/bin/llvm-gcc: No such file or directory
make[2]: *** [/Users/jackietsoi/Documents/develop/jdk7u-dev/JVM/jdkBuild/openjdk_7u4/build/btbins/freetype_versioncheck] Error 1

解决方法:

sudo ln -s /usr/bin/llvm-g++ /Library/Developer/CommandLineTools/usr/bin/llvm-g++
sudo ln -s /usr/bin/llvm-gcc /Library/Developer/CommandLineTools/usr/bin/llvm-gcc

2.cups 头文件缺失问题

ERROR: You do not have access to valid Cups header files. 
       Please check your access to 
           /usr/include/cups/cups.h 
       and/or check your value of ALT_CUPS_HEADERS_PATH, 
       CUPS is frequently pre-installed on many systems, 
       or may be downloaded from http://www.cups.org 

解决方法:
http://www.cups.org 去下载cups2.3.3 然后解压整个文件夹,放到编译项目根目录 然后在编译脚本文件中加入一句:export ALT_CUPS_HEADERS_PATH=/Users/jackietsoi/Documents/develop/jdk7u-dev/cups-2.3.3

3.freetype 版本问题

ERROR: FreeType version  2.3.0  or higher is required. 
 /Users/jackietsoi/Documents/develop/jdk7u-dev/JVM/jdkBuild/openjdk_7u4/build/btbins/freetype_versioncheck
Required version of freetype: 2.3.0
Detected freetype headers: 2.10.4
Failed: headers are too old.
Detected freetype library: 2.10.4
Failed: too old library.  

Exiting because of the above error(s). 
 
make: *** [post-sanity] Error 1

去官网(https://www.freetype.org/download.html)下载 freetype-2.3.0 版本压缩包
解压,进入根目录执行以下命令进行编译,并安装:

./configure
make
make install

在编译脚本文件中加入两句:

export ALT_FREETYPE_HEADERS_PATH=/usr/local/include
export ALT_FREETYPE_LIB_PATH=/usr/local/lib

4.ant 1.10.x 要求最低jdk8问题

Exception in thread "main" java.lang.UnsupportedClassVersionError: org/apache/tools/ant/launch/Launcher : Unsupported major.minor version 52.0
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:791)
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
    at java.net.URLClassLoader.defineClass(URLClassLoader.java:449)
    at java.net.URLClassLoader.access$100(URLClassLoader.java:71)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:361)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:423)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:356)
    at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:480)
Exception in thread "main" java.lang.UnsupportedClassVersionError: org/apache/tools/ant/launch/Launcher : Unsupported major.minor version 52.0
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:791)
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
    at java.net.URLClassLoader.defineClass(URLClassLoader.java:449)
    at java.net.URLClassLoader.access$100(URLClassLoader.java:71)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:361)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:423)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:356)
    at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:480)
make[2]: *** [/Users/jackietsoi/Documents/develop/jdk7u-dev/JVM/jdkBuild/openjdk_7u4/build/langtools/build/ant-diagnostics.log] Error 1
make[1]: *** [langtools-build] Error 2
make: *** [build_product_image] Error 2

解决方法:
到Apache Ant官网(http://ant.apache.org/bindownload.cgi)下载 1.9.x版本的ant,将压缩包解压到一个目录下,如/usr/local

配置环境变量:
编辑 ~/.zshrc,在末尾加入两行:

export ANT_HOME=/usr/local/apache-ant-1.9.15
export PATH=$ANT_HOME/bin:$PATH

然后 source ~/.zshrc 使其生效

5.jdk版本问题

[javac] Compiling 298 source files to /Users/jackietsoi/Documents/develop/jdk7u-dev/JVM/jdkBuild/openjdk_7u4/build/langtools/build/bootstrap/classes
    [javac] /Users/jackietsoi/Documents/develop/jdk7u-dev/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java:2182: ??: [overrides] ?Resolve.InapplicableSymbolsError.Candidate??? equals, ???????????? hashCode ??
    [javac]         private class Candidate {
    [javac]                 ^
    [javac] ??: ????, ???? -Werror
    [javac] 1 ???
    [javac] 1 ???

BUILD FAILED
/Users/jackietsoi/Documents/develop/jdk7u-dev/langtools/make/build.xml:452: The following error occurred while executing this line:
/Users/jackietsoi/Documents/develop/jdk7u-dev/langtools/make/build.xml:795: Compile failed; see the compiler error output for details.

Total time: 4 seconds
make[2]: *** [build] Error 1
make[1]: *** [langtools-build] Error 2
make: *** [build_product_image] Error 2

解决方法:
将Bootstrap JDK 从1.8换到1.7即可,下载jdk7(https://www.oracle.com/java/technologies/javase/javase7-archive-downloads.html)
这里我下载的是jdk7u80,然后在编译脚本更改Bootstrap JDK的路径:
export ALT_BOOTDIR=/Library/Java/JavaVirtualMachines/jdk1.7.0_80.jdk/Contents/Home

6. warning 转义错误

/Users/jackietsoi/Documents/develop/jdk7u-dev/hotspot/src/share/vm/adlc/filebuff.cpp:109:8: error: 'this' pointer cannot be null in well-defined C++ code; pointer may be assumed to always convert to true [-Werror,-Wundefined-bool-conversion]
  if( !this ) return NULL;      // The empty buffer region
      ~^~~~
/Users/jackietsoi/Documents/develop/jdk7u-dev/hotspot/src/share/vm/adlc/filebuff.cpp:122:8: error: 'this' pointer cannot be null in well-defined C++ code; pointer may be assumed to always convert to true [-Werror,-Wundefined-bool-conversion]
  if( !this ) return br;        // Merging into nothing
      ~^~~~
/Users/jackietsoi/Documents/develop/jdk7u-dev/hotspot/src/share/vm/adlc/filebuff.cpp:228:8: error: reference cannot be bound to dereferenced null pointer in well-defined C++ code; comparison may be assumed to always evaluate to false [-Werror,-Wtautological-undefined-compare]
  if( &br == NULL ) return os;  // The empty buffer region
       ^~    ~~~~
/Users/jackietsoi/Documents/develop/jdk7u-dev/hotspot/src/share/vm/adlc/filebuff.cpp:244:8: error: 'this' pointer cannot be null in well-defined C++ code; pointer may be assumed to always convert to true [-Werror,-Wundefined-bool-conversion]
  if( !this ) return;           // Nothing to print
      ~^~~~
/Users/jackietsoi/Documents/develop/jdk7u-dev/hotspot/src/share/vm/adlc/archDesc.cpp:335:35: error: '&&' within '||' [-Werror,-Wlogical-op-parentheses]
    if ( instr->is_ideal_branch() && instr->label_position() == -1 ||
         ~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~
/Users/jackietsoi/Documents/develop/jdk7u-dev/hotspot/src/share/vm/adlc/archDesc.cpp:335:35: note: place parentheses around the '&&' expression to silence this warning
    if ( instr->is_ideal_branch() && instr->label_position() == -1 ||
                                  ^
         (                                                        )
/Users/jackietsoi/Documents/develop/jdk7u-dev/hotspot/src/share/vm/adlc/archDesc.cpp:336:35: error: '&&' within '||' [-Werror,-Wlogical-op-parentheses]
        !instr->is_ideal_branch() && instr->label_position() != -1) {
        ~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/Users/jackietsoi/Documents/develop/jdk7u-dev/hotspot/src/share/vm/adlc/archDesc.cpp:336:35: note: place parentheses around the '&&' expression to silence this warning
        !instr->is_ideal_branch() && instr->label_position() != -1) {
                                  ^
        (                                                         )
4 errors generated.
2 errors generated.
make[8]: *** [../generated/adfiles/filebuff.o] Error 1
make[8]: *** Waiting for unfinished jobs....
make[8]: *** [../generated/adfiles/archDesc.o] Error 1
Compiling /Users/jackietsoi/Documents/develop/jdk7u-dev/hotspot/src/share/vm/adlc/forms.cpp
rm -f ../generated/adfiles/forms.o
llvm-g++ -D_ALLBSD_SOURCE -D_GNU_SOURCE -DAMD64 -I/Users/jackietsoi/Documents/develop/jdk7u-dev/hotspot/src/share/vm/prims -I/Users/jackietsoi/Documents/develop/jdk7u-dev/hotspot/src/share/vm -I/Users/jackietsoi/Documents/develop/jdk7u-dev/hotspot/src/share/vm/precompiled -I/Users/jackietsoi/Documents/develop/jdk7u-dev/hotspot/src/cpu/x86/vm -I/Users/jackietsoi/Documents/develop/jdk7u-dev/hotspot/src/os_cpu/bsd_x86/vm -I/Users/jackietsoi/Documents/develop/jdk7u-dev/hotspot/src/os/bsd/vm -I/Users/jackietsoi/Documents/develop/jdk7u-dev/hotspot/src/os/posix/vm -I/Users/jackietsoi/Documents/develop/jdk7u-dev/hotspot/src/share/vm/adlc -I../generated -DASSERT -DTARGET_OS_FAMILY_bsd -DTARGET_ARCH_x86 -DTARGET_ARCH_MODEL_x86_64 -DTARGET_OS_ARCH_bsd_x86 -DTARGET_OS_ARCH_MODEL_bsd_x86_64 -DTARGET_COMPILER_gcc -DCOMPILER2 -DCOMPILER1  -fno-rtti -fno-exceptions -pthread -fcheck-new -fvisibility=hidden -m64 -pipe -Werror -g -c -o ../generated/adfiles/forms.o /Users/jackietsoi/Documents/develop/jdk7u-dev/hotspot/src/share/vm/adlc/forms.cpp 
/Users/jackietsoi/Documents/develop/jdk7u-dev/hotspot/src/share/vm/adlc/adlparse.cpp:3217:71: error: equality comparison with extraneous parentheses [-Werror,-Wparentheses-equality]
    if ( ((primary = get_ident_or_literal_constant("primary opcode")) == NULL) ) {
          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~
/Users/jackietsoi/Documents/develop/jdk7u-dev/hotspot/src/share/vm/adlc/adlparse.cpp:3217:71: note: remove extraneous parentheses around the comparison to silence this warning
    if ( ((primary = get_ident_or_literal_constant("primary opcode")) == NULL) ) {
         ~                                                            ^      ~
/Users/jackietsoi/Documents/develop/jdk7u-dev/hotspot/src/share/vm/adlc/adlparse.cpp:3217:71: note: use '=' to turn this equality comparison into an assignment
    if ( ((primary = get_ident_or_literal_constant("primary opcode")) == NULL) ) {
                                                                      ^~
                                                                      =
/Users/jackietsoi/Documents/develop/jdk7u-dev/hotspot/src/share/vm/adlc/adlparse.cpp:3226:77: error: equality comparison with extraneous parentheses [-Werror,-Wparentheses-equality]
      if ( ((secondary = get_ident_or_literal_constant("secondary opcode")) == NULL) ) {
            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~
/Users/jackietsoi/Documents/develop/jdk7u-dev/hotspot/src/share/vm/adlc/adlparse.cpp:3226:77: note: remove extraneous parentheses around the comparison to silence this warning
      if ( ((secondary = get_ident_or_literal_constant("secondary opcode")) == NULL) ) {
           ~                                                                ^      ~
/Users/jackietsoi/Documents/develop/jdk7u-dev/hotspot/src/share/vm/adlc/adlparse.cpp:3226:77: note: use '=' to turn this equality comparison into an assignment
      if ( ((secondary = get_ident_or_literal_constant("secondary opcode")) == NULL) ) {
                                                                            ^~
                                                                            =
/Users/jackietsoi/Documents/develop/jdk7u-dev/hotspot/src/share/vm/adlc/adlparse.cpp:3235:77: error: equality comparison with extraneous parentheses [-Werror,-Wparentheses-equality]
        if ( ((tertiary = get_ident_or_literal_constant("tertiary opcode")) == NULL) ) {
              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~
/Users/jackietsoi/Documents/develop/jdk7u-dev/hotspot/src/share/vm/adlc/adlparse.cpp:3235:77: note: remove extraneous parentheses around the comparison to silence this warning
        if ( ((tertiary = get_ident_or_literal_constant("tertiary opcode")) == NULL) ) {
             ~                                                              ^      ~
/Users/jackietsoi/Documents/develop/jdk7u-dev/hotspot/src/share/vm/adlc/adlparse.cpp:3235:77: note: use '=' to turn this equality comparison into an assignment
        if ( ((tertiary = get_ident_or_literal_constant("tertiary opcode")) == NULL) ) {
                                                                            ^~
                                                                            =
/Users/jackietsoi/Documents/develop/jdk7u-dev/hotspot/src/share/vm/adlc/adlparse.cpp:4476:21: error: '&&' within '||' [-Werror,-Wlogical-op-parentheses]
  while ((c >= '0') && (c <= '9')
         ~~~~~~~~~~~^~~~~~~~~~~~~
/Users/jackietsoi/Documents/develop/jdk7u-dev/hotspot/src/share/vm/adlc/adlparse.cpp:4476:21: note: place parentheses around the '&&' expression to silence this warning
  while ((c >= '0') && (c <= '9')
                    ^
         (                       )
/Users/jackietsoi/Documents/develop/jdk7u-dev/hotspot/src/share/vm/adlc/adlparse.cpp:4515:17: error: equality comparison with extraneous parentheses [-Werror,-Wparentheses-equality]
    if( (second == '=') ) {
         ~~~~~~~^~~~~~
/Users/jackietsoi/Documents/develop/jdk7u-dev/hotspot/src/share/vm/adlc/adlparse.cpp:4515:17: note: remove extraneous parentheses around the comparison to silence this warning
    if( (second == '=') ) {
        ~       ^     ~
/Users/jackietsoi/Documents/develop/jdk7u-dev/hotspot/src/share/vm/adlc/adlparse.cpp:4515:17: note: use '=' to turn this equality comparison into an assignment
    if( (second == '=') ) {
                ^~
                =
5 errors generated.
make[8]: *** [../generated/adfiles/adlparse.o] Error 1
make[7]: *** [ad_stuff] Error 2
make[6]: *** [product] Error 2
make[5]: *** [generic_build2] Error 2
make[4]: *** [product] Error 2
make[3]: *** [all_product_universal] Error 2
make[2]: *** [universal_product] Error 2
make[1]: *** [hotspot-build] Error 2
make: *** [build_product_image] Error 2

解决方法:
关掉warning警告,打开编译脚本加入一行export COMPILER_WARNINGS_FATAL=false,继续执行即可

7. clang: error: unknown argument: ‘-fpch-deps’错误

clang: error: unknown argument: '-fpch-deps'
make[8]: *** [precompiled.hpp.gch] Error 1
make[7]: *** [the_vm] Error 2
make[6]: *** [product] Error 2
make[5]: *** [generic_build2] Error 2
make[4]: *** [product] Error 2
make[3]: *** [all_product_universal] Error 2
make[2]: *** [universal_product] Error 2
make[1]: *** [hotspot-build] Error 2
make: *** [build_product_image] Error 2

解决方法:
vi ./hotspot/make/bsd/makefiles/gcc.make将以下两段代码注释掉

#ifneq ($(COMPILER_WARNINGS_FATAL),false)
#  WARNINGS_ARE_ERRORS = -Werror
#endif
#ifneq ("${CC_VER_MAJOR}", "2")
#DEPFLAGS = -fpch-deps -MMD -MP -MF $(DEP_DIR)/$(@:%=%.d)
#endif

8.error: friend declaration specifying a default argument must be a definition 错误

/Users/jackietsoi/Documents/develop/jdk7u-dev/hotspot/src/share/vm/code/relocInfo.hpp:374:27: error: friend declaration specifying a default argument must be a definition
  inline friend relocInfo prefix_relocInfo(int datalen = 0);
                          ^
/Users/jackietsoi/Documents/develop/jdk7u-dev/hotspot/src/share/vm/code/relocInfo.hpp:469:18: error: friend declaration specifying a default argument must be the only declaration
inline relocInfo prefix_relocInfo(int datalen) {

解决方法: vi hotspot/src/share/vm/code/relocInfo.hpp
inline friend relocInfo prefix_relocInfo(int datalen = 0);改成 inline friend relocInfo prefix_relocInfo(int datalen);
inline relocInfo prefix_relocInfo(int datalen) {改成inline relocInfo prefix_relocInfo(int datalen = 0) {

9.指针与0比较问题

/Users/jackietsoi/Documents/develop/jdk7u-dev/hotspot/src/share/vm/runtime/virtualspace.cpp:527:14: error: ordered comparison between pointer and zero ('char *' and 'int')
  if (base() > 0) {
      ~~~~~~ ^ ~
/Users/jackietsoi/Documents/develop/jdk7u-dev/hotspot/src/share/vm/runtime/virtualspace.cpp:546:14: error: ordered comparison between pointer and zero ('char *' and 'int')
  if (base() > 0) {
      ~~~~~~ ^ ~

解决方法:
vi ./hotspot/src/share/vm/runtime/virtualspace.cpp
/if (base() > 0)查找所有该语句,并将其改成if (base() != NULL)

10.找不到JavaNativeFoundation.h头文件问题

/Users/jackietsoi/Documents/develop/jdk7u-dev/hotspot/agent/src/os/bsd/MacosxDebuggerLocal.m:27:9: fatal error: 'JavaNativeFoundation/JavaNativeFoundation.h' file not found
#import <JavaNativeFoundation/JavaNativeFoundation.h>
        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/Users/jackietsoi/Documents/develop/jdk7u-dev/hotspot/agent/src/os/bsd/MacosxDebuggerLocal.m:27:9: note: did not find header 'JavaNativeFoundation.h' in framework 'JavaNativeFoundation' (loaded from '/System/Library/Frameworks/JavaVM.framework/Frameworks')
1 error generated.

解决方法:
终端执行find / -name "*JavaNativeFoundation.h*"命令,出现结果:

/Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk/System/Library/Frameworks/JavaVM.framework/Versions/A/Frameworks/JavaNativeFoundation.framework/Versions/A/Headers/JavaNativeFoundation.h
/Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk/System/Library/Frameworks/JavaVM.framework/Versions/A/Frameworks/JavaNativeFoundation.framework/Versions/A/Headers/JavaNativeFoundation.h

编辑hotspot/make/bsd/makefiles/saproc.make进行如下修改:

原:
SALIBS = -g -framework Foundation -F/System/Library/Frameworks/JavaVM.framework/Frameworks -framework JavaNativeFoundation -framework Security -framework CoreFoundation
修改后:
SALIBS = -g -framework Foundation -F/Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk/System/Library/Frameworks -framework JavaNativeFoundation -framework Security -framework CoreFoundation

原:
-I/System/Library/Frameworks/JavaVM.framework/Headers
修改后:
-I/Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk/System/Library/Frameworks/JavaVM.framework/Versions/A/Frameworks/JavaNativeFoundation.framework/Versions/A/Headers

11.Undefined symbols for architecture x86_64

llvm-gcc -m64   -m64  -L`pwd`  -framework CoreFoundation  -o gamma launcher/java_md.o launcher/java.o launcher/jli_util.o launcher/wildcard.o -ljvm -lm -pthread
Undefined symbols for architecture x86_64:
  "_JNI_CreateJavaVM", referenced from:
      _LoadJavaVM in java_md.o
  "_JNI_GetDefaultJavaVMInitArgs", referenced from:
      _LoadJavaVM in java_md.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[8]: *** [gamma] Error 1
make[7]: *** [the_vm] Error 2
make[6]: *** [product] Error 2
make[5]: *** [generic_build2] Error 2
make[4]: *** [product] Error 2
make[3]: *** [all_product_universal] Error 2
make[2]: *** [universal_product] Error 2
make[1]: *** [hotspot-build] Error 2
make: *** [build_product_image] Error 2

解决方法:
这个错误困扰了我很久,一开始看上面的

Linking vm...
ld: warning: cannot export hidden symbol _AsyncGetCallTrace from forte.o

还以为是export symbol过程中出现问题,修改过jdk/src/macosx/native/sun/osxapp/ThreadUtilities.中的attachCurrentThread函数,改为static,还是无法解决问题
后面上stackflow上面搜了以下,发现应该是llvm-gcc编译的时候,找不到库文件导致的,仔细看了以下编译命令

llvm-gcc -m64   -m64  -L`pwd`...

其中-L是指定库文件目录,它指向了当前pwd即目录,然后我find ./ -name "java_md.o",发现它在.//JVM/jdkBuild/openjdk_7u4/build/hotspot/outputdir/bsd_amd64_compiler2/product/launcher/java_md.o,那么此时pwd就应该在.//JVM/jdkBuild/openjdk_7u4/build/hotspot/outputdir/bsd_amd64_compiler2/product,而当前编译所需要的库文件是/Library/Java/JavaVirtualMachines/jdk1.7.0_80.jdk/Contents/Home/jre/lib/server/libjvm.dylib
使用cp命令将其复制到pwd就好了:

sudo cp /Library/Java/JavaVirtualMachines/jdk1.7.0_80.jdk/Contents/Home/jre/lib/server/libjvm.dylib ./JVM/jdkBuild/openjdk_7u4/build/hotspot/outputdir/bsd_amd64_compiler2/product

12.找不到CGBase.h头文件问题

/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/Foundation.framework/Headers/NSGeometry.h:9:9: fatal error: 
      'CoreGraphics/CGBase.h' file not found
#import <CoreGraphics/CGBase.h>
        ^~~~~~~~~~~~~~~~~~~~~~~
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/Foundation.framework/Headers/NSGeometry.h:9:9: note: 
      did not find header 'CGBase.h' in framework 'CoreGraphics' (loaded from
      '/System/Library/Frameworks/ApplicationServices.framework/Frameworks')
1 error generated.
make[5]: *** [/Users/jackietsoi/Documents/develop/jdk7u-dev/JVM/jdkBuild/openjdk_7u4/build/tmp/java/java.lang/java/obj64/java_props_macosx.o] Error 1
make[4]: *** [library_parallel_compile] Error 2
make[3]: *** [all] Error 1
make[2]: *** [all] Error 1
make[1]: *** [jdk-build] Error 2
make: *** [build_product_image] Error 2

解决方法:
vi ./jdk/make/common/Defs-macosx.gmk进行如下更改:

#OTHER_CFLAGS = \
#         -F/System/Library/Frameworks/JavaVM.framework/Frameworks \
#       -F/System/Library/Frameworks/CoreGraphics.framework \
#        -F/System/Library/Frameworks/ApplicationServices.framework/Frameworks

OTHER_CFLAGS = \
      -F/Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk/System/Library/Frameworks/JavaVM.framework/Frameworks \
      -F/Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk/System/Library/Frameworks/CoreGraphics.framework/Frameworks \
     -F/Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks

同样使用find ./ -name "CGBase.h"找到路径,将/System/Library/Frameworks/JavaVM.framework/Frameworks等路径替换掉即可。

15 从macOS14 sdk开始不再支持32位程序编译

awt库的编译需要有i386架构的库的支持,但是Apple从macOS14 sdk开始就不再包含32位程序编译支持了,最后一个支持32位程序编译的版本是macOS13 sdk。

ld: warning: The i386 architecture is deprecated for macOS (remove from the Xcode build setting: ARCHS)
ld: warning: ignoring file /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/lib/libSystem.tbd, missing required architecture i386 in file /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/lib/libSystem.tbd
Undefined symbols for architecture i386:
  "___stack_chk_fail", referenced from:
      _main in sizer-32b644.o
  "___stack_chk_guard", referenced from:
      _main in sizer-32b644.o
  "_printf", referenced from:
      _main in sizer-32b644.o
ld: symbol(s) not found for architecture i386
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[4]: *** [/Users/jackietsoi/Documents/develop/jdk7u-dev/JVM/jdkBuild/openjdk_7u4/build/gensrc/sun/awt/X11/generator/sizer.32] Error 1
make[3]: *** [all] Error 1
make[2]: *** [all] Error 1
make[1]: *** [jdk-build] Error 2
make: *** [build_product_image] Error 2

解决方法:
我也尝试去下载了Command_Line_Tools_macOS_10.13_for_Xcode_10.1.dmg进行安装,但是却提示“该软件包与此版本的macOS不兼容”,有兴趣的朋友可以自己再试一下,我就不再折腾了。最后给出最后给出Command Line Tools的下载地址https://developer.apple.com/download/more/

0x05 总结

在macOS中编译openjdk7也折腾了两天,最终还是以失败告终,接下来我将使用Ubuntu16.04进行再一次编译尝试,敬请期待。