cmake真心强大,这不,我这有个Makefile管理的CUDA项目需要大改,程序目录结构替换,可能导致大量的Makefile工程文件需要维护,我想着cmake可不可以编译CUDA项目呢,果然没有让人失望。
FIND_PACKAGE(CUDA REQUIRED)
cuda_add_library(... ...)
cuda_add_executable(... ...)
一如既往的简单,不过,总有让人气馁的地方:
~/project_tst/src/compute/cuda/ckernels.cu(52): error: identifier "BLOCK" is undefined
1 error detected in the compilation of "/tmp/tmpxft_00000706_00000000-6_ckernels.cpp1.ii".
CMake Error at vas_generated_ckernels.cu.o.cmake:280 (message):
Error generating file
~/project_tst/build/CMakeFiles/vas.dir/src/compute/cuda/./test_generated_ckernels.cu.o
CMakeFiles/vas.dir/build.make:740: recipe for target 'CMakeFiles/vas.dir/src/compute/cuda/vas_generated_ckernels.cu.o' failed
make[2]: *** [CMakeFiles/vas.dir/src/compute/cuda/test_generated_ckernels.cu.o] Error 1
make[2]: *** Waiting for unfinished jobs....
~/project_tst/src/compute/cuda/ckernels.cu(185): error: identifier "cuda_random" is undefined
~/project_tst/src/compute/cuda/ckernels.cu(198): error: identifier "cuda_gridsize" is undefined
~/project_tst/src/compute/cuda/ckernels.cu(199): error: identifier "check_error" is undefined
3 errors detected in the compilation of "/tmp/tmpxft_0000073c_00000000-6_crop_layer_kernels.cpp1.ii".
上面介绍,可能很多小伙伴看着恐惧,其实就是 “BLOCK” 宏定义找不到。这个就莫名其妙了,项目也构成成功了,头文件也找到了,宏定义是我的项目里面大大的显示起的。
但也没必要慌,问题总是要解决的,我们来跟踪下。
make VERBOSE=1
恩恩,这里就可以显示出来项目编译时候的命令了
/usr/local/cuda/bin/nvcc \
~/project_tst/src/compute/cuda/ckernels.cu \
-c \
-o ~/project_tst/build/CMakeFiles/test.dir/src/compute/cuda/./test_generated_ckernels.cu.o \
-ccbin /usr/bin/cc \
-m64 \
-DGPU \
-DCUDNN \
-gencode \
arch=compute_61,code=sm_61 -std=c++11 -DNVCC \
-I/usr/local/cuda/include \
-I~/project_tst/src/compute/inc \
-I~/project_tst/include
这命令说明问题大致运行是没有毛病的,这就让我摸不到头脑了。我直接把命令放到命令行里面运行,发现还真的有问题。
千般调戏,额,调试,果然是小问题,看到倒数第三行的-I/usr/local/cuda/include
,如果没有这一行的话,就没问题了。
问题我大概定位在因为我工程里的头文件名和cuda提供的文件冲突了,折腾,cuda的头文件命名和我一样随便,它还是啥世界通用的加速项目,吐吐槽,哈哈。
又说回来,这个cuda寻找目录不指明,项目其他部分编译又有问题,为啥以前在Makefile做的时候没有发现呢。于是我把头文件查找顺序替换了一下,发现问题也没有了。
好嘛,问题定位没问了,我们来看看怎么解决。
这个cuda目录没有手动添加,只能是cmake后面做了手脚,那就还得看看cmake怎么说,官网来了。
官网说了,之所以编译的时候有这个cuda的目录是因为 包含 这个cuda目录的 CUDA_INCLUDE_DIRS 变量 被工程默认引用了。
我只是想替换下顺序,怎么做到呢,我这里提供一种"愚蠢"的方法,供大家参考:
set(prj_name test)
set(prj_src ${test_src})
set(prj_inc ${test_inc} include)
set(prj_def PUBLIC GPU=1 PUBLIC CUDNN=1)
# 将CUDA_INCLUDE_DIRS变量中的值保存到另外一个变量中
set(cuda_inc ${CUDA_INCLUDE_DIRS})
# 把 CUDA_INCLUDE_DIRS 变量值空
set(CUDA_INCLUDE_DIRS)
cuda_add_library(${prj_name} SHARED ${prj_src})
target_compile_definitions(${prj_name} ${prj_def})
# 这里通过我们的自定义变量就可以自定义引用顺序了
target_include_directories(${prj_name} ${prj_inc} ${cuda_inc})
坑真大,不过还是一脸灰的出来了。供大家参考!!