1#!/bin/bash
2
3# This script builds Octave / Matlab interfaces for macOS.
4# A Matlab installation must be specified in order to build the
5# Matlab interface. The paths should not contain spaces!
6#
7# The script is known to work on macOS 10.5 Catalina with Homebrew.
8#
9# At least the following packages are required:
10# octave gnu-sed cunit
11#
12#
13# Example call:
14# ./macos-build-mex.sh --matlab=/path/to/matlab
15#
16
17# Any subsequent commands which fail will cause the shell script to exit immediately
18set -ex
19
20GCCARCH=haswell
21FFTWDIR=/usr/local
22GCC="gcc-9 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk"
23
24# default values (to be overwritten if respective parameters are set)
25OCTAVEDIR=/usr/local
26
27# read the options
28TEMP=`getopt -o o:m:f:v: --long octave:,matlab:,matlab-version:,fftw: -n 'macos-build-mex.sh' -- "$@"`
29eval set -- "$TEMP"
30
31# extract options and their arguments into variables.
32while true ; do
33    case "$1" in
34        -o|--octave)
35            case "$2" in
36                "")  shift 2 ;;
37                *) OCTAVEDIR=$2; shift 2 ;;
38            esac ;;
39        -m|--matlab)
40            case "$2" in
41                "")  shift 2 ;;
42                *) MATLABDIR=$2; shift 2 ;;
43            esac ;;
44        -v|--matlab-version)
45            case "$2" in
46                "")  shift 2 ;;
47                *) MATLABVERSION=$2; shift 2 ;;
48            esac ;;
49        --) shift ; break ;;
50        *) echo "Internal error!" ; exit 1 ;;
51    esac
52done
53
54NFFTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
55HOMEDIR="$NFFTDIR"/macos-build-mex
56mkdir -p "$HOMEDIR"
57cd "$HOMEDIR"
58GCCVERSION=`$GCC -dumpversion`
59FFTWVERSION=`fftw-wisdom | grep fftw- | gsed 's/(fftw-//' | gsed 's/ fftw_wisdom.*//'`
60OCTAVEVERSION=`"$OCTAVEDIR"/bin/octave-cli --eval "fprintf('OCTAVE_VERSION=%s\n', version); exit;" | grep OCTAVE_VERSION | gsed 's/OCTAVE_VERSION=//'`
61
62# Build NFFT
63READMECONTENT="
64$(gsed -e '/^\[!/d' -e '/Directory structure/Q' $NFFTDIR/README)
65"
66FFTWREADME='
67FFTW
68----
69The compiled NFFT files contain parts of the FFTW library (http://www.fftw.org)
70Copyright (c) 2003, 2007-14 Matteo Frigo
71Copyright (c) 2003, 2007-14 Massachusetts Institute of Technology'
72BINARIES_ARCH_README='
73Please note that since the binaries were compiled with gcc flag -march=haswell,
74they may not work on older CPUs (below Intel i3/i5/i7-4xxx or
75AMD Excavator/4th gen Bulldozer) as well as on some Intel Atom/Pentium CPUs.
76'
77
78cd "$NFFTDIR"
79make distclean || true
80
81for OMPYN in 1
82do
83if [ $OMPYN = 1 ]; then
84  NFFTBUILDDIR="$HOMEDIR/build-openmp"
85  OMPFLAG="--enable-openmp"
86  OMPLIBS="-fopenmp -static-libgcc"
87  THREADSSUFFIX="_threads"
88  OMPSUFFIX="-openmp"
89  FFTW_LINK_COMMAND="-Wl,-force_load,$FFTWDIR/lib/libfftw3_threads.a -Wl,-force_load,$FFTWDIR/lib/libfftw3.a"
90else
91  NFFTBUILDDIR="$HOMEDIR/build"
92  OMPFLAG=""
93  OMPLIBS="-static-libgcc"
94  THREADSSUFFIX=""
95  OMPSUFFIX=""
96  FFTW_LINK_COMMAND="-Wl,-force_load,$FFTWDIR/lib/libfftw3.a"
97fi
98
99rm -f -r "$NFFTBUILDDIR"
100mkdir "$NFFTBUILDDIR"
101cd "$NFFTBUILDDIR"
102
103CC=$GCC CPPFLAGS=-I"$FFTWDIR"/include LDFLAGS=-L"$FFTWDIR"/lib "$NFFTDIR/configure" --enable-all $OMPFLAG --with-octave="$OCTAVEDIR" --with-gcc-arch=$GCCARCH --disable-static --enable-shared --disable-examples --enable-applications
104make
105make check
106
107NFFTVERSION=$( grep 'Version: ' nfft3.pc | cut -c10-)
108
109# Create archive for Julia interface
110cd julia
111for LIB in nf*t
112do
113  cd "$LIB"
114  $GCC -dynamiclib -o lib"$LIB"julia.dylib .libs/lib"$LIB"julia.o -Wl,-force_load,../../.libs/libnfft3_julia.a $FFTW_LINK_COMMAND -lm -O3 -malign-double -march=$GCCARCH $OMPLIBS
115  cd ..
116done
117
118cd fastsum
119$GCC -dynamiclib -o libfastsumjulia.dylib .libs/libfastsumjulia.o -Wl,-force_load,../../.libs/libnfft3_julia.a $FFTW_LINK_COMMAND -Wl,-force_load,../../applications/fastsum/.libs/libfastsum$THREADSSUFFIX.a -Wl,-force_load,../../applications/fastsum/.libs/libkernels.a -lm -O3 -malign-double -march=$GCCARCH $OMPLIBS
120cd ..
121
122cd "$NFFTBUILDDIR"
123
124ARCH=$(uname -m)
125JULIADIR=nfft-"$NFFTVERSION"-julia-macos_$ARCH$OMPSUFFIX
126mkdir "$JULIADIR"
127rsync -rLt --exclude='Makefile*' --exclude='doxygen*' --exclude='*.c.in' --exclude='*.c' --exclude='*.h' "$NFFTDIR/julia/" "$JULIADIR"
128rsync -rLt --exclude='Makefile*' --exclude='.deps' --exclude='.libs' --exclude='*.la' --exclude='*.lo' --exclude='*.o' --exclude='*.c' 'julia/' "$JULIADIR"
129
130for DIR in $JULIADIR/nf*t $JULIADIR/fastsum; do cd $DIR; for NAME in simple_test*.jl; do julia "$NAME"; done; cd "$NFFTBUILDDIR"; done;
131
132echo 'This archive contains the NFFT' $NFFTVERSION 'Julia interface.
133The NFFT library was compiled with double precision support for '$ARCH' macOS
134using GCC '$GCCVERSION' with -march='$GCCARCH' and FFTW '$FFTWVERSION'.
135'"$BINARIES_ARCH_README""$READMECONTENT""$FFTWREADME" > "$JULIADIR"/readme-julia.txt
136zip -9 -r ../"$JULIADIR".zip "$JULIADIR"
137# End of Julia interface
138
139
140# Create Matlab/Octave release
141for LIB in nfft nfsft nfsoft nnfft fastsum nfct nfst fpt
142do
143  cd matlab/"$LIB"
144  $GCC -o .libs/lib"$LIB".mex -bundle  .libs/lib"$LIB"_la-"$LIB"mex.o -Wl,-force_load,../../.libs/libnfft3_matlab.a -Wl,-force_load,../../matlab/.libs/libmatlab.a -L"$OCTAVEDIR"/lib/octave/"$OCTAVEVERSION" $FFTW_LINK_COMMAND -lm -loctinterp -loctave -O3 -malign-double -march=$GCCARCH $OMPLIBS
145  cd ../..
146done
147
148DIR=nfft-$NFFTVERSION-mexmaci64$OMPSUFFIX
149mkdir $DIR
150rsync -rLt --exclude='Makefile*' --exclude='doxygen*' --exclude='*.c.in' --exclude='*.c' --exclude='*.h' "$NFFTDIR/matlab/" "$DIR"
151rsync -rLt --exclude='Makefile*' --exclude='.deps' --exclude='.libs' --exclude='*.la' --exclude='*.lo' --exclude='*.o' --exclude='*.c' "matlab/" "$DIR"
152
153# Compile with Matlab
154if [ -n "$MATLABDIR" ]; then
155  if [ -z "$MATLABVERSION" ]; then
156    MATLABVERSION=`"$MATLABDIR"/bin/matlab -wait -nodesktop -nosplash -r "fprintf('MATLAB_VERSION=%s\n', version); exit;" | grep MATLAB_VERSION | gsed 's/.*(//' | gsed 's/)//'`
157  fi
158  MATLABSTRING="and Matlab $MATLABVERSION "
159  cd "$NFFTBUILDDIR"
160  make clean
161  CC=$GCC CPPFLAGS=-I"$FFTWDIR"/include LDFLAGS=-L"$FFTWDIR"/lib "$NFFTDIR/configure" --enable-all $OMPFLAG --with-matlab="$MATLABDIR" --with-gcc-arch=$GCCARCH --disable-static --enable-shared --disable-examples --disable-applications
162  make
163  make check
164  for LIB in nfft nfsft nfsoft nnfft fastsum nfct nfst fpt
165  do
166    cd matlab/"$LIB"
167    $GCC -o .libs/lib"$LIB".mexmaci64 -bundle  .libs/lib"$LIB"_la-"$LIB"mex.o   -Wl,-force_load,../../.libs/libnfft3_matlab.a -Wl,-force_load,../../matlab/.libs/libmatlab.a  -L"$MATLABDIR"/bin/maci64 -lm -lmwfftw3 -lmx -lmex -lmat -O3 -malign-double -march=$GCCARCH $OMPLIBS
168    cd ../..
169  done
170fi
171
172for SUBDIR in nfft nfsft nfsoft nnfft fastsum nfct nfst fpt
173  do
174  cp -f -L matlab/$SUBDIR/*.mex* "$DIR"/$SUBDIR/
175done
176
177for SUBDIR in nfft nfsft nfsoft nnfft fastsum nfct nfst infft1d fpt ; do
178  cd "$DIR/$SUBDIR"
179  if [ -f simple_test.m ] ; then
180  for TESTFILE in *test*.m
181    do
182    if [ "$SUBDIR" != "infft1d" ] ; then
183      "$OCTAVEDIR"/bin/octave-cli --eval="run('$TESTFILE')"
184    fi
185     if [ -n "$MATLABDIR" ]; then
186      "$MATLABDIR"/bin/matlab -wait -nodesktop -nosplash -r "run('$TESTFILE'); exit"
187    fi
188  done
189  fi
190  cd "$NFFTBUILDDIR"
191done
192
193cd "$NFFTBUILDDIR"
194cp "$NFFTDIR"/COPYING "$DIR"/COPYING
195if [ -n "$MATLABDIR" ]; then
196echo 'This archive contains the Matlab and Octave interface of NFFT '$NFFTVERSION'
197compiled for '$ARCH' macOS using GCC '$GCCVERSION' with -march='$GCCARCH'
198'$MATLABSTRING'and Octave '$OCTAVEVERSION'.
199'"$BINARIES_ARCH_README""$READMECONTENT""$FFTWREADME" > "$DIR"/readme-matlab.txt
200else
201echo 'This archive contains the Octave interface of NFFT '$NFFTVERSION'
202compiled for '$ARCH' macOS using GCC '$GCCVERSION' with -march='$GCCARCH'
203and Octave '$OCTAVEVERSION'.
204'"$BINARIES_ARCH_README""$READMECONTENT""$FFTWREADME" > "$DIR"/readme-matlab.txt
205fi
206
207zip -9 -r ../"$DIR".zip "$DIR"
208
209done
210