具有文件夹结构的 CUDA 和 C++ - 通用 makefile

CUDA and C++ with folders structure - generic makefile

我想编写通用的 makefile 来编译和链接我的所有模块。

文件夹结构:

\include
----+Common.h
----+Graph.h
----+GraphColoringCPU.h
----+GraphColoringGPU.cuh
----+LogCreate.h
\obj <- initially empty, all .o files
---- ...
\src
----+Common.cu
----+Graph.cpp
----+GraphColoringCPU.cpp
----+GraphColoringGPU.cu
----+LogCreate.cpp
----+main.cu
+Makefile
+main <- target, missing before 'make'

生成文件:

CUDA_INSTALL_PATH ?= /usr/local/cuda

# Compilers
CXX := g++
LINK := g++ -fPIC
NVCC  := nvcc -ccbin /usr/bin

# Includes
INCLUDES = -I. -I$(CUDA_INSTALL_PATH)/include

# Common flags
COMMONFLAGS += $(INCLUDES)
NVCCFLAGS := $(COMMONFLAGS) -gencode arch=compute_20,code=sm_20
CXXFLAGS += $(COMMONFLAGS)
CFLAGS += $(COMMONFLAGS)

# Compiler flags
DLINKFLAGS      := -lcublas_device -lcudadevrt -lcublas -lcudart

# Debug mode
NVCCFLAGS += --compiler-options -Wall -G

#-arch=sm_35

# Libraries
LIB_CUDA := -L$(CUDA_INSTALL_PATH)/lib64 -lcudart

# Folder structure
OBJ = obj
SRC = src
INC = include

# Options
OBJS_CU = $(OBJ)/Common.ch.o $(OBJ)/GraphColoringGPU.cuh.o $(OBJ)/kernel.cu.o 
OBJS = $(OBJ)/Graph.cpp.o $(OBJ)/LogCreate.cpp.o $(OBJ)/GraphColoringCPU.cpp.o $(OBJ)/link.o 
TARGET = main
LINKLINE = $(LINK) -o $(TARGET) $(OBJS_CU) $(OBJS) $(LIB_CUDA)

.SUFFIXES: .c .cpp .h .cu .cuh .o

$(OBJ)/%.cuh.o: $(SRC)/%.cu $(INC)/%.cuh
    $(NVCC) $(NVCCFLAGS) -dc $< -o $@

$(OBJ)/%.ch.o: $(SRC)/%.cu $(INC)/%.h
    $(NVCC) $(NVCCFLAGS) -dc $< -o $@

$(OBJ)/%.cu.o: $(SRC)/%.cu
    $(NVCC) $(NVCCFLAGS) -dc $< -o $@

$(OBJ)/link.o:
    $(NVCC) -dlink $(NVCCFLAGS) $(DLINKFLAGS) $(OBJS_CU) -o $@  

$(OBJ)/%.cpp.o: $(SRC)/%.cpp $(INC)/%.h
    $(CXX) $(CXXFLAGS) -c $< -o $@

$(TARGET): $(OBJS_CU) $(OBJS) Makefile
    $(LINKLINE)

# all:
    # $(NVCC) $(NVCCFLAGS) -dc $(SRC)Common.cu $(SRC)GraphColoringGPU.cu $(SRC)kernel.cu 
    # $(NVCC) $(NVCCFLAGS) -dlink $(OBJ)Common.o $(OBJ)GraphColoringGPU.o $(OBJ)kernel.o -o $(OBJ)link.o
    # $(CXX) $(CXXFLAGS) -c $(SRC)Graph.cpp -o $(OBJ)graph.o
    # $(CXX) $(CXXFLAGS) -c $(SRC)LogCreate.cpp -o $(OBJ)logcreate.o
    # $(CXX) $(CXXFLAGS) -c $(SRC)GraphColoringCPU.cpp -o $(OBJ)GraphColoringCPU.o
    # $(LINK) -o main $(OBJ)Common.o $(OBJ)GraphColoringGPU.o $(OBJ)kernel.o $(OBJ)link.o $(OBJ)graph.o $(OBJ)logcreate.o $(OBJ)GraphColoringCPU.o $(LIB_CUDA)

