Visual Studio/CMake 中未解析的外部符号 cuda_library::foo(int)
unresolved external symbol cuda_library::foo(int) in Visual Studio/CMake
原题(标题:.cu 文件在 Visual Studio/CMake 中被处理为 .cpp 文件)
我正在尝试将带有 CUDA 代码的静态库添加到我的 C++ 项目中。我有一个顶级 CMakeLists.txt
文件,一个从那里添加的静态库,以及从该库添加的我的 CUDA-using 库(两个库都有自己的 CMakeLists.txt
文件。在根文件中我在一级图书馆的CMakeLists.txt
中使用了enable_language(CUDA)
,我这样做了:
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 的“全部构建”(或 运行 带有忍者的 CMake,通常可以使用 [=32 编译简单的 CUDA 示例=],错误是相同的)而且我不在 cuda_library.cu
文件中,我只得到归结为 unresolved external symbol cuda_library::foo(int)
的错误,根据一些研究,这意味着函数可能被声明但没有定义。如果包含 header 但未正确编译 .cu
文件,这是有意义的。
但是,只有当我使 .cu
文件处于活动状态时,VS 才会向我显示与 CUDA 代码相关的错误,它们被视为 C++ 代码,并且它们没有正常的错误徽标(如第一个此图像中的错误),但您可以在第二个和第三个中看到:
那么它们可能只是在构建时不会出现的智能感知错误吗?
在这种情况下,可能还有另一个原因导致静态库的实现未正确链接。为了更彻底,这是 header (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
我真的不明白到底出了什么问题,所以欢迎任何帮助。
你必须在每个源cpp文件中添加一个属性来表示它真的是一个cuda源。
set_source_files_properties(file.cpp PROPERTIES LANGUAGE CUDA)
启用 CUDA 作为语言后 (enable_language(CUDA)
)。
我们使用它,但我不知道这是否是一个好的做法(欢迎提供反馈)。
我意识到有两个主要因素阻止了它的工作:
- 函数签名中的
inline
似乎自行破坏了它(此时我不太关心我的代码中的它而不是删除它,如果有人想对其进行更多调查的话他们可以自由地做。
enable_language(CUDA)
必须在顶级 CMakeLists.txt
文件中。
修复它构建的这两个东西没有任何问题。
原题(标题:.cu 文件在 Visual Studio/CMake 中被处理为 .cpp 文件)
我正在尝试将带有 CUDA 代码的静态库添加到我的 C++ 项目中。我有一个顶级 CMakeLists.txt
文件,一个从那里添加的静态库,以及从该库添加的我的 CUDA-using 库(两个库都有自己的 CMakeLists.txt
文件。在根文件中我在一级图书馆的CMakeLists.txt
中使用了enable_language(CUDA)
,我这样做了:
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 的“全部构建”(或 运行 带有忍者的 CMake,通常可以使用 [=32 编译简单的 CUDA 示例=],错误是相同的)而且我不在 cuda_library.cu
文件中,我只得到归结为 unresolved external symbol cuda_library::foo(int)
的错误,根据一些研究,这意味着函数可能被声明但没有定义。如果包含 header 但未正确编译 .cu
文件,这是有意义的。
但是,只有当我使 .cu
文件处于活动状态时,VS 才会向我显示与 CUDA 代码相关的错误,它们被视为 C++ 代码,并且它们没有正常的错误徽标(如第一个此图像中的错误),但您可以在第二个和第三个中看到:
那么它们可能只是在构建时不会出现的智能感知错误吗?
在这种情况下,可能还有另一个原因导致静态库的实现未正确链接。为了更彻底,这是 header (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
我真的不明白到底出了什么问题,所以欢迎任何帮助。
你必须在每个源cpp文件中添加一个属性来表示它真的是一个cuda源。
set_source_files_properties(file.cpp PROPERTIES LANGUAGE CUDA)
启用 CUDA 作为语言后 (enable_language(CUDA)
)。
我们使用它,但我不知道这是否是一个好的做法(欢迎提供反馈)。
我意识到有两个主要因素阻止了它的工作:
- 函数签名中的
inline
似乎自行破坏了它(此时我不太关心我的代码中的它而不是删除它,如果有人想对其进行更多调查的话他们可以自由地做。 enable_language(CUDA)
必须在顶级CMakeLists.txt
文件中。
修复它构建的这两个东西没有任何问题。