From 4c18b9e1faba32bd54a5d8b0b3c21b07f694c71b Mon Sep 17 00:00:00 2001 From: Jorn Vernee Date: Wed, 14 Jun 2023 12:03:42 +0000 Subject: [PATCH] 8309880: Add support for linking libffi on Windows and Mac Co-authored-by: Aleksey Shipilev Co-authored-by: Jorn Vernee Reviewed-by: erikj --- make/autoconf/lib-ffi.m4 | 82 ++++++++++++++----- make/devkit/createLibffiBundle.sh | 65 ++++++++++++++- make/modules/java.base/Lib.gmk | 1 + .../cpu/zero/globalDefinitions_zero.hpp | 4 - .../native/libfallbackLinker/fallbackLinker.c | 1 + test/jdk/java/foreign/TestUpcallStack.java | 1 + .../arraystructs/TestArrayStructs.java | 2 + 7 files changed, 126 insertions(+), 30 deletions(-) diff --git a/make/autoconf/lib-ffi.m4 b/make/autoconf/lib-ffi.m4 index 0905c3cd225..3a11bec4a97 100644 --- a/make/autoconf/lib-ffi.m4 +++ b/make/autoconf/lib-ffi.m4 @@ -57,7 +57,11 @@ AC_DEFUN_ONCE([LIB_SETUP_LIBFFI], if test "x${with_libffi}" != x; then LIBFFI_LIB_PATH="${with_libffi}/lib" - LIBFFI_LIBS="-L${with_libffi}/lib -lffi" + if test "x${OPENJDK_TARGET_OS}" != "xwindows"; then + LIBFFI_LIBS="-L${with_libffi}/lib -lffi" + else + LIBFFI_LIBS="${with_libffi}/lib/libffi.lib" + fi LIBFFI_CFLAGS="-I${with_libffi}/include" LIBFFI_FOUND=yes fi @@ -67,7 +71,11 @@ AC_DEFUN_ONCE([LIB_SETUP_LIBFFI], fi if test "x${with_libffi_lib}" != x; then LIBFFI_LIB_PATH="${with_libffi_lib}" - LIBFFI_LIBS="-L${with_libffi_lib} -lffi" + if test "x${OPENJDK_TARGET_OS}" != "xwindows"; then + LIBFFI_LIBS="-L${with_libffi_lib} -lffi" + else + LIBFFI_LIBS="${with_libffi_lib}/libffi.lib" + fi LIBFFI_FOUND=yes fi # Do not try pkg-config if we have a sysroot set. @@ -106,12 +114,13 @@ AC_DEFUN_ONCE([LIB_SETUP_LIBFFI], AC_MSG_ERROR([Could not find libffi! $HELP_MSG]) fi - AC_MSG_CHECKING([if libffi works]) AC_LANG_PUSH(C) OLD_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $LIBFFI_CFLAGS" OLD_LIBS="$LIBS" LIBS="$LIBS $LIBFFI_LIBS" + + AC_MSG_CHECKING([if libffi works]) AC_LINK_IFELSE([AC_LANG_PROGRAM([#include ], [ ffi_call(NULL, NULL, NULL, NULL); @@ -120,9 +129,6 @@ AC_DEFUN_ONCE([LIB_SETUP_LIBFFI], [LIBFFI_WORKS=yes], [LIBFFI_WORKS=no] ) - CFLAGS="$OLD_CFLAGS" - LIBS="$OLD_LIBS" - AC_LANG_POP(C) AC_MSG_RESULT([$LIBFFI_WORKS]) if test "x$LIBFFI_WORKS" = xno; then @@ -130,39 +136,71 @@ AC_DEFUN_ONCE([LIB_SETUP_LIBFFI], AC_MSG_ERROR([Found libffi but could not link and compile with it. $HELP_MSG]) fi + # Check if FFI_GO_CLOSURES is properly defined. On some distributions, notably MacOS AArch64, + # ffitarget.h (included from ffi.h) does not explicitly define FFI_GO_CLOSURES. This makes the + # further include of ffi.h trigger the "FFI_GO_CLOSURES is undefined" warning, which fails + # the build when warnings are fatal. + AC_MSG_CHECKING([for FFI_GO_CLOSURES definition]) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([ + #include + #ifndef FFI_GO_CLOSURES + #error "FFI_GO_CLOSURES is not defined" + #endif + ][])], + [ + AC_MSG_RESULT([yes]) + ], + [ + AC_MSG_RESULT([no, defining]) + LIBFFI_CFLAGS="$LIBFFI_CFLAGS -DFFI_GO_CLOSURES=0" + ] + ) + + CFLAGS="$OLD_CFLAGS" + LIBS="$OLD_LIBS" + AC_LANG_POP(C) + # Find the libffi.so.X to bundle if test "x${ENABLE_LIBFFI_BUNDLING}" = "xtrue"; then + if test "x${OPENJDK_TARGET_OS}" = "xmacosx"; then + LIBFFI_LIB_FILE_NAME=libffi.?.dylib + elif test "x${OPENJDK_TARGET_OS}" = "xwindows"; then + LIBFFI_LIB_FILE_NAME=libffi.dll + else + LIBFFI_LIB_FILE_NAME=libffi.so.? + fi + AC_MSG_CHECKING([for libffi lib file location]) if test "x${LIBFFI_LIB_PATH}" != x; then - if test -e ${LIBFFI_LIB_PATH}/libffi.so.?; then - LIBFFI_LIB_FILE="${LIBFFI_LIB_PATH}/libffi.so.?" + if test -e ${LIBFFI_LIB_PATH}/${LIBFFI_LIB_FILE_NAME}; then + LIBFFI_LIB_FILE="${LIBFFI_LIB_PATH}/${LIBFFI_LIB_FILE_NAME}" else - AC_MSG_ERROR([Could not locate libffi.so.? for bundling in ${LIBFFI_LIB_PATH}]) + AC_MSG_ERROR([Could not locate ${LIBFFI_LIB_FILE_NAME} for bundling in ${LIBFFI_LIB_PATH}]) fi else # If we don't have an explicit path, look in a few obvious places if test "x${OPENJDK_TARGET_CPU}" = "xx86"; then - if test -e ${SYSROOT}/usr/lib/libffi.so.? ; then - LIBFFI_LIB_FILE="${SYSROOT}/usr/lib/libffi.so.?" - elif test -e ${SYSROOT}/usr/lib/i386-linux-gnu/libffi.so.? ; then - LIBFFI_LIB_FILE="${SYSROOT}/usr/lib/i386-linux-gnu/libffi.so.?" + if test -e ${SYSROOT}/usr/lib/${LIBFFI_LIB_FILE_NAME} ; then + LIBFFI_LIB_FILE="${SYSROOT}/usr/lib/${LIBFFI_LIB_FILE_NAME}" + elif test -e ${SYSROOT}/usr/lib/i386-linux-gnu/${LIBFFI_LIB_FILE_NAME} ; then + LIBFFI_LIB_FILE="${SYSROOT}/usr/lib/i386-linux-gnu/${LIBFFI_LIB_FILE_NAME}" else - AC_MSG_ERROR([Could not locate libffi.so.? for bundling]) + AC_MSG_ERROR([Could not locate ${LIBFFI_LIB_FILE_NAME} for bundling]) fi elif test "x${OPENJDK_TARGET_CPU}" = "xx86_64" || test "x${OPENJDK_TARGET_CPU}" = "xaarch64"; then - if test -e ${SYSROOT}/usr/lib64/libffi.so.? ; then - LIBFFI_LIB_FILE="${SYSROOT}/usr/lib64/libffi.so.?" - elif test -e ${SYSROOT}/usr/lib/x86_64-linux-gnu/libffi.so.? ; then - LIBFFI_LIB_FILE="${SYSROOT}/usr/lib/x86_64-linux-gnu/libffi.so.?" + if test -e ${SYSROOT}/usr/lib64/${LIBFFI_LIB_FILE_NAME} ; then + LIBFFI_LIB_FILE="${SYSROOT}/usr/lib64/${LIBFFI_LIB_FILE_NAME}" + elif test -e ${SYSROOT}/usr/lib/x86_64-linux-gnu/${LIBFFI_LIB_FILE_NAME} ; then + LIBFFI_LIB_FILE="${SYSROOT}/usr/lib/x86_64-linux-gnu/${LIBFFI_LIB_FILE_NAME}" else - AC_MSG_ERROR([Could not locate libffi.so.? for bundling]) + AC_MSG_ERROR([Could not locate ${LIBFFI_LIB_FILE_NAME} for bundling]) fi else # Fallback on the default /usr/lib dir - if test -e ${SYSROOT}/usr/lib/libffi.so.? ; then - LIBFFI_LIB_FILE="${SYSROOT}/usr/lib/libffi.so.?" + if test -e ${SYSROOT}/usr/lib/${LIBFFI_LIB_FILE_NAME} ; then + LIBFFI_LIB_FILE="${SYSROOT}/usr/lib/${LIBFFI_LIB_FILE_NAME}" else - AC_MSG_ERROR([Could not locate libffi.so.? for bundling]) + AC_MSG_ERROR([Could not locate ${LIBFFI_LIB_FILE_NAME} for bundling]) fi fi fi diff --git a/make/devkit/createLibffiBundle.sh b/make/devkit/createLibffiBundle.sh index 100dcc1fe0d..4bf1f12fb2f 100644 --- a/make/devkit/createLibffiBundle.sh +++ b/make/devkit/createLibffiBundle.sh @@ -38,6 +38,38 @@ # Note that the libtool and texinfo packages are needed to build libffi # $ sudo apt install libtool texinfo +# Note that while the build system supports linking against libffi on Windows (x64), +# I couldn't get this script working with a Windows devkit, and instead had to manually create +# a libffi bundle for Windows. The steps I took were as follows: +# +# 1. run 'x64 Native Tools Command Prompt for VS 2022'. After that, cl.exe and link.exe should be on path +# +# 2. in the same shell, run `ucrt64` (this is one of the shell environments that comes with MSYS2). +# This should carry over the environment set up by the VS dev prompt into the ucrt64 prompt. +# +# 3. then, in the libffi repo root folder: +# 3.a run `autogen.sh` +# 3.b run: +# ``` +# bash configure \ +# CC="/path/to/libffi/msvcc.sh -m64" \ +# CXX="/path/to/libffi/msvcc.sh -m64" \ +# CPPFLAGS="-DFFI_BUILDING_DLL" \ +# --disable-docs \ +# --prefix= +# ``` +# (`` can be whatever you like. That's what you point `--with-libffi` to). +# +# 4. run `make install`. This should create the `` directory with the files: +# `include/ffi.h`, `include/ffitarget.h`, `lib/libffi.dll`. It also creates a `lib/libffi.lib` file, +# but it is of the wrong file type, `DLL` rather than `LIBRARY`. +# +# 5. Manually create a working `.lib` file (in the /lib dir): +# 5.a use `dumpbin /exports libffi.dll` to get a list of exported symbols +# 5.b put them in a `libffi.def` file: `EXPORTS` on the first line, then a symbol on each line following +# 5.c run `lib /def:libffi.def /machine:x64 /out:libffi.lib` to create the right `.lib` file (`lib` is a visual studio tool) +# + LIBFFI_VERSION=3.4.2 BUNDLE_NAME=libffi-$LIBFFI_VERSION.tar.gz @@ -49,6 +81,7 @@ SRC_DIR="$OUTPUT_DIR/src" DOWNLOAD_DIR="$OUTPUT_DIR/download" INSTALL_DIR="$OUTPUT_DIR/install" IMAGE_DIR="$OUTPUT_DIR/image" +OS_NAME=$(uname -s) USAGE="$0 " @@ -81,8 +114,33 @@ cd $LIBFFI_DIR if [ ! -e $LIBFFI_DIR/configure ]; then bash ./autogen.sh fi + +case $OS_NAME in + Linux) + CC=$DEVKIT_DIR/bin/gcc + CXX=$DEVKIT_DIR/bin/g++ + # For Linux/x86 it's under /lib/ instead of /lib64/ + LIB_FOLDER=lib64 + LIB_NAME=libffi.so* + ;; + Darwin) + CC=$DEVKIT_DIR/Xcode/Contents/Developer/usr/bin/gcc + CXX=$DEVKIT_DIR/Xcode/Contents/Developer/usr/bin/gcc + LIB_FOLDER=lib + LIB_NAME=libffi.*.dylib + ;; + *) + echo " Unsupported OS: $OS_NAME" + exit 1 + ;; +esac + # For Linux/x86, add --build=i686-pc-linux-gnu CFLAGS=-m32 CXXFLAGS=-m32 LDFLAGS=-m32 -bash ./configure --prefix=$INSTALL_DIR CC=$DEVKIT_DIR/bin/gcc CXX=$DEVKIT_DIR/bin/g++ +bash ./configure \ + --disable-docs \ + --prefix=$INSTALL_DIR \ + CC=$CC \ + CXX=$CXX # Run with nice to keep system usable during build. nice make $MAKE_ARGS install @@ -90,10 +148,9 @@ nice make $MAKE_ARGS install mkdir -p $IMAGE_DIR # Extract what we need into an image if [ ! -e $IMAGE_DIR/lib/libffi.so ]; then - echo "Copying libffi.so* to image" + echo "Copying ${LIB_NAME} to image" mkdir -p $IMAGE_DIR/lib - # For Linux/x86 it's under /lib/ instead of /lib64/ - cp -a $INSTALL_DIR/lib64/libffi.so* $IMAGE_DIR/lib/ + cp -a $INSTALL_DIR/${LIB_FOLDER}/${LIB_NAME} $IMAGE_DIR/lib/ fi if [ ! -e $IMAGE_DIR/include/ ]; then echo "Copying include to image" diff --git a/make/modules/java.base/Lib.gmk b/make/modules/java.base/Lib.gmk index 1e0f66726d0..728773b1ccc 100644 --- a/make/modules/java.base/Lib.gmk +++ b/make/modules/java.base/Lib.gmk @@ -228,6 +228,7 @@ ifeq ($(ENABLE_FALLBACK_LINKER), true) LDFLAGS := $(LDFLAGS_JDKLIB) \ $(call SET_SHARED_LIBRARY_ORIGIN), \ LIBS := $(LIBFFI_LIBS), \ + LIBS_windows := $(LIBFFI_LIBS) ws2_32.lib, \ )) TARGETS += $(BUILD_LIBFALLBACKLINKER) diff --git a/src/hotspot/cpu/zero/globalDefinitions_zero.hpp b/src/hotspot/cpu/zero/globalDefinitions_zero.hpp index b8f01f40454..33d3867d69e 100644 --- a/src/hotspot/cpu/zero/globalDefinitions_zero.hpp +++ b/src/hotspot/cpu/zero/globalDefinitions_zero.hpp @@ -32,10 +32,6 @@ #define SUPPORT_MONITOR_COUNT -#ifdef __APPLE__ -#define FFI_GO_CLOSURES 0 -#endif - #include // Indicates whether the C calling conventions require that diff --git a/src/java.base/share/native/libfallbackLinker/fallbackLinker.c b/src/java.base/share/native/libfallbackLinker/fallbackLinker.c index 7f554d49737..9b3d88dcc0c 100644 --- a/src/java.base/share/native/libfallbackLinker/fallbackLinker.c +++ b/src/java.base/share/native/libfallbackLinker/fallbackLinker.c @@ -28,6 +28,7 @@ #include #include +#include #ifdef _WIN64 #include #include diff --git a/test/jdk/java/foreign/TestUpcallStack.java b/test/jdk/java/foreign/TestUpcallStack.java index cea15bd9d8c..99bb4647466 100644 --- a/test/jdk/java/foreign/TestUpcallStack.java +++ b/test/jdk/java/foreign/TestUpcallStack.java @@ -25,6 +25,7 @@ * @test * @enablePreview * @requires jdk.foreign.linker != "UNSUPPORTED" + * @requires (!(os.name == "Mac OS X" & os.arch == "aarch64") | jdk.foreign.linker != "FALLBACK") * @modules java.base/jdk.internal.foreign * @build NativeTestHelper CallGeneratorHelper TestUpcallBase * diff --git a/test/jdk/java/foreign/arraystructs/TestArrayStructs.java b/test/jdk/java/foreign/arraystructs/TestArrayStructs.java index 6f6abdbdb4a..997de3f99de 100644 --- a/test/jdk/java/foreign/arraystructs/TestArrayStructs.java +++ b/test/jdk/java/foreign/arraystructs/TestArrayStructs.java @@ -26,6 +26,7 @@ * @enablePreview * @library ../ * @requires jdk.foreign.linker != "UNSUPPORTED" + * @requires (!(os.name == "Mac OS X" & os.arch == "aarch64") | jdk.foreign.linker != "FALLBACK") * @modules java.base/jdk.internal.foreign * @run testng/othervm * --enable-native-access=ALL-UNNAMED @@ -39,6 +40,7 @@ * @enablePreview * @library ../ * @requires jdk.foreign.linker != "UNSUPPORTED" + * @requires (!(os.name == "Mac OS X" & os.arch == "aarch64") | jdk.foreign.linker != "FALLBACK") * @modules java.base/jdk.internal.foreign * @run testng/othervm * --enable-native-access=ALL-UNNAMED