Jelajahi Sumber

Merge topic 'extract-cmLinkLineComputer'

41340304 cmLinkLineComputer: Extract link libraries computation from cmLocalGenerator
f03d446e cmLinkLineComputer: Move FrameworkPath computation from cmLocalGenerator
3444105f cmLocalGenerator: Inline last use of local variable
77c4202e cmLinkLineComputer: Move RPath computation from cmLocalGenerator
09b6cc66 cmLinkLineComputer: Move LinkPath computation from cmLocalGenerator
0c978063 cmLinkLineComputer: Move ComputeLinkLibs from cmLocalGenerator
0152a01f cmLocalGenerator: Move variable to where it is used
011e6870 cmLocalGenerator: Use a std::string instead of char*
cbca80f3 cmLocalGenerator: Move stringstream to where it is used
d48f69d0 cmLocalGenerator: Move flag determination up in the function
ff8e321c cmLocalGenerator: Separate stdlib content from library stream
80f57e67 cmLocalGenerator: Separate rpath content from library stream
7ef83468 cmLocalGenerator: Pass link library info to OutputLinkLibraries
69295812 Makefiles: Port CreateLinkLibs to cmLinkLineComputer
5b361fdd cmLinkLineComputer: Extract from cmLocalGenerator
2e5d1990 Ninja: Constify
...
Brad King 9 tahun lalu
induk
melakukan
656ebaca3b

+ 6 - 0
Source/CMakeLists.txt

