Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Makefile: Converting C-code to mex code (Linking error)

I have a C-code which works fine using makefile. Now, I am trying to convert it to mex file so that I can run it from Matlab. Here also, I am using makefile approach. But, makefile for mex gives me error.

Here is the tsnnls lib that I want to compile along with my mex file.

Organization of C-project:

tsnnls_test_DKU.c
Include_4_TSNNLS.c
Include_4_TSNNLS.h

"Include_4_TSNNLS.*" files have function TestingLibraries() which call 3rd part libraries; while I tried to keep "tsnnls_test_DKU.c" very simple as:

Original Code: tsnnls_test_DKU.c

int TestingLibraries() ;

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

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

Now, the code was changed:

Changed code: 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() ;

}

Original make file (that 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 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) $^

Changed Makefile that does not run Notice, I have revert the linking part to original with gcc compiler; however, I would like to use mex here.

I have changed some line based on my understanding and used the tag "# mex".

Also, Include_4_TSNNLS.o is being created successfully. Also, previous problem with "include" has been addressed by hard-wiring all paths.

  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

I get the following linking errors:

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

Could someone please help me with linking options?

like image 838
Garima Singh Avatar asked Feb 12 '15 18:02

Garima Singh


2 Answers

The problem is that all of the object files listed in $(OBJS_tsnnls0) (or, at the very least, libtsnnls_la-taucs_ccs_order.o) have been compiled without the -fPIC gcc compiler option. The gcc man page says for -fPIC

Generate position-independent code ( PIC ) suitable for use in a shared library

Note that MEX-files are shared libraries. Thus, all the object code links perfectly fine into a standalone executable (which does not require PIC), but it is just not compiled right to link into a MEX-file (or any shared library). If you have the original source files, you should be able to recompile them with the right switches by running

$(MEX) -c -o filename.o filename.c

for each of the source files.

like image 134
SCFrench Avatar answered Nov 09 '22 15:11

SCFrench


You have a circular dependency on tsnnls_test_DKU.o because OBJS_tsnnlsAll expands to include OBJS_tsnnls1 which is defined as tsnnls_test_DKU.o in the first line of the Makefile.

Also you don't have a rule to build OBJS_tsnnlsAll. You are just passing the names of all the object files to the compiler which is ignoring them because of the -c flag.

You should remove $(OBJS_tsnnlsALL) from the tsnnls_test_DKU.o rule, and remove the tsnnls_test_DKU.o from the final target so last two rules look like this:

# 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
like image 43
Nathan Wilson Avatar answered Nov 09 '22 15:11

Nathan Wilson