VS10: Refactor link options collection

Avoid collecting the link options twice.  Collect them once in a
LinkOptions member and use it from both places.  We already do this for
compiler options with the ClOptions member.
diff --git a/Source/cmIDEOptions.cxx b/Source/cmIDEOptions.cxx
index d9c0e87..76a60cf 100644
--- a/Source/cmIDEOptions.cxx
+++ b/Source/cmIDEOptions.cxx
@@ -177,3 +177,14 @@
 {
   this->FlagMap.erase(flag);
 }
+
+//----------------------------------------------------------------------------
+const char* cmIDEOptions::GetFlag(const char* flag)
+{
+  std::map<cmStdString, cmStdString>::iterator i = this->FlagMap.find(flag);
+  if(i != this->FlagMap.end())
+    {
+    return i->second.c_str();
+    }
+  return 0;
+}
diff --git a/Source/cmIDEOptions.h b/Source/cmIDEOptions.h
index a5be8fb..e556bde 100644
--- a/Source/cmIDEOptions.h
+++ b/Source/cmIDEOptions.h
@@ -29,6 +29,7 @@
   void AddDefines(const char* defines);
   void AddFlag(const char* flag, const char* value);
   void RemoveFlag(const char* flag);
+  const char* GetFlag(const char* flag);
 
 protected:
   // create a map of xml tags to the values they should have in the output
diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx
index 1e37ca5..db03163 100644
--- a/Source/cmVisualStudio10TargetGenerator.cxx
+++ b/Source/cmVisualStudio10TargetGenerator.cxx
@@ -109,6 +109,11 @@
     {
     delete i->second;
     }
+  for(OptionsMap::iterator i = this->LinkOptions.begin();
+      i != this->LinkOptions.end(); ++i)
+    {
+    delete i->second;
+    }
   if(!this->BuildFileStream)
     {
     return;
@@ -181,6 +186,10 @@
       {
       return;
       }
+    if(!this->ComputeLinkOptions())
+      {
+      return;
+      }
     }
   cmMakefile* mf = this->Target->GetMakefile();
   std::string path =  mf->GetStartOutputDirectory();
@@ -1077,7 +1086,6 @@
 cmVisualStudio10TargetGenerator::
 OutputLinkIncremental(std::string const& configName)
 {
-  std::string CONFIG = cmSystemTools::UpperCase(configName);
   // static libraries and things greater than modules do not need
   // to set this option
   if(this->Target->GetType() == cmTarget::STATIC_LIBRARY
@@ -1085,72 +1093,19 @@
     {
     return;
     }
-  const char* linkType = "SHARED";
-  if(this->Target->GetType() == cmTarget::EXECUTABLE)
-    {
-    linkType = "EXE";
-    }
+  Options& linkOptions = *(this->LinkOptions[configName]);
 
-  // assume incremental linking
-  const char* incremental = "true";
-  const char* linkLanguage =
-    this->Target->GetLinkerLanguage(configName.c_str());
-  if(!linkLanguage)
-    {
-    cmSystemTools::Error
-      ("CMake can not determine linker language for target:",
-       this->Name.c_str());
-    return;
-    }
-  std::string linkFlagVarBase = "CMAKE_";
-  linkFlagVarBase += linkType;
-  linkFlagVarBase += "_LINKER_FLAGS";
-  std::string flags = this->
-    Target->GetMakefile()->GetRequiredDefinition(linkFlagVarBase.c_str());
-  std::string linkFlagVar = linkFlagVarBase + "_" + CONFIG;
-  flags += this->
-    Target->GetMakefile()->GetRequiredDefinition(linkFlagVar.c_str());
-  if(strcmp(linkLanguage, "C") == 0 || strcmp(linkLanguage, "CXX") == 0
-     || strcmp(linkLanguage, "Fortran") == 0)
-    {
-    std::string baseFlagVar = "CMAKE_";
-    baseFlagVar += linkLanguage;
-    baseFlagVar += "_FLAGS";
-    flags += this->
-      Target->GetMakefile()->GetRequiredDefinition(baseFlagVar.c_str());
-    std::string flagVar = baseFlagVar + std::string("_") + CONFIG;
-    flags +=
-      Target->GetMakefile()->GetRequiredDefinition(flagVar.c_str());
-    }
-  const char* targetLinkFlags = this->Target->GetProperty("LINK_FLAGS");
-  if(targetLinkFlags)
-    {
-    flags += " ";
-    flags += targetLinkFlags;
-    }
-  std::string flagsProp = "LINK_FLAGS_";
-  flagsProp += CONFIG;
-  if(const char* flagsConfig = this->Target->GetProperty(flagsProp.c_str()))
-    {
-    flags += " ";
-    flags += flagsConfig;
-    }
-  if(flags.find("INCREMENTAL:NO") != flags.npos)
-    {
-    incremental = "false";
-    }
+  const char* incremental = linkOptions.GetFlag("LinkIncremental");
   this->WritePlatformConfigTag("LinkIncremental", configName.c_str(), 3);
-  *this->BuildFileStream << incremental
+  *this->BuildFileStream << (incremental?incremental:"true")
                          << "</LinkIncremental>\n";
+  linkOptions.RemoveFlag("LinkIncremental");
 
-  const char* manifest = "true";
-  if(flags.find("MANIFEST:NO") != flags.npos)
-    {
-    manifest = "false";
-    }
+  const char* manifest = linkOptions.GetFlag("GenerateManifest");
   this->WritePlatformConfigTag("GenerateManifest", configName.c_str(), 3);
-  *this->BuildFileStream << manifest
+  *this->BuildFileStream << (manifest?manifest:"true")
                          << "</GenerateManifest>\n";
+  linkOptions.RemoveFlag("GenerateManifest");
 }
 
 //----------------------------------------------------------------------------
@@ -1343,18 +1298,36 @@
     }
 }
 
