[cmake-commits] king committed CMakeLists.txt 1.386 1.387 cmComputeLinkInformation.cxx NONE 1.1 cmComputeLinkInformation.h NONE 1.1 cmDocumentVariables.cxx 1.9 1.10 cmGlobalGenerator.cxx 1.217 1.218 cmGlobalGenerator.h 1.101 1.102 cmGlobalXCodeGenerator.cxx 1.179 1.180 cmLocalGenerator.cxx 1.257 1.258 cmLocalGenerator.h 1.98 1.99 cmLocalVisualStudio6Generator.cxx 1.137 1.138 cmLocalVisualStudio7Generator.cxx 1.213 1.214 cmLocalVisualStudio7Generator.h 1.47 1.48 cmOrderLinkDirectories.cxx 1.38 NONE cmOrderLinkDirectories.h 1.20 NONE cmTarget.cxx 1.177 1.178 cmTarget.h 1.95 1.96

cmake-commits at cmake.org cmake-commits at cmake.org
Tue Jan 22 09:13:05 EST 2008


Update of /cvsroot/CMake/CMake/Source
In directory public:/mounts/ram/cvs-serv11636/Source

Modified Files:
	CMakeLists.txt cmDocumentVariables.cxx cmGlobalGenerator.cxx 
	cmGlobalGenerator.h cmGlobalXCodeGenerator.cxx 
	cmLocalGenerator.cxx cmLocalGenerator.h 
	cmLocalVisualStudio6Generator.cxx 
	cmLocalVisualStudio7Generator.cxx 
	cmLocalVisualStudio7Generator.h cmTarget.cxx cmTarget.h 
Added Files:
	cmComputeLinkInformation.cxx cmComputeLinkInformation.h 
Removed Files:
	cmOrderLinkDirectories.cxx cmOrderLinkDirectories.h 
Log Message:
ENH: Implement linking with paths to library files instead of -L and -l separation.  See bug #3832

  - This is purely an implementation improvement.  No interface has changed.
  - Create cmComputeLinkInformation class
  - Move and re-implement logic from:
      cmLocalGenerator::ComputeLinkInformation
      cmOrderLinkDirectories
  - Link libraries to targets with their full path (if it is known)
  - Dirs specified with link_directories command still added with -L
  - Make link type specific to library names without paths
    (name libfoo.a without path becomes -Wl,-Bstatic -lfoo)
  - Make directory ordering specific to a runtime path computation feature
    (look for conflicting SONAMEs instead of library names)
  - Implement proper rpath support on HP-UX and AIX.


Index: cmLocalVisualStudio7Generator.cxx
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmLocalVisualStudio7Generator.cxx,v
retrieving revision 1.213
retrieving revision 1.214
diff -u -d -r1.213 -r1.214
--- cmLocalVisualStudio7Generator.cxx	18 Jan 2008 00:29:43 -0000	1.213
+++ cmLocalVisualStudio7Generator.cxx	22 Jan 2008 14:13:03 -0000	1.214
@@ -24,12 +24,24 @@
 #include "cmCacheManager.h"
 #include "cmake.h"
 
+#include "cmComputeLinkInformation.h"
 #include "cmGeneratedFileStream.h"
 
 #include <cmsys/System.h>
 
 #include <ctype.h> // for isspace
 
+class cmLocalVisualStudio7GeneratorInternals
+{
+public:
+  cmLocalVisualStudio7GeneratorInternals(cmLocalVisualStudio7Generator* e):
+    LocalGenerator(e) {}
+  typedef cmComputeLinkInformation::ItemVector ItemVector;
+  void OutputLibraries(std::ostream& fout, ItemVector const& libs);
+private:
+  cmLocalVisualStudio7Generator* LocalGenerator;
+};
+
 extern cmVS7FlagTable cmLocalVisualStudio7GeneratorFlagTable[];
 
 //----------------------------------------------------------------------------
@@ -38,10 +50,12 @@
   this->Version = 7;
   this->PlatformName = "Win32";
   this->ExtraFlagTable = 0;
+  this->Internal = new cmLocalVisualStudio7GeneratorInternals(this);
 }
 
 cmLocalVisualStudio7Generator::~cmLocalVisualStudio7Generator()
 {
+  delete this->Internal;
 }
 
 void cmLocalVisualStudio7Generator::AddHelperCommands()
@@ -748,20 +762,12 @@
                            targetNameImport, targetNamePDB, configName);
 
     // Compute the link library and directory information.
-    std::vector<cmStdString> linkLibs;
-    std::vector<cmStdString> linkDirs;
-    this->ComputeLinkInformation(target, configName, linkLibs, linkDirs);
-
-    // Get the language to use for linking.
-    const char* linkLanguage = 
-      target.GetLinkerLanguage(this->GetGlobalGenerator());
-    if(!linkLanguage)
+    cmComputeLinkInformation cli(&target, configName);
+    if(!cli.Compute())
       {
-      cmSystemTools::Error
-        ("CMake can not determine linker language for target:",
-         target.GetName());
       return;
       }
+    const char* linkLanguage = cli.GetLinkLanguage();
 
     // Compute the variable name to lookup standard libraries for this
     // language.
@@ -777,7 +783,7 @@
     fout << "\t\t\t\tAdditionalDependencies=\"$(NOINHERIT) "
          << this->Makefile->GetSafeDefinition(standardLibsVar.c_str())
          << " ";
-    this->OutputLibraries(fout, linkLibs);
+    this->Internal->OutputLibraries(fout, cli.GetItems());
     fout << "\"\n";
     temp = target.GetDirectory(configName);
     temp += "/";
@@ -787,7 +793,7 @@
     this->WriteTargetVersionAttribute(fout, target);
     linkOptions.OutputFlagMap(fout, "\t\t\t\t");
     fout << "\t\t\t\tAdditionalLibraryDirectories=\"";
-    this->OutputLibraryDirectories(fout, linkDirs);
+    this->OutputLibraryDirectories(fout, cli.GetDirectories());
     fout << "\"\n";
     this->OutputModuleDefinitionFile(fout, target);
     temp = target.GetDirectory(configName);
@@ -825,20 +831,12 @@
                               targetNameImport, targetNamePDB, configName);
 
     // Compute the link library and directory information.
-    std::vector<cmStdString> linkLibs;
-    std::vector<cmStdString> linkDirs;
-    this->ComputeLinkInformation(target, configName, linkLibs, linkDirs);
-
-    // Get the language to use for linking.
-    const char* linkLanguage = 
-      target.GetLinkerLanguage(this->GetGlobalGenerator());
-    if(!linkLanguage)
+    cmComputeLinkInformation cli(&target, configName);
+    if(!cli.Compute())
       {
-      cmSystemTools::Error
-        ("CMake can not determine linker language for target:",
-         target.GetName());
       return;
       }
+    const char* linkLanguage = cli.GetLinkLanguage();
 
     // Compute the variable name to lookup standard libraries for this
     // language.
@@ -854,7 +852,7 @@
     fout << "\t\t\t\tAdditionalDependencies=\"$(NOINHERIT) "
          << this->Makefile->GetSafeDefinition(standardLibsVar.c_str())
          << " ";
-    this->OutputLibraries(fout, linkLibs);
+    this->Internal->OutputLibraries(fout, cli.GetItems());
     fout << "\"\n";
     temp = target.GetDirectory(configName);
     temp += "/";
@@ -864,7 +862,7 @@
     this->WriteTargetVersionAttribute(fout, target);
     linkOptions.OutputFlagMap(fout, "\t\t\t\t");
     fout << "\t\t\t\tAdditionalLibraryDirectories=\"";
-    this->OutputLibraryDirectories(fout, linkDirs);
+    this->OutputLibraryDirectories(fout, cli.GetDirectories());
     fout << "\"\n";
     fout << "\t\t\t\tProgramDataBaseFile=\""
          << target.GetDirectory(configName) << "/" << targetNamePDB
@@ -936,14 +934,23 @@
 
 //----------------------------------------------------------------------------
 void
