How compile c++ class file of *.cu ?

I make a simple class of c++ with CUDA. I can compile the files use command line with the command"nvcc -o main main.cpp", but I use CMake, I failed in complaining "undefined reference".

my computer configuration:

my os : ubuntu16.04
cuda:cuda9.0
intel i7
CMake version:3.5
the folowing is my file for my problem:
CUDAImageUtil.h:
#include <cuda_runtime.h>

class CUDAImageUtil {
public:
template static void copy(T* d_output, T* d_input, unsigned int width, unsigned int height);

};

CUDAImageUtil.cu:

#include “CUDAImageUtil.h”
template void CUDAImageUtil::copy(T* d_output, T* d_input, unsigned int width, unsigned int height) {
cudaMemcpy(d_output, d_input, sizeof(T)widthheight, cudaMemcpyDeviceToDevice);
}

main.cpp:
#include
#include “CUDAImageUtil.h”
int main()
{
std::cout << “Hello world” << std::endl;
float a[5]={1,1,1,1,1};
float *d_a;
cudaMalloc((float **)&d_a, 5);

CUDAImageUtil::copy(d_a, a, 5, 1);

}
CMakeLists.txt
cmake_minimum_required(VERSION 3.0)
project(Test)

find_package(CUDA REQUIRED)
include_directories(${CUDA_INCLUDE_DIRS})

set(CUDA_NVCC_FLAGS -arch=sm_61;-G;-g;)

CUDA_ADD_EXECUTABLE(main main.cpp CUDAImageUtil.cu)

target_link_libraries(main ${CUDA_LIBRARIES})

I compile the above three files with cmake compile, it give me the following errors
CMakeFiles/main.dir/main.cpp.o: In function main': main.cpp:(.text+0x9b): undefined reference to void CUDAImageUtil::copy(float*, float*, unsigned int, unsigned int)’
collect2: error: ld returned 1 exit status
CMakeFiles/main.dir/build.make:227: recipe for target ‘main’ failed
make[2]: *** [main] Error 1
CMakeFiles/Makefile2:67: recipe for target ‘CMakeFiles/main.dir/all’ failed
make[1]: *** [CMakeFiles/main.dir/all] Error 2
Makefile:83: recipe for target ‘all’ failed
make: *** [all] Error 2

But If rewrite the class CUDAImageUtil into main.cpp and I can use nvcc -o main.cpp to compile, successfully.
Could you someone tell me why? Thanks a lot and wish you every success!

That could not possibly work.

Anyway the problem is that you have a templated class all by itself in a compilation unit. Therefore the compiler does not instantiate a version of that class for float. When compiling CUDAImageUtil.cu, the compiler has no idea what types to instantiate your templated class for. It won’t automatically or magically instantiate it for float type.

This isn’t unique or specific to CUDA, but is a common problem when using templates in multi-file projects. You can find help for this on stackoverflow and other places.

A simple approach would be to add something at the end of CUDAImageUtil.cu to force template instantiation for type float:

https://stackoverflow.com/questions/2152002/how-do-i-force-a-particular-instance-of-a-c-template-to-instantiate

Thank you Robert_Crovella! I have solved this problem under your help!