Hi,
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:
https://devblogs.nvidia.com/building-cuda-applications-cmake/
code-samples/posts/cmake at master · robertmaynard/code-samples · GitHub -
In the CMakeLists.txt, replace:
target_link_libraries(particle_test PRIVATE particles)
with:
target_link_libraries(particle_test PRIVATE particles particles)
- Compile:
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
Use case
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_a
and library_b
, both of which link against the base_library
.
Now, CMake will generate the NVCC linking command so that main links against:
library_a
, base_library
, library_b
, base_library
And since we have base_library
included twice, it will complain about multiple definitions.
Is this intended? How could we solve it?
Thanks!