c++cudalinkeroptix

undefined reference to `cuCtxGetCurrent` while getting CUDA context for OptiX


I'm trying to learn how to implement OptiX into my C++ project. One of the first steps is to get the current CUDA context with cuCtxGetCurrent(&some_CUcontext_variable), however I'm getting a compile time error saying that I've made an undefined reference to cuCtxGetCurrent.

Here's what I have:

I believe this error is linker related, so I'm assume I'm missing something in my CMakeLists, but I don't know what. Please let me know how I can fix this issue!

Thank you in advanced for your help!


Update #2: Solved

It's moments like this make make me pull my hair out: all I had to do with literally put cuda in my target link libraries. Not -lcuda or CUDA::cuda, just cuda. Somehow that linked in the drivers and it looks to be compiling now.


[OLD, BUT KEPT FOR REFERENCE] Update #1: Here's my CMakeLists.txt.

Sorry for the lack of code in my original post. I was trying to avoid pasting large chunks of arbitrary code.

cmake_minimum_required(VERSION 3.17)
project(My_Project_Name CUDA CXX)

set(CMAKE_CXX_STANDARD 14)

set(CMAKE_MODULE_PATH
    "${CMAKE_SOURCE_DIR}/cmake"
    ${CMAKE_MODULE_PATH})

find_package(CUDAToolkit REQUIRED)
find_package(OptiX REQUIRED VERSION 7.0)

add_executable(
    ${PROJECT_NAME}
    main.cpp [and other cpp and cu files])

# For project
set_target_properties(
    ${PROJECT_NAME}
    PROPERTIES
    CUDA_SEPARABLE_COMPILATION ON
)
target_compile_options(
    ${PROJECT_NAME}
    PRIVATE
    $<$<COMPILE_LANGUAGE:CUDA>:
    -arch=sm_61
    -gencode arch=compute_52,code=sm_52>
)
target_include_directories(
    ${PROJECT_NAME}
    PRIVATE
    include
    ${OptiX_INCLUDE}
)
target_link_libraries(
    ${PROJECT_NAME}
    PRIVATE
    CUDA::cudart
    CUDA::cublas
)

Solution

  • As @talonmies notes, CUDA has two (official) host-side APIs: The "CUDA Runtime API" and the "CUDA Driver API"; you can read about the difference between them here.

    You have mentioned files and CMake identifiers relating to the Runtime API: cuda_runtime.h, CUDA::cudart. But - "CUDA Contexts" are concepts of the Driver API, and cuCtxGetCurrent() etc. are driver API calls.

    Specifically, an "undefined reference" is indeed a linker error. In your case, you need to link with the CUDA driver. As a library, on Linux systems, that's called libcuda.so. For that to happen, and for your executable named ERPT_Render_Engine, you need to add the command:

    target_link_libraries(ERPT_Render_Engine cuda)
    

    I'll also say that the CMakeLists.txt you listed above looks weird, because it defines dependencies for a target that doesn't exist - the project name; your relevant target is your executable.

    Additionally - a CUDA context doesn't exist merely by virtue of you creating your process. You need to initialize the driver, create a context and make it current - or have something else do that for you (like a library) - before you can obtain the current context using cuCtxGetCurrent().


    Finally, and in case you're interested, I am the author of the C++ cuda-api-wrappers library, which covers (most of) the host-side functionality of both the driver and runtime APIs. Some example code:

    cuda::initialize_driver();
    (cuda::device::count() > 0) or die_("No CUDA devices on this system")
    auto device_id =  cuda::device::default_device_id;
    auto device = cuda::device::get(device_id);
    auto context = cuda::context::create(device);
    //etc. etc.
    

    and when you using it within CMake (explained on the repository page), the dependencies are taken care of. But again - you really don't have to use this, it's just a convenience.