I am working on a project that uses .c and .cu files. The original package was written entirely in C and had its own Makefile (it was perfectly working). I added the .cu file to the project and now I want to modify the Makefile so that it compiles everything together.
Here is my attempt:
CC = nvcc
SOURCEDIR = ../sourcedir
EXE = it
#C_SOURCES = $(wildcard $(SOURCEDIR)/*.c)
#CU_SOURCES = $(wildcard $(SOURCEDIR)/*.cu)
SOURCES = $(SOURCEDIR)/it.c \
$(SOURCEDIR)/em.c \
$(SOURCEDIR)/art.c \
$(SOURCEDIR)/cg.c \
$(SOURCEDIR)/amatrix.c \
$(SOURCEDIR)/itreadargs.c \
$(SOURCEDIR)/sparse.c \
$(SOURCEDIR)/misc.c \
$(SOURCEDIR)/eval.c \
$(SOURCEDIR)/imgtools.c \
$(SOURCEDIR)/calc.c \
$(SOURCEDIR)/egif_lib.c \
$(SOURCEDIR)/dgif_lib.c \
$(SOURCEDIR)/gif_err.c \
$(SOURCEDIR)/gif_hash.c
CU_SOURCES = $(SOURCEDIR)/cg_cuda.cu
H_FILES = $(wildcard $(IDIR)/*.h)
IDIR = -I../include
OBJS = $(SOURCES:.c=.o)
CU_OBJS = $(CU_SOURCES:.cu=.o)
CFLAGS = -O3
#-finline-functions -Winline -Wall -falign-loops=2 -falign-jumps=2 -falign-functions=2 -Wstrict-prototypes
NVCCFLAGS = -arch=sm_20
#CFLAGS = -g -Wstrict-prototypes -Winline -Wall
LFLAGS = -lm
$(EXE) : $(OBJS) $(CU_OBJS)
$(CC) $(CFLAGS) $(NVCCFLAGS) -o $@ $?
$(SOURCEDIR)/%.o : $(SOURCEDIR)/%.c $(H_FILES)
$(CC) $(CFLAGS) $(IDIR) -c -o $@ $<
$(SOURCEDIR)/%.o : $(SOURCEDIR)/%.cu $(H_FILES)
$(CC) $(NVCCFLAGS) $(IDIR) -c -o $@ $<
clean:
rm -f $(OBJS) $(EXE)
The structure of the project is as follows:
where include has all the .h files and sourcedir has the .c and the .cu files (there is only one .cu file); it has the Makefile.
The problem with my Makefile is that when I do make in the it folder I get a bunch of errors that tell me that the file that has the main() function (it.c in sourcedir folder) is not getting linked to any of the functions from other libraries. The same holds for my .cu file.
Can you please give me some hints on what might be wrong with my Makefile? I used as a reference the following Stackoverflow post: makefile for C++/CUDA project
Thank you for your help,
Vlad
EDIT:
Here is the original Makefile, the one that worked on the .c files. Can you help me with what I need to add in order for the .cu file to be compiled along with the others? Thanks again.
CC = gcc
SOURCEDIR = ../sourcedir
EXE = it
SOURCES = $(SOURCEDIR)/it.c \
$(SOURCEDIR)/em.c \
$(SOURCEDIR)/art.c \
$(SOURCEDIR)/cg.c \
$(SOURCEDIR)/amatrix.c \
$(SOURCEDIR)/itreadargs.c \
$(SOURCEDIR)/sparse.c \
$(SOURCEDIR)/misc.c \
$(SOURCEDIR)/eval.c \
$(SOURCEDIR)/imgtools.c \
$(SOURCEDIR)/calc.c \
$(SOURCEDIR)/egif_lib.c \
$(SOURCEDIR)/dgif_lib.c \
$(SOURCEDIR)/gif_err.c \
$(SOURCEDIR)/gif_hash.c
IDIR = -I../include
OBJS = $(SOURCES:.c=.o)
CFLAGS = -O3 -finline-functions -Winline -Wall -falign-loops=2 -falign-jumps=2 -falign-functions=2 -Wstrict-prototypes
#CFLAGS = -g -Wstrict-prototypes -Winline -Wall
LFLAGS = -lm
$(EXE) : $(OBJS)
$(CC) $(CFLAGS) -o $(EXE) $(OBJS) $(LFLAGS)
%.o : %.c
$(CC) -c $(IDIR) $(CFLAGS) $< -o $@
clean:
rm -f $(OBJS) $(EXE)
LATER EDIT:
I changed the Makefile some more, cleaned it a bit, and now I only get a few errors which are related to the fact that the .cu is not getting linked to the .c files and vice-versa.
CC := gcc
SOURCEDIR := ../sourcedir
EXE := it
SOURCES := $(SOURCEDIR)/it.c \
$(SOURCEDIR)/em.c \
$(SOURCEDIR)/art.c \
$(SOURCEDIR)/cg.c \
$(SOURCEDIR)/amatrix.c \
$(SOURCEDIR)/itreadargs.c \
$(SOURCEDIR)/sparse.c \
$(SOURCEDIR)/misc.c \
$(SOURCEDIR)/eval.c \
$(SOURCEDIR)/imgtools.c \
$(SOURCEDIR)/calc.c \
$(SOURCEDIR)/egif_lib.c \
$(SOURCEDIR)/dgif_lib.c \
$(SOURCEDIR)/gif_err.c \
$(SOURCEDIR)/gif_hash.c
CU_SOURCES := $(SOURCEDIR)/cg_cuda.cu
IDIR := ../include
INCLUDES := -I../include
H_FILES := $(IDIR)/analyze.h \
$(IDIR)/calc.h \
$(IDIR)/eval.h \
$(IDIR)/gif_hash.h \
$(IDIR)/gif_lib.h \
$(IDIR)/imgtools.h \
$(IDIR)/iradon.h \
$(IDIR)/iradoninc.h \
$(IDIR)/it.h \
$(IDIR)/itini.h \
$(IDIR)/misc.h \
$(IDIR)/sparse.h
CFLAGS := -g -O3
NVCCFLAGS := -g -G -O3 -arch=sm_20
LDFLAGS := -lGL -lGLU -lglut -lpthread -lcuda
HOST_OBJ := $(SOURCES:.c=.c.o)
DEVICE_OBJ := $(CU_SOURCES:.cu=.cu.o)
%.c.o : %.c $(HFILES)
$(CC) -c $(INCLUDES) $(CFLAGS) $< -o $@
%.cu.o : %.cu $(H_FILES)
nvcc -c $(INCLUDES) $(NVFLAGS) $< -o $@
$(EXE): $(HOST_OBJ) $(DEVICE_OBJ)
nvcc $(NVFLAGS) $(LDFLAGS) $(INCLUDES) -o $@ $^
clean:
rm -f $(OBJS) $(EXE)
So now I am getting these errors:
nvcc -lGL -lGLU -lglut -lpthread -lcuda -I../include -o it ../sourcedir/it.c.o ../sourcedir/em.c.o ../sourcedir/art.c.o ../sourcedir/cg.c.o ../sourcedir/amatrix.c.o ../sourcedir/itreadargs.c.o ../sourcedir/sparse.c.o ../sourcedir/misc.c.o ../sourcedir/eval.c.o ../sourcedir/imgtools.c.o ../sourcedir/calc.c.o ../sourcedir/egif_lib.c.o ../sourcedir/dgif_lib.c.o ../sourcedir/gif_err.c.o ../sourcedir/gif_hash.c.o ../sourcedir/cg_cuda.cu.o
../sourcedir/it.c.o: In function `main':
/home/vburca/CUDA_Research_2012/Recon2D/it/../sourcedir/it.c:280: undefined reference to `CG_CUDA'
../sourcedir/cg_cuda.cu.o: In function `CGUpdateAddVector(Vector*, Vector*, Vector*, float)':
tmpxft_00004e1d_00000000-1_cg_cuda.cudafe1.cpp:(.text+0x44): undefined reference to `Error(char*, ...)'
../sourcedir/cg_cuda.cu.o: In function `CG_CUDA(SparseMatrix*, Vector*, Vector*)':
tmpxft_00004e1d_00000000-1_cg_cuda.cudafe1.cpp:(.text+0x15f): undefined reference to `Print(int, char*, ...)'
tmpxft_00004e1d_00000000-1_cg_cuda.cudafe1.cpp:(.text+0x18c): undefined reference to `ReadFIF(char*)'
tmpxft_00004e1d_00000000-1_cg_cuda.cudafe1.cpp:(.text+0x1a2): undefined reference to `ImageToVector(Image*)'
tmpxft_00004e1d_00000000-1_cg_cuda.cudafe1.cpp:(.text+0x1b8): undefined reference to `FreeImage(Image*)'
tmpxft_00004e1d_00000000-1_cg_cuda.cudafe1.cpp:(.text+0x1c7): undefined reference to `DeviationVector(Vector*)'
tmpxft_00004e1d_00000000-1_cg_cuda.cudafe1.cpp:(.text+0x248): undefined reference to `Print(int, char*, ...)'
tmpxft_00004e1d_00000000-1_cg_cuda.cudafe1.cpp:(.text+0x255): undefined reference to `InitVector(int)'
tmpxft_00004e1d_00000000-1_cg_cuda.cudafe1.cpp:(.text+0x269): undefined reference to `InitVector(int)'
tmpxft_00004e1d_00000000-1_cg_cuda.cudafe1.cpp:(.text+0x27d): undefined reference to `InitVector(int)'
tmpxft_00004e1d_00000000-1_cg_cuda.cudafe1.cpp:(.text+0x291): undefined reference to `InitVector(int)'
tmpxft_00004e1d_00000000-1_cg_cuda.cudafe1.cpp:(.text+0x2a5): undefined reference to `InitVector(int)'
tmpxft_00004e1d_00000000-1_cg_cuda.cudafe1.cpp:(.text+0x2c0): undefined reference to `Print(int, char*, ...)'
tmpxft_00004e1d_00000000-1_cg_cuda.cudafe1.cpp:(.text+0x2e0): undefined reference to `MultSparseMatrixVector(SparseMatrix*, Vector*, Vector*)'
tmpxft_00004e1d_00000000-1_cg_cuda.cudafe1.cpp:(.text+0x328): undefined reference to `MultSparseTMatrixVector(SparseMatrix*, Vector*, Vector*)'
tmpxft_00004e1d_00000000-1_cg_cuda.cudafe1.cpp:(.text+0x37c): undefined reference to `MultSparseMatrixVector(SparseMatrix*, Vector*, Vector*)'
tmpxft_00004e1d_00000000-1_cg_cuda.cudafe1.cpp:(.text+0x395): undefined reference to `MultVectorVector(Vector*, Vector*)'
tmpxft_00004e1d_00000000-1_cg_cuda.cudafe1.cpp:(.text+0x3b1): undefined reference to `Print(int, char*, ...)'
tmpxft_00004e1d_00000000-1_cg_cuda.cudafe1.cpp:(.text+0x3fb): undefined reference to `Print(int, char*, ...)'
tmpxft_00004e1d_00000000-1_cg_cuda.cudafe1.cpp:(.text+0x414): undefined reference to `MultVectorVector(Vector*, Vector*)'
tmpxft_00004e1d_00000000-1_cg_cuda.cudafe1.cpp:(.text+0x47b): undefined reference to `ConstrainVector(Vector*, float, float)'
tmpxft_00004e1d_00000000-1_cg_cuda.cudafe1.cpp:(.text+0x4ce): undefined reference to `MultSparseTMatrixVector(SparseMatrix*, Vector*, Vector*)'
tmpxft_00004e1d_00000000-1_cg_cuda.cudafe1.cpp:(.text+0x4e7): undefined reference to `MultVectorVector(Vector*, Vector*)'
tmpxft_00004e1d_00000000-1_cg_cuda.cudafe1.cpp:(.text+0x55b): undefined reference to `MultSparseMatrixVector(SparseMatrix*, Vector*, Vector*)'
tmpxft_00004e1d_00000000-1_cg_cuda.cudafe1.cpp:(.text+0x581): undefined reference to `SaveIteration(Vector*, int, char*)'
tmpxft_00004e1d_00000000-1_cg_cuda.cudafe1.cpp:(.text+0x5ab): undefined reference to `L2NormVector(Vector*, Vector*, float)'
tmpxft_00004e1d_00000000-1_cg_cuda.cudafe1.cpp:(.text+0x602): undefined reference to `Print(int, char*, ...)'
tmpxft_00004e1d_00000000-1_cg_cuda.cudafe1.cpp:(.text+0x61f): undefined reference to `VectorToImage(Vector*, int, int)'
tmpxft_00004e1d_00000000-1_cg_cuda.cudafe1.cpp:(.text+0x650): undefined reference to `L2NormVector(Vector*, Vector*, float)'
tmpxft_00004e1d_00000000-1_cg_cuda.cudafe1.cpp:(.text+0x66a): undefined reference to `Print(int, char*, ...)'
tmpxft_00004e1d_00000000-1_cg_cuda.cudafe1.cpp:(.text+0x679): undefined reference to `FreeVector(Vector*)'
tmpxft_00004e1d_00000000-1_cg_cuda.cudafe1.cpp:(.text+0x69c): undefined reference to `RenameImage(Image*, char*)'
collect2: ld returned 1 exit status
make: *** [it] Error 1
Thank you for your patience reading my post.
All right, this is going to take a few iterations. Try this and comment with the results:
CC = nvcc
SOURCEDIR = ../sourcedir
EXE = it
SOURCES = $(SOURCEDIR)/it.c \
$(SOURCEDIR)/em.c \
$(SOURCEDIR)/art.c \
$(SOURCEDIR)/cg.c \
$(SOURCEDIR)/amatrix.c \
$(SOURCEDIR)/itreadargs.c \
$(SOURCEDIR)/sparse.c \
$(SOURCEDIR)/misc.c \
$(SOURCEDIR)/eval.c \
$(SOURCEDIR)/imgtools.c \
$(SOURCEDIR)/calc.c \
$(SOURCEDIR)/egif_lib.c \
$(SOURCEDIR)/dgif_lib.c \
$(SOURCEDIR)/gif_err.c \
$(SOURCEDIR)/gif_hash.c
IDIR = -I../include
OBJS = $(SOURCES:.c=.o)
CFLAGS = -O3
NVCCFLAGS = -arch=sm_20
LFLAGS = -lm
$(EXE) : $(OBJS) $(SOURCEDIR)/cg_cuda.o
$(CC) $(CFLAGS) -o $@ $^ $(LFLAGS)
$(SOURCEDIR)/%.o : $(SOURCEDIR)/%.c
$(CC) $(NVCCFLAGS) $(IDIR) -c -o $@ $<
$(SOURCEDIR)/%.o : $(SOURCEDIR)/%.cu $(H_FILES)
$(CC) $(NVCCFLAGS) $(IDIR) -c -o $@ $<
clean:
rm -f $(OBJS) $(EXE)
EDIT: round 2
I've modified the makefile. Try make clean ; make
and note the result. Then try make ../sourcedir/cg_cuda.o
.
EDIT: round 3
All right, try it again: make clean ; make
.