Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

compiling on windows #3

Open
wants to merge 15 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 73 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# mwrapdemo: simple MWrap examples

Alex Barnett 7/31/15-8/3/15
Alex Barnett 7/31/15-8/3/15
compiling for Windows: Ralf Hambach 04/03/16

[MWrap](http://www.cs.cornell.edu/~bindel/sw/mwrap/) is a super-useful code by David Bindel that turns the horrible pain of writing a MEX interface into a quick automatic procedure. To quote Bindel's introduction,

Expand All @@ -11,12 +12,26 @@ The present project contains simple, minimally complete examples showing how to
### Dependencies

[MATLAB](http://www.mathworks.com/products/matlab)
C and Fortran compilers supporting C99 and OpenMP.
C and Fortran compilers supporting C99 and OpenMP.
If you are on a Mac system, you need Xcode to use MEX.
GNU make.
GNU make (Linux, Mac) or NMAKE (Windows).
Optional: [MWrap](http://www.cs.cornell.edu/~bindel/sw/mwrap/), although a distribution of MWrap is also included in this repository.

### Getting started

### Contents of this repository

`c/` - simple single-thread C example, 1D array, complex, and a Boolean
`c2domp/` - 2D array, multi-thread OpenMP C example
`f/` - simple single-thread Fortran example, 1D array, complex, and a Boolean
`f2domp/` - 2D array, multi-thread OpenMP Fortran example
`testall.m` - MATLAB script to run all demos
`makefile` - top-level makefile to compile all demos (use `Makefile.win` on Windows)
`make.inc.example` - system-specific makefile settings (adapt `make.inc.win` on Windows)
(copy to `make.inc` and edit that rather than changing this distributed file)
`mwrap-0.33.3/` - modiefied version 0.33 of MWrap (you may want to check Bindel's page for a later version). If you don't use this, then you'll need to change the `MWRAP` variable in `make.inc` to the location of your `mwrap` executable.


### Getting started (Linux,Mac)

Download this repository either via `git clone` or as zip archive, to a linux or Mac machine. Then

Expand All @@ -37,19 +52,8 @@ See the README files in each of the directories for more information.

To remove generated/compiled objects, type `make clean` from the top level directory.

### Contents of this repository

`c/` - simple single-thread C example, 1D array, complex, and a Boolean
`c2domp/` - 2D array, multi-thread OpenMP C example
`f/` - simple single-thread Fortran example, 1D array, complex, and a Boolean
`f2domp/` - 2D array, multi-thread OpenMP Fortran example
`testall.m` - MATLAB script to run all demos
`makefile` - top-level makefile to compile all demos
`make.inc.example` - system-specific makefile settings
(copy to `make.inc` and edit that rather than changing this distributed file)
`mwrap-0.33.3/` - version 0.33 of MWrap included for convenience (you may want to check Bindel's page for a later version). If you don't use this, then you'll need to change the `MWRAP` variable in `make.inc` to the location of your `mwrap` executable.

### My usage notes for MWrap
#### My usage notes for MWrap

* The makefiles I include contain useful compilation flags.
* Function names cannot use _ (underscore), even though this is allowable in MATLAB, C, and Fortran. It will fail in a non-informative way if you try this.
Expand All @@ -58,13 +62,64 @@ To remove generated/compiled objects, type `make clean` from the top level direc
* Text output from Fortran `write(*,*)` doesn't seem to make it to the MATLAB terminal, unlike C stdout which does, at least when MATLAB is run with `-nodesktop`. mexPrintf is clumsy but works (see `f/lib.f`).
* The Mac OSX flags require some tweaking: `-lgfortran` may need to be removed. Currently we have problems with `write` in Fortran. Also it seems Xcode doesn't even support OpenMP, so apparently Mac users wanting this will have to install gcc and adjust `mexopts.sh` to point mex to this compiler.



### Getting started (Windows)

Download this repository either via `git clone` or as zip archive, to a Windows machine. Then

1. Install Bison/Flex (only needed, if you want to compile MWrap yourself)
* download [Win-flex-bison package](http://sourceforge.net/projects/winflexbison/), version 2.4.5/2.5.5
* extract files to some arbitrary path `<WINFLEXBISONPATH>`
* add installation path to windows PATH environment variable

1. Install MWrap. For example use the local distribution of Mwrap (modified version 0.33.3):
* open power shell and cd to `mwrap-0.33.3/`
* adapt `make.inc.win`;
* run `nmake /C /f Makefile.win`
* run `nmake /C /f Makefile.win test`

1. Check examples in directory `c/` and `c2omp`
* copy `make.inc.example` to `make.inc`. Type `mex` from the command line; you should get something like `mex: nofile name given.` and something mentioning MATLAB. If you don't, then you need to find the path to your mex executable then edit `make.inc` to make the variable `MEX` point to your mex executable.
* cd to the directory `c/` and run `nmake /C /f Makefile.win`
* cd to the directory `c2omp/` and run `nmake /C /f Makefile.win`
* open MATLAB and run `test` from the two directories (Fortran tests not yet implemented under Windows)

#### Comments

* The C-header `<complex.h>` is not available for MVS/SDK7.1 compiler. It has to be replaced by the C++ version `<complex>` and the C++ compiler has to be used throughout.
* The CL-compiler envokes the C or C++ compiler according to the file extension (C-code: `.C`; C++-code: `.cc,.cpp`). This behavior can be overwritten using the command line options (`/Tc` and `/Tp`).
* MVS/SDK7.1 does not include OpenMP. Use Microsoft Visual Studio C/C++ Compiler instead.
* NMAKE has a problem to handle path names with spaces, you will typically get an error `"C:\Program" not found`
* Many linker errors are due to C-style binding which is built into flex routines (requires `extern "C"` statements to enforce C symbol names although we use a C++ compiler to include `<complex>`. To investigate `*.obj` files for the actual symbol names, use `dumpbin /symbols file.obj` (see [dumpbin tutorial](https://support.microsoft.com/en-us/kb/177429))
* If you have several Matlab versions installed (e.g. 32bit and 64bit), care must be taken to call the right mex-compiler and setup the environment variables correctly (always use the full name to the mex-compiler):
```
"C:\Program Files (x86)\MATLAB\R2014b\mex" -setup C++ # 32bit
"C:\Program Files\MATLAB\R2014b\mex" -setup C++ # 64bit
```
* specify the command-line-options file explicitely if compilation still fails
```
"C:\Program Files (x86)\MATLAB\R2014b\mex" -setup:%APPDATA%\MathWorks\MATLAB\R2014b\mex_C++_win32.xml # 32bit
"C:\Program Files\MATLAB\R2014b\mex" -setup:%APPDATA%\MathWorks\MATLAB\R2014b\mex_C++_win64.xml # 64bit
```
* The examples in the MWrap distribution do not yet use mxIndex, mxSize types. This leads to many compiler warnings, if `/W4` is enabled
```
> mex -v COMPFLAGS="$COMPFLAGS /W4" test_transfers.cc
... warning C4267: '=' : conversion from 'size_t' to 'int', possible loss of data
```

### Other projects showing how to use MWrap

[fmmlib2d](http://www.cims.nyu.edu/cmcl/fmm2dlib/fmm2dlib.html) - Fortran, with makefile for a variety of environments
[fmmlib2d](http://www.cims.nyu.edu/cmcl/fmm2dlib/fmm2dlib.html) - Fortran, with makefile for a variety of environments
[lhelmfs](https://math.dartmouth.edu/~ahb/software/lhelmfs.tgz) - C, Linux environment

### To do list

* Set up flags on Mac and get `write` working there
* Check this on Windows system; include makefiles







14 changes: 8 additions & 6 deletions c/README
Original file line number Diff line number Diff line change
@@ -1,23 +1,25 @@
Very simple MWrap demo for interfacing MATLAB to a C library via MEX.
Very simple MWrap demo for interfacing MATLAB to a C++ library via MEX.
Shows 1d arrays, complex numbers and Boolean.
Barnett 7/30/15

To build the interface:
make
make # (Linux/Mac)
nmake /C /f Makefile.win # (Windows)

Test script to run from a MATLAB shell:
test

To clean up this directory:
make clean
make clean # (Linux/Mac)
nmake /C /f Makefile.win clean # (Windows)

Notes:

Running the makefile does this:
1) compiles the lib.c library into lib.o
2) uses MWrap to read demo.mw and auto-generate gateway.c and myfunc.m
1) compiles the lib.cc library into lib.o
2) uses MWrap to read demo.mw and auto-generate gateway.cc and myfunc.m
(it's worth looking at these two files for education purposes only)
3) calls the MEX compiler to compile gateway.c and link to lib.o to
3) calls the MEX compiler to compile gateway.cc and link to lib.o to
give the MEX executable object gateway.mexa64 (for instance)
In the MWrap documentation "gateway" is called "outputmex".

Expand Down
6 changes: 4 additions & 2 deletions c/demo.mw
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
% MWrap file for C demo. Generates gateway.c and myfunc.m
% MWrap file for C++ demo. Generates gateway.cc and myfunc.m
% Following is augmented MATLAB code, ie there are special lines beginning with
% the @ and # symbols.

$ #include "lib.hh"

@function [y z]=myfunc(x,w,flag)
% MYFUNC minimal function for MWrap demo
%
Expand All @@ -22,7 +24,7 @@ flag = double(flag); % crucial even though it's int type in C
% Code for calling the C function, using same variable names as for MATLAB.
% Notes: 1) there is a trailing semicolon
% 2) For dcomplex I have had more success with inout than inputs or outputs.
# myfunc(int N, double[] x, output double[N] y, inout dcomplex[] w, int flag);
# myfunc(mwSize N, double[] x, output double[N] y, inout dcomplex[] w, int flag);

% do any MATLAB postprocessing here
z = w;
Expand Down
8 changes: 4 additions & 4 deletions c/lib.c → c/lib.cc
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
/* minimal C library for MWrap demo. Barnett 7/30/15 */
/* minimal C++ library for MWrap demo. Barnett 7/30/15 */

#include <math.h>
#include <complex.h>
#include <stdio.h>
#include "lib.hh"

void myfunc(int n, double* in, double* out, double complex *z, int flag)
void myfunc(mwSize n, double* in, double* out, std::complex<double> *z, int flag)
/* Just computes sin of a list of doubles, and squares a complex number,
and prints the value of flag.
Notes: * usual 0-indexing even though MATLAB was 1-indexed
* names don't have to match those in demo.mw
*/
{
int i;
mwIndex i;
for (i=0;i<n;++i)
out[i] = sin(in[i]);
z[0] = z[0]*z[0];
Expand Down
6 changes: 6 additions & 0 deletions c/lib.hh
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/* minimal C++ library for MWrap demo. Barnett 7/30/15 */

#include <complex>
#include <matrix.h>

void myfunc(mwSize n, double* in, double* out, std::complex<double> *z, int flag);
12 changes: 6 additions & 6 deletions c/makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,19 @@ include ../make.inc
default: mexfile

# How to compile your C library function: (-fPIC is needed for linking to MEX)
lib.o: lib.c makefile
$(CC) -fPIC -O3 -c lib.c
lib.o: lib.cc makefile
$(CC) -fPIC -O3 -c lib.cc

# Tell mwrap to make the interface and the name of the final MEX file:
# Note: -c99complex assumes usual C complex numbers (see MWrap docs)
gateway.c: demo.mw makefile
$(MWRAP) -c99complex -mex gateway -mb -list demo.mw
$(MWRAP) -c99complex -mex gateway -c gateway.c demo.mw
$(MWRAP) -c99complex -mex gateway -c gateway.cc demo.mw

# How to make MATLAB/MEX compile the interface (whatever libs needed):
mexfile: gateway.c lib.o makefile
$(MEX) gateway.c lib.o -largeArrayDims -lm
mexfile: gateway.cc lib.o makefile
$(MEX) gateway.cc lib.o -largeArrayDims -lm

# Remove the MEX interface, MATLAB caller, and MEX file:
clean:
rm -f myfunc.m gateway.c *.o *.mex* *~
rm -f myfunc.m gateway.cc *.o *.mex* *~
59 changes: 59 additions & 0 deletions c/makefile.win
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#-------------------------------------------------------------------------
# NMAKE-Makefile for interfacing to a C++ library
# Barnett 7/30/15 modified by Hambach
#-------------------------------------------------------------------------

!INCLUDE <../make.win.inc>

#-------------------------------------------------------------------------
# Main-Targets
#-------------------------------------------------------------------------

all: mex_setup mexfile
@echo .
@echo Compilation successful. Run Matlab to test the Mexfile
@echo MATLABROOT\matlab -nosplash -nodesktop -r test

#-------------------------------------------------------------------------
# Sub-Targets
#-------------------------------------------------------------------------

# first setup the MEX compiler
# Note: if setup/linking fails, set command-line-options file explicitly
# $(MEX) -setup:$(APPDATA)\MathWorks\MATLAB\R2014b\mex_C++_win32.xml

mex_setup:
@echo -------------------------------------------------------------
@echo 1. MEX Setup
@echo -------------------------------------------------------------
$(MEX) -setup C++

# then pre-compile C-library
# (we use MEX compiler to avoid -fPIC and other flag compatibility issues)

lib.obj: lib.cc
@echo -------------------------------------------------------------
@echo 2. Compile lib.cc
@echo -------------------------------------------------------------
$(MEX) $(MEXFLAGS) -c $**

# then use mwrap to make the interface and the name of the final MEX file
# Note: -cppcomplex needed as C99 complex numbers are not available in SDK7.1

gateway.cc: demo.mw
@echo -------------------------------------------------------------
@echo 3. Create Interface using MWrap
@echo -------------------------------------------------------------
$(MWRAP) $(MWRAP_FLAGS) -mex gateway -mb -list demo.mw
$(MWRAP) $(MWRAP_FLAGS) -mex gateway -c gateway.cc demo.mw

# finally compile and link the interface with MEX (whatever libs needed)
mexfile: lib.obj gateway.cc
@echo -------------------------------------------------------------
@echo 4. Compile interface + Link
@echo -------------------------------------------------------------
$(MEX) $(MEXFLAGS) $**

# Remove the MEX interface, MATLAB caller, and MEX file:
clean:
-erase myfunc.m gateway.cc *.obj *.mex*
14 changes: 8 additions & 6 deletions c2domp/README
Original file line number Diff line number Diff line change
@@ -1,23 +1,25 @@
Simple MWrap demo for interfacing MATLAB to a C library via MEX with OpenMP.
Simple MWrap demo for interfacing MATLAB to a C++ library via MEX with OpenMP.
Barnett 7/30/15

To build the interface:
make
make # (Linux/Mac)
nmake /C /f Makefile.win # (Windows)

Test script to run from a MATLAB shell:
test

To clean up this directory:
make clean
make clean # (Linux/Mac)
nmake /C /f Makefile.win clean # (Windows)

Notes:

Running the makefile does this:
1) compiles the lib.c library into lib.o
2) uses MWrap to read demo.mw and auto-generate gateway.c, array2d.m and
1) compiles the lib.cc library into lib.o
2) uses MWrap to read demo.mw and auto-generate gateway.cc, array2d.m and
array2domp.m (it's worth looking at these two files for education purposes
only)
3) calls the MEX compiler to compile gateway.c and link to lib.o to
3) calls the MEX compiler to compile gateway.cc and link to lib.o to
give the MEX executable object gateway.mexa64 (for instance)
In the MWrap documentation "gateway" is called "outputmex".

