簡體   English   中英

用於cuda / c ++的Makefile,無法成功編譯

[英]Makefile for cuda/c++, Cannot successfully compile

我花了很多時間嘗試編寫一個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規則。

它不是正確的二進制文件

最接近的原因是您將設備鏈接指定為最終構建(即鏈接階段)操作:

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

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

因此,您執行的最后一個構建步驟是設備鏈接,該鏈接不會創建可執行文件 您的Makefile通常也沒有正確設置以進行設備鏈接,因為將編譯與鏈接分開時,如果要進行設備鏈接(即,生成可重定位的設備代碼 ),則必須在編譯期間指定-dc ,而不是-c

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

因為您已經指定了鏈接階段應該立即完成,並且使用nvcc ,我們可以對您的makefile進行一些相對簡單的更改 ,以實現可以進行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!
$

請注意,如果您實際上不希望生成RDC代碼,則可以在上面的Makefile中將-dc更改回-c 但是,出於演示目的,我的特定代碼示例取決於CUDA RDC。

比直接回答更多的是建議:

您做錯的是嘗試重新發明輪子。 使用更高級別的構建系統,不要麻煩自己編寫Makefile。 周圍有不止一種; 我個人使用CMake並對此感到滿意。 CMake有一個模塊,用於為CUDA設置事物路徑和其他變量。 這是一個簡短的教程,您可以簽出:

如何使用CMake構建CUDA程序

現在,這並不是說您永遠不會遇到任何問題,而是:

  1. 他們會更少
  2. 它們可能更容易調試(在SO上查看了一些CMake + CUDA問題 )。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM