Link error LNK2005 when trying to compile several CUDA files together
I have a CUDA program that works fine, but that is currently all written in one file. I'd like to split this big file into several smaller ones, in order to make it easier to maintain and navigate.
The new structure is :
foo.cuh
foo.cu
bar.cuh
bar.cu
main.cu
The .cuh
header files contain structs and function prototypes, and the .cu
files contain the function definitions (as usual). The main file includes bar.cuh
, and bar.cu
includes foo.cuh
. All the .cu files include cutil_inline.h, in order to be able to use the CUDA functions.
Hence :
// main.cu
#include "bar.cuh"
#include <cutil_inline.h>
int main() [...]
// bar.cu
#include "bar.cuh"
#include "foo.cuh"
#include <cutil_inline.h>
[...]
// foo.cu
#include "foo.cuh"
#include <cutil_inline.h>
[...]
The problem is that when I compile my Visual Studio 2008 project with this new structure, I get tons of link errors :
error LNK2005: "void __cdecl __cutilBankChecker(unsigned int,unsigned int,unsigned int,unsigned int,unsigned int,unsigned int,char *,int,char *,int)" (?__cutilBankChecker@@YAXIIIIIIPADH0H@Z) already defined in cuda_generated_foo.cu.obj cuda_generated_bar.cu.obj
error LNK2005: "void __cdecl __cutilCondition(int,char *,int)" (?__cutilCondition@@YAXHPADH@Z) already defined in cuda_generated_foo.cu.obj cuda_generated_bar.cu.obj
开发者_如何学编程error LNK2005: "void __cdecl __cutilExit(int,char * *)" (?__cutilExit@@YAXHPAPAD@Z) already defined in cuda_generated_foo.cu.obj cuda_generated_bar.cu.obj
error LNK2005: "int __cdecl cutGetMaxGflopsDeviceId(void)" (?cutGetMaxGflopsDeviceId@@YAHXZ) already defined in cuda_generated_foo.cu.obj cuda_generated_bar.cu.obj
error LNK2005: "void __cdecl __cudaSafeCallNoSync(enum cudaError,char const *,int)" (?__cudaSafeCallNoSync@@YAXW4cudaError@@PBDH@Z) already defined in cuda_generated_foo.cu.obj cuda_generated_bar.cu.obj
error LNK2005: "void __cdecl __cudaSafeCall(enum cudaError,char const *,int)" (?__cudaSafeCall@@YAXW4cudaError@@PBDH@Z) already defined in cuda_generated_foo.cu.obj cuda_generated_bar.cu.obj
error LNK2005: "void __cdecl __cudaSafeThreadSync(char const *,int)" (?__cudaSafeThreadSync@@YAXPBDH@Z) already defined in cuda_generated_foo.cu.obj cuda_generated_bar.cu.obj
error LNK2005: "void __cdecl __cufftSafeCall(enum cufftResult_t,char const *,int)" (?__cufftSafeCall@@YAXW4cufftResult_t@@PBDH@Z) already defined in cuda_generated_foo.cu.obj cuda_generated_bar.cu.obj
I understand what they mean (all those symbols already defined are part of cutil_inline.h) but I have to include this header in all files, otherwise it does not compile. What am I doing wrong ?
UPDATE: To clarify the situation : * with all code in one big file, it compiles, links and runs fine * with the new structure (several smaller files) and including cutil_inline.h in all .cu files, it compiles correctly but fails during linking * with the new structure and including cutil_inline.h only in the main file, it fails during compilation, saying that the cutil function are unknown in the files where cutil_inline.h was not included (as expected, but I had to try everything) - List item
This error also happened in my program. I solved it by adding the keyword inline
before __global__
or __device__
. Then, the error went away.
Somehow, the functions in cutil_inline.h aren't flagged as "inline" when they are compiled.
If you got this error in a normal non-Cuda C++ project, the answer would simply be that you have function definitions (not just declarations) in the header file and the "inline" keyword in missing.
You might have to generate the corresponding .i files (pre-processor) output to really see what's going on after all macro expansion.
EDIT 1/2/2009
If you can't figure out what's wrong just by reading the .h files, because of some macro expansion obfuscation, here's how you generate the .i file:
In the Visual Studio "Solution Explorer" window, right-click on the source file and choose "Properties".
In the properties tree, select "C/C++", "Preprocessor".
Change the "Generate Preprocessed File" from "No" to one of the other options.
Then compile the file. The compiler will write the preprocessor output to a file and then stop without actually compiling. You can see in the .i file produced what the final result of all macro expansions is.
You will have to go back and reset that property back to "No" in order to get the project to compiler to work properly again.
Do you need to link with the cutil library (i.e. cutil32D.lib for 32-bit debug etc.)?
For some reason you have multiple definitions. Are you using the NVIDIA Cuda.rules file to enable Visual Studio to compile your .cu files to .obj files? It looks like you have modified the rules to link with cutil, whereas you should use the NVIDIA Cuda.rules to tell VS how to compile .cu to .obj, then modify the standard linker properties to pull in the cutil library.
Consider using 'static' instead of 'inline' to avoid warnings during compilation. That's according to this answer. The causes to this error are discussed here:
However, that's most likely caused by including .cuh
files (containing your kernels) into a usual .h
file. Either:
make a separate dll filled with your
.cuh
and.cu
files, and link against that;or rename your
.h
files to.cuh
and.cpp
tocu
. For this option, make sure to also do this: https://stackoverflow.com/a/20057857/9007125
In the context menu for your .cu file (that you just renamed), select Properties. Then go to General and make sure Item Type is set to CUDA C/C++.
Mind you, the second option will make your project compile a lot slower (compiles 4 times slower)
精彩评论