../gnu-classpath-on-macos
在 macOS 上编译 GNU Classpath
Published:
classpath
gnu
记录在 macOS Catalina 上编译 GNU Classpath 0.99 的过程。
变更记录
- 2020-01-10 初始化
编译环境
- macOS Catalina 10.15.6
- OpenJDK 8
- Antlr4
准备编译环境和源文件
# 安装 antlr
brew install antlr
# 根目录不可写,重新挂载一下
sudo mount -uw /
# 项目路径
sudo mkdir -p /usr/local/app
sudo chown -R `whoami`:admin /usr/loca/app
# 下载并解压源文件
cd /usr/local/app
wget 'https://ftp.gnu.org/gnu/classpath/classpath-0.99.tar.gz'
tar -xvf classpath-0.99.tar.gz
# 安装路径
sudo mkdir -p /usr/local/classpath
sudo chown -R `whoami`:admin /usr/local/classpath
编译
configure
cd /usr/local/app/classpath-0.99
# configure
./configure --disable-plugin --disable-gtk-peer --disable-gjdoc --disable-examples --disable-gconf-peer --with-glibj=both
没有报错则说明配置成功。
make 第一次
make
一通输出之后,最后输出为
...
java_io_VMConsole.c:80:19: error: use of undeclared identifier 'IUCLC'
new.c_iflag &= ~TERMIOS_ECHO_IFLAGS;
^
java_io_VMConsole.c:50:30: note: expanded from macro 'TERMIOS_ECHO_IFLAGS'
#define TERMIOS_ECHO_IFLAGS (IUCLC|IXON|IXOFF|IXANY)
^
21 warnings and 1 error generated.
make[2]: *** [java_io_VMConsole.lo] Error 1
make[1]: *** [all-recursive] Error 1
make: *** [all-recursive] Error 1
参考 how-to-build-gnu-classpath-and-jamvm。
sed -i '/#define/i\#define IUCLC 001000' native/jni/java-io/java_io_VMConsole.c
修改后继续编译
make 第二次
make
一通输出之后,最后输出为
/bin/sh ../../../libtool --tag=CC --mode=link gcc -W -Wall -Wmissing-declarations -Wwrite-strings -Wmissing-prototypes -Wno-long-long -Wstrict-prototypes -pedantic -fexceptions -fasynchronous-unwind-tables -g -O2 -version-info 0:0:0 -no-undefined -o libjavaio.la -rpath /usr/local/classpath/lib/classpath java_io_VMConsole.lo java_io_VMFile.lo java_io_VMObjectInputStream.lo java_io_VMObjectStreamClass.lo ../../../native/jni/classpath/jcl.lo ../../../native/jni/native-lib/libclasspathnative.la
libtool: link: gcc -dynamiclib -o .libs/libjavaio.0.dylib .libs/java_io_VMConsole.o .libs/java_io_VMFile.o .libs/java_io_VMObjectInputStream.o .libs/java_io_VMObjectStreamClass.o ../../../native/jni/classpath/.libs/jcl.o -Wl,-force_load,../../../native/jni/native-lib/.libs/libclasspathnative.a -O2 -install_name /usr/local/classpath/lib/classpath/libjavaio.0.dylib -compatibility_version 1 -current_version 1.0 -Wl,-single_module
Undefined symbols for architecture x86_64:
"___darwin_check_fd_set_overflow", referenced from:
_waitForReadable in libclasspathnative.a(cpnet.o)
_waitForWritable in libclasspathnative.a(cpnet.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[3]: *** [libjavaio.la] Error 1
make[2]: *** [all-recursive] Error 1
make[1]: *** [all-recursive] Error 1
make: *** [all-recursive] Error 1
大概就是有个函数找不到了,为了编译,将相关引用注释掉。
- 将
native/jni/native-lib/cpnet.c
文件内waitForWritable
方法替换为。
static jint waitForWritable(jint fd)
{
// struct timeval tv;
// fd_set writeset;
// int ret;
//
//
// FD_ZERO(&writeset);
// FD_SET(fd, &writeset);
// if (socketTimeouts[fd] > 0)
// {
// tv.tv_sec = socketTimeouts[fd] / 1000;
// tv.tv_usec = (socketTimeouts[fd] % 1000) * 1000;
// ret = select(fd+1, NULL, &writeset, NULL, &tv);
// }
// else
// ret = select(fd+1, NULL, &writeset, NULL, NULL);
//
// return (ret <= 0) ? -1 : 0;
return 0;
}
- 将
native/jni/native-lib/cpnet.c
文件内waitForReadable
方法替换为。
static jint waitForReadable(jint fd)
{
// struct timeval tv;
// fd_set readset;
// int ret;
//
//
// FD_ZERO(&readset);
// FD_SET(fd, &readset);
// if (socketTimeouts[fd] > 0)
// {
// tv.tv_sec = socketTimeouts[fd] / 1000;
// tv.tv_usec = (socketTimeouts[fd] % 1000) * 1000;
// ret = select(fd+1, &readset, NULL, NULL, &tv);
// }
// else
// ret = select(fd+1, &readset, NULL, NULL, NULL);
//
// return (ret <= 0) ? -1 : 0;
return 0;
}
make 第三次
继续编译
make
一通输出之后,最后输出为
libtool: link: gcc -dynamiclib -o .libs/libjavanio.0.dylib .libs/gnu_java_nio_VMPipe.o .libs/gnu_java_nio_VMChannel.o .libs/gnu_java_nio_VMSelector.o .libs/gnu_java_nio_charset_iconv_IconvDecoder.o .libs/gnu_java_nio_charset_iconv_IconvEncoder.o .libs/java_nio_MappedByteBufferImpl.o .libs/java_nio_VMDirectByteBuffer.o .libs/gnu_java_nio_EpollSelectorImpl.o .libs/gnu_java_nio_KqueueSelectorImpl.o ../../../native/jni/classpath/.libs/jcl.o -Wl,-force_load,../../../native/jni/native-lib/.libs/libclasspathnative.a -liconv -O2 -install_name /usr/local/classpath/lib/classpath/libjavanio.0.dylib -compatibility_version 1 -current_version 1.0 -Wl,-single_module
Undefined symbols for architecture x86_64:
"___darwin_check_fd_set_overflow", referenced from:
_Java_gnu_java_nio_VMChannel_connect in gnu_java_nio_VMChannel.o
_Java_gnu_java_nio_VMChannel_connect6 in gnu_java_nio_VMChannel.o
_Java_gnu_java_nio_VMChannel_accept in gnu_java_nio_VMChannel.o
_helper_put_filedescriptors in gnu_java_nio_VMSelector.o
_helper_get_filedescriptors in gnu_java_nio_VMSelector.o
_Java_gnu_java_nio_VMSelector_select in gnu_java_nio_VMSelector.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[3]: *** [libjavanio.la] Error 1
make[2]: *** [all-recursive] Error 1
make[1]: *** [all-recursive] Error 1
make: *** [all-recursive] Error 1
与上面的报错一直,同理,注释掉相关代码, 看代码发现内部有宏控制,修改 src/config.h.in
文件。
sed -i '/#undef HAVE_CONNECT/i\/\//' src/config.h.in
sed -i '/#undef HAVE_ACCEPT/i\/\//' src/config.h.in
而下方三个需要注释方法体。
_helper_put_filedescriptors in gnu_java_nio_VMSelector.o
_helper_get_filedescriptors in gnu_java_nio_VMSelector.o
_Java_gnu_java_nio_VMSelector_select in gnu_java_nio_VMSelector.o
- 将
native/jni/java-nio/gnu_java_nio_VMSelector.c
文件内helper_put_filedescriptors
方法替换为。
void
helper_put_filedescriptors (JNIEnv * env, jintArray fdArray, fd_set * fds,
int *max_fd){
}
- 将
native/jni/java-nio/gnu_java_nio_VMSelector.c
文件内helper_get_filedescriptors
方法替换为。
void
helper_put_filedescriptors (JNIEnv * env, jintArray fdArray, fd_set * fds,
int *max_fd){
}
- 将
native/jni/java-nio/gnu_java_nio_VMSelector.c
文件内Java_gnu_java_nio_VMSelector_select
方法替换为。
JNIEXPORT jint JNICALL
Java_gnu_java_nio_VMSelector_select (JNIEnv * env,
jclass obj __attribute__ ((__unused__)),
jintArray read,
jintArray write,
jintArray except, jlong timeout)
{
return 0;
}
make 第四次
重新配置并编译
./configure --disable-plugin --disable-gtk-peer --disable-gjdoc --disable-examples --disable-gconf-peer --with-glibj=both
make
一通输出之后,最后输出为
test -z "/usr/local/classpath/bin" || /usr/local/opt/coreutils/libexec/gnubin/mkdir -p "/usr/local/classpath/bin"
/usr/local/opt/coreutils/libexec/gnubin/install -c gappletviewer gjarsigner gkeytool gjar gnative2ascii gserialver gjavah grmiregistry gtnameserv gorbd grmid grmic '/usr/local/classpath/bin'
test -z "/usr/local/classpath/share/classpath" || /usr/local/opt/coreutils/libexec/gnubin/mkdir -p "/usr/local/classpath/share/classpath"
/usr/local/opt/coreutils/libexec/gnubin/install -c -m 644 tools.zip '/usr/local/classpath/share/classpath'
make[2]: Nothing to be done for `install-exec-am'.
make[2]: Nothing to be done for `install-data-am'.
编译成功。
安装
make install
不出意外 /usr/local/classpath
目录下结构如下
tree -L 3 -d /usr/local/classpath
=>
/usr/local/classpath/
├── bin
├── include
├── lib
│ ├── classpath
│ └── security
└── share
├── classpath
│ ├── META-INF
│ ├── gnu
│ ├── java
│ ├── javax
│ ├── org
│ └── sun
├── info
└── man
└── man1
16 directories
其他
修改之后的项目仓库 classpath-0.99
此次变更的 commit c9fbfb4