I found an issue with device linking with nvcc. If you link your binary against the same static library more than once, then you get the error “Multiple definition of X”. This does not occur with g++.
There is some documentation about it:
6.5.5. Device Code in Libraries
If a device function with non-weak external linkage is defined in a library as well as a non-library object, the device linker will complain about the multiple definitions (this differs from traditional host linkers that may ignore the function definition from the library object, if it was already found in an earlier object).
However it talks about library-object incompatibility, but here the problem occurs even with library-library.
CUDA version: V9.0.176
CUDA arch: sm_61
CMake version: 3.11.4
g++ version: 5.4.0
OS: Ubuntu 16.04
How to reproduce
Download this example code of CUDA + CMake:
In the CMakeLists.txt, replace:
target_link_libraries(particle_test PRIVATE particles)
target_link_libraries(particle_test PRIVATE particles particles)
mkdir build cd build make VERBOSE=1
This change generates the following error:
[ 85%] Linking CUDA device code CMakeFiles/particle_test.dir/cmake_device_link.o /opt/cmake-3.11.4-Linux-x86_64/bin/cmake -E cmake_link_script CMakeFiles/particle_test.dir/dlink.txt --verbose=1 /usr/local/cuda/bin/nvcc -Xcompiler=-fPIC -Wno-deprecated-gpu-targets -shared -dlink CMakeFiles/particle_test.dir/test.cu.o -o CMakeFiles/particle_test.dir/cmake_device_link.o -L/usr/local/cuda/targets/x86_64-linux/lib libparticles.a libparticles.a nvlink error : Multiple definition of '_ZN8particle7advanceEf' in 'libparticles.a:particle.cu.o', first defined in 'libparticles.a:particle.cu.o' nvlink error : Multiple definition of '_ZN2v38scrambleEv' in 'libparticles.a:v3.cu.o', first defined in 'libparticles.a:v3.cu.o' nvlink error : Multiple definition of '_ZN2v39normalizeEv' in 'libparticles.a:v3.cu.o', first defined in 'libparticles.a:v3.cu.o' nvlink fatal : Internal error: duplicate relocations at same address CMakeFiles/particle_test.dir/build.make:85: recipe for target 'CMakeFiles/particle_test.dir/cmake_device_link.o' failed
A possible use case is as follows (pseudocode in CMake):
add_library(base_library STATIC ...) add_library(library_a ...) target_link_libraries(library_a STATIC base_library) add_library(library_b ...) target_link_libraries(library_b STATIC base_library) add_executable(main ...) target_link_libraries(main library_a library_b)
In this example, the
main binary links against 2 libraries,
library_b, both of which link against the
Now, CMake will generate the NVCC linking command so that main links against:
And since we have
base_library included twice, it will complain about multiple definitions.
Is this intended? How could we solve it?