clean: 
    rm -rf *.o log.txt

如您所见,底部有一些注释代码。此代码在没有文件夹结构的情况下工作正常(主目录中的所有文件)。

注释代码的输出:

nvcc -ccbin /usr/bin -I. -I/usr/local/cuda/include -gencode arch=compute_20,code=sm_20 --compiler-options -Wall -G -dc Common.cu GraphColoringGPU.cu kernel.cu
nvcc -ccbin /usr/bin -I. -I/usr/local/cuda/include -gencode arch=compute_20,code=sm_20 --compiler-options -Wall -G -dlink Common.o GraphColoringGPU.o kernel.o -o link.o
g++ -I. -I/usr/local/cuda/include -c Graph.cpp -o graph.o
g++ -I. -I/usr/local/cuda/include -c LogCreate.cpp -o logcreate.o
g++ -I. -I/usr/local/cuda/include -c GraphColoringCPU.cpp -o GraphColoringCPU.o
g++ -fPIC -o main Common.o GraphColoringGPU.o kernel.o link.o graph.o logcreate.o GraphColoringCPU.o -L/usr/local/cuda/lib64 -lcudart

实际生成文件产生输出:

nvcc -ccbin /usr/bin -dlink -I. -I/usr/local/cuda/include -gencode arch=compute_20,code=sm_20 --compiler-options -Wall -G -lcublas_device -lcudadevrt -lcublas -lcudart obj/Common.ch.o obj/GraphColoringGPU.cuh.o obj/kernel.cu.o  -o obj/link.o
nvlink fatal   : Could not open input file 'obj/Common.ch.o'
make: *** [obj/link.o] Error 255

我知道它试图以不正确的顺序进行编译,但我不知道如何更改它。

正确的顺序规则:

1) Compile all '.cu' files using 'nvcc -dc' and places suitable '.o' files into \obj folder 
2) Link all '.o' files (where sources are .cu files) using 'nvcc -dlink' into 'link.o' file (and place it into \obj folder) 
3) Compile all '.cpp' files using 'g++ -c' and places suitable '.o' files into \obj folder 
4) Links all '.o' files into target 'main' (and place it in main folder)

感谢您的建议。

我知道我已经非常接近写出正确的 make 了。我试过命令 'make main' 并且它...有效(需要做一些小改动)。

这是工作 Makefile(省略未更改的代码):

# Options
OBJS_CU = $(OBJ)/Common.ch.o $(OBJ)/GraphColoringGPU.cuh.o $(OBJ)/main.cu.o 
OBJS = $(OBJ)/Graph.cpp.o $(OBJ)/LogCreate.cpp.o $(OBJ)/GraphColoringCPU.cpp.o $(OBJ)/link.o 
TARGET = main
LINKLINE = $(LINK) -o $(TARGET) $(OBJS_CU) $(OBJS) $(LIB_CUDA)

.SUFFIXES: .c .cpp .h .cu .cuh .o

$(OBJ)/%.cuh.o: $(SRC)/%.cu $(INC)/%.cuh
    $(NVCC) $(NVCCFLAGS) -dc $< -o $@

$(OBJ)/%.ch.o: $(SRC)/%.cu $(INC)/%.h
    $(NVCC) $(NVCCFLAGS) -dc $< -o $@

$(OBJ)/%.cu.o: $(SRC)/%.cu
    $(NVCC) $(NVCCFLAGS) -dc $< -o $@

$(OBJ)/link.o:
    $(NVCC) $(NVCCFLAGS) -dlink $(OBJS_CU) -o $@    

$(OBJ)/%.cpp.o: $(SRC)/%.cpp $(INC)/%.h
    $(CXX) $(CXXFLAGS) -c $< -o $@

$(TARGET): $(OBJS_CU) $(OBJS) Makefile
    $(LINKLINE)

另外,如果 $(TARGET) 的规则是第一个规则,简单的 'make' 就足以正常工作。