-cmLocalVisualStudio7Generator
-::OutputLibraries(std::ostream& fout,
-                  std::vector<cmStdString> const& libs)
+cmLocalVisualStudio7GeneratorInternals
+::OutputLibraries(std::ostream& fout, ItemVector const& libs)
 {
-  for(std::vector<cmStdString>::const_iterator l = libs.begin();
-      l != libs.end(); ++l)
+  cmLocalVisualStudio7Generator* lg = this->LocalGenerator;
+  for(ItemVector::const_iterator l = libs.begin(); l != libs.end(); ++l)
     {
-    fout << this->ConvertToXMLOutputPath(l->c_str()) << " ";
+    if(l->IsPath)
+      {
+      std::string rel = lg->Convert(l->Value.c_str(),
+                                    cmLocalGenerator::START_OUTPUT,
+                                    cmLocalGenerator::UNCHANGED);
+      fout << lg->ConvertToXMLOutputPath(rel.c_str()) << " ";
+      }
+    else
+      {
+      fout << l->Value << " ";
+      }
     }
 }
 
@@ -951,10 +958,10 @@
 void
 cmLocalVisualStudio7Generator
 ::OutputLibraryDirectories(std::ostream& fout,
-                           std::vector<cmStdString> const& dirs)
+                           std::vector<std::string> const& dirs)
 {
   const char* comma = "";
-  for(std::vector<cmStdString>::const_iterator d = dirs.begin();
+  for(std::vector<std::string>::const_iterator d = dirs.begin();
       d != dirs.end(); ++d)
     {
     // Remove any trailing slash and skip empty paths.

Index: cmLocalVisualStudio7Generator.h
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmLocalVisualStudio7Generator.h,v
retrieving revision 1.47
retrieving revision 1.48
diff -u -d -r1.47 -r1.48
--- cmLocalVisualStudio7Generator.h	14 Jan 2008 14:20:57 -0000	1.47
+++ cmLocalVisualStudio7Generator.h	22 Jan 2008 14:13:03 -0000	1.48
@@ -27,6 +27,7 @@
 
 class cmLocalVisualStudio7GeneratorOptions;
 class cmLocalVisualStudio7GeneratorFCInfo;
+class cmLocalVisualStudio7GeneratorInternals;
 
 /** \class cmLocalVisualStudio7Generator
  * \brief Write Visual Studio .NET project files.
@@ -96,10 +97,8 @@
                          cmTarget &target, const char *libName);
   void OutputBuildTool(std::ostream& fout, const char* configName,
                        cmTarget& t);
-  void OutputLibraries(std::ostream& fout,
-                       std::vector<cmStdString> const& libs);
   void OutputLibraryDirectories(std::ostream& fout,
-                                std::vector<cmStdString> const& dirs);
+                                std::vector<std::string> const& dirs);
   void OutputModuleDefinitionFile(std::ostream& fout, cmTarget &target);
   void WriteProjectStart(std::ostream& fout, const char *libName,
                          cmTarget &tgt, std::vector<cmSourceGroup> &sgs);
@@ -120,11 +119,13 @@
   virtual std::string GetTargetDirectory(cmTarget const&) const;
 
   friend class cmLocalVisualStudio7GeneratorFCInfo;
+  friend class cmLocalVisualStudio7GeneratorInternals;
 
   cmVS7FlagTable const* ExtraFlagTable;
   std::string ModuleDefinitionFile;
   int Version;
   std::string PlatformName; // Win32 or x64 
+  cmLocalVisualStudio7GeneratorInternals* Internal;
 };
 
 // This is a table mapping XML tag IDE names to command line options

Index: cmLocalGenerator.cxx
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmLocalGenerator.cxx,v
retrieving revision 1.257
retrieving revision 1.258
diff -u -d -r1.257 -r1.258
--- cmLocalGenerator.cxx	19 Jan 2008 20:09:36 -0000	1.257
+++ cmLocalGenerator.cxx	22 Jan 2008 14:13:03 -0000	1.258
@@ -16,6 +16,7 @@
 =========================================================================*/
 #include "cmLocalGenerator.h"
 
+#include "cmComputeLinkInformation.h"
 #include "cmGeneratedFileStream.h"
 #include "cmGlobalGenerator.h"
 #include "cmInstallGenerator.h"
@@ -23,7 +24,6 @@
 #include "cmInstallScriptGenerator.h"
 #include "cmInstallTargetGenerator.h"
 #include "cmMakefile.h"
-#include "cmOrderLinkDirectories.h"
 #include "cmSourceFile.h"
 #include "cmTest.h"
 #include "cmake.h"
@@ -477,7 +477,7 @@
 }
 
 //----------------------------------------------------------------------------
-void cmLocalGenerator::GenerateTargetManifest(cmTargetManifest& manifest)
+void cmLocalGenerator::GenerateTargetManifest()
 {
   // Collect the set of configuration types.
   std::vector<std::string> configNames;
@@ -500,34 +500,17 @@
   for(cmTargets::iterator t = targets.begin(); t != targets.end(); ++t)
     {
     cmTarget& target = t->second;
-    cmTarget::TargetType type = target.GetType();
-    if(type == cmTarget::STATIC_LIBRARY ||
-       type == cmTarget::SHARED_LIBRARY ||
-       type == cmTarget::MODULE_LIBRARY ||
-       type == cmTarget::EXECUTABLE)
+    if(configNames.empty())
       {
-      if(configNames.empty())
-        {
-        manifest[""].insert(target.GetFullPath(0, false));
-        if(type == cmTarget::SHARED_LIBRARY &&
-           this->Makefile->GetDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX"))
-          {
-          manifest[""].insert(target.GetFullPath(0, true));
-          }
-        }
-      else
+      target.GenerateTargetManifest(0);
+      }
+    else
+      {
+      for(std::vector<std::string>::iterator ci = configNames.begin();
+          ci != configNames.end(); ++ci)
         {
-        for(std::vector<std::string>::iterator ci = configNames.begin();
-            ci != configNames.end(); ++ci)
-          {
-          const char* config = ci->c_str();
-          manifest[config].insert(target.GetFullPath(config, false));
-          if(type == cmTarget::SHARED_LIBRARY &&
-             this->Makefile->GetDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX"))
-            {
-            manifest[config].insert(target.GetFullPath(config, true));
-            }
-          }
+        const char* config = ci->c_str();
+        target.GenerateTargetManifest(config);
         }
       }
     }
@@ -1478,50 +1461,53 @@
   // collect all the flags needed for linking libraries
   linkLibs = "";
 
-  // Try to emit each search path once
-  std::set<cmStdString> emitted;
+  const char* config = this->Makefile->GetDefinition("CMAKE_BUILD_TYPE");
+
+  cmComputeLinkInformation cli(&tgt, config);
+  if(!cli.Compute())
+    {
+    return false;
+    }
+
+  const char* linkLanguage = cli.GetLinkLanguage();
+
   // Embed runtime search paths if possible and if required.
-  bool outputRuntime = true;
+  bool outputRuntime = !this->Makefile->IsOn("CMAKE_SKIP_RPATH");
+
+  // Lookup rpath specification flags.
   std::string runtimeFlag;
   std::string runtimeSep;
-
-  const char* config = this->Makefile->GetDefinition("CMAKE_BUILD_TYPE");
-  const char* linkLanguage = 
-      tgt.GetLinkerLanguage(this->GetGlobalGenerator());
-  if(!linkLanguage)
+  if(tgt.GetType() != cmTarget::STATIC_LIBRARY)
     {
-    cmSystemTools::
-      Error("CMake can not determine linker language for target:",
-            tgt.GetName());
-    return false;
+    std::string runTimeFlagVar = "CMAKE_";
+    if(tgt.GetType() == cmTarget::EXECUTABLE)
+      {
+      runTimeFlagVar += "EXECUTABLE";
+      }
+    else
+      {
+      runTimeFlagVar += "SHARED_LIBRARY";
+      }
+    runTimeFlagVar += "_RUNTIME_";
+    runTimeFlagVar += linkLanguage;
+    runTimeFlagVar += "_FLAG";
+    std::string runTimeFlagSepVar = runTimeFlagVar + "_SEP";
+    runtimeFlag = this->Makefile->GetSafeDefinition(runTimeFlagVar.c_str());
+    runtimeSep = this->Makefile->GetSafeDefinition(runTimeFlagSepVar.c_str());
     }
-  std::string runTimeFlagVar = "CMAKE_SHARED_LIBRARY_RUNTIME_";
-  runTimeFlagVar += linkLanguage;
-  runTimeFlagVar += "_FLAG";
-  std::string runTimeFlagSepVar = runTimeFlagVar + "_SEP";
-  runtimeFlag = this->Makefile->GetSafeDefinition(runTimeFlagVar.c_str());
-  runtimeSep = this->Makefile->GetSafeDefinition(runTimeFlagSepVar.c_str());
-  
   // concatenate all paths or no?
-  bool runtimeConcatenate = ( runtimeSep!="" );
-  if(runtimeFlag == "" || this->Makefile->IsOn("CMAKE_SKIP_RPATH"))
+  bool runtimeConcatenate = !runtimeSep.empty();
+
+  const char* runtimeAlways =
+    this->Makefile->GetDefinition("CMAKE_PLATFORM_REQUIRED_RUNTIME_PATH");
+
+  // Turn off rpath support if no flag is available to specify it.
+  if(runtimeFlag.empty())
     {
     outputRuntime = false;
+    runtimeAlways = 0;
     }
 
-  // Some search paths should never be emitted
-  emitted.insert("");
-  if(const char* implicitLinks =
-     (this->Makefile->GetDefinition
-      ("CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES")))
-    {
-    std::vector<std::string> implicitLinkVec;
-    cmSystemTools::ExpandListArgument(implicitLinks, implicitLinkVec);
-    for(unsigned int k = 0; k < implicitLinkVec.size(); ++k)
-      {
-      emitted.insert(implicitLinkVec[k]);
-      }
-    }
   std::string libPathFlag = 
     this->Makefile->GetRequiredDefinition("CMAKE_LIBRARY_PATH_FLAG");
   std::string libPathTerminator = 
@@ -1539,10 +1525,43 @@
     linkLibs += " ";
     }
 
-  // Compute the link library and directory information.
-  std::vector<cmStdString> libNames;
-  std::vector<cmStdString> libDirs;
-  this->ComputeLinkInformation(tgt, config, libNames, libDirs);
+  // Append the framework search path flags.
+  std::vector<std::string> const& fwDirs = cli.GetFrameworkPaths();
+  for(std::vector<std::string>::const_iterator fdi = fwDirs.begin();
+      fdi != fwDirs.end(); ++fdi)
+    {
+    linkLibs += "-F";
+    linkLibs += this->Convert(fdi->c_str(), NONE, SHELL, false);
+    linkLibs += " ";
+    }
+
+  // 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->c_str());
+    linkLibs += libPathFlag;
+    linkLibs += libpath;
+    linkLibs += libPathTerminator;
+    linkLibs += " ";
+    }
+
+  // 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->IsPath)
+      {
+      linkLibs += this->Convert(li->Value.c_str(), START_OUTPUT, SHELL);
+      }
+    else
+      {
+      linkLibs += li->Value;
+      }
+    linkLibs += " ";
+    }
 
   // Select whether to generate an rpath for the install tree or the
   // build tree.
@@ -1562,68 +1581,46 @@
     {
     const char* install_rpath = tgt.GetProperty("INSTALL_RPATH");
     cmSystemTools::ExpandListArgument(install_rpath, runtimeDirs);
-    for(unsigned int i=0; i < runtimeDirs.size(); ++i)
-      {
-      runtimeDirs[i] =
-        this->Convert(runtimeDirs[i].c_str(), FULL, SHELL, false);
-      }
     }
-
-  // Append the library search path flags.
-  for(std::vector<cmStdString>::const_iterator libDir = libDirs.begin();
-      libDir != libDirs.end(); ++libDir)
+  if(use_build_rpath || use_link_rpath)
     {
-   std::string libpath = this->ConvertToOutputForExisting(libDir->c_str());
-    if(emitted.insert(libpath).second)
+    std::vector<std::string> const& rdirs = cli.GetRuntimeSearchPath();
+    for(std::vector<std::string>::const_iterator ri = rdirs.begin();
+        ri != rdirs.end(); ++ri)
       {
-      std::string fullLibPath;
-      if(!this->WindowsShell && this->UseRelativePaths)
-        {
-        fullLibPath = "\"`cd ";
-        }
-      fullLibPath += libpath;
-      if(!this->WindowsShell && this->UseRelativePaths)
+      // Put this directory in the rpath if using build-tree rpath
+      // support or if using the link path as an rpath.
+      if(use_build_rpath)
         {
-        fullLibPath += ";pwd`\"";
+        runtimeDirs.push_back(*ri);
         }
-      std::string::size_type pos = libDir->find(libPathFlag.c_str());
-      if((pos == std::string::npos || pos > 0)
-         && libDir->find("${") == std::string::npos)
+      else if(use_link_rpath)
         {
-        linkLibs += libPathFlag;
-        linkLibs += fullLibPath;
-        linkLibs += libPathTerminator;
-        linkLibs += " ";
-
-        // Put this directory in the rpath if using build-tree rpath
-        // support or if using the link path as an rpath.
-        if(use_build_rpath)
-          {
-          runtimeDirs.push_back(fullLibPath);
-          }
-        else if(use_link_rpath)
+        // Do not add any path inside the source or build tree.
+        const char* topSourceDir = this->Makefile->GetHomeDirectory();
+        const char* topBinaryDir = this->Makefile->GetHomeOutputDirectory();
+        if(!cmSystemTools::ComparePath(ri->c_str(), topSourceDir) &&
+           !cmSystemTools::ComparePath(ri->c_str(), topBinaryDir) &&
+           !cmSystemTools::IsSubDirectory(ri->c_str(), topSourceDir) &&
+           !cmSystemTools::IsSubDirectory(ri->c_str(), topBinaryDir))
           {
-          // Do not add any path inside the source or build tree.
-          const char* topSourceDir = this->Makefile->GetHomeDirectory();
-          const char* topBinaryDir = this->Makefile->GetHomeOutputDirectory();
-          if(!cmSystemTools::ComparePath(libDir->c_str(), topSourceDir) &&
-             !cmSystemTools::ComparePath(libDir->c_str(), topBinaryDir) &&
-             !cmSystemTools::IsSubDirectory(libDir->c_str(), topSourceDir) &&
-             !cmSystemTools::IsSubDirectory(libDir->c_str(), topBinaryDir))
-            {
-            runtimeDirs.push_back(fullLibPath);
-            }
+          runtimeDirs.push_back(*ri);
           }
         }
       }
     }
+  if(runtimeAlways)
+    {
+    // Add runtime paths required by the platform to always be
+    // present.  This is done even when skipping rpath support.
+    cmSystemTools::ExpandListArgument(runtimeAlways, runtimeDirs);
+    }
 
-  // Append the link libraries.
-  for(std::vector<cmStdString>::iterator lib = libNames.begin();
-      lib != libNames.end(); ++lib)
+  // Convert the runtime directory names for use in the build file.
+  for(std::vector<std::string>::iterator ri = runtimeDirs.begin();
+      ri != runtimeDirs.end(); ++ri)
     {
-    linkLibs += *lib;
-    linkLibs += " ";
+    *ri = this->Convert(ri->c_str(), FULL, SHELL, false);
     }
 
   if(!runtimeDirs.empty())
@@ -1715,257 +1712,6 @@
 }
 
 //----------------------------------------------------------------------------
-void cmLocalGenerator
-::ComputeLinkInformation(cmTarget& target,
-                         const char* config,
-                         std::vector<cmStdString>& outLibs,
-                         std::vector<cmStdString>& outDirs,
-                         std::vector<cmStdString>* fullPathLibs)
-{
-  // Compute which library configuration to link.
-  cmTarget::LinkLibraryType linkType = cmTarget::OPTIMIZED;
-  if(config && cmSystemTools::UpperCase(config) == "DEBUG")
-    {
-    linkType = cmTarget::DEBUG;
-    }
-
-  // Get the language used for linking.
-  const char* linkLanguage =
-    target.GetLinkerLanguage(this->GetGlobalGenerator());
-
-  // Check whether we should use an import library for linking a target.
-  bool implib =
-    this->Makefile->GetDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX")?true:false;
-
-  // On platforms without import libraries there may be a special flag
-  // to use when creating a plugin (module) that obtains symbols from
-  // the program that will load it.
-  const char* loader_flag = 0;
-  if(!implib && target.GetType() == cmTarget::MODULE_LIBRARY)
-    {
-    if(!linkLanguage)
-      {
-      cmSystemTools::
-        Error("CMake can not determine linker language for target:",
-          target.GetName());
-      return;
-      }
-    std::string loader_flag_var = "CMAKE_SHARED_MODULE_LOADER_";
-    loader_flag_var += linkLanguage;
-    loader_flag_var += "_FLAG";
-    loader_flag = this->Makefile->GetDefinition(loader_flag_var.c_str());
-    }
-
-  // Get the list of libraries against which this target wants to link.
-  std::vector<std::string> linkLibraries;
-  const cmTarget::LinkLibraryVectorType& inLibs = target.GetLinkLibraries();
-  for(cmTarget::LinkLibraryVectorType::const_iterator j = inLibs.begin();
-      j != inLibs.end(); ++j)
-    {
-    // For backwards compatibility variables may have been expanded
-    // inside library names.  Clean up the resulting name.
-    std::string lib = j->first;
-    std::string::size_type pos = lib.find_first_not_of(" \t\r\n");
-    if(pos != lib.npos)
-      {
-      lib = lib.substr(pos, lib.npos);
-      }
-    pos = lib.find_last_not_of(" \t\r\n");
-    if(pos != lib.npos)
-      { 
-      lib = lib.substr(0, pos+1); 
-      }
-    if(lib.empty())
-      {
-      continue;
-      }
-    // Link to a library if it is not the same target and is meant for
-    // this configuration type.
-    if((target.GetType() == cmTarget::EXECUTABLE ||
-        lib != target.GetName()) &&
-       (j->second == cmTarget::GENERAL || j->second == linkType))
-      {
-      // Compute the proper name to use to link this library.
-      cmTarget* tgt = this->GlobalGenerator->FindTarget(0, lib.c_str(), false);
-      bool impexe = (tgt &&
-                     tgt->GetType() == cmTarget::EXECUTABLE &&
-                     tgt->GetPropertyAsBool("ENABLE_EXPORTS"));
-      if(impexe && !implib && !loader_flag)
-        {
-        // Skip linking to executables on platforms with no import
-        // libraries or loader flags.
-        continue;
-        }
-      else if(tgt && (tgt->GetType() == cmTarget::STATIC_LIBRARY ||
-                      tgt->GetType() == cmTarget::SHARED_LIBRARY ||
-                      tgt->GetType() == cmTarget::MODULE_LIBRARY ||
-                      impexe))
-        {
-        // This is a CMake target.  Ask the target for its real name.
-        std::string linkItem;
-        if(impexe && loader_flag)
-          {
-          // This link item is an executable that may provide symbols
-          // used by this target.  A special flag is needed on this
-          // platform.  Add it now.
-          std::string exe = tgt->GetFullPath(config, implib);
-          linkItem += loader_flag;
-          linkItem += this->Convert(exe.c_str(), NONE, SHELL, false);
-          }
-        else
-          {
-          // Pass the full path to the target file but purposely leave
-          // off the per-configuration subdirectory.  The link directory
-          // ordering knows how to deal with this.
-          linkItem += tgt->GetDirectory(0, implib);
-          // on apple if the FRAMEWORK prop is set, then
-          // do not add the target full name but just use the directory
-          // name
-#ifdef __APPLE__
-          if (!(tgt->GetType() == cmTarget::SHARED_LIBRARY &&
-                tgt->GetPropertyAsBool("FRAMEWORK")))
-#endif
-            { 
-            linkItem += "/";
-            linkItem += tgt->GetFullName(config, implib);
-            }
-          }
-        linkLibraries.push_back(linkItem);
-        // For full path, use the true location.
-        if(fullPathLibs)
-          {
-          fullPathLibs->push_back(tgt->GetFullPath(config, implib));
-          }
-        }
-      else
-        {
-        // This is not a CMake target.  Use the name given.
-        linkLibraries.push_back(lib);
-
-        // Add to the list of full paths if this library is one.
-        if(fullPathLibs &&
-           cmSystemTools::FileIsFullPath(lib.c_str()) &&
-           !cmSystemTools::FileIsDirectory(lib.c_str()))
-          {
-          fullPathLibs->push_back(lib);
-          }
-        }
-      }
-    }
-
-  // Get the list of directories the target wants to search for libraries.
-  const std::vector<std::string>&
-    linkDirectories = target.GetLinkDirectories();
-
-  // Lookup link type selection flags.
-  const char* static_link_type_flag = 0;
-  const char* shared_link_type_flag = 0;
-  const char* target_type_str = 0;
-  switch(target.GetType())
-    {
-    case cmTarget::EXECUTABLE:     target_type_str = "EXE"; break;
-    case cmTarget::SHARED_LIBRARY: target_type_str = "SHARED_LIBRARY"; break;
-    case cmTarget::MODULE_LIBRARY: target_type_str = "SHARED_MODULE"; break;
-    default: break;
-    }
-  if(target_type_str)
-    {
-    if(!linkLanguage)
-      {
-      cmSystemTools::
-        Error("CMake can not determine linker language for target:",
-          target.GetName());
-      return;
-      }
-    std::string static_link_type_flag_var = "CMAKE_";
-    static_link_type_flag_var += target_type_str;
-    static_link_type_flag_var += "_LINK_STATIC_";
-    static_link_type_flag_var += linkLanguage;
-    static_link_type_flag_var += "_FLAGS";
-    static_link_type_flag =
-      this->Makefile->GetDefinition(static_link_type_flag_var.c_str());
-
-    std::string shared_link_type_flag_var = "CMAKE_";
-    shared_link_type_flag_var += target_type_str;
-    shared_link_type_flag_var += "_LINK_DYNAMIC_";
-    shared_link_type_flag_var += linkLanguage;
-    shared_link_type_flag_var += "_FLAGS";
-    shared_link_type_flag =
-      this->Makefile->GetDefinition(shared_link_type_flag_var.c_str());
-    }
-
-  // Compute the link directory order needed to link the libraries.
-  cmOrderLinkDirectories orderLibs;
-  orderLibs.SetLinkTypeInformation(cmOrderLinkDirectories::LinkShared,
-                                   static_link_type_flag,
-                                   shared_link_type_flag);
-  orderLibs.AddLinkPrefix(
-    this->Makefile->GetDefinition("CMAKE_STATIC_LIBRARY_PREFIX"));
-  orderLibs.AddLinkPrefix(
-    this->Makefile->GetDefinition("CMAKE_SHARED_LIBRARY_PREFIX"));
-
-  // Import library names should be matched and treated as shared
-  // libraries for the purposes of linking.
-  orderLibs.AddLinkExtension(
-    this->Makefile->GetDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX"),
-    cmOrderLinkDirectories::LinkShared);
-  orderLibs.AddLinkExtension(
-    this->Makefile->GetDefinition("CMAKE_STATIC_LIBRARY_SUFFIX"),
-    cmOrderLinkDirectories::LinkStatic);
-  orderLibs.AddLinkExtension(
-    this->Makefile->GetDefinition("CMAKE_SHARED_LIBRARY_SUFFIX"),
-    cmOrderLinkDirectories::LinkShared);
-  orderLibs.AddLinkExtension(
-    this->Makefile->GetDefinition("CMAKE_LINK_LIBRARY_SUFFIX"));
-  if(const char* linkSuffixes =
-     this->Makefile->GetDefinition("CMAKE_EXTRA_LINK_EXTENSIONS"))
-    {
-    std::vector<std::string> linkSuffixVec;
-    cmSystemTools::ExpandListArgument(linkSuffixes, linkSuffixVec);
-    for(std::vector<std::string>::iterator i = linkSuffixVec.begin();
-        i != linkSuffixVec.end(); ++i)
-      {
-      orderLibs.AddLinkExtension(i->c_str());
-      }
-    }
-  std::string configSubdir;
-  cmGlobalGenerator* gg = this->GetGlobalGenerator();
-  gg->AppendDirectoryForConfig("", config, "", configSubdir);
-  orderLibs.SetLinkInformation(target.GetName(),
-                               linkLibraries,
-                               linkDirectories,
-                               gg->GetTargetManifest(),
-                               configSubdir.c_str());
-  orderLibs.DetermineLibraryPathOrder();
-  std::vector<cmStdString> orderedLibs;
-  orderLibs.GetLinkerInformation(outDirs, orderedLibs);
-
-  // Make sure libraries are linked with the proper syntax.
-  std::string libLinkFlag =
-    this->Makefile->GetSafeDefinition("CMAKE_LINK_LIBRARY_FLAG");
-  std::string libLinkSuffix =
-    this->Makefile->GetSafeDefinition("CMAKE_LINK_LIBRARY_SUFFIX");
-  for(std::vector<cmStdString>::iterator l = orderedLibs.begin();
-      l != orderedLibs.end(); ++l)
-    {
-    std::string lib = *l;
-    if(lib[0] == '-' || lib[0] == '$' || lib[0] == '`')
-      {
-      // The library is linked with special syntax by the user.
-      outLibs.push_back(lib);
-      }
-    else
-      {
-      // Generate the proper link syntax.
-      lib = libLinkFlag;
-      lib += *l;
-      lib += libLinkSuffix;
-      outLibs.push_back(lib);
-      }
-    }
-}
-
-//----------------------------------------------------------------------------
 void cmLocalGenerator::AddLanguageFlags(std::string& flags,
                                         const char* lang,
                                         const char* config)

Index: cmGlobalXCodeGenerator.cxx
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmGlobalXCodeGenerator.cxx,v
retrieving revision 1.179
retrieving revision 1.180
diff -u -d -r1.179 -r1.180
--- cmGlobalXCodeGenerator.cxx	18 Jan 2008 00:29:43 -0000	1.179
+++ cmGlobalXCodeGenerator.cxx	22 Jan 2008 14:13:03 -0000	1.180
@@ -22,6 +22,7 @@
 #include "cmXCode21Object.h"
 #include "cmake.h"
 #include "cmGeneratedFileStream.h"
+#include "cmComputeLinkInformation.h"
 #include "cmSourceFile.h"
 
 //----------------------------------------------------------------------------
@@ -2107,23 +2108,27 @@
       }
 
     // Compute the link library and directory information.
-    std::vector<cmStdString> libNames;
-    std::vector<cmStdString> libDirs;
-    std::vector<cmStdString> fullPathLibs;
-    this->CurrentLocalGenerator->ComputeLinkInformation(*cmtarget, configName,
-                                                    libNames, libDirs,
-                                                    &fullPathLibs);
+    cmComputeLinkInformation cli(cmtarget, configName);
+    if(!cli.Compute())
+      {
+      continue;
+      }
 
     // Add dependencies directly on library files.
-    for(std::vector<cmStdString>::iterator j = fullPathLibs.begin();
-        j != fullPathLibs.end(); ++j)
+    {
+    std::vector<std::string> const& libDeps = cli.GetDepends();
+    for(std::vector<std::string>::const_iterator j = libDeps.begin();
+        j != libDeps.end(); ++j)
       {
       target->AddDependLibrary(configName, j->c_str());
       }
+    }
 
-    std::string linkDirs;
     // add the library search paths
-    for(std::vector<cmStdString>::const_iterator libDir = libDirs.begin();
+    {
+    std::vector<std::string> const& libDirs = cli.GetDirectories();
+    std::string linkDirs;
+    for(std::vector<std::string>::const_iterator libDir = libDirs.begin();
         libDir != libDirs.end(); ++libDir)
       {
       if(libDir->size() && *libDir != "/usr/lib")
@@ -2141,45 +2146,50 @@
       }
     this->AppendBuildSettingAttribute(target, "LIBRARY_SEARCH_PATHS",
                                       linkDirs.c_str(), configName);
+    }
+
+    // add the framework search paths
+    {
+    const char* sep = "";
+    std::string fdirs;
+    std::vector<std::string> const& fwDirs = cli.GetFrameworkPaths();
+    for(std::vector<std::string>::const_iterator fdi = fwDirs.begin();
+        fdi != fwDirs.end(); ++fdi)
+      {
+      fdirs += sep;
+      sep = " ";
+      fdirs += this->XCodeEscapePath(fdi->c_str());
+      }
+    if(!fdirs.empty())
+      {
+      this->AppendBuildSettingAttribute(target, "FRAMEWORK_SEARCH_PATHS",
+                                        fdirs.c_str(), configName);
+      }
+    }
+
     // now add the link libraries
     if(cmtarget->GetType() != cmTarget::STATIC_LIBRARY)
       {
-      std::string fdirs;
-      std::set<cmStdString> emitted;
-      emitted.insert("/System/Library/Frameworks");
-      for(std::vector<cmStdString>::iterator lib = libNames.begin();
-          lib != libNames.end(); ++lib)
+      std::string linkLibs;
+      const char* sep = "";
+      typedef cmComputeLinkInformation::ItemVector ItemVector;
+      ItemVector const& libNames = cli.GetItems();
+      for(ItemVector::const_iterator li = libNames.begin();
+          li != libNames.end(); ++li)
         {
-        std::string& libString = *lib;
-        // check to see if this is a -F framework path and extract it if it is
-        // -F framework stuff should be in the FRAMEWORK_SEARCH_PATHS and not
-        // OTHER_LDFLAGS
-        if(libString.size() > 2 && libString[0] == '-'
-           && libString[1] == 'F')
+        linkLibs += sep;
+        sep = " ";
+        if(li->IsPath)
           {
-          std::string path = libString.substr(2);
-          // remove escaped spaces from the path
-          cmSystemTools::ReplaceString(path, "\\ ", " ");
-          if(emitted.insert(path).second)
-            {
-            if(fdirs.size())
-              {
-              fdirs += " ";
-              }
-            fdirs += this->XCodeEscapePath(path.c_str());
-            }
+          linkLibs += this->XCodeEscapePath(li->Value.c_str());
           }
         else
           {
-          this->AppendBuildSettingAttribute(target, "OTHER_LDFLAGS",
-                                            lib->c_str(), configName);
+          linkLibs += li->Value;
           }
         }
-      if(fdirs.size())
-        {
-        this->AppendBuildSettingAttribute(target, "FRAMEWORK_SEARCH_PATHS",
-                                          fdirs.c_str(), configName);
-        }
+      this->AppendBuildSettingAttribute(target, "OTHER_LDFLAGS",
+                                        linkLibs.c_str(), configName);
       }
     }
 }

