8

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:

  • Project
    • include
    • sourcedir
    • it
    • other folders

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.

Community
  • 1
  • 1
vburca
  • 208
  • 2
  • 10
  • 1
    Are you sure this worked before you introduced the `.cu` file? Anyway, I suggest you try changing `$?` to `$^`. – Beta May 17 '12 at 16:39
  • Well I changed it; I can post the original Makefile as well... maybe that would help with what I need to add so that the .cu files will compile as well. – vburca May 17 '12 at 17:07
  • You haven't given us enough information (e.g. the error message) to be sure of the exact problem, but you've made many small changes between these two makefiles. Try a binary search: write a makefile with only half of these changes, and see if it works. If you find *one change* that makes the difference, and it still doesn't make sense, let us know. – Beta May 17 '12 at 18:05
  • Here is a part of the error (I get a lot of similar lines, for each of the defined functions): <> – vburca May 17 '12 at 18:22
  • All .cu files must be compiled in the *same* compilation unit. – user703016 May 17 '12 at 20:09

1 Answers1

3

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.

Beta
  • 96,650
  • 16
  • 149
  • 150
  • make: Warning: File `Makefile' has modification time 3e+02 s in the future nvcc -O3 -o it ../sourcedir/it.o ../sourcedir/em.o ../sourcedir/art.o ../sourcedir/cg.o ../sourcedir/amatrix.o ../sourcedir/itreadargs.o ../sourcedir/sparse.o ../sourcedir/misc.o ../sourcedir/eval.o ../sourcedir/imgtools.o ../sourcedir/calc.o ../sourcedir/egif_lib.o ../sourcedir/dgif_lib.o ../sourcedir/gif_err.o ../sourcedir/gif_hash.o -lm ../sourcedir/it.o: In function `main': it.c:(.text+0x188): undefined reference to `CG_CUDA' collect2: ld returned 1 exit status make: *** [it] Error 1 – vburca May 17 '12 at 20:18
  • The first time I ran make it generated a bunch of warnings and such but the second time I only got the error posted above. – vburca May 17 '12 at 20:20
  • I realise this does not directly answer your question but I find using cmake much easier for cuda projects. I specify the cmake list files and then let cmake generate the Makefiles for me. If interested I could send you a simple example project of how this works. – fbielejec May 18 '12 at 11:45
  • Sorry for replying so late but I had problems with the machine that runs CUDA and couldn't try your suggestions. Thanks for your patience! – vburca May 18 '12 at 14:04
  • For make clean ; make ::::: make: Warning: File `Makefile' has modification time 3.9e+02 s in the future nvcc -O3 -o it ../sourcedir/it.o ../sourcedir/em.o ../sourcedir/art.o ../sourcedir/cg.o ../sourcedir/amatrix.o ../sourcedir/itreadargs.o ../sourcedir/sparse.o ../sourcedir/misc.o ../sourcedir/eval.o ../sourcedir/imgtools.o ../sourcedir/calc.o ../sourcedir/egif_lib.o ../sourcedir/dgif_lib.o ../sourcedir/gif_err.o ../sourcedir/gif_hash.o -lm ../sourcedir/it.o: In function `main': it.c:(.text+0x5b9): undefined reference to `CG_CUDA' collect2: ld returned 1 exit status make: *** [it] Error 1 – vburca May 18 '12 at 16:04
  • For make ../sourcedir/cg_cuda.o ::::::: make: Warning: File `Makefile' has modification time 2.3e+02 s in the future nvcc -arch=sm_20 -I../include -c -o ../sourcedir/cg_cuda.o ../sourcedir/cg_cuda.cu make: warning: Clock skew detected. Your build may be incomplete. – vburca May 18 '12 at 17:01