Search code examples
cmakebuildcudaopencl

How can I "tell" CMake 3.9+ I want to use NVIDIA's OpenCL library?


In my CMakeLists.txt I have:

cmake_minimum_required(VERSION 3.9)
# ... etc etc ...
find_package(CUDA 8.0 REQUIRED)
find_package(OpenCL REQUIRED)

and this finds CUDA and OpenCL. But - it prefers my system's non-NVIDIA OpenCL library over the library which comes with the CUDA installation. Actually, it's worse than that, since I get:

//Path to a file.
OpenCL_INCLUDE_DIR:PATH=/usr/local/cuda/include

//Path to a library.
OpenCL_LIBRARY:FILEPATH=/usr/lib/x86_64-linux-gnu/libOpenCL.so

in my CMakeCache.txt file.

How can I, from within CMakeLists.txt (i.e. not as the user but as the package maintainer), get CMake to switch the order of preference?

Note: Yes, it needs to be CMake 3.9 for compatibility reasons.


Solution

  • Since you're on CMake 3.9, your hands are very much tied.


    If you were using CMake 3.17+ then you shouldn't find OpenCL at all. You would just use FindCUDAToolkit and the CUDA::OpenCL target:

    cmake_minimum_required(VERSION 3.17)
    project(test)
    
    find_package(CUDAToolkit 8.0 REQUIRED)
    
    add_executable(my_target ...)
    target_link_libraries(my_target PRIVATE CUDA::OpenCL)
    

    If you were using CMake 3.16, then you could still use FindCUDA and link to the CUDA-found OpenCL using the package variables:

    cmake_minimum_required(VERSION 3.16)
    project(test)
    
    find_package(CUDA 8.0 REQUIRED)
    
    cuda_add_executable(my_target ...)
    target_link_libraries(my_target PRIVATE ${CUDA_OpenCL_LIBRARY})
    

    If you were as far back as 3.12, then you could use the <Pkg>_ROOT variable to guide the search:

    cmake_minimum_required(VERSION 3.12)
    project(test)
    
    find_package(CUDA 8.0 REQUIRED)
    
    set(OpenCL_ROOT "${CUDA_TOOLKIT_ROOT_DIR}")
    find_package(OpenCL REQUIRED)
    

    and I would expect that to find the right OpenCL version.


    But on earlier versions, the best you can do is use the CUDA root variable to find OpenCL inside the CUDA installation manually. Then, let FindOpenCL create the imported target:

    cmake_minimum_required(VERSION 3.9)
    project(test)
    
    find_package(CUDA 8.0 REQUIRED)
    
    find_path(
      OpenCL_INCLUDE_DIR CL/opencl.h
      HINTS "${CUDA_TOOLKIT_ROOT_DIR}/include"
      NO_DEFAULT_PATH
    )
    
    if (CMAKE_SIZEOF_VOID_P EQUAL 8)
      set(opencl_lib64 "${CUDA_TOOLKIT_ROOT_DIR}/lib64" )
    endif()
    
    find_library(
      OpenCL_LIBRARY OpenCL
      HINTS ${opencl_lib64} "${CUDA_TOOLKIT_ROOT_DIR}/lib"
      PATH_SUFFIXES "${CMAKE_LIBRARY_ARCHITECTURE}"
      NO_DEFAULT_PATH
    )
    
    find_package(OpenCL REQUIRED)
    
    cuda_add_executable(my_target ...)
    target_link_libraries(my_target PRIVATE OpenCL::OpenCL)