Matlab的MEX编译过程中如何链接

发布于 2024-10-16 01:18:19 字数 7255 浏览 4 评论 0原文

我编写了一个以下形式的程序:

#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 编译命令才能成功链接?
  • 或者,在 Matlab 环境之外编译和链接以编译 .mex64 可执行文件的 gcc 标志是什么?
  • 如果我的分析是错误的,那么接下来该何去何从?

我想我已经排除了不受支持的编译器警告,因为我已经能够使用 gcc 4.4 使用 OpenMP 程序编译简单的 mex,但这些程序不必链接除数学库之外的任何内容。另外,如果我使用版本 gcc 版本 4.1.2 或 4.3.4 进行编译,无论是否带有“-fopenmp”标志,我都会收到相同的错误。

最后我确实需要 4.4 版本,因为某些 OpenMP 支持在之前的版本中没有出现。

预先感谢您的帮助。

--Andrew

编辑:(@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 重新编译库吗?

我没有该库的源代码,如果建议重新编译该库,是否有解决方法?

“针对本地对象重定位”是什么意思?

我继续表示感谢。

I've written a program of the following form:

#include "stuff_I_need.h"

int main(){

construct_array(); // uses OpenMP pragma's
print_array();

return(0);


}

that compiles, links, and runs correctly with the following command:

`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" is simply gcc version 4.4 and is named like this because it's being compiled on a cluster that maintains several versions of gcc. The libraries sundials_cvode and sundials_nvecserial are used in the solving of several differential equations during the construction of the array.

Now when I want to transfer over to Matlab and try to compile the mex file of the form:

#include "stuff_I_need.h"

void mexFunction(int nlhs,mxArray* plhs[], int nrhs, const mxArray* prhs[]){

construct_array(); // uses OpenMP pragma's
print_array();

}

and try to compile with the following command in 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

I get the following messages culminating in a link error:

    -> 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.

Somehow, I'm not giving the correct flags to link appropriately. As I get the same set of errors (plus a few more) if I remove the commands to link in the gcc44 command, I'm pretty sure that I'm not getting the compiler to "see" the libraries.

My questions are :

  • If my analysis of the error is correct, what flags do I need to pass to the mex compilation command to successfully link?
  • Alternatively, what are the gcc flags to compile and link outside of the Matlab environment to compile a .mex64 executable?
  • If my analysis is wrong, where to go from here?

I think I've ruled out the unsupported compiler warning since I've been able to compile simple mex with OpenMP programs using gcc 4.4, but these did not have to link against anything except the math library. Also, if I compile with version gcc version 4.1.2 or 4.3.4 with or without the "-fopenmp" flags I get the same error.

In the end I do need version 4.4 because of certain OpenMP support that did not appear in prior versions.

Thanks in advance for the help.

--Andrew

Edits: (@KWATFORD)

So I tried the command with the statements outside the the quotes, and got the error:

-> 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.

I'm a bit confused about the suggestion to recompile with "-fPIC" because when I look at the gcc44 command I see the -fPIC as an option.

Are they saying to recompile the library with -fPIC?

I don't have the source for the library, if the suggestion is to recompile the library is there a workaround?

What does "relocation against local object" mean?

My continued thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

荒岛晴空 2024-10-23 01:18:19

尝试不要将 -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

Try not putting the -l, -L, or -I arguments in those environment variables. The mex function will handle those types of arguments directly. So perhaps something like:

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
但可醉心 2024-10-23 01:18:19

科沃特福德的第二个问题让我走上了正轨。我能够通过使用共享库重建日晷求解器来使 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

因为 mex 知道如何处理 -L 和 -I。

Kwatford put me on the right track with the second question. I was able to get the mex command to work by rebuilding the sundials solver with shared libraries. Specifically, I built with:

% make distclean
% ./configure --prefix=/home/matteson/sundials --enable-shared
% make
% make install

Also, thanks to kwatford for the fix to the original by calling:

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

since mex knows how to handle the -L and -I.

蓝颜夕 2024-10-23 01:18:19

Matlab 使用自己的 libstdc 和 libstdc++。

快捷方式是将这些库与您要使用的 gcc44 库建立符号链接。

但这可能不是我们想要的方法。您可以尝试在 matlab 提示符之外进行编译,看看是否仍然编译失败。

Matlab uses its own libstdc and libstdc++.

The shortcut would be to do a symbolink to those libraries to the gcc44 libraries that you want to use.

But this may not be the desired way to go. You could try compiling outside matlab prompt and see if it still fails compilation first.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文