我花了很多时间尝试编写一个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规则纳入更复杂的内容。
答案 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
现在,并非您不会遇到任何问题,但是: