Skip to content

Commit 4c18b9e

Browse files
JornVerneeshipilev
andcommitted
8309880: Add support for linking libffi on Windows and Mac
Co-authored-by: Aleksey Shipilev <shade@openjdk.org> Co-authored-by: Jorn Vernee <jvernee@openjdk.org> Reviewed-by: erikj
1 parent 1d1ed0d commit 4c18b9e

File tree

7 files changed

+126
-30
lines changed

7 files changed

+126
-30
lines changed

make/autoconf/lib-ffi.m4

Lines changed: 60 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,11 @@ AC_DEFUN_ONCE([LIB_SETUP_LIBFFI],
5757
5858
if test "x${with_libffi}" != x; then
5959
LIBFFI_LIB_PATH="${with_libffi}/lib"
60-
LIBFFI_LIBS="-L${with_libffi}/lib -lffi"
60+
if test "x${OPENJDK_TARGET_OS}" != "xwindows"; then
61+
LIBFFI_LIBS="-L${with_libffi}/lib -lffi"
62+
else
63+
LIBFFI_LIBS="${with_libffi}/lib/libffi.lib"
64+
fi
6165
LIBFFI_CFLAGS="-I${with_libffi}/include"
6266
LIBFFI_FOUND=yes
6367
fi
@@ -67,7 +71,11 @@ AC_DEFUN_ONCE([LIB_SETUP_LIBFFI],
6771
fi
6872
if test "x${with_libffi_lib}" != x; then
6973
LIBFFI_LIB_PATH="${with_libffi_lib}"
70-
LIBFFI_LIBS="-L${with_libffi_lib} -lffi"
74+
if test "x${OPENJDK_TARGET_OS}" != "xwindows"; then
75+
LIBFFI_LIBS="-L${with_libffi_lib} -lffi"
76+
else
77+
LIBFFI_LIBS="${with_libffi_lib}/libffi.lib"
78+
fi
7179
LIBFFI_FOUND=yes
7280
fi
7381
# Do not try pkg-config if we have a sysroot set.
@@ -106,12 +114,13 @@ AC_DEFUN_ONCE([LIB_SETUP_LIBFFI],
106114
AC_MSG_ERROR([Could not find libffi! $HELP_MSG])
107115
fi
108116
109-
AC_MSG_CHECKING([if libffi works])
110117
AC_LANG_PUSH(C)
111118
OLD_CFLAGS="$CFLAGS"
112119
CFLAGS="$CFLAGS $LIBFFI_CFLAGS"
113120
OLD_LIBS="$LIBS"
114121
LIBS="$LIBS $LIBFFI_LIBS"
122+
123+
AC_MSG_CHECKING([if libffi works])
115124
AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <ffi.h>],
116125
[
117126
ffi_call(NULL, NULL, NULL, NULL);
@@ -120,49 +129,78 @@ AC_DEFUN_ONCE([LIB_SETUP_LIBFFI],
120129
[LIBFFI_WORKS=yes],
121130
[LIBFFI_WORKS=no]
122131
)
123-
CFLAGS="$OLD_CFLAGS"
124-
LIBS="$OLD_LIBS"
125-
AC_LANG_POP(C)
126132
AC_MSG_RESULT([$LIBFFI_WORKS])
127133
128134
if test "x$LIBFFI_WORKS" = xno; then
129135
HELP_MSG_MISSING_DEPENDENCY([ffi])
130136
AC_MSG_ERROR([Found libffi but could not link and compile with it. $HELP_MSG])
131137
fi
132138
139+
# Check if FFI_GO_CLOSURES is properly defined. On some distributions, notably MacOS AArch64,
140+
# ffitarget.h (included from ffi.h) does not explicitly define FFI_GO_CLOSURES. This makes the
141+
# further include of ffi.h trigger the "FFI_GO_CLOSURES is undefined" warning, which fails
142+
# the build when warnings are fatal.
143+
AC_MSG_CHECKING([for FFI_GO_CLOSURES definition])
144+
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([
145+
#include <ffi.h>
146+
#ifndef FFI_GO_CLOSURES
147+
#error "FFI_GO_CLOSURES is not defined"
148+
#endif
149+
][])],
150+
[
151+
AC_MSG_RESULT([yes])
152+
],
153+
[
154+
AC_MSG_RESULT([no, defining])
155+
LIBFFI_CFLAGS="$LIBFFI_CFLAGS -DFFI_GO_CLOSURES=0"
156+
]
157+
)
158+
159+
CFLAGS="$OLD_CFLAGS"
160+
LIBS="$OLD_LIBS"
161+
AC_LANG_POP(C)
162+
133163
# Find the libffi.so.X to bundle
134164
if test "x${ENABLE_LIBFFI_BUNDLING}" = "xtrue"; then
165+
if test "x${OPENJDK_TARGET_OS}" = "xmacosx"; then
166+
LIBFFI_LIB_FILE_NAME=libffi.?.dylib
167+
elif test "x${OPENJDK_TARGET_OS}" = "xwindows"; then
168+
LIBFFI_LIB_FILE_NAME=libffi.dll
169+
else
170+
LIBFFI_LIB_FILE_NAME=libffi.so.?
171+
fi
172+
135173
AC_MSG_CHECKING([for libffi lib file location])
136174
if test "x${LIBFFI_LIB_PATH}" != x; then
137-
if test -e ${LIBFFI_LIB_PATH}/libffi.so.?; then
138-
LIBFFI_LIB_FILE="${LIBFFI_LIB_PATH}/libffi.so.?"
175+
if test -e ${LIBFFI_LIB_PATH}/${LIBFFI_LIB_FILE_NAME}; then
176+
LIBFFI_LIB_FILE="${LIBFFI_LIB_PATH}/${LIBFFI_LIB_FILE_NAME}"
139177
else
140-
AC_MSG_ERROR([Could not locate libffi.so.? for bundling in ${LIBFFI_LIB_PATH}])
178+
AC_MSG_ERROR([Could not locate ${LIBFFI_LIB_FILE_NAME} for bundling in ${LIBFFI_LIB_PATH}])
141179
fi
142180
else
143181
# If we don't have an explicit path, look in a few obvious places
144182
if test "x${OPENJDK_TARGET_CPU}" = "xx86"; then
145-
if test -e ${SYSROOT}/usr/lib/libffi.so.? ; then
146-
LIBFFI_LIB_FILE="${SYSROOT}/usr/lib/libffi.so.?"
147-
elif test -e ${SYSROOT}/usr/lib/i386-linux-gnu/libffi.so.? ; then
148-
LIBFFI_LIB_FILE="${SYSROOT}/usr/lib/i386-linux-gnu/libffi.so.?"
183+
if test -e ${SYSROOT}/usr/lib/${LIBFFI_LIB_FILE_NAME} ; then
184+
LIBFFI_LIB_FILE="${SYSROOT}/usr/lib/${LIBFFI_LIB_FILE_NAME}"
185+
elif test -e ${SYSROOT}/usr/lib/i386-linux-gnu/${LIBFFI_LIB_FILE_NAME} ; then
186+
LIBFFI_LIB_FILE="${SYSROOT}/usr/lib/i386-linux-gnu/${LIBFFI_LIB_FILE_NAME}"
149187
else
150-
AC_MSG_ERROR([Could not locate libffi.so.? for bundling])
188+
AC_MSG_ERROR([Could not locate ${LIBFFI_LIB_FILE_NAME} for bundling])
151189
fi
152190
elif test "x${OPENJDK_TARGET_CPU}" = "xx86_64" || test "x${OPENJDK_TARGET_CPU}" = "xaarch64"; then
153-
if test -e ${SYSROOT}/usr/lib64/libffi.so.? ; then
154-
LIBFFI_LIB_FILE="${SYSROOT}/usr/lib64/libffi.so.?"
155-
elif test -e ${SYSROOT}/usr/lib/x86_64-linux-gnu/libffi.so.? ; then
156-
LIBFFI_LIB_FILE="${SYSROOT}/usr/lib/x86_64-linux-gnu/libffi.so.?"
191+
if test -e ${SYSROOT}/usr/lib64/${LIBFFI_LIB_FILE_NAME} ; then
192+
LIBFFI_LIB_FILE="${SYSROOT}/usr/lib64/${LIBFFI_LIB_FILE_NAME}"
193+
elif test -e ${SYSROOT}/usr/lib/x86_64-linux-gnu/${LIBFFI_LIB_FILE_NAME} ; then
194+
LIBFFI_LIB_FILE="${SYSROOT}/usr/lib/x86_64-linux-gnu/${LIBFFI_LIB_FILE_NAME}"
157195
else
158-
AC_MSG_ERROR([Could not locate libffi.so.? for bundling])
196+
AC_MSG_ERROR([Could not locate ${LIBFFI_LIB_FILE_NAME} for bundling])
159197
fi
160198
else
161199
# Fallback on the default /usr/lib dir
162-
if test -e ${SYSROOT}/usr/lib/libffi.so.? ; then
163-
LIBFFI_LIB_FILE="${SYSROOT}/usr/lib/libffi.so.?"
200+
if test -e ${SYSROOT}/usr/lib/${LIBFFI_LIB_FILE_NAME} ; then
201+
LIBFFI_LIB_FILE="${SYSROOT}/usr/lib/${LIBFFI_LIB_FILE_NAME}"
164202
else
165-
AC_MSG_ERROR([Could not locate libffi.so.? for bundling])
203+
AC_MSG_ERROR([Could not locate ${LIBFFI_LIB_FILE_NAME} for bundling])
166204
fi
167205
fi
168206
fi

make/devkit/createLibffiBundle.sh

Lines changed: 61 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,38 @@
3838
# Note that the libtool and texinfo packages are needed to build libffi
3939
# $ sudo apt install libtool texinfo
4040

41+
# Note that while the build system supports linking against libffi on Windows (x64),
42+
# I couldn't get this script working with a Windows devkit, and instead had to manually create
43+
# a libffi bundle for Windows. The steps I took were as follows:
44+
#
45+
# 1. run 'x64 Native Tools Command Prompt for VS 2022'. After that, cl.exe and link.exe should be on path
46+
#
47+
# 2. in the same shell, run `ucrt64` (this is one of the shell environments that comes with MSYS2).
48+
# This should carry over the environment set up by the VS dev prompt into the ucrt64 prompt.
49+
#
50+
# 3. then, in the libffi repo root folder:
51+
# 3.a run `autogen.sh`
52+
# 3.b run:
53+
# ```
54+
# bash configure \
55+
# CC="/path/to/libffi/msvcc.sh -m64" \
56+
# CXX="/path/to/libffi/msvcc.sh -m64" \
57+
# CPPFLAGS="-DFFI_BUILDING_DLL" \
58+
# --disable-docs \
59+
# --prefix=<install dest>
60+
# ```
61+
# (`<install dest>` can be whatever you like. That's what you point `--with-libffi` to).
62+
#
63+
# 4. run `make install`. This should create the `<install dest>` directory with the files:
64+
# `include/ffi.h`, `include/ffitarget.h`, `lib/libffi.dll`. It also creates a `lib/libffi.lib` file,
65+
# but it is of the wrong file type, `DLL` rather than `LIBRARY`.
66+
#
67+
# 5. Manually create a working `.lib` file (in the <install dest>/lib dir):
68+
# 5.a use `dumpbin /exports libffi.dll` to get a list of exported symbols
69+
# 5.b put them in a `libffi.def` file: `EXPORTS` on the first line, then a symbol on each line following
70+
# 5.c run `lib /def:libffi.def /machine:x64 /out:libffi.lib` to create the right `.lib` file (`lib` is a visual studio tool)
71+
#
72+
4173
LIBFFI_VERSION=3.4.2
4274

4375
BUNDLE_NAME=libffi-$LIBFFI_VERSION.tar.gz
@@ -49,6 +81,7 @@ SRC_DIR="$OUTPUT_DIR/src"
4981
DOWNLOAD_DIR="$OUTPUT_DIR/download"
5082
INSTALL_DIR="$OUTPUT_DIR/install"
5183
IMAGE_DIR="$OUTPUT_DIR/image"
84+
OS_NAME=$(uname -s)
5285

5386
USAGE="$0 <devkit dir>"
5487

@@ -81,19 +114,43 @@ cd $LIBFFI_DIR
81114
if [ ! -e $LIBFFI_DIR/configure ]; then
82115
bash ./autogen.sh
83116
fi
117+
118+
case $OS_NAME in
119+
Linux)
120+
CC=$DEVKIT_DIR/bin/gcc
121+
CXX=$DEVKIT_DIR/bin/g++
122+
# For Linux/x86 it's under /lib/ instead of /lib64/
123+
LIB_FOLDER=lib64
124+
LIB_NAME=libffi.so*
125+
;;
126+
Darwin)
127+
CC=$DEVKIT_DIR/Xcode/Contents/Developer/usr/bin/gcc
128+
CXX=$DEVKIT_DIR/Xcode/Contents/Developer/usr/bin/gcc
129+
LIB_FOLDER=lib
130+
LIB_NAME=libffi.*.dylib
131+
;;
132+
*)
133+
echo " Unsupported OS: $OS_NAME"
134+
exit 1
135+
;;
136+
esac
137+
84138
# For Linux/x86, add --build=i686-pc-linux-gnu CFLAGS=-m32 CXXFLAGS=-m32 LDFLAGS=-m32
85-
bash ./configure --prefix=$INSTALL_DIR CC=$DEVKIT_DIR/bin/gcc CXX=$DEVKIT_DIR/bin/g++
139+
bash ./configure \
140+
--disable-docs \
141+
--prefix=$INSTALL_DIR \
142+
CC=$CC \
143+
CXX=$CXX
86144

87145
# Run with nice to keep system usable during build.
88146
nice make $MAKE_ARGS install
89147

90148
mkdir -p $IMAGE_DIR
91149
# Extract what we need into an image
92150
if [ ! -e $IMAGE_DIR/lib/libffi.so ]; then
93-
echo "Copying libffi.so* to image"
151+
echo "Copying ${LIB_NAME} to image"
94152
mkdir -p $IMAGE_DIR/lib
95-
# For Linux/x86 it's under /lib/ instead of /lib64/
96-
cp -a $INSTALL_DIR/lib64/libffi.so* $IMAGE_DIR/lib/
153+
cp -a $INSTALL_DIR/${LIB_FOLDER}/${LIB_NAME} $IMAGE_DIR/lib/
97154
fi
98155
if [ ! -e $IMAGE_DIR/include/ ]; then
99156
echo "Copying include to image"

make/modules/java.base/Lib.gmk

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,7 @@ ifeq ($(ENABLE_FALLBACK_LINKER), true)
228228
LDFLAGS := $(LDFLAGS_JDKLIB) \
229229
$(call SET_SHARED_LIBRARY_ORIGIN), \
230230
LIBS := $(LIBFFI_LIBS), \
231+
LIBS_windows := $(LIBFFI_LIBS) ws2_32.lib, \
231232
))
232233

