global variables

I was wondering what was the correct way to set up a multi-file project. Basically I am having trouble at the linking stage.

In my main file I include the .cu files like you would a .h file, because that was the only way that seemed to work. I also tried putting function prototypes in a header file, but that didn’t work. So that works for functions, but for the global variables in other files, I get symbol redefinition errors. I have tried using macros to tell the compiler not to compile them if they have been defined before, but that didn’t work.

How am I supposed to do this?

My main file is a .c file, and the others are .cu files.

On Linux I use gcc/g++ to compile the .c and .cpp files respectively and nvcc to compile the .cu files. All the .o files are then linked using gcc. On Windows I have converted one of the examples int he SDK to be a “template” project for Microsoft Visual Studio C++ where there is a custom build rule for the .cu files. I don’t #include .cu files. You can define the host functions in the .cu files in a header file. You may need to declare them extern “C” if using C++ though sometimes I find that is not necessary either.

Okay, so not I am not including the .cu files in my main.c file, but I am still getting linking errors.

[sam@gpu1 basic_fdtd]$ make

rm -f fdtd *.o

gcc -c main.c -O3 -I. -I/usr/local/cuda/include

nvcc -c cudaManagement.cu memory.cu update.cu -I. -I/usr/local/cuda/include

gcc -o fdtd  cudaManagement.o  memory.o  update.o  main.o -lrt -lm -lcudart -I. -I/usr/local/cuda/include -L/usr/local/cuda/lib

main.o: In function `main':

main.c:(.text+0x20): undefined reference to `allocateMemory'

main.c:(.text+0x31): undefined reference to `update'

collect2: ld returned 1 exit status

make: *** [fdtd] Error 1

This is what my Makefile looks like.

[sam@gpu1 basic_fdtd]$ cat Makefile 

# flags

CUDA_INSTALL_PATH := /usr/local/cuda

INCLUDES          += -I. -I$(CUDA_INSTALL_PATH)/include

LIBS              := -L$(CUDA_INSTALL_PATH)/lib

CFLAGS            := -O3

LDFLAGS           := -lrt -lm -lcudart

# compilers

NVCC              := nvcc

CC                := gcc

# files

C_SOURCES         := $(wildcard *.c)

CU_SOURCES        := $(wildcard *.cu)

HEADERS           := $(wildcard *.h)

C_OBJS            := $(patsubst %.c, %.o, $(C_SOURCES))

CU_OBJS           := $(patsubst %.cu, %.o, $(CU_SOURCES))

fdtd: clean $(C_OBJS) $(CU_OBJS) $(HEADERS)

        $(CC) -o fdtd $(CU_OBJS) $(C_OBJS) $(LDFLAGS) $(INCLUDES) $(LIBS)

$(C_OBJS): $(C_SOURCES) $(HEADERS)

        $(CC) -c $(C_SOURCES) $(CFLAGS) $(INCLUDES)

$(CU_OBJS): $(CU_SOURCES) $(HEADERS)

        $(NVCC) -c $(CU_SOURCES) $(INCLUDES)

You can try extern “C”. cu is compiled using a hybrid C++/C compiling, so you may need it on cu side even if the other side is C.

I think you are right. I switched my CC from gcc to g++ and my linking problems went away. I will try your full solution, but I think that it will prove be correct.