Procházet zdrojové kódy

VS: added support for C# (for Visual Studio 2010, 2012, 2013, 2015)

Michael Stürmer před 9 roky
rodič
revize
a7dd8e6692

+ 0 - 4
Modules/CMakeTestCSharpCompiler.cmake

@@ -34,10 +34,6 @@ if(NOT CMAKE_CSharp_COMPILER_WORKS)
   # Move result from cache to normal variable.
   set(CMAKE_CSharp_COMPILER_WORKS ${CMAKE_CSharp_COMPILER_WORKS})
   unset(CMAKE_CSharp_COMPILER_WORKS CACHE)
-  if(NOT CMAKE_CSharp_COMPILER_WORKS)
-    message("forcing compiler works to true (will be removed once C# support is integrated)")
-    set(CMAKE_CSharp_COMPILER_WORKS 1)
-  endif()
   set(CSharp_TEST_WAS_RUN 1)
 endif()
 

+ 362 - 69
Source/cmVisualStudio10TargetGenerator.cxx

@@ -130,9 +130,18 @@ void cmVisualStudio10TargetGenerator::WritePlatformConfigTag(
   }
   stream->fill(' ');
   stream->width(indentLevel * 2);
-  (*stream) << "";
-  (*stream) << "<" << tag << " Condition=\"'$(Configuration)|$(Platform)'=='";
-  (*stream) << config << "|" << this->Platform << "'\"";
+  (*stream) << "<" << tag << " Condition=\"";
+  (*stream) << "'$(Configuration)|$(Platform)'=='";
+  (*stream) << config << "|" << this->Platform;
+  (*stream) << "'";
+  // handle special case for 32 bit C# targets
+  if (csproj == this->ProjectType && this->Platform == "Win32") {
+    (*stream) << " Or ";
+    (*stream) << "'$(Configuration)|$(Platform)'=='";
+    (*stream) << config << "|x86";
+    (*stream) << "'";
+  }
+  (*stream) << "\"";
   if (attribute) {
     (*stream) << attribute;
   }
@@ -159,6 +168,14 @@ void cmVisualStudio10TargetGenerator::WriteString(const char* line,
   "$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props"
 #define VS10_CXX_TARGETS "$(VCTargetsPath)\\Microsoft.Cpp.targets"
 
+#define VS10_CSharp_DEFAULT_PROPS                                             \
+  "$(MSBuildExtensionsPath)\\$(MSBuildToolsVersion)\\Microsoft.Common.props"
+// This does not seem to exist by default, it's just provided for consistency
+// in case users want to have default custom props for C# targets
+#define VS10_CSharp_USER_PROPS                                                \
+  "$(UserRootDir)\\Microsoft.CSharp.$(Platform).user.props"
+#define VS10_CSharp_TARGETS "$(MSBuildToolsPath)\\Microsoft.CSharp.targets"
+
 void cmVisualStudio10TargetGenerator::Generate()
 {
   // do not generate external ms projects
@@ -257,7 +274,9 @@ void cmVisualStudio10TargetGenerator::Generate()
     this->WriteString("</PropertyGroup>\n", 1);
   }
 
-  this->WriteProjectConfigurations();
+  if (csproj != this->ProjectType) {
+    this->WriteProjectConfigurations();
+  }
   this->WriteString("<PropertyGroup Label=\"Globals\">\n", 1);
   this->WriteString("<ProjectGUID>", 2);
   (*this->BuildFileStream) << "{" << this->GUID << "}</ProjectGUID>\n";
@@ -271,9 +290,14 @@ void cmVisualStudio10TargetGenerator::Generate()
   const char* vsProjectTypes =
     this->GeneratorTarget->GetProperty("VS_GLOBAL_PROJECT_TYPES");
   if (vsProjectTypes) {
-    this->WriteString("<ProjectTypes>", 2);
-    (*this->BuildFileStream) << cmVS10EscapeXML(vsProjectTypes)
-                             << "</ProjectTypes>\n";
+    std::string tagName = "ProjectTypes";
+    if (csproj == this->ProjectType) {
+      tagName = "ProjectTypeGuids";
+    }
+    this->WriteString("", 2);
+    (*this->BuildFileStream) << "<" << tagName << ">"
+                             << cmVS10EscapeXML(vsProjectTypes) << "</"
+                             << tagName << ">\n";
   }
 
   const char* vsProjectName =
@@ -371,10 +395,59 @@ void cmVisualStudio10TargetGenerator::Generate()
                              << "</" << globalKey << ">\n";
   }
 
+  if (this->Managed) {
+    std::string outputType = "<OutputType>";
+    switch (this->GeneratorTarget->GetType()) {
+      case cmStateEnums::OBJECT_LIBRARY:
+      case cmStateEnums::STATIC_LIBRARY:
+      case cmStateEnums::SHARED_LIBRARY:
+        outputType += "Library";
+        break;
+      case cmStateEnums::MODULE_LIBRARY:
+        outputType += "Module";
+        break;
+      case cmStateEnums::EXECUTABLE:
+        if (this->GeneratorTarget->Target->GetPropertyAsBool(
+              "WIN32_EXECUTABLE")) {
+          outputType += "WinExe";
+        } else {
+          outputType += "Exe";
+        }
+        break;
+      case cmStateEnums::UTILITY:
+      case cmStateEnums::GLOBAL_TARGET:
+        outputType += "Utility";
+        break;
+      case cmStateEnums::UNKNOWN_LIBRARY:
+      case cmStateEnums::INTERFACE_LIBRARY:
+        break;
+    }
+    outputType += "</OutputType>\n";
+    this->WriteString(outputType.c_str(), 2);
+    this->WriteString("<AppDesignerFolder>Properties</AppDesignerFolder>\n",
+                      2);
+  }
+
   this->WriteString("</PropertyGroup>\n", 1);
-  this->WriteString("<Import Project=\"" VS10_CXX_DEFAULT_PROPS "\" />\n", 1);
+
+  switch (this->ProjectType) {
+    case vcxproj:
+      this->WriteString("<Import Project=\"" VS10_CXX_DEFAULT_PROPS "\" />\n",
+                        1);
+      break;
+    case csproj:
+      this->WriteString("<Import Project=\"" VS10_CSharp_DEFAULT_PROPS "\" "
+                        "Condition=\"Exists('" VS10_CSharp_DEFAULT_PROPS "')\""
+                        "/>\n",
+                        1);
+      break;
+  }
+
   this->WriteProjectConfigurationValues();
-  this->WriteString("<Import Project=\"" VS10_CXX_PROPS "\" />\n", 1);
+
+  if (vcxproj == this->ProjectType) {
+    this->WriteString("<Import Project=\"" VS10_CXX_PROPS "\" />\n", 1);
+  }
   this->WriteString("<ImportGroup Label=\"ExtensionSettings\">\n", 1);
   if (this->GlobalGenerator->IsMasmEnabled()) {
     this->WriteString("<Import Project=\"$(VCTargetsPath)\\"
@@ -384,16 +457,26 @@ void cmVisualStudio10TargetGenerator::Generate()
   this->WriteString("</ImportGroup>\n", 1);
   this->WriteString("<ImportGroup Label=\"PropertySheets\">\n", 1);
   {
-    std::string props = VS10_CXX_USER_PROPS;
+    std::string props;
+    switch (this->ProjectType) {
+      case vcxproj:
+        props = VS10_CXX_USER_PROPS;
+        break;
+      case csproj:
+        props = VS10_CSharp_USER_PROPS;
+        break;
+    }
     if (const char* p = this->GeneratorTarget->GetProperty("VS_USER_PROPS")) {
       props = p;
+    }
+    if (!props.empty()) {
       this->ConvertToWindowsSlash(props);
+      this->WriteString("", 2);
+      (*this->BuildFileStream)
+        << "<Import Project=\"" << cmVS10EscapeXML(props) << "\""
+        << " Condition=\"exists('" << cmVS10EscapeXML(props) << "')\""
+        << " Label=\"LocalAppDataPlatform\" />\n";
     }
-    this->WriteString("", 2);
-    (*this->BuildFileStream)
-      << "<Import Project=\"" << cmVS10EscapeXML(props) << "\""
-      << " Condition=\"exists('" << cmVS10EscapeXML(props) << "')\""
-      << " Label=\"LocalAppDataPlatform\" />\n";
   }
   this->WritePlatformExtensions();
   this->WriteString("</ImportGroup>\n", 1);
@@ -409,7 +492,14 @@ void cmVisualStudio10TargetGenerator::Generate()
   this->WriteWinRTReferences();
   this->WriteProjectReferences();
   this->WriteSDKReferences();
-  this->WriteString("<Import Project=\"" VS10_CXX_TARGETS "\" />\n", 1);
+  switch (this->ProjectType) {
+    case vcxproj:
+      this->WriteString("<Import Project=\"" VS10_CXX_TARGETS "\" />\n", 1);
+      break;
+    case csproj:
+      this->WriteString("<Import Project=\"" VS10_CSharp_TARGETS "\" />\n", 1);
+      break;
+  }
 
   this->WriteTargetSpecificReferences();
   this->WriteString("<ImportGroup Label=\"ExtensionTargets\">\n", 1);
@@ -420,6 +510,17 @@ void cmVisualStudio10TargetGenerator::Generate()
                       2);
   }
   this->WriteString("</ImportGroup>\n", 1);
