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