Using GCC (MinGW) as MATLAB's MEX compiler

Why not adjust the mexopts.bat file in your directory? That way you can use the "mex" command transparently to compile anything, as usual in MATLAB, the same as if it was configured by MATLAB using mex -setup. I'm surprised nobody did this before.

The file below is for x64 version of Matlab and Mingw. I'm using the TDM Mingw64 distribution, which I installed in p:\mingw64-tdm. I have Matlab installed in p:\matlab\R2012a -- edit those accordingly.

This is the mexopts.bat file I'm using, copy paste this in %USERPROFILE%\AppData\Roaming\MathWorks\MATLAB\R2012a\mexopts.bat:

@echo off

set MINGWPATH=p:\mingw64-tdm
set PATH=%MINGWPATH%\bin;%PATH%

set COMPILER=gcc
set COMPFLAGS=-c -m64 -I"%MATLAB%\extern\include" -DMATLAB_MEX_FILE -Wall -std=c99
set OPTIMFLAGS=-O3 -DNDEBUG
set DEBUGFLAGS=-g
set NAME_OBJECT=-o

set LINKER=gcc
set LINKFLAGS=-shared -L"%MATLAB%\bin\win64" -L"%MATLAB%\extern\lib\win64\microsoft" -lmex -lmx -leng -lmat -lmwlapack -lmwblas
set NAME_OUTPUT=-o "%OUTDIR%%MEX_NAME%%MEX_EXT%"

Then you can just try doing this in Matlab:

mex -v p:\matlab\R2012a\extern\examples\mex\yprime.c
which yprime

Should yield b:\code\m\yprime.mexw64 (or whatever the current folder is). Then if you do:

yprime(1,1:4)

You should see:

ans =
    2.0000    8.9685    4.0000   -1.0947

Which means you're in business. Good luck!

EDIT Oct 2014: I now use an improved mexopts.bat file than the above with a different MinGW64 (yields slightly faster binary code than TDM's). See my homepage for details and downloads.


In Matlab 2011b, just compile and link directly in mingw64 or cygwin environment.

MINGWPATH=c:/MinGW64
CYGPATH=c:/cygwin

MATLABROOT=c:/Progra~1/MATLAB/R2011b
CC=$(MINGWPATH)/bin/x86_64-w64-mingw32-gcc 
CFLAG= -Wall -m64 -O3 -I$(MATLABROOT)/extern/include $(SRC) $(LIBS) -o $(EXE)
MEXFLAG=-m64 -shared -DMATLAB_MEX_FILE -I$(MATLABROOT)/extern/include -Wl,--export-all-symbols $(LIBS) $(MEXSRC) -o $(MEXTGT).mexw64

LIBS= -L$(MATLABROOT)/bin/win64 -L$(MATLABROOT)/extern/lib/win64/microsoft -lmex -lmx -lmwlapack -lmwblas -leng
EXE=../bin/engwindemo.exe
MEXTGT=
SRC=engwindemo.c
MEXSRC=
all:$(EXE)

$(EXE):  $(SRC)
    $(CC) $(CFLAG) -ladvapi32 -luser32 -lgdi32 -lkernel32 -lmingwex -o $(EXE)
    @rm -f *.o*

$(MEXTGT):  $(MEXSRC)
    $(CC) $(MEXFLAG) -ladvapi32 -luser32 -lgdi32 -lkernel32 -lmingwex 
    @rm -f *.o*

Put this makefile on the source code directory and make. No dll files conversion needed.


As of MATLAB R2015b, MinGW is officially supported!

It's now at the top of the list of supported compilers.

See here for the official instructions for downloading MinGW (they recommend TDB-GCC).

There are several limitations and caveats listed (e.g. don't link with libraries compiled with other compilers, you have to catch your exceptions inside the MEX file, etc.).

Below is my old way of making an XML file to do the same thing.


The years have gone by and MATLAB (as of R2014a) has moved to a new XML-based system for configuring MEX files. MATLAB still temporariily supports legacy .bat files, for now, but it will bother you about it. Another change is that are distinct C and C++ configurations (more later).

What has stayed the same is that you just need to download and extract a MinGW distribution and point MATLAB to it. There is still no need for MSYS, cygwin or gnumex. The only tricky part is pointing MATLAB to it, but here is a solution.

Short Version

  • Download and extract a MinGW distribution. Pick one, such as MinGW-w64 (64-bit) or TDM-GCC (32-bit and 64-bit options).
  • Customize the XML config file, using this one as a template (details in long version below).
  • Set MINGWROOT environment variable.
  • Run mex -setup:[xmlfile] [C|C++].

Long Version

For MinGW-w64, I do the following to set it up:

  1. Grab the latest revision for w64 from Sourceforge (or use the installer to choose the toolchain you want, picking a pthread or Win32 threads version depending on your needs).
  2. Extract it so that you have a path to the compiler like C:\mingw-w64\x86_64-4.9.2-release-posix-seh-rt_v3-rev1\bin\x86_64-w64-mingw32-g++.exe. There is no need for MSYS, cygwin, or any other environment if you plan on compiling in MATLAB with the mex command. Check your PATH environment variable to make sure you don't have multiple compilers (g++) on your path, preferably none. Verify with a fresh command prompt.
  3. Set it up with a custom XML configuration file. On my GitHub repo, I have posted C++ configurations for MinGW-w64 in both file types: mex_C++_mingw-w64.xml and legacy mingw_mexopts.bat. Start with that as a template and (optionally) edit the XML file with a descriptive name and version of the MinGW distribution you downloaded and extracted.
  4. Set (or create) the MINGWROOT environment variable. This is what allows the mex command to locate the compiler. You can do this in MATLAB (and every time MATLAB starts with a startup.m script in userpath) with setenv, or just once with the Windows properties dialog or the native Windows 7 setx.exe command.
  5. Run mex -setup:C:\actual\configFilePath.xml C++. For example, using the .xml file to set up C++ MEX file compilation:

    setenv('MINGWROOT','H:\mingw-w64\x86_64-4.9.2-release-posix-seh-rt_v3-rev1')
    mex -setup:H:\building\GitHub\MATLAB\MinGW\mex_C++_mingw-w64.xml C++
    

    The output should look like this:

    MEX configured to use 'MinGW-w64 GCC 4.9.2 posixthreads seh' for C++ language compilation.

If needed, set up the C compiler in a similar manner with a new XML config file specifying the C language, the C compiler frontend (e.g. "x86_64-w64-mingw32-gcc.exe" which won't automatically link the C++ standard library), adjust the link libraries as needed, compiler flags (e.g. change -std=c++11 to -std=c99), etc.


Note about static vs. dynamic linking of runtime libraries

Libraries such as a MEX file created with MinGW-w64 as above may depend on a few DLLs (at runtime): LIBGCC_S_SEH-1.DLL (for the seh exception distributions) and LIBSTDC++-6.DLL, and possibly libwinpthread-1.dll if you chose a pthreads distribution instead of Win32 threads. If you don't want to copy these files around, you can statically link the runtime libraries into your MEX file by adding the following switches:

-static-libgcc -static-libstdc++

There's a comment in the XML template about this. See here for info about libpthread-1.dll.

With TDM-GCC, the opposite is true: the runtimes (including pthread) are statically linked automatically. To link dynamically, which will require the DLLs but reduce your MEX file size, you need:

-shared-libgcc -shared-libstdc++

EDIT: There seems to be a much better way with MinGW; see my other answer.

You can compile a .mex file using gcc if you have Matlab installed, from the command line. Some might say it's a little tedious the first time.

First things first - what Matlab do you use? if it's 64-bits, MinGW won't help you, because it's 32-bit. I will therefore show how to use MinGW-w64 instead. Understanding how to do this with 32-bit MinGW should be straightforward.

  1. Add C:\MinGW-64\bin\ to your path. You won't regret this :)
  2. Compile your .c files using gcc:

    x86_64-w64-mingw32-c++ -m64 -shared -I"C:\Program Files\MATLAB\R2010b\extern\include" -o bla.mexw64 -DMATLAB_MEX_FILE -Wl,--export-all-symbols *.cpp
    
  3. This will result in a bunch of linker errors, such as

    undefined reference to `mexErrMsgTxt'
    

    To solve this problem, you'll have to create an import library which connects with libmex.dll, libmx.dll, libmat.dll and libeng.dll (you might have others, but these are the main ones)

  4. List the functions you're missing, and, well, guess what dll they're coming from. Hint: mexErrMsgTxt is from libmex.dll, because it starts with "mex"...

  5. For every dll you need to export, create a .def file containing

    EXPORTS
    ... relevant function names go here, such as mexErrMsgTxt, matOpen, etc.
    
  6. Execute the following command, to create import libraries:

    x86_64-w64-mingw32-dlltool -d libmx.def --dllname libmx.dll -l libmx.a
    

    (Same for the rest of the .def files)

  7. Now you're good to go!

    x86_64-w64-mingw32-c++ -m64 -shared -I"C:\..." -DMATLAB_MEX_FILE -o bla.mexw64 -Wl,--export-all-symbols *.cpp libmex.a libmx.a libmat.a libeng.a
    

Things which can be done better - instead of --export-all-symbol, only export mexFunction (requires creating another .def file, or adding "__declspec(dllexport)" before void mexFunction(...)).