Expand Down
6 changes: 4 additions & 2 deletions c2domp/demo.mw
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
% MWrap file for C demo w/ OpenMP.
% Generates gateway.c, array2d.m and array2domp.m.
% MWrap file for C++ demo w/ OpenMP.
% Generates gateway.cc, array2d.m and array2domp.m.
% Illustrates inout type, and multiple interfaces in a single gateway.
% First see ../c/demo.mw on which this example builds.

$ #include "lib.hh"

% --------------------------------------------------------------------------
@function y=array2d(x,reps)
% ARRAY2D compute iterated sin of all elements of a 2D array
Expand Down
3 changes: 2 additions & 1 deletion c2domp/lib.c → c2domp/lib.cc
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
/* minimal C library showing openmp and overwriting arrays. Barnett 7/30/15 */
/* minimal C++ library showing openmp and overwriting arrays. Barnett 7/30/15 */

#include <math.h>
#include <omp.h>
#include <stdio.h>
#include "lib.hh"

void array2d(int n, double* a, int reps)
/* Computes iterated sin of a list of doubles, overwriting.
Expand Down
7 changes: 7 additions & 0 deletions c2domp/lib.hh
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/* minimal C++ library for MWrap demo. Barnett 7/30/15 */

#include <complex>
#include <matrix.h>

