Makefile: 将C代码转换为mex代码(链接错误)

8
我是一名有用的助手,可以为您翻译文本。

我有一个使用 makefile 工作良好的 C 代码。现在,我正在尝试将其转换为 mex 文件,以便我可以从 Matlab 中运行它。在这里,我也使用 makefile 方法。但是,mex 的 makefile 给我报错。

这里是我想与我的 mex 文件一起编译的 tsnnls lib

C 项目的组织:

tsnnls_test_DKU.c
Include_4_TSNNLS.c
Include_4_TSNNLS.h

"Include_4_TSNNLS.*"文件包含函数TestingLibraries(),该函数调用第三方库;而我尝试保持"tsnnls_test_DKU.c"非常简单:

原始代码: tsnnls_test_DKU.c

int TestingLibraries() ;

int main( int argc, char* argv[] ) 
{

    int k = TestingLibraries() ;
    return(1);
}

现在,代码已经更改:
更改后的代码:tsnnls_test_DKU.c:
#include "mex.h"
#include <math.h>

int TestingLibraries() ;

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

    int k = TestingLibraries() ;

}

原始的可用make文件

CXX       = gcc
FLAGS     = 
CFLAGS    = "-m64"   ## "-m32"
INCLUDE_TSNNLS  = -I/home/dkumar/libtsnnls-2.3.3 -I/home/dkumar/libtsnnls-2.3.3/tsnnls  -I/home/dkumar/libtsnnls-2.3.3/tsnnls/taucs_basic

#################### ALL TSNNLS lib related ##########################
## this is where all object file (*.o) generated by tsnnls library makefile are located.
tsnnl_PATH = /home/dkumar/libtsnnls-2.3.3/tsnnls/

# Here is a simple Make Macro.
OBJS_tsnnls1        = tsnnls_test_DKU.o
OBJS_ADD        = Include_4_TSNNLS.o

# Here is a Make Macro that uses the backslash to extend to multiple lines.
OBJS_tsnnls0 =  libtsnnls_la-taucs_malloc.o libtsnnls_la-taucs_ccs_order.o \
    libtsnnls_la-taucs_ccs_ops.o libtsnnls_la-taucs_vec_base.o \
    libtsnnls_la-taucs_complex.o libtsnnls_la-colamd.o \
    libtsnnls_la-amdbar.o libtsnnls_la-amdexa.o \
    libtsnnls_la-amdtru.o libtsnnls_la-genmmd.o \
    libtsnnls_la-taucs_timer.o libtsnnls_la-taucs_sn_llt.o \
    libtsnnls_la-taucs_ccs_base.o libtsnnls_la-tlsqr.o \
    libtsnnls_la-tsnnls.o libtsnnls_la-lsqr.o

 ## adding "$(OBJS_PATH)" to each word in "$(OBJS)"
# which in our case is basically to add the same folder in front of all "*.o" object files.
OBJS_TEMP = $(addprefix $(tsnnl_PATH), $(OBJS_tsnnls0)) 

# OBJS_LOC is in current working directory,
OBJS_tsnnlsALL = $(OBJS_TEMP)   $(OBJS_tsnnls1)

# Libraries for tsnnls
STLIB_tsnnls    = /usr/local/lib/taucs_full/lib/linux/libtaucs.a 
LIBS_tsnnls     = -largtable2 -llapack -lblas -lquadmath -lm

########################################################################
TARGET  = tsnnls_test_DKU
REBUILDABLES = $(OBJS_tsnnls1) $(TARGET) 
LIBS      =    $(LIBS_tsnnls)  $(STLIB_tsnnls)

INCLUDE = $(INCLUDE_TSNNLS)

all : $(TARGET)
    echo All done

clean : 
    rm -f $(REBUILDABLES)   
    echo Clean done

$(OBJS_ADD):    Include_4_TSNNLS.c
    gcc -c -o Include_4_TSNNLS.o Include_4_TSNNLS.c

# Final linking
$(TARGET) : $(OBJS_tsnnlsALL)  $(OBJS_ADD) $(LIBS)
    $(CXX) -g -o $@ $(INCLUDE) $(CFLAGS) $^
