diff --git a/.gitignore b/.gitignore index 9dbcc6b..7873cdd 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,19 @@ +/aclocal.m4 +/autom4te.cache /bin +/build-aux +/configure +/config.h +/config.h.in +/config.log +/config.status +/libtool +/stamp-h1 + +.deps +.libs +Makefile +Makefile.in *.jar -*.so -*.dll +*.la +*.lo diff --git a/Makefile b/Makefile deleted file mode 100644 index 0fc296f..0000000 --- a/Makefile +++ /dev/null @@ -1,19 +0,0 @@ -# simple makefile for now - -CC = gcc -JAVAC = javac -JAVA_HOME = /usr/lib/jvm/java -JAVA_PLATFORM = linux - -all: libopenslide-jni.so - ant - -libopenslide-jni.so: openslide-jni.c - $(CC) $(CFLAGS) -fPIC -shared -g -O2 -Wall -o $@ $< -I$(JAVA_HOME)/include -I$(JAVA_HOME)/include/$(JAVA_PLATFORM) $$(pkg-config openslide --cflags --libs) - -clean: - ant clean - $(RM) libopenslide-jni.so openslide_wrap.c *~ bin - - -.PHONY: all clean diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..03db8ee --- /dev/null +++ b/Makefile.am @@ -0,0 +1,60 @@ +ACLOCAL_AMFLAGS = -I m4 + +AM_CFLAGS = -Wall $(JNI_CFLAGS) $(OPENSLIDE_CFLAGS) +AM_CFLAGS += -Wno-pointer-to-int-cast -Wno-int-to-pointer-cast +AM_LDFLAGS = -avoid-version -no-undefined -module $(OPENSLIDE_LIBS) + +if DLL +# JNI uses stdcall without @ +AM_LDFLAGS += -Wl,--kill-at +JNI_LA = openslide-jni.la +JNI_SO = openslide-jni.dll +else +JNI_LA = libopenslide-jni.la +JNI_SO = libopenslide-jni.so +endif + +if EMBED_PATH +JNI_EMBED_PATH = $(pkglibdir)/$(JNI_SO) +endif + +export JAVA_HOME +export ANT_HOME + +pkglib_LTLIBRARIES = $(JNI_LA) +libopenslide_jni_la_SOURCES = openslide-jni.c + +pkglib_DATA = openslide.jar +JAVA_SRC = build.xml \ + src/edu/cmu/cs/openslide/AssociatedImageMap.java \ + src/edu/cmu/cs/openslide/OpenSlideDisposedException.java \ + src/edu/cmu/cs/openslide/OpenSlide.java \ + src/edu/cmu/cs/openslide/OpenSlideJNI.java \ + src/edu/cmu/cs/openslide/TestCLI.java \ + src/edu/cmu/cs/openslide/gui/Annotation.java \ + src/edu/cmu/cs/openslide/gui/DefaultAnnotation.java \ + src/edu/cmu/cs/openslide/gui/DefaultSelectionListModel.java \ + src/edu/cmu/cs/openslide/gui/Demo.java \ + src/edu/cmu/cs/openslide/gui/OpenSlideView.java \ + src/edu/cmu/cs/openslide/gui/SelectionListModel.java \ + src/org/openslide/dzi/DeepZoomGenerator.java + +openslide.jar: $(JAVA_SRC) config.h + @$(ANT) -f $(srcdir)/build.xml -Dbuilddir=$(abs_builddir) \ + -Dopenslide.jni.path=$(JNI_EMBED_PATH) + +mostlyclean-local: + @$(ANT) -f $(srcdir)/build.xml -Dbuilddir=$(abs_builddir) clean + +install-exec-hook: + chmod -x $(DESTDIR)$(pkglibdir)/$(JNI_SO) + rm -f $(DESTDIR)$(pkglibdir)/$(JNI_LA) \ + $(DESTDIR)$(pkglibdir)/$(JNI_SO).a + +EXTRA_DIST = \ + CHANGELOG.txt \ + LICENSE.txt \ + README.txt \ + TODO.txt \ + lgpl-2.1.txt \ + $(JAVA_SRC) diff --git a/README.txt b/README.txt new file mode 100644 index 0000000..5a5262c --- /dev/null +++ b/README.txt @@ -0,0 +1,45 @@ +Build requirements +------------------ + +- JDK +- Apache Ant +- OpenSlide + +Building on Linux +----------------- + +./configure +make +make install + +Cross-compiling for Windows with mingw32 +---------------------------------------- + +You will need the GNU Classpath version of jni.h installed. (On Fedora +this is in the libgcj-devel package.) + +PKG_CONFIG=pkg-config \ + PKG_CONFIG_PATH=/path/to/cross/compiled/openslide/lib/pkgconfig \ + ./configure --host=i686-pc-mingw32 --build=$(build-aux/config.guess) +make +make install + +Building on Windows +------------------- + +Install a JDK, Apache Ant, MinGW, and MSYS. Edit the MSYS fstab file +(e.g. C:\MinGW\msys\1.0\etc\fstab) to mount your JDK and Apache Ant +installations within the MSYS directory tree: + +C:\Progra~1\Java\jdk1.6.0_29 /java +C:\ant /ant + +You must use 8.3 short file names for path elements that contain spaces. + +Then: + +./configure --prefix=/path/to/install/dir JAVA_HOME=/java \ + ANT_HOME=/ant OPENSLIDE_CFLAGS=-I/path/to/openslide/include \ + OPENSLIDE_LIBS="-L/path/to/openslide/lib -lopenslide" +make +make install diff --git a/acinclude.m4 b/acinclude.m4 new file mode 100644 index 0000000..120af64 --- /dev/null +++ b/acinclude.m4 @@ -0,0 +1,33 @@ +# FIND_FILE([OUTPUT], [FILE_NAME], [SEARCH_PATHS]) +# The paths in SEARCH_PATHS are searched to determine whether they contain +# the file FILE_NAME. If so, OUTPUT is set to the directory containing +# the file. Otherwise, an error is produced. +# ------------------------------------------------------------------------ +AC_DEFUN([FIND_FILE], [ + AC_MSG_CHECKING([for $2]) + $1= + for ac__path in $3 + do + if test -r $ac__path/$2 ; then + AC_MSG_RESULT([$ac__path]) + $1=$ac__path + break + fi + done + if test z$$1 = z ; then + AC_MSG_RESULT([not found]) + AC_MSG_ERROR([cannot find $2 in $3]) + fi +]) + + +# JOIN_EACH([OUTPUT], [PATHS], [SUBDIR]) +# Append SUBDIR to each of the PATHS and put the result in OUTPUT. +# ---------------------------------------------------------------- +AC_DEFUN([JOIN_EACH], [ + $1= + for dir in $2 + do + $1="$$1 $dir/$3" + done +]) diff --git a/build.xml b/build.xml index ab4cc91..54341e3 100644 --- a/build.xml +++ b/build.xml @@ -4,22 +4,24 @@ + + - + - - + + - - + + - + @@ -30,10 +32,13 @@ - + + + + diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..f5af812 --- /dev/null +++ b/configure.ac @@ -0,0 +1,106 @@ +# -*- Autoconf -*- +# Process this file with autoconf to produce a configure script. + +AC_PREREQ([2.66]) +AC_INIT([OpenSlide Java], [0.9.2], [openslide-users@lists.andrew.cmu.edu]) +AC_CONFIG_AUX_DIR([build-aux]) +AC_CONFIG_MACRO_DIR([m4]) +AC_CONFIG_SRCDIR([openslide-jni.c]) +AC_CONFIG_HEADERS([config.h]) +AM_INIT_AUTOMAKE([foreign dist-xz]) +AM_SILENT_RULES([yes]) +LT_INIT([win32-dll disable-static]) + +# Checks for programs. + +PKG_PROG_PKG_CONFIG() +AC_PROG_CC + +# For distribution-packaged Ant, $ANT may not be $ANT_HOME/bin/ant. +# Use and pass through ANT_HOME if we receive it; otherwise, focus on ANT. +AC_ARG_VAR([ANT], [path to ant program]) +AC_ARG_VAR([ANT_HOME], [path to ant installation directory]) +if test z$ANT = z -a z$ANT_HOME != z ; then + ANT=$ANT_HOME/bin/ant +fi +AC_PATH_PROG([ANT], [ant]) +if test z$ANT = z ; then + AC_MSG_ERROR([ant not found]) +fi + +# Checks for libraries. + +PKG_CHECK_MODULES([OPENSLIDE], [openslide]) + +# Checks for header files. + +AC_ARG_VAR([JAVA_HOME], [path to JDK]) +AC_ARG_WITH([java], [AS_HELP_STRING([--with-java], [path to JDK])], [], + [with_java="$JAVA_HOME /usr/lib/jvm/java"]) +if test $host = $build; then + # Find jni.h + JOIN_EACH([include_paths], [$with_java], [include]) + FIND_FILE([jni_h_dir], [jni.h], [$include_paths]) + JAVA_HOME=$(dirname $jni_h_dir) + # Find jni_md.h + AS_CASE([$host], + [*-*-linux-gnu], [include_subdir=linux], + [*-*-mingw32], [include_subdir=win32], + [include_subdir=] + ) + JOIN_EACH([platform_include_paths], [$include_paths], [$include_subdir]) + FIND_FILE([jni_md_h_dir], [jni_md.h], + [$platform_include_paths $include_paths]) + JNI_CFLAGS="-I$jni_h_dir -I$jni_md_h_dir" +else + # For cross builds, we don't have the OpenJDK jni_md.h for the target + # platform, so use the GNU Classpath JNI headers in the build system's + # gcj include directory instead. Autoconf doesn't give us a variable + # for the build compiler, which is okay because anything other than + # GCC probably won't support this syntax. + # + # Don't set JAVA_HOME unless it was specified on the command line. + # + # This is terrible. + JNI_CFLAGS= + AC_MSG_CHECKING([for cross jni.h and jni_md.h]) + for word in $(gcc - -v -E < /dev/null 2>&1) + do + if test -r "$word/jni.h" -a -r "$word/jni_md.h" ; then + AC_MSG_RESULT([$word]) + JNI_CFLAGS="-I$word" + break + fi + done + if test x$JNI_CFLAGS = x ; then + AC_MSG_RESULT([not found]) + AC_MSG_ERROR([cannot find JNI headers]) + fi +fi +AC_SUBST([JNI_CFLAGS]) + +# Checks for typedefs, structures, and compiler characteristics. + +AC_TYPE_INT64_T +AC_TYPE_UINT32_T + +AC_MSG_CHECKING([JNI library name]) +if test x$shrext_cmds = x.dll ; then + AC_MSG_RESULT([openslide-jni.dll]) +else + AC_MSG_RESULT([libopenslide-jni.so]) +fi +AM_CONDITIONAL([DLL], [test x$shrext_cmds = x.dll]) + +AC_MSG_CHECKING([whether to embed library path in JAR]) +if test x$shrext_cmds = x.dll ; then + AC_MSG_RESULT([no]) +else + AC_MSG_RESULT([yes]) +fi +AM_CONDITIONAL([EMBED_PATH], [test x$shrext_cmds != x.dll]) + +# Checks for library functions. + +AC_CONFIG_FILES([Makefile]) +AC_OUTPUT diff --git a/m4/.gitignore b/m4/.gitignore new file mode 100644 index 0000000..72e8ffc --- /dev/null +++ b/m4/.gitignore @@ -0,0 +1 @@ +* diff --git a/mingw32-cheatsheet.txt b/mingw32-cheatsheet.txt deleted file mode 100644 index 1ace2e4..0000000 --- a/mingw32-cheatsheet.txt +++ /dev/null @@ -1,5 +0,0 @@ -* kill-at is required because JNI uses stdcall without @ -* Use classpath's jni.h instead of OpenJDK's, because it has all the - win32 conditionals - -i686-pc-mingw32-gcc -Wl,--kill-at -shared -g -O2 -Wall -Wno-pointer-to-int-cast -Wno-int-to-pointer-cast -o openslide-jni.dll openslide-jni.c -I/tmp/zzzzz/usr/i686-pc-mingw32/sys-root/mingw/include/openslide -I/usr/lib/gcc/x86_64-redhat-linux/4.4.0/include -lopenslide -L/tmp/zzzzz/usr/i686-pc-mingw32/sys-root/mingw/lib diff --git a/src/edu/cmu/cs/openslide/OpenSlideJNI.java b/src/edu/cmu/cs/openslide/OpenSlideJNI.java index 7c956b0..aea7d4a 100644 --- a/src/edu/cmu/cs/openslide/OpenSlideJNI.java +++ b/src/edu/cmu/cs/openslide/OpenSlideJNI.java @@ -21,12 +21,39 @@ package edu.cmu.cs.openslide; +import java.io.InputStream; +import java.io.IOException; +import java.util.Properties; + class OpenSlideJNI { private OpenSlideJNI() { } static { - System.loadLibrary("openslide-jni"); + String libraryPath = null; + + try { + InputStream is = OpenSlideJNI.class.getClassLoader(). + getResourceAsStream("resources/openslide.properties"); + if (is != null) { + Properties p = new Properties(); + p.load(is); + libraryPath = p.getProperty("openslide.jni.path"); + if (libraryPath.equals("")) { + libraryPath = null; + } + } + } catch (SecurityException e1) { + e1.printStackTrace(); + } catch (IOException e2) { + e2.printStackTrace(); + } + + if (libraryPath != null) { + System.load(libraryPath); + } else { + System.loadLibrary("openslide-jni"); + } } native static boolean openslide_can_open(String file);