makefile为cuda / c ++,无法成功编译

时间:2017-04-29 18:04:59

标签: c++ makefile compilation cuda

我花了很多时间尝试编写一个makefile来编译一些c ++文件和一些.cu文件。我当前得到输出时无法成功编译目标,它不是一个合适的二进制文件。

所以,基本上我的所有源文件都在src目录中,我的makefile在主项目文件夹中,一个目录来自src。我有一个main.cpp,一个hostDeviceCom.cu,一个myKernel.cu和一个cudaErrorCheck.cu,我在之前用nvcc手工编译的项目中测试过。这个概念是有一个单独的构建文件夹,其中.out将是。

所以我的问题是:我在下面的makefile中做错了什么?

TARGET_EXEC ?= cudaNestim.out
T_CUDA_O    ?= cudaTMp.o
NVCC        ?= nvcc
BUILD_DIR   ?= ./build
SRC_DIRS    ?= ./src
CUDA_ARCH   ?= -arch=sm_52
NVCCFLAGS   ?= $(CUDA_ARCH) 
NVCCFLNK    ?= $(CUDA_ARCH) --device-link
CXXFLAGS    ?= --std=c++11 -MM -MT
CXXOPTS     ?= -MM -MT
# System Libraries -------------------------------------------------------------------------------
OCV_DIR     ?= -L/user/local/lib
OCV_LIB     ?= -lopencv_core -lopencv_viz -lopencv_highgui -lopencv_features2d -lopencv_imgproc
OCV_INC     ?= -I/usr/include
OCV_LINK    ?= $(OCV_DIR) $(OCV_LIB)

CUDA_DIR    ?= -L/user/local/cuda-8.0/lib64
CUDA_LIB    ?= -lcutil -lcudpp -lcuda -lcudart 
CUDA_INC    ?= -I/usr/local/cuda-8.0/include
CUDA_LINK   ?= $(CUDA_DIR) $(CUDA_LIB)
#--------------------------------------------------------------------------------------------------

# find all the source files
SRCS := $(shell find $(SRC_DIRS) -name *.cu -or -name *.cpp -or -name *.c -or -name *.s) 
#go to build directory and create a .o file for each src file found
OBJS := $(SRCS:%=$(BUILD_DIR)/%.o)
# create a .d file from each .o file. SO one .d for each .source
DEPS := $(OBJS:.o=.d)


LIB_DIRS := $(OCV_LINK) $(CUDA_LINK)
INCS     := $(CUDA_INC) $(OCV_INC)

$(BUILD_DIR)/$(TARGET_EXEC): $(OBJS) 
    $(NVCC) $(NVCCFLNK) $(OBJS) $(LIB_DIRS)  -o $@ 

$(BUILD_DIR)/%.cu.o: %.cu
    $(MKDIR_P) $(dir $@)
    $(NVCC) $(NVCCFLAGS) -o $@ -c $< 

    #echo ".cu.o rule:" $(NVCCFLAGS) -o $@ -c $< $(OCV_INC) $(CUDA_INC)
    #$(NVCC) $(NVCCFLAGS) -o $@ -c $< $(OCV_INC) $(CUDA_INC)

$(BUILD_DIR)/%.cpp.o: %.cpp
    $(MKDIR_P) $(dir $@)
    $(CXX) $(CXXFLAGS) $(INCS) -o $@ -c $< 

# Phony rules -------------------------------------------------------------------------------

.PHONY: clean
clean:
    $(RM) -r $(BUILD_DIR)

MKDIR_P ?= mkdir -p

-include $(DEPS)

我知道,我没有使用任何.d规则,我正在努力完成这项工作并稍后弄清楚如何将.d规则纳入更复杂的内容。

2 个答案:

答案 0 :(得分:1)

  

它不是一个合适的二进制文件

最近的原因是您指定设备链接作为最终构建(即链接阶段)操作:

NVCCFLNK    ?= $(CUDA_ARCH) --device-link
                              ^^^^^^^^^^^
...

$(BUILD_DIR)/$(TARGET_EXEC): $(OBJS) 
    $(NVCC) $(NVCCFLNK) $(OBJS) $(LIB_DIRS)  -o $@ 
              ^^^^^^^^

