undefined reference when linking .c and .cu files .cu functions are not able to link to objects foun

Hi,

I tried to describe my problem in topic title/topic description. Let me be more descriptive:

My project is divided to several files, where main.cu and hyper.cu are the ones that currently are cuda modified, the rest are plain c files.

Here is my problem:

15:24:58 , pattakosn #_ for i in `ls *.cu`;do nvcc -c $i;done

main.cu(59): warning: variable "filename" was declared but never referenced

main.cu(59): warning: variable "filename" was declared but never referenced

15:25:17 , pattakosn #_ for i in `ls *.c`;do nvcc -c $i;done

15:25:43 , pattakosn #_ nvcc *.o -lm

main.o: In function `main':

tmpxft_000078fa_00000000-1_main.cudafe1.cpp:(.text+0x29a): undefined reference to `read_bin(double*, char*, int, int)'

main.o:(.data+0x0): undefined reference to `hyperbolic(double*, float*)'

main.o:(.data+0x8): undefined reference to `inverse_hyperbolic(double*, float*)'

main.o:(.data+0x10): undefined reference to `inverse_sigmoid(double*, float*)'

main.o:(.data+0x18): undefined reference to `sigmoid(double*, float*)'

main.o:(.data+0x20): undefined reference to `tanmichelsen(double*, float*)'

main.o:(.data+0x28): undefined reference to `michelsen(double*, float*)'

main.o:(.data+0x30): undefined reference to `leib_neo(double*, float*)'

main.o:(.data+0x38): undefined reference to `johns(double*, float*)'

collect2: ld returned 1 exit status

I also tried linking using g++ or explicitely using absolute paths but the result was the same:

15:38:08 , pattakosn #_ for i in `ls *.cu`;do nvcc -c $i --machine 64 --ptxas-options=-v -O3 -I. -I/opt/cuda/common/inc -DUNIX ;done

15:38:27 , pattakosn@iraklis,cuda #_ g++ -m64 -O3 *.o -o test1 -lm -L/opt/cuda/lib64 -lcudart

main.o: In function `main':

tmpxft_00007a5f_00000000-1_main.cudafe1.cpp:(.text+0xc0b): undefined reference to `read_bin(double*, char*, int, int)'

tmpxft_00007a5f_00000000-1_main.cudafe1.cpp:(.text+0xca2): undefined reference to `hyperbolic(double*, float*)'

main.o: In function `__deviceText_$sm_10$':

tmpxft_00007a5f_00000000-1_main.cudafe1.cpp:(.rodata+0xb00): undefined reference to `hyperbolic(double*, float*)'

tmpxft_00007a5f_00000000-1_main.cudafe1.cpp:(.rodata+0xb08): undefined reference to `inverse_hyperbolic(double*, float*)'

tmpxft_00007a5f_00000000-1_main.cudafe1.cpp:(.rodata+0xb10): undefined reference to `inverse_sigmoid(double*, float*)'

tmpxft_00007a5f_00000000-1_main.cudafe1.cpp:(.rodata+0xb18): undefined reference to `sigmoid(double*, float*)'

tmpxft_00007a5f_00000000-1_main.cudafe1.cpp:(.rodata+0xb20): undefined reference to `tanmichelsen(double*, float*)'

tmpxft_00007a5f_00000000-1_main.cudafe1.cpp:(.rodata+0xb28): undefined reference to `michelsen(double*, float*)'

tmpxft_00007a5f_00000000-1_main.cudafe1.cpp:(.rodata+0xb30): undefined reference to `leib_neo(double*, float*)'

tmpxft_00007a5f_00000000-1_main.cudafe1.cpp:(.rodata+0xb38): undefined reference to `johns(double*, float*)'

collect2: ld returned 1 exit status

If I rename all files to .cu then everything works.

Specs:

ubuntu 10.04 x86_64 server, CUDA Driver Version = 3.20, CUDA Runtime Version = 3.20, driver 260.19.26

cuda sdk and everything else I have tried compiles/runs smoothly.

I have already read cuda compiler driver, searched the forum and googled about it but I still can not get it.

Can someone please explain these to me ?

.cu files are effectively compiled as C++ files (even if you set [font=“Courier New”]–host-compilation C[/font] on the command line). Thus functions within .cu files need to be declared as [font=“Courier New”]extern “C”[/font] in order to be visible by C functions in ordinary .c files.

To begin with, I changed all declarations to extern void funcname(void) but I still get the same error.

Furthermore, I probably was not clear. Functions that are contained in .c files are inaccessible from functions in .cu files.

I also tried this :

for i in `ls *.c` ; do nvcc -c $i ; done

for i in `ls *.cu` ; do nvcc -c $i ; done

g++ -m64 -O3 *.o -o test -lm -L/opt/cuda/lib64 -lcudart

As I initially said, if I rename all files to .cu then it compiles and runs fine (either by simply nvcc *.cu or with the 2 stage quoted above)

Please cure my curiosity!

It’s [font=“Courier New”]extern “C”[/font], not just [font=“Courier New”]extern[/font].
If you want to call a C function from a .cu file, you have to add a function prototype to the .cu file (which always is a good idea anyway) and declare that [font=“Courier New”]extern “C”[/font] as well.

I am sorry, but you are probably talking about sth I have never come across. I always use functions prototypes, but I do not know anything about extern “C”. Here is part of a .c file:

#include <stdio.h>

#include <math.h> // fabs, sqrt

#include "size.h"

extern void zkread(double *, float *, float *, int);

extern void h_of_b(float *, float *, float *, float *);

extern void bounds(float *, float *, float *, float *);

extern int inverse_hyperbolic(double *data, float *betas)

{

...

}

and here is the .cu file refering to this function:

extern int inverse_hyperbolic(double *, float *);

for some reason neither zkread, h_of_b, bounds is accessible to inverse_hyperbolic nor is inverse_hyperbolic visible to main…

Put this into your .cu file:

extern "C" int inverse_hyperbolic(double *, float *);

Thanks a lot.