问题
I have a c-code which I can compile using makefile and run. Now, I want to convert it to mex file which I would like to compile using corresponding makefile. However, my makefile for mex code is not working. I would appreciate if someone can guide me.
I am working on 64 bit system.
Structure of both C-codes and mex codes:
C-codes Mex Code
Test_tsnnls.c <--Main defined Test_tsnnls_MEX.c <--mex defined here
Include_4_TSNNLS.h Include_4_TSNNLS.h
Include_4_TSNNLS.c Include_4_TSNNLS.c
Makefile (C-project) works:
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 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_tsnnls = $(addprefix $(tsnnl_PATH), $(OBJS_tsnnls0))
# Libraries for tsnnls
STLIB_tsnnls = /usr/local/lib/taucs_full/lib/linux/libtaucs.a
LIBS_tsnnls = -largtable2 -llapack -lblas -lquadmath -lm
########################################################################
TARGET_WO_EXTN = Test_tsnnls
TARGET = $(TARGET_WO_EXTN)
LIBS = $(LIBS_tsnnls) $(STLIB_tsnnls)
INCLUDE = $(INCLUDE_TSNNLS)
REBUILDABLES = *.o $(TARGET)
all : $(TARGET)
echo All done
clean :
rm -f $(REBUILDABLES)
echo Clean done
Include_4_TSNNLS.o: Include_4_TSNNLS.c
$(CXX) -c -o Include_4_TSNNLS.o Include_4_TSNNLS.c
$(TARGET_WO_EXTN).o: $(TARGET_WO_EXTN).c
$(CXX) -c -o $(TARGET_WO_EXTN).o $(TARGET_WO_EXTN).c
# Final linking
$(TARGET) : $(OBJS_tsnnls) $(TARGET_WO_EXTN).o Include_4_TSNNLS.o $(LIBS)
$(CXX) -g -o $@ $(INCLUDE) $(CFLAGS) $^
Makefile (mex project) DOES NOT work:
MEXSUFFIX = mexa64
MATLABHOME = /usr/local/MATLAB/R2014b
MEX = mex
CXX = gcc
CFLAGS = -fPIC -pthread -DMX_COMPAT_32 \
-DMATLAB_MEX_FILE
INCLUDE_Matlab = -I$(MATLABHOME)/extern/include
MEXFLAGS = -cxx CC='$(CXX)' CXX='$(CXX)' LD='$(CXX)'
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 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_tsnnls = $(addprefix $(tsnnl_PATH), $(OBJS_tsnnls0))
# Libraries for tsnnls
STLIB_tsnnls = /usr/local/lib/taucs_full/lib/linux/libtaucs.a
LIBS_tsnnls = -largtable2 -llapack -lblas -lquadmath -lm
########################################################################
TARGET_WO_EXTN = Test_tsnnls_Mex
TARGET = $(TARGET_WO_EXTN).$(MEXSUFFIX)
LIBS = $(LIBS_tsnnls) $(STLIB_tsnnls)
INCLUDE = $(INCLUDE_Matlab) $(INCLUDE_TSNNLS)
REBUILDABLES = *.o $(TARGET)
all : $(TARGET)
echo All done
clean :
rm -f $(REBUILDABLES)
echo Clean done
Include_4_TSNNLS.o: Include_4_TSNNLS.c
$(CXX) $(CFLAGS) $(INCLUDE) -c $^
## $(CXX) -c -o Include_4_TSNNLS.o Include_4_TSNNLS.c
$(TARGET_WO_EXTN).o: $(TARGET_WO_EXTN).c
$(CXX) $(CFLAGS) $(INCLUDE) -c $^
# Final linking
$(TARGET): $(OBJS_tsnnls) $(TARGET_WO_EXTN).o Include_4_TSNNLS.o $(LIBS)
$(MEX) $(MEXFLAGS) $(LIBS) -output $(TARGET_WO_EXTN) $^
Errors that I get
dkumar@dkumar-Precision-WorkStation-T7500 ~/Mex_Codes_DKU/Using_tsnnls_DKU_copy_MEX/Pure_Mex $ make
cc -fPIC -pthread -DMX_COMPAT_32 -DMATLAB_MEX_FILE -c -o Test_tsnnls_Mex.o Test_tsnnls_Mex.c
gcc -c -o Include_4_TSNNLS.o Include_4_TSNNLS.c
In file included from Include_4_TSNNLS.c:1:0:
Include_4_TSNNLS.h:72:15: warning: useless storage class specifier in empty declaration [enabled by default]
extern enum STYPE;
^
mex -cxx CC='gcc' CXX='gcc' LD='gcc' -largtable2 -llapack -lblas -lquadmath -lm /usr/local/lib/taucs_full/lib/linux/libtaucs.a -output Test_tsnnls_Mex /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 Test_tsnnls_Mex.o Include_4_TSNNLS.o /usr/local/lib/libargtable2.so /usr/lib/liblapack.so /usr/lib/libblas.so /usr/lib/libquadmath.so /usr/lib/x86_64-linux-gnu/libm.so /usr/local/lib/taucs_full/lib/linux/libtaucs.a
Building with 'g++'.
Warning: You are using gcc version '4.8.2'. The version of gcc is not supported. The version currently supported with MEX is '4.7.x'. For a list of currently supported compilers see: http://www.mathworks.com/support/compilers/current_release.
Warning: You are using gcc version '4.8.2-19ubuntu1)'. The version of gcc is not supported. The version currently supported with MEX is '4.7.x'. 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
make: *** [Test_tsnnls_Mex.mexa64] Error 255
I think that I am already compiling with -fPIC.
My understanding is that $(OBJS_tsnnls)
may not properly included in my mex project.
OR, issue could be with 32-bit vs 64 bit platform Stackoveflow-link. I have no idea how to fix this.
Any help would be so very much appreciated.
回答1:
Have another look at the error messages - the part with the call to mex
:
mex -cxx CC='gcc' CXX='gcc' LD='gcc' -largtable2 -llapack -lblas -lquadmath -lm
While you have modified the CFLAGS
Makefile variable to include -fPIC
, you didn't ensure it was being passed to mex
(the very bottom command in your Makefile). You could modify MEXFLAGS
. This should cover all bases:
MEXFLAGS = -v -cxx CC='$(CXX)' CXX='$(CXX)' CFLAGS='$(CFLAGS)' CXXFLAGS='$(CFLAGS)' LD='$(CXX)'
You don't need both CC
and CXX
(probably just CXX
since it's compiling as C++). Also, add the -v
flag to see what the failing g++ command was.
It is interesting to use mex
just to link object files instead of also do the compiling. If I understand the goal here, it's to link object files compiled as C, and the approach was to instruct mex
to compile as C++, but setting CXX=gcc
, forcing it to use the C frontend. Should work I guess, but it seems rather contorted.
来源:https://stackoverflow.com/questions/28583355/makefile-with-mex-project-rodata-can-not-be-used-when-making-a-shared-object