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);