Index: cmGlobalGenerator.h
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmGlobalGenerator.h,v
retrieving revision 1.101
retrieving revision 1.102
diff -u -d -r1.101 -r1.102
--- cmGlobalGenerator.h	23 Dec 2007 20:03:42 -0000	1.101
+++ cmGlobalGenerator.h	22 Jan 2008 14:13:03 -0000	1.102
@@ -150,6 +150,9 @@
   ///! Get the export target set with the   given name
   const std::vector<cmTargetExport*>* GetExportSet(const char* name) const;
 
+  /** Add a file to the manifest of generated targets for a configuration.  */
+  void AddToManifest(const char* config, std::string const& f);
+
   void EnableInstallTarget();
 
   int TryCompileTimeout;
@@ -209,6 +212,13 @@
       configuration.  This is valid during generation only.  */
   cmTargetManifest const& GetTargetManifest() { return this->TargetManifest; }
 
+  /** Get the content of a directory on disk including the target
+      files to be generated.  This may be called only during the
+      generation step.  It is intended for use only by
+      cmComputeLinkInformation.  */
+  std::set<cmStdString> const& GetDirectoryContent(std::string const& dir,
+                                                   bool needDisk);
+
   void AddTarget(cmTargets::value_type &v);
 
   virtual const char* GetAllTargetName()          { return "ALL_BUILD"; }
@@ -304,6 +314,17 @@
                       std::vector<cmTarget const*>& steps);
   typedef std::map<cmTarget const*, TargetDependSet> TargetDependMap;
   TargetDependMap TargetDependencies;
+
+  // Cache directory content and target files to be built.
+  struct DirectoryContent: public std::set<cmStdString>
+  {
+    typedef std::set<cmStdString> derived;
+    bool LoadedFromDisk;
+    DirectoryContent(): LoadedFromDisk(false) {}
+    DirectoryContent(DirectoryContent const& dc):
+      derived(dc), LoadedFromDisk(dc.LoadedFromDisk) {}
+  };
+  std::map<cmStdString, DirectoryContent> DirectoryContentMap;
 };
 
 #endif

--- NEW FILE: cmComputeLinkInformation.cxx ---
/*=========================================================================

  Program:   CMake - Cross-Platform Makefile Generator
  Module:    $RCSfile: cmComputeLinkInformation.cxx,v $
  Language:  C++
  Date:      $Date: 2008/01/22 14:13:03 $
  Version:   $Revision: 1.1 $

  Copyright (c) 2002 Kitware, Inc., Insight Consortium.  All rights reserved.
  See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include "cmComputeLinkInformation.h"

#include "cmGlobalGenerator.h"
[...1118 lines suppressed...]
    RuntimeConflictList const& clist = this->RuntimeConflictGraph[i];
    e << "dir " << i << " is [" << this->RuntimeDirectories[i] << "]\n";
    for(RuntimeConflictList::const_iterator j = clist.begin();
        j != clist.end(); ++j)
      {
      e << "  dir " << j->first << " must precede it due to [";
      LibraryRuntimeEntry const& re = this->LibraryRuntimeInfo[j->second];
      if(re.SOName.empty())
        {
        e << re.FileName;
        }
      else
        {
        e << re.SOName;
        }
      e << "]\n";
      }
    }
  cmSystemTools::Message(e.str().c_str());
}

--- cmOrderLinkDirectories.h DELETED ---

Index: cmGlobalGenerator.cxx
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmGlobalGenerator.cxx,v
retrieving revision 1.217
retrieving revision 1.218
diff -u -d -r1.217 -r1.218
--- cmGlobalGenerator.cxx	31 Dec 2007 22:29:20 -0000	1.217
+++ cmGlobalGenerator.cxx	22 Jan 2008 14:13:03 -0000	1.218
@@ -27,6 +27,8 @@
 #include "cmVersion.h"
 #include "cmInstallExportGenerator.h"
 
+#include <cmsys/Directory.hxx>
+
 #include <stdlib.h> // required for atof
 
 #include <assert.h>
@@ -784,7 +786,7 @@
   // Compute the manifest of main targets generated.
   for (i = 0; i < this->LocalGenerators.size(); ++i)
     {
-    this->LocalGenerators[i]->GenerateTargetManifest(this->TargetManifest);
+    this->LocalGenerators[i]->GenerateTargetManifest();
     }
 
   // Create a map from local generator to the complete set of targets
@@ -1880,3 +1882,42 @@
     this->FilesReplacedDuringGenerate.end(),
     std::back_inserter(filenames));
 }
+
+//----------------------------------------------------------------------------
+void cmGlobalGenerator::AddToManifest(const char* config,
+                                      std::string const& f)
+{
+  // Add to the main manifest for this configuration.
+  this->TargetManifest[config].insert(f);
+
+  // Add to the content listing for the file's directory.
+  std::string dir = cmSystemTools::GetFilenamePath(f);
+  std::string file = cmSystemTools::GetFilenameName(f);
+  this->DirectoryContentMap[dir].insert(file);
+}
+
+//----------------------------------------------------------------------------
+std::set<cmStdString> const&
+cmGlobalGenerator::GetDirectoryContent(std::string const& dir, bool needDisk)
+{
+  DirectoryContent& dc = this->DirectoryContentMap[dir];
+  if(needDisk && !dc.LoadedFromDisk)
+    {
+    // Load the directory content from disk.
+    cmsys::Directory d;
+    if(d.Load(dir.c_str()))
+      {
+      unsigned long n = d.GetNumberOfFiles();
+      for(unsigned long i = 0; i < n; ++i)
+        {
+        const char* f = d.GetFile(i);
+        if(strcmp(f, ".") != 0 && strcmp(f, "..") != 0)
+          {
+          dc.insert(f);
+          }
+        }
+      }
+    dc.LoadedFromDisk = true;
+    }
+  return dc;
+}

Index: cmLocalVisualStudio6Generator.cxx
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmLocalVisualStudio6Generator.cxx,v
retrieving revision 1.137
retrieving revision 1.138
diff -u -d -r1.137 -r1.138
--- cmLocalVisualStudio6Generator.cxx	18 Jan 2008 00:29:43 -0000	1.137
+++ cmLocalVisualStudio6Generator.cxx	22 Jan 2008 14:13:03 -0000	1.138
@@ -22,6 +22,8 @@
 #include "cmCacheManager.h"
 #include "cmake.h"
 
+#include "cmComputeLinkInformation.h"
+
 #include <cmsys/RegularExpression.hxx>
 
 cmLocalVisualStudio6Generator::cmLocalVisualStudio6Generator()
@@ -1569,12 +1571,17 @@
                      std::string& options)
 {
   // Compute the link information for this configuration.
-  std::vector<cmStdString> linkLibs;
-  std::vector<cmStdString> linkDirs;
-  this->ComputeLinkInformation(target, configName, linkLibs, linkDirs);
+  cmComputeLinkInformation cli(&target, configName);
+  if(!cli.Compute())
+    {
+    return;
+    }
+  typedef cmComputeLinkInformation::ItemVector ItemVector;
+  ItemVector const& linkLibs = cli.GetItems();
+  std::vector<std::string> const& linkDirs = cli.GetDirectories();
 
   // Build the link options code.
-  for(std::vector<cmStdString>::const_iterator d = linkDirs.begin();
+  for(std::vector<std::string>::const_iterator d = linkDirs.begin();
       d != linkDirs.end(); ++d)
     {
     std::string dir = *d;
@@ -1592,11 +1599,19 @@
       options += "\n";
       }
     }
-  for(std::vector<cmStdString>::const_iterator l = linkLibs.begin();
+  for(ItemVector::const_iterator l = linkLibs.begin();
       l != linkLibs.end(); ++l)
     {
     options += "# ADD LINK32 ";
-    options += this->ConvertToOptionallyRelativeOutputPath(l->c_str());
+    if(l->IsPath)
+      {
+      options +=
+        this->ConvertToOptionallyRelativeOutputPath(l->Value.c_str());
+      }
+    else
+      {
+      options += l->Value;
+      }
     options += "\n";
     }
 

Index: cmDocumentVariables.cxx
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmDocumentVariables.cxx,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -d -r1.9 -r1.10
--- cmDocumentVariables.cxx	21 Jan 2008 23:30:17 -0000	1.9
+++ cmDocumentVariables.cxx	22 Jan 2008 14:13:03 -0000	1.10
@@ -1035,6 +1035,12 @@
                      cmProperty::VARIABLE,0,0);
   cm->DefineProperty("CMAKE_SHARED_LIBRARY_RUNTIME_<LANG>_FLAG_SEP",
                      cmProperty::VARIABLE,0,0);
+  cm->DefineProperty("CMAKE_EXECUTABLE_RUNTIME_<LANG>_FLAG",
+                     cmProperty::VARIABLE,0,0);
+  cm->DefineProperty("CMAKE_EXECUTABLE_RUNTIME_<LANG>_FLAG_SEP",
+                     cmProperty::VARIABLE,0,0);
+  cm->DefineProperty("CMAKE_PLATFORM_REQUIRED_RUNTIME_PATH",
+                     cmProperty::VARIABLE,0,0);
   cm->DefineProperty("CMAKE_SHARED_MODULE_CREATE_<LANG>_FLAGS",
                      cmProperty::VARIABLE,0,0);
   cm->DefineProperty("CMAKE_SHARED_MODULE_<LANG>_FLAGS",

--- cmOrderLinkDirectories.cxx DELETED ---

Index: cmTarget.h
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmTarget.h,v
retrieving revision 1.95
retrieving revision 1.96
diff -u -d -r1.95 -r1.96
--- cmTarget.h	17 Jan 2008 23:13:55 -0000	1.95
+++ cmTarget.h	22 Jan 2008 14:13:03 -0000	1.96
@@ -271,6 +271,9 @@
                                std::string& impName,
                                std::string& pdbName, const char* config);
 
+  /** Add the target output files to the global generator manifest.  */
+  void GenerateTargetManifest(const char* config);
+
   /**
    * Compute whether this target must be relinked before installing.
    */
