diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst
index 2606ba063f5babe062eae7652080505d9e43db4f..e4ee7255b618201c78d8d1d247e012cefc7a539e 100644
--- a/Help/manual/cmake-variables.7.rst
+++ b/Help/manual/cmake-variables.7.rst
@@ -84,6 +84,7 @@ Variables that Provide Information
    /variable/CMAKE_VS_NsightTegra_VERSION
    /variable/CMAKE_VS_PLATFORM_NAME
    /variable/CMAKE_VS_PLATFORM_TOOLSET
+   /variable/CMAKE_VS_PLATFORM_TOOLSET_CUDA
    /variable/CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE
    /variable/CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION
    /variable/CMAKE_XCODE_PLATFORM_TOOLSET
diff --git a/Help/variable/CMAKE_VS_PLATFORM_TOOLSET_CUDA.rst b/Help/variable/CMAKE_VS_PLATFORM_TOOLSET_CUDA.rst
new file mode 100644
index 0000000000000000000000000000000000000000..1604a76675f2eddec54c93c8ceb041d01d9b4772
--- /dev/null
+++ b/Help/variable/CMAKE_VS_PLATFORM_TOOLSET_CUDA.rst
@@ -0,0 +1,12 @@
+CMAKE_VS_PLATFORM_TOOLSET_CUDA
+------------------------------
+
+NVIDIA CUDA Toolkit version whose Visual Studio toolset to use.
+
+The :ref:`Visual Studio Generators` for VS 2010 and above support using
+a CUDA toolset provided by a CUDA Toolkit.  The toolset version number
+may be specified by a field in :variable:`CMAKE_GENERATOR_TOOLSET` of
+the form ``cuda=8.0``.  If none is specified CMake will choose a default
+version.  CMake provides the selected CUDA toolset version in this variable.
+The value may be empty if no CUDA Toolkit with Visual Studio integration
+is installed.
diff --git a/Modules/CMakeDetermineCUDACompiler.cmake b/Modules/CMakeDetermineCUDACompiler.cmake
index 375e2307de6dace9862d3115ba60e73ec3cae89a..55a6f0ceb53cf919925a17f563629a3d0eece497 100644
--- a/Modules/CMakeDetermineCUDACompiler.cmake
+++ b/Modules/CMakeDetermineCUDACompiler.cmake
@@ -5,36 +5,40 @@ include(${CMAKE_ROOT}/Modules/CMakeDetermineCompiler.cmake)
 include(${CMAKE_ROOT}/Modules//CMakeParseImplicitLinkInfo.cmake)
 
 if( NOT ( ("${CMAKE_GENERATOR}" MATCHES "Make") OR
-          ("${CMAKE_GENERATOR}" MATCHES "Ninja") ) )
+          ("${CMAKE_GENERATOR}" MATCHES "Ninja") OR
+          ("${CMAKE_GENERATOR}" MATCHES "Visual Studio (1|[7-9][0-9])") ) )
   message(FATAL_ERROR "CUDA language not currently supported by \"${CMAKE_GENERATOR}\" generator")
 endif()
 
-if(NOT CMAKE_CUDA_COMPILER)
-  set(CMAKE_CUDA_COMPILER_INIT NOTFOUND)
-
-    # prefer the environment variable CUDACXX
-    if(NOT $ENV{CUDACXX} STREQUAL "")
-      get_filename_component(CMAKE_CUDA_COMPILER_INIT $ENV{CUDACXX} PROGRAM PROGRAM_ARGS CMAKE_CUDA_FLAGS_ENV_INIT)
-      if(CMAKE_CUDA_FLAGS_ENV_INIT)
-        set(CMAKE_CUDA_COMPILER_ARG1 "${CMAKE_CUDA_FLAGS_ENV_INIT}" CACHE STRING "First argument to CXX compiler")
-      endif()
-      if(NOT EXISTS ${CMAKE_CUDA_COMPILER_INIT})
-        message(FATAL_ERROR "Could not find compiler set in environment variable CUDACXX:\n$ENV{CUDACXX}.\n${CMAKE_CUDA_COMPILER_INIT}")
+if(${CMAKE_GENERATOR} MATCHES "Visual Studio")
+else()
+  if(NOT CMAKE_CUDA_COMPILER)
+    set(CMAKE_CUDA_COMPILER_INIT NOTFOUND)
+
+      # prefer the environment variable CUDACXX
+      if(NOT $ENV{CUDACXX} STREQUAL "")
+        get_filename_component(CMAKE_CUDA_COMPILER_INIT $ENV{CUDACXX} PROGRAM PROGRAM_ARGS CMAKE_CUDA_FLAGS_ENV_INIT)
+        if(CMAKE_CUDA_FLAGS_ENV_INIT)
+          set(CMAKE_CUDA_COMPILER_ARG1 "${CMAKE_CUDA_FLAGS_ENV_INIT}" CACHE STRING "First argument to CXX compiler")
+        endif()
+        if(NOT EXISTS ${CMAKE_CUDA_COMPILER_INIT})
+          message(FATAL_ERROR "Could not find compiler set in environment variable CUDACXX:\n$ENV{CUDACXX}.\n${CMAKE_CUDA_COMPILER_INIT}")
+        endif()
       endif()
+
+    # finally list compilers to try
+    if(NOT CMAKE_CUDA_COMPILER_INIT)
+      set(CMAKE_CUDA_COMPILER_LIST nvcc)
     endif()
 
-  # finally list compilers to try
-  if(NOT CMAKE_CUDA_COMPILER_INIT)
-    set(CMAKE_CUDA_COMPILER_LIST nvcc)
+    _cmake_find_compiler(CUDA)
+  else()
+    _cmake_find_compiler_path(CUDA)
   endif()
 
-  _cmake_find_compiler(CUDA)
-else()
-  _cmake_find_compiler_path(CUDA)
+  mark_as_advanced(CMAKE_CUDA_COMPILER)
 endif()
 
-mark_as_advanced(CMAKE_CUDA_COMPILER)
-
 #Allow the user to specify a host compiler
 set(CMAKE_CUDA_HOST_COMPILER "" CACHE FILEPATH "Host compiler to be used by nvcc")
 if(NOT $ENV{CUDAHOSTCXX} STREQUAL "")
@@ -75,7 +79,12 @@ if(MSVC_CUDA_ARCHITECTURE_ID)
     "set(MSVC_CUDA_ARCHITECTURE_ID ${MSVC_CUDA_ARCHITECTURE_ID})")
 endif()
 
-if(CMAKE_CUDA_COMPILER_ID STREQUAL NVIDIA)
+if(${CMAKE_GENERATOR} MATCHES "Visual Studio")
+  set(CMAKE_CUDA_HOST_LINK_LAUNCHER "${CMAKE_LINKER}")
+  set(CMAKE_CUDA_HOST_IMPLICIT_LINK_LIBRARIES "")
+  set(CMAKE_CUDA_HOST_IMPLICIT_LINK_DIRECTORIES "")
+  set(CMAKE_CUDA_HOST_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "")
+elseif(CMAKE_CUDA_COMPILER_ID STREQUAL NVIDIA)
   set(_nvcc_log "")
   string(REPLACE "\r" "" _nvcc_output_orig "${CMAKE_CUDA_COMPILER_PRODUCED_OUTPUT}")
   if(_nvcc_output_orig MATCHES "#\\\$ +LIBRARIES= *([^\n]*)\n")
diff --git a/Modules/CMakeDetermineCompilerId.cmake b/Modules/CMakeDetermineCompilerId.cmake
index ae485bfbbdf303f94a6753a669720007fd34c51a..6fce8e20722e95ac102e23bf94ca83981820283c 100644
--- a/Modules/CMakeDetermineCompilerId.cmake
+++ b/Modules/CMakeDetermineCompilerId.cmake
@@ -235,6 +235,26 @@ Id flags: ${testflags} ${CMAKE_${lang}_COMPILER_ID_FLAGS_ALWAYS}
     endif()
     set(id_dir ${CMAKE_${lang}_COMPILER_ID_DIR})
     set(id_src "${src}")
+    set(id_compile "ClCompile")
+    set(id_PostBuildEvent_Command "for %%i in (${id_cl}) do %40echo CMAKE_${lang}_COMPILER=%%~$PATH:i")
+    set(id_Import_props "")
+    set(id_Import_targets "")
+    set(id_ItemDefinitionGroup_entry "")
+    set(id_Link_AdditionalDependencies "")
+    if(lang STREQUAL CUDA)
+      if(NOT CMAKE_VS_PLATFORM_TOOLSET_CUDA)
+        message(FATAL_ERROR "No CUDA toolset found.")
+      endif()
+      set(cuda_tools "CUDA ${CMAKE_VS_PLATFORM_TOOLSET_CUDA}")
+      set(id_compile "CudaCompile")
+      set(id_PostBuildEvent_Command [[echo CMAKE_CUDA_COMPILER=$(CudaToolkitBinDir)\nvcc.exe]])
+      string(CONCAT id_Import_props [[<Import Project="$(VCTargetsPath)\BuildCustomizations\]] "${cuda_tools}" [[.props" />]])
+      string(CONCAT id_Import_targets [[<Import Project="$(VCTargetsPath)\BuildCustomizations\]] "${cuda_tools}" [[.targets" />]])
+      if(CMAKE_VS_PLATFORM_NAME STREQUAL x64)
+        set(id_ItemDefinitionGroup_entry "<CudaCompile><TargetMachinePlatform>64</TargetMachinePlatform></CudaCompile>")
+      endif()
+      set(id_Link_AdditionalDependencies "<AdditionalDependencies>cudart.lib</AdditionalDependencies>")
+    endif()
     configure_file(${CMAKE_ROOT}/Modules/CompilerId/VS-${v}.${ext}.in
       ${id_dir}/CompilerId${lang}.${ext} @ONLY)
     if(CMAKE_VS_MSBUILD_COMMAND AND NOT lang STREQUAL "Fortran")
diff --git a/Modules/CompilerId/VS-10.vcxproj.in b/Modules/CompilerId/VS-10.vcxproj.in
index 50be9cbccc0c78c078030208d35433232ec6e942..6b9b361cc0c862c4b8f9f77a8e5116ead1e49cc3 100644
--- a/Modules/CompilerId/VS-10.vcxproj.in
+++ b/Modules/CompilerId/VS-10.vcxproj.in
@@ -25,6 +25,9 @@
     <CharacterSet>MultiByte</CharacterSet>
   </PropertyGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+    @id_Import_props@
+  </ImportGroup>
   <PropertyGroup>
     <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
     <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|@id_platform@'">.\</OutDir>
@@ -44,16 +47,21 @@
       <DebugInformationFormat>
       </DebugInformationFormat>
     </ClCompile>
+    @id_ItemDefinitionGroup_entry@
     <Link>
       <GenerateDebugInformation>false</GenerateDebugInformation>
       <SubSystem>Console</SubSystem>
+      @id_Link_AdditionalDependencies@
     </Link>
     <PostBuildEvent>
-      <Command>for %%i in (@id_cl@) do %40echo CMAKE_@id_lang@_COMPILER=%%~$PATH:i</Command>
+      <Command>@id_PostBuildEvent_Command@</Command>
     </PostBuildEvent>
   </ItemDefinitionGroup>
   <ItemGroup>
-    <ClCompile Include="@id_src@" />
+    <@id_compile@ Include="@id_src@" />
   </ItemGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+    @id_Import_targets@
+  </ImportGroup>
 </Project>
diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx
index b1285acc820228164ca89008203b4ac12cec0250..ca98e6c920c7e54e574b717ae48db20abcbcb037 100644
--- a/Source/cmGlobalVisualStudio10Generator.cxx
+++ b/Source/cmGlobalVisualStudio10Generator.cxx
@@ -10,15 +10,25 @@
 #include "cmSourceFile.h"
 #include "cmVS10CLFlagTable.h"
 #include "cmVS10CSharpFlagTable.h"
+#include "cmVS10CudaFlagTable.h"
+#include "cmVS10CudaHostFlagTable.h"
 #include "cmVS10LibFlagTable.h"
 #include "cmVS10LinkFlagTable.h"
 #include "cmVS10MASMFlagTable.h"
 #include "cmVS10NASMFlagTable.h"
 #include "cmVS10RCFlagTable.h"
+#include "cmVersion.h"
 #include "cmVisualStudioSlnData.h"
 #include "cmVisualStudioSlnParser.h"
+#include "cmXMLWriter.h"
 #include "cmake.h"
 
+#include <cmsys/FStream.hxx>
+#include <cmsys/Glob.hxx>
+#include <cmsys/RegularExpression.hxx>
+
+#include <algorithm>
+
 static const char vs10generatorName[] = "Visual Studio 10 2010";
 
 // Map generator name without year to name with year.
@@ -95,6 +105,7 @@ cmGlobalVisualStudio10Generator::cmGlobalVisualStudio10Generator(
     "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VCExpress\\10.0\\Setup\\VC;"
     "ProductDir",
     vc10Express, cmSystemTools::KeyWOW64_32);
+  this->CudaEnabled = false;
   this->SystemIsWindowsCE = false;
   this->SystemIsWindowsPhone = false;
   this->SystemIsWindowsStore = false;
@@ -113,6 +124,8 @@ cmGlobalVisualStudio10Generator::cmGlobalVisualStudio10Generator(
   this->DefaultCSharpFlagTable = cmVS10CSharpFlagTable;
   this->DefaultLibFlagTable = cmVS10LibFlagTable;
   this->DefaultLinkFlagTable = cmVS10LinkFlagTable;
+  this->DefaultCudaFlagTable = cmVS10CudaFlagTable;
+  this->DefaultCudaHostFlagTable = cmVS10CudaHostFlagTable;
   this->DefaultMasmFlagTable = cmVS10MASMFlagTable;
   this->DefaultNasmFlagTable = cmVS10NASMFlagTable;
   this->DefaultRcFlagTable = cmVS10RCFlagTable;
@@ -155,6 +168,13 @@ bool cmGlobalVisualStudio10Generator::SetGeneratorPlatform(
   return true;
 }
 
+static void cmCudaToolVersion(std::string& s)
+{
+  // "CUDA x.y.props" => "x.y"
+  s = s.substr(5);
+  s = s.substr(0, s.size() - 6);
+}
+
 bool cmGlobalVisualStudio10Generator::SetGeneratorToolset(
   std::string const& ts, cmMakefile* mf)
 {
@@ -170,12 +190,37 @@ bool cmGlobalVisualStudio10Generator::SetGeneratorToolset(
   if (!this->ParseGeneratorToolset(ts, mf)) {
     return false;
   }
+
+  if (!this->FindVCTargetsPath(mf)) {
+    return false;
+  }
+
+  if (this->GeneratorToolsetCuda.empty()) {
+    // Find the highest available version of the CUDA tools.
+    std::vector<std::string> cudaTools;
+    std::string const bcDir = this->VCTargetsPath + "/BuildCustomizations";
+    cmsys::Glob gl;
+    gl.SetRelative(bcDir.c_str());
+    if (gl.FindFiles(bcDir + "/CUDA *.props")) {
+      cudaTools = gl.GetFiles();
+    }
+    if (!cudaTools.empty()) {
+      std::for_each(cudaTools.begin(), cudaTools.end(), cmCudaToolVersion);
+      std::sort(cudaTools.begin(), cudaTools.end(),
+                cmSystemTools::VersionCompareGreater);
+      this->GeneratorToolsetCuda = cudaTools.at(0);
+    }
+  }
+
   if (const char* toolset = this->GetPlatformToolset()) {
     mf->AddDefinition("CMAKE_VS_PLATFORM_TOOLSET", toolset);
   }
   if (const char* hostArch = this->GetPlatformToolsetHostArchitecture()) {
     mf->AddDefinition("CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE", hostArch);
   }
+  if (const char* cuda = this->GetPlatformToolsetCuda()) {
+    mf->AddDefinition("CMAKE_VS_PLATFORM_TOOLSET_CUDA", cuda);
+  }
   return true;
 }
 
@@ -251,8 +296,10 @@ bool cmGlobalVisualStudio10Generator::ParseGeneratorToolset(
 bool cmGlobalVisualStudio10Generator::ProcessGeneratorToolsetField(
   std::string const& key, std::string const& value)
 {
-  static_cast<void>(key);
-  static_cast<void>(value);
+  if (key == "cuda") {
+    this->GeneratorToolsetCuda = value;
+    return true;
+  }
   return false;
 }
 
@@ -417,6 +464,9 @@ void cmGlobalVisualStudio10Generator::EnableLanguage(
     if (*it == "ASM_NASM") {
       this->NasmEnabled = true;
     }
+    if (*it == "CUDA") {
+      this->CudaEnabled = true;
+    }
   }
   this->AddPlatformDefinitions(mf);
   cmGlobalVisualStudio8Generator::EnableLanguage(lang, mf, optional);
@@ -453,6 +503,20 @@ cmGlobalVisualStudio10Generator::GetPlatformToolsetHostArchitecture() const
   return CM_NULLPTR;
 }
 
+const char* cmGlobalVisualStudio10Generator::GetPlatformToolsetCuda() const
+{
+  if (!this->GeneratorToolsetCuda.empty()) {
+    return this->GeneratorToolsetCuda.c_str();
+  }
+  return CM_NULLPTR;
+}
+
+std::string const&
+cmGlobalVisualStudio10Generator::GetPlatformToolsetCudaString() const
+{
+  return this->GeneratorToolsetCuda;
+}
+
 bool cmGlobalVisualStudio10Generator::FindMakeProgram(cmMakefile* mf)
 {
   if (!this->cmGlobalVisualStudio8Generator::FindMakeProgram(mf)) {
@@ -507,6 +571,208 @@ std::string cmGlobalVisualStudio10Generator::FindDevEnvCommand()
   return this->cmGlobalVisualStudio71Generator::FindDevEnvCommand();
 }
 
+bool cmGlobalVisualStudio10Generator::FindVCTargetsPath(cmMakefile* mf)
+{
+  // Skip this in special cases within our own test suite.
+  if (this->GetPlatformName() == "Test Platform" ||
+      this->GetPlatformToolsetString() == "Test Toolset") {
+    return true;
+  }
+
+  std::string wd;
+  if (!this->ConfiguredFilesPath.empty()) {
+    // In a try-compile we are given the outer CMakeFiles directory.
+    wd = this->ConfiguredFilesPath;
+  } else {
+    wd = this->GetCMakeInstance()->GetHomeOutputDirectory();
+    wd += cmake::GetCMakeFilesDirectory();
+  }
+  wd += "/";
+  wd += cmVersion::GetCMakeVersion();
+
+  // We record the result persistently in a file.
+  std::string const txt = wd + "/VCTargetsPath.txt";
+
+  // If we have a recorded result, use it.
+  {
+    cmsys::ifstream fin(txt.c_str());
+    if (fin && cmSystemTools::GetLineFromStream(fin, this->VCTargetsPath) &&
+        cmSystemTools::FileIsDirectory(this->VCTargetsPath)) {
+      cmSystemTools::ConvertToUnixSlashes(this->VCTargetsPath);
+      return true;
+    }
+  }
+
+  // Prepare the work directory.
+  if (!cmSystemTools::MakeDirectory(wd)) {
+    std::string e = "Failed to make directory:\n  " + wd;
+    mf->IssueMessage(cmake::FATAL_ERROR, e.c_str());
+    cmSystemTools::SetFatalErrorOccured();
+    return false;
+  }
+
+  // Generate a project file for MSBuild to tell us the VCTargetsPath value.
+  std::string const vcxproj = "VCTargetsPath.vcxproj";
+  {
+    std::string const vcxprojAbs = wd + "/" + vcxproj;
+    cmsys::ofstream fout(vcxprojAbs.c_str());
+    cmXMLWriter xw(fout);
+
+    /* clang-format off */
+    xw.StartDocument();
+    xw.StartElement("Project");
+     xw.Attribute("DefaultTargets", "Build");
+     xw.Attribute("ToolsVersion", "4.0");
+     xw.Attribute("xmlns",
+                  "http://schemas.microsoft.com/developer/msbuild/2003");
+     if (this->IsNsightTegra()) {
+       xw.StartElement("PropertyGroup");
+        xw.Attribute("Label", "NsightTegraProject");
+        xw.StartElement("NsightTegraProjectRevisionNumber");
+         xw.Content("6");
+        xw.EndElement(); // NsightTegraProjectRevisionNumber
+       xw.EndElement(); // PropertyGroup
+     }
+     xw.StartElement("ItemGroup");
+      xw.Attribute("Label", "ProjectConfigurations");
+      xw.StartElement("ProjectConfiguration");
+       xw.Attribute("Include", "Debug|" + this->GetPlatformName());
+       xw.StartElement("Configuration");
+        xw.Content("Debug");
+       xw.EndElement(); // Configuration
+       xw.StartElement("Platform");
+        xw.Content(this->GetPlatformName());
+       xw.EndElement(); // Platform
+      xw.EndElement(); // ProjectConfiguration
+     xw.EndElement(); // ItemGroup
+    xw.StartElement("PropertyGroup");
+     xw.Attribute("Label", "Globals");
+     xw.StartElement("ProjectGUID");
+      xw.Content("{F3FC6D86-508D-3FB1-96D2-995F08B142EC}");
+     xw.EndElement(); // ProjectGUID
+     xw.StartElement("Keyword");
+      xw.Content("Win32Proj");
+     xw.EndElement(); // Keyword
+     xw.StartElement("Platform");
+      xw.Content(this->GetPlatformName());
+     xw.EndElement(); // Platform
+     if (this->GetSystemName() == "WindowsPhone") {
+       xw.StartElement("ApplicationType");
+        xw.Content("Windows Phone");
+       xw.EndElement(); // ApplicationType
+       xw.StartElement("ApplicationTypeRevision");
+        xw.Content(this->GetSystemVersion());
+       xw.EndElement(); // ApplicationTypeRevision
+     } else if (this->GetSystemName() == "WindowsStore") {
+       xw.StartElement("ApplicationType");
+        xw.Content("Windows Store");
+       xw.EndElement(); // ApplicationType
+       xw.StartElement("ApplicationTypeRevision");
+        xw.Content(this->GetSystemVersion());
+       xw.EndElement(); // ApplicationTypeRevision
+     }
+     if (!this->WindowsTargetPlatformVersion.empty()) {
+       xw.StartElement("WindowsTargetPlatformVersion");
+        xw.Content(this->WindowsTargetPlatformVersion);
+       xw.EndElement(); // WindowsTargetPlatformVersion
+     }
+     if (this->GetPlatformName() == "ARM") {
+       xw.StartElement("WindowsSDKDesktopARMSupport");
+        xw.Content("true");
+       xw.EndElement(); // WindowsSDKDesktopARMSupport
+     }
+    xw.EndElement(); // PropertyGroup
+    xw.StartElement("Import");
+     xw.Attribute("Project",
+                  "$(VCTargetsPath)\\Microsoft.Cpp.Default.props");
+    xw.EndElement(); // Import
+    if (!this->GeneratorToolsetHostArchitecture.empty()) {
+      xw.StartElement("PropertyGroup");
+       xw.StartElement("PreferredToolArchitecture");
+        xw.Content(this->GeneratorToolsetHostArchitecture);
+       xw.EndElement(); // PreferredToolArchitecture
+      xw.EndElement(); // PropertyGroup
+    }
+    xw.StartElement("PropertyGroup");
+     xw.Attribute("Label", "Configuration");
+     xw.StartElement("ConfigurationType");
+      if (this->IsNsightTegra()) {
+        // Tegra-Android platform does not understand "Utility".
+        xw.Content("StaticLibrary");
+      } else {
+        xw.Content("Utility");
+      }
+     xw.EndElement(); // ConfigurationType
+     xw.StartElement("CharacterSet");
+      xw.Content("MultiByte");
+     xw.EndElement(); // CharacterSet
+     if (this->IsNsightTegra()) {
+       xw.StartElement("NdkToolchainVersion");
+       xw.Content(this->GetPlatformToolsetString());
+       xw.EndElement(); // NdkToolchainVersion
+     } else {
+       xw.StartElement("PlatformToolset");
+       xw.Content(this->GetPlatformToolsetString());
+       xw.EndElement(); // PlatformToolset
+     }
+    xw.EndElement(); // PropertyGroup
+    xw.StartElement("Import");
+     xw.Attribute("Project", "$(VCTargetsPath)\\Microsoft.Cpp.props");
+    xw.EndElement(); // Import
+    xw.StartElement("ItemDefinitionGroup");
+     xw.StartElement("PostBuildEvent");
+      xw.StartElement("Command");
+       xw.Content("echo VCTargetsPath=$(VCTargetsPath)");
+      xw.EndElement(); // Command
+     xw.EndElement(); // PostBuildEvent
+    xw.EndElement(); // ItemDefinitionGroup
+    xw.StartElement("Import");
+     xw.Attribute("Project",
+                  "$(VCTargetsPath)\\Microsoft.Cpp.targets");
+    xw.EndElement(); // Import
+    xw.EndElement(); // Project
+    xw.EndDocument();
+    /* clang-format on */
+  }
+
+  std::vector<std::string> cmd;
+  cmd.push_back(this->GetMSBuildCommand());
+  cmd.push_back(vcxproj);
+  cmd.push_back(std::string("/p:VisualStudioVersion=") +
+                this->GetIDEVersion());
+  std::string out;
+  int ret = 0;
+  cmsys::RegularExpression regex("\n *VCTargetsPath=([^%\r\n]+)[\r\n]");
+  if (!cmSystemTools::RunSingleCommand(cmd, &out, &out, &ret, wd.c_str(),
+                                       cmSystemTools::OUTPUT_NONE) ||
+      ret != 0 || !regex.find(out)) {
+    cmSystemTools::ReplaceString(out, "\n", "\n  ");
+    std::ostringstream e;
+    /* clang-format off */
+    e <<
+      "Failed to run MSBuild command:\n"
+      "  " << cmd[0] << "\n"
+      "to get the value of VCTargetsPath:\n"
+      "  " << out << "\n"
+      ;
+    /* clang-format on */
+    if (ret != 0) {
+      e << "Exit code: " << ret << "\n";
+    }
+    mf->IssueMessage(cmake::FATAL_ERROR, e.str().c_str());
+    cmSystemTools::SetFatalErrorOccured();
+    return false;
+  }
+  this->VCTargetsPath = regex.match(1);
+  cmSystemTools::ConvertToUnixSlashes(this->VCTargetsPath);
+
+  {
+    cmsys::ofstream fout(txt.c_str());
+    fout << this->VCTargetsPath << "\n";
+  }
+  return true;
+}
+
 void cmGlobalVisualStudio10Generator::GenerateBuildCommand(
   std::vector<std::string>& makeCommand, const std::string& makeProgram,
   const std::string& projectName, const std::string& projectDir,
@@ -721,6 +987,17 @@ cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetLinkFlagTable() const
   return (table != CM_NULLPTR) ? table : this->DefaultLinkFlagTable;
 }
 
+cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetCudaFlagTable() const
+{
+  return this->DefaultCudaFlagTable;
+}
+
+cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetCudaHostFlagTable()
+  const
+{
+  return this->DefaultCudaHostFlagTable;
+}
+
 cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetMasmFlagTable() const
 {
   cmIDEFlagTable const* table = this->ToolsetOptions.GetMasmFlagTable(
diff --git a/Source/cmGlobalVisualStudio10Generator.h b/Source/cmGlobalVisualStudio10Generator.h
index c5e4bcdc6af0453ae06257da4e7d307037fcdbd3..20f992af39465e061ad541d7b9c0913276f8ecfd 100644
--- a/Source/cmGlobalVisualStudio10Generator.h
+++ b/Source/cmGlobalVisualStudio10Generator.h
@@ -42,6 +42,8 @@ public:
                               cmMakefile*, bool optional);
   virtual void WriteSLNHeader(std::ostream& fout);
 
+  bool IsCudaEnabled() const { return this->CudaEnabled; }
+
   /** Generating for Nsight Tegra VS plugin?  */
   bool IsNsightTegra() const;
   std::string GetNsightTegraVersion() const;
@@ -53,6 +55,10 @@ public:
   /** The toolset host architecture name (e.g. x64 for 64-bit host tools).  */
   const char* GetPlatformToolsetHostArchitecture() const;
 
+  /** The cuda toolset version.  */
+  const char* GetPlatformToolsetCuda() const;
+  std::string const& GetPlatformToolsetCudaString() const;
+
   /** Return the CMAKE_SYSTEM_NAME.  */
   std::string const& GetSystemName() const { return this->SystemName; }
 
@@ -94,6 +100,8 @@ public:
   cmIDEFlagTable const* GetRcFlagTable() const;
   cmIDEFlagTable const* GetLibFlagTable() const;
   cmIDEFlagTable const* GetLinkFlagTable() const;
+  cmIDEFlagTable const* GetCudaFlagTable() const;
+  cmIDEFlagTable const* GetCudaHostFlagTable() const;
   cmIDEFlagTable const* GetMasmFlagTable() const;
   cmIDEFlagTable const* GetNasmFlagTable() const;
 
@@ -118,6 +126,7 @@ protected:
 
   std::string GeneratorToolset;
   std::string GeneratorToolsetHostArchitecture;
+  std::string GeneratorToolsetCuda;
   std::string DefaultPlatformToolset;
   std::string WindowsTargetPlatformVersion;
   std::string SystemName;
@@ -127,6 +136,8 @@ protected:
   cmIDEFlagTable const* DefaultCSharpFlagTable;
   cmIDEFlagTable const* DefaultLibFlagTable;
   cmIDEFlagTable const* DefaultLinkFlagTable;
+  cmIDEFlagTable const* DefaultCudaFlagTable;
+  cmIDEFlagTable const* DefaultCudaHostFlagTable;
   cmIDEFlagTable const* DefaultMasmFlagTable;
   cmIDEFlagTable const* DefaultNasmFlagTable;
   cmIDEFlagTable const* DefaultRcFlagTable;
@@ -160,6 +171,11 @@ private:
 
   bool ParseGeneratorToolset(std::string const& ts, cmMakefile* mf);
 
+  std::string VCTargetsPath;
+  bool FindVCTargetsPath(cmMakefile* mf);
+
+  bool CudaEnabled;
+
   // We do not use the reload macros for VS >= 10.
   virtual std::string GetUserMacrosDirectory() { return ""; }
 };
diff --git a/Source/cmVS10CudaFlagTable.h b/Source/cmVS10CudaFlagTable.h
new file mode 100644
index 0000000000000000000000000000000000000000..da19d649b3ee29008e7a44da745b2137c3176e5f
--- /dev/null
+++ b/Source/cmVS10CudaFlagTable.h
@@ -0,0 +1,51 @@
+static cmVS7FlagTable cmVS10CudaFlagTable[] = {
+  // Collect options meant for the host compiler.
+  { "AdditionalCompilerOptions", "Xcompiler=", "Host compiler options", "",
+    cmVS7FlagTable::UserValue | cmVS7FlagTable::SpaceAppendable },
+  { "AdditionalCompilerOptions", "Xcompiler", "Host compiler options", "",
+    cmVS7FlagTable::UserFollowing | cmVS7FlagTable::SpaceAppendable },
+
+  // Select the CUDA runtime library.
+  { "CudaRuntime", "cudart=none", "No CUDA runtime library", "None", 0 },
+  { "CudaRuntime", "cudart=shared", "Shared/dynamic CUDA runtime library",
+    "Shared", 0 },
+  { "CudaRuntime", "cudart=static", "Static CUDA runtime library", "Static",
+    0 },
+  { "CudaRuntime", "cudart", "CUDA runtime library", "",
+    cmVS7FlagTable::UserFollowing },
+
+  // Capture arch/code arguments into temporaries for post-processing.
+  { "cmake-temp-gencode", "gencode=", "", "",
+    cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
+  { "cmake-temp-gencode", "gencode", "", "",
+    cmVS7FlagTable::UserFollowing | cmVS7FlagTable::SemicolonAppendable },
+  { "cmake-temp-gencode", "-generate-code=", "", "",
+    cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable },
+  { "cmake-temp-gencode", "-generate-code", "", "",
+    cmVS7FlagTable::UserFollowing | cmVS7FlagTable::SemicolonAppendable },
+
+  { "cmake-temp-code", "code=", "", "", cmVS7FlagTable::UserValue },
+  { "cmake-temp-code", "code", "", "", cmVS7FlagTable::UserFollowing },
+  { "cmake-temp-code", "-gpu-code=", "", "", cmVS7FlagTable::UserValue },
+  { "cmake-temp-code", "-gpu-code", "", "", cmVS7FlagTable::UserFollowing },
+
+  { "cmake-temp-arch", "arch=", "", "", cmVS7FlagTable::UserValue },
+  { "cmake-temp-arch", "arch", "", "", cmVS7FlagTable::UserFollowing },
+  { "cmake-temp-arch", "-gpu-architecture=", "", "",
+    cmVS7FlagTable::UserValue },
+  { "cmake-temp-arch", "-gpu-architecture", "", "",
+    cmVS7FlagTable::UserFollowing },
+
+  // Other flags.
+
+  { "FastMath", "use_fast_math", "", "true", 0 },
+  { "FastMath", "-use_fast_math", "", "true", 0 },
+
+  { "GPUDebugInfo", "G", "", "true", 0 },
+  { "GPUDebugInfo", "-device-debug", "", "true", 0 },
+
+  { "HostDebugInfo", "g", "", "true", 0 },
+  { "HostDebugInfo", "-debug", "", "true", 0 },
+
+  { 0, 0, 0, 0, 0 }
+};
diff --git a/Source/cmVS10CudaHostFlagTable.h b/Source/cmVS10CudaHostFlagTable.h
new file mode 100644
index 0000000000000000000000000000000000000000..5b61066caffe823bd34508b9a8ec82fc4851519e
--- /dev/null
+++ b/Source/cmVS10CudaHostFlagTable.h
@@ -0,0 +1,35 @@
+static cmVS7FlagTable cmVS10CudaHostFlagTable[] = {
+  //{"Optimization", "", "<inherit from host>", "InheritFromHost", 0},
+  { "Optimization", "Od", "Disabled", "Od", 0 },
+  { "Optimization", "O1", "Minimize Size", "O1", 0 },
+  { "Optimization", "O2", "Maximize Speed", "O2", 0 },
+  { "Optimization", "Ox", "Full Optimization", "O3", 0 },
+
+  //{"Runtime", "", "<inherit from host>", "InheritFromHost", 0},
+  { "Runtime", "MT", "Multi-Threaded", "MT", 0 },
+  { "Runtime", "MTd", "Multi-Threaded Debug", "MTd", 0 },
+  { "Runtime", "MD", "Multi-Threaded DLL", "MD", 0 },
+  { "Runtime", "MDd", "Multi-threaded Debug DLL", "MDd", 0 },
+  { "Runtime", "ML", "Single-Threaded", "ML", 0 },
+  { "Runtime", "MLd", "Single-Threaded Debug", "MLd", 0 },
+
+  //{"RuntimeChecks", "", "<inherit from host>", "InheritFromHost", 0},
+  //{"RuntimeChecks", "", "Default", "Default", 0},
+  { "RuntimeChecks", "RTCs", "Stack Frames", "RTCs", 0 },
+  { "RuntimeChecks", "RTCu", "Uninitialized Variables", "RTCu", 0 },
+  { "RuntimeChecks", "RTC1", "Both", "RTC1", 0 },
+
+  //{"TypeInfo", "", "<inherit from host>", "InheritFromHost", 0},
+  { "TypeInfo", "GR", "Yes", "true", 0 },
+  { "TypeInfo", "GR-", "No", "false", 0 },
+
+  //{"Warning", "", "<inherit from host>", "InheritFromHost", 0},
+  { "Warning", "W0", "Off: Turn Off All Warnings", "W0", 0 },
+  { "Warning", "W1", "Level 1", "W1", 0 },
+  { "Warning", "W2", "Level 2", "W2", 0 },
+  { "Warning", "W3", "Level 3", "W3", 0 },
+  { "Warning", "W4", "Level 4", "W4", 0 },
+  { "Warning", "Wall", "Enable All Warnings", "Wall", 0 },
+
+  { 0, 0, 0, 0, 0 }
+};
diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx
index 4aea6f8e651d0dd48a0dc9fdeda579b188fcd1d1..052cc7fcbc6c55bb3b5c14441f8c0a009da4ebc5 100644
--- a/Source/cmVisualStudio10TargetGenerator.cxx
+++ b/Source/cmVisualStudio10TargetGenerator.cxx
@@ -112,6 +112,10 @@ cmVisualStudio10TargetGenerator::~cmVisualStudio10TargetGenerator()
        i != this->LinkOptions.end(); ++i) {
     delete i->second;
   }
+  for (OptionsMap::iterator i = this->CudaOptions.begin();
+       i != this->CudaOptions.end(); ++i) {
+    delete i->second;
+  }
   if (!this->BuildFileStream) {
     return;
   }
@@ -206,6 +210,9 @@ void cmVisualStudio10TargetGenerator::Generate()
     if (!this->ComputeRcOptions()) {
       return;
     }
+    if (!this->ComputeCudaOptions()) {
+      return;
+    }
     if (!this->ComputeMasmOptions()) {
       return;
     }
@@ -454,6 +461,14 @@ void cmVisualStudio10TargetGenerator::Generate()
     this->WriteString("<Import Project=\"" VS10_CXX_PROPS "\" />\n", 1);
   }
   this->WriteString("<ImportGroup Label=\"ExtensionSettings\">\n", 1);
+  if (this->GlobalGenerator->IsCudaEnabled()) {
+    this->WriteString("<Import Project=\"$(VCTargetsPath)\\"
+                      "BuildCustomizations\\CUDA ",
+                      2);
+    (*this->BuildFileStream)
+      << cmVS10EscapeXML(this->GlobalGenerator->GetPlatformToolsetCudaString())
+      << ".props\" />\n";
+  }
   if (this->GlobalGenerator->IsMasmEnabled()) {
     this->WriteString("<Import Project=\"$(VCTargetsPath)\\"
                       "BuildCustomizations\\masm.props\" />\n",
@@ -524,6 +539,14 @@ void cmVisualStudio10TargetGenerator::Generate()
   this->WriteTargetSpecificReferences();
   this->WriteString("<ImportGroup Label=\"ExtensionTargets\">\n", 1);
   this->WriteTargetsFileReferences();
+  if (this->GlobalGenerator->IsCudaEnabled()) {
+    this->WriteString("<Import Project=\"$(VCTargetsPath)\\"
+                      "BuildCustomizations\\CUDA ",
+                      2);
+    (*this->BuildFileStream)
+      << cmVS10EscapeXML(this->GlobalGenerator->GetPlatformToolsetCudaString())
+      << ".targets\" />\n";
+  }
   if (this->GlobalGenerator->IsMasmEnabled()) {
     this->WriteString("<Import Project=\"$(VCTargetsPath)\\"
                       "BuildCustomizations\\masm.targets\" />\n",
@@ -1694,8 +1717,10 @@ void cmVisualStudio10TargetGenerator::WriteSource(std::string const& tool,
   //
   // and fail if this exceeds the maximum allowed path length.  Our path
   // conversion uses full paths when possible to allow deeper trees.
-  bool forceRelative = false;
-  std::string sourceFile = this->ConvertPath(sf->GetFullPath(), false);
+  // However, CUDA 8.0 msbuild rules fail on absolute paths so for CUDA
+  // we must use relative paths.
+  bool forceRelative = sf->GetLanguage() == "CUDA";
+  std::string sourceFile = this->ConvertPath(sf->GetFullPath(), forceRelative);
   if (this->LocalGenerator->GetVersion() ==
         cmGlobalVisualStudioGenerator::VS10 &&
       cmSystemTools::FileIsFullPath(sourceFile.c_str())) {
@@ -1772,6 +1797,8 @@ void cmVisualStudio10TargetGenerator::WriteAllSources()
       tool = "ResourceCompile";
     } else if (lang == "CSharp") {
       tool = "Compile";
+    } else if (lang == "CUDA" && this->GlobalGenerator->IsCudaEnabled()) {
+      tool = "CudaCompile";
     }
 
     if (!tool.empty()) {
@@ -2207,8 +2234,10 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions(
   if (linkLanguage == "CXX") {
     clOptions.AddFlag("CompileAs", "CompileAsCpp");
   }
-  this->LocalGenerator->AddCompileOptions(flags, this->GeneratorTarget,
-                                          linkLanguage, configName.c_str());
+  if (linkLanguage != "CUDA") {
+    this->LocalGenerator->AddCompileOptions(flags, this->GeneratorTarget,
+                                            linkLanguage, configName.c_str());
+  }
 
   // Get preprocessor definitions for this directory.
   std::string defineFlags =
@@ -2400,6 +2429,99 @@ void cmVisualStudio10TargetGenerator::WriteRCOptions(
   this->WriteString("</ResourceCompile>\n", 2);
 }
 
+bool cmVisualStudio10TargetGenerator::ComputeCudaOptions()
+{
+  if (!this->GlobalGenerator->IsCudaEnabled()) {
+    return true;
+  }
+  for (std::vector<std::string>::const_iterator i =
+         this->Configurations.begin();
+       i != this->Configurations.end(); ++i) {
+    if (!this->ComputeCudaOptions(*i)) {
+      return false;
+    }
+  }
+  return true;
+}
+
+bool cmVisualStudio10TargetGenerator::ComputeCudaOptions(
+  std::string const& configName)
+{
+  cmGlobalVisualStudio10Generator* gg =
+    static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator);
+  CM_AUTO_PTR<Options> pOptions(new Options(
+    this->LocalGenerator, Options::CudaCompiler, gg->GetCudaFlagTable()));
+  Options& cudaOptions = *pOptions;
+
+  // Get compile flags for CUDA in this directory.
+  std::string CONFIG = cmSystemTools::UpperCase(configName);
+  std::string configFlagsVar = std::string("CMAKE_CUDA_FLAGS_") + CONFIG;
+  std::string flags =
+    std::string(this->Makefile->GetSafeDefinition("CMAKE_CUDA_FLAGS")) +
+    std::string(" ") +
+    std::string(this->Makefile->GetSafeDefinition(configFlagsVar));
+
+  // Get preprocessor definitions for this directory.
+  std::string defineFlags =
+    this->GeneratorTarget->Target->GetMakefile()->GetDefineFlags();
+
+  cudaOptions.Parse(flags.c_str());
+  cudaOptions.Parse(defineFlags.c_str());
+  cudaOptions.ParseFinish();
+
+  if (this->GeneratorTarget->GetPropertyAsBool("CUDA_SEPARABLE_COMPILATION")) {
+    cudaOptions.AddFlag("GenerateRelocatableDeviceCode", "true");
+  }
+
+  // Convert the host compiler options to the toolset's abstractions
+  // using a secondary flag table.
+  cudaOptions.ClearTables();
+  cudaOptions.AddTable(gg->GetCudaHostFlagTable());
+  cudaOptions.Reparse("AdditionalCompilerOptions");
+
+  // `CUDA 8.0.targets` places these before nvcc!  Just drop whatever
+  // did not parse and hope it works.
+  cudaOptions.RemoveFlag("AdditionalCompilerOptions");
+
+  cudaOptions.FixCudaCodeGeneration();
+
+  std::vector<std::string> targetDefines;
+  this->GeneratorTarget->GetCompileDefinitions(targetDefines,
+                                               configName.c_str(), "CUDA");
+  cudaOptions.AddDefines(targetDefines);
+
+  // Add a definition for the configuration name.
+  std::string configDefine = "CMAKE_INTDIR=\"";
+  configDefine += configName;
+  configDefine += "\"";
+  cudaOptions.AddDefine(configDefine);
+  if (const char* exportMacro = this->GeneratorTarget->GetExportMacro()) {
+    cudaOptions.AddDefine(exportMacro);
+  }
+
+  this->CudaOptions[configName] = pOptions.release();
+  return true;
+}
+
+void cmVisualStudio10TargetGenerator::WriteCudaOptions(
+  std::string const& configName, std::vector<std::string> const& includes)
+{
+  if (!this->MSTools || !this->GlobalGenerator->IsCudaEnabled()) {
+    return;
+  }
+  this->WriteString("<CudaCompile>\n", 2);
+
+  Options& cudaOptions = *(this->CudaOptions[configName]);
+  cudaOptions.AppendFlag("Include", includes);
+  cudaOptions.AppendFlag("Include", "%(Include)");
+  cudaOptions.OutputPreprocessorDefinitions(*this->BuildFileStream, "      ",
+                                            "\n", "CUDA");
+  cudaOptions.PrependInheritedString("AdditionalOptions");
+  cudaOptions.OutputFlagMap(*this->BuildFileStream, "      ");
+
+  this->WriteString("</CudaCompile>\n", 2);
+}
+
 bool cmVisualStudio10TargetGenerator::ComputeMasmOptions()
 {
   if (!this->GlobalGenerator->IsMasmEnabled()) {
@@ -2738,8 +2860,10 @@ bool cmVisualStudio10TargetGenerator::ComputeLinkOptions(
     this->LocalGenerator, Options::Linker, gg->GetLinkFlagTable(), 0, this));
   Options& linkOptions = *pOptions;
 
-  const std::string& linkLanguage =
-    this->GeneratorTarget->GetLinkerLanguage(config.c_str());
+  cmGeneratorTarget::LinkClosure const* linkClosure =
+    this->GeneratorTarget->GetLinkClosure(config);
+
+  const std::string& linkLanguage = linkClosure->LinkerLanguage;
   if (linkLanguage.empty()) {
     cmSystemTools::Error(
       "CMake can not determine linker language for target: ",
@@ -2794,6 +2918,19 @@ bool cmVisualStudio10TargetGenerator::ComputeLinkOptions(
   std::vector<std::string> libVec;
   std::vector<std::string> vsTargetVec;
   this->AddLibraries(cli, libVec, vsTargetVec);
+  if (std::find(linkClosure->Languages.begin(), linkClosure->Languages.end(),
+                "CUDA") != linkClosure->Languages.end()) {
+    switch (this->CudaOptions[config]->GetCudaRuntime()) {
+      case cmVisualStudioGeneratorOptions::CudaRuntimeStatic:
+        libVec.push_back("cudart_static.lib");
+        break;
+      case cmVisualStudioGeneratorOptions::CudaRuntimeShared:
+        libVec.push_back("cudart.lib");
+        break;
+      case cmVisualStudioGeneratorOptions::CudaRuntimeNone:
+        break;
+    }
+  }
   std::string standardLibsVar = "CMAKE_";
   standardLibsVar += linkLanguage;
   standardLibsVar += "_STANDARD_LIBRARIES";
@@ -3132,6 +3269,7 @@ void cmVisualStudio10TargetGenerator::WriteItemDefinitionGroups()
       this->WriteClOptions(*i, includes);
       //    output rc compile flags <ResourceCompile></ResourceCompile>
       this->WriteRCOptions(*i, includes);
+      this->WriteCudaOptions(*i, includes);
       this->WriteMasmOptions(*i, includes);
       this->WriteNasmOptions(*i, includes);
     }
diff --git a/Source/cmVisualStudio10TargetGenerator.h b/Source/cmVisualStudio10TargetGenerator.h
index 0ebb4e494c2d2e8f37fe55949e4254840805596a..52d55501dcc1dcaa94574b31f9dac28c5eab3a18 100644
--- a/Source/cmVisualStudio10TargetGenerator.h
+++ b/Source/cmVisualStudio10TargetGenerator.h
@@ -98,6 +98,10 @@ private:
   bool ComputeRcOptions(std::string const& config);
   void WriteRCOptions(std::string const& config,
                       std::vector<std::string> const& includes);
+  bool ComputeCudaOptions();
+  bool ComputeCudaOptions(std::string const& config);
+  void WriteCudaOptions(std::string const& config,
+                        std::vector<std::string> const& includes);
   bool ComputeMasmOptions();
   bool ComputeMasmOptions(std::string const& config);
   void WriteMasmOptions(std::string const& config,
@@ -150,6 +154,7 @@ private:
   typedef std::map<std::string, Options*> OptionsMap;
   OptionsMap ClOptions;
   OptionsMap RcOptions;
+  OptionsMap CudaOptions;
   OptionsMap MasmOptions;
   OptionsMap NasmOptions;
   OptionsMap LinkOptions;
diff --git a/Source/cmVisualStudioGeneratorOptions.cxx b/Source/cmVisualStudioGeneratorOptions.cxx
index dfe5ce6f8eebd0e141441d1bb8f6c5976411c94d..1ca6b9cd108bde42bf091339389d628847a8e561 100644
--- a/Source/cmVisualStudioGeneratorOptions.cxx
+++ b/Source/cmVisualStudioGeneratorOptions.cxx
@@ -43,6 +43,8 @@ cmVisualStudioGeneratorOptions::cmVisualStudioGeneratorOptions(
   this->FortranRuntimeDebug = false;
   this->FortranRuntimeDLL = false;
   this->FortranRuntimeMT = false;
+
+  this->UnknownFlagField = "AdditionalOptions";
 }
 
 cmVisualStudioGeneratorOptions::cmVisualStudioGeneratorOptions(
@@ -67,6 +69,8 @@ cmVisualStudioGeneratorOptions::cmVisualStudioGeneratorOptions(
   this->FortranRuntimeDebug = false;
   this->FortranRuntimeDLL = false;
   this->FortranRuntimeMT = false;
+
+  this->UnknownFlagField = "AdditionalOptions";
 }
 
 void cmVisualStudioGeneratorOptions::AddTable(cmVS7FlagTable const* table)
@@ -81,6 +85,13 @@ void cmVisualStudioGeneratorOptions::AddTable(cmVS7FlagTable const* table)
   }
 }
 
+void cmVisualStudioGeneratorOptions::ClearTables()
+{
+  for (int i = 0; i < FlagTableCount; ++i) {
+    this->FlagTable[i] = CM_NULLPTR;
+  }
+}
+
 void cmVisualStudioGeneratorOptions::FixExceptionHandlingDefault()
 {
   // Exception handling is on by default because the platform file has
@@ -176,6 +187,78 @@ bool cmVisualStudioGeneratorOptions::UsingSBCS() const
   return false;
 }
 
+cmVisualStudioGeneratorOptions::CudaRuntime
+cmVisualStudioGeneratorOptions::GetCudaRuntime() const
+{
+  std::map<std::string, FlagValue>::const_iterator i =
+    this->FlagMap.find("CudaRuntime");
+  if (i != this->FlagMap.end() && i->second.size() == 1) {
+    std::string const& cudaRuntime = i->second[0];
+    if (cudaRuntime == "Static") {
+      return CudaRuntimeStatic;
+    }
+    if (cudaRuntime == "Shared") {
+      return CudaRuntimeShared;
+    }
+    if (cudaRuntime == "None") {
+      return CudaRuntimeNone;
+    }
+  }
+  // nvcc default is static
+  return CudaRuntimeStatic;
+}
+
+void cmVisualStudioGeneratorOptions::FixCudaCodeGeneration()
+{
+  // Extract temporary values stored by our flag table.
+  FlagValue arch = this->TakeFlag("cmake-temp-arch");
+  FlagValue code = this->TakeFlag("cmake-temp-code");
+  FlagValue gencode = this->TakeFlag("cmake-temp-gencode");
+
+  // No -code allowed without -arch.
+  if (arch.empty()) {
+    code.clear();
+  }
+
+  if (arch.empty() && gencode.empty()) {
+    return;
+  }
+
+  // Create a CodeGeneration field with [arch],[code] syntax in each entry.
+  // CUDA will convert it to `-gencode=arch=[arch],code="[code],[arch]"`.
+  FlagValue& result = this->FlagMap["CodeGeneration"];
+
+  // First entries for the -arch=<arch> [-code=<code>,...] pair.
+  if (!arch.empty()) {
+    std::string arch_name = arch[0];
+    std::vector<std::string> codes;
+    if (!code.empty()) {
+      codes = cmSystemTools::tokenize(code[0], ",");
+    }
+    if (codes.empty()) {
+      codes.push_back(arch_name);
+      // nvcc -arch=<arch> has a special case that allows a real
+      // architecture to be specified instead of a virtual arch.
+      // It translates to -arch=<virtual> -code=<real>.
+      cmSystemTools::ReplaceString(arch_name, "sm_", "compute_");
+    }
+    for (std::vector<std::string>::iterator ci = codes.begin();
+         ci != codes.end(); ++ci) {
+      std::string entry = arch_name + "," + *ci;
+      result.push_back(entry);
+    }
+  }
+
+  // Now add entries for the -gencode=<arch>,<code> pairs.
+  for (std::vector<std::string>::iterator ei = gencode.begin();
+       ei != gencode.end(); ++ei) {
+    std::string entry = *ei;
+    cmSystemTools::ReplaceString(entry, "arch=", "");
+    cmSystemTools::ReplaceString(entry, "code=", "");
+    result.push_back(entry);
+  }
+}
+
 void cmVisualStudioGeneratorOptions::Parse(const char* flags)
 {
   // Parse the input string as a windows command line since the string
@@ -209,6 +292,21 @@ void cmVisualStudioGeneratorOptions::ParseFinish()
     rl += this->FortranRuntimeDLL ? "DLL" : "";
     this->FlagMap["RuntimeLibrary"] = rl;
   }
+
+  if (this->CurrentTool == CudaCompiler) {
+    std::map<std::string, FlagValue>::iterator i =
+      this->FlagMap.find("CudaRuntime");
+    if (i != this->FlagMap.end() && i->second.size() == 1) {
+      std::string& cudaRuntime = i->second[0];
+      if (cudaRuntime == "static") {
+        cudaRuntime = "Static";
+      } else if (cudaRuntime == "shared") {
+        cudaRuntime = "Shared";
+      } else if (cudaRuntime == "none") {
+        cudaRuntime = "None";
+      }
+    }
+  }
 }
 
 void cmVisualStudioGeneratorOptions::PrependInheritedString(
@@ -222,6 +320,18 @@ void cmVisualStudioGeneratorOptions::PrependInheritedString(
   value = "%(" + key + ") " + value;
 }
 
+void cmVisualStudioGeneratorOptions::Reparse(std::string const& key)
+{
+  std::map<std::string, FlagValue>::iterator i = this->FlagMap.find(key);
+  if (i == this->FlagMap.end() || i->second.size() != 1) {
+    return;
+  }
+  std::string const original = i->second[0];
+  i->second[0] = "";
+  this->UnknownFlagField = key;
+  this->Parse(original.c_str());
+}
+
 void cmVisualStudioGeneratorOptions::StoreUnknownFlag(const char* flag)
 {
   // Look for Intel Fortran flags that do not map well in the flag table.
@@ -248,7 +358,19 @@ void cmVisualStudioGeneratorOptions::StoreUnknownFlag(const char* flag)
   std::string const opts = cmOutputConverter::EscapeWindowsShellArgument(
     flag, cmOutputConverter::Shell_Flag_AllowMakeVariables |
       cmOutputConverter::Shell_Flag_VSIDE);
-  this->AppendFlagString("AdditionalOptions", opts);
+  this->AppendFlagString(this->UnknownFlagField, opts);
+}
+
+cmIDEOptions::FlagValue cmVisualStudioGeneratorOptions::TakeFlag(
+  std::string const& key)
+{
+  FlagValue value;
+  std::map<std::string, FlagValue>::iterator i = this->FlagMap.find(key);
+  if (i != this->FlagMap.end()) {
+    value = i->second;
+    this->FlagMap.erase(i);
+  }
+  return value;
 }
 
 void cmVisualStudioGeneratorOptions::SetConfiguration(const char* config)
@@ -264,6 +386,9 @@ void cmVisualStudioGeneratorOptions::OutputPreprocessorDefinitions(
     return;
   }
   const char* tag = "PreprocessorDefinitions";
+  if (lang == "CUDA") {
+    tag = "Defines";
+  }
   if (this->Version >= cmGlobalVisualStudioGenerator::VS10) {
     // if there are configuration specific flags, then
     // use the configuration specific tag for PreprocessorDefinitions
diff --git a/Source/cmVisualStudioGeneratorOptions.h b/Source/cmVisualStudioGeneratorOptions.h
index 8c49470067f2e170e857eced9f275ac826b759cf..52689e0a5515d679a2fd0b91feaa0c58a39da129 100644
--- a/Source/cmVisualStudioGeneratorOptions.h
+++ b/Source/cmVisualStudioGeneratorOptions.h
@@ -26,6 +26,7 @@ public:
   {
     Compiler,
     ResourceCompiler,
+    CudaCompiler,
     MasmCompiler,
     NasmCompiler,
     Linker,
@@ -43,12 +44,19 @@ public:
   // Add a table of flags.
   void AddTable(cmVS7FlagTable const* table);
 
+  // Clear the flag tables.
+  void ClearTables();
+
   // Store options from command line flags.
   void Parse(const char* flags);
   void ParseFinish();
 
   void PrependInheritedString(std::string const& key);
 
+  // Parse the content of the given flag table entry again to extract
+  // known flags and leave the rest in the original entry.
+  void Reparse(std::string const& key);
+
   // Fix the ExceptionHandling option to default to off.
   void FixExceptionHandlingDefault();
 
@@ -59,6 +67,16 @@ public:
   bool UsingUnicode() const;
   bool UsingSBCS() const;
 
+  enum CudaRuntime
+  {
+    CudaRuntimeStatic,
+    CudaRuntimeShared,
+    CudaRuntimeNone
+  };
+  CudaRuntime GetCudaRuntime() const;
+
+  void FixCudaCodeGeneration();
+
   bool IsDebug() const;
   bool IsWinRt() const;
   bool IsManaged() const;
@@ -81,7 +99,11 @@ private:
   bool FortranRuntimeDLL;
   bool FortranRuntimeMT;
 
+  std::string UnknownFlagField;
+
   virtual void StoreUnknownFlag(const char* flag);
+
+  FlagValue TakeFlag(std::string const& key);
 };
 
 #endif
diff --git a/Tests/CudaOnly/WithDefs/CMakeLists.txt b/Tests/CudaOnly/WithDefs/CMakeLists.txt
index 2646d29a3f63802756cf4840b4b0c502d70f3bce..38f2a44a3464de6ec4c03a7912e975e9b7570a8c 100644
--- a/Tests/CudaOnly/WithDefs/CMakeLists.txt
+++ b/Tests/CudaOnly/WithDefs/CMakeLists.txt
@@ -16,8 +16,15 @@ set(release_compile_defs DEFREL)
 #build a executable that needs to be passed a complex define through add_defintions
 #this verifies we can pass things such as '_','(' to nvcc
 add_definitions("-DPACKED_DEFINE=__attribute__((packed))")
-set_source_files_properties(main.notcu PROPERTIES LANGUAGE CUDA)
-add_executable(CudaOnlyWithDefs main.notcu)
+
+if(CMAKE_GENERATOR MATCHES "Visual Studio")
+  # CUDA MSBuild rules do not pass '-x cu' to nvcc
+  set(main main_for_vs.cu)
+else()
+  set(main main.notcu)
+  set_source_files_properties(main.notcu PROPERTIES LANGUAGE CUDA)
+endif()
+add_executable(CudaOnlyWithDefs ${main})
 
 target_compile_options(CudaOnlyWithDefs
   PRIVATE
diff --git a/Tests/CudaOnly/WithDefs/main_for_vs.cu b/Tests/CudaOnly/WithDefs/main_for_vs.cu
new file mode 100644
index 0000000000000000000000000000000000000000..56078e7af2a91d634a26d5d003340ba19ea1c639
--- /dev/null
+++ b/Tests/CudaOnly/WithDefs/main_for_vs.cu
@@ -0,0 +1 @@
+#include "main.notcu"
diff --git a/Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake b/Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake
index 44c67a268975082e78c8029291273f7eae0f3284..f6449f205b0428d50152b63c9f41d242504f5b31 100644
--- a/Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake
+++ b/Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake
@@ -6,6 +6,12 @@ run_cmake(NoToolset)
 if("${RunCMake_GENERATOR}" MATCHES "Visual Studio 1[01245]")
   set(RunCMake_GENERATOR_TOOLSET "Test Toolset")
   run_cmake(TestToolset)
+  set(RunCMake_GENERATOR_TOOLSET "Test Toolset,cuda=Test Cuda")
+  run_cmake(TestToolsetCudaBoth)
+  set(RunCMake_GENERATOR_TOOLSET ",cuda=Test Cuda")
+  run_cmake(TestToolsetCudaOnly)
+  set(RunCMake_GENERATOR_TOOLSET "cuda=Test Cuda")
+  run_cmake(TestToolsetCudaOnly)
   if("${RunCMake_GENERATOR}" MATCHES "Visual Studio 1[245]")
     set(RunCMake_GENERATOR_TOOLSET "Test Toolset,host=x64")
     run_cmake(TestToolsetHostArchBoth)
diff --git a/Tests/RunCMake/GeneratorToolset/TestToolsetCudaBoth-stdout.txt b/Tests/RunCMake/GeneratorToolset/TestToolsetCudaBoth-stdout.txt
new file mode 100644
index 0000000000000000000000000000000000000000..90503e2ccd792ccf53e778014fd01e8ef2c913df
--- /dev/null
+++ b/Tests/RunCMake/GeneratorToolset/TestToolsetCudaBoth-stdout.txt
@@ -0,0 +1,2 @@
+-- CMAKE_VS_PLATFORM_TOOLSET='Test Toolset'
+-- CMAKE_VS_PLATFORM_TOOLSET_CUDA='Test Cuda'
diff --git a/Tests/RunCMake/GeneratorToolset/TestToolsetCudaBoth.cmake b/Tests/RunCMake/GeneratorToolset/TestToolsetCudaBoth.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..befa0af9d6c2290a226f5a5bc31d5523dff222e1
--- /dev/null
+++ b/Tests/RunCMake/GeneratorToolset/TestToolsetCudaBoth.cmake
@@ -0,0 +1,2 @@
+message(STATUS "CMAKE_VS_PLATFORM_TOOLSET='${CMAKE_VS_PLATFORM_TOOLSET}'")
+message(STATUS "CMAKE_VS_PLATFORM_TOOLSET_CUDA='${CMAKE_VS_PLATFORM_TOOLSET_CUDA}'")
diff --git a/Tests/RunCMake/GeneratorToolset/TestToolsetCudaOnly-stdout.txt b/Tests/RunCMake/GeneratorToolset/TestToolsetCudaOnly-stdout.txt
new file mode 100644
index 0000000000000000000000000000000000000000..94e1e43e4339925f5ef9e3d58b94380986b2f2e6
--- /dev/null
+++ b/Tests/RunCMake/GeneratorToolset/TestToolsetCudaOnly-stdout.txt
@@ -0,0 +1,2 @@
+-- CMAKE_VS_PLATFORM_TOOLSET='(v[0-9]+|Windows7.1SDK)'
+-- CMAKE_VS_PLATFORM_TOOLSET_CUDA='Test Cuda'
diff --git a/Tests/RunCMake/GeneratorToolset/TestToolsetCudaOnly.cmake b/Tests/RunCMake/GeneratorToolset/TestToolsetCudaOnly.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..befa0af9d6c2290a226f5a5bc31d5523dff222e1
--- /dev/null
+++ b/Tests/RunCMake/GeneratorToolset/TestToolsetCudaOnly.cmake
@@ -0,0 +1,2 @@
+message(STATUS "CMAKE_VS_PLATFORM_TOOLSET='${CMAKE_VS_PLATFORM_TOOLSET}'")
+message(STATUS "CMAKE_VS_PLATFORM_TOOLSET_CUDA='${CMAKE_VS_PLATFORM_TOOLSET_CUDA}'")