Makefile改动后无法运行 注意,我已经将链接部分还原到gcc编译器的原始状态;但是,我想在这里使用mex。
我根据自己的理解更改了一些行,并使用了标记“# mex”。
此外,Include_4_TSNNLS.o已成功创建。之前关于“include”的问题已通过硬编码所有路径得到解决。
  MEXSUFFIX  = mexa64                       # mex
  MATLABHOME = /usr/local/MATLAB/R2011b             # mex
  MEX        = /usr/local/MATLAB/R2011b/bin/mex         # mex

  MEXFLAGS  = -cxx CC='$(CXX)' CXX='$(CXX)' LD='$(CXX)'     # mex

CXX       = gcc
FLAGS     = 
CFLAGS    = -fPIC -pthread -DMX_COMPAT_32 -DMATLAB_MEX_FILE -m64   ## "-m32"
INCLUDE_TSNNLS  = -I/usr/local/MATLAB/R2011b/extern/include  -I/home/dkumar/libtsnnls-2.3.3 -I/home/dkumar/libtsnnls-2.3.3/tsnnls  -I/home/dkumar/libtsnnls-2.3.3/tsnnls/taucs_basic

#################### ALL TSNNLS lib related ##########################
## this is where all object file (*.o) generated by tsnnls library makefile are located.
tsnnl_PATH = /home/dkumar/libtsnnls-2.3.3/tsnnls/

# Here is a simple Make Macro.
OBJS_tsnnls1        = tsnnls_test_DKU.o
OBJS_ADD        = Include_4_TSNNLS.o

# Here is a Make Macro that uses the backslash to extend to multiple lines.
OBJS_tsnnls0 =  libtsnnls_la-taucs_malloc.o libtsnnls_la-taucs_ccs_order.o \
    libtsnnls_la-taucs_ccs_ops.o libtsnnls_la-taucs_vec_base.o \
    libtsnnls_la-taucs_complex.o libtsnnls_la-colamd.o \
    libtsnnls_la-amdbar.o libtsnnls_la-amdexa.o \
    libtsnnls_la-amdtru.o libtsnnls_la-genmmd.o \
    libtsnnls_la-taucs_timer.o libtsnnls_la-taucs_sn_llt.o \
    libtsnnls_la-taucs_ccs_base.o libtsnnls_la-tlsqr.o \
    libtsnnls_la-tsnnls.o libtsnnls_la-lsqr.o

 ## adding "$(OBJS_PATH)" to each word in "$(OBJS)"
# which in our case is basically to add the same folder in front of all "*.o" object files.
OBJS_TEMP = $(addprefix $(tsnnl_PATH), $(OBJS_tsnnls0)) 

# OBJS_LOC is in current working directory,
OBJS_tsnnlsALL = $(OBJS_TEMP)   $(OBJS_tsnnls1)

# Libraries for tsnnls
##STLIB_tsnnls  = /usr/local/lib/taucs_full/lib/linux/libtaucs.a 
STLIB_tsnnls    = /usr/local/lib/libtaucs.a 
#LIBS_tsnnls    = -largtable2 -llapack -lblas -lquadmath -lm
LIBS_tsnnls     = -largtable2 -llapack -lblas -lm
########################################################################
## TARGET   = tsnnls_test_DKU

TARGET_WO_EXTN =  tsnnls_test_DKU               # mex
TARGET      = TARGET_WO_EXTN

#TARGET =  $(TARGET_WO_EXTN).$(MEXSUFFIX)           # mex

REBUILDABLES = $(OBJS_tsnnls1) $(TARGET) *.mexa64  
LIBS      =    $(LIBS_tsnnls)  $(STLIB_tsnnls)
INCLUDE = $(INCLUDE_TSNNLS)

all : $(TARGET)
    echo All done

clean : 
    rm -f $(REBUILDABLES)   
    echo Clean done

$(OBJS_ADD):    Include_4_TSNNLS.c
    gcc -c -o $(INCLUDE) Include_4_TSNNLS.o Include_4_TSNNLS.c

# CHANGED FROM HERE     # mex
tsnnls_test_DKU.o: tsnnls_test_DKU.c  Include_4_TSNNLS.c $(OBJS_tsnnlsALL)  $(OBJS_ADD)
    $(CXX) $(CFLAGS) $(INCLUDE)  -c $^

