Visual Studio/CMake 中未解析的外部符号 cuda_library::foo(int)

Posted

技术标签:

【中文标题】Visual Studio/CMake 中未解析的外部符号 cuda_library::foo(int)【英文标题】:unresolved external symbol cuda_library::foo(int) in Visual Studio/CMake 【发布时间】:2021-08-02 02:31:57 【问题描述】:

原题(题目:.cu 文件在 Visual Studio/CMake 中被处理为 .cpp 文件)

我正在尝试将带有 CUDA 代码的静态库添加到我的 C++ 项目中。我有一个*** CMakeLists.txt 文件,一个从那里添加的静态库,以及从该库添加的使用 CUDA 的库(两个库都有自己的 CMakeLists.txt 文件。在根文件中,我使用了 enable_language(CUDA) ,在一级图书馆的CMakeLists.txt我已经这样做了:

  add_subdirectory(cuda_library)
  set_target_properties(level_1_lib PROPERTIES POSITION_INDEPENDENT_CODE ON)
  set_target_properties(level_1_lib PROPERTIES CUDA_SEPARABLE_COMPILATION ON)
  target_link_libraries(level_1_lib cuda_library)

在 CUDA 库的CMakeLists.txt

add_library(cuda_library 
  cuda_library.cu cuda_library.h)

target_include_directories(cuda_library
  INTERFACE $CMAKE_CURRENT_SOURCE_DIR
  )

1 级库中的 .cpp 文件调用我在 cuda_library.h 中声明的“接口函数”,该函数在 cuda_library.cu 中实现,并以这种方式在内部启动 CUDA __global__ 内核:

namespace cuda_library 
    __global__
    void real_foo(int number, int *out)  
        *out = number * 2; 
    

    inline int foo(int number)  
        int* x;
        
        cudaMallocManaged(&x, sizeof(int));
        real_foo<<<1,1>>>(number, x); 
        cudaDeviceSynchronize();
        int y = *x;
        cudaFree(x);
        return y;
     

当我从 Visual Studio 构建时(启用了 CMake 扩展,它使用 ninja 作为生成器),但是,构建不喜欢 __global__ 关键字,让我认为 .cu 文件是像普通的 .cpp 文件一样对待,而不是编译为 CUDA 代码。

我做错了什么?

编辑以更好地澄清我得到的错误

如果我点击 Visual Studio 的“全部构建”(或从 Visual Studio 命令提示符使用 ninja 运行 CMake,通常可以使用 nvcc 编译简单的 CUDA 示例,错误是相同的)并且我不在cuda_library.cu 文件,我只得到归结为unresolved external symbol cuda_library::foo(int) 的错误,从一些研究来看,这意味着该函数可能已声明但未定义。如果包含标头但未正确编译 .cu 文件,则这是有意义的。

但是,只有当我使 .cu 文件处于活动状态时,VS 才会向我显示与被视为 C++ 代码的 CUDA 代码相关的错误,并且它们没有正常的错误徽标(就像这张图片中的第一个错误),但您可以在第二个和第三个中看到:

那么它们可能只是构建时没有出现的 Intellisense 错误吗?

在这种情况下,静态库的实现未正确链接可能还有另一个原因。为了更彻底,这是标题(cuda_library.h):

#ifndef _CUDA_LIBRARY_H_
#define _CUDA_LIBRARY_H_

namespace cuda_library 
    inline int foo(int number);


#endif

我尝试在出现unresolved external symbol cuda_library::foo(int) 错误的.cpp 文件中以这种方式导入和使用它:

#include "cuda_library/cuda_library.h"

printf("Result from the GPU: %d\n", cuda_library::foo(5));

有趣的是我也试过了

#include <cuda_library.h>

结果是一样的,可能是因为 CMake 将它包含在什么是包含搜索路径中?

项目结构如下:

root_dir\
  CMakeLists.txt
  libs\
    CMakeLists.txt
    level_1_lib\
      CMakeLists.txt
      file_using_cuda_lib.cpp
      cuda_library\
        CMakeLists.txt
        cuda_library.cu
        cuda_library.h

我真的不明白到底出了什么问题,所以任何帮助都会被接受。

【问题讨论】:

您是否在任何地方都启用了 CUDA 作为构建语言? 是的,我用过enable_language(CUDA) 在哪里?它没有显示在您的问题中的任何地方 在根级CMakeLists.txt文件中,我在问题的开头已经说过了。我还尝试在其他 CMakeLists.txt 文件中移动该语句,甚至只是在所有三个文件中都使用它,但没有成功。 我已经编辑了这个问题,以便更彻底地了解我所做的事情和我得到的错误。也许我在错误的地方寻找错误。 【参考方案1】:

您必须为每个源 cpp 文件添加一个属性,以说明它确实是一个 cuda 源。

    set_source_files_properties(file.cpp PROPERTIES LANGUAGE CUDA)

在启用 CUDA 作为一种语言 (enable_language(CUDA)) 之后。

我们使用它,但我不知道这是否是一种好的做法(感谢您的反馈)。

【讨论】:

我意识到无论有没有你的选择,在输出上我都有Linking CUDA static library [...]\cuda_library.lib,所以错误绝对不是文件被视为.cpp 我不明白你是怎么得出这个结论的。无论如何,请检查您的实际编译行,例如在详细模式下,看看它是如何尝试编译或链接有问题的文件的。 我在 VS 的输出中看到了上面的语句或Building CUDA object [...]\cuda_library.cu.obj,而其他行类似于Building CXX object [...]【参考方案2】:

我意识到有两个主要因素阻止了它的工作:

函数签名中的inline 似乎自行破坏了它(此时我在我的代码中不太关心它而不删除它,如果有人想对其进行更多调查,他们是免费的去做)。 enable_language(CUDA) 必须位于*** CMakeLists.txt 文件中。

修复它构建的这两个东西没有任何问题。

【讨论】:

以上是关于Visual Studio/CMake 中未解析的外部符号 cuda_library::foo(int)的主要内容,如果未能解决你的问题,请参考以下文章

错误 LNK2019:Visual Studio 中未解析的外部符号 [重复]

C++:Visual Studio 2015 中未解析的外部符号 _sprintf 和 _sscanf

Google Test:错误LNK2019:Visual Studio 2013中未解析的外部符号

Visual Studio 2008 中未显示属性页

Visual Studio 远程调试中未命中断点

在 Visual Studio 2017 中未发现单元测试