+  if (csproj == this->ProjectType) {
+    for (std::vector<std::string>::const_iterator i =
+           this->Configurations.begin();
+         i != this->Configurations.end(); ++i) {
+      this->WriteString("<PropertyGroup Condition=\"'$(Configuration)' == '",
+                        1);
+      (*this->BuildFileStream) << *i << "'\">\n";
+      this->WriteEvents(*i);
+      this->WriteString("</PropertyGroup>\n", 1);
+    }
+  }
   this->WriteString("</Project>", 0);
   // The groups are stored in a separate file for VS 10
   this->WriteGroups();
@@ -660,48 +761,55 @@ void cmVisualStudio10TargetGenerator::WriteProjectConfigurationValues()
        i != this->Configurations.end(); ++i) {
     this->WritePlatformConfigTag("PropertyGroup", i->c_str(), 1,
                                  " Label=\"Configuration\"", "\n");
-    std::string configType = "<ConfigurationType>";
-    if (const char* vsConfigurationType =
-          this->GeneratorTarget->GetProperty("VS_CONFIGURATION_TYPE")) {
-      configType += cmVS10EscapeXML(vsConfigurationType);
-    } else {
-      switch (this->GeneratorTarget->GetType()) {
-        case cmStateEnums::SHARED_LIBRARY:
-        case cmStateEnums::MODULE_LIBRARY:
-          configType += "DynamicLibrary";
-          break;
-        case cmStateEnums::OBJECT_LIBRARY:
-        case cmStateEnums::STATIC_LIBRARY:
-          configType += "StaticLibrary";
-          break;
-        case cmStateEnums::EXECUTABLE:
-          if (this->NsightTegra &&
-              !this->GeneratorTarget->GetPropertyAsBool("ANDROID_GUI")) {
-            // Android executables are .so too.
+
+    if (csproj != this->ProjectType) {
+      std::string configType = "<ConfigurationType>";
+      if (const char* vsConfigurationType =
+            this->GeneratorTarget->GetProperty("VS_CONFIGURATION_TYPE")) {
+        configType += cmVS10EscapeXML(vsConfigurationType);
+      } else {
+        switch (this->GeneratorTarget->GetType()) {
+          case cmStateEnums::SHARED_LIBRARY:
+          case cmStateEnums::MODULE_LIBRARY:
             configType += "DynamicLibrary";
-          } else {
-            configType += "Application";
-          }
-          break;
-        case cmStateEnums::UTILITY:
-        case cmStateEnums::GLOBAL_TARGET:
-          if (this->NsightTegra) {
-            // Tegra-Android platform does not understand "Utility".
+            break;
+          case cmStateEnums::OBJECT_LIBRARY:
+          case cmStateEnums::STATIC_LIBRARY:
             configType += "StaticLibrary";
-          } else {
-            configType += "Utility";
-          }
-          break;
-        case cmStateEnums::UNKNOWN_LIBRARY:
-        case cmStateEnums::INTERFACE_LIBRARY:
-          break;
+            break;
+          case cmStateEnums::EXECUTABLE:
+            if (this->NsightTegra &&
+                !this->GeneratorTarget->GetPropertyAsBool("ANDROID_GUI")) {
+              // Android executables are .so too.
+              configType += "DynamicLibrary";
+            } else {
+              configType += "Application";
+            }
+            break;
+          case cmStateEnums::UTILITY:
+          case cmStateEnums::GLOBAL_TARGET:
+            if (this->NsightTegra) {
+              // Tegra-Android platform does not understand "Utility".
+              configType += "StaticLibrary";
+            } else {
+              configType += "Utility";
+            }
+            break;
+          case cmStateEnums::UNKNOWN_LIBRARY:
+          case cmStateEnums::INTERFACE_LIBRARY:
+            break;
+        }
       }
+      configType += "</ConfigurationType>\n";
+      this->WriteString(configType.c_str(), 2);
     }
-    configType += "</ConfigurationType>\n";
-    this->WriteString(configType.c_str(), 2);
 
     if (this->MSTools) {
-      this->WriteMSToolConfigurationValues(*i);
+      if (!this->Managed) {
+        this->WriteMSToolConfigurationValues(*i);
+      } else {
+        this->WriteMSToolConfigurationValuesManaged(*i);
+      }
     } else if (this->NsightTegra) {
       this->WriteNsightTegraConfigurationValues(*i);
     }
@@ -760,6 +868,61 @@ void cmVisualStudio10TargetGenerator::WriteMSToolConfigurationValues(
   }
 }
 
+void cmVisualStudio10TargetGenerator::WriteMSToolConfigurationValuesManaged(
+  std::string const& config)
+{
+  cmGlobalVisualStudio10Generator* gg =
+    static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator);
+
+  Options& o = *(this->ClOptions[config]);
+
+  if (o.IsDebug()) {
+    this->WriteString("<DebugSymbols>true</DebugSymbols>\n", 2);
+    this->WriteString("<DefineDebug>true</DefineDebug>\n", 2);
+  }
+
+  std::string outDir =
+    this->GeneratorTarget->GetDirectory(config.c_str()) + "/";
+  this->ConvertToWindowsSlash(outDir);
+  this->WriteString("<OutputPath>", 2);
+  (*this->BuildFileStream) << cmVS10EscapeXML(outDir) << "</OutputPath>\n";
+
+  if (o.HasFlag("Platform")) {
+    this->WriteString("<PlatformTarget>", 2);
+    (*this->BuildFileStream) << cmVS10EscapeXML(o.GetFlag("Platform"))
+                             << "</PlatformTarget>\n";
+    o.RemoveFlag("Platform");
+  }
+
+  if (const char* toolset = gg->GetPlatformToolset()) {
+    this->WriteString("<PlatformToolset>", 2);
+    (*this->BuildFileStream) << cmVS10EscapeXML(toolset)
+                             << "</PlatformToolset>\n";
+  }
+
+  std::string postfixName = cmSystemTools::UpperCase(config);
+  postfixName += "_POSTFIX";
+  std::string assemblyName =
+    this->GeneratorTarget->GetOutputName(config, false);
+  if (const char* postfix = this->GeneratorTarget->GetProperty(postfixName)) {
+    assemblyName += postfix;
+  }
+  this->WriteString("<AssemblyName>", 2);
+  (*this->BuildFileStream) << cmVS10EscapeXML(assemblyName)
+                           << "</AssemblyName>\n";
+
+  if (cmStateEnums::EXECUTABLE == this->GeneratorTarget->GetType()) {
+    this->WriteString("<StartAction>Program</StartAction>\n", 2);
+    this->WriteString("<StartProgram>", 2);
+    (*this->BuildFileStream) << cmVS10EscapeXML(outDir)
+                             << cmVS10EscapeXML(assemblyName)
+                             << ".exe</StartProgram>\n";
+  }
+
+  o.OutputFlagMap(*this->BuildFileStream, "    ");
+}
+
+//----------------------------------------------------------------------------
 void cmVisualStudio10TargetGenerator::WriteNsightTegraConfigurationValues(
   std::string const&)
 {
@@ -923,6 +1086,10 @@ void cmVisualStudio10TargetGenerator::ConvertToWindowsSlash(std::string& s)
 }
 void cmVisualStudio10TargetGenerator::WriteGroups()
 {
+  if (csproj == this->ProjectType) {
+    return;
+  }
+
   // collect up group information
   std::vector<cmSourceGroup> sourceGroups = this->Makefile->GetSourceGroups();
   std::vector<cmSourceFile*> classes;
@@ -1181,7 +1348,33 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource(cmSourceFile const* sf)
   std::string shaderEntryPoint;
   std::string shaderModel;
   std::string shaderAdditionalFlags;
+  std::string sourceLink;
   std::string ext = cmSystemTools::LowerCase(sf->GetExtension());
+  if (csproj == this->ProjectType) {
+    // EVERY extra source file must have a <Link>, otherwise it might not
+    // be visible in Visual Studio at all. The path relative to current
+    // source- or binary-dir is used within the link, if the file is
+    // in none of these paths, it is added with the plain filename without
+    // any path. This means the file will show up at root-level of the csproj
+    // (where CMakeLists.txt etc. are).
+    if (!this->InSourceBuild) {
+      toolHasSettings = true;
+      std::string fullFileName = sf->GetFullPath();
+      std::string srcDir = this->Makefile->GetCurrentSourceDirectory();
+      std::string binDir = this->Makefile->GetCurrentBinaryDirectory();
+      if (fullFileName.find(binDir) != std::string::npos) {
+        sourceLink = "";
+      } else if (fullFileName.find(srcDir) != std::string::npos) {
+        sourceLink = fullFileName.substr(srcDir.length() + 1);
+      } else {
+        // fallback: add plain filename without any path
+        sourceLink = cmsys::SystemTools::GetFilenameName(fullFileName);
+      }
+      if (!sourceLink.empty()) {
+        this->ConvertToWindowsSlash(sourceLink);
+      }
+    }
+  }
   if (ext == "hlsl") {
     tool = "FXCompile";
     // Figure out the type of shader compiler to use.
@@ -1302,6 +1495,10 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource(cmSourceFile const* sf)
       (*this->BuildFileStream) << cmVS10EscapeXML(shaderAdditionalFlags)
                                << "</AdditionalOptions>\n";
     }
+    if (!sourceLink.empty()) {
+      this->WriteString("<Link>", 3);
+      (*this->BuildFileStream) << cmVS10EscapeXML(sourceLink) << "</Link>\n";
+    }
     this->WriteString("</", 2);
     (*this->BuildFileStream) << tool << ">\n";
   } else {
@@ -1343,6 +1540,12 @@ void cmVisualStudio10TargetGenerator::WriteSource(std::string const& tool,
       this->GlobalGenerator->PathTooLong(this->GeneratorTarget, sf, sourceRel);
     }
   }
+  if (csproj == this->ProjectType && this->InSourceBuild) {
+    std::string srcdir = this->Makefile->GetCurrentSourceDirectory();
+    if (sourceFile.find(srcdir) != std::string::npos) {
+      sourceFile = sourceFile.substr(srcdir.size() + 1);
+    }
+  }
   this->ConvertToWindowsSlash(sourceFile);
   this->WriteString("<", 2);
   (*this->BuildFileStream) << tool << " Include=\""
@@ -1393,6 +1596,8 @@ void cmVisualStudio10TargetGenerator::WriteAllSources()
       tool = "MASM";
     } else if (lang == "RC") {
       tool = "ResourceCompile";
+    } else if (lang == "CSharp") {
+      tool = "Compile";
     }
 
     if (!tool.empty()) {
@@ -1596,6 +1801,37 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
     std::string xamlFileName = fileName.substr(0, fileName.find_last_of("."));
     (*this->BuildFileStream) << xamlFileName << "</DependentUpon>\n";
   }
