Goal:
- create a shared library containing my CUDA kernels that has a CUDA-free wrapper/header.
- create a
test
executable for the shared library.
Problem
- shared library
MYLIB.so
seems to compile fine. (no problem). - Error in linking:
./libMYLIB.so: undefined reference to __cudaRegisterLinkedBinary_39_tmpxft_000018cf_00000000_6_MYLIB_cpp1_ii_74c599a1
simplified makefile:
libMYlib.so : MYLIB.o
g++ -shared -Wl,-soname,libMYLIB.so -o libMYLIB.so MYLIB.o -L/the/cuda/lib/dir -lcudart
MYLIB.o : MYLIB.cu MYLIB.h
nvcc -m64 -arch=sm_20 -dc -Xcompiler '-fPIC' MYLIB.cu -o MYLIB.o -L/the/cuda/lib/dir -lcudart
test : test.cpp libMYlib.so
g++ test.cpp -o test -L. -ldl -Wl,-rpath,. -lMYLIB -L/the/cuda/lib/dir -lcudart
indeed
nm libMYLIB.so
shows that all CUDA api functions are "undefined symbols":
U __cudaRegisterFunction
U __cudaRegisterLinkedBinary_39_tmpxft_0000598c_00000000_6_CUPA_cpp1_ii_74c599a1
U cudaEventRecord
U cudaFree
U cudaGetDevice
U cudaGetDeviceProperties
U cudaGetErrorString
U cudaLaunch
U cudaMalloc
U cudaMemcpy
So CUDA somehow did not get linked to the shared library MYLIB.so What am I missing?
CUDA did not even get linked to the object file somehow:
nm MYLIB.o
U __cudaRegisterFunction
U __cudaRegisterLinkedBinary_39_tmpxft_0000598c_00000000_6_CUPA_cpp1_ii_74c599a1
U cudaEventRecord
U cudaFree
U cudaGetDevice
U cudaGetDeviceProperties
U cudaGetErrorString
U cudaLaunch
U cudaMalloc
U cudaMemcpy
(same as above)
Have you tried explictly disabling relocatable device code? i.e.
-rdc=false
? I got thisundefined reference to __cudaRegisterLinkedBinaryWhatever
with-rdc=true
and it went away when I removed it. Although I'm not enough of an expert to explain what exactly is going on with that.Here's an example linux shared object creation along the lines you indicated:
First the shared library. The build commands for this are as follows:
It seems you may be missing the second step above in your makefile, but I haven't analyzed if there are any other issues with your makefile.
Now, for the test executable, the build commands are as follows:
To run it, simply execute the
testmain
executable, but be sure thetest.so
library is on yourLD_LIBRARY_PATH
.These are the files I used for test purposes:
test1.h:
test1.cu:
test2.h:
test2.cu:
main.cpp:
When I compile according to the commands given, and run
./testmain
I get:Note that if you prefer, you may generate a
libtest.so
instead oftest.so
, and then you may use a modified build sequence for the test executable:I don't believe it makes any difference, but it may be more familiar syntax.
I'm sure there is more than one way to accomplish this. This is just an example. You may wish to also review the relevant section of the nvcc manual and also review the examples.
EDIT: I tested this under cuda 5.5 RC, and the final application link step complained about not finding the cudart lib (
warning: libcudart.so.5.5., needed by ./libtest.so, not found
). However the following relatively simple modification (example Makefile) should work under either cuda 5.0 or cuda 5.5.Makefile:
The other answers did not work for me (maybe because I’m using cuda 10). The solution that worked for me was compiling the cuda files as:
Than compiling the c++ file as:
And finally linking all using nvcc:
Don’t take this code literally. But the core of the solution to the error was using nvcc instead of g++ in the final linking step.