# Final linking
$(TARGET): tsnnls_test_DKU.o     $(OBJS_tsnnlsALL)  $(OBJS_ADD)   $(LIBS) 
    $(MEX) $(MEXFLAGS)  -output $(TARGET_WO_EXTN) $^      -largeArrayDims

我得到了以下链接错误:
dkumar@kumar-Aspire-E1-510 ~/CPP_ExampleCodes_DKU/Using_tsnnls_DKU_copy_2_MEX $ make
make: Circular tsnnls_test_DKU.o <- tsnnls_test_DKU.o dependency dropped.
gcc -fPIC -pthread -DMX_COMPAT_32 -DMATLAB_MEX_FILE    -I/usr/local/MATLAB/R2011b/extern/include  -I/home/dkumar/libtsnnls-2.3.3 -I/home/dkumar/libtsnnls-2.3.3/tsnnls  -I/home/dkumar/libtsnnls-2.3.3/tsnnls/taucs_basic -c tsnnls_test_DKU.c Include_4_TSNNLS.c /home/dkumar/libtsnnls-2.3.3/tsnnls/libtsnnls_la-taucs_malloc.o /home/dkumar/libtsnnls-2.3.3/tsnnls/libtsnnls_la-taucs_ccs_order.o /home/dkumar/libtsnnls-2.3.3/tsnnls/libtsnnls_la-taucs_ccs_ops.o /home/dkumar/libtsnnls-2.3.3/tsnnls/libtsnnls_la-taucs_vec_base.o /home/dkumar/libtsnnls-2.3.3/tsnnls/libtsnnls_la-taucs_complex.o /home/dkumar/libtsnnls-2.3.3/tsnnls/libtsnnls_la-colamd.o /home/dkumar/libtsnnls-2.3.3/tsnnls/libtsnnls_la-amdbar.o /home/dkumar/libtsnnls-2.3.3/tsnnls/libtsnnls_la-amdexa.o /home/dkumar/libtsnnls-2.3.3/tsnnls/libtsnnls_la-amdtru.o /home/dkumar/libtsnnls-2.3.3/tsnnls/libtsnnls_la-genmmd.o /home/dkumar/libtsnnls-2.3.3/tsnnls/libtsnnls_la-taucs_timer.o /home/dkumar/libtsnnls-2.3.3/tsnnls/libtsnnls_la-taucs_sn_llt.o /home/dkumar/libtsnnls-2.3.3/tsnnls/libtsnnls_la-taucs_ccs_base.o /home/dkumar/libtsnnls-2.3.3/tsnnls/libtsnnls_la-tlsqr.o /home/dkumar/libtsnnls-2.3.3/tsnnls/libtsnnls_la-tsnnls.o /home/dkumar/libtsnnls-2.3.3/tsnnls/libtsnnls_la-lsqr.o Include_4_TSNNLS.o
gcc: warning: /home/dkumar/libtsnnls-2.3.3/tsnnls/libtsnnls_la-taucs_malloc.o: linker input file unused because linking not done
gcc: warning: /home/dkumar/libtsnnls-2.3.3/tsnnls/libtsnnls_la-taucs_ccs_order.o: linker input file unused because linking not done
gcc: warning: /home/dkumar/libtsnnls-2.3.3/tsnnls/libtsnnls_la-taucs_ccs_ops.o: linker input file unused because linking not done
gcc: warning: /home/dkumar/libtsnnls-2.3.3/tsnnls/libtsnnls_la-taucs_vec_base.o: linker input file unused because linking not done
gcc: warning: /home/dkumar/libtsnnls-2.3.3/tsnnls/libtsnnls_la-taucs_complex.o: linker input file unused because linking not done
gcc: warning: /home/dkumar/libtsnnls-2.3.3/tsnnls/libtsnnls_la-colamd.o: linker input file unused because linking not done
gcc: warning: /home/dkumar/libtsnnls-2.3.3/tsnnls/libtsnnls_la-amdbar.o: linker input file unused because linking not done
gcc: warning: /home/dkumar/libtsnnls-2.3.3/tsnnls/libtsnnls_la-amdexa.o: linker input file unused because linking not done
gcc: warning: /home/dkumar/libtsnnls-2.3.3/tsnnls/libtsnnls_la-amdtru.o: linker input file unused because linking not done
gcc: warning: /home/dkumar/libtsnnls-2.3.3/tsnnls/libtsnnls_la-genmmd.o: linker input file unused because linking not done
gcc: warning: /home/dkumar/libtsnnls-2.3.3/tsnnls/libtsnnls_la-taucs_timer.o: linker input file unused because linking not done
gcc: warning: /home/dkumar/libtsnnls-2.3.3/tsnnls/libtsnnls_la-taucs_sn_llt.o: linker input file unused because linking not done
gcc: warning: /home/dkumar/libtsnnls-2.3.3/tsnnls/libtsnnls_la-taucs_ccs_base.o: linker input file unused because linking not done
gcc: warning: /home/dkumar/libtsnnls-2.3.3/tsnnls/libtsnnls_la-tlsqr.o: linker input file unused because linking not done
gcc: warning: /home/dkumar/libtsnnls-2.3.3/tsnnls/libtsnnls_la-tsnnls.o: linker input file unused because linking not done
gcc: warning: /home/dkumar/libtsnnls-2.3.3/tsnnls/libtsnnls_la-lsqr.o: linker input file unused because linking not done
gcc: warning: Include_4_TSNNLS.o: linker input file unused because linking not done
/usr/local/MATLAB/R2011b/bin/mex             -cxx CC='gcc' CXX='gcc' LD='gcc'         -output tsnnls_test_DKU                tsnnls_test_DKU.o /home/dkumar/libtsnnls-2.3.3/tsnnls/libtsnnls_la-taucs_malloc.o /home/dkumar/libtsnnls-2.3.3/tsnnls/libtsnnls_la-taucs_ccs_order.o /home/dkumar/libtsnnls-2.3.3/tsnnls/libtsnnls_la-taucs_ccs_ops.o /home/dkumar/libtsnnls-2.3.3/tsnnls/libtsnnls_la-taucs_vec_base.o /home/dkumar/libtsnnls-2.3.3/tsnnls/libtsnnls_la-taucs_complex.o /home/dkumar/libtsnnls-2.3.3/tsnnls/libtsnnls_la-colamd.o /home/dkumar/libtsnnls-2.3.3/tsnnls/libtsnnls_la-amdbar.o /home/dkumar/libtsnnls-2.3.3/tsnnls/libtsnnls_la-amdexa.o /home/dkumar/libtsnnls-2.3.3/tsnnls/libtsnnls_la-amdtru.o /home/dkumar/libtsnnls-2.3.3/tsnnls/libtsnnls_la-genmmd.o /home/dkumar/libtsnnls-2.3.3/tsnnls/libtsnnls_la-taucs_timer.o /home/dkumar/libtsnnls-2.3.3/tsnnls/libtsnnls_la-taucs_sn_llt.o /home/dkumar/libtsnnls-2.3.3/tsnnls/libtsnnls_la-taucs_ccs_base.o /home/dkumar/libtsnnls-2.3.3/tsnnls/libtsnnls_la-tlsqr.o /home/dkumar/libtsnnls-2.3.3/tsnnls/libtsnnls_la-tsnnls.o /home/dkumar/libtsnnls-2.3.3/tsnnls/libtsnnls_la-lsqr.o Include_4_TSNNLS.o /usr/lib/libargtable2.so /usr/lib/liblapack.so /usr/lib/libblas.so /usr/lib/x86_64-linux-gnu/libm.so /usr/local/lib/libtaucs.a      -largeArrayDims

