Как сделать ссылку во время компиляции Matlab MEX
Я написал программу следующего вида:
#include "stuff_I_need.h"
int main(){
construct_array(); // uses OpenMP pragma's
print_array();
return(0);
}
который компилируется, связывается и работает правильно с помощью следующей команды:
`gcc44 -I/home/matteson/sundials/include/ main.c -lm -L/home/matteson/sundials/lib -lsundials_cvode -lsundials_nvecserial -fopenmp -o /home/matteson/MPI_test/CVODE_test/main_test`
"gcc44" - это просто gcc версии 4.4 и называется так, потому что он компилируется в кластере, который поддерживает несколько версий gcc. Библиотеки sundials_cvode и sundials_nvecserial используются при решении нескольких дифференциальных уравнений при построении массива.
Теперь, когда я хочу перейти на Matlab и попытаться скомпилировать mex-файл формы:
#include "stuff_I_need.h"
void mexFunction(int nlhs,mxArray* plhs[], int nrhs, const mxArray* prhs[]){
construct_array(); // uses OpenMP pragma's
print_array();
}
и попробуйте скомпилировать с помощью следующей команды в Matlab:
>> mex -v CC="gcc44" CFLAGS="\$CFLAGS -I/home/matteson/sundials/include/ -fopenmp" LDFLAGS="\$LDFLAGS -fopenmp -L/home/matteson/sundials/lib -lsundials_cvode -lsundials_nvecserial" mex_cvode.c
Я получаю следующие сообщения, завершающиеся ошибкой ссылки:
-> mexopts.sh sourced from directory (DIR = $HOME/.matlab/$REL_VERSION)
FILE = /home/matteson/.matlab/R2010b/mexopts.sh
----------------------------------------------------------------
-> MATLAB = /misc/linux/64/opt/pkg/matlab/R2010b
-> CC = gcc44
-> CC flags:
CFLAGS = -ansi -D_GNU_SOURCE -fexceptions -fPIC -fno-omit-frame-pointer -pthread -I/home/matteson/sundials/include/ -L/home/matteson/sundials/lib -lsundials_cvode -L/home/matteson/sundials/lib -lsundials_nvecserial
CDEBUGFLAGS = -g
COPTIMFLAGS = -O -DNDEBUG
CLIBS = -Wl,-rpath-link,/misc/linux/64/opt/pkg/matlab/R2010b/bin/glnxa64 -L/misc/linux/64/opt/pkg/matlab/R2010b/bin/glnxa64 -lmx -lmex -lmat -lm -lstdc++
arguments = -DMX_COMPAT_32
-> CXX = g++
-> CXX flags:
CXXFLAGS = -ansi -D_GNU_SOURCE -fPIC -fno-omit-frame-pointer -pthread
CXXDEBUGFLAGS = -g
CXXOPTIMFLAGS = -O -DNDEBUG
CXXLIBS = -Wl,-rpath-link,/misc/linux/64/opt/pkg/matlab/R2010b/bin/glnxa64 -L/misc/linux/64/opt/pkg/matlab/R2010b/bin/glnxa64 -lmx -lmex -lmat -lm
arguments = -DMX_COMPAT_32
-> FC = g95
-> FC flags:
FFLAGS = -fexceptions -fPIC -fno-omit-frame-pointer
FDEBUGFLAGS = -g
FOPTIMFLAGS = -O
FLIBS = -Wl,-rpath-link,/misc/linux/64/opt/pkg/matlab/R2010b/bin/glnxa64 -L/misc/linux/64/opt/pkg/matlab/R2010b/bin/glnxa64 -lmx -lmex -lmat -lm
arguments = -DMX_COMPAT_32
-> LD = gcc44
-> Link flags:
LDFLAGS = -pthread -shared -Wl,--version-script,/misc/linux/64/opt/pkg/matlab/R2010b/extern/lib/glnxa64/mexFunction.map -Wl,--no-undefined -fopenmpofopenmp
LDDEBUGFLAGS = -g
LDOPTIMFLAGS = -O
LDEXTENSION = .mexa64
arguments =
-> LDCXX =
-> Link flags:
LDCXXFLAGS =
LDCXXDEBUGFLAGS =
LDCXXOPTIMFLAGS =
LDCXXEXTENSION =
arguments =
----------------------------------------------------------------
Warning: You are using gcc version "4.4.4". The version
currently supported with MEX is "4.3.4".
For a list of currently supported compilers see:
http://www.mathworks.com/support/compilers/current_release/
-> gcc44 -c -I/misc/linux/64/opt/pkg/matlab/R2010b/extern/include -I/misc/linux/64/opt/pkg/matlab/R2010b/simulink/include -DMATLAB_MEX_FILE -ansi -D_GNU_SOURCE -fexceptions -fPIC -fno-omit-frame-pointer -pthread -I/home/matteson/sundials/include/ -L/home/matteson/sundials/lib -lsundials_cvode -L/home/matteson/sundials/lib -lsundials_nvecserial -DMX_COMPAT_32 -O -DNDEBUG "mex_cvode.c"
-> gcc44 -O -pthread -shared -Wl,--version-script,/misc/linux/64/opt/pkg/matlab/R2010b/extern/lib/glnxa64/mexFunction.map -Wl,--no-undefined -fopenmpofopenmp -o "mex_cvode.mexa64" mex_cvode.o -Wl,-rpath-link,/misc/linux/64/opt/pkg/matlab/R2010b/bin/glnxa64 -L/misc/linux/64/opt/pkg/matlab/R2010b/bin/glnxa64 -lmx -lmex -lmat -lm -lstdc++
mex_cvode.o: In function `mexFunction':
mex_cvode.c:(.text+0x2b2): undefined reference to `N_VNew_Serial'
mex_cvode.c:(.text+0x2db): undefined reference to `N_VNew_Serial'
mex_cvode.c:(.text+0x35b): undefined reference to `CVodeCreate'
mex_cvode.c:(.text+0x39c): undefined reference to `CVodeInit'
mex_cvode.c:(.text+0x3dd): undefined reference to `CVodeSVtolerances'
mex_cvode.c:(.text+0x412): undefined reference to `CVodeSetUserData'
mex_cvode.c:(.text+0x449): undefined reference to `CVDense'
mex_cvode.c:(.text+0x482): undefined reference to `CVDlsSetDenseJacFn'
mex_cvode.c:(.text+0x50c): undefined reference to `CVode'
mex_cvode.c:(.text+0x5b4): undefined reference to `N_VDestroy_Serial'
mex_cvode.c:(.text+0x5c0): undefined reference to `N_VDestroy_Serial'
mex_cvode.c:(.text+0x5cc): undefined reference to `CVodeFree'
collect2: ld returned 1 exit status
mex: link of ' "mex_cvode.mexa64"' failed.
??? Error using ==> mex at 208
Unable to complete successfully.
Почему-то я не даю правильные флаги для соответствующей ссылки. Поскольку я получаю тот же набор ошибок (плюс еще несколько), если я удаляю команды для ссылки в команде gcc44, я почти уверен, что не получаю компилятор для "просмотра" библиотек.
Мои вопросы:
- Если мой анализ ошибки верен, какие флаги мне нужно передать команде компиляции mex для успешной компоновки?
- В качестве альтернативы, что такое флаги gcc для компиляции и компоновки вне среды Matlab для компиляции исполняемого файла.mex64?
- Если мой анализ неверен, куда идти?
Я думаю, что исключил предупреждение о неподдерживаемом компиляторе, так как я смог скомпилировать простой mex с программами OpenMP, используя gcc 4.4, но они не должны были ссылаться ни на что, кроме математической библиотеки. Кроме того, если я компилирую с версией gcc версии 4.1.2 или 4.3.4 с или без флагов "-fopenmp", я получаю ту же ошибку.
В конце концов мне нужна версия 4.4 из-за определенной поддержки OpenMP, которая не появлялась в предыдущих версиях.
Заранее спасибо за помощь.
--Эндрю
Редактирует: (@KWATFORD)
Поэтому я попробовал команду с операторами вне кавычек, и получил ошибку:
-> gcc44 -c -I/home/matteson/sundials/include/ -I/misc/linux/64/opt/pkg/matlab/R2010b/extern/include -I/misc/linux/64/opt/pkg/matlab/R2010b/simulink/include -DMATLAB_MEX_FILE -ansi -D_GNU_SOURCE -fexceptions -fPIC -fno-omit-frame-pointer -pthread -fopenmp -DMX_COMPAT_32 -O -DNDEBUG "mex_cvode.c"
-> gcc44 -O -pthread -shared -Wl,--version-script,/misc/linux/64/opt/pkg/matlab/R2010b/extern/lib/glnxa64/mexFunction.map -Wl,--no-undefined -fopenmp -o "mex_cvode.mexa64" mex_cvode.o -L/home/matteson/sundials/lib -lsundials_cvode -lsundials_nvecserial -Wl,-rpath-link,/misc/linux/64/opt/pkg/matlab/R2010b/bin/glnxa64 -L/misc/linux/64/opt/pkg/matlab/R2010b/bin/glnxa64 -lmx -lmex -lmat -lm -lstdc++
/usr/bin/ld: /home/matteson/sundials/lib/libsundials_cvode.a(cvode.o): relocation R_X86_64_32 against `a local symbol' can not be used when making a shared object; recompile with -fPIC
/home/matteson/sundials/lib/libsundials_cvode.a: could not read symbols: Bad value
collect2: ld returned 1 exit status
mex: link of ' "mex_cvode.mexa64"' failed.
??? Error using ==> mex at 208
Unable to complete successfully.
Я немного озадачен предложением перекомпилировать с "-fPIC", потому что когда я смотрю на команду gcc44, я вижу опцию -fPIC.
Они говорят перекомпилировать библиотеку с -fPIC?
У меня нет источника для библиотеки, если предложение перекомпилировать библиотеку, есть ли обходной путь?
Что означает "перемещение против локального объекта"?
Мои постоянные спасибо.
3 ответа
Попробуй не ставить -l
, -L
, или же -I
аргументы в этих переменных среды. Функция mex будет обрабатывать эти типы аргументов напрямую. Так что, возможно, что-то вроде:
mex -v CC="gcc44" CFLAGS="\$CFLAGS -fopenmp" LDFLAGS="\$LDFLAGS -fopenmp" -I/home/matteson/sundials/include/ -L/home/matteson/sundials/lib -lsundials_cvode -lsundials_nvecserial mex_cvode.c
Кватфорд поставил меня на правильный путь со вторым вопросом. Мне удалось заставить команду mex работать, перестроив решатель солнечных часов с общими библиотеками. В частности, я построил с:
% make distclean
% ./configure --prefix=/home/matteson/sundials --enable-shared
% make
% make install
Кроме того, спасибо kwatford за исправление к оригиналу, позвонив:
mex -v CC="gcc44" CFLAGS="\$CFLAGS -fopenmp" LDFLAGS="\$LDFLAGS -fopenmp" -I/home/matteson/sundials/include/ -L/home/matteson/sundials/lib -lsundials_cvode -lsundials_nvecserial mex_cvode.c
Так как Мекс знает, как обращаться с -L и -I.
Matlab использует свои собственные libstdc и libstdC++.
Ярлык должен был бы сделать символическую ссылку на эти библиотеки на библиотеки gcc44, которые вы хотите использовать.
Но это не может быть желаемым путем. Вы можете попытаться скомпилировать внешнюю подсказку matlab и посмотреть, не сработает ли она во-первых.