void array2d(int n, double* a, int reps);
void array2domp(int n, double* a, int reps);
14 changes: 7 additions & 7 deletions c2domp/makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,19 @@ include ../make.inc
default: mexfile

# How to compile your C library function: (-fPIC is needed for linking to MEX)
lib.o: lib.c makefile
$(CC) -fPIC -O2 -fopenmp -c lib.c
lib.o: lib.cc makefile
$(CC) -fPIC -O2 -fopenmp -c lib.cc

# Tell mwrap to make the interface and the name of the final MEX file:
# (note -mb here makes separate .m file for each @ function in the .mw)
gateway.c: demo.mw makefile
gateway.cc: demo.mw makefile
$(MWRAP) -list -mex gateway -mb demo.mw
$(MWRAP) -mex gateway -c gateway.c demo.mw
$(MWRAP) -mex gateway -c gateway.cc demo.mw

# How to make MATLAB/MEX compile the interface (whatever libs needed):
mexfile: gateway.c lib.o makefile
$(MEX) gateway.c lib.o -largeArrayDims -lm -lgomp
mexfile: gateway.cc lib.o makefile
$(MEX) gateway.cc lib.o -largeArrayDims -lm -lgomp

# Remove the MEX interface, MATLAB caller, and MEX file:
clean:
rm -f array2d.m array2domp.m gateway.c *.o *.mex* *~
rm -f array2d.m array2domp.m gateway.cc *.o *.mex* *~
Loading