如何“告诉”CMake 3.9+ 我想使用 NVIDIA 的 OpenCL 库?

Posted

技术标签:

【中文标题】如何“告诉”CMake 3.9+ 我想使用 NVIDIA 的 OpenCL 库?【英文标题】:How can I "tell" CMake 3.9+ I want to use NVIDIA's OpenCL library? 【发布时间】:2021-08-10 23:01:52 【问题描述】:

在我的CMakeLists.txt 我有:

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

这会找到 CUDA 和 OpenCL。但是 - 它更喜欢我系统的非 NVIDIA OpenCL 库,而不是 CUDA 安装附带的库。实际上,它比那更糟糕,因为我得到了:

//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

在我的CMakeCache.txt 文件中。

我怎样才能从 CMakeLists.txt 中(即不是作为用户而是作为包维护者)让 CMake 切换偏好顺序?

注意:是的,出于兼容性原因,它需要是 CMake 3.9。

【问题讨论】:

"是的,出于兼容性原因,它需要是 CMake 3.9。" - 我们以前也这么说,直到重新实现上游长期存在的行为的维护痛苦变得太大。现在我们在古老的 ARM SOC 上运行 CMake 3.20。这是一个决定,而不是要求 @AlexReinking:当您开发一个针对广泛受众的库时,您无法决定人们将拥有哪个版本的 CMake... Ubuntu 18.04+ 上的 CMake snap 始终是最新的并且会自动更新。 Ubuntu 20.04 的存储库中有 3.16,Kitware 为 18.04+ 提供了一个始终是最新的 APT 存储库。 Homebrew 始终是最新的。 VS2019 更新频繁,现在是 3.19。所有的二进制版本都可以在没有 admin/root 的情况下轻松安装,包括 aarch64。您的哪些用户(可能是 C++ 开发人员)拒绝更新基本工具? 可能您的用户必须在他们的系统上安装 CUDA 才能构建您的库。当他们等待 CUDA 下载时,他们可以安装 CMake @AlexReinking:嗯,显然,你是对的! 【参考方案1】:

由于您使用的是 CMake 3.9,因此您的双手非常紧张。


如果您使用的是 CMake 3.17+,那么您根本不应该找到 OpenCL。您只需使用 FindCUDAToolkitCUDA::OpenCL 目标:

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)

如果您使用的是 CMake 3.16,那么您仍然可以使用 FindCUDA 并使用包变量链接到 CUDA 找到的 OpenCL:

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)

如果您早在 3.12,那么您可以使用 <Pkg>_ROOT 变量来指导搜索:

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)

我希望找到合适的 OpenCL 版本。


但在早期版本中,您能做的最好的事情是使用 CUDA 根变量在 CUDA 安装中手动查找 OpenCL。然后,让FindOpenCL 创建导入的目标:

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)

【讨论】:

那么,find_path()find_library() 会偏向find_package() 调用的行为吗? @einpoklum 是的。这些 find 调用设置 FindOpenCL 使用的两个缓存变量:cmake.org/cmake/help/v3.9/module/FindOpenCL.html

以上是关于如何“告诉”CMake 3.9+ 我想使用 NVIDIA 的 OpenCL 库?的主要内容,如果未能解决你的问题,请参考以下文章

你如何告诉 CMake 静态链接到使用 find_package 找到的包中的库?

CMAKE 如何告诉 makefile 链接库?

使用 cmake 如何静态链接一些库和动态链接其他库?

如何告诉 cmake 在哪里输出其构建数据?

如何告诉 CMake(通过 externalNativeBuild 调用)在哪里寻找库?

如何将 cpplint.py 检查添加到 CMake 中?