This bug happens when using the CUDA_WRAP_SRCS macro on Windows with Visual Studio if the CUDA_HOST_COMPILER variable is left blank, and here’s why:
In FindCUDA.cmake @ line 1378 (inside the CUDA_WRAP_SRCS definition) exists the following code:
# This needs to be passed in at this stage, because VS needs to fill out the
# value of VCInstallDir from within VS. Note that CCBIN is only used if
# -ccbin or --compiler-bindir isn't used and CUDA_HOST_COMPILER matches
# $(VCInstallDir)/bin.
if(CMAKE_GENERATOR MATCHES "Visual Studio")
set(ccbin_flags -D "\"CCBIN:PATH=$(VCInstallDir)bin\"" )
else()
set(ccbin_flags)
endif()
The comment notes that the CCBIN variable is only used if -ccbin or --compiler-bindir isn’t used and CUDA_HOST_COMPILER matches $(VCInstallDir)/bin. However this is not true.
The CCBIN variable is used in the run_nvcc.cmake file (which is a configure file used to run nvcc), however the variable is used regardless of the above situtation. It is checked in that situation by the following code @ line 125:
# Any -ccbin existing in CUDA_NVCC_FLAGS gets highest priority
list( FIND CUDA_NVCC_FLAGS "-ccbin" ccbin_found0 )
list( FIND CUDA_NVCC_FLAGS "--compiler-bindir" ccbin_found1 )
if( ccbin_found0 LESS 0 AND ccbin_found1 LESS 0 AND CUDA_HOST_COMPILER )
if (CUDA_HOST_COMPILER STREQUAL "$(VCInstallDir)bin" AND DEFINED CCBIN)
set(CCBIN -ccbin "${CCBIN}")
else()
set(CCBIN -ccbin "${CUDA_HOST_COMPILER}")
endif()
endif()
However if none of the conditionals pass, for instance if CUDA_HOST_COMPILER is blank, then the variable CCBIN is left unchanged, this is a problem because FindCUDA.cmake sets it to various path values:
FindCUDA.cmake @ line 1715 onwards:
if (CUDA_HOST_COMPILER STREQUAL "$(VCInstallDir)bin")
if (CUDA_VS_DIR)
set(_cuda_dependency_ccbin -D "CCBIN:PATH=${CUDA_VS_DIR}/VC/bin")
endif()
elseif(ccbin_flags)
# The CUDA_HOST_COMPILER is set to something interesting, so use the
# ccbin_flags as-is.
set(_cuda_dependency_ccbin ${ccbin_flags})
endif()
This results in the CCBIN variable being set to a path and added to the nvcc command which nvcc interprets as another file giving the error:
A single input file is required for a non-link phase when an outputfile is specified
Now the easiest fix for this is to change run_nvcc.cmake to obey the comment in FindCUDA.cmake and not use the CCBIN variable if the conditions aren’t met, this can easily be done by clearing the CCBIN variable like so:
# Any -ccbin existing in CUDA_NVCC_FLAGS gets highest priority
list( FIND CUDA_NVCC_FLAGS "-ccbin" ccbin_found0 )
list( FIND CUDA_NVCC_FLAGS "--compiler-bindir" ccbin_found1 )
if( ccbin_found0 LESS 0 AND ccbin_found1 LESS 0 AND CUDA_HOST_COMPILER )
if (CUDA_HOST_COMPILER STREQUAL "$(VCInstallDir)bin" AND DEFINED CCBIN)
set(CCBIN -ccbin "${CCBIN}")
else()
set(CCBIN -ccbin "${CUDA_HOST_COMPILER}")
endif()
else()
# Need to ensure here that ccbin is cleared as FindCUDA.cmake sets this to something non-executable on Windows
set(CCBIN "")
endif()
That’s the fix I have locally and it works fine, I know those cmake files are only distributed along with the samples but I imagine quite a few people like myself port them to actual projects.
Cheers