SPM/SPM2 MEX Compilation on Windows

Prerequisites:

Introduction

The source code for the SPM mex files references a few header files – and their respective compiled libraries – that typically exist in Unix/Linux distributions but not in Windows. To overcome this limitation a Linux environment called Cygwin can be installed on a Windows machine and the mex file compilation can be done within that environment. Compiling mex files within Cygwin alone would require that the Cygwin DLL be distributed with the mex files in order for them to work. Because the Cygwin DLL contains MANY compiled Unix routines it is overkill. To avoid using the Cygwin DLL, the MinGW (Minimalist GNU for Windows) package can be used instead to provide the minimal Unix functionality that the SPM mex files require.

The following is what I finally arrived at (after some trial and error and online research) as a working setup to compile the mex files for SPM2 for use with Matlab R2007a on Windows XP...

Step 1: Setup Gnumex

Matlab's mex command is actually a batch file (in unix it's a shell script) that calls a perl script that runs the selected compiler to build appropriate mex files. When mex is run it consults mexopts.bat to find the chosen compiler and command line options for it. Normally mexopts.bat is generated by Matlab when you run 'mex -setup' and choose a compiler from the list of those installed. Gnumex takes on this task instead and generates a proper mexopts.bat so that the mex command calls the compiler in Cygwin or MinGW (the compiler is actually gcc).

If you are using Matlab R2007a or later you will have to edit gnumex.m to accommodate your version. Assuming that Gnumex is installed in c:\gnumex and you've added that to the Matlab path, run edit gnumex.m from the Matlab prompt. Starting on line 619 of gnumex.m there is an if/elseif block that checks a variable mlv (obtained from Matlab's version command) this check only reaches up to version 7, we need to add a block to process 7.4. At line 648 replace end with: else % matlab R2007

mexdefs = {};

engdefs = {};

fmexdefs = {};

fengdefs = {};

end

Now you can run gnumex from the Matlab prompt and setup the options as you see below:



The above options assume that you've installed Gnumex to c:\gnumex and MinGW to c:\mingw. Now hit the Make opts button. Gnumex itself uses 2 mex files shortpath.dll and getpath.dll to be exact, so if you receive an error like this: ??? Undefined function or method 'shortpath' for input arguments of type 'char'. Error in ==> gnumex at 567

s = shortpath(s);

Error in ==> gnumex at 591

pps = gnumex('parsepaths', pstruct);

??? Error using ==> gnumex('makeopt')

Undefined function or method 'shortpath' for input arguments of type 'char'.

??? Error while evaluating uicontrol Callback

You may have to SPM/Compile the gnumex mex files so that they will work with your version of Matlab BEFORE you can use gnumex itself.

Again, if you are using Matlab R2007a or later you will now have to edit the mexopts.bat file that Gnumex generated in order to make it work with you version of Matlab. By default the file is located in: C:\Documents and Settings\USERNAME\Application Data\MathWorks\MATLAB\R2007a Add the following lines to mexopts.bat directly under the 'Added libraries for linking' section replacing the existing set GM_ADD_LIBS line: set ML=C:\PROGRA~1\MATLAB\R2007a\extern\lib\win32\micros~1 set GM_ADD_LIBS=%ML%\libmx.lib %ML%\libmex.lib %ML%\libeng.lib %ML%\libmat.lib

Step 2: Edit the Makefile

The Makefile that's included With the SPM2 source code needs a couple of additional options so that the compiler will know where to search for header files and library files when compiling/linking. On about line 60 you should see something like: make all SUF=dll    CC="gcc -mno-cygwin -O3 -funroll-loops -fomit-frame-pointer ... Within the double quotes of the CC= statement there may be a number of options like:    -I/some/path or -L/some/path it is probably safe to remove these defaults and insert the following: -DMINGWPIDT -I./ -I/cygdrive/c/mingw/include -L/cygdrive/c/mingw/lib -L/cygdrive/c/progra~1/matlab/r2007a/extern/lib/win32/micros~1

Step 3: Edit win32mmap.h

Open up the header file win32mmap.h in c:\spm2. On line 23 or so you should see: typedef int pid_t; but for our compilation we will use a pid_t definition from MinGW, so wrap this line in an #ifndef statement: #ifndef MINGWPIDT typedef int pid_t; #endif this will tell the compiler not to use pid_t from SPM's provided file if MINGWPIDT is defined (which it is, because of the -DMINGWPIDT option added to the Makefile).

Step 4: Compile

Startup Cygwin and change directories to the SPM2 folder. Cygwin has a Unix like filesystem structure but maintains a list of drive-letter folders in /cygdrive so if you installed SPM2 in c:\spm2 then: user@localhost ~ $ cd /cygdrive/c/spm2

user@localhost /cygdrive/c/spm2 $ make windows If you need to recompile it's best that you 'clean' the build environment, that is, delete temporary and intermediate files left behind by the last call to 'make'. You can do so with: user@localhost /cygdrive/c/spm2 $ rm *.o; rm *.a; rm *.dll Hopefully all went well and you didn't get any errors, you should now have a working set of dll files for SPM2.