Skip to content

Commit

Permalink
Enable building JNA for Darwin arm64
Browse files Browse the repository at this point in the history
- Big Sur uses a shared dylib cache to lookup system libraries and frameworks. Checking existence in the file system will fail, but loading them will succeed nevertheless.
- Arm64 calling convention requires varargs to always be passed on the stack. JNA's and ffi's argument handling logic seems to handle this case correctly, but it is important that the Java definitions match their native counterparts exactly.
  • Loading branch information
fkistner committed Jul 21, 2020
1 parent 3d9b024 commit 32c8915
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 12 deletions.
33 changes: 29 additions & 4 deletions native/Makefile
Expand Up @@ -99,8 +99,18 @@ CFLAGS=$(PCFLAGS) $(CFLAGS_EXTRA) $(COPT) $(CDEBUG) $(CDEFINES) $(CINCLUDES) \
-DJNA_JNI_VERSION='"$(JNA_JNI_VERSION)"' -DCHECKSUM='"$(CHECKSUM)"'
LDFLAGS=-o $@ -shared
ifeq ($(DYNAMIC_LIBFFI),true)
ifeq ($(OS),darwin)
ifeq ($(DARWIN_USE_SDK_LIBFFI),true)
CFLAGS += -I$(SDKROOT)/usr/include/ffi
LIBS += -L$(SDKROOT)/usr/lib -lffi
else
CFLAGS += $(shell pkg-config --cflags libffi 2>/dev/null || echo)
LIBS += $(shell pkg-config --libs libffi 2>/dev/null || echo -lffi)
endif
else
CFLAGS += $(shell pkg-config --cflags libffi 2>/dev/null || echo)
LIBS += $(shell pkg-config --libs libffi 2>/dev/null || echo -lffi)
endif
else
# -static-libgcc avoids gcc library incompatibilities across linux systems
LDFLAGS += -static-libgcc
Expand Down Expand Up @@ -373,19 +383,26 @@ endif


ifeq ($(OS),darwin)
XCODE_VERSION=$(shell xcodebuild -version | grep Xcode | sed 's/^Xcode \([1-9]\).*/\1/g')
XCODE_VERSION=$(shell xcodebuild -version | grep Xcode | sed 's/^Xcode \([1-9][0-9]*\).*/\1/g')
JAVA_INCLUDES+=-I/System/Library/Frameworks/JavaVM.framework/Headers
DEFAULT_ARCH=$(shell arch)
ARCH=$(shell arch)
HOST_CONFIG=--host $(ARCH)-apple-darwin
FFI_ENV += CC="$(CC)" CFLAGS="-arch $(ARCH) $(ISYSROOT) $(COPT) $(CDEBUG)" CPPFLAGS="$(CDEFINES)" LD="$(LD) -arch $(ARCH)"
ALT_ARCHS=
ifneq ($(ARCH),i386)
ifeq ($(shell echo "int main(void) { return 0; }" | $(CC) $(LOC_CC_OPTS) -arch i386 $(CFLAGS) -x c - -o /dev/null &>/dev/null; echo $$?),0)
ALT_ARCHS+=i386
endif
endif
ifneq ($(ARCH),x86_64)
ALT_ARCHS+=x86_64
endif
ifneq ($(ARCH),arm64)
ifeq ($(shell echo "int main(void) { return 0; }" | $(CC) $(LOC_CC_OPTS) -arch arm64 $(CFLAGS) -x c - -o /dev/null &>/dev/null; echo $$?),0)
ALT_ARCHS+=arm64
endif
endif
ifneq ($(ARCH),ppc)
ifeq ($(XCODE_VERSION),3)
# Xcode 3 options
Expand All @@ -401,7 +418,13 @@ JNISFX=.jnilib
ifneq ($(SDKROOT),)
SYSLIBROOT=-Wl,-syslibroot,$(SDKROOT)
ISYSROOT=-isysroot $(SDKROOT)
ARCHFLAGS=-arch i386 -arch x86_64
ARCHFLAGS=-arch x86_64
ifeq ($(shell echo "int main(void) { return 0; }" | $(CC) $(LOC_CC_OPTS) -arch i386 $(CFLAGS) -x c - -o /dev/null &>/dev/null; echo $$?),0)
ARCHFLAGS+=-arch i386
endif
ifeq ($(shell echo "int main(void) { return 0; }" | $(CC) $(LOC_CC_OPTS) -arch arm64 $(CFLAGS) -x c - -o /dev/null &>/dev/null; echo $$?),0)
ARCHFLAGS+=-arch arm64
endif
ifeq ($(XCODE_VERSION),3)
ARCHFLAGS+=-arch ppc
endif
Expand All @@ -410,16 +433,18 @@ endif
PCFLAGS+=$(ISYSROOT) -x objective-c
# JAWT no longer supported on OSX
CDEFINES+=-DTARGET_RT_MAC_CFM=0 -DFFI_MMAP_EXEC_WRIT -DNO_JAWT
LDFLAGS=$(ARCHFLAGS) -dynamiclib -o $@ -framework JavaVM \
LDFLAGS=$(ARCHFLAGS) -dynamiclib -o $@ \
-compatibility_version $(shell echo ${JNA_JNI_VERSION}|sed 's/^\([0-9][0-9]*\).*/\1/g') \
-current_version $(JNA_JNI_VERSION) \
-mmacosx-version-min=10.3 \
-framework Foundation \
$(NO_COMPACT_UNWIND) \
-install_name ${@F} \
$(SYSLIBROOT)
ifeq ($(shell test $(XCODE_VERSION) -lt 12; echo $$?),0)
# JAWT linkage handled by -framework JavaVM
LIBS=
LIBS+=-framework JavaVM
endif
endif