233234
TARGETS += $(BUILD_LIBFALLBACKLINKER)

src/hotspot/cpu/zero/globalDefinitions_zero.hpp

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,6 @@
3232

3333
#define SUPPORT_MONITOR_COUNT
3434

35-
#ifdef __APPLE__
36-
#define FFI_GO_CLOSURES 0
37-
#endif
38-
3935
#include <ffi.h>
4036

4137
// Indicates whether the C calling conventions require that

src/java.base/share/native/libfallbackLinker/fallbackLinker.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include <ffi.h>
2929

3030
#include <errno.h>
31+
#include <stdint.h>
3132
#ifdef _WIN64
3233
#include <Windows.h>
3334
#include <Winsock2.h>

test/jdk/java/foreign/TestUpcallStack.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
* @test
2626
* @enablePreview
2727
* @requires jdk.foreign.linker != "UNSUPPORTED"
28+
* @requires (!(os.name == "Mac OS X" & os.arch == "aarch64") | jdk.foreign.linker != "FALLBACK")
2829
* @modules java.base/jdk.internal.foreign
2930
* @build NativeTestHelper CallGeneratorHelper TestUpcallBase
3031
*

test/jdk/java/foreign/arraystructs/TestArrayStructs.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
* @enablePreview
2727
* @library ../
2828
* @requires jdk.foreign.linker != "UNSUPPORTED"
29+
* @requires (!(os.name == "Mac OS X" & os.arch == "aarch64") | jdk.foreign.linker != "FALLBACK")
2930
* @modules java.base/jdk.internal.foreign
3031
* @run testng/othervm
3132
* --enable-native-access=ALL-UNNAMED
@@ -39,6 +40,7 @@
3940
* @enablePreview
4041
* @library ../
4142
* @requires jdk.foreign.linker != "UNSUPPORTED"
43+
* @requires (!(os.name == "Mac OS X" & os.arch == "aarch64") | jdk.foreign.linker != "FALLBACK")
4244
* @modules java.base/jdk.internal.foreign
4345
* @run testng/othervm
4446
* --enable-native-access=ALL-UNNAMED

0 commit comments

Comments
 (0)