# # Makefile for JNA native bits # Copyright (c) 2007-2014 Timothy Wall All Rights Reserved # # You may need to run 'ant javah' at the root before performing a build from # this directory. # # To build with debug information, use 'make DEBUG=true' # # Supported platforms (built and tested): # # Windows (x86/amd64/aarch64) # Windows CE/Mobile (arm) # Darwin/OS X (i386/x86-64/ppc/aarch64) # Linux (i386/amd64/ppc/arm) # Solaris (i386/amd64/sparc/sparcv9) # AIX (ppc/ppc64) # DragonFly (x86-64) # FreeBSD (i386/amd64/aarch64) # OpenBSD/NetBSD (i386/amd64) # Android (arm/armv7/aarch64/x86/x86-64/mipsel/mips64el) # # Built, but with outstanding bugs (not necessarily within JNA): # # Linux (ppc64/ppc64le/ia64) # # The w32ce build requires cegcc and phoneME for cross-compilation; if these # tools are available on the path then "ant -Dos.prefix=w32ce-arm" should # result in a proper build. # # The android build requires the android SDK+NDK for cross-compilation; # make the tools available on the path and compile with # "ant -Dos.prefix=android-{arm|x86}". Put the NDK tools in the path and adjust # NDK_PLATFORM below or set it in your environment. # # The windows build requires a cygwin installation. The build will use MSVC # for compilation if cl.exe is found on the PATH, otherwise the build will fall # back to mingw. # Systems which support POSIX signals may be able to support VM crash # protection simply by defining HAVE_PROTECTION. This option has been only # been enabled for those platforms on which it has been tested successfully. OS=$(shell uname | sed -e 's/CYGWIN.*/win32/g' \ -e 's/MINGW32.*/win32/g' \ -e 's/SunOS.*/solaris/g' \ -e 's/NetBSD/netbsd/g' \ -e 's/GNU\/kFreeBSD/kfreebsd/g' \ -e 's/FreeBSD/freebsd/g' \ -e 's/DragonFly/dragonfly/g' \ -e 's/OpenBSD/openbsd/g' \ -e 's/Darwin.*/darwin/g' \ -e 's/AIX.*/aix/g' \ -e 's/Linux.*/linux/g') JNA_JNI_VERSION=5.1.0 # auto-generated by ant CHECKSUM=74e8f8e397c43487738c5c1f1363498b # auto-generated by ant JAVA_INCLUDES=-I"$(JAVA_HOME)/include" \ -I"$(JAVA_HOME)/include/$(OS)" BUILD=../build/native JAVAH=$(BUILD) INSTALLDIR=../build/$(OS) JNIDISPATCH_OBJS=$(BUILD)/dispatch.o $(BUILD)/callback.o $(EXTRAOBJS) RSRC=$(BUILD)/rsrc.o DLLCB=$(BUILD)/dll-callback.o ifneq ($(DYNAMIC_LIBFFI),true) FFI_SRC=$(shell pwd)/libffi FFI_BUILD=$(BUILD)/libffi FFI_LIB=$(FFI_BUILD)/.libs/libffi$(ARSFX) FFI_ENV=CC="$(CC)" CFLAGS="$(COPT) $(CDEBUG) -DFFI_STATIC_BUILD" CPPFLAGS="$(CDEFINES) -DFFI_STATIC_BUILD" FFI_CONFIG=--enable-static --disable-shared --with-pic=yes endif LIBRARY=$(BUILD)/$(LIBPFX)jnidispatch$(JNISFX) TESTLIB=$(BUILD)/$(LIBPFX)testlib$(LIBSFX) TESTLIB_JAR=$(BUILD)/$(LIBPFX)testlib-jar$(LIBSFX) TESTLIB_PATH=$(BUILD)/$(LIBPFX)testlib-path$(LIBSFX) TESTLIB_TRUNC=$(BUILD)/testlib-truncated TESTLIB2=$(BUILD)/$(LIBPFX)testlib2$(LIBSFX) # Reasonable defaults based on GCC LIBPFX=lib LIBSFX=.so ARSFX=.a JNISFX=$(LIBSFX) CC=gcc LD=$(CC) LIBS= # Default to Sun recommendations for JNI compilation COPT=-O2 -fno-omit-frame-pointer -fno-strict-aliasing COPT+=-Wno-implicit-function-declaration CASM=-S ifeq ($(DEBUG),true) CDEBUG=-g endif CFLAGS_EXTRA= COUT=-o $@ CINCLUDES=$(JAVA_INCLUDES) -I"$(JAVAH)" -I$(FFI_BUILD)/include CDEFINES=-D_REENTRANT PCFLAGS=-W -Wall -Wno-unused -Wno-parentheses CFLAGS=$(PCFLAGS) $(CFLAGS_EXTRA) $(COPT) $(CDEBUG) $(CDEFINES) $(CINCLUDES) \ -DJNA_JNI_VERSION='"$(JNA_JNI_VERSION)"' -DCHECKSUM='"$(CHECKSUM)"' LDFLAGS=-o $@ -shared ifeq ($(DYNAMIC_LIBFFI),true) CFLAGS += $(shell pkg-config --cflags libffi 2>/dev/null || echo) LIBS += $(shell pkg-config --libs libffi 2>/dev/null || echo -lffi) else # -static-libgcc avoids gcc library incompatibilities across linux systems LDFLAGS += -static-libgcc endif # Avoid bug in X11-based 1.5/1.6 VMs; dynamically load instead of linking # See http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6539705 #LIBS=-L"$(LIBDIR)" -ljawt STRIP=strip -x # end defaults # Android build (cross-compile) requires the android NDK. # Ensure the following tools are in your path and adjust NDK_PLATFORM as needed ifeq ($(OS),android) AARCH=$(ARCH) ALIBDIR=/usr/lib ifeq ($(ARCH),arm) PREFIX=arm-linux-androideabi- COPT+= -mthumb-interwork -march=armv5te -mtune=xscale -msoft-float -fstack-protector HOST=arm-linux-eabi else ifeq ($(ARCH),armv7) PREFIX=arm-linux-androideabi- COPT+= -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16 -Wl,--fix-cortex-a8 HOST=arm-linux-eabi AARCH=arm else ifeq ($(ARCH),aarch64) PREFIX=aarch64-linux-android- HOST=aarch64-linux-android AARCH=arm64 ALIBDIR=/usr/lib64 else ifeq ($(ARCH),x86) PREFIX=i686-linux-android- COPT+= -march=i686 HOST=i686-linux-android else ifeq ($(ARCH),x86-64) PREFIX=x86_64-linux-android- COPT+= -m64 HOST=x86_64-linux-android AARCH=x86_64 ALIBDIR=/usr/lib64 else ifeq ($(ARCH),mips) PREFIX=mipsel-linux-android- HOST=mipsel-linux-android COPT+= else ifeq ($(ARCH),mips64) PREFIX=mips64el-linux-android- HOST=mips64el-linux-android COPT+= ALIBDIR=/usr/lib64 else ERROR = $(error "Unsupported android architecture '$(ARCH)'") endif endif endif endif endif endif endif NDK?=/Developer/Applications/android-ndk-r10e NDK_PLATFORM?=$(NDK)/platforms/android-21 SYSROOT=$(NDK_PLATFORM)/arch-$(AARCH) CC=$(PREFIX)gcc --sysroot $(SYSROOT) CPP=$(PREFIX)cpp LD=$(CC) RANLIB=$(PREFIX)ranlib STRIP=$(PREFIX)strip -x CDEFINES=-DFFI_STATIC_BUILD -DNO_JAWT -DNO_WEAK_GLOBALS -DFFI_MMAP_EXEC_WRIT=1 -DFFI_MMAP_EXEC_SELINUX=0 COPT+=-fpic -ffunction-sections -funwind-tables -fno-short-enums JAVA_INCLUDES= CINCLUDES+=-I"$(NDK_PLATFORM)/arch-$(AARCH)/usr/include" # -I/usr/include LIBS=-nostdlib -L"$(NDK_PLATFORM)/arch-$(AARCH)$(ALIBDIR)/" -lgcc -lc -ldl -lm LDFLAGS+=-Wl,-shared,-Bsymbolic -Wl,--build-id=sha1 FFI_ENV=CPP="$(CPP)" CC="$(CC)" CFLAGS="$(COPT) $(CDEBUG) $(CINCLUDES)" CPPFLAGS="$(CDEFINES) $(CINCLUDES)" LIBS="$(LIBS)" RANLIB="$(RANLIB)" FFI_CONFIG=--enable-static --disable-shared --with-pic=yes --host=$(HOST) endif # W32CE build requires cegcc cross-compiler and phoneME JavaME implementation # cegcc: http://sf.net/projects/cegcc # phoneme: http://davy.preuveneers.net/ ifeq ($(OS),w32ce) ARCH=arm CC=arm-mingw32ce-gcc -mwin32 CDEFINES=-D_WIN32_IE=0x400 -D_WIN32_WCE=0x0420 -DNO_JAWT -DNO_NIO_BUFFERS -DWINCE -D_WIN32_STDARG_H CFLAGS+=-Wno-unknown-pragmas LD=arm-mingw32ce-gcc LDFLAGS=-o $@ -shared LIBS=-lcoredll -lgcc -ltoolhelp WINDRES=arm-mingw32ce-windres EXTRAOBJS=$(RSRC) STRIP=arm-mingw32ce-strip -x LIBPFX= LIBSFX=.dll HOST_CONFIG=--host=arm-mingw32ce # libffi must use GNU ld; jnidispatch.dll requires gcc FFI_ENV+=LD=arm-mingw32ce-ld CPP=cpp CFLAGS="$(CDEFINES)" PHONEME=../phoneme/cdc/src JAVA_INCLUDES=-I$(PHONEME)/share/javavm/export -I$(PHONEME)/share -I$(PHONEME)/win32 -I$(PHONEME)/win32-arm TESTLIB_TRUNC=$(BUILD)/testlib-truncated.dll endif ifeq ($(OS),win32) ifeq ($(shell type cl >& /dev/null && echo found),found) USE_MSVC=true endif # This will be overridden when called from ant ARCH=$(shell uname -m | sed 's/i.86/i386/g') CDEFINES=-DPSAPI_VERSION=1 -DFFI_BUILDING -DUNICODE -D_UNICODE WINDRES=windres EXTRAOBJS=$(RSRC) STRIP=@echo LIBPFX= LIBSFX=.dll TESTLIB_TRUNC=$(BUILD)/testlib-truncated.dll ifeq ($(ARCH),amd64) MINGW_PREFIX?=x86_64-w64-mingw32- FFI_CONFIG+=--host=x86_64-w64-mingw32 else FFI_CONFIG+=--host=i686-w64-mingw32 MINGW_PREFIX?=i686-w64-mingw32- endif # Need windres from mingw distribution, even if building with MSVC WINDRES=$(MINGW_PREFIX)windres MINGW=$(MINGW_PREFIX)gcc ifeq ($(USE_MSVC),true) # MS compiler CC=$(FFI_SRC)/msvcc.sh CDEFINES+=-DHAVE_PROTECTION ifneq ($(DYNAMIC_LIBFFI),true) CDEFINES+=-DUSE_STATIC_RTL endif COPT= CPP=cl -nologo -EP LD=link LDFLAGS=/DLL /OUT:$@ LIBS=psapi.lib ARSFX=.lib ifeq ($(ARCH),amd64) CC+= -m64 FFI_TARGET=$(FFI_SRC)/src/x86/ffitarget.h else ifeq ($(ARCH),aarch64) # Force $(CC) fallback; avoid arch mismatch WINDRES=false # Disable mingw; no aarch64 support MINGW= FFI_CONFIG+=--host=aarch64-cygwin # Skip building assembly callback functions CDEFINES+= -DASMFN_OFF DLLCB= CC+= -marm64 FFI_CONFIG+=--host=aarch64-cygwin endif FFI_TARGET?=$(FFI_SRC)/src/$(ARCH)/ffitarget.h FFI_CONFIG+= && rm -f include/ffitarget.h && cp $(FFI_SRC)/include/*.h $(FFI_TARGET) include FFI_ENV+=LD="$(LD)" CPP="$(CPP)" CXXCPP="$(CPP)" EXTRAOBJS+=$(DLLCB) else # Mingw compiler LDFLAGS=-o $@ -shared FFI_ENV+=CXXCPP="$(CPP)" CC=$(MINGW_PREFIX)gcc CPP=$(MINGW_PREFIX)gcc -E LDFLAGS+=-Wl,--add-stdcall-alias LIBS= -lmingwex -lpsapi -lkernel32 -lmsvcrt endif endif ifeq ($(OS),linux) ARCH=$(shell uname -m | sed 's/i.86/i386/g') PCFLAGS+=-fPIC CDEFINES+=-DHAVE_PROTECTION ifeq ($(DYNAMIC_LIBFFI),true) LDFLAGS+=-Wl,-soname,$@ else # Ensure we bind to local libffi symbols LDFLAGS+=-Wl,-soname,$@,-Bsymbolic endif endif ifneq (,$(or $(findstring bsd,$(OS)),$(findstring dragonfly,$(OS)))) ARCH=$(shell uname -m | sed 's/i.86/i386/g') PCFLAGS+=-fPIC # This is a mess: X11 headers locate in /usr/local/include on FreeBSD and # DragonFly, in /usr/X11R7/include on NetBSD, and in /usr/X11R6/include on # OpenBSD. CINCLUDES+=-I/usr/local/include -I/usr/X11R7/include -I/usr/X11R6/include CINCLUDES+=$(X11INC) # Allow extra X11 include path if necessary. LDFLAGS=-o $@ -shared CDEFINES+=-DHAVE_PROTECTION -DFFI_MMAP_EXEC_WRIT -DUSE_DEAFULT_LIBNAME_ENCODING endif ifeq ($(OS),solaris) ifeq ($(ARCH),) ARCH=$(shell uname -p) endif PCFLAGS+=-fPIC -std=gnu99 CDEFINES+=-DHAVE_PROTECTION -DFFI_MMAP_EXEC_WRIT -DUSE_DEFAULT_LIBNAME_ENCODING ifeq ($(ARCH), sparcv9) # alter CC instead of PCFLAGS, since we need to pass it down to libffi # configure and some of the other settings in PCFLAGS might make the build # choke CC += -m64 LD += -m64 endif endif ifeq ($(OS),aix) LIBSFX=.a PCFLAGS+=-fPIC CDEFINES+=-DHAVE_PROTECTION -DNO_JAWT -Wall -D_AIX -DPOWERPC_AIX -D_THREAD_SAFE_ERRNO COPT+=-D_AIX -DPOWERPC_AIX -mxl-compat LDFLAGS+=-Wl,-lc128,-lc,-lm,-lpthread FFI_ENV+=AR_FLAGS="-X32_64 cru" STRIP=echo strip -X32_64 ifeq ($(ARCH),ppc64) COPT+=-maix64 LDFLAGS+=$(COPT) HOST_CONFIG=--host=ppc-aix64 endif ifeq ($(ARCH),ppc) COPT+=-maix32 LDFLAGS+=$(COPT) HOST_CONFIG=--host=ppc-aix endif endif # CC_OPTS only applied to objects build for jnidispatch, not for libffi # -Wno-unknown-warning-option # => Suppress warning for unknown warnings # -Werror => Treat warnings as errors # -Wno-clobbered => Silence GCC warning about clobbered automatic variables. # The "longjmp" case only happens in protect.h in the logic # that implements "protected" mode. In that case an exception # is raised and the value of the potentially clobbered # variables is ignored. # -Wno-alloca-larger-than => Silence warnings about unbounded alloca calls in # the dispatch logic. GCC tries to assert, that the size of # the allocated memory is bounded and thus a check for the # variable needs to be inplace. For the JNA case, the size # comes from the Java side, so checks are not visible on the # C side and thus can't be checked there. # # Enable this only on GCC versions, that can work with it. It is assumed, that # GCC version 4.X is the lower bound. That version is problematic, as it # does not support -Wno-unknown-warning-option ifeq ($(CC),gcc) GCC_MAJOR_VERSION = $(shell gcc -dumpversion | cut -f 1 -d '.') ifneq ($(GCC_MAJOR_VERSION),4) ifneq ($(GCC_MAJOR_VERSION),3) LOC_CC_OPTS=-Wno-unknown-warning-option -Werror -Wno-clobbered -Wno-unused-variable -Wno-alloca-larger-than endif endif else LOC_CC_OPTS=-Wno-unknown-warning-option -Werror -Wno-clobbered -Wno-unused-variable endif # Enable 64-bit builds if the arch demands it ifeq ($(CC),gcc) ifneq ($(OS),aix) ifeq ($(ARCH),amd64) CC += -m64 LD += -m64 endif ifeq ($(ARCH),ppc64) CC += -m64 LD += -m64 endif ifeq ($(ARCH),ppc64le) CC += -m64 LD += -m64 endif ifeq ($(ARCH),ppc) CC += -m32 LD += -m32 HOST_CONFIG=--host=ppc-linux endif ifeq ($(ARCH),i386) CC += -m32 LD += -m32 endif endif endif ifeq ($(OS),darwin) DARWIN_ARCH=$(ARCH) ifeq ($(ARCH),aarch64) DARWIN_ARCH=arm64 else ifeq ($(ARCH),x86-64) DARWIN_ARCH=x86_64 else ifeq ($(ARCH),x86) DARWIN_ARCH=x86 else endif endif endif XCODE_VERSION=$(shell xcodebuild -version | grep Xcode | sed 's/^Xcode \([1-9][0-9]*\).*/\1/g') MACOS_VERSION_MAJOR=$(shell sw_vers -productVersion | cut -d. -f 1) MACOS_VERSION_MINOR=$(shell sw_vers -productVersion | cut -d. -f 2) JAVA_INCLUDES+=-I/System/Library/Frameworks/JavaVM.framework/Headers # Actual deployment target depends on SDK support MACOSX_DEPLOYMENT_TARGET=10.3 DEFAULT_ARCH=$(shell arch) HOST_CONFIG=--host $(DARWIN_ARCH)-apple-darwin FFI_ENV += CC="$(CC)" CFLAGS="-mmacosx-version-min=$(MACOSX_DEPLOYMENT_TARGET) -arch $(DARWIN_ARCH) $(ISYSROOT) $(COPT) $(CDEBUG)" CPPFLAGS="$(CDEFINES)" LD="$(LD) -arch $(DARWIN_ARCH)" LIBSFX=.dylib JNISFX=.jnilib # JAWT no longer supported on OSX CDEFINES+=-DTARGET_RT_MAC_CFM=0 -DFFI_MMAP_EXEC_WRIT -DNO_JAWT ifneq ($(ARCH),ppc) ifneq ($(XCODE_VERSION),3) # Xcode 4+ options NO_COMPACT_UNWIND=-Wl,-no_compact_unwind endif endif ifneq ($(SDKROOT),) SYSLIBROOT=-Wl,-syslibroot,$(SDKROOT) ISYSROOT=-isysroot $(SDKROOT) ARCHFLAGS+=-arch $(DARWIN_ARCH) endif PCFLAGS+=$(ISYSROOT) -x objective-c # MAJOR < 10 || (MAJOR = 10 && MINOR < 7) MACOS_LT_10_7 = $(shell [ ${MACOS_VERSION_MAJOR} -lt 10 -o ${MACOS_VERSION_MAJOR} -eq 10 -a ${MACOS_VERSION_MINOR} -lt 7 ] && echo true) # JavaVM.framwork is "Deprecated in OS X v10.7." ifeq ($(MACOS_LT_10_7),true) FRAMEWORK=-framework JavaVM endif LDFLAGS=$(ARCHFLAGS) -dynamiclib -o $@ $(FRAMEWORK) \ -compatibility_version $(shell echo ${JNA_JNI_VERSION}|sed 's/^\([0-9][0-9]*\).*/\1/g') \ -current_version $(JNA_JNI_VERSION) \ -mmacosx-version-min=$(MACOSX_DEPLOYMENT_TARGET) \ -framework Foundation \ $(NO_COMPACT_UNWIND) \ -install_name ${@F} \ $(SYSLIBROOT) # JAWT linkage handled by -framework JavaVM LIBS= endif # Unfortunately, we have to use different libffi include files depending on # the target, so we can't do a simple universal build on darwin. Do # separate builds, then merge the results. $(BUILD)/%.o : %.c dispatch.h protect.h $(FFI_LIB) @mkdir -p $(BUILD) ifneq ($(SDKROOT),) $(CC) $(LOC_CC_OPTS) -mmacosx-version-min=$(MACOSX_DEPLOYMENT_TARGET) -arch $(DARWIN_ARCH) $(CFLAGS) -c $< -o $@ else $(CC) $(CFLAGS) $(LOC_CC_OPTS) -c $< $(COUT) endif all: $(LIBRARY) $(TESTLIB) $(TESTLIB2) $(TESTLIB_JAR) $(TESTLIB_PATH) $(TESTLIB_TRUNC) install: mkdir $(INSTALLDIR) cp $(LIBRARY) $(INSTALLDIR) ifeq ($(ARCH), amd64) $(DLLCB): dll-callback.c $(MINGW) -DDEFINE_CALLBACKS -c $< $(COUT) endif $(RSRC): $(BUILD)/jnidispatch.rc $(BUILD)/$(JNA_JNI_VERSION).stamp $(WINDRES) -i $< -o $@ \ || (echo > $@.c && $(CC) $(CFLAGS) -c $@.c $(COUT)) $(BUILD)/$(JNA_JNI_VERSION).stamp: @touch $@ $(LIBRARY): $(JNIDISPATCH_OBJS) $(FFI_LIB) $(LD) $(LDFLAGS) $(JNIDISPATCH_OBJS) $(FFI_LIB) $(LIBS) $(STRIP) $@ $(TESTLIB): $(BUILD)/testlib.o $(LD) $(LDFLAGS) $< $(LIBS) # These targets provide for different shared library loading methods # without getting into native library load conflicts $(TESTLIB_JAR) $(TESTLIB_PATH) $(TESTLIB_TRUNC): $(TESTLIB) @cp $< $@ ifeq ($(ARSFX),.lib) TESTDEP=$(TESTLIB:.dll=.lib) else TESTDEP=$(TESTLIB) endif $(TESTLIB2): $(BUILD)/testlib2.o $(LD) $(LDFLAGS) $< $(TESTDEP) $(LIBS) ifneq ($(DYNAMIC_LIBFFI),true) $(FFI_LIB): @mkdir -p $(FFI_BUILD) @if [ ! -f $(FFI_SRC)/configure ]; then \ echo "Generating configure"; \ (cd $(FFI_SRC); /bin/sh autogen.sh); \ fi @if [ ! -f $(FFI_BUILD)/Makefile ]; then \ echo "Configuring libffi ($(ARCH))"; \ (cd $(FFI_BUILD) \ && $(FFI_ENV) $(FFI_SRC)/configure $(FFI_CONFIG) $(HOST_CONFIG)); \ fi $(MAKE) -C $(FFI_BUILD) endif clean: $(RM) -rf $(BUILD) version: @echo version=$(JNA_JNI_VERSION) #EOF