From f2059585e6302446707560b123c7b785df5f5859 Mon Sep 17 00:00:00 2001
From: Brad King <brad.king@kitware.com>
Date: Wed, 21 Jun 2017 13:44:43 -0400
Subject: VS: Fix target_compile_options for CUDA

Fix the VS generator to honor `COMPILE_OPTIONS` for CUDA.  The exclusion
added by commit v3.9.0-rc1~431^2~7 (VS: Do not pass CUDA compile options
to C compiler, 2017-03-07) was correct but we need additional logic to
pass the CUDA compile options to the CUDA compiler.  Also we should
still pass the CXX or C options to MSVC (ClCompile) when those languages
are enabled even if the link language is CUDA.
---
 Source/cmVisualStudio10TargetGenerator.cxx | 32 +++++++++++++++++++++++-------
 Tests/CudaOnly/WithDefs/CMakeLists.txt     |  1 +
 Tests/CudaOnly/WithDefs/main.notcu         |  4 ++++
 3 files changed, 30 insertions(+), 7 deletions(-)

diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx
index 238c9e8..2a7d96b 100644
--- a/Source/cmVisualStudio10TargetGenerator.cxx
+++ b/Source/cmVisualStudio10TargetGenerator.cxx
@@ -2,6 +2,7 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmVisualStudio10TargetGenerator.h"
 
+#include "cmAlgorithms.h"
 #include "cmComputeLinkInformation.h"
 #include "cmCustomCommandGenerator.h"
 #include "cmGeneratedFileStream.h"
@@ -2227,10 +2228,27 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions(
       this->Name.c_str());
     return false;
   }
-  if (linkLanguage == "C" || linkLanguage == "CXX" ||
-      linkLanguage == "Fortran" || linkLanguage == "CSharp") {
+
+  // Choose a language whose flags to use for ClCompile.
+  static const char* clLangs[] = { "CXX", "C", "Fortran", "CSharp" };
+  std::string langForClCompile;
+  if (std::find(cmArrayBegin(clLangs), cmArrayEnd(clLangs), linkLanguage) !=
+      cmArrayEnd(clLangs)) {
+    langForClCompile = linkLanguage;
+  } else {
+    std::set<std::string> languages;
+    this->GeneratorTarget->GetLanguages(languages, configName);
+    for (const char* const* l = cmArrayBegin(clLangs);
+         l != cmArrayEnd(clLangs); ++l) {
+      if (languages.find(*l) != languages.end()) {
+        langForClCompile = *l;
+        break;
+      }
+    }
+  }
+  if (!langForClCompile.empty()) {
     std::string baseFlagVar = "CMAKE_";
-    baseFlagVar += linkLanguage;
+    baseFlagVar += langForClCompile;
     baseFlagVar += "_FLAGS";
     flags =
       this->GeneratorTarget->Target->GetMakefile()->GetRequiredDefinition(
@@ -2241,6 +2259,8 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions(
     flags +=
       this->GeneratorTarget->Target->GetMakefile()->GetRequiredDefinition(
         flagVar.c_str());
+    this->LocalGenerator->AddCompileOptions(flags, this->GeneratorTarget,
+                                            langForClCompile, configName);
   }
   // set the correct language
   if (linkLanguage == "C") {
@@ -2249,10 +2269,6 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions(
   if (linkLanguage == "CXX") {
     clOptions.AddFlag("CompileAs", "CompileAsCpp");
   }
-  if (linkLanguage != "CUDA") {
-    this->LocalGenerator->AddCompileOptions(flags, this->GeneratorTarget,
-                                            linkLanguage, configName.c_str());
-  }
 
   // Check IPO related warning/error.
   this->GeneratorTarget->IsIPOEnabled(linkLanguage, configName);
@@ -2480,6 +2496,8 @@ bool cmVisualStudio10TargetGenerator::ComputeCudaOptions(
     std::string(this->Makefile->GetSafeDefinition("CMAKE_CUDA_FLAGS")) +
     std::string(" ") +
     std::string(this->Makefile->GetSafeDefinition(configFlagsVar));
+  this->LocalGenerator->AddCompileOptions(flags, this->GeneratorTarget, "CUDA",
+                                          configName);
 
   // Get preprocessor definitions for this directory.
   std::string defineFlags =
diff --git a/Tests/CudaOnly/WithDefs/CMakeLists.txt b/Tests/CudaOnly/WithDefs/CMakeLists.txt
index 38f2a44..e25f141 100644
--- a/Tests/CudaOnly/WithDefs/CMakeLists.txt
+++ b/Tests/CudaOnly/WithDefs/CMakeLists.txt
@@ -28,6 +28,7 @@ add_executable(CudaOnlyWithDefs ${main})
 
 target_compile_options(CudaOnlyWithDefs
   PRIVATE
+    -Xcompiler=-DHOST_DEFINE
     $<$<CONFIG:DEBUG>:$<BUILD_INTERFACE:${debug_compile_flags}>>
   )
 
diff --git a/Tests/CudaOnly/WithDefs/main.notcu b/Tests/CudaOnly/WithDefs/main.notcu
index 80ed3a5..d2eff3f 100644
--- a/Tests/CudaOnly/WithDefs/main.notcu
+++ b/Tests/CudaOnly/WithDefs/main.notcu
@@ -2,6 +2,10 @@
 #include <cuda_runtime.h>
 #include <iostream>
 
+#ifndef HOST_DEFINE
+#error "HOST_DEFINE not defined!"
+#endif
+
 #ifndef PACKED_DEFINE
 #error "PACKED_DEFINE not defined!"
 #endif
-- 
cgit v0.12