8

I'm trying to build a program that requires CUDA. To the CMake script I supply:

cmake -D CUDA_TOOLKIT_ROOT_DIR=/usr/local/cuda ..

CUDA is found and CMake runs normally:

staudt ~/workspace/clutbb/cluster/build $ cmake -D CUDA_TOOLKIT_ROOT_DIR=/usr/local/cuda ..                                                                                  
-- Found CUDA: /usr/local/cuda (found version "6.5") 
-- Found Intel TBB
-- Boost version: 1.56.0
-- Found the following Boost libraries:
--   iostreams
--   program_options
-- Looking for include file pthread.h
-- Looking for include file pthread.h - found
-- Looking for pthread_create
-- Looking for pthread_create - not found
-- Looking for pthread_create in pthreads
-- Looking for pthread_create in pthreads - not found
-- Looking for pthread_create in pthread
-- Looking for pthread_create in pthread - found
-- Found Threads: TRUE  
-- Could NOT find SDL (missing:  SDL_LIBRARY SDL_INCLUDE_DIR) 
-- Configuring done
-- Generating done
-- Build files have been written to: /home/i11/staudt/workspace/clutbb/cluster/build

But then the linker step fails:

staudt ~/workspace/clutbb/cluster/build $ make
[ 69%] Built target cluster
Linking CXX executable clu
CMakeFiles/clu.dir/clu.cpp.o: In function `initCUDA(int&, CUctx_st*&, int const&)':
clu.cpp:(.text+0x517): undefined reference to `cuInit'
clu.cpp:(.text+0x52b): undefined reference to `cuDeviceGet'
clu.cpp:(.text+0x53f): undefined reference to `cuCtxCreate_v2'
clu.cpp:(.text+0x559): undefined reference to `cuDeviceGetName'
clu.cpp:(.text+0x55e): undefined reference to `cuCtxSynchronize'
CMakeFiles/clu.dir/clu.cpp.o: In function `exitCUDA(int&, CUctx_st*&)':
clu.cpp:(.text+0x684): undefined reference to `cuCtxDestroy_v2'
CMakeFiles/clu.dir/clu.cpp.o: In function `main':
clu.cpp:(.text.startup+0x1092): undefined reference to `cuCtxDestroy_v2'
clu.cpp:(.text.startup+0x10d1): undefined reference to `cuCtxSynchronize'
clu.cpp:(.text.startup+0x10e1): undefined reference to `cuCtxSynchronize'
collect2: error: ld returned 1 exit status
make[2]: *** [bin/clu] Fehler 1
make[1]: *** [bin/CMakeFiles/clu.dir/all] Fehler 2
make: *** [all] Fehler 2

The required library is at /usr/local/cuda/lib64/stubs/libcuda.so, but how can I point that out to cmake or make?

clstaudt
  • 21,436
  • 45
  • 156
  • 239
  • 3
    The `libcuda.so` that should be linked against is typically not the one at the directory you have shown. The proper `libcuda.so` is installed by the *driver*, not the CUDA installer. It will typically be found at `/usr/lib64` or some place like that. Somewhere you have either a `-lcuda` missing in your make process, or else the library directory search path is not set up to point to the proper location of `libcuda.so` on your machine. `/usr/local/cuda/...` is normally not the right place to look for `libcuda.so` – Robert Crovella Nov 19 '14 at 14:17
  • The linker command is `/usr/bin/c++ -O3 -Wall -ffast-math -DNDEBUG -DLEAN CMakeFiles/clu.dir/clu.cpp.o -o clu -rdynamic /usr/local/cuda/lib64/libcudart.so -ltbb -lboost_iostreams-mt -lboost_program_options-mt -lrt ../src/libcluster.a /usr/local/cuda/lib64/libcudart.so -Wl,-rpath,/usr/local/cuda/lib64 ` There is no `-lcuda`, and I have not the slightest idea how to add it. – clstaudt Nov 19 '14 at 14:21
  • I updated my response a little bit, see if that fixes your problems. – Anycorn Nov 19 '14 at 14:43
  • I'm a bit confused by the discussion: Apparently CMake reports that it finds CUDA but fails to generate a `-lcuda`linker flag, right? – clstaudt Nov 20 '14 at 11:30
  • 3
    Briefly, CUDA apps fall into 2 categories. Driver API apps and those that use the runtime API. Runtime API apps, arguably more common, do not require linking against libcuda. So CMake "finding" CUDA presumably means that it is set up to build a runtime API CUDA app. You will need to discover how to push the magic buttons in CMake to build a driver API app. I'm not a CMake expert. If you read the question immediately prior to yours in the CUDA tag, it discusses driver API vs. runtime API. The answers by Anycorn, mostly talking about paths, won't address the lack of `-lcuda`, I don't think. – Robert Crovella Nov 20 '14 at 14:13
  • Can you show your `CMakeLists.txt` file, especially the lines around the `cuda_add_executable()` line? Suppose that line contains an executable name of `clu`. Then try adding the following line somewhere after that line: `target_link_libraries(clu cuda)` And you may already have such a line, in which case you can just add `cuda` (or `-lcuda`) to the list. – Robert Crovella Nov 23 '14 at 01:55
  • @RobertCrovella This is the CMakeLists.txt: https://gist.github.com/anonymous/5b2954b50df1150cfd24 - seems that this is only a part of the CMake machinery for this project, where is the rest? – clstaudt Nov 23 '14 at 15:38
  • @RobertCrovella I've uploaded the complete project files here: https://dl.dropboxusercontent.com/u/8870493/clutbb.zip – clstaudt Nov 23 '14 at 15:58
  • I have had problems like this in the past with cmake. The way I solve them is to open the cmake file with cmake-gui, look at relevant entries (cuda, cuda linker, LD flags and fix the offending entry). – XapaJIaMnu Nov 24 '14 at 11:50

