CUDA和C的Makefile

8
我正在处理一个使用.c和.cu文件的项目。原始软件包完全是用C编写的,并且有自己的Makefile(运行良好)。我将.cu文件添加到了该项目中,现在我想修改Makefile以便一起编译所有文件。
以下是我的尝试:
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)

项目结构如下:
  • Project
    • include
    • sourcedir
    • it
    • 其他文件夹

其中,include文件夹包含所有的.h文件,sourcedir文件夹包含.c和.cu文件(只有一个.cu文件);it文件夹中有Makefile。
我的Makefile存在问题,当我在it文件夹中运行make时,会出现一堆错误,告诉我包含main()函数的文件(sourcedir文件夹中的it.c文件)没有与其他库中的任何函数链接。我的.cu文件也是一样的。
请问您能否给我一些提示,我的Makefile可能存在什么问题?我参考了以下Stackoverflow帖子: makefile for C++/CUDA project 谢谢您的帮助, Vlad
编辑:
这是原始的Makefile,适用于.c文件。您能否帮我添加必要的内容以便与其他文件一起编译.cu文件?再次感谢。
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)

后来我修改了Makefile,进行了一些清理,现在只有一些错误与事实相关,即.cu文件未链接到.c文件,反之亦然。

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)

所以现在我遇到了这些错误:
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

感谢您耐心阅读我的帖子。

1
你确定在引入.cu文件之前这个程序是可以工作的吗?无论如何,我建议你尝试将$?改为$^ - Beta
我已经修改了它;我可以发布原始的Makefile……也许这会有助于我需要添加的内容,以便.cu文件也能编译。 - vburca
你没有给我们足够的信息(例如错误消息),以确保确切的问题,但是在这两个makefile之间进行了许多小的更改。尝试二分查找:编写一个仅包含这些更改一半的makefile,并查看其是否有效。如果您找到一个更改使其有所不同,并且它仍然没有意义,请告诉我们。 - Beta
这是错误的一部分(我得到了很多类似的行,针对每个定义的函数):<<将它们添加到原始帖子中>> - vburca
所有的 .cu 文件必须在同一个编译单元中进行编译。 - user703016
1个回答

3
好的,这需要几次迭代。尝试一下并在评论中留下结果:
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)
编辑:第二轮
我已经修改了makefile文件。请尝试运行make clean ; make并观察结果。然后尝试运行make ../sourcedir/cg_cuda.o编辑:第三轮
好的,请再次尝试运行make clean ; make

make: 警告:文件“Makefile”的修改时间比未来的3e+02秒 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: 在函数“main”中: it.c:(.text+0x188):对“CG_CUDA”的未定义引用 collect2: ld 返回了1个退出状态 make: *** [it] 错误1 - vburca
第一次运行make时生成了一堆警告之类的信息,但第二次只出现了上述错误。 - vburca
我意识到这并没有直接回答你的问题,但是我发现对于CUDA项目来说使用CMake要容易得多。我指定CMake列表文件,然后让CMake为我生成Makefiles。如果你有兴趣,我可以给你发送一个简单的示例项目,展示如何使用CMake。 - fbielejec
非常抱歉回复晚了,但是我遇到了运行CUDA的机器问题,无法尝试您的建议。感谢您的耐心等待! - vburca
make clean; make :::::make:警告: 文件 `Makefile' 的修改时间在将来的 3.9e+02 秒 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: 在函数‘main’中: it.c:(.text+0x5b9):对‘CG_CUDA’未定义的引用 collect2: ld 返回 1 的退出状态 make: *** [it] 错误 1 - vburca
进行 ../sourcedir/cg_cuda.o 的编译::::::: make: 警告:文件“Makefile”的修改时间比将来的时间大2.3e+02秒 nvcc -arch=sm_20 -I../include -c -o ../sourcedir/cg_cuda.o ../sourcedir/cg_cuda.cu make: 警告:检测到时钟偏差。您的构建可能不完整。 - vburca

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接