# Unfortunately, we have to use different libffi include files depending on
Expand Down
16 changes: 10 additions & 6 deletions test/com/sun/jna/LibraryLoadTest.java
Expand Up @@ -203,13 +203,12 @@ public void testLoadLibraryWithLongName() throws Exception {
public void testLoadFrameworkLibrary() {
if (Platform.isMac()) {
final String PATH = "/System/Library/Frameworks/CoreServices.framework";
assertTrue("CoreServices not present on this setup, expected at " + PATH, new File(PATH).exists());
try {
NativeLibrary lib = NativeLibrary.getInstance("CoreServices");
assertNotNull("CoreServices not found", lib);
}
catch(UnsatisfiedLinkError e) {
fail("Should search /System/Library/Frameworks");
failCoreServices("Should search /System/Library/Frameworks: ", e, PATH);
}
}
}
Expand All @@ -218,31 +217,36 @@ public void testLoadFrameworkLibraryAbsolute() {
if (Platform.isMac()) {
final String PATH = "/System/Library/Frameworks/CoreServices";
final String FRAMEWORK = PATH + ".framework";
assertTrue("CoreServices not present on this setup, expected at " + FRAMEWORK, new File(FRAMEWORK).exists());
try {
NativeLibrary lib = NativeLibrary.getInstance(PATH);
assertNotNull("CoreServices not found", lib);
}
catch(UnsatisfiedLinkError e) {
fail("Should try FRAMEWORK.framework/FRAMEWORK if the absolute framework (truncated) path given exists: " + e);
failCoreServices("Should try FRAMEWORK.framework/FRAMEWORK if the absolute framework (truncated) path given exists: ", e, FRAMEWORK);
}
}
}

public void testLoadFrameworkLibraryAbsoluteFull() {
if (Platform.isMac()) {
final String PATH = "/System/Library/Frameworks/CoreServices.framework/CoreServices";
assertTrue("CoreServices not present on this setup, expected at " + PATH, new File(PATH).exists());
try {
NativeLibrary lib = NativeLibrary.getInstance(PATH);
assertNotNull("CoreServices not found", lib);
}
catch(UnsatisfiedLinkError e) {
fail("Should try FRAMEWORK verbatim if the absolute path given exists: " + e);
failCoreServices("Should try FRAMEWORK verbatim if the absolute path given exists: ", e, PATH);
}
}
}

private void failCoreServices(String message, UnsatisfiedLinkError e, String expectedPath) {
if (!new File(expectedPath).exists()) {
message = "CoreServices not present on this setup, expected at " + expectedPath + "\n" + message;
}
fail(message + e);
}

public void testHandleObjectMethods() {
CLibrary lib = (CLibrary)load();
String method = "toString";
Expand Down
4 changes: 2 additions & 2 deletions test/com/sun/jna/VarArgsTest.java
Expand Up @@ -42,8 +42,8 @@ protected List<String> getFieldOrder() {
}
public int addVarArgs(String fmt, Number... args);
public String returnStringVarArgs(String fmt, Object... args);
public void modifyStructureVarArgs(String fmt, Object arg1, Object... args);
public String returnStringVarArgs2(String... args);
public void modifyStructureVarArgs(String fmt, Object... args);
public String returnStringVarArgs2(String fmt, String... args);
}
TestLibrary lib;
@Override
Expand Down

0 comments on commit 32c8915

Please sign in to comment.