@@ -414,10 +417,9 @@
   LinkLibraryVectorType LinkLibraries;
   LinkLibraryVectorType PrevLinkedLibraries;
   bool LinkLibrariesAnalyzed;
-  bool LinkDirectoriesComputed;
   std::vector<std::string> Frameworks;
   std::vector<std::string> LinkDirectories;
-  std::vector<std::string> ExplicitLinkDirectories;
+  std::set<cmStdString> LinkDirectoriesEmmitted;
   bool HaveInstallRule;
   std::string InstallNameFixupPath;
   std::string InstallPath;

Index: CMakeLists.txt
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/CMakeLists.txt,v
retrieving revision 1.386
retrieving revision 1.387
diff -u -d -r1.386 -r1.387
--- CMakeLists.txt	17 Dec 2007 19:43:11 -0000	1.386
+++ CMakeLists.txt	22 Jan 2008 14:13:03 -0000	1.387
@@ -87,6 +87,8 @@
   cmCommandArgumentLexer.cxx
   cmCommandArgumentParser.cxx
   cmCommandArgumentParserHelper.cxx
+  cmComputeLinkInformation.cxx
+  cmComputeLinkInformation.h
   cmCustomCommand.cxx
   cmCustomCommand.h
   cmDepends.cxx
@@ -151,7 +153,6 @@
   cmMakefileExecutableTargetGenerator.cxx
   cmMakefileLibraryTargetGenerator.cxx
   cmMakefileUtilityTargetGenerator.cxx