+  if (csproj == this->ProjectType) {
+    std::string f = source->GetFullPath();
+    typedef std::map<std::string, std::string> CsPropMap;
+    CsPropMap sourceFileTags;
+    // set <Link> tag if necessary
+    if (!this->InSourceBuild) {
+      const std::string stripFromPath =
+        this->Makefile->GetCurrentSourceDirectory();
+      if (f.find(stripFromPath) != std::string::npos) {
+        std::string link = f.substr(stripFromPath.length() + 1);
+        this->ConvertToWindowsSlash(link);
+        sourceFileTags["Link"] = link;
+      }
+    }
+    //
+    // NOTE: in future commits additional props will be added!
+    //
+    // write source file specific tags
+    if (!sourceFileTags.empty()) {
+      hasFlags = true;
+      (*this->BuildFileStream) << firstString;
+      firstString = "";
+      for (CsPropMap::const_iterator i = sourceFileTags.begin();
+           i != sourceFileTags.end(); ++i) {
+        this->WriteString("<", 2);
+        (*this->BuildFileStream)
+          << i->first << ">" << cmVS10EscapeXML(i->second) << "</" << i->first
+          << ">\n";
+      }
+    }
+  }
 
   return hasFlags;
 }
@@ -1606,6 +1842,9 @@ void cmVisualStudio10TargetGenerator::WritePathAndIncrementalLinkOptions()
   if (ttype > cmStateEnums::GLOBAL_TARGET) {
     return;
   }