因此,您执行的最后一个构建步骤是设备链接does not create an executable。您的Makefile通常也没有为设备链接正确设置,因为在将编译与链接分开时,如果您想要设备链接(即生成relocatable device code),那么您必须指定-dc,而不是{{1在编译期间:

-c

由于您已经指定链接阶段应该立即完成,并且使用$(BUILD_DIR)/%.cu.o: %.cu $(MKDIR_P) $(dir $@) $(NVCC) $(NVCCFLAGS) -o $@ -c $< ^^ ,我们可以对您的makefile进行some relatively simple changes以实现将执行rdc链接的makefile。这是一个完整的例子,源自你的:

nvcc

请注意,如果您实际上不想生成RDC代码,可以在上面的Makefile中将$ cat Makefile TARGET_EXEC ?= cudaNestim.out NVCC ?= nvcc BUILD_DIR ?= ./bld SRC_DIRS ?= ./src CUDA_ARCH ?= -arch=sm_61 NVCCFLAGS ?= $(CUDA_ARCH) #NVCCFLNK ?= $(CUDA_ARCH) --device-link NVCCFLNK ?= $(CUDA_ARCH) CXXFLAGS ?= --std=c++11 -MM -MT CXXOPTS ?= -MM -MT # System Libraries ------------------------------------------------------------------------------- OCV_DIR ?= -L/user/local/lib #OCV_LIB ?= -lopencv_core -lopencv_viz -lopencv_highgui -lopencv_features2d -lopencv_imgproc OCV_LIB ?= OCV_INC ?= -I/usr/include OCV_LINK ?= $(OCV_DIR) $(OCV_LIB) CUDA_DIR ?= -L/usr/local/cuda-8.0/lib64 #CUDA_LIB ?= -lcutil -lcudpp -lcuda -lcudart CUDA_LIB ?= -lcuda -lcudart CUDA_INC ?= -I/usr/local/cuda-8.0/include CUDA_LINK ?= $(CUDA_DIR) $(CUDA_LIB) #-------------------------------------------------------------------------------------------------- MKDIR_P ?= mkdir -p # find all the source files SRCS := $(shell find $(SRC_DIRS) -name *.cu -or -name *.cpp -or -name *.c -or -name *.s) #go to build directory and create a .o file for each src file found OBJS := $(SRCS:%=$(BUILD_DIR)/%.o) # create a .d file from each .o file. SO one .d for each .source DEPS := $(OBJS:.o=.d) LIB_DIRS := $(OCV_LINK) $(CUDA_LINK) INCS := $(CUDA_INC) $(OCV_INC) $(BUILD_DIR)/$(TARGET_EXEC): $(OBJS) $(NVCC) $(NVCCFLNK) $(OBJS) $(LIB_DIRS) -o $@ $(BUILD_DIR)/%.cu.o: %.cu $(MKDIR_P) $(dir $@) $(NVCC) $(NVCCFLAGS) -o $@ -dc $< #echo ".cu.o rule:" $(NVCCFLAGS) -o $@ -c $< $(OCV_INC) $(CUDA_INC) #$(NVCC) $(NVCCFLAGS) -o $@ -c $< $(OCV_INC) $(CUDA_INC) $(BUILD_DIR)/%.cpp.o: %.cpp $(MKDIR_P) $(dir $@) $(CXX) $(CXXFLAGS) $(INCS) -o $@ -c $< # Phony rules ------------------------------------------------------------------------------- .PHONY: clean clean: $(RM) -r $(BUILD_DIR) $ ls bld Makefile src $ cat src/hello.cu #include <stdio.h> __device__ void hello(){ printf("hello!\n"); } $ cat src/test.cu #include <stdio.h> __device__ void hello(); __global__ void my_hello(){ hello(); } int main(){ my_hello<<<1,1>>>(); cudaDeviceSynchronize(); } $ make clean rm -f -r ./bld $ make mkdir -p bld/./src/ nvcc -arch=sm_61 -o bld/./src/hello.cu.o -dc src/hello.cu mkdir -p bld/./src/ nvcc -arch=sm_61 -o bld/./src/test.cu.o -dc src/test.cu nvcc -arch=sm_61 ./bld/./src/hello.cu.o ./bld/./src/test.cu.o -L/user/local/lib -L/usr/local/cuda-8.0/lib64 -lcuda -lcudart -o bld/cudaNestim.out $ bld/cudaNestim.out hello! $ 更改回-dc。但是,出于演示目的,我的特定代码示例依赖于CUDA RDC。

答案 1 :(得分:-2)

更多的建议而非直接回答:

你做错了是试图重新发明轮子。使用更高级别的构建系统,不要自己编写Makefile。其中不止一个;我个人使用CMake并且对它很满意。 CMake有一个模块,用于为CUDA设置路径和其他变量。这是一个你可以查看的简短教程:

How to build CUDA programs using CMake

现在,并非您不会遇到任何问题,但是:

  1. 他们会少一些
  2. 他们可能更容易调试(在SO上看一些CMake+CUDA questions。)