I converted a C++ code to C and now I’m trying to change the Makefile as well. I had this:
g++ -fPIC -o bin/linux/release/gpu_md5 cuda_md5.c cuda_md5_cpu.c obj/release/cuda_md5_gpu.cu.o
-L/usr/local/cuda/lib64 -L../../lib64
-L../../common/lib64/linux -L/opt/cuda/NVIDIA_CUDA_SDK/lib64 -lcudart
-L/usr/local/cuda/lib64 -L../../lib64
-L../../common/lib64/linux -L/opt/cuda/NVIDIA_CUDA_SDK/lib64
As far as I know I could just change g++ to gcc and it should work well, but it is not. Looks like gcc can’t find the functions from cuda_md5_cpu.c that I’m calling in cuda_md5.c (PS: I’m not including cuda_md5_cpu.c in cuda_md5.c):
/tmp/ccKdDJiq.o: In function `cuda_compute_md5s':
cuda_md5.c:(.text+0x201): undefined reference to `init_constants'
cuda_md5.c:(.text+0x2e2): undefined reference to `execute_kernel'
collect2: ld returned 1 exit status
What is wrong? I just changed from g++ to gcc.
I would say there’s a very good chance that
obj/release/cuda_md5_gpu.cu.o(which you don’t seem to be recompiling) has been compiled with a C++ compiler and therefore has symbol names which have been modified by name mangling.Name mangling is a technique used by C++ compilers to allow different functions to have the same name but with different parameter types (overloading), and C compilers have no need to do this since there is no overloading allowed.
In other words, you may find that
init_constants(int,float);may simply be morphed by a C compiler into_init_constantsbut, if you use a C++ compiler, you’ll get something like_init_constants_$$_IntFloatso as to distinguish it frominit_constants(int,double)orinit_constants(void).So a linker that tries to link together a C-compiled
cuda_md5.cwith a C++-compiledobj/release/cuda_md5_gpu.cu.owill not be able to match the function names together.That’s often why you see
extern "C" { ... }in C++ code, it uses the C rules to export function names (and other things) to the linker to allow linking of C and C++ code together.