undefined reference linking libraries

hi i’m new at this forum and have a little problem compiling an application

I want create some shared library of different math function implementations which use the GPU. The problem appear when i try to link the program with shared library.

i’m using this Makefile to generate shared library

DIR = ../..

DIR_INCLUDE = $(DIR)/include/

DIR_LIB = $(DIR)/lib

DIR_GCC = /opt/gcc/bin

CC = nvcc

FLAGS = -G -g -arch=sm_20 -O3 -Xcompiler -fPIC #-ccbin $(DIR_GCC)

LIBFLAGS = -shared -Xlinker -soname,$(LIB).1

SRC = grad_conj.cu

OBJ = grad_conj.o

LIB = libgrad_conj_cublas.so

all: $(OBJ)

	$(CC) $(LIBFLAGS) $(OBJ) -o $(DIR_LIB)/$(LIB).1.0 -lcublas

	ln -sf $(LIB).1.0 $(DIR_LIB)/$(LIB).1

	ln -sf $(LIB).1 $(DIR_LIB)/$(LIB)

$(OBJ):$(SRC)

	$(CC) $(FLAGS) -I$(DIR_INCLUDE) $(SRC) -c

and this other one to generate to link with program

DIR = ..

DIR_CUDA = cuda

DIR_CUBLAS = cublas

DIR_C = c

DIR_DATA = estructuras

DIR_BIN = $(DIR)/bin

DIR_INCLUDE = $(DIR)/include

DIR_LIB = $(DIR)/lib

CC_CUDA = nvcc

CC = gcc

CFLAGS = -Wall -g -O3

CUDAFLAGS = -G -g -arch=sm_20 -O3

FUENTE = main.c

OBJETO = main.o

EXEC = $(DIR_BIN)/grad_conj

...

cublas:$(OBJ)

	$(MAKE) -C $(DIR_DATA) cuda  # to compile some other files .c

	$(MAKE) -C $(DIR_CUBLAS) all # to create the shared library

	$(CC) $(CFLAGS) $(OBJ) $(DIR_DATA)/vector.o $(DIR_DATA)/matrix.o -L$(DIR_LIB) -lgrad_conj_cublas  -o $(EXEC)_cublas

$(OBJ):$(SRC)

	$(CC) $(SRC) -c -o $(OBJ) $(CFLAGS) -I$(DIR_INCLUDE)

...

the problem is when I execute the Makefile, the result is:

make -C estructuras cuda

make[1]: se ingresa al directorio `/home/phirus/Facultad/ssii/desarrollo/fuentes/estructuras'

nvcc -G -g -arch=sm_20 -O3 -Xcompiler -fPIC vector.c matrix.c -I ../../include/ -c 

make[1]: se sale del directorio `/home/phirus/Facultad/ssii/desarrollo/fuentes/estructuras'

make -C cublas all

make[1]: se ingresa al directorio `/home/phirus/Facultad/ssii/desarrollo/fuentes/cublas'

nvcc -G -g -arch=sm_20 -O3 -Xcompiler -fPIC  -I../../include/ grad_conj.cu -c

nvcc -shared -Xlinker -soname,libgrad_conj_cublas.so.1 grad_conj.o -o ../../lib/libgrad_conj_cublas.so.1.0 -lcublas

ln -sf libgrad_conj_cublas.so.1.0 ../../lib/libgrad_conj_cublas.so.1

ln -sf libgrad_conj_cublas.so.1 ../../lib/libgrad_conj_cublas.so

make[1]: se sale del directorio `/home/phirus/Facultad/ssii/desarrollo/fuentes/cublas'

gcc main.c -c -o main.o -g -O3 -Wall-I../include

gcc -Wall -g -O3 main.o estructuras/vector.o estructuras/matrix.o -L../lib -lgrad_conj_cublas -lcuda -o ../bin/grad_conj_cublas

main.o: In function `main':

<b>/home/phirus/Facultad/ssii/desarrollo/fuentes/main.c:161: undefined reference to `Grad_Conjugado'</b>

collect2: ld devolvió el estado de salida 1

make: *** [cublas] Error 1

the name Grad_Conjugado is the extern function of shared library. the code is:

grad_conj.h

...

extern int Grad_Conjugado (matrix A, vector b, vector x_ini, vector x);

...

grad_conj.cu

#include <cuda_runtime.h>

#include <cublas_v2.h>

...

extern int Grad_Conjugado(matrix A, vector b, vector x_ini, vector x){

...

some cublas calls

...

}

main.c

...

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

...

      gettimeofday(&t1,NULL);

      Grad_Conjugado(*A, *b, *x0, *xf);

      gettimeofday(&t2,NULL);

...

}

How must i do it??

Edit:

the library has the correct name of function. Why gcc doesn’t find it:

nm ../lib/libgrad_conj_cublas.so | grep Grad_Conjugado

0000000000000b60 T _Z14Grad_Conjugado6matrix6vectorS0_S0

thx for your time, sorry for my english

main.c is looking for a symbol _Grad_Conjugado. The library exports a symbol _Z14Grad_Conjugado6matrix6vectorS0_S0. As they are not the same, they cannot be linked, and thus there is a missing symbol.

Why is this happening? CUDA uses a C++ frontend. C++ compilers “decorate” function names. The additional information provided by the decoration encodes the types of function arguments for example. This provides support for templates and overloading of functions names. Except for prepending function names with an underscore, C compilers do not decorate function names.

To make functions in C++ or CUDA code callable from C code, instruct the C++ / CUDA compiler to generate undecorated names like a C compiler would do. Change your header file as follows:

#ifdef __cplusplus

extern "C" {

#endif

int Grad_Conjugado (matrix A, vector b, vector x_ini, vector x);

#ifdef __cplusplus

}

#endif

Include the header file from both your .cu and your .c file. The #ifdef’s in the code above guard the code that’s only need by and useful for a C++ or CUDA compiler.

thank you very much. I solved the problem this morning after read your reply and i went to write the explication. But your explanation is perfect.

thx for reply