I'm working on an DNA Fragment Assembly program. The CPU-only version is built in C language using GCC and I'm trying to build a GPU version using NVCC.
Here is the makefile
all : clean FragmentAssembly.exe
FragmentAssembly.exe : Common.o Fragment.o ILS.o Consensus.o main.o
nvcc -pg -o FragmentAssembly.exe Common.o Fragment.o ILS.o Consensus.o main.o
Common.o : Common.cu
nvcc -pg -o Common.o -c Common.cu
Fragment.o : Fragment.cu
nvcc -pg -o Fragment.o -c Fragment.cu
ILS.o : ILS.cu
nvcc -pg -o ILS.o -c ILS.cu
Consensus.o : Consensus.cu
nvcc -pg -o Consensus.o -c Consensus.cu
main.o : main.cu
nvcc -pg -o main.o -c main.cu
clean :
rm -f *.exe *.o
As seen, the original .c
files became .cu files for nvcc
to compile them correctly.
All of the cu files contain includes of their corresponding files (Common.h for Common.cu, etc..) except for main.cu
.
ILS.h contians definition of global variables p_instanceFragments
and p_instanceLength
The problem is when compiling NVCC, for an unknown reason, I get the following errors :
Consensus.o:(.bss+0x0): multiple definition of `p_instanceFragments'
ILS.o:(.bss+0x0): first defined here
Consensus.o:(.bss+0x8): multiple definition of `p_instanceLength'
ILS.o:(.bss+0x8): first defined here
There is no real multiple definitions since the same code is built correctly using GCC. It looks as if ILS.h
is getting included twice in nvcc, by ILS.cu
and Consensus.cu
. This is also not possible since I've wrapped all my header files with an #ifndef .. #define .. #endif
statements to avoid multiple includes and infinite include loops.
Maybe something with the makefile commands ? or should I use gcc for linking ? Can you tell me how to deal with it ?
Regards,
After discussion: Here a description of what happened:
If you use gcc and you have two files (lets say f1.c
and f2.c
), and in both files you declare:
int myGlobalVariable;
Then the following will happen:
f1.c
into f1.o
, the object file will reserve space for myGlobalVariable
.f2.c
into f2.o
, the object file will also reserve space for myGlobalVariable
.myGlobalVariable
and will merge these variables together.Now it seems the nvcc
compiler/linker is not able to merge these variables.
The problem was, that the file ILS.h
declares <some type> p_instanceFragments;
. Because ILS.h
is included into both ILS.cu
and Consensus.cu
, you get this variable twice and nvcc
complains when it has to link the application.
The solution is to declare extern <some type> p_instanceFragments;
in ILS.h
and then to define <some type> p_instanceFragments;
either in ILS.cu
or Consensus.cu
(not in both).
The question What are extern variables in C has a rather extensive answer explaining all of this in detail.