Skip to content

Commit

Permalink
Release Candidate 0.10.0 (#145)
Browse files Browse the repository at this point in the history
* rdsamp: octave compatibility fixes.

Java arrays may or may not be directly usable as Octave matrices,
depending on the version of Octave in use, the type of the array, and
the dimensionality.

Octave 4.0 permits using 1D arrays of various types without any
explicit conversion.  1D and 2D 'double' arrays can be converted using
the builtin java2mat function.  Other types can be converted (less
efficiently) using the org.octave.Matrix class.

There are a lot of layers involved here, and a lot of magical bits I
don't understand.  The efficiency could certainly be improved.

* rdsampjni: add a working test case for 'make check'.

* SystemSettings: fix native library loading on Windows.

This was broken by "SystemSettings: use standard paths for loading
rdsampjni".

The story in more detail:

- To load DLLs, Windows looks in the PATH, the directory containing
  the executable, and the current working directory (in some order, I
  don't remember exactly.)  Despite what you might naively expect, it
  doesn't search in the directory containing the library that
  requested the dependency.

- System.loadLibrary() searches for library files according to the
  system property 'java.library.path'.  However, it's impossible to
  change that at runtime.  (The value is cached.
  http://fahdshariff.blogspot.com/2011/08/changing-java-library-path-at-runtime.html
  proposes a way to hack 'ClassLoader' to make it work.  This doesn't
  appear to work with the current JRE.)  I also don't know whether
  this has any effect on DLL dependencies, but I somewhat suspect it
  doesn't.

So there doesn't seem to be any sane way to load a DLL, along with its
dependencies, from an arbitrary location.

Instead (as the code did prior to my recent changes), we must pre-load
the required libraries.  To avoid hard-coding that list, read it from
a text file in the bin directory; that file is now generated by
mcode/nativelibs/Makefile and is only somewhat hard-coded.

Finally, throw an exception if this fails, rather than calling
System.exit().

(Note that none of this is necessary on ELF systems, where we set the
RPATH to "$ORIGIN/../lib", or on Darwin, where we set the install name
to "@loader_path/../lib/libfoo.dylib".)

* Add note to UnitTests about the required toolboxes.

* Bump version to 0.10.0.

* NEWS updates.

* Add a simple script for building all binaries.

* wfdbloadlib: bump version number.
  • Loading branch information
ikarosilva committed Nov 1, 2017
1 parent c7daec5 commit f1dd6e8
Show file tree
Hide file tree
Showing 11 changed files with 115 additions and 19 deletions.
2 changes: 1 addition & 1 deletion Makefile
Expand Up @@ -16,7 +16,7 @@ ANT = ant
#There is really no reason by the *.jar and *.zip should need to have the same
#version numbers, as they are really modular...But for now we keep them at the same
#versioning level in order to avoid (or increase?) confusion.
VERSION=0-9-10
VERSION=0-10-0
APP_NAME=wfdb-app-toolbox-$(VERSION).zip
JAR7_NAME=wfdb-app-JVM7-$(VERSION).jar

Expand Down
5 changes: 3 additions & 2 deletions UnitTests/test_edr.m
Expand Up @@ -9,7 +9,8 @@
end

%Test the examples

% Note: This requires the Signal Processing toolbox

test_string={['signal=''fantasia/f1o02'';r_peaks=''ecg'';' ...
'data_type=1;channel=2;y=edr(data_type,signal,r_peaks,[],[],[],channel);' ...
'wfdb2mat(''f1o02'');[~,signal,Fs,~]=rdmat(''f1o02m'');' ...
Expand All @@ -20,4 +21,4 @@
'xlabel(''time (s)'');close all']};

clean_up={['delete([pwd filesep ''f1o02m*'']);']};
[tests,pass,perf]=test_wrapper(test_string,clean_up,verbose);
[tests,pass,perf]=test_wrapper(test_string,clean_up,verbose);
3 changes: 2 additions & 1 deletion UnitTests/test_woody.m
Expand Up @@ -9,6 +9,7 @@
end

%Test the examples
% Note: This requires the Signal Processing toolbox
str=['t=[0:1/1000:1];N=1001;x=sin(2*pi*t)+sin(4*pi*t)+sin(8*pi*t);' ...
'y=exp(0.01*[-1*[500:-1:1] 0 -1*[1:500]]);'...
's=x.*y;sig1=0;sig2=0.1;M=100;S=zeros(N,M);center=501;TAU=round((rand(1,M)-0.5)*160);'...
Expand All @@ -25,4 +26,4 @@
test_string={str};

clean_up={};
[tests,pass,perf]=test_wrapper(test_string,clean_up,verbose);
[tests,pass,perf]=test_wrapper(test_string,clean_up,verbose);
39 changes: 39 additions & 0 deletions build-toolbox
@@ -0,0 +1,39 @@
#!/bin/bash

set -e
set -x

if [ $# != 3 ]; then
echo "Usage: $0 repository branch version" >&2
exit 1
fi

repo=$1
branch=$2
version=$3

package=wfdb-app-toolbox-$version

builddir=/tmp/toolbox-build
outdir=/tmp
make="make -j"

rm -rf $builddir

git clone --branch $branch --depth 1 $repo $builddir

cd $builddir

git archive --prefix=wfdb-app-toolbox-$version/ HEAD | gzip -c -9 > $outdir/$package.tar.gz

# FIXME: use wfdb-toolbox-build chroot for this
schroot -cjessie make jar7 &> jar7.log

$make -C mcode/nativelibs download &> download.log

(cd dependencies/jni && ./autogen.sh) &> autogen.log

$make -C mcode/nativelibs install-linux install-windows install-macosx &> nativelibs.log

make package APP_NAME=wfdb-app-toolbox-$version.zip
mv $package.zip $outdir/
20 changes: 20 additions & 0 deletions dependencies/jni/100s.expected
@@ -0,0 +1,20 @@
995
1011
995
1011
995
1011
995
1011
995
1011
995
1011
995
1011
995
1011
1000
1008
997
1008
10 changes: 6 additions & 4 deletions dependencies/jni/Makefile.in
Expand Up @@ -27,11 +27,12 @@ classdir = $(srcdir)/../../bin/classes

all: librdsampjni.la

# FIXME: this doesn't work
# it tries to look for the shared libraries in absurd places
# plus it doesn't actually test anything
check: librdsampjni.la
LD_LIBRARY_PATH=".libs:$(LD_LIBRARY_PATH)" $(JAVA) -classpath $(classdir) org.physionet.wfdb.jni.Rdsamp
rm -rf test.jar nativelibs
jar cf test.jar -C $(classdir) .
make install libdir=`pwd`/nativelibs/custom/lib
$(JAVA) -cp test.jar org.physionet.wfdb.jni.Rdsamp -r 100s -t s10 > 100s.out
diff 100s.out $(srcdir)/100s.expected

install: librdsampjni.la
mkdir -p $(libdir)
Expand All @@ -54,6 +55,7 @@ org_physionet_wfdb_jni_Rdsamp.h: $(classdir)/org/physionet/wfdb/jni/Rdsamp.class
clean:
$(LIBTOOL) --mode=clean rm -f *.la *.lo
rm -f org_physionet_wfdb_jni_Rdsamp.h
rm -rf test.jar nativelibs 100s.out

distclean: clean
rm -f config.status config.log libtool
Expand Down
4 changes: 2 additions & 2 deletions jarbuild.xml
Expand Up @@ -4,8 +4,8 @@
<property name="build.dir" value="bin"/>
<property name="classes.dir" value="${build.dir}/classes"/>
<property name="jar.dir" value="mcode"/>
<property name="jar7name" value="wfdb-app-JVM7-0-9-10.jar"/>
<property name="jar8name" value="wfdb-app-JVM8-0-9-10.jar"/>
<property name="jar7name" value="wfdb-app-JVM7-0-10-0.jar"/>
<property name="jar8name" value="wfdb-app-JVM8-0-10-0.jar"/>

<target name="compile7">
<delete dir="${build.dir}"/>
Expand Down
10 changes: 10 additions & 0 deletions mcode/NEWS
@@ -1,6 +1,16 @@
For a detailed list of changes see the repository Log at:
http://github.com/ikarosilva/wfdb-app-toolbox.git

0.10.0 (October 31, 2017)
Updated WFDB library and applications to version 10.5.25pre1.

The API for the RDSAMP function has changed with this version.
Note that the matrix of sample values is now the *first* output
value rather than the third.

The toolbox is now compatible with MATLAB/Octave releases that
use Java 1.8 (or later.)

0.9.10 (March 13, 2015)
Added the function SNIP to the library. Added local caching of PhysioNet files to the {wfdbroot}/databases directory.
Updated native libraries to WFDB 10.5.24. Implement RSDSAMP via the JNI for improvement in memory and speed.
Expand Down
9 changes: 7 additions & 2 deletions mcode/nativelibs/Makefile
Expand Up @@ -78,6 +78,7 @@ buildbindir = $(BUILD_DIR)/bin
MATLAB=matlab

export nocheck
export nojavacheck
export PATH

# ensure that libraries installed in $(libdir) are visible to binaries
Expand Down Expand Up @@ -118,7 +119,7 @@ install-windows:
f77_extra_libs="-Wl,-Bstatic -lgfortran -lquadmath -Wl,-Bdynamic" \
JAVA_HOME=/home/benjamin/packages/zulu8.13.0.5-jdk8.0.72-win_x64 \
WINEPREFIX=$(SRC_DIR)/windows/build/.wine \
WINEARCH=win64 WINEDEBUG=warn+dll DISPLAY=
WINEARCH=win64 WINEDEBUG=warn+dll DISPLAY= nojavacheck=1
rm -rf $(SRC_DIR)/windows/build/.wine
$(MAKE) installclean host=windows
clean-windows:
Expand Down Expand Up @@ -346,7 +347,11 @@ $(BUILD_DIR)/librdsampjni.isconfig: $(BUILD_DIR)/wfdb.isbuilt
touch $(BUILD_DIR)/librdsampjni.isconfig
$(BUILD_DIR)/librdsampjni.isbuilt: $(BUILD_DIR)/librdsampjni.isconfig
( cd $(BUILD_DIR)/librdsampjni && $(MAKE) install )
# [ -n "$(nocheck)" ] || ( cd $(BUILD_DIR)/librdsampjni && $(MAKE) check )
[ -n "$(nocheck)$(nojavacheck)" ] || ( cd $(BUILD_DIR)/librdsampjni && $(MAKE) check )
set -e; if [ -f $(bindir)/librdsampjni.dll ]; then \
( cd $(bindir); ls libcurl-*.dll > librdsampjni.dep ); \
( cd $(bindir); ls wfdb-*.*.dll >> librdsampjni.dep ); \
fi
librdsampjni: $(BUILD_DIR)/librdsampjni.isbuilt
installclean-librdsampjni:
rm -f $(BUILD_DIR)/librdsampjni.isbuilt
Expand Down
2 changes: 1 addition & 1 deletion mcode/wfdbloadlib.m
Expand Up @@ -101,7 +101,7 @@
ml_jar_version=['Java ' ml_jar_version];
end
%Check if path has not been added yet
wfdb_path=[wfdb_path 'wfdb-app-JVM7-0-9-10.jar'];
wfdb_path=[wfdb_path 'wfdb-app-JVM7-0-10-0.jar'];
javaaddpath(wfdb_path)
isloaded=1;

Expand Down
30 changes: 24 additions & 6 deletions src/org/physionet/wfdb/SystemSettings.java
Expand Up @@ -4,6 +4,9 @@
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.Map;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class SystemSettings {

Expand All @@ -29,14 +32,29 @@ public static void loadCurl(Boolean customArch){

private static void loadLib(String libName, Boolean customArch){
if(getOsName().contains("windows")){
// No RPATH on windows, so library dependencies can't
// be loaded automatically and must be pre-loaded.

// (Although Windows automatically searches for
// required DLLs in the *application's* directory, it
// doesn't do the same when loading a DLL.)

// Nasty kludge: list the required libraries in a
// separate text file, so they do not have to be
// hardcoded here.

String libdir = getWFDB_NATIVE_BIN(customArch) + "bin\\";
String depfile = libdir + "lib" + libName + ".dep";
try {
System.load(SystemSettings.getWFDB_NATIVE_BIN(customArch)
+ "\\bin\\lib" + libName + ".dll");
} catch (UnsatisfiedLinkError e) {
System.err.println("Native code library failed to load.\n" + e);
System.exit(1);
BufferedReader r = new BufferedReader(new FileReader(depfile));
String name;
while ((name = r.readLine()) != null) {
System.load(libdir + name);
}
} catch (IOException e) {
throw new UnsatisfiedLinkError("error reading " + depfile);
}

System.load(libdir + "lib" + libName + ".dll");
}else if(getOsName().contains("mac")){
System.load(SystemSettings.getWFDB_NATIVE_BIN(customArch)
+ "/lib/lib" + libName + ".dylib");
Expand Down

0 comments on commit f1dd6e8

Please sign in to comment.