3 Answers3

7

In the archive you have now posted, there are multiple project hierarchies. The actual error you have posted in the question is occurring during compile and linking of the clu project based on clu.cpp in the clutbb/cluster/bin directory.

In this same directory, there is a CMakeLists.txt file. This file governs this particular level of the project hierarchy.

In this particular CMakeLists.txt file, there is the following section:

cuda_add_executable(clu clu.cpp)
target_link_libraries(clu ${CUDA_LIBRARY} ${TBB_LIBRARY} ${Boost_LIBRARIES} rt)
target_link_libraries(clu cluster)

Try modifying the middle line above to:

target_link_libraries(clu ${CUDA_LIBRARY} ${TBB_LIBRARY} ${Boost_LIBRARIES} rt cuda)

This should fix the missing -lcuda in the linker command line. It may still be necessary to give it the path to libcuda.so on your machine, but it may not be necessary, depending on how your machine environment is set up.

Robert Crovella
  • 143,785
  • 11
  • 213
  • 257
  • Thanks, this solved the problem partially. Another problem was that the proper Nvidia CUDA drivers were not installed on my system so that `libcuda.so` was not found. In the end I was able to build the project. – clstaudt Nov 24 '14 at 15:26
4

The correct way of doing this on CMake 3.17+ is to use the FindCUDAToolkit module, like so:

find_package(CUDAToolkit REQUIRED)
target_link_libraries(my_target PRIVATE CUDA::cudart CUDA::cuda_driver)

The CUDA::cuda_driver target is equivalent to -lcuda when the linker would find it, and is otherwise an absolute path to the correct library. You should avoid adding system libraries via target_link_libraries to ensure portability.


If you have an older version (CMake 3.0+), you can use the (now-deprecated) FindCUDA module to imitate the 3.17 module, like so:

find_package(CUDA REQUIRED)

# Do what the new package does
find_library(CUDA_DRIVER_LIBRARY
             NAMES cuda_driver cuda
             HINTS ${CUDA_TOOLKIT_ROOT_DIR}
                   ENV CUDA_PATH
             PATH_SUFFIXES nvidia/current lib64 lib/x64 lib)
if (NOT CUDA_DRIVER_LIBRARY)
    # Don't try any stub directories until we have exhausted all other search locations.
    find_library(CUDA_DRIVER_LIBRARY
                 NAMES cuda_driver cuda
                 HINTS ${CUDA_TOOLKIT_ROOT_DIR}
                       ENV CUDA_PATH
                 PATH_SUFFIXES lib64/stubs lib/x64/stubs lib/stubs stubs)
endif ()
mark_as_advanced(CUDA_DRIVER_LIBRARY)
##

target_include_directories(my_target PRIVATE ${CUDA_INCLUDE_DIRS})
target_link_libraries(my_target PRIVATE ${CUDA_LIBRARIES} ${CUDA_DRIVER_LIBRARY})

This is adapted from the official sources, here.

rerx
  • 1,133
  • 8
  • 19
Alex Reinking
  • 16,724
  • 5
  • 52
  • 86
0

The C++ file with host calls doesnt know it needs to link to libcudart. You have to explicitly set dependencies for the file/binary that file is in, eg.

target_link_libraries(clu ${CUDA_LIBRARIES})

The above response is slightly wrong. It looks like libcuda.so is installed in unexpected location for whatever reason. You can try setting CMAKE_LIBRARY_PATH or/and CUDA_LIB_PATH to that path.

The CUDA_LIB_PATH needs to be set outside cmake I think, eg export CUDA_LIB_PATH=/usr/local/cuda/lib64/stubs/

Anycorn
  • 50,217
  • 42
  • 167
  • 261
  • 4
    libcudart isn't the missing library here. The application appears to be using the driver API and needs to link against libcuda, as OP has indicated. Somewhere a `-lcuda` is missing, or the library search is not quite right. CMake conveniently doesn't bother to show you the commands it is issuing. – Robert Crovella Nov 19 '14 at 14:14
  • @RobertCrovella Ah, yes, I see now. – Anycorn Nov 19 '14 at 14:35
  • In FindCUDA.cmake (at least in 2.8) CUDA_LIB_PATH env var will be searched for libcuda. If cuda library is installed in non-standard location (as is the case with the post) this should help to at least link to libcuda – Anycorn Nov 19 '14 at 16:19