Procházet zdrojové kódy

VisualStudio generators: refactoring

Uniformize include directories handling.
Fix memory leaks in class cmVisualStudio10TargetGenerator:
OptionsMap uses now std::unique_ptr.
Marc Chevrier před 7 roky
rodič
revize
3073bd1f3d

+ 42 - 0
Source/cmIDEOptions.cxx

@@ -13,6 +13,7 @@ cmIDEOptions::cmIDEOptions()
 {
   this->DoingDefine = false;
   this->AllowDefine = true;
+  this->DoingInclude = false;
   this->AllowSlash = false;
   this->DoingFollowing = 0;
   for (int i = 0; i < FlagTableCount; ++i) {
@@ -33,6 +34,13 @@ void cmIDEOptions::HandleFlag(const char* flag)
     return;
   }
 
+  // If the last option was -I then this option is the include directory.
+  if (this->DoingInclude) {
+    this->DoingInclude = false;
+    this->Includes.push_back(flag);
+    return;
+  }
+
   // If the last option expected a following value, this is it.
   if (this->DoingFollowing) {
     this->FlagMapUpdate(this->DoingFollowing, flag);
@@ -53,6 +61,17 @@ void cmIDEOptions::HandleFlag(const char* flag)
       }
       return;
     }
+    // Look for include directory.
+    if (this->AllowInclude && flag[1] == 'I') {
+      if (flag[2] == '\0') {
+        // The next argument will have the include directory.
+        this->DoingInclude = true;
+      } else {
+        // Store this include directory.
+        this->Includes.push_back(flag + 2);
+      }
+      return;
+    }
 
     // Look through the available flag tables.
     bool flag_handled = false;
@@ -155,6 +174,29 @@ std::vector<std::string> const& cmIDEOptions::GetDefines() const
   return this->Defines;
 }
 
+void cmIDEOptions::AddInclude(const std::string& include)
+{
+  this->Includes.push_back(include);
+}
+
+void cmIDEOptions::AddIncludes(const char* includes)
+{
+  if (includes) {
+    // Expand the list of includes.
+    cmSystemTools::ExpandListArgument(includes, this->Includes);
+  }
+}
+void cmIDEOptions::AddIncludes(const std::vector<std::string>& includes)
+{
+  this->Includes.insert(this->Includes.end(), includes.begin(),
+                        includes.end());
+}
+
+std::vector<std::string> const& cmIDEOptions::GetIncludes() const
+{
+  return this->Includes;
+}
+
 void cmIDEOptions::AddFlag(std::string const& flag, std::string const& value)
 {
   this->FlagMap[flag] = value;

+ 11 - 1
Source/cmIDEOptions.h

@@ -20,12 +20,17 @@ public:
   cmIDEOptions();
   virtual ~cmIDEOptions();
 
-  // Store definitions and flags.
+  // Store definitions, includes and flags.
   void AddDefine(const std::string& define);
   void AddDefines(const char* defines);
   void AddDefines(const std::vector<std::string>& defines);
   std::vector<std::string> const& GetDefines() const;
 
+  void AddInclude(const std::string& includes);
+  void AddIncludes(const char* includes);
+  void AddIncludes(const std::vector<std::string>& includes);
+  std::vector<std::string> const& GetIncludes() const;
+
   void AddFlag(std::string const& flag, std::string const& value);
   void AddFlag(std::string const& flag, std::vector<std::string> const& value);
   void AppendFlag(std::string const& flag, std::string const& value);
@@ -76,8 +81,13 @@ protected:
   // Preprocessor definitions.
   std::vector<std::string> Defines;
 
+  // Include directories.
+  std::vector<std::string> Includes;
+
   bool DoingDefine;
   bool AllowDefine;
+  bool DoingInclude;
+  bool AllowInclude;
   bool AllowSlash;
   cmIDEFlagTable const* DoingFollowing;
   enum

+ 21 - 62
Source/cmLocalVisualStudio7Generator.cxx

@@ -45,15 +45,6 @@ public:
 
 extern cmVS7FlagTable cmLocalVisualStudio7GeneratorFlagTable[];
 
-static void cmConvertToWindowsSlash(std::string& s)
-{
-  std::string::size_type pos = 0;
-  while ((pos = s.find('/', pos)) != std::string::npos) {
-    s[pos] = '\\';
-    pos++;
-  }
-}
-
 cmLocalVisualStudio7Generator::cmLocalVisualStudio7Generator(
   cmGlobalGenerator* gg, cmMakefile* mf)
   : cmLocalVisualStudioGenerator(gg, mf)
@@ -704,11 +695,16 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(
   targetOptions.Parse(flags.c_str());
   targetOptions.Parse(defineFlags.c_str());
   targetOptions.ParseFinish();
-  std::vector<std::string> targetDefines;
   if (!langForClCompile.empty()) {
+    std::vector<std::string> targetDefines;
     target->GetCompileDefinitions(targetDefines, configName, langForClCompile);
+    targetOptions.AddDefines(targetDefines);
+
+    std::vector<std::string> targetIncludes;
+    this->GetIncludeDirectories(targetIncludes, target, langForClCompile,
+                                configName);
+    targetOptions.AddIncludes(targetIncludes);
   }
-  targetOptions.AddDefines(targetDefines);
   targetOptions.SetVerboseMakefile(
     this->Makefile->IsOn("CMAKE_VERBOSE_MAKEFILE"));
 
@@ -795,27 +791,9 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(
          << this->ConvertToXMLOutputPath(modDir.c_str())
          << "\\$(ConfigurationName)\"\n";
   }
-  fout << "\t\t\t\tAdditionalIncludeDirectories=\"";
-  std::vector<std::string> includes_cl;
-  if (!langForClCompile.empty()) {
-    this->GetIncludeDirectories(includes_cl, target, langForClCompile,
-                                configName);
-  }
-  std::vector<std::string>::iterator i = includes_cl.begin();
-  for (; i != includes_cl.end(); ++i) {
-    // output the include path
-    std::string ipath = this->ConvertToXMLOutputPath(i->c_str());
-    fout << ipath << ";";
-    // if this is fortran then output the include with
-    // a ConfigurationName on the end of it.
-    if (this->FortranProject) {
-      ipath = i->c_str();
-      ipath += "/$(ConfigurationName)";
-      ipath = this->ConvertToXMLOutputPath(ipath.c_str());
-      fout << ipath << ";";
-    }
-  }
-  fout << "\"\n";
+  targetOptions.OutputAdditionalIncludeDirectories(
+    fout, "\t\t\t\t", "\n",
+    this->FortranProject ? "Fortran" : langForClCompile);
   targetOptions.OutputFlagMap(fout, "\t\t\t\t");
   targetOptions.OutputPreprocessorDefinitions(fout, "\t\t\t\t", "\n",
                                               langForClCompile);
@@ -835,20 +813,10 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(
     fout <<
       "\t\t\t<Tool\n"
       "\t\t\t\tName=\"MASM\"\n"
-      "\t\t\t\tIncludePaths=\""
       ;
-    std::vector<std::string> includes_masm;
-    this->GetIncludeDirectories(includes_masm, target, "ASM_MASM",
-                                configName);
     /* clang-format on */
-    const char* sep = "";
-    for (i = includes_masm.begin(); i != includes_masm.end(); ++i) {
-      std::string inc = *i;
-      cmConvertToWindowsSlash(inc);
-      fout << sep << this->EscapeForXML(inc);
-      sep = ";";
-    }
-    fout << "\"\n";
+    targetOptions.OutputAdditionalIncludeDirectories(fout, "\t\t\t\t", "\n",
+                                                     "ASM_MASM");
     // Use same preprocessor definitions as VCCLCompilerTool.
     targetOptions.OutputPreprocessorDefinitions(fout, "\t\t\t\t", "\n",
                                                 "ASM_MASM");
@@ -868,16 +836,10 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(
   if (this->FortranProject) {
     tool = "VFResourceCompilerTool";
   }
-  fout << "\t\t\t<Tool\n\t\t\t\tName=\"" << tool << "\"\n"
-       << "\t\t\t\tAdditionalIncludeDirectories=\"";
-  std::vector<std::string> includes_rc;
-  this->GetIncludeDirectories(includes_rc, target, "RC", configName);
-  for (i = includes_rc.begin(); i != includes_rc.end(); ++i) {
-    std::string ipath = this->ConvertToXMLOutputPath(i->c_str());
-    fout << ipath << ";";
-  }
+  fout << "\t\t\t<Tool\n\t\t\t\tName=\"" << tool << "\"\n";
+  targetOptions.OutputAdditionalIncludeDirectories(fout, "\n\t\t\t\t", "",
+                                                   "RC");
   // add the -D flags to the RC tool
-  fout << "\"";
   targetOptions.OutputPreprocessorDefinitions(fout, "\n\t\t\t\t", "", "RC");
   fout << "/>\n";
   tool = "VCMIDLTool";
@@ -885,14 +847,8 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(
     tool = "VFMIDLTool";
   }
   fout << "\t\t\t<Tool\n\t\t\t\tName=\"" << tool << "\"\n";
-  fout << "\t\t\t\tAdditionalIncludeDirectories=\"";
-  std::vector<std::string> includes_midl;
-  this->GetIncludeDirectories(includes_midl, target, "MIDL", configName);
-  for (i = includes_midl.begin(); i != includes_midl.end(); ++i) {
-    std::string ipath = this->ConvertToXMLOutputPath(i->c_str());
-    fout << ipath << ";";
-  }
-  fout << "\"\n";
+  targetOptions.OutputAdditionalIncludeDirectories(fout, "\n\t\t\t\t", "",
+                                                   "MIDL");
   fout << "\t\t\t\tMkTypLibCompatible=\"false\"\n";
   if (gg->GetPlatformName() == "x64") {
     fout << "\t\t\t\tTargetEnvironment=\"3\"\n";
@@ -1658,7 +1614,7 @@ bool cmLocalVisualStudio7Generator::WriteGroup(
         this->WriteCustomRule(fout, configs, source.c_str(), *command, fcinfo);
       } else if (!fcinfo.FileConfigMap.empty()) {
         const char* aCompilerTool = "VCCLCompilerTool";
-        const char* ppLang = "CXX";
+        std::string ppLang = "CXX";
         if (this->FortranProject) {
           aCompilerTool = "VFFortranCompilerTool";
         }
@@ -1718,6 +1674,9 @@ bool cmLocalVisualStudio7Generator::WriteGroup(
             fileOptions.AddDefines(fc.CompileDefs.c_str());
             fileOptions.AddDefines(fc.CompileDefsConfig.c_str());
             fileOptions.OutputFlagMap(fout, "\t\t\t\t\t");
+            fileOptions.OutputAdditionalIncludeDirectories(
+              fout, "\t\t\t\t\t", "\n",
+              ppLang == "CXX" && this->FortranProject ? "Fortran" : ppLang);
             fileOptions.OutputPreprocessorDefinitions(fout, "\t\t\t\t\t", "\n",
                                                       ppLang);
           }

+ 41 - 54
Source/cmVisualStudio10TargetGenerator.cxx

@@ -114,22 +114,6 @@ cmVisualStudio10TargetGenerator::cmVisualStudio10TargetGenerator(
 
 cmVisualStudio10TargetGenerator::~cmVisualStudio10TargetGenerator()
 {
-  for (OptionsMap::iterator i = this->ClOptions.begin();
-       i != this->ClOptions.end(); ++i) {
-    delete i->second;
-  }
-  for (OptionsMap::iterator i = this->LinkOptions.begin();
-       i != this->LinkOptions.end(); ++i) {
-    delete i->second;
-  }
-  for (OptionsMap::iterator i = this->CudaOptions.begin();
-       i != this->CudaOptions.end(); ++i) {
-    delete i->second;
-  }
-  for (OptionsMap::iterator i = this->CudaLinkOptions.begin();
-       i != this->CudaLinkOptions.end(); ++i) {
-    delete i->second;
-  }
   if (!this->BuildFileStream) {
     return;
   }
@@ -2156,10 +2140,6 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
         }
         clOptions.Parse(expandedOptions.c_str());
       }
-      if (clOptions.HasFlag("AdditionalIncludeDirectories")) {
-        clOptions.AppendFlag("AdditionalIncludeDirectories",
-                             "%(AdditionalIncludeDirectories)");
-      }
       if (clOptions.HasFlag("DisableSpecificWarnings")) {
         clOptions.AppendFlag("DisableSpecificWarnings",
                              "%(DisableSpecificWarnings)");
@@ -2173,6 +2153,8 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
       clOptions.SetConfiguration(config.c_str());
       clOptions.PrependInheritedString("AdditionalOptions");
       clOptions.OutputFlagMap(*this->BuildFileStream, "      ");
+      clOptions.OutputAdditionalIncludeDirectories(*this->BuildFileStream,
+                                                   "      ", "\n", lang);
       clOptions.OutputPreprocessorDefinitions(*this->BuildFileStream, "      ",
                                               "\n", lang);
     }
@@ -2465,6 +2447,13 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions(
       break;
   }
   clOptions.AddDefines(targetDefines);
+
+  // Get includes for this target
+  if (!this->LangForClCompile.empty()) {
+    clOptions.AddIncludes(
+      this->GetIncludes(configName, this->LangForClCompile));
+  }
+
   if (this->MSTools) {
     clOptions.SetVerboseMakefile(
       this->Makefile->IsOn("CMAKE_VERBOSE_MAKEFILE"));
@@ -2516,7 +2505,7 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions(
     }
   }
 
-  this->ClOptions[configName] = pOptions.release();
+  this->ClOptions[configName] = std::move(pOptions);
   return true;
 }
 
@@ -2529,14 +2518,9 @@ void cmVisualStudio10TargetGenerator::WriteClOptions(
   }
   this->WriteString("<ClCompile>\n", 2);
   clOptions.PrependInheritedString("AdditionalOptions");
-  if (!this->LangForClCompile.empty()) {
-    std::vector<std::string> const includes =
-      this->GetIncludes(configName, this->LangForClCompile);
-    clOptions.AppendFlag("AdditionalIncludeDirectories", includes);
-  }
-  clOptions.AppendFlag("AdditionalIncludeDirectories",
-                       "%(AdditionalIncludeDirectories)");
   clOptions.OutputFlagMap(*this->BuildFileStream, "      ");
+  clOptions.OutputAdditionalIncludeDirectories(
+    *this->BuildFileStream, "      ", "\n", this->LangForClCompile);
   clOptions.OutputPreprocessorDefinitions(*this->BuildFileStream, "      ",
                                           "\n", this->LangForClCompile);
 
@@ -2614,7 +2598,10 @@ bool cmVisualStudio10TargetGenerator::ComputeRcOptions(
   Options& clOptions = *(this->ClOptions[configName]);
   rcOptions.AddDefines(clOptions.GetDefines());
 
-  this->RcOptions[configName] = pOptions.release();
+  // Get includes for this target
+  rcOptions.AddIncludes(this->GetIncludes(configName, "RC"));
+
+  this->RcOptions[configName] = std::move(pOptions);
   return true;
 }
 
@@ -2629,11 +2616,8 @@ void cmVisualStudio10TargetGenerator::WriteRCOptions(
   Options& rcOptions = *(this->RcOptions[configName]);
   rcOptions.OutputPreprocessorDefinitions(*this->BuildFileStream, "      ",
                                           "\n", "RC");
-  std::vector<std::string> const includes =
-    this->GetIncludes(configName, "RC");
-  rcOptions.AppendFlag("AdditionalIncludeDirectories", includes);
-  rcOptions.AppendFlag("AdditionalIncludeDirectories",
-                       "%(AdditionalIncludeDirectories)");
+  rcOptions.OutputAdditionalIncludeDirectories(*this->BuildFileStream,
+                                               "      ", "\n", "RC");
   rcOptions.PrependInheritedString("AdditionalOptions");
   rcOptions.OutputFlagMap(*this->BuildFileStream, "      ");
 
@@ -2747,7 +2731,10 @@ bool cmVisualStudio10TargetGenerator::ComputeCudaOptions(
     cudaOptions.AddDefine(exportMacro);
   }
 
-  this->CudaOptions[configName] = pOptions.release();
+  // Get includes for this target
+  cudaOptions.AddIncludes(this->GetIncludes(configName, "CUDA"));
+
+  this->CudaOptions[configName] = std::move(pOptions);
   return true;
 }
 
@@ -2760,10 +2747,8 @@ void cmVisualStudio10TargetGenerator::WriteCudaOptions(
   this->WriteString("<CudaCompile>\n", 2);
 
   Options& cudaOptions = *(this->CudaOptions[configName]);
-  std::vector<std::string> const includes =
-    this->GetIncludes(configName, "CUDA");
-  cudaOptions.AppendFlag("Include", includes);
-  cudaOptions.AppendFlag("Include", "%(Include)");
+  cudaOptions.OutputAdditionalIncludeDirectories(*this->BuildFileStream,
+                                                 "      ", "\n", "CUDA");
   cudaOptions.OutputPreprocessorDefinitions(*this->BuildFileStream, "      ",
                                             "\n", "CUDA");
   cudaOptions.PrependInheritedString("AdditionalOptions");
@@ -2820,7 +2805,7 @@ bool cmVisualStudio10TargetGenerator::ComputeCudaLinkOptions(
                                      "-Wno-deprecated-gpu-targets");
   }
 
-  this->CudaLinkOptions[configName] = pOptions.release();
+  this->CudaLinkOptions[configName] = std::move(pOptions);
   return true;
 }
 
@@ -2871,7 +2856,11 @@ bool cmVisualStudio10TargetGenerator::ComputeMasmOptions(
     std::string(this->Makefile->GetSafeDefinition(configFlagsVar));
 
   masmOptions.Parse(flags.c_str());
-  this->MasmOptions[configName] = pOptions.release();
+
+  // Get includes for this target
+  masmOptions.AddIncludes(this->GetIncludes(configName, "ASM_MASM"));
+
+  this->MasmOptions[configName] = std::move(pOptions);
   return true;
 }
 
@@ -2889,10 +2878,8 @@ void cmVisualStudio10TargetGenerator::WriteMasmOptions(
                                           "\n", "ASM_MASM");
 
   Options& masmOptions = *(this->MasmOptions[configName]);
-  std::vector<std::string> const includes =
-    this->GetIncludes(configName, "ASM_MASM");
-  masmOptions.AppendFlag("IncludePaths", includes);
-  masmOptions.AppendFlag("IncludePaths", "%(IncludePaths)");
+  masmOptions.OutputAdditionalIncludeDirectories(*this->BuildFileStream,
+                                                 "      ", "\n", "ASM_MASM");
   masmOptions.PrependInheritedString("AdditionalOptions");
   masmOptions.OutputFlagMap(*this->BuildFileStream, "      ");
 
@@ -2930,7 +2917,11 @@ bool cmVisualStudio10TargetGenerator::ComputeNasmOptions(
     std::string(" ") +
     std::string(this->Makefile->GetSafeDefinition(configFlagsVar));
   nasmOptions.Parse(flags.c_str());
-  this->NasmOptions[configName] = pOptions.release();
+
+  // Get includes for this target
+  nasmOptions.AddIncludes(this->GetIncludes(configName, "ASM_NASM"));
+
+  this->NasmOptions[configName] = std::move(pOptions);
   return true;
 }
 
@@ -2945,12 +2936,8 @@ void cmVisualStudio10TargetGenerator::WriteNasmOptions(
   std::vector<std::string> includes =
     this->GetIncludes(configName, "ASM_NASM");
   Options& nasmOptions = *(this->NasmOptions[configName]);
-  for (size_t i = 0; i < includes.size(); i++) {
-    includes[i] += "\\";
-  }
-
-  nasmOptions.AppendFlag("IncludePaths", includes);
-  nasmOptions.AppendFlag("IncludePaths", "%(IncludePaths)");
+  nasmOptions.OutputAdditionalIncludeDirectories(*this->BuildFileStream,
+                                                 "      ", "\n", "ASM_NASM");
   nasmOptions.OutputFlagMap(*this->BuildFileStream, "      ");
   nasmOptions.PrependInheritedString("AdditionalOptions");
   nasmOptions.OutputPreprocessorDefinitions(*this->BuildFileStream, "      ",
@@ -3376,7 +3363,7 @@ bool cmVisualStudio10TargetGenerator::ComputeLinkOptions(
     }
   }
 
-  this->LinkOptions[config] = pOptions.release();
+  this->LinkOptions[config] = std::move(pOptions);
   return true;
 }
 
@@ -3542,7 +3529,7 @@ void cmVisualStudio10TargetGenerator::WriteItemDefinitionGroups()
   if (this->ProjectType == csproj) {
     return;
   }
-  for (std::string const& i : this->Configurations) {
+  for (const auto& i : this->Configurations) {
     this->WritePlatformConfigTag("ItemDefinitionGroup", i, 1);
     *this->BuildFileStream << "\n";
     //    output cl compile flags <ClCompile></ClCompile>

+ 4 - 1
Source/cmVisualStudio10TargetGenerator.h

@@ -7,6 +7,7 @@
 
 #include <iosfwd>
 #include <map>
+#include <memory>
 #include <set>
 #include <string>
 #include <vector>
@@ -24,6 +25,8 @@ class cmVisualStudioGeneratorOptions;
 
 class cmVisualStudio10TargetGenerator
 {
+  CM_DISABLE_COPY(cmVisualStudio10TargetGenerator)
+
 public:
   cmVisualStudio10TargetGenerator(cmGeneratorTarget* target,
                                   cmGlobalVisualStudio10Generator* gg);
@@ -169,7 +172,7 @@ private:
 
 private:
   typedef cmVisualStudioGeneratorOptions Options;
-  typedef std::map<std::string, Options*> OptionsMap;
+  typedef std::map<std::string, std::unique_ptr<Options>> OptionsMap;
   OptionsMap ClOptions;
   OptionsMap RcOptions;
   OptionsMap CudaOptions;

+ 67 - 16
Source/cmVisualStudioGeneratorOptions.cxx

@@ -29,23 +29,8 @@ static std::string cmVisualStudioGeneratorOptionsEscapeForXML(std::string ret)
 cmVisualStudioGeneratorOptions::cmVisualStudioGeneratorOptions(
   cmLocalVisualStudioGenerator* lg, Tool tool,
   cmVisualStudio10TargetGenerator* g)
-  : cmIDEOptions()
-  , LocalGenerator(lg)
-  , Version(lg->GetVersion())
-  , CurrentTool(tool)
-  , TargetGenerator(g)
+  : cmVisualStudioGeneratorOptions(lg, tool, nullptr, nullptr, g)
 {
-  // Preprocessor definitions are not allowed for linker tools.
-  this->AllowDefine = (tool != Linker);
-
-  // Slash options are allowed for VS.
-  this->AllowSlash = true;
-
-  this->FortranRuntimeDebug = false;
-  this->FortranRuntimeDLL = false;
-  this->FortranRuntimeMT = false;
-
-  this->UnknownFlagField = "AdditionalOptions";
 }
 
 cmVisualStudioGeneratorOptions::cmVisualStudioGeneratorOptions(
@@ -64,6 +49,9 @@ cmVisualStudioGeneratorOptions::cmVisualStudioGeneratorOptions(
   // Preprocessor definitions are not allowed for linker tools.
   this->AllowDefine = (tool != Linker);
 
+  // include directories are not allowed for linker tools.
+  this->AllowInclude = (tool != Linker);
+
   // Slash options are allowed for VS.
   this->AllowSlash = true;
 
@@ -511,6 +499,69 @@ void cmVisualStudioGeneratorOptions::OutputPreprocessorDefinitions(
   }
 }
 
+void cmVisualStudioGeneratorOptions::OutputAdditionalIncludeDirectories(
+  std::ostream& fout, const char* prefix, const char* suffix,
+  const std::string& lang)
+{
+  if (this->Includes.empty()) {
+    return;
+  }
+
+  const char* tag = "AdditionalIncludeDirectories";
+  if (lang == "CUDA") {
+    tag = "Include";
+  } else if (lang == "ASM_MASM" || lang == "ASM_NASM") {
+    tag = "IncludePaths";
+  }
+
+  if (this->Version >= cmGlobalVisualStudioGenerator::VS10) {
+    // if there are configuration specific flags, then
+    // use the configuration specific tag for PreprocessorDefinitions
+    if (!this->Configuration.empty()) {
+      fout << prefix;
+      this->TargetGenerator->WritePlatformConfigTag(
+        tag, this->Configuration.c_str(), 0, 0, 0, &fout);
+    } else {
+      fout << prefix << "<" << tag << ">";
+    }
+  } else {
+    fout << prefix << tag << "=\"";
+  }
+
+  const char* sep = "";
+  for (std::string include : this->Includes) {
+    // first convert all of the slashes
+    std::string::size_type pos = 0;
+    while ((pos = include.find('/', pos)) != std::string::npos) {
+      include[pos] = '\\';
+      pos++;
+    }
+
+    if (lang == "ASM_NASM") {
+      include += "\\";
+    }
+
+    // Escape this include for the IDE.
+    fout << sep << (this->Version >= cmGlobalVisualStudioGenerator::VS10
+                      ? cmVisualStudio10GeneratorOptionsEscapeForXML(include)
+                      : cmVisualStudioGeneratorOptionsEscapeForXML(include));
+    sep = ";";
+
+    if (lang == "Fortran") {
+      include += "/$(ConfigurationName)";
+      fout << sep << (this->Version >= cmGlobalVisualStudioGenerator::VS10
+                        ? cmVisualStudio10GeneratorOptionsEscapeForXML(include)
+                        : cmVisualStudioGeneratorOptionsEscapeForXML(include));
+    }
+  }
+
+  if (this->Version >= cmGlobalVisualStudioGenerator::VS10) {
+    fout << sep << "%(" << tag << ")</" << tag << ">" << suffix;
+  } else {
+    fout << "\"" << suffix;
+  }
+}
+
 void cmVisualStudioGeneratorOptions::OutputFlagMap(std::ostream& fout,
                                                    const char* indent)
 {

+ 4 - 0
Source/cmVisualStudioGeneratorOptions.h

@@ -86,6 +86,10 @@ public:
   void OutputPreprocessorDefinitions(std::ostream& fout, const char* prefix,
                                      const char* suffix,
                                      const std::string& lang);
+  void OutputAdditionalIncludeDirectories(std::ostream& fout,
+                                          const char* prefix,
+                                          const char* suffix,
+                                          const std::string& lang);
   void OutputFlagMap(std::ostream& fout, const char* indent);
   void SetConfiguration(const char* config);