3

I've got an issue with what I believe is a linker error when compiling a CUDA project with catkin. A snippet of the source code is below. When I try to run catkin build I get an error:

error

In function `curand_init(double*, int, int):
./src/cwru_cuda.cu undefined reference to `curandCreateGenerator'
./src/cwru_cuda.cu undefined reference to `curandSetPseudoRandomGeneratorSeed'

I checked the verbose build output and it is using c++ to link the file, it is passing the appropriate flags like I defined in CURAND_FLAGS. I'm not sure what else might be the issue here? I'm not very knowledgeable about build tools.

CURAND reference

cwru_cuda.h

#include <cuda.h>
#include <cuda_runtime.h>
#include <curand.h>
#include <helper_cuda.h>
#include <device_launch_parameters.h>

void curand_init(double*, int, int);

cwru_cuda.cu

#include <cwru_cuda.h>

curandGenerator_t __curand_gen;
double* __curand_float_address;
size_t __curand_float_size;
int __curand_num_elems;

void curand_init(double* address, int numElements, int seed = 1234) {
    curandCreateGenerator(&__curand_gen, CURAND_RNG_PSEUDO_DEFAULT);
    curandSetPseudoRandomGeneratorSeed(__curand_gen, seed);
    __curand_num_elems = numElements;
    __curand_float_size = numElements * sizeof(double);
    cudaMallocManaged(&__curand_float_address, __curand_float_size);
}

CMakeLists.txt

cmake_minimum_required(VERSION 2.8.3)
project(cwru_cuda)

find_package(catkin REQUIRED COMPONENTS
  roscpp
  std_msgs
)

# https://stackoverflow.com/questions/25748039/add-cuda-to-ros-package

find_package(CUDA REQUIRED) 

# set CUDA_NVCC_FLAGS as you would do with CXX/C FLAGS         
set(CUDA_NVCC_FLAGS CACHE STRING "nvcc flags" FORCE)
set(CUDA_VERBOSE_BUILD ON CACHE BOOL "nvcc verbose" FORCE)
set(CURAND_FLAGS "-lcurand_static -lculibos -lcudart_static -lpthread -ldl -I /usr/local/cuda/include -L /usr/local/cuda/lib64")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CURAND_FLAGS}")
set(LIB_TYPE STATIC) 
cuda_add_library(cuda_vector_lib ${LIB_TYPE} src/cwru_cuda.cu)

catkin_package(
  INCLUDE_DIRS include
  LIBRARIES cuda_vector_lib
#  CATKIN_DEPENDS roscpp std_msgs
#  DEPENDS system_lib
)

include_directories(
  include
  ${catkin_INCLUDE_DIRS}
)

add_executable(cuda_vector_test src/tests.cpp src/Timer.cpp)

add_dependencies(cuda_vector_test cuda_vector_lib)

TARGET_LINK_LIBRARIES(cuda_vector_test
    ${catkin_LIBRARIES}
    cuda_vector_lib
)

Building with catkin build cwru_cuda --verbose

build output

make[2]: Entering directory '/home/ethan/catkin_ws/build/cwru_cuda'
[ 60%] Linking CXX executable /home/ethan/catkin_ws/devel/.private/cwru_cuda/lib/cwru_cuda/cuda_vector_test
/usr/bin/cmake -E cmake_link_script CMakeFiles/cuda_vector_test.dir/link.txt --verbose=1
/usr/bin/c++   -lcurand_static -lculibos -lcudart_static -lpthread -ldl -I /usr/local/cuda/include -L /usr/local/cuda/lib64  -rdynamic CMakeFiles/cuda_vector_test.dir/src/tests.cpp.o CMakeFiles/cuda_vector_test.dir/src/Timer.cpp.o  -o /home/ethan/catkin_ws/devel/.private/cwru_cuda/lib/cwru_cuda/cuda_vector_test -Wl,-rpath,/opt/ros/melodic/lib /opt/ros/melodic/lib/libroscpp.so -lboost_filesystem /opt/ros/melodic/lib/librosconsole.so /opt/ros/melodic/lib/librosconsole_log4cxx.so /opt/ros/melodic/lib/librosconsole_backend_interface.so -llog4cxx -lboost_regex /opt/ros/melodic/lib/libxmlrpcpp.so /opt/ros/melodic/lib/libroscpp_serialization.so /opt/ros/melodic/lib/librostime.so /opt/ros/melodic/lib/libcpp_common.so -lboost_system -lboost_thread -lboost_chrono -lboost_date_time -lboost_atomic -lpthread /usr/lib/x86_64-linux-gnu/libconsole_bridge.so.0.4 libcuda_vector_lib.a /usr/local/cuda-11.0/lib64/libcudart_static.a -lpthread -ldl -lrt 
libcuda_vector_lib.a(cuda_vector_lib_generated_cwru_cuda.cu.o): In function `curand_init(double*, int, int)':
/home/ethan/catkin_ws/src/cwru_cuda/src/cwru_cuda.cu:23: undefined reference to `curandCreateGenerator'
/home/ethan/catkin_ws/src/cwru_cuda/src/cwru_cuda.cu:24: undefined reference to `curandSetPseudoRandomGeneratorSeed'
libcuda_vector_lib.a(cuda_vector_lib_generated_cwru_cuda.cu.o): In function `generate_uniform_double()':
/home/ethan/catkin_ws/src/cwru_cuda/src/cwru_cuda.cu:31: undefined reference to `curandGenerateUniformDouble'
collect2: error: ld returned 1 exit status
CMakeFiles/cuda_vector_test.dir/build.make:141: recipe for target '/home/ethan/catkin_ws/devel/.private/cwru_cuda/lib/cwru_cuda/cuda_vector_test' failed
Ethan Shafer
  • 68
  • 2
  • 16
  • 1
    It would be helpful if you posted the actual build output. Clearly the curand library isn't being linked. Why comes down to understanding the build commands emitted by the make system, which we can't see – talonmies Oct 30 '20 at 02:46
  • Thanks, I edited the question to display the build output with the --verbose flag. edit: There is a number of lines of output prior to this as well, but this seemed to be the pertinent information. – Ethan Shafer Oct 30 '20 at 15:31
  • 1
    Depending on the actual c++ compiler toolchain in use, the linker may not like the fact that you have (a few) listed libraries first, followed by objects to link. Later versions of g++ for example desire that link dependencies be satisfied in a left-to-right order. Given that the linker is not complaining about not being able to find, for example, `-lcurand_static` (where the dependendency is satisfied) I think this is worth investigating. – Robert Crovella Oct 30 '20 at 18:01
  • 1
    rather than trying to satisfy your CURAND dependency via `CMAKE_CXX_FLAGS` perhaps you should use the method [here](https://stackoverflow.com/questions/51236835/cmake-3-11-linking-cublas). – Robert Crovella Oct 30 '20 at 18:28

1 Answers1

3

Robert Crovella answered this question in the comments above.

I was able to use target_link_libraries() to set -lcurand and -lcublas which satisfied the dependencies. So I added the following line to my CMakeLists.txt

target_link_libraries(cuda_vector_lib -lcublas -lcurand)
Ethan Shafer
  • 68
  • 2
  • 16