You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用CMake分别编译*.cpp与*.cu文件解决CUDA项目编译报错

错误原因分析

  • 第一版CMake错误:同时定义了两个包含相同C++源文件的可执行目标cuda和Project_4,且混用了已废弃的旧版CUDA CMake接口cuda_add_executable和3.10+版本原生支持的CUDA语言编译逻辑,导致中间生成文件冲突,触发.cu.o相关的CMake报错。
  • 第二版CMake错误:完全未将.cu文件加入可执行目标的源文件列表,且如果CUDA核函数调用的<<<>>>语法直接写在.cpp文件中,会被C++编译器(GCC/Clang)识别为非法语法,因此抛出<符号前缺少表达式的语法错误。

修复方案

1. 修正CMakeLists.txt配置

3.16版本CMake原生支持CUDA语言编译,无需调用FindCUDA等旧版模块,也无需使用cuda_add_executable接口,正确配置如下:

cmake_minimum_required(VERSION 3.16)
project(Project_4 LANGUAGES CXX CUDA)

# 语言标准设置
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CUDA_STANDARD 17)
set(CMAKE_CUDA_STANDARD_REQUIRED ON)
set(CMAKE_BUILD_TYPE Release)

# 输出路径设置
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/build)

# 头文件路径
include_directories(include)

# 自动适配当前设备的CUDA架构,无需手动指定sm版本
# 如需手动指定,可改为set(CMAKE_CUDA_ARCHITECTURES 75) 对应10系/20系显卡,86对应30系显卡
set(CMAKE_CUDA_ARCHITECTURES Auto)

# 收集所有源文件,同时包含cpp和cu文件
file(GLOB_RECURSE DIR_SRCS 
    ${PROJECT_SOURCE_DIR}/src/*.cpp
    ${PROJECT_SOURCE_DIR}/src/*.cu
)

# 原生add_executable会自动识别后缀,用NVCC编译cu文件,用C++编译器编译cpp文件
add_executable(Project_4 ${DIR_SRCS})

# 链接CUDA依赖库
target_link_libraries(Project_4 PRIVATE ${CUDA_LIBRARIES})

# 开启CUDA分离编译
set_target_properties(Project_4 PROPERTIES
    CUDA_SEPARABLE_COMPILATION ON
)

注意:原配置中的arch=compute_30,code=sm_30对应开普勒架构显卡,CUDA 11及以上版本已完全弃用该架构支持,若使用新版本CUDA会触发编译报错,建议直接用CMAKE_CUDA_ARCHITECTURES Auto自动适配。

2. 代码层面适配

不要在.cpp文件中直接使用<<<>>>语法调用CUDA核函数,建议采用接口封装方案:

  1. 在头文件中定义C/C++兼容的接口函数,例如matrix_mul_cuda.h:
#pragma once
// 矩阵乘法CUDA实现对外接口,无CUDA专属语法
void matrix_mul_cuda(const float* a, const float* b, float* c, int m, int n, int k);
  1. 在对应的.cu文件中实现接口,内部调用核函数:
#include "matrix_mul_cuda.h"

// 核函数仅在cu文件内部可见
__global__ void mat_mul_kernel(const float* a, const float* b, float* c, int m, int n, int k) {
    // 核函数逻辑实现
}

void matrix_mul_cuda(const float* a, const float* b, float* c, int m, int n, int k) {
    dim3 block_size(32, 32);
    dim3 grid_size((n + 31) / 32, (m + 31) / 32);
    // <<<>>>语法仅出现在cu文件中,由NVCC编译
    mat_mul_kernel<<<grid_size, block_size>>>(a, b, c, m, n, k);
    cudaDeviceSynchronize();
}
  1. C++代码中直接引入头文件调用封装后的接口即可,无需处理CUDA专属语法。
    如果确实需要在原有.cpp文件中写核函数调用,直接将该文件后缀改为.cu即可,CMake会自动识别并使用NVCC编译。

内容的提问来源于stack exchange,提问作者zephyrus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 02:24:04