Warning: You are using gcc version "4.8.2-19ubuntu1)".  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/

/usr/bin/ld: /home/dkumar/libtsnnls-2.3.3/tsnnls/libtsnnls_la-taucs_ccs_order.o: relocation R_X86_64_32 against `.rodata' can not be used when making a shared object; recompile with -fPIC
/home/dkumar/libtsnnls-2.3.3/tsnnls/libtsnnls_la-taucs_ccs_order.o: error adding symbols: Bad value
collect2: error: ld returned 1 exit status

    mex: link of ' "tsnnls_test_DKU.mexa64"' failed.

make: *** [tsnnls_test_DKU] Error 1

请问有人能帮我解决链接选项吗?


1
使用-I(matlab_dir)/extern/include将makefile指向头文件。 - user3528438
1
在你的代码底部,你正在使用"gcc -c -o..."进行编译,并使用"$(MEX) -g -o ...."进行链接。由于你的$(INCLUDE)在$(MEX)之后,所以它被视为链接器选项而不是编译器选项。尝试将$(INCLUDE)和$(CFLAGS)移动到gcc附近。 - user3528438
1
我对mex不是很了解。但是,在规则$(OBJS_ADD): Include_4_TSNNLS.c中,您已经包含了mex include lib。您正在链接阶段进行包含。有人可能会给您精确的命令。 - Garima Singh
使用MX_COMPAT_32-largeArrayDims发生冲突。请删除其中一个。但几乎肯定还有其他问题... - chappjc
我不知道如何创建mex文件,但我认为问题可能出在链接上,或者是因为您正在使用不支持mex的新版本编译器。您可以通过键入“man mex”来获取所有与mex相关的命令。 - Madhu Kumar Dadi
显示剩余2条评论
2个回答

4
问题在于$(OBJS_tsnnls0)中列出的所有目标文件(或至少是libtsnnls_la-taucs_ccs_order.o)都没有使用-fPIC gcc编译器选项进行编译。gcc手册上-fPIC有以下说明:
生成适用于共享库的位置无关代码(PIC)
请注意,MEX文件是共享库。因此,所有这些目标代码可以完美地链接到独立的可执行文件(不需要PIC),但是它们只是编译链接到MEX文件(或任何共享库)时存在问题。如果您有原始源文件,则应该能够通过运行以下命令并使用正确的开关重新编译它们: $(MEX) -c -o filename.o filename.c
对于每个源文件都要执行这个命令。

该库似乎使用了一些自动工具(libtool)。在$(OBJS_tsnnls0)中的configure之后使用makefile,我可以看到像这样的命令:libtool: compile: gcc -DHAVE_CONFIG_H -I. -I.. -Wall -MT libtsnnls_la-taucs_ccs_order.lo -MD -MP -MF .deps/libtsnnls_lataucs_ccs_order.Tpo -c taucs_basic/taucs_ccs_order.c -fPIC -DPIC -o .libs/libtsnnls_la-taucs_ccs_order.o。它似乎已经使用了-fPIC。我应该将这个命令改成什么? - Garima Singh
是的,我已经下载了该库和所有源代码:jasoncantarella.com/wordpress/software/tsnnls。它的makefile是使用makefile.am创建的。然而,鉴于我不擅长C语言,我无法弄清楚如何将makefile.am->makefile以及如何更改标志或编译器。您能否尝试使用此库并帮助我解决这个问题?我会非常感激您的帮助。我将特别在我的论文中感谢您或将您列为我的合作者。这将解决医学成像中的一个突出问题,因此非常重要。 - Garima Singh

2
您在Makefile文件中存在循环依赖于tsnnls_test_DKU.o,因为OBJS_tsnnlsAll扩展包含OBJS_tsnnls1,而OBJS_tsnnls1Makefile的第一行被定义为tsnnls_test_DKU.o
另外,您没有构建OBJS_tsnnlsAll的规则。您只是将所有目标文件的名称传递给编译器,但由于-c标志,编译器会忽略它们。
您应该从tsnnls_test_DKU.o规则中删除$(OBJS_tsnnlsALL),并且从最终目标中删除tsnnls_test_DKU.o,使得最后两个规则如下所示:
# CHANGED FROM HERE     # mex
tsnnls_test_DKU.o: tsnnls_test_DKU.c  Include_4_TSNNLS.c $(OBJS_ADD)
    $(CXX) $(CFLAGS) $(INCLUDE)  -c $^

# Final linking
$(TARGET): $(OBJS_tsnnlsALL)  $(OBJS_ADD)   $(LIBS) 
    $(MEX) $(MEXFLAGS)  -output $(TARGET_WO_EXTN) $^      -largeArrayDims

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接