CMAKE_CXX_SOURCE_FILE_EXTENSIONS 无法使用 thrust/cuda

CMAKE_CXX_SOURCE_FILE_EXTENSIONS not working with thrust/cuda

Thrust 允许在 cmake 配置时通过 THRUST_DEVICE_SYSTEM 标志指定不同的后端。我的问题是我有一堆 .cu 文件,当用户使用 -DTHRUST_DEVICE_SYSTEM=OMP (例如)运行 cmake 时,我想将这些文件编译为常规 c++ 文件。如果我将 .cu 文件的扩展名更改为 .cpp,它们编译得很好(表明我只需要告诉 cmake 在 .cu 文件上使用 c++ 编译器)。但是,如果我将 .cu 添加到 CMAKE_CXX_SOURCE_FILE_EXTENSIONS,那么我会得到 CMake Error: Cannot determine link language for target "cuda_kernels"。这是一个最小的 cmake 示例:

cmake_minimum_required(VERSION 3.19)

project(kernels LANGUAGES C CXX Fortran)

set(KERNELS_USE_OMP OFF)
if ("${THRUST_DEVICE_SYSTEM}" STREQUAL "OMP")
  set(KERNELS_USE_OMP ON)
endif()

# verify CUDA support
include(CheckLanguage)
check_language(CUDA)
if (CMAKE_CUDA_COMPILER AND NOT KERNELS_USE_OMP)
  enable_language(CUDA)
else()
  list(PREPEND CMAKE_CXX_SOURCE_FILE_EXTENSIONS "cu;CU")
endif()

message(STATUS "${CMAKE_CXX_SOURCE_FILE_EXTENSIONS}")

find_package(Thrust REQUIRED CONFIG)
thrust_create_target(Thrust FROM_OPTIONS)


add_library(cuda_kernels my_kernels.cu)
target_link_libraries(cuda_kernels Thrust)

message 命令在我的系统上的输出是:-- cu;CU;C;M;c++;cc;cpp;cxx;mm;mpp;CPP;ixx;cppm

为什么 cmake 不尊重我的 CMAKE_CXX_SOURCE_FILE_EXTENSIONS 更改?

Why is cmake not respecting my CMAKE_CXX_SOURCE_FILE_EXTENSIONS changes?

<LANG> 的 extension-to-language 会在语言检测模块退出时通过检查 CMAKE_<LANG>_SOURCE_FILE_EXTENSIONS 变量的值来启用 <LANG> 后立即设置。

不幸的是,CXX 没有像 Modules/CMakeCXXCompiler.cmake.in 中的 hard-coded 那样覆盖此列表的好方法。

也许解决实际错误的最佳方法是使用 LANGUAGE 源文件 属性 告诉 CMake 如何编译单个 CUDA 文件,如下所示:

cmake_minimum_required(VERSION 3.19)
project(kernels LANGUAGES CXX)

find_package(Thrust REQUIRED)
thrust_create_target(Thrust FROM_OPTIONS)

thrust_is_cuda_system_found(USE_CUDA)
if (USE_CUDA)
  enable_language(CUDA)
endif()

set(cuda_kernel_sources my_kernels.cu)

add_library(cuda_kernels ${cuda_kernel_sources})
target_link_libraries(cuda_kernels PRIVATE Thrust)

if (NOT USE_CUDA)
  set_source_files_properties(
    ${cuda_kernel_sources}
    PROPERTIES
    LANGUAGE CXX
  )
endif ()

这对于可能尝试 add_subdirectory 你的项目的其他项目来说肯定会更友好。


不过,如果我们想很调皮,我们可以这样做:

cmake_minimum_required(VERSION 3.19)
project(kernels LANGUAGES NONE)

###
# Hacky language extension override

function(add_cuda_extensions variable access value current_list_file stack)
  if (NOT cu IN_LIST value)
    list(PREPEND "${variable}" "cu" "CU")
    set("${variable}" "${${variable}}" PARENT_SCOPE)
  endif ()
endfunction()

# verify CUDA support
include(CheckLanguage)
check_language(CUDA)
if (CMAKE_CUDA_COMPILER AND NOT THRUST_DEVICE_SYSTEM STREQUAL "OMP")
  enable_language(CUDA)
  enable_language(CXX)
else()
  variable_watch(CMAKE_CXX_SOURCE_FILE_EXTENSIONS add_cuda_extensions)
  enable_language(CXX)
endif()

###
# Normal project code starts here

message(STATUS "${CMAKE_CXX_SOURCE_FILE_EXTENSIONS}")

find_package(Thrust REQUIRED)
thrust_create_target(Thrust FROM_OPTIONS)

add_library(cuda_kernels my_kernels.cu)
target_link_libraries(cuda_kernels PRIVATE Thrust)

这会等待平台模块尝试写入 CMAKE_CXX_SOURCE_FILE_EXTENSIONS,然后在任何时候访问它时,快速将 cuCU 扩展名插入列表。