【问题标题】:Makefile for cuda/c++, Cannot successfully compilecuda/c++ 的 Makefile,无法成功编译
【发布时间】:2017-04-29 18:04:59
【问题描述】:

我花了很多时间尝试编写一个 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 规则合并到更复杂的内容中。

【问题讨论】:

  • 发布最终的链接命令,因为它出现在您的 shell 中。详细说明“它不是一个正确的二进制文件。”。
  • 另外,如果您尝试分两步(首先是对象,然后是cudaNestim.out)在不使用 Make 的情况下手动构建二进制文件会发生什么?

标签: c++ makefile compilation cuda


【解决方案1】:

它不是一个正确的二进制文件

这样做的最接近的原因是您将 device-link 指定为最终构建(即链接阶段)操作:

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,而不是 -c

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

由于您已经指定应该立即完成链接阶段,并且使用nvcc,我们可以将some relatively simple changes 添加到您的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。

【讨论】:

    【解决方案2】:

    更多的是建议而不是直接回答:

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

    How to build CUDA programs using CMake

    现在,并不是说您永远不会遇到任何问题,而是:

    1. 它们会更少
    2. 他们可能会更容易调试(查看一些CMake+CUDA questions 这里的 SO)。

    【讨论】:

    • 解释 JWZ -- 改用 CMake。现在你有两个问题。
    • @talonmies:自动发现 CUDA 相关路径是 CMake 将为 OP 做的事情。所以,不,现在 OP 将有 0 或 1 个问题。
    猜你喜欢
    • 2011-08-31
    • 2022-03-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多