+  if (csproj == this->ProjectType) {
+    return;
+  }
 
   this->WriteString("<PropertyGroup>\n", 2);
   this->WriteString("<_ProjectFileVersion>10.0.20506.1"
@@ -1680,6 +1919,9 @@ void cmVisualStudio10TargetGenerator::OutputLinkIncremental(
   if (!this->MSTools) {
     return;
   }
+  if (csproj == this->ProjectType) {
+    return;
+  }
   // static libraries and things greater than modules do not need
   // to set this option
   if (this->GeneratorTarget->GetType() == cmStateEnums::STATIC_LIBRARY ||
@@ -1734,8 +1976,18 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions(
 
   cmGlobalVisualStudio10Generator* gg =
     static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator);
-  CM_AUTO_PTR<Options> pOptions(new Options(
-    this->LocalGenerator, Options::Compiler, gg->GetClFlagTable()));
+  CM_AUTO_PTR<Options> pOptions;
+  switch (this->ProjectType) {
+    case vcxproj:
+      pOptions = CM_AUTO_PTR<Options>(new Options(
+        this->LocalGenerator, Options::Compiler, gg->GetClFlagTable()));
+      break;
+    case csproj:
+      pOptions = CM_AUTO_PTR<Options>(new Options(this->LocalGenerator,
+                                                  Options::CSharpCompiler,
+                                                  gg->GetCSharpFlagTable()));
+      break;
+  }
   Options& clOptions = *pOptions;
 
   std::string flags;
@@ -1748,7 +2000,7 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions(
     return false;
   }
   if (linkLanguage == "C" || linkLanguage == "CXX" ||
-      linkLanguage == "Fortran") {
+      linkLanguage == "Fortran" || linkLanguage == "CSharp") {
     std::string baseFlagVar = "CMAKE_";
     baseFlagVar += linkLanguage;
     baseFlagVar += "_FLAGS";
@@ -1776,16 +2028,26 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions(
   std::string defineFlags =
     this->GeneratorTarget->Target->GetMakefile()->GetDefineFlags();
   if (this->MSTools) {
-    clOptions.FixExceptionHandlingDefault();
-    clOptions.AddFlag("PrecompiledHeader", "NotUsing");
-    std::string asmLocation = configName + "/";
-    clOptions.AddFlag("AssemblerListingLocation", asmLocation.c_str());
+    if (vcxproj == this->ProjectType) {
+      clOptions.FixExceptionHandlingDefault();
+      clOptions.AddFlag("PrecompiledHeader", "NotUsing");
+      std::string asmLocation = configName + "/";
+      clOptions.AddFlag("AssemblerListingLocation", asmLocation.c_str());
+    }
   }
   clOptions.Parse(flags.c_str());
   clOptions.Parse(defineFlags.c_str());
   std::vector<std::string> targetDefines;
-  this->GeneratorTarget->GetCompileDefinitions(targetDefines,
-                                               configName.c_str(), "CXX");
+  switch (this->ProjectType) {
+    case vcxproj:
+      this->GeneratorTarget->GetCompileDefinitions(targetDefines,
+                                                   configName.c_str(), "CXX");
+      break;
+    case csproj:
+      this->GeneratorTarget->GetCompileDefinitions(
+        targetDefines, configName.c_str(), "CSharp");
+      break;
+  }
   clOptions.AddDefines(targetDefines);
   if (this->MSTools) {
     clOptions.SetVerboseMakefile(
@@ -1840,6 +2102,9 @@ void cmVisualStudio10TargetGenerator::WriteClOptions(
   std::string const& configName, std::vector<std::string> const& includes)
 {
   Options& clOptions = *(this->ClOptions[configName]);
+  if (this->ProjectType == csproj) {
+    return;
+  }
   this->WriteString("<ClCompile>\n", 2);
   clOptions.OutputAdditionalOptions(*this->BuildFileStream, "      ", "");
   clOptions.AppendFlag("AdditionalIncludeDirectories", includes);
@@ -2508,6 +2773,9 @@ void cmVisualStudio10TargetGenerator::WriteLinkOptions(
       this->GeneratorTarget->GetType() > cmStateEnums::MODULE_LIBRARY) {
     return;
   }
+  if (csproj == this->ProjectType) {
+    return;
+  }
   Options& linkOptions = *(this->LinkOptions[config]);
   this->WriteString("<Link>\n", 2);
 
@@ -2575,6 +2843,9 @@ void cmVisualStudio10TargetGenerator::WriteMidlOptions(
   if (!this->MSTools) {
     return;
   }
+  if (csproj == this->ProjectType) {
+    return;
+  }
 
   // This processes *any* of the .idl files specified in the project's file
   // list (and passed as the item metadata %(Filename) expressing the rule
@@ -2636,7 +2907,9 @@ void cmVisualStudio10TargetGenerator::WriteItemDefinitionGroups()
     //    output midl flags       <Midl></Midl>
     this->WriteMidlOptions(*i, includes);
     // write events
-    this->WriteEvents(*i);
+    if (csproj != this->ProjectType) {
+      this->WriteEvents(*i);
+    }
     //    output link flags       <Link></Link>
     this->WriteLinkOptions(*i);
     //    output lib flags       <Lib></Lib>
@@ -2702,12 +2975,20 @@ void cmVisualStudio10TargetGenerator::WriteEvent(
     script += cmVS10EscapeXML(lg->ConstructScript(ccg));
   }
   comment = cmVS10EscapeComment(comment);
-  this->WriteString("<Message>", 3);
-  (*this->BuildFileStream) << cmVS10EscapeXML(comment) << "</Message>\n";
-  this->WriteString("<Command>", 3);
+  if (csproj != this->ProjectType) {
+    this->WriteString("<Message>", 3);
+    (*this->BuildFileStream) << cmVS10EscapeXML(comment) << "</Message>\n";
+    this->WriteString("<Command>", 3);
+  } else {
+    if (!comment.empty()) {
+      (*this->BuildFileStream) << "echo " << cmVS10EscapeXML(comment) << "\n";
+    }
+  }
   (*this->BuildFileStream) << script;
-  (*this->BuildFileStream) << "</Command>"
-                           << "\n";
+  if (csproj != this->ProjectType) {
+    (*this->BuildFileStream) << "</Command>";
+  }
+  (*this->BuildFileStream) << "\n";
   this->WriteString("</", 2);
   (*this->BuildFileStream) << name << ">\n";
 }
@@ -2732,6 +3013,10 @@ void cmVisualStudio10TargetGenerator::WriteProjectReferences()
           ->TargetIsFortranOnly(dt)) {
       continue;
     }
+    if (csproj == this->ProjectType &&
+        !this->GlobalGenerator->TargetIsCSharpOnly(dt)) {
+      continue;
+    }
     this->WriteString("<ProjectReference Include=\"", 2);
     cmLocalGenerator* lg = dt->GetLocalGenerator();
     std::string name = dt->GetName();
@@ -2748,8 +3033,16 @@ void cmVisualStudio10TargetGenerator::WriteProjectReferences()
     this->ConvertToWindowsSlash(path);
     (*this->BuildFileStream) << cmVS10EscapeXML(path) << "\">\n";
     this->WriteString("<Project>", 3);
-    (*this->BuildFileStream) << this->GlobalGenerator->GetGUID(name.c_str())
-                             << "</Project>\n";
+    if (csproj == this->ProjectType) {
+      (*this->BuildFileStream) << "{";
+    }
+    (*this->BuildFileStream) << this->GlobalGenerator->GetGUID(name.c_str());
+    if (csproj == this->ProjectType) {
+      (*this->BuildFileStream) << "}";
+    }
+    (*this->BuildFileStream) << "</Project>\n";
+    this->WriteString("<Name>", 3);
+    (*this->BuildFileStream) << name << "</Name>\n";
     this->WriteString("</ProjectReference>\n", 2);
   }
   this->WriteString("</ItemGroup>\n", 1);

+ 1 - 0
Source/cmVisualStudio10TargetGenerator.h

@@ -56,6 +56,7 @@ private:
   void WriteProjectConfigurations();
   void WriteProjectConfigurationValues();
   void WriteMSToolConfigurationValues(std::string const& config);
+  void WriteMSToolConfigurationValuesManaged(std::string const& config);
   void WriteHeaderSource(cmSourceFile const* sf);
   void WriteExtraSource(cmSourceFile const* sf);
   void WriteNsightTegraConfigurationValues(std::string const& config);

+ 3 - 0
Tests/CMakeLists.txt

@@ -325,6 +325,9 @@ if(BUILD_TESTING)
     endif()
   endif()
 
+  if(${CMAKE_GENERATOR} MATCHES "Visual Studio ([^789]|[789][0-9])")
+    ADD_TEST_MACRO(CSharpOnly CSharpOnly)
+  endif()
 
   ADD_TEST_MACRO(COnly COnly)
   ADD_TEST_MACRO(CxxOnly CxxOnly)

+ 10 - 0
Tests/CSharpOnly/CMakeLists.txt

@@ -0,0 +1,10 @@
+# a simple CSharp only test case
+project (CSharpOnly CSharp)
+
+# C# does not make any difference between STATIC and SHARED libs
+add_library(lib1 STATIC lib1.cs)
+add_library(lib2 SHARED lib2.cs)
+
+add_executable(CSharpOnly csharponly.cs)
+
+target_link_libraries(CSharpOnly lib1 lib2)

+ 15 - 0
Tests/CSharpOnly/csharponly.cs

@@ -0,0 +1,15 @@
+namespace CSharpOnly
+{
+    class CSharpOnly
+    {
+        public static void Main(string[] args)
+        {
+            int val = Lib1.getResult();
+
+            Lib2 l = new Lib2();
+            val = l.myVal;
+
+            return;
+        }
+    }
+}

+ 10 - 0
Tests/CSharpOnly/lib1.cs

@@ -0,0 +1,10 @@
+namespace CSharpOnly
+{
+    public class Lib1
+    {
+        public static int getResult()
+        {
+            return 23;
+        }
+    }
+}

+ 10 - 0
Tests/CSharpOnly/lib2.cs

@@ -0,0 +1,10 @@
+namespace CSharpOnly
+{
+    public class Lib2
+    {
+        public int myVal = 42;
+
+        public Lib2()
+        {}
+    }
+}