我最近与CMake进行了一些斗争,试图让它在涉及Cuda的不同平台上为Debug和Release目标生成项目文件。我在C和Windows上使用的Cuda版本是9.1。 CMake版本在Windows上为3.9,在Linux上为3.10。
问题实际上很简单,因为如果 nvcc 正确传递"-DEBUG"
标志,我就可以在Windows上生成构建。但是,我似乎无法通过配置自动正确传递标志。我尝试使用CMAKE_NVCC_FLAGS_CONFIG
,CMAKE_CXX_FLAGS_CONFIG
将CUDA_PROPAGATE_HOST_FLAGS
设置为ON/OFF
,将CUDA_HOST_COMPILATION_CPP
切换为ON/OFF
也没有帮助。使用表达式生成器设置标志以使用set_directory_property
设置目录属性,或作为cuda_add_executable
的选项也不起作用。
这是我的cmake脚本的要点:
# CMake entry point
cmake_minimum_required (VERSION 3.9.1)
set( APP_NAME example-CUDA )
find_package(XYZ)
find_package(CUDA) # not required according to 1st-class status in CMake3 .8+
enable_language(CUDA)
set(CUDA_VERBOSE_BUILD ON)
set(SRC_EXAMPLE "main.cpp" "gj.cu" "gj.cuh")
SOURCE_GROUP(Example FILES ${SRC_EXAMPLE})
set(SRC_BUILD_FILES ${SRC_EXAMPLE})
# note: similar stuff for linux ommitted..
if("${CMAKE_SYSTEM_NAME}" STREQUAL "Windows")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4 /WX /sdl- -Zm256")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MD")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /we4146 /we4308 /we4532 /we4533 /we4700 /we4703 /we4789 /we4995 /we4996")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /INCREMENTAL")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MP")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /we4146 /we4308 /we4532 /we4533 /we4700 /we4703 /we4789 /we4995 /we4996")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /W4 /WX /sdl- -Zm256")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /Zi")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /D_DEBUG" CACHE STRING "compile flags debug" FORCE)
endif()
# cuda 9 flags for max compatibility ( note: no more sm 20!)
set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS} "-arch=sm_30 -gencode=arch=compute_30,code=sm_30 -gencode=arch=compute_50,code=sm_50 -gencode=arch=compute_52,code=sm_52 -gencode=arch=compute_60,code=sm_60 -gencode=arch=compute_61,code=sm_61 -gencode=arch=compute_62,code=sm_62 -gencode=arch=compute_70,code=sm_70 -gencode=arch=compute_70,code=compute_70")
include_directories(SYSTEM ${CUDA_TOOLKIT_INCLUDE} ${CMAKE_CURRENT_SOURCE_DIR})
#set(CUDA_HOST_COMPILATION_CPP ON)
#set(CUDA_PROPAGATE_HOST_FLAGS ON)
#set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS} " -D_DEBUG ") # works, but hadcoded config :(
set(CUDA_NVCC_FLAGS_DEBUG ${CUDA_NVCC_FLAGS_DEBUG} " -D_DEBUG ") # fails, not picked up..
#cuda_add_executable (${APP_NAME} ${SRC_EXAMPLE} OPTIONS $<$<CONFIG:Debug>:"-DEBUG">) #fails, generator not run
cuda_add_executable (${APP_NAME} ${SRC_EXAMPLE})
target_link_libraries (${APP_NAME} PUBLIC CUDA XYZ)
我在VS2015中遇到的错误(我也使用2017年)是典型的_ITERATOR_DEBUG_LEVEL不正确,这意味着其中一个编译单元没有正确传递-DEBUG标志,并且链接器看到了反复和释放模块混合。由nvcc.exe构建的模块在内部传递以供cl.exe编译用于非cuda代码位,除了缺少所有_DEBUG配置标志。我通过FindCUDA.cmake阅读了一些有趣的内容,但几乎不可能分辨出哪些有用,哪些无效。
我显然错过了什么,但是什么?任何解决方法?更新1:我还在CMakeLists.txt层次结构中提前设置了以下方法:
project (MyLittleBigProject)
# Set default build type
set(PROJECT_CONFIGURATIONS Debug Release CACHE TYPE INTERNAL FORCE)
if(DEFINED CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE} CACHE STRING "Build configs: ${PROJECT_CONFIGURATIONS}")
else()
set(CMAKE_BUILD_TYPE Debug CACHE STRING "Build configs: ${PROJECT_CONFIGURATIONS}")
endif()
答案 0 :(得分:1)
我不了解CUDA / NVCC,但查看FindCUDA
的文档,您可以尝试以下几种方法:
CMAKE_C_FLAGS_DEBUG
传递调试标记,因为CUDA_HOST_COMPILER
的文档指出默认使用CMAKE_C_COMPILER
,而不是CMAKE_CXX_COMPILER
,cuda_add_executable()
传递调试标记:文档指示它调用cuda_wrap_srcs()
,您可以使用OPTIONS DEBUG ...
传递特定标记希望这有帮助。
答案 1 :(得分:0)
有很多事情共同努力来创造这个问题,最大的问题是对VS2017的支持根本不存在。
也就是说,通过构建我自己的Cmake虚拟目标来包装所有CUDA库依赖项和构建设置,我仍然可以正确地为其他编译器工作。我从可以找到的CUDA的现有Find_XXX CMake脚本开始,并在宏之后添加了以下部分(我几乎使用了任何依赖项的技巧)。这一部分实际上并不是绝对必要的,因为CMake显然在幕后为你做了同样的事情,但它也适用于自动化出现问题的情况,并且奖励你可以完全控制正在发生的事情。
set(API "CUDA")
if(NOT TARGET "${API}")
if (CUDA_cudart_static_LIBRARY) # we assume at least cuda 5.5+
add_custom_target("Generate${API}" DEPENDS "${CUDA_cudart_static_LIBRARY}" )
add_library( "${API}" STATIC IMPORTED GLOBAL )
set_property(TARGET "${API}" PROPERTY IMPORTED_LOCATION "${CUDA_cudart_static_LIBRARY}")
set_property(TARGET "${API}" PROPERTY INTERFACE_LINK_LIBRARIES "${CUDA_LIBRARIES}")
set_property(TARGET "${API}" PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${CUDA_INCLUDE_DIRS}" )
set_property(TARGET "${API}" PROPERTY FOLDER "APIGenerators" )
set_property(TARGET "Generate${API}" PROPERTY FOLDER "APIGenerators" )
add_dependencies( "${API}" "Generate${API}")
else()
add_library( "${API}" INTERFACE IMPORTED GLOBAL )
endif()
endif()
现在您已经为CUDA准备了自己的CUDA Find_Package调用,yhou可以继续设置cmake来创建项目,只需调用find_package(CUDA)即可。 CMake'自动'识别CUDA,因此链接实际上是隐含的。以下是我为幕后调用的NVCC编译步骤设置一些变量的方法:
enable_language(CUDA)
set(CUDA_VERBOSE_BUILD ON)
set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS} "-I=${GLM_INCLUDE_DIR} ")
set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS} "-I=${GLEW_INCLUDE_PATH} ")
set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS} "-I=${YOUR_INCLUDE_DIRS} ")
# cuda 9 flags for max compatibility ( no more sm 20!)
if("${CMAKE_SYSTEM_NAME}" STREQUAL "Windows")
#set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS} "-arch=sm_30 -gencode=arch=compute_30,code=sm_30 -gencode=arch=compute_50,code=sm_50 -gencode=arch=compute_52,code=sm_52 -gencode=arch=compute_60,code=sm_60 -gencode=arch=compute_61,code=sm_61 -gencode=arch=compute_62,code=sm_62 -gencode=arch=compute_70,code=sm_70 -gencode=arch=compute_70,code=compute_70")
set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS} "-arch=sm_30")
set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS} " -gencode=arch=compute_30,code=sm_30")
set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS} " -gencode=arch=compute_50,code=sm_50")
set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS} " -gencode=arch=compute_52,code=sm_52")
set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS} " -gencode=arch=compute_60,code=sm_60")
set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS} " -gencode=arch=compute_61,code=sm_61")
set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS} " -gencode=arch=compute_62,code=sm_62")
set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS} " -gencode=arch=compute_70,code=sm_70")
set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS} " -gencode=arch=compute_70,code=compute_70")
else()
set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS} "-arch=sm_30")
set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS} " -gencode=arch=compute_30,code=sm_30")
set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS} " -gencode=arch=compute_50,code=sm_50")
set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS} " -gencode=arch=compute_52,code=sm_52")
set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS} " -std=c++11")
endif()
现在你可以关闭包含主机标志的CUDA标志,因为你自己设置了它们,并指定了我的情况下所需的一些相关的编译定义。
set(CUDA_HOST_COMPILATION_CPP OFF)
set(CUDA_PROPAGATE_HOST_FLAGS OFF)
target_compile_definitions(${APP_NAME} PRIVATE $<$<CONFIG:Debug>:"_DEBUG ">)
target_compile_definitions(${APP_NAME} PRIVATE "_MWAITXINTRIN_H_INCLUDED")
target_compile_definitions(${APP_NAME} PRIVATE "_FORCE_INLINES")
target_compile_definitions(${APP_NAME} PRIVATE "__STRICT_ANSI__")
set_target_properties(${APP_NAME} PROPERTIES COMPILE_FLAGS "-std=c++11")
最后但并非最不重要的是,切换到C ++ 11编译,因为否则您的编译器可能会被所有&lt; &GT;类似模板的自动类型构造。
set_target_properties(${APP_NAME} PROPERTIES COMPILE_FLAGS "-std=c++11")
希望这对你们中的一些人有所帮助。如果您知道如何在没有太多麻烦的情况下让它在VS2017上运行,请发表评论!