matlab - support - mingw standalone
Usando GCC(MinGW) como compilador MEX de MATLAB (13)
Me dieron un proyecto para ejecutar en MATLAB R2011a. Como hay varios archivos .c allí, necesito configurar GCC como el compilador MEX para ese proyecto. Sin embargo, no puedo encontrar ninguna explicación sobre cómo configurarlo. Probé un programa de script llamado gnumex, pero falló (probablemente configurado para una versión anterior de MATLAB).
¿Alguna idea de cómo configurarlo?
A partir de MATLAB R2015b, MinGW es oficialmente compatible.
Ahora está en la parte superior de la lista de compiladores compatibles .
Vea aquí las instrucciones oficiales para descargar MinGW (recomiendan TDB-GCC).
Hay varias limitaciones y advertencias enumeradas (p. Ej., No se vincula con bibliotecas compiladas con otros compiladores, tiene que detectar sus excepciones dentro del archivo MEX, etc.).
A continuación se muestra mi antigua forma de hacer un archivo XML para hacer lo mismo.
Los años han pasado y MATLAB (a partir de R2014a) se ha movido a un nuevo sistema basado en XML para configurar archivos MEX. MATLAB todavía soporta temporariamente archivos legacy .bat, por ahora, pero le molestará al respecto . Otro cambio es que son distintas configuraciones de C y C ++ (más adelante).
Lo que ha quedado igual es que solo necesita descargar y extraer una distribución MinGW y señalarle MATLAB. Todavía no hay necesidad de MSYS, cygwin o gnumex. La única parte difícil es apuntar a MATLAB, pero aquí hay una solución.
Version corta
- Descargue y extraiga una distribución MinGW. Seleccione uno, como MinGW-w64 (64 bits) o TDM-GCC (opciones de 32 bits y 64 bits).
- Personalice el archivo de configuración XML, usando este como plantilla (detalles en la versión larga a continuación).
- Establezca la variable de entorno
MINGWROOT
. - Ejecute
mex -setup:[xmlfile] [C|C++]
.
Versión larga
Para MinGW-w64, hago lo siguiente para configurarlo:
- MinGW-w64 la MinGW-w64 (o use el instalador para elegir la cadena de herramientas que desee, seleccionando una versión pthread o Win32 de subprocesos según sus necesidades).
- Extraelo para que tenga una ruta al compilador como
C:/mingw-w64/x86_64-4.9.2-release-posix-seh-rt_v3-rev1/bin/x86_64-w64-mingw32-g++.exe
. No es necesario MSYS, cygwin ni ningún otro entorno si planea compilar en MATLAB con el comandomex
. Comprueba laPATH
entornoPATH
para asegurarte de que no tienes múltiples compiladores (g++
) en tu ruta, preferiblemente ninguno. Verificar con un nuevo símbolo del sistema. - Configúrelo con un archivo de configuración XML personalizado. En mi repositorio de GitHub, publiqué las configuraciones de C ++ para MinGW-w64 en ambos tipos de archivos: mex_C ++ _ mingw-w64.xml y legacy mingw_mexopts.bat . Comience con eso como una plantilla y (opcionalmente) edite el archivo XML con un nombre descriptivo y la versión de la distribución MinGW que descargó y extrajo .
- Establezca (o cree) la variable de entorno
MINGWROOT
. Esto es lo que permite al comandomex
ubicar el compilador. Puede hacer esto en MATLAB (y cada vez que MATLAB comience con una secuencia de comandosstartup.m
en lauserpath
deuserpath
) consetenv
, o solo una vez con el cuadro de diálogo de propiedades de Windows o el comando nativo de Windows 7 setx.exe . Ejecute
mex -setup:C:/actual/configFilePath.xml C++
. Por ejemplo, utilizando el archivo .xml para configurar la compilación de archivos C ++ MEX: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++
La salida debería verse así:
MEX configurado para usar ''MinGW-w64 GCC 4.9.2 posixthreads seh'' para la compilación del lenguaje C ++.
Si es necesario, configure el compilador de C de manera similar con un nuevo archivo de configuración XML que especifique el lenguaje C, el frontend del compilador C (por ejemplo, "x86_64-w64-mingw32-gcc.exe" que no vinculará automáticamente la biblioteca estándar de C ++ ), ajuste las bibliotecas de enlaces según sea necesario, indicadores del compilador (por ejemplo, change -std=c++11
to -std=c99
), etc.
Nota sobre el enlace estático vs. dinámico de las bibliotecas de tiempo de ejecución
Las bibliotecas como un archivo MEX creado con MinGW-w64 como el anterior pueden depender de unos pocos archivos DLL (en tiempo de ejecución): LIBGCC_S_SEH-1.DLL (para las distribuciones de excepción seh) y LIBSTDC ++ - 6.DLL, y posiblemente libwinpthread-1.dll si elige una distribución pthreads en lugar de hilos Win32. Si no desea copiar estos archivos, puede vincular estáticamente las bibliotecas de tiempo de ejecución en su archivo MEX agregando los siguientes modificadores:
-static-libgcc -static-libstdc++
Hay un comentario en la plantilla XML sobre esto. Consulte here para obtener información sobre libpthread-1.dll.
Con TDM-GCC, lo contrario es cierto : los tiempos de ejecución (incluido pthread) se vinculan de forma estática automáticamente. Para vincular dinámicamente, lo que requerirá las DLL pero reducirá el tamaño de su archivo MEX, necesita:
-shared-libgcc -shared-libstdc++
Éste funciona en Matlab 2012b bajo Windows 8:
https://github.com/DynareTeam/dynare/blob/master/windows/mexopts-win64.bat
Modifique el directorio cgwin o reemplácelo con el directorio mingw si se usa. También puede cambiar el compilador-exe si cambia a una versión de 64 bits.
¿Por qué no ajustar el archivo mexopts.bat en su directorio? De esta forma, puede usar el comando "mex" de forma transparente para compilar cualquier cosa, como es habitual en MATLAB, de la misma manera que si MATLAB lo configurara con el sistema mex -setup
. Me sorprende que nadie haya hecho esto antes.
El siguiente archivo es para la versión x64 de Matlab y Mingw. Estoy usando la distribución TDM Mingw64 , que instalé en p:/mingw64-tdm
. Tengo instalado Matlab en p:/matlab/R2012a
- edítelos en consecuencia.
Este es el archivo mexopts.bat que estoy usando, copie y pegue esto en %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%"
Entonces puedes intentar hacer esto en Matlab:
mex -v p:/matlab/R2012a/extern/examples/mex/yprime.c
which yprime
Debería generar b:/code/m/yprime.mexw64
(o cualquiera que sea la carpeta actual). Entonces si lo haces:
yprime(1,1:4)
Debería ver:
ans =
2.0000 8.9685 4.0000 -1.0947
Lo que significa que estás en el negocio. ¡Buena suerte!
EDITAR Oct 2014: ahora uso un archivo mejorado de mexopts.bat que el anterior con un MinGW64 diferente (produce un código binario ligeramente más rápido que los TDM). Ver mi página de inicio para más detalles y descargas.
¿Por qué tantos pasos? Si tiene Matlab 2016 o superior , solo haga lo siguiente:
- Descargue mingw e instálelo en una carpeta sin espacios (es decir, no en "Archivos de programa")
- Agregue la variable de entorno
MW_MINGW64_LOC
que apunta a la carpeta de instalación (exactamente lo mismo que escribió en el instalador) - Reinicia tu PC
- Abra MATLAB y escriba
mex -setup
en la consola. Debería decir "configurado para usar MinGW" - Ejecute / compile su programa MATLAB
¡He probado estos en una nueva PC con Windows 10 y funciona!
En Linux, si escribe mex -setup
, puede elegir el compilador.
En Windows, debe intentar instalar lcc, puede hacerlo, por ejemplo, instalando Microsoft Visual Studio Express, que es gratis.
En Matlab 2011b, simplemente compile y vincule directamente en mingw64 o 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*
Pon este makefile en el directorio del código fuente y make
. No se necesita conversión de archivos dll.
En Windows 64 bit con R2011a funcionó con http://tdm-gcc.tdragon.net/ y http://gnumex.sourceforge.net/ pero tengo que cambiar la entrada de línea de GM_ADD_LIBS
siguiente manera:
rem Add path to where dlls are:
set DLL_PATH="C:/Program Files/MATLAB/R2011a/bin/win64"
rem Add every dll needed:
set GM_ADD_LIBS=%DLL_PATH%/libmx.dll %DLL_PATH%/libmex.dll %DLL_PATH%/libmat.dll
Me tomó mucho tiempo llegar a este punto, buena suerte.
Este es un tutorial detallado de esta respuesta . Por lo tanto, todo el crédito debería ir a esa respuesta .
1 Instale MinGW-w64:
1.1 Descargue esta compilación MinGW64-w64 y su actualización:
1.2 Instalar (descomprimir) los archivos descargados:
1.2.1 Descomprime el archivo de compilación y mueve la carpeta mingw64/
resultante en c:/
1.2.2 Descomprimir y copiar (sobrescribir) el archivo de actualización en c:/mingw64
1.3 Agregue C:/mingw64/bin
a la variable Path:
set PATH=C:/mingw64/bin;%PATH%
2 En una línea de comandos (fuera del entorno de Matlab), compile sus archivos * .c: por ejemplo, CCODEFILE.c
(suponiendo que Matlab 2012b se instaló en la carpeta C:/Program Files/MATLAB/R2012b/
):
"c:/mingw64/bin/x86_64-w64-mingw32-g++.exe" -m64 -shared -I"C:/Program Files/MATLAB/R2012b/extern/include" -DMATLAB_MEX_FILE -o CCODEFILE.mexw64 -Wl,--export-all-symbols CCODEFILE.c -L"C:/Program Files/MATLAB/R2012b/bin/win64" -lmex -lmx -leng -lmat
3 Luego, cualquier código de Matlab debería funcionar bien cuando llame a la función CCODEFILE
.
Matlab se vincula a un código externo (C ++, Fortran, Java, etc.) utilizando archivos MEX. ( http://gnumex.sourceforge.net/ )
Configuración del compilador:
- Instale TDM-GCC ( compilador C ++
"C:/MinGW32/bin;"
) desde http://tdm-gcc.tdragon.net/download - Instale Cygwin (toolkit proporciona herramientas de Unix en la plataforma de Windows) de ( http://ptolemy.eecs.berkeley.edu/ptolemyII/ptII4.0/cygwin.htm ).
Descargar e instalarcygwingDevel.exe
- Obtenga el archivo gnumex a través de ( https://sourceforge.net/projects/gnumex ) y extraiga el gnumex en (
$MATLABHOME/gnumex
).
Donde$MATLABHOME
sería, por ejemplo (C:/Program Files/MATLAB/R2010a
) - Agregue este directorio (
$MATLABHOME/gnumex
) a la ruta de Matlab (File->Set Path
en Matlab).
Nota: Ejecute Matlab con privilegios de administrador. En Matlab, escriba
gnumex
en el prompt. Complete los caminos apropiados como;MinGW_Root = C: / MinGW32, Cygwin_Root = C: / cygwin
Haga ''
File->Save Config
'', luego haga clic en ''Make Options file
''. Salir de la ventana de configuración de gnumex.
Pruebas:
Copie mexopts.bat ( %AppData%/MathWorks/MATLAB/R2010a/mexopts.bat
) en el directorio de trabajo ( %UserProfile%/Documents/MATLAB
) para esta prueba.
En matlab, ejecute lo siguiente en el prompt;
mex -f mexopts.bat "C: / Archivos de programa / MATLAB / R2010a / extern / examples / mex / yprime.c"
%UserProfile%/Documents/MATLAB/yprime.mexw32
(%UserProfile%/Documents/MATLAB/yprime.mexw32
) cuando%UserProfile%/Documents/MATLAB/yprime.mexw32
;que yprime
Ejecútelo escribiendo Matlab prompt
>> yprime(1,1:4)
y vea si obtiene2.0000 8.9685 4.0000 -1.0947
.- Ahora solo copiamos mexopts.bat a
$MATLABHOME/bin
y debería funcionar desde cualquier lugar.
Matlab en la plataforma Linux:
En la solicitud de Linux, instale lo siguiente;
sudo apt-get install gcc g ++ gfortran
En Matlab, ejecute lo siguiente en el prompt;
mex-setup
Los archivos de opciones disponibles para Mex son:
**1**: /usr/local/MATLAB/R2012b/bin/mexopts.sh
: Seleccione la opción 1 . Para probar el funcionamiento, ejecute lo siguiente en el prompt de Matlab;mex "/usr/local/MATLAB/R2012b/extern/examples/mex/yprime.c"
yprime (1,1: 4)
En caso de que recibas la advertencia;
Warning: You are using gcc version "4.6.3-1ubuntu5)". The version
currently supported with MEX is "4.4.6".
For a list of currently supported compilers see:
http://www.mathworks.com/support/compilers/current_release/
En el prompt de Linux:
-
sudo apt-get install gcc-4.4 g++-4.4 gfortran-4.4
-
sudo gedit /usr/local/MATLAB/R2012b/bin/mexopts.sh
- Cambiar
''gcc''
a''gcc-4.4''
,''g++''
a''g++-4.4''
,''gfortran''
a''gfortran-4.4''
en todos los casos deCC = ''gcc''
,CXX = ''g++''
yFC = ''gfortran''
. - Guarda el archivo y cierra.
Originalmente pensé que esto sonaba como una forma de tortura, pero de acuerdo con la respuesta anterior de @ user10171136, en realidad me resultó bastante sencillo realizar una compilación cruzada para Windows mex desde Fedora Linux. Fedora tiene paquetes mingw y mingw64, entonces:
-
sudo yum install mingw64-gcc mingw64-gcc-c++
- Copiar desde Windows Matlab instale los directorios
extern/include
ybin/win64
(en realidad, es probable que solo necesite un subconjunto de los encabezados y un pequeño subconjunto de los archivoslibmat.dll libmex.dll libmx.dll
;libmat.dll libmex.dll libmx.dll
puede ser todo lo que necesita Puse estos dos directorios en un nuevo directorioR2010a-w64
en mi directorio Linux MATLAB existente, cambie los siguientes comandos apropiados para donde almacenó los encabezados y libs de Windows. - Hubo un problema con el que me encontré, que es que se necesitaba
matrix.h
enmatrix.h
y no estaba definido. Supongo quematrix.h
olvidó incluiruchar.h
? Trabajé con una directiva-include
; vea abajo. -
x86_64-w64-mingw32-gcc -m64 -shared -include uchar.h -I/opt/MATLAB/R2010a-w64/extern/include -DMATLAB_MEX_FILE -L/opt/MATLAB/R2010a-w64/bin/win64 -o bla.mexw64 bla.c -lmx -lmex
- (Es posible que necesite bibliotecas adicionales para vincular, por ejemplo, -lmat -leng -lm, etc.)
- Esto genera con éxito un archivo mex que es ejecutable bajo Windows Matlab para mi configuración. Hasta ahora solo he probado esto con programas C bastante simples.
Interesado en escuchar si esto suena razonable; No tengo mucha experiencia con la compilación cruzada.
Si no puede instalar Mingw-w64 con la barra de herramientas de complementos de Matlab2016b en Windows , puede usar esta solución alternativa. Tenga esto en cuenta que debe cambiar las rutas de acuerdo con sus rutas de instalación.
- El sitio web oficial de Mingw-w64 lo redirige al proyecto Win-builds , que es un administrador de paquetes para un conjunto de herramientas de desarrollo de código abierto. Entonces, primero necesita instalar Win-builds.
- Al instalar Win-builds, asegúrese de ingresar una ruta que no contenga ningún espacio, por ejemplo,
C:/Win-builds
. - Después de instalar Win-builds, solo presione el botón
Process
para instalar todos los paquetes donde Mingw-w64 se encuentre entre ellos. - Ahora que instaló Mingw-w64, necesita definir la variable de entorno
MW_MINGW64_LOC
que Matlab usa para detectar Mingw-w64 . - Para definir la variable de entorno, realice los siguientes pasos:
Panel de control / Sistema / Configuración avanzada del sistema / Avanzado / Variable de entorno / Variables de usuario para $ YOUR_USER_NAME / New
- Poner
Variable name = MW_MINGW64_LOC
yVariable value = C:/Win-builds
. Observe que Win-builds coloca todos los ejecutables enC:/Win-builds/bin
y al definir esta variable, Matlab escaneará automáticamente la carpetabin
de la ruta en busca degcc.exe
. - Ahora que instaló Mingw-w64 y definió la variable de entorno
MW_MINGW64_LOC
, es hora de compilar y probar el ejemplo yprime . Entonces inicie Matlab y escriba el siguiente comando (No olvide modificar la ruta en consecuencia):mex -v ''C: / Archivos de programa / MATLAB / R2016b / extern / examples / mex / yprime.c''
- Una instalación exitosa mostrará el siguiente mensaje:
MEX completado con éxito.
- Finalmente, puede probar su instalación escribiendo
yprime(1,1:4)
. La respuesta sería:ans = 2.0000 8.9685 4.0000 -1.0947
MinGW
es capaz de vincular directamente una DLL
; es decir, creará una especie de biblioteca de importación sobre la marcha al enlazar.
Esto significa que la compilación se puede realizar en un solo paso:
x86_64-w64-mingw32-c++ -m64 -shared -I"%MATLAB%/extern/include" -DMATLAB_MEX_FILE -o bla.mexw64 -Wl,--export-all-symbols *.cpp -L"%MATLAB%/bin/win64" -lmex -lmx -leng -lmat
EDITAR: parece haber una manera mucho mejor con MinGW; ver mi otra respuesta.
Puede compilar un archivo .mex
usando gcc
si tiene Matlab
instalado, desde la línea de comandos. Algunos podrían decir que es un poco tedioso la primera vez.
Lo primero es lo primero: ¿qué Matlab usas? si es de 64 bits, MinGW
no lo ayudará, porque es de 32 bits. Por lo tanto, mostraré cómo usar MinGW-w64 en MinGW-w64 lugar. Comprender cómo hacer esto con MinGW
32 bits debería ser sencillo.
- Agregue
C:/MinGW-64/bin/
a su ruta. No te arrepentirás :) Compila tus archivos
.c
usandogcc
: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
Esto dará como resultado un grupo de errores del enlazador, como
undefined reference to `mexErrMsgTxt''
Para resolver este problema, deberá crear una biblioteca de importación que se conecte con
libmex.dll
,libmx.dll
,libmat.dll
ylibeng.dll
(es posible que tenga otros, pero estos son los principales)Enumera las funciones que te faltan, y, bueno, adivina de qué provienen. Sugerencia:
mexErrMsgTxt
es delibmex.dll
, porque comienza con "mex" ...Por cada
dll
que necesite exportar, cree un archivo.def
que contengaEXPORTS ... relevant function names go here, such as mexErrMsgTxt, matOpen, etc.
Ejecute el siguiente comando para crear bibliotecas de importación:
x86_64-w64-mingw32-dlltool -d libmx.def --dllname libmx.dll -l libmx.a
(Lo mismo para el resto de los archivos
.def
)¡Ahora estás listo para partir!
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
Cosas que se pueden hacer mejor: en lugar de --export-all-symbol
, solo exporta mexFunction
(requiere crear otro archivo .def
o agregar " __declspec(dllexport)
" antes de void mexFunction(...)
).