@@ -300,6 +300,8 @@ set(SRCS
   cmInstallDirectoryGenerator.cxx
   cmLinkedTree.h
   cmLinkItem.h
+  cmLinkLineComputer.cxx
+  cmLinkLineComputer.h
   cmListFileCache.cxx
   cmListFileCache.h
   cmListFileLexer.c
@@ -318,6 +320,8 @@ set(SRCS
   cmMakefileUtilityTargetGenerator.cxx
   cmMessenger.cxx
   cmMessenger.h
+  cmMSVC60LinkLineComputer.cxx
+  cmMSVC60LinkLineComputer.h
   cmOSXBundleGenerator.cxx
   cmOSXBundleGenerator.h
   cmOutputConverter.cxx
@@ -545,6 +549,8 @@ set(SRCS ${SRCS}
   cmNinjaNormalTargetGenerator.h
   cmNinjaUtilityTargetGenerator.cxx
   cmNinjaUtilityTargetGenerator.h
+  cmNinjaLinkLineComputer.cxx
+  cmNinjaLinkLineComputer.h
   )
 
 # Temporary variable for tools targets

+ 4 - 2
Source/cmCommonTargetGenerator.cxx

@@ -12,6 +12,7 @@
 #include "cmComputeLinkInformation.h"
 #include "cmGeneratorTarget.h"
 #include "cmGlobalCommonGenerator.h"
+#include "cmLinkLineComputer.h"
 #include "cmLocalCommonGenerator.h"
 #include "cmLocalGenerator.h"
 #include "cmMakefile.h"
@@ -59,7 +60,8 @@ void cmCommonTargetGenerator::AddFeatureFlags(std::string& flags,
   }
 }
 
-void cmCommonTargetGenerator::AddModuleDefinitionFlag(std::string& flags)
+void cmCommonTargetGenerator::AddModuleDefinitionFlag(
+  cmLinkLineComputer* linkLineComputer, std::string& flags)
 {
   if (!this->ModuleDefinitionFile) {
     return;
@@ -76,7 +78,7 @@ void cmCommonTargetGenerator::AddModuleDefinitionFlag(std::string& flags)
   // vs6's "cl -link" pass it to the linker.
   std::string flag = defFileFlag;
   flag += this->LocalGenerator->ConvertToOutputFormat(
-    this->LocalGenerator->ConvertToLinkReference(
+    linkLineComputer->ConvertToLinkReference(
       this->ModuleDefinitionFile->GetFullPath()),
     cmOutputConverter::SHELL);
   this->LocalGenerator->AppendFlags(flags, flag);

+ 3 - 1
Source/cmCommonTargetGenerator.h

@@ -16,6 +16,7 @@ class cmGlobalCommonGenerator;
 class cmLocalCommonGenerator;
 class cmMakefile;
 class cmSourceFile;
+class cmLinkLineComputer;
 
 /** \class cmCommonTargetGenerator
  * \brief Common infrastructure for Makefile and Ninja per-target generators
@@ -37,7 +38,8 @@ protected:
   bool GetFeatureAsBool(const std::string& feature);
 
   // Helper to add flag for windows .def file.
-  void AddModuleDefinitionFlag(std::string& flags);
+  void AddModuleDefinitionFlag(cmLinkLineComputer* linkLineComputer,
+                               std::string& flags);
 
   cmGeneratorTarget* GeneratorTarget;
   cmMakefile* Makefile;

+ 9 - 2
Source/cmGhsMultiTargetGenerator.cxx

@@ -5,6 +5,7 @@
 #include "cmGeneratedFileStream.h"
 #include "cmGeneratorTarget.h"
 #include "cmGlobalGhsMultiGenerator.h"
+#include "cmLinkLineComputer.h"
 #include "cmLocalGhsMultiGenerator.h"
 #include "cmMakefile.h"
 #include "cmSourceFile.h"
@@ -362,9 +363,15 @@ void cmGhsMultiTargetGenerator::WriteTargetLinkLibraries(
       this->GeneratorTarget->GetCreateRuleVariable(language, config);
     bool useWatcomQuote =
       this->Makefile->IsOn(createRule + "_USE_WATCOM_QUOTE");
+    CM_AUTO_PTR<cmLinkLineComputer> linkLineComputer(
+      this->GetGlobalGenerator()->CreateLinkLineComputer(
+        this->LocalGenerator,
+        this->LocalGenerator->GetStateSnapshot().GetDirectory()));
+    linkLineComputer->SetUseWatcomQuote(useWatcomQuote);
+
     this->LocalGenerator->GetTargetFlags(
-      config, linkLibraries, flags, linkFlags, frameworkPath, linkPath,
-      this->GeneratorTarget, useWatcomQuote);
+      linkLineComputer.get(), config, linkLibraries, flags, linkFlags,
+      frameworkPath, linkPath, this->GeneratorTarget);
     linkFlags = cmSystemTools::TrimWhitespace(linkFlags);
 
     if (!linkPath.empty()) {

+ 14 - 0
Source/cmGlobalGenerator.cxx

@@ -20,7 +20,9 @@
 #include "cmGeneratorExpression.h"
 #include "cmGeneratorTarget.h"
 #include "cmInstallGenerator.h"
+#include "cmLinkLineComputer.h"
 #include "cmLocalGenerator.h"
+#include "cmMSVC60LinkLineComputer.h"
 #include "cmMakefile.h"
 #include "cmOutputConverter.h"
 #include "cmPolicies.h"
@@ -1412,6 +1414,18 @@ cmGlobalGenerator::CreateQtAutoGeneratorsTargets()
   return autogenTargets;
 }
 
+cmLinkLineComputer* cmGlobalGenerator::CreateLinkLineComputer(
+  cmOutputConverter* outputConverter, cmState::Directory stateDir) const
+{
+  return new cmLinkLineComputer(outputConverter, stateDir);
+}
+
+cmLinkLineComputer* cmGlobalGenerator::CreateMSVC60LinkLineComputer(
+  cmOutputConverter* outputConverter, cmState::Directory stateDir) const
+{
+  return new cmMSVC60LinkLineComputer(outputConverter, stateDir);
+}
+
 void cmGlobalGenerator::FinalizeTargetCompileInfo()
 {
   std::vector<std::string> const langs =

+ 8 - 0
Source/cmGlobalGenerator.h

@@ -34,7 +34,9 @@ class cmExportBuildFileGenerator;
 class cmExternalMakefileProjectGenerator;
 class cmGeneratorTarget;
 class cmLocalGenerator;
+class cmLinkLineComputer;
 class cmMakefile;
+class cmOutputConverter;
 class cmake;
 
 /** \class cmGlobalGenerator
@@ -105,6 +107,12 @@ public:
    */
   virtual void Generate();
 
+  virtual cmLinkLineComputer* CreateLinkLineComputer(
+    cmOutputConverter* outputConverter, cmState::Directory stateDir) const;
+
+  cmLinkLineComputer* CreateMSVC60LinkLineComputer(
+    cmOutputConverter* outputConverter, cmState::Directory stateDir) const;
+
   /**
    * Set/Get and Clear the enabled languages.
    */

+ 13 - 2
Source/cmGlobalNinjaGenerator.cxx

@@ -11,6 +11,7 @@
 #include "cmLocalGenerator.h"
 #include "cmLocalNinjaGenerator.h"
 #include "cmMakefile.h"
+#include "cmNinjaLinkLineComputer.h"
 #include "cmOutputConverter.h"
 #include "cmState.h"
 #include "cmSystemTools.h"
@@ -64,6 +65,14 @@ void cmGlobalNinjaGenerator::WriteComment(std::ostream& os,
   os << "# " << comment.substr(lpos) << "\n\n";
 }
 
+cmLinkLineComputer* cmGlobalNinjaGenerator::CreateLinkLineComputer(
+  cmOutputConverter* outputConverter, cmState::Directory /* stateDir */) const
+{
+  return new cmNinjaLinkLineComputer(
+    outputConverter,
+    this->LocalGenerators[0]->GetStateSnapshot().GetDirectory(), this);
+}
+
 std::string cmGlobalNinjaGenerator::EncodeRuleName(std::string const& name)
 {
   // Ninja rule names must match "[a-zA-Z0-9_.-]+".  Use ".xx" to encode
@@ -830,7 +839,8 @@ static void EnsureTrailingSlash(std::string& path)
 #endif
 }
 
-std::string cmGlobalNinjaGenerator::ConvertToNinjaPath(const std::string& path)
+std::string cmGlobalNinjaGenerator::ConvertToNinjaPath(
+  const std::string& path) const
 {
   cmLocalNinjaGenerator* ng =
     static_cast<cmLocalNinjaGenerator*>(this->LocalGenerators[0]);
@@ -1421,7 +1431,8 @@ void cmGlobalNinjaGenerator::InitOutputPathPrefix()
   EnsureTrailingSlash(this->OutputPathPrefix);
 }
 
-std::string cmGlobalNinjaGenerator::NinjaOutputPath(std::string const& path)
+std::string cmGlobalNinjaGenerator::NinjaOutputPath(
+  std::string const& path) const
 {
   if (!this->HasOutputPathPrefix() || cmSystemTools::FileIsFullPath(path)) {
     return path;

+ 6 - 2
Source/cmGlobalNinjaGenerator.h

@@ -70,6 +70,10 @@ public:
   std::string EncodePath(const std::string& path);
   static std::string EncodeDepfileSpace(const std::string& path);
 
+  cmLinkLineComputer* CreateLinkLineComputer(
+    cmOutputConverter* outputConverter,
+    cmState::Directory stateDir) const CM_OVERRIDE;
+
   /**
    * Write the given @a comment to the output stream @a os. It
    * handles new line character properly.
@@ -233,7 +237,7 @@ public:
     return this->RulesFileStream;
   }
 
-  std::string ConvertToNinjaPath(const std::string& path);
+  std::string ConvertToNinjaPath(const std::string& path) const;
   std::string ConvertToNinjaFolderRule(const std::string& path);
 
   struct MapToNinjaPathImpl
@@ -333,7 +337,7 @@ public:
   bool SupportsConsolePool() const;
   bool SupportsImplicitOuts() const;
 
-  std::string NinjaOutputPath(std::string const& path);
+  std::string NinjaOutputPath(std::string const& path) const;
   bool HasOutputPathPrefix() const { return !this->OutputPathPrefix.empty(); }
   void StripNinjaOutputPathPrefixAsSuffix(std::string& path);
 

+ 179 - 0
Source/cmLinkLineComputer.cxx

@@ -0,0 +1,179 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+
+#include "cmLinkLineComputer.h"
+#include "cmComputeLinkInformation.h"
+#include "cmGeneratorTarget.h"
+#include "cmOutputConverter.h"
+
+cmLinkLineComputer::cmLinkLineComputer(cmOutputConverter* outputConverter,
+                                       cmState::Directory stateDir)
+  : StateDir(stateDir)
+  , OutputConverter(outputConverter)
+  , ForResponse(false)
+  , UseWatcomQuote(false)
+  , Relink(false)
+{
+}
+
+cmLinkLineComputer::~cmLinkLineComputer()
+{
+}
+
+void cmLinkLineComputer::SetUseWatcomQuote(bool useWatcomQuote)
+{
+  this->UseWatcomQuote = useWatcomQuote;
+}
+
+void cmLinkLineComputer::SetForResponse(bool forResponse)
+{
+  this->ForResponse = forResponse;
+}
+
+void cmLinkLineComputer::SetRelink(bool relink)
+{
+  this->Relink = relink;
+}
+
+std::string cmLinkLineComputer::ConvertToLinkReference(
+  std::string const& lib) const
+{
+  std::string relLib = lib;
+
+  if (cmOutputConverter::ContainedInDirectory(
+        this->StateDir.GetCurrentBinary(), lib, this->StateDir)) {
+    relLib = cmOutputConverter::ForceToRelativePath(
+      this->StateDir.GetCurrentBinary(), lib);
+  }
+  return relLib;
+}
+
+std::string cmLinkLineComputer::ComputeLinkLibs(cmComputeLinkInformation& cli)
+{
+  std::string linkLibs;
+  typedef cmComputeLinkInformation::ItemVector ItemVector;
+  ItemVector const& items = cli.GetItems();
+  for (ItemVector::const_iterator li = items.begin(); li != items.end();
+       ++li) {
+    if (li->Target && li->Target->GetType() == cmState::INTERFACE_LIBRARY) {
+      continue;
+    }
+    if (li->IsPath) {
+      linkLibs +=
+        this->ConvertToOutputFormat(this->ConvertToLinkReference(li->Value));
+    } else {
+      linkLibs += li->Value;
+    }
+    linkLibs += " ";
+  }
+  return linkLibs;
+}
+
+std::string cmLinkLineComputer::ConvertToOutputFormat(std::string const& input)
+{
+  cmOutputConverter::OutputFormat shellFormat = (this->ForResponse)
+    ? cmOutputConverter::RESPONSE
+    : ((this->UseWatcomQuote) ? cmOutputConverter::WATCOMQUOTE
+                              : cmOutputConverter::SHELL);
+
+  return this->OutputConverter->ConvertToOutputFormat(input, shellFormat);
+}
+
+std::string cmLinkLineComputer::ConvertToOutputForExisting(
+  std::string const& input)
+{
+  cmOutputConverter::OutputFormat shellFormat = (this->ForResponse)
+    ? cmOutputConverter::RESPONSE
+    : ((this->UseWatcomQuote) ? cmOutputConverter::WATCOMQUOTE
+                              : cmOutputConverter::SHELL);
+
+  return this->OutputConverter->ConvertToOutputForExisting(input, shellFormat);
+}
+
+std::string cmLinkLineComputer::ComputeLinkPath(
+  cmComputeLinkInformation& cli, std::string const& libPathFlag,
+  std::string const& libPathTerminator)
+{
+  std::string linkPath;
+  std::vector<std::string> const& libDirs = cli.GetDirectories();
+  for (std::vector<std::string>::const_iterator libDir = libDirs.begin();
+       libDir != libDirs.end(); ++libDir) {
+    std::string libpath = this->ConvertToOutputForExisting(*libDir);
+    linkPath += " " + libPathFlag;
+    linkPath += libpath;
+    linkPath += libPathTerminator;
+    linkPath += " ";
+  }
+  return linkPath;
+}
+
+std::string cmLinkLineComputer::ComputeRPath(cmComputeLinkInformation& cli)
+{
+  std::string rpath;
+  // Check what kind of rpath flags to use.
+  if (cli.GetRuntimeSep().empty()) {
+    // Each rpath entry gets its own option ("-R a -R b -R c")
+    std::vector<std::string> runtimeDirs;
+    cli.GetRPath(runtimeDirs, this->Relink);
+
+    for (std::vector<std::string>::iterator ri = runtimeDirs.begin();
+         ri != runtimeDirs.end(); ++ri) {
+      rpath += cli.GetRuntimeFlag();
+      rpath += this->ConvertToOutputFormat(*ri);
+      rpath += " ";
+    }
+  } else {
+    // All rpath entries are combined ("-Wl,-rpath,a:b:c").
+    std::string rpathString = cli.GetRPathString(this->Relink);
+
+    // Store the rpath option in the stream.
+    if (!rpathString.empty()) {
+      rpath += cli.GetRuntimeFlag();
+      rpath +=
+        this->OutputConverter->EscapeForShell(rpathString, !this->ForResponse);
+      rpath += " ";
+    }
+  }
+  return rpath;
+}
+
+std::string cmLinkLineComputer::ComputeFrameworkPath(
+  cmComputeLinkInformation& cli, std::string const& fwSearchFlag)
+{
+  std::string frameworkPath;
+  if (!fwSearchFlag.empty()) {
+    std::vector<std::string> const& fwDirs = cli.GetFrameworkPaths();
+    for (std::vector<std::string>::const_iterator fdi = fwDirs.begin();
+         fdi != fwDirs.end(); ++fdi) {
+      frameworkPath += fwSearchFlag;
+      frameworkPath += this->ConvertToOutputFormat(*fdi);
+      frameworkPath += " ";
+    }
+  }
+  return frameworkPath;
+}
+
+std::string cmLinkLineComputer::ComputeLinkLibraries(
+  cmComputeLinkInformation& cli, std::string const& stdLibString)
+{
+  std::ostringstream fout;
+  fout << this->ComputeRPath(cli);
+
+  // Write the library flags to the build rule.
+  fout << this->ComputeLinkLibs(cli);
+
+  // Add the linker runtime search path if any.
+  std::string rpath_link = cli.GetRPathLinkString();
+  if (!cli.GetRPathLinkFlag().empty() && !rpath_link.empty()) {
+    fout << cli.GetRPathLinkFlag();
+    fout << this->OutputConverter->EscapeForShell(rpath_link,
+                                                  !this->ForResponse);
+    fout << " ";
+  }
+
+  if (!stdLibString.empty()) {
+    fout << stdLibString << " ";
+  }
+
+  return fout.str();
+}

+ 50 - 0
Source/cmLinkLineComputer.h

@@ -0,0 +1,50 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+
+#ifndef cmLinkLineComputer_h
+#define cmLinkLineComputer_h
+
+#include "cmState.h"
+
+class cmComputeLinkInformation;
+class cmOutputConverter;
+
+class cmLinkLineComputer
+{
+public:
+  cmLinkLineComputer(cmOutputConverter* outputConverter,
+                     cmState::Directory stateDir);
+  virtual ~cmLinkLineComputer();
+
+  void SetUseWatcomQuote(bool useWatcomQuote);
+  void SetForResponse(bool forResponse);
+  void SetRelink(bool relink);
+
+  virtual std::string ConvertToLinkReference(std::string const& input) const;
+
+  std::string ComputeLinkPath(cmComputeLinkInformation& cli,
+                              std::string const& libPathFlag,
+                              std::string const& libPathTerminator);
+
+  std::string ComputeFrameworkPath(cmComputeLinkInformation& cli,
+                                   std::string const& fwSearchFlag);
+
+  std::string ComputeLinkLibraries(cmComputeLinkInformation& cli,
+                                   std::string const& stdLibString);
+
+private:
+  std::string ComputeLinkLibs(cmComputeLinkInformation& cli);
+  std::string ComputeRPath(cmComputeLinkInformation& cli);
+
+  std::string ConvertToOutputFormat(std::string const& input);
+  std::string ConvertToOutputForExisting(std::string const& input);
+
+  cmState::Directory StateDir;
+  cmOutputConverter* OutputConverter;
+
+  bool ForResponse;
+  bool UseWatcomQuote;
+  bool Relink;
+};
+
+#endif

+ 32 - 135
Source/cmLocalGenerator.cxx

@@ -12,6 +12,7 @@
 #include "cmInstallGenerator.h"
 #include "cmInstallScriptGenerator.h"
 #include "cmInstallTargetGenerator.h"
+#include "cmLinkLineComputer.h"
 #include "cmMakefile.h"
 #include "cmSourceFile.h"
 #include "cmSystemTools.h"
@@ -1148,11 +1149,12 @@ void cmLocalGenerator::GetStaticLibraryFlags(std::string& flags,
 }
 
 void cmLocalGenerator::GetTargetFlags(
-  const std::string& config, std::string& linkLibs, std::string& flags,
-  std::string& linkFlags, std::string& frameworkPath, std::string& linkPath,
-  cmGeneratorTarget* target, bool useWatcomQuote)
+  cmLinkLineComputer* linkLineComputer, const std::string& config,
+  std::string& linkLibs, std::string& flags, std::string& linkFlags,
+  std::string& frameworkPath, std::string& linkPath, cmGeneratorTarget* target)
 {
   const std::string buildType = cmSystemTools::UpperCase(config);
+  cmComputeLinkInformation* pcli = target->GetLinkInformation(config);
   const char* libraryLinkVariable =
     "CMAKE_SHARED_LINKER_FLAGS"; // default to shared library
 
@@ -1203,8 +1205,10 @@ void cmLocalGenerator::GetTargetFlags(
           linkFlags += " ";
         }
       }
-      this->OutputLinkLibraries(linkLibs, frameworkPath, linkPath, *target,
-                                false, false, useWatcomQuote);
+      if (pcli) {
+        this->OutputLinkLibraries(pcli, linkLineComputer, linkLibs,
+                                  frameworkPath, linkPath);
+      }
     } break;
     case cmState::EXECUTABLE: {
       linkFlags += this->Makefile->GetSafeDefinition("CMAKE_EXE_LINKER_FLAGS");
@@ -1223,8 +1227,10 @@ void cmLocalGenerator::GetTargetFlags(
         return;
       }
       this->AddLanguageFlags(flags, linkLanguage, buildType);
-      this->OutputLinkLibraries(linkLibs, frameworkPath, linkPath, *target,
-                                false, false, useWatcomQuote);
+      if (pcli) {
+        this->OutputLinkLibraries(pcli, linkLineComputer, linkLibs,
+                                  frameworkPath, linkPath);
+      }
       if (cmSystemTools::IsOn(
             this->Makefile->GetDefinition("BUILD_SHARED_LIBS"))) {
         std::string sFlagVar = std::string("CMAKE_SHARED_BUILD_") +
@@ -1383,155 +1389,46 @@ std::string cmLocalGenerator::GetTargetFortranFlags(
   return std::string();
 }
 
-std::string cmLocalGenerator::ConvertToLinkReference(std::string const& lib)
-{
-#if defined(_WIN32) && !defined(__CYGWIN__)
-  // Work-ardound command line parsing limitations in MSVC 6.0
-  if (this->Makefile->IsOn("MSVC60")) {
-    // Search for the last space.
-    std::string::size_type pos = lib.rfind(' ');
-    if (pos != lib.npos) {
-      // Find the slash after the last space, if any.
-      pos = lib.find('/', pos);
-
-      // Convert the portion of the path with a space to a short path.
-      std::string sp;
-      if (cmSystemTools::GetShortPath(lib.substr(0, pos).c_str(), sp)) {
-        // Append the rest of the path with no space.
-        sp += lib.substr(pos);
-
-        return sp;
-      }
-    }
-  }
-#endif
-
-  // Normal behavior.
-  return this->ConvertToRelativePath(this->GetCurrentBinaryDirectory(), lib);
-}
-
 /**
  * Output the linking rules on a command line.  For executables,
  * targetLibrary should be a NULL pointer.  For libraries, it should point
  * to the name of the library.  This will not link a library against itself.
  */
-void cmLocalGenerator::OutputLinkLibraries(std::string& linkLibraries,
-                                           std::string& frameworkPath,
-                                           std::string& linkPath,
-                                           cmGeneratorTarget& tgt, bool relink,
-                                           bool forResponseFile,
-                                           bool useWatcomQuote)
-{
-  OutputFormat shellFormat =
-    (forResponseFile) ? RESPONSE : ((useWatcomQuote) ? WATCOMQUOTE : SHELL);
-  bool escapeAllowMakeVars = !forResponseFile;
-  std::ostringstream fout;
-  std::string config = this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE");
-  cmComputeLinkInformation* pcli = tgt.GetLinkInformation(config);
-  if (!pcli) {
-    return;
-  }
+void cmLocalGenerator::OutputLinkLibraries(
+  cmComputeLinkInformation* pcli, cmLinkLineComputer* linkLineComputer,
+  std::string& linkLibraries, std::string& frameworkPath,
+  std::string& linkPath)
+{
   cmComputeLinkInformation& cli = *pcli;
 
   std::string linkLanguage = cli.GetLinkLanguage();
 
-  std::string linkLibs;
-
   std::string libPathFlag =
     this->Makefile->GetRequiredDefinition("CMAKE_LIBRARY_PATH_FLAG");
   std::string libPathTerminator =
     this->Makefile->GetSafeDefinition("CMAKE_LIBRARY_PATH_TERMINATOR");
 
-  // Append the framework search path flags.
-  std::string fwSearchFlagVar = "CMAKE_";
-  fwSearchFlagVar += linkLanguage;
-  fwSearchFlagVar += "_FRAMEWORK_SEARCH_FLAG";
-  const char* fwSearchFlag = this->Makefile->GetDefinition(fwSearchFlagVar);
-  if (fwSearchFlag && *fwSearchFlag) {
-    std::vector<std::string> const& fwDirs = cli.GetFrameworkPaths();
-    for (std::vector<std::string>::const_iterator fdi = fwDirs.begin();
-         fdi != fwDirs.end(); ++fdi) {
-      frameworkPath += fwSearchFlag;
-      frameworkPath += this->ConvertToOutputFormat(*fdi, shellFormat);
-      frameworkPath += " ";
-    }
-  }
-
-  // Append the library search path flags.
-  std::vector<std::string> const& libDirs = cli.GetDirectories();
-  for (std::vector<std::string>::const_iterator libDir = libDirs.begin();
-       libDir != libDirs.end(); ++libDir) {
-    std::string libpath =
-      this->ConvertToOutputForExisting(*libDir, shellFormat);
-    linkPath += " " + libPathFlag;
-    linkPath += libpath;
-    linkPath += libPathTerminator;
-    linkPath += " ";
-  }
-
-  // Append the link items.
-  typedef cmComputeLinkInformation::ItemVector ItemVector;
-  ItemVector const& items = cli.GetItems();
-  for (ItemVector::const_iterator li = items.begin(); li != items.end();
-       ++li) {
-    if (li->Target && li->Target->GetType() == cmState::INTERFACE_LIBRARY) {
-      continue;
-    }
-    if (li->IsPath) {
-      linkLibs += this->ConvertToOutputFormat(
-        this->ConvertToLinkReference(li->Value), shellFormat);
-    } else {
-      linkLibs += li->Value;
-    }
-    linkLibs += " ";
-  }
-
-  // Check what kind of rpath flags to use.
-  if (cli.GetRuntimeSep().empty()) {
-    // Each rpath entry gets its own option ("-R a -R b -R c")
-    std::vector<std::string> runtimeDirs;
-    cli.GetRPath(runtimeDirs, relink);
-
-    std::string rpath;
-    for (std::vector<std::string>::iterator ri = runtimeDirs.begin();
-         ri != runtimeDirs.end(); ++ri) {
-      rpath += cli.GetRuntimeFlag();
-      rpath += this->ConvertToOutputFormat(*ri, shellFormat);
-      rpath += " ";
-    }
-    fout << rpath;
-  } else {
-    // All rpath entries are combined ("-Wl,-rpath,a:b:c").
-    std::string rpath = cli.GetRPathString(relink);
-
-    // Store the rpath option in the stream.
-    if (!rpath.empty()) {
-      fout << cli.GetRuntimeFlag();
-      fout << this->EscapeForShell(rpath, escapeAllowMakeVars);
-      fout << " ";
-    }
-  }
-
-  // Write the library flags to the build rule.
-  fout << linkLibs;
-
-  // Add the linker runtime search path if any.
-  std::string rpath_link = cli.GetRPathLinkString();
-  if (!cli.GetRPathLinkFlag().empty() && !rpath_link.empty()) {
-    fout << cli.GetRPathLinkFlag();
-    fout << this->EscapeForShell(rpath_link, escapeAllowMakeVars);
-    fout << " ";
-  }
-
   // Add standard libraries for this language.
   std::string standardLibsVar = "CMAKE_";
   standardLibsVar += cli.GetLinkLanguage();
   standardLibsVar += "_STANDARD_LIBRARIES";
+  std::string stdLibString;
   if (const char* stdLibs = this->Makefile->GetDefinition(standardLibsVar)) {
-    fout << stdLibs << " ";
+    stdLibString = stdLibs;
   }
 
-  linkLibraries = fout.str();
+  // Append the framework search path flags.
+  std::string fwSearchFlagVar = "CMAKE_";
+  fwSearchFlagVar += linkLanguage;
+  fwSearchFlagVar += "_FRAMEWORK_SEARCH_FLAG";
+  std::string fwSearchFlag =
+    this->Makefile->GetSafeDefinition(fwSearchFlagVar);
+
+  frameworkPath = linkLineComputer->ComputeFrameworkPath(cli, fwSearchFlag);
+  linkPath =
+    linkLineComputer->ComputeLinkPath(cli, libPathFlag, libPathTerminator);
+
+  linkLibraries = linkLineComputer->ComputeLinkLibraries(cli, stdLibString);
 }
 
 std::string cmLocalGenerator::GetLinkLibsCMP0065(

+ 9 - 8
Source/cmLocalGenerator.h

@@ -19,11 +19,13 @@
 #include <string>
 #include <vector>
 
+class cmComputeLinkInformation;
 class cmCustomCommandGenerator;
 class cmGeneratorTarget;
 class cmGlobalGenerator;
 class cmMakefile;
 class cmSourceFile;
+class cmLinkLineComputer;
 
 /** \class cmLocalGenerator
  * \brief Create required build files for a directory.
@@ -312,10 +314,11 @@ public:
 
   /** Fill out these strings for the given target.  Libraries to link,
    *  flags, and linkflags. */
-  void GetTargetFlags(const std::string& config, std::string& linkLibs,
+  void GetTargetFlags(cmLinkLineComputer* linkLineComputer,
+                      const std::string& config, std::string& linkLibs,
                       std::string& flags, std::string& linkFlags,
                       std::string& frameworkPath, std::string& linkPath,
-                      cmGeneratorTarget* target, bool useWatcomQuote);
+                      cmGeneratorTarget* target);
   void GetTargetDefines(cmGeneratorTarget const* target,
                         std::string const& config, std::string const& lang,
                         std::set<std::string>& defines) const;
@@ -345,10 +348,10 @@ public:
 
 protected:
   ///! put all the libraries for a target on into the given stream
-  void OutputLinkLibraries(std::string& linkLibraries,
-                           std::string& frameworkPath, std::string& linkPath,
-                           cmGeneratorTarget&, bool relink,
-                           bool forResponseFile, bool useWatcomQuote);
+  void OutputLinkLibraries(cmComputeLinkInformation* pcli,
+                           cmLinkLineComputer* linkLineComputer,
+                           std::string& linkLibraries,
+                           std::string& frameworkPath, std::string& linkPath);
 
   // Expand rule variables in CMake of the type found in language rules
   void ExpandRuleVariables(std::string& string,
@@ -370,8 +373,6 @@ protected:
   std::string& CreateSafeUniqueObjectFileName(const std::string& sin,
                                               std::string const& dir_max);
 
-  virtual std::string ConvertToLinkReference(std::string const& lib);
-
   /** Check whether the native build system supports the given
       definition.  Issues a warning.  */
   virtual bool CheckDefinition(std::string const& define) const;

+ 0 - 6
Source/cmLocalNinjaGenerator.cxx

@@ -120,12 +120,6 @@ cmGlobalNinjaGenerator* cmLocalNinjaGenerator::GetGlobalNinjaGenerator()
 
 // Virtual protected methods.
 
-std::string cmLocalNinjaGenerator::ConvertToLinkReference(
-  std::string const& lib)
-{
-  return this->GetGlobalNinjaGenerator()->ConvertToNinjaPath(lib);
-}
-
 std::string cmLocalNinjaGenerator::ConvertToIncludeReference(
   std::string const& path, cmOutputConverter::OutputFormat format,
   bool forceFullPaths)

+ 0 - 2
Source/cmLocalNinjaGenerator.h

@@ -76,8 +76,6 @@ public:
   void AppendCustomCommandDeps(cmCustomCommandGenerator const& ccg,
                                cmNinjaDeps& ninjaDeps);
 
-  std::string ConvertToLinkReference(std::string const& lib) CM_OVERRIDE;
-
   void ComputeObjectFilenames(
     std::map<cmSourceFile const*, std::string>& mapping,
     cmGeneratorTarget const* gt = CM_NULLPTR) CM_OVERRIDE;

+ 36 - 0
Source/cmMSVC60LinkLineComputer.cxx

@@ -0,0 +1,36 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+
+#include "cmMSVC60LinkLineComputer.h"
+
+#include "cmSystemTools.h"
+
+cmMSVC60LinkLineComputer::cmMSVC60LinkLineComputer(
+  cmOutputConverter* outputConverter, cmState::Directory stateDir)
+  : cmLinkLineComputer(outputConverter, stateDir)
+{
+}
+
+std::string cmMSVC60LinkLineComputer::ConvertToLinkReference(
+  std::string const& lib) const
+{
+#if defined(_WIN32) && !defined(__CYGWIN__)
+  // Work-ardound command line parsing limitations in MSVC 6.0
+  // Search for the last space.
+  std::string::size_type pos = lib.rfind(' ');
+  if (pos != lib.npos) {
+    // Find the slash after the last space, if any.
+    pos = lib.find('/', pos);
+
+    // Convert the portion of the path with a space to a short path.
+    std::string sp;
+    if (cmSystemTools::GetShortPath(lib.substr(0, pos).c_str(), sp)) {
+      // Append the rest of the path with no space.
+      sp += lib.substr(pos);
+      return sp;
+    }
+  }
+#endif
+
+  return cmLinkLineComputer::ConvertToLinkReference(lib);
+}

+ 19 - 0
Source/cmMSVC60LinkLineComputer.h

@@ -0,0 +1,19 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+
+#ifndef cmMSVC60LinkLineComputer_h
+#define cmMSVC60LinkLineComputer_h
+
+#include "cmLinkLineComputer.h"
+
+class cmMSVC60LinkLineComputer : public cmLinkLineComputer
+{
+public:
+  cmMSVC60LinkLineComputer(cmOutputConverter* outputConverter,
+                           cmState::Directory stateDir);
+
+  std::string ConvertToLinkReference(std::string const& input) const
+    CM_OVERRIDE;
+};
+
+#endif

+ 19 - 3
Source/cmMakefileExecutableTargetGenerator.cxx

@@ -5,6 +5,7 @@
 #include "cmGeneratedFileStream.h"
 #include "cmGeneratorTarget.h"
 #include "cmGlobalUnixMakefileGenerator3.h"
+#include "cmLinkLineComputer.h"
 #include "cmLocalGenerator.h"
 #include "cmLocalUnixMakefileGenerator3.h"
 #include "cmMakefile.h"
@@ -215,7 +216,14 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
   this->LocalGenerator->AppendFlags(
     linkFlags, this->GeneratorTarget->GetProperty(linkFlagsConfig));
 
-  this->AddModuleDefinitionFlag(linkFlags);
+  {
+    CM_AUTO_PTR<cmLinkLineComputer> linkLineComputer(
+      this->CreateLinkLineComputer(
+        this->LocalGenerator,
+        this->LocalGenerator->GetStateSnapshot().GetDirectory()));
+
+    this->AddModuleDefinitionFlag(linkLineComputer.get(), linkFlags);
+  }
 
   // Construct a list of files associated with this executable that
   // may need to be cleaned.
@@ -296,10 +304,18 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
     // Set path conversion for link script shells.
     this->LocalGenerator->SetLinkScriptShell(useLinkScript);
 
+    CM_AUTO_PTR<cmLinkLineComputer> linkLineComputer(
+      this->CreateLinkLineComputer(
+        this->LocalGenerator,
+        this->LocalGenerator->GetStateSnapshot().GetDirectory()));
+    linkLineComputer->SetForResponse(useResponseFileForLibs);
+    linkLineComputer->SetUseWatcomQuote(useWatcomQuote);
+    linkLineComputer->SetRelink(relink);
+
     // Collect up flags to link in needed libraries.
     std::string linkLibs;
-    this->CreateLinkLibs(linkLibs, relink, useResponseFileForLibs, depends,
-                         useWatcomQuote);
+    this->CreateLinkLibs(linkLineComputer.get(), linkLibs,
+                         useResponseFileForLibs, depends);
 
     // Construct object file lists that may be needed to expand the
     // rule.

+ 26 - 4
Source/cmMakefileLibraryTargetGenerator.cxx

@@ -5,6 +5,7 @@
 #include "cmGeneratedFileStream.h"
 #include "cmGeneratorTarget.h"
 #include "cmGlobalUnixMakefileGenerator3.h"
+#include "cmLinkLineComputer.h"
 #include "cmLocalGenerator.h"
 #include "cmLocalUnixMakefileGenerator3.h"
 #include "cmMakefile.h"
@@ -159,7 +160,13 @@ void cmMakefileLibraryTargetGenerator::WriteSharedLibraryRules(bool relink)
 
   this->LocalGenerator->AddConfigVariableFlags(
     extraFlags, "CMAKE_SHARED_LINKER_FLAGS", this->ConfigName);
-  this->AddModuleDefinitionFlag(extraFlags);
+
+  CM_AUTO_PTR<cmLinkLineComputer> linkLineComputer(
+    this->CreateLinkLineComputer(
+      this->LocalGenerator,
+      this->LocalGenerator->GetStateSnapshot().GetDirectory()));
+
+  this->AddModuleDefinitionFlag(linkLineComputer.get(), extraFlags);
 
   if (this->GeneratorTarget->GetProperty("LINK_WHAT_YOU_USE")) {
     this->LocalGenerator->AppendFlags(extraFlags, " -Wl,--no-as-needed");
@@ -184,7 +191,13 @@ void cmMakefileLibraryTargetGenerator::WriteModuleLibraryRules(bool relink)
     extraFlags, this->GeneratorTarget->GetProperty(linkFlagsConfig));
   this->LocalGenerator->AddConfigVariableFlags(
     extraFlags, "CMAKE_MODULE_LINKER_FLAGS", this->ConfigName);
-  this->AddModuleDefinitionFlag(extraFlags);
+
+  CM_AUTO_PTR<cmLinkLineComputer> linkLineComputer(
+    this->CreateLinkLineComputer(
+      this->LocalGenerator,
+      this->LocalGenerator->GetStateSnapshot().GetDirectory()));
+
+  this->AddModuleDefinitionFlag(linkLineComputer.get(), extraFlags);
 
   this->WriteLibraryRules(linkRuleVar, extraFlags, relink);
 }
@@ -491,8 +504,17 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
     // Collect up flags to link in needed libraries.
     std::string linkLibs;
     if (this->GeneratorTarget->GetType() != cmState::STATIC_LIBRARY) {
-      this->CreateLinkLibs(linkLibs, relink, useResponseFileForLibs, depends,
-                           useWatcomQuote);
+
+      CM_AUTO_PTR<cmLinkLineComputer> linkLineComputer(
+        this->CreateLinkLineComputer(
+          this->LocalGenerator,
+          this->LocalGenerator->GetStateSnapshot().GetDirectory()));
+      linkLineComputer->SetForResponse(useResponseFileForLibs);
+      linkLineComputer->SetUseWatcomQuote(useWatcomQuote);
+      linkLineComputer->SetRelink(relink);
+
+      this->CreateLinkLibs(linkLineComputer.get(), linkLibs,
+                           useResponseFileForLibs, depends);
     }
 
     // Construct object file lists that may be needed to expand the

+ 19 - 5
Source/cmMakefileTargetGenerator.cxx

@@ -10,6 +10,7 @@
 #include "cmGeneratorExpression.h"
 #include "cmGeneratorTarget.h"
 #include "cmGlobalUnixMakefileGenerator3.h"
+#include "cmLinkLineComputer.h"
 #include "cmLocalGenerator.h"
 #include "cmLocalUnixMakefileGenerator3.h"
 #include "cmMakefile.h"
@@ -1588,15 +1589,28 @@ std::string cmMakefileTargetGenerator::CreateResponseFile(
   return responseFileName;
 }
 
+cmLinkLineComputer* cmMakefileTargetGenerator::CreateLinkLineComputer(
+  cmOutputConverter* outputConverter, cmState::Directory stateDir)
+{
+  if (this->Makefile->IsOn("MSVC60")) {
+    return this->GlobalGenerator->CreateMSVC60LinkLineComputer(outputConverter,
+                                                               stateDir);
+  }
+  return this->GlobalGenerator->CreateLinkLineComputer(outputConverter,
+                                                       stateDir);
+}
+
 void cmMakefileTargetGenerator::CreateLinkLibs(
-  std::string& linkLibs, bool relink, bool useResponseFile,
-  std::vector<std::string>& makefile_depends, bool useWatcomQuote)
+  cmLinkLineComputer* linkLineComputer, std::string& linkLibs,
+  bool useResponseFile, std::vector<std::string>& makefile_depends)
 {
   std::string frameworkPath;
   std::string linkPath;
-  this->LocalGenerator->OutputLinkLibraries(linkLibs, frameworkPath, linkPath,
-                                            *this->GeneratorTarget, relink,
-                                            useResponseFile, useWatcomQuote);
+  std::string config = this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE");
+  cmComputeLinkInformation* pcli =
+    this->GeneratorTarget->GetLinkInformation(config);
+  this->LocalGenerator->OutputLinkLibraries(pcli, linkLineComputer, linkLibs,
+                                            frameworkPath, linkPath);
   linkLibs = frameworkPath + linkPath + linkLibs;
 
   if (useResponseFile && linkLibs.find_first_not_of(' ') != linkLibs.npos) {

+ 7 - 3
Source/cmMakefileTargetGenerator.h

@@ -20,6 +20,7 @@ class cmGeneratedFileStream;
 class cmGeneratorTarget;
 class cmGlobalUnixMakefileGenerator3;
 class cmSourceFile;
+class cmLinkLineComputer;
 
 /** \class cmMakefileTargetGenerator
  * \brief Support Routines for writing makefiles
@@ -139,6 +140,9 @@ protected:
                         std::vector<std::string>& makefile_commands,
                         std::vector<std::string>& makefile_depends);
 
+  cmLinkLineComputer* CreateLinkLineComputer(
+    cmOutputConverter* outputConverter, cmState::Directory stateDir);
+
   /** Create a response file with the given set of options.  Returns
       the relative path from the target build working directory to the
       response file name.  */
@@ -149,9 +153,9 @@ protected:
   bool CheckUseResponseFileForLibraries(std::string const& l) const;
 
   /** Create list of flags for link libraries. */
-  void CreateLinkLibs(std::string& linkLibs, bool relink, bool useResponseFile,
-                      std::vector<std::string>& makefile_depends,
-                      bool useWatcomQuote);
+  void CreateLinkLibs(cmLinkLineComputer* linkLineComputer,
+                      std::string& linkLibs, bool useResponseFile,
+                      std::vector<std::string>& makefile_depends);
 
   /** Create lists of object files for linking and cleaning.  */
   void CreateObjectLists(bool useLinkScript, bool useArchiveRules,

+ 19 - 0
Source/cmNinjaLinkLineComputer.cxx

@@ -0,0 +1,19 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+
+#include "cmNinjaLinkLineComputer.h"
+#include "cmGlobalNinjaGenerator.h"
+
+cmNinjaLinkLineComputer::cmNinjaLinkLineComputer(
+  cmOutputConverter* outputConverter, cmState::Directory stateDir,
+  cmGlobalNinjaGenerator const* gg)
+  : cmLinkLineComputer(outputConverter, stateDir)
+  , GG(gg)
+{
+}
+
+std::string cmNinjaLinkLineComputer::ConvertToLinkReference(
+  std::string const& lib) const
+{
+  return GG->ConvertToNinjaPath(lib);
+}

+ 26 - 0
Source/cmNinjaLinkLineComputer.h

@@ -0,0 +1,26 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+
+#ifndef cmNinjaLinkLineComputer_h
+#define cmNinjaLinkLineComputer_h
+
+#include "cmLinkLineComputer.h"
+#include "cmState.h"
+
+class cmGlobalNinjaGenerator;
+
+class cmNinjaLinkLineComputer : public cmLinkLineComputer
+{
+public:
+  cmNinjaLinkLineComputer(cmOutputConverter* outputConverter,
+                          cmState::Directory stateDir,
+                          cmGlobalNinjaGenerator const* gg);
+
+  std::string ConvertToLinkReference(std::string const& input) const
+    CM_OVERRIDE;
+
+private:
+  cmGlobalNinjaGenerator const* GG;
+};
+
+#endif

+ 11 - 4
Source/cmNinjaNormalTargetGenerator.cxx

@@ -8,6 +8,7 @@
 #include "cmGeneratedFileStream.h"
 #include "cmGeneratorTarget.h"
 #include "cmGlobalNinjaGenerator.h"
+#include "cmLinkLineComputer.h"
 #include "cmLocalGenerator.h"
 #include "cmLocalNinjaGenerator.h"
 #include "cmMakefile.h"
@@ -470,9 +471,15 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
   vars["TARGET_FILE"] =
     localGen.ConvertToOutputFormat(targetOutputReal, cmOutputConverter::SHELL);
 
-  localGen.GetTargetFlags(this->GetConfigName(), vars["LINK_LIBRARIES"],
-                          vars["FLAGS"], vars["LINK_FLAGS"], frameworkPath,
-                          linkPath, &genTarget, useWatcomQuote);
+  CM_AUTO_PTR<cmLinkLineComputer> linkLineComputer(
+    this->GetGlobalGenerator()->CreateLinkLineComputer(
+      this->GetLocalGenerator(),
+      this->GetLocalGenerator()->GetStateSnapshot().GetDirectory()));
+  linkLineComputer->SetUseWatcomQuote(useWatcomQuote);
+
+  localGen.GetTargetFlags(
+    linkLineComputer.get(), this->GetConfigName(), vars["LINK_LIBRARIES"],
+    vars["FLAGS"], vars["LINK_FLAGS"], frameworkPath, linkPath, &genTarget);
   if (this->GetMakefile()->IsOn("CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS") &&
       (gt.GetType() == cmState::SHARED_LIBRARY ||
        gt.IsExecutableWithExports())) {
@@ -497,7 +504,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
 
   this->addPoolNinjaVariable("JOB_POOL_LINK", &gt, vars);
 
-  this->AddModuleDefinitionFlag(vars["LINK_FLAGS"]);
+  this->AddModuleDefinitionFlag(linkLineComputer.get(), vars["LINK_FLAGS"]);
   vars["LINK_FLAGS"] =
     cmGlobalNinjaGenerator::EncodeLiteral(vars["LINK_FLAGS"]);
 

+ 5 - 2
Source/cmServerProtocol.cxx

@@ -7,6 +7,7 @@
 #include "cmFileMonitor.h"
 #include "cmGeneratorTarget.h"
 #include "cmGlobalGenerator.h"
+#include "cmLinkLineComputer.h"
 #include "cmListFileCache.h"
 #include "cmLocalGenerator.h"
 #include "cmMakefile.h"
@@ -728,8 +729,10 @@ static Json::Value DumpTarget(cmGeneratorTarget* target,
     std::string linkLanguageFlags;
     std::string frameworkPath;
     std::string linkPath;
-    lg->GetTargetFlags(config, linkLibs, linkLanguageFlags, linkFlags,
-                       frameworkPath, linkPath, target, false);
+    cmLinkLineComputer linkLineComputer(lg,
+                                        lg->GetStateSnapshot().GetDirectory());
+    lg->GetTargetFlags(&linkLineComputer, config, linkLibs, linkLanguageFlags,
+                       linkFlags, frameworkPath, linkPath, target);
 
     linkLibs = cmSystemTools::TrimWhitespace(linkLibs);
     linkFlags = cmSystemTools::TrimWhitespace(linkFlags);

+ 5 - 2
Source/cmake.cxx

@@ -12,6 +12,7 @@
 #include "cmGeneratorTarget.h"
 #include "cmGlobalGenerator.h"
 #include "cmGlobalGeneratorFactory.h"
+#include "cmLinkLineComputer.h"
 #include "cmLocalGenerator.h"
 #include "cmMakefile.h"
 #include "cmMessenger.h"
@@ -582,8 +583,10 @@ bool cmake::FindPackage(const std::vector<std::string>& args)
     gg->CreateGenerationObjects();
     cmGeneratorTarget* gtgt = gg->FindGeneratorTarget(tgt->GetName());
     cmLocalGenerator* lg = gtgt->GetLocalGenerator();
-    lg->GetTargetFlags(buildType, linkLibs, flags, linkFlags, frameworkPath,
-                       linkPath, gtgt, false);
+    cmLinkLineComputer linkLineComputer(lg,
+                                        lg->GetStateSnapshot().GetDirectory());
+    lg->GetTargetFlags(&linkLineComputer, buildType, linkLibs, flags,
+                       linkFlags, frameworkPath, linkPath, gtgt);
     linkLibs = frameworkPath + linkPath + linkLibs;
 
     printf("%s\n", linkLibs.c_str());

+ 2 - 0
bootstrap

@@ -297,6 +297,8 @@ CMAKE_CXX_SOURCES="\
   cmFileTimeComparison \
   cmGlobalUnixMakefileGenerator3 \
   cmLocalUnixMakefileGenerator3 \
+  cmLinkLineComputer \
+  cmMSVC60LinkLineComputer \
   cmMakefileExecutableTargetGenerator \
   cmMakefileLibraryTargetGenerator \
   cmMakefileTargetGenerator \