Reputation: 373
I have the following project structure:
| CMakeLists.txt (1)
| main.cpp
| cudalib/
| CMakeLists.txt (2)
| cppfunction.cpp
| cudafunction.cu
| cudalib.h
and I am trying to build the content of the cudalib folder as a static library that is afterwards linked to by the main project. This process usually works if the static library has no CUDA code in it. But as soon as it has CUDA code, I get the following linker error when building the mainapp:
cudalib.lib(cudafunction.cu.obj) : error LNK2019: unresolved external symbol cudaMalloc referenced in function "void __cdecl cudafunction(void)" (?cudafunction@@YAXXZ)
cudalib.lib(cudafunction.cu.obj) : error LNK2019: unresolved external symbol __cudaRegisterLinkedBinary_c8e43a78_15_cudafunction_cu_4243b124 referenced in function "void __cdecl __nv_cudaEntityRegisterCallback(void * *)" (?__nv_cudaEntityRegisterCallback@@YAXPEAPEAX@Z)
Only building the library works fine. The error only happens when I try to link the final app with my cudalib library.
A full MWE has the following file contents:
CMakeLists.txt (1)
cmake_minimum_required(VERSION 3.22)
project(MAINAPP CUDA CXX)
add_subdirectory(cudalib) # MYCUDALIB is defined here
add_executable(mainapp main.cpp)
target_link_libraries(mainapp ${MYCUDALIB})
CMakeLists.txt (2)
cmake_minimum_required(VERSION 3.22)
project(CUDALIB CUDA CXX)
add_library(cudalib STATIC cppfunction.cpp cudafunction.cu)
set_target_properties(cudalib PROPERTIES CUDA_SEPARABLE_COMPILATION ON)
# define so we know the path to the lib in the upper project
set(MYCUDALIB ${CMAKE_CURRENT_BINARY_DIR}/cudalib.lib PARENT_SCOPE)
main.cpp
#include "cudalib/cudalib.h"
int main(){
cudafunction();
cppfunction();
return 0;
}
cppfunction.cpp
#include <iostream>
void cppfunction(){
std::cout << "In CPPFunction";
}
cudafunction.cu
#include <iostream>
void cudafunction(){
std::cout << "In CudaFunction";
void* ptr;
cudaMalloc(&ptr, 1000);
}
cudalib.h
void cppfunction();
void cudafunction();
Does somebody know why this error happens? How could I improve this project structure?
Upvotes: 1
Views: 1546
Reputation: 373
I found the answer after hours of trouble. There are two resources that gave me the hints I needed:
https://developer.nvidia.com/blog/building-cuda-applications-cmake/
https://gist.github.com/gavinb/c993f71cf33d2354515c4452a3f8ef30
You have to link the mainapp against the CUDA runtime:
CMakeLists.txt (1)
cmake_minimum_required(VERSION 3.22)
project(MAINAPP CUDA CXX)
find_library(CUDART_LIBRARY cudart ${CMAKE_CUDA_IMPLICIT_LINK_DIRECTORIES})
add_subdirectory(cudalib) # MYCUDALIB is defined here
add_executable(mainapp main.cpp)
target_link_libraries(mainapp ${MYCUDALIB} ${CUDART_LIBRARY})
and if you have CUDA_SEPARABLE_COMPILATION==ON
you have to enable device-linking before linking the final executable like this:
CMakeLists.txt (2)
cmake_minimum_required(VERSION 3.22)
project(CUDALIB CUDA CXX)
add_library(cudalib cppfunction.cpp cudafunction.cu)
set_target_properties(cudalib PROPERTIES CUDA_SEPARABLE_COMPILATION ON)
set_target_properties(cudalib PROPERTIES CUDA_RESOLVE_DEVICE_SYMBOLS ON)
# so we know the path to the lib in the other upper project
set(MYCUDALIB ${CMAKE_CURRENT_BINARY_DIR}/cudalib.lib PARENT_SCOPE)
Upvotes: 2