-  cmOrderLinkDirectories.cxx
   cmProperty.cxx
   cmProperty.h
   cmPropertyDefinition.cxx

--- NEW FILE: cmComputeLinkInformation.h ---
/*=========================================================================

  Program:   CMake - Cross-Platform Makefile Generator
  Module:    $RCSfile: cmComputeLinkInformation.h,v $
  Language:  C++
  Date:      $Date: 2008/01/22 14:13:03 $
  Version:   $Revision: 1.1 $

  Copyright (c) 2002 Kitware, Inc., Insight Consortium.  All rights reserved.
  See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#ifndef cmComputeLinkInformation_h
#define cmComputeLinkInformation_h

#include "cmStandardIncludes.h"

#include <cmsys/RegularExpression.hxx>

class cmGlobalGenerator;
class cmLocalGenerator;
class cmMakefile;
class cmTarget;

/** \class cmComputeLinkInformation
 * \brief Compute link information for a target in one configuration.
 */
class cmComputeLinkInformation
{
public:
  cmComputeLinkInformation(cmTarget* target, const char* config);
  bool Compute();

  struct Item
  {
    Item(): Value(), IsPath(true) {}
    Item(Item const& item): Value(item.Value), IsPath(item.IsPath) {}
    Item(std::string const& v, bool p): Value(v), IsPath(p) {}
    std::string Value;
    bool IsPath;
  };
  typedef std::vector<Item> ItemVector;
  ItemVector const& GetItems();
  std::vector<std::string> const& GetDirectories();
  std::vector<std::string> const& GetDepends();
  std::vector<std::string> const& GetFrameworkPaths();
  const char* GetLinkLanguage() const { return this->LinkLanguage; }
  std::vector<std::string> const& GetRuntimeSearchPath();
private:
  void AddItem(std::string const& item);

  // Output information.
  ItemVector Items;
  std::vector<std::string> Directories;
  std::vector<std::string> Depends;
  std::vector<std::string> FrameworkPaths;
  std::vector<std::string> RuntimeSearchPath;

  // Context information.
  cmTarget* Target;
  cmMakefile* Makefile;
  cmLocalGenerator* LocalGenerator;
  cmGlobalGenerator* GlobalGenerator;

  // Configuration information.
  const char* Config;
  const char* LinkLanguage;

  // System info.
  bool UseImportLibrary;
  const char* LoaderFlag;
  std::string LibLinkFlag;
  std::string LibLinkSuffix;

  // Link type adjustment.
  void ComputeLinkTypeInfo();
  enum LinkType { LinkUnknown, LinkStatic, LinkShared };
  LinkType StartLinkType;
  LinkType CurrentLinkType;
  std::string StaticLinkTypeFlag;
  std::string SharedLinkTypeFlag;
  bool LinkTypeEnabled;
  void SetCurrentLinkType(LinkType lt);

  // Link item parsing.
  void ComputeItemParserInfo();
  std::vector<std::string> StaticLinkExtensions;
  std::vector<std::string> SharedLinkExtensions;
  std::vector<std::string> LinkExtensions;
  std::set<cmStdString> LinkPrefixes;
  cmsys::RegularExpression RemoveLibraryExtension;
  cmsys::RegularExpression ExtractStaticLibraryName;
  cmsys::RegularExpression ExtractSharedLibraryName;
  cmsys::RegularExpression ExtractAnyLibraryName;
  void AddLinkPrefix(const char* p);
  void AddLinkExtension(const char* e, LinkType type);
  std::string CreateExtensionRegex(std::vector<std::string> const& exts);
  std::string NoCaseExpression(const char* str);

  // Handling of link items that are not targets or full file paths.
  void AddUserItem(std::string const& item);
  void AddDirectoryItem(std::string const& item);
  void AddFrameworkItem(std::string const& item);
  void DropDirectoryItem(std::string const& item);

  // Framework info.
  void ComputeFrameworkInfo();
  void AddFrameworkPath(std::string const& p);
  std::set<cmStdString> FrameworkPathsEmmitted;
  cmsys::RegularExpression SplitFramework;

  // Linker search path computation.
  void ComputeLinkerSearchDirectories();
  void AddLinkerSearchDirectories(std::vector<std::string> const& dirs);
  std::set<cmStdString> DirectoriesEmmitted;

  // Runtime path computation.
  struct LibraryRuntimeEntry
  {
    // The file name of the library.
    std::string FileName;

    // The soname of the shared library if it is known.
    std::string SOName;

    // The directory in which the library is supposed to be found.
    std::string Directory;

    // The index assigned to the directory.
    int DirectoryIndex;
  };
  bool RuntimeSearchPathComputed;
  std::vector<LibraryRuntimeEntry> LibraryRuntimeInfo;
  std::set<cmStdString> LibraryRuntimeInfoEmmitted;
  std::vector<std::string> RuntimeDirectories;
  std::map<cmStdString, int> RuntimeDirectoryIndex;
  std::vector<char> RuntimeDirectoryVisited;
  void AddLibraryRuntimeInfo(std::string const& fullPath, cmTarget* target);
  void AddLibraryRuntimeInfo(std::string const& fullPath,
                             const char* soname = 0);
  void CollectRuntimeDirectories();
  int AddRuntimeDirectory(std::string const& dir);
  void FindConflictingLibraries();
  void FindDirectoriesForLib(unsigned int lri);
  void OrderRuntimeSearchPath();
  void VisitRuntimeDirectory(unsigned int i, bool top);
  void DiagnoseCycle();
  bool CycleDiagnosed;

  // Adjacency-list representation of runtime path ordering graph.
  // This maps from directory to those that must come *before* it.
  // Each entry that must come before is a pair.  The first element is
  // the index of the directory that must come first.  The second
  // element is the index of the runtime library that added the
  // constraint.
  typedef std::pair<int, int> RuntimeConflictPair;
  struct RuntimeConflictList: public std::vector<RuntimeConflictPair> {};
  std::vector<RuntimeConflictList> RuntimeConflictGraph;
};

#endif

Index: cmLocalGenerator.h
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmLocalGenerator.h,v
retrieving revision 1.98
retrieving revision 1.99
diff -u -d -r1.98 -r1.99
--- cmLocalGenerator.h	18 Jan 2008 00:58:01 -0000	1.98
+++ cmLocalGenerator.h	22 Jan 2008 14:13:03 -0000	1.99
@@ -75,7 +75,7 @@
   /**
    * Generate a manifest of target files that will be built.
    */
-  virtual void GenerateTargetManifest(cmTargetManifest&);
+  virtual void GenerateTargetManifest();
 
   ///! Get the makefile for this generator
   cmMakefile *GetMakefile() {
@@ -174,13 +174,6 @@
                                   bool /*color*/)
     { return true; }
 
-  /** Compute the list of link libraries and directories for the given
-      target and configuration.  */
-  void ComputeLinkInformation(cmTarget& target, const char* config,
-                              std::vector<cmStdString>& outLibs,
-                              std::vector<cmStdString>& outDirs,
-                              std::vector<cmStdString>* fullPathLibs=0);
-
   /** Get the include flags for the current makefile and language.  */
   void GetIncludeDirectories(std::vector<std::string>& dirs,
                              bool filter_system_dirs = true);

Index: cmTarget.cxx
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmTarget.cxx,v
retrieving revision 1.177
retrieving revision 1.178
diff -u -d -r1.177 -r1.178
--- cmTarget.cxx	21 Jan 2008 18:59:10 -0000	1.177
+++ cmTarget.cxx	22 Jan 2008 14:13:03 -0000	1.178
@@ -35,7 +35,6 @@
 {
   this->Makefile = 0;
   this->LinkLibrariesAnalyzed = false;
-  this->LinkDirectoriesComputed = false;
   this->HaveInstallRule = false;
   this->DLLPlatform = false;
   this->IsImportedTarget = false;
@@ -843,71 +842,15 @@
 void cmTarget::AddLinkDirectory(const char* d)
 {
   // Make sure we don't add unnecessary search directories.
-  if(std::find(this->ExplicitLinkDirectories.begin(),
-               this->ExplicitLinkDirectories.end(), d)
-     == this->ExplicitLinkDirectories.end() )
+  if(this->LinkDirectoriesEmmitted.insert(d).second)
     {
-    this->ExplicitLinkDirectories.push_back( d );
-    this->LinkDirectoriesComputed = false;
+    this->LinkDirectories.push_back(d);
     }
 }
 
 //----------------------------------------------------------------------------
 const std::vector<std::string>& cmTarget::GetLinkDirectories()
 {
-  // Make sure all library dependencies have been analyzed.
-  if(!this->LinkLibrariesAnalyzed && !this->LinkLibraries.empty())
-    {
-    cmSystemTools::Error(
-      "cmTarget::GetLinkDirectories called before "
-      "cmTarget::AnalyzeLibDependencies on target ",
-      this->Name.c_str());
-    }
-
-  // Make sure the complete set of link directories has been computed.
-  if(!this->LinkDirectoriesComputed)
-    {
-    // Check whether we should use an import library for linking a target.
-    bool implib =
-      this->Makefile->GetDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX") != 0;
-
-    // Compute the full set of link directories including the
-    // locations of targets that have been linked in.  Start with the
-    // link directories given explicitly.
-    this->LinkDirectories = this->ExplicitLinkDirectories;
-    for(LinkLibraryVectorType::iterator ll = this->LinkLibraries.begin();
-        ll != this->LinkLibraries.end(); ++ll)
-      {
-      // If this library is a CMake target then add its location as a
-      // link directory.
-      std::string lib = ll->first;
-      cmTarget* tgt = 0;
-      if(this->Makefile && this->Makefile->GetLocalGenerator() &&
-         this->Makefile->GetLocalGenerator()->GetGlobalGenerator())
-        {
-        tgt = (this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
-               ->FindTarget(0, lib.c_str(), false));
-        }
-      if(tgt)
-        {
-        // Add the directory only if it is not already present.  This
-        // is an N^2 algorithm for adding the directories, but N
-        // should not get very big.
-        const char* libpath = tgt->GetDirectory(0, implib);
-        if(std::find(this->LinkDirectories.begin(),
-                     this->LinkDirectories.end(),
-                     libpath) == this->LinkDirectories.end())
-          {
-          this->LinkDirectories.push_back(libpath);
-          }
-        }
-      }
-
-    // The complete set of link directories has now been computed.
-    this->LinkDirectoriesComputed = true;
-    }
-
-  // Return the complete set of link directories.
   return this->LinkDirectories;
 }
 
@@ -2245,6 +2188,76 @@
 }
 
 //----------------------------------------------------------------------------
+void cmTarget::GenerateTargetManifest(const char* config)
+{
+  cmMakefile* mf = this->Makefile;
+  cmLocalGenerator* lg = mf->GetLocalGenerator();
+  cmGlobalGenerator* gg = lg->GetGlobalGenerator();
+
+  // Get the names.
+  std::string name;
+  std::string soName;
+  std::string realName;
+  std::string impName;
+  std::string pdbName;
+  if(this->GetType() == cmTarget::EXECUTABLE)
+    {
+    this->GetExecutableNames(name, realName, impName, pdbName, config);
+    }
+  else if(this->GetType() == cmTarget::STATIC_LIBRARY ||
+          this->GetType() == cmTarget::SHARED_LIBRARY ||
+          this->GetType() == cmTarget::MODULE_LIBRARY)
+    {
+    this->GetLibraryNames(name, soName, realName, impName, pdbName, config);
+    }
+  else
+    {
+    return;
+    }
+
+  // Get the directory.
+  std::string dir = this->GetDirectory(config, false);
+
+  // Add each name.
+  std::string f;
+  if(!name.empty())
+    {
+    f = dir;
+    f += "/";
+    f += name;
+    gg->AddToManifest(config? config:"", f);
+    }
+  if(!soName.empty())
+    {
+    f = dir;
+    f += "/";
+    f += soName;
+    gg->AddToManifest(config? config:"", f);
+    }
+  if(!realName.empty())
+    {
+    f = dir;
+    f += "/";
+    f += realName;
+    gg->AddToManifest(config? config:"", f);
+    }
+  if(!pdbName.empty())
+    {
+    f = dir;
+    f += "/";
+    f += pdbName;
+    gg->AddToManifest(config? config:"", f);
+    }
+  if(!impName.empty())
+    {
+    f = this->GetDirectory(config, true);
+    f += "/";
+    f += impName;
+    gg->AddToManifest(config? config:"", f);
+    }
+}
+
+//----------------------------------------------------------------------------
 void cmTarget::SetPropertyDefault(const char* property,
                                   const char* default_value)
 {



More information about the Cmake-commits mailing list