-
-void cmVisualStudio10TargetGenerator::WriteLinkOptions(std::string const&
-                                                       config)
+//----------------------------------------------------------------------------
+bool cmVisualStudio10TargetGenerator::ComputeLinkOptions()
 {
-
-  // static libraries and things greater than modules do not need
-  // to set this option
-  if(this->Target->GetType() == cmTarget::STATIC_LIBRARY
-     || this->Target->GetType() > cmTarget::MODULE_LIBRARY)
+  if(this->Target->GetType() == cmTarget::EXECUTABLE ||
+     this->Target->GetType() == cmTarget::SHARED_LIBRARY ||
+     this->Target->GetType() == cmTarget::MODULE_LIBRARY)
     {
-    return;
+    std::vector<std::string> const* configs =
+      this->GlobalGenerator->GetConfigurations();
+    for(std::vector<std::string>::const_iterator i = configs->begin();
+        i != configs->end(); ++i)
+      {
+      if(!this->ComputeLinkOptions(*i))
+        {
+        return false;
+        }
+      }
     }
+  return true;
+}
+
+//----------------------------------------------------------------------------
+bool
+cmVisualStudio10TargetGenerator::ComputeLinkOptions(std::string const& config)
+{
+  cmsys::auto_ptr<Options> pOptions(
+    new Options(this->LocalGenerator, Options::Linker,
+                cmVSGetLinkFlagTable(this->LocalGenerator), 0, this));
+  Options& linkOptions = *pOptions;
+
   const char* linkLanguage =
     this->Target->GetLinkerLanguage(config.c_str());
   if(!linkLanguage)
@@ -1362,10 +1335,9 @@
     cmSystemTools::Error
       ("CMake can not determine linker language for target:",
        this->Name.c_str());
-    return;
+    return false;
     }
 
-  this->WriteString("<Link>\n", 2);
   std::string CONFIG = cmSystemTools::UpperCase(config);
 
   const char* linkType = "SHARED";
@@ -1387,7 +1359,6 @@
     flags += " ";
     flags += stackVal;
     }
-  // assume incremental linking
   std::string linkFlagVarBase = "CMAKE_";
   linkFlagVarBase += linkType;
   linkFlagVarBase += "_LINKER_FLAGS";
@@ -1411,10 +1382,6 @@
     flags += " ";
     flags += flagsConfig;
     }
-  cmVisualStudioGeneratorOptions
-    linkOptions(this->LocalGenerator,
-                cmVisualStudioGeneratorOptions::Linker,
-                cmVSGetLinkFlagTable(this->LocalGenerator), 0, this);
   if ( this->Target->GetPropertyAsBool("WIN32_EXECUTABLE") )
     {
     flags += " /SUBSYSTEM:WINDOWS";
@@ -1423,8 +1390,6 @@
     {
     flags += " /SUBSYSTEM:CONSOLE";
     }
-  cmSystemTools::ReplaceString(flags, "/INCREMENTAL:YES", "");
-  cmSystemTools::ReplaceString(flags, "/INCREMENTAL:NO", "");
   std::string standardLibsVar = "CMAKE_";
   standardLibsVar += linkLanguage;
   standardLibsVar += "_STANDARD_LIBRARIES";
@@ -1452,7 +1417,7 @@
     cmSystemTools::Error
       ("CMake can not compute cmComputeLinkInformation for target:",
        this->Name.c_str());
-    return;
+    return false;
     }
   // add the libraries for the target to libs string
   cmComputeLinkInformation& cli = *pcli;
@@ -1521,7 +1486,22 @@
                         this->GeneratorTarget->ModuleDefinitionFile.c_str());
     }
 
-  linkOptions.RemoveFlag("GenerateManifest");
+  this->LinkOptions[config] = pOptions.release();
+  return true;
+}
+
+//----------------------------------------------------------------------------
+void
+cmVisualStudio10TargetGenerator::WriteLinkOptions(std::string const& config)
+{
+  if(this->Target->GetType() == cmTarget::STATIC_LIBRARY
+     || this->Target->GetType() > cmTarget::MODULE_LIBRARY)
+    {
+    return;
+    }
+  Options& linkOptions = *(this->LinkOptions[config]);
+  this->WriteString("<Link>\n", 2);
+
   linkOptions.OutputAdditionalOptions(*this->BuildFileStream, "      ", "");
   linkOptions.OutputFlagMap(*this->BuildFileStream, "      ");
 
diff --git a/Source/cmVisualStudio10TargetGenerator.h b/Source/cmVisualStudio10TargetGenerator.h
index 308b9bd..55a850a 100644
--- a/Source/cmVisualStudio10TargetGenerator.h
+++ b/Source/cmVisualStudio10TargetGenerator.h
@@ -68,6 +68,8 @@
                       std::vector<std::string> const & includes);
   void WriteRCOptions(std::string const& config,
                       std::vector<std::string> const & includes);
+  bool ComputeLinkOptions();
+  bool ComputeLinkOptions(std::string const& config);
   void WriteLinkOptions(std::string const& config);
   void WriteMidlOptions(std::string const& config,
                         std::vector<std::string> const & includes);
@@ -95,6 +97,7 @@
   typedef cmVisualStudioGeneratorOptions Options;
   typedef std::map<cmStdString, Options*> OptionsMap;
   OptionsMap ClOptions;
+  OptionsMap LinkOptions;
   std::string PathToVcxproj;
   cmTarget* Target;
   cmGeneratorTarget* GeneratorTarget;