From 5594ad488576a77d9c6b8c3c1999a04fb4e6867d Mon Sep 17 00:00:00 2001
From: Brad King <brad.king@kitware.com>
Date: Mon, 28 Jan 2008 08:38:36 -0500
Subject: ENH: Updated exporting and importing of targets to support libraries
 and configurations.

  - Created cmExportFileGenerator hierarchy to implement export file generation
  - Installed exports use per-config import files loaded by a central one.
  - Include soname of shared libraries in import information
  - Renamed PREFIX to NAMESPACE in INSTALL(EXPORT) and EXPORT() commands
  - Move addition of CMAKE_INSTALL_PREFIX to destinations to install generators
  - Import files compute the installation prefix relative to their location when loaded
  - Add mapping of importer configurations to importee configurations
  - Rename IMPORT targets to IMPORTED targets to distinguish from windows import libraries
  - Scope IMPORTED targets within directories to isolate them
  - Place all properties created by import files in the IMPORTED namespace
  - Document INSTALL(EXPORT) and EXPORT() commands.
  - Document IMPORTED signature of add_executable and add_library
  - Enable finding of imported targets in cmComputeLinkDepends
---
 Source/CMakeLists.txt                          |   6 +
 Source/cmAddDependenciesCommand.cxx            |   2 +-
 Source/cmAddExecutableCommand.cxx              |  56 ++-
 Source/cmAddExecutableCommand.h                |  18 +
 Source/cmAddLibraryCommand.cxx                 |  45 +-
 Source/cmAddLibraryCommand.h                   |  21 +-
 Source/cmComputeLinkDepends.cxx                |  93 +++-
 Source/cmComputeLinkDepends.h                  |   5 +-
 Source/cmComputeLinkInformation.cxx            |  28 +-
 Source/cmExportBuildFileGenerator.cxx          | 117 +++++
 Source/cmExportBuildFileGenerator.h            |  55 +++
 Source/cmExportCommand.cxx                     | 197 ++++-----
 Source/cmExportCommand.h                       |  31 +-
 Source/cmExportFileGenerator.cxx               | 281 ++++++++++++
 Source/cmExportFileGenerator.h                 |  96 ++++
 Source/cmExportInstallFileGenerator.cxx        | 259 +++++++++++
 Source/cmExportInstallFileGenerator.h          | 122 ++++++
 Source/cmGetPropertyCommand.cxx                |   4 +-
 Source/cmGetTargetPropertyCommand.cxx          |   4 +-
 Source/cmGlobalGenerator.cxx                   |  37 +-
 Source/cmGlobalGenerator.h                     |   7 +-
 Source/cmGlobalVisualStudio6Generator.cxx      |   2 +-
 Source/cmGlobalVisualStudio71Generator.cxx     |   3 +-
 Source/cmGlobalVisualStudio7Generator.cxx      |   3 +-
 Source/cmGlobalVisualStudio8Generator.cxx      |   2 +-
 Source/cmGlobalVisualStudioGenerator.cxx       |   6 +-
 Source/cmGlobalXCodeGenerator.cxx              |   8 +-
 Source/cmIncludeExternalMSProjectCommand.cxx   |   3 +-
 Source/cmInstallCommand.cxx                    |  96 ++--
 Source/cmInstallCommand.h                      |  47 +-
 Source/cmInstallCommandArguments.cxx           |  28 +-
 Source/cmInstallCommandArguments.h             |   4 +-
 Source/cmInstallDirectoryGenerator.cxx         |   3 +-
 Source/cmInstallExportGenerator.cxx            | 325 ++++++--------
 Source/cmInstallExportGenerator.h              |  84 +---
 Source/cmInstallFilesCommand.cxx               |   5 +-
 Source/cmInstallFilesGenerator.cxx             |   2 +-
 Source/cmInstallGenerator.cxx                  |  39 +-
 Source/cmInstallGenerator.h                    |  12 +-
 Source/cmInstallProgramsCommand.cxx            |   5 +-
 Source/cmInstallTargetGenerator.cxx            |  21 +-
 Source/cmInstallTargetGenerator.h              |   3 +
 Source/cmLocalGenerator.cxx                    |  12 +-
 Source/cmLocalVisualStudio6Generator.cxx       |   3 +-
 Source/cmMakefile.cxx                          |  87 ++--
 Source/cmMakefile.h                            |  18 +-
 Source/cmMakefileExecutableTargetGenerator.cxx |   4 +-
 Source/cmMakefileTargetGenerator.cxx           |   4 +-
 Source/cmSetPropertyCommand.cxx                |   4 +-
 Source/cmSetTargetPropertiesCommand.cxx        |   4 +-
 Source/cmTarget.cxx                            | 580 +++++++++++++++++++++----
 Source/cmTarget.h                              |  45 +-
 52 files changed, 2212 insertions(+), 734 deletions(-)
 create mode 100644 Source/cmExportBuildFileGenerator.cxx
 create mode 100644 Source/cmExportBuildFileGenerator.h
 create mode 100644 Source/cmExportFileGenerator.cxx
 create mode 100644 Source/cmExportFileGenerator.h
 create mode 100644 Source/cmExportInstallFileGenerator.cxx
 create mode 100644 Source/cmExportInstallFileGenerator.h

diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index 63ecda3..9608224 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -121,6 +121,12 @@ SET(SRCS
   cmExprLexer.cxx
   cmExprParser.cxx
   cmExprParserHelper.cxx
+  cmExportBuildFileGenerator.h
+  cmExportBuildFileGenerator.cxx
+  cmExportFileGenerator.h
+  cmExportFileGenerator.cxx
+  cmExportInstallFileGenerator.h
+  cmExportInstallFileGenerator.cxx
   cmExtraEclipseCDT4Generator.cxx
   cmExtraEclipseCDT4Generator.h
   cmFileTimeComparison.cxx
diff --git a/Source/cmAddDependenciesCommand.cxx b/Source/cmAddDependenciesCommand.cxx
index eccf7d6..4f1e05b 100644
--- a/Source/cmAddDependenciesCommand.cxx
+++ b/Source/cmAddDependenciesCommand.cxx
@@ -32,7 +32,7 @@ bool cmAddDependenciesCommand
 
   cmTarget* target = 
     this->GetMakefile()->GetLocalGenerator()->
-    GetGlobalGenerator()->FindTarget(0, target_name.c_str(), false);
+    GetGlobalGenerator()->FindTarget(0, target_name.c_str());
   if(target)
     {
     std::vector<std::string>::const_iterator s = args.begin();
diff --git a/Source/cmAddExecutableCommand.cxx b/Source/cmAddExecutableCommand.cxx
index 9914e17..cea12bc 100644
--- a/Source/cmAddExecutableCommand.cxx
+++ b/Source/cmAddExecutableCommand.cxx
@@ -51,7 +51,7 @@ bool cmAddExecutableCommand
       ++s;
       excludeFromAll = true;
       }
-    else if(*s == "IMPORT")
+    else if(*s == "IMPORTED")
      {
      ++s;
      importTarget = true;
@@ -61,12 +61,60 @@ bool cmAddExecutableCommand
       break;
       }
     }
-    
-  if (importTarget)
+
+  // Special modifiers are not allowed with IMPORTED signature.
+  if(importTarget && (use_win32 || use_macbundle || excludeFromAll))
+    {
+    if(use_win32)
+      {
+      this->SetError("may not be given WIN32 for an IMPORTED target.");
+      }
+    else if(use_macbundle)
+      {
+      this->SetError(
+        "may not be given MACOSX_BUNDLE for an IMPORTED target.");
+      }
+    else // if(excludeFromAll)
+      {
+      this->SetError(
+        "may not be given EXCLUDE_FROM_ALL for an IMPORTED target.");
+      }
+    return false;
+    }
+
+  // Check for an existing target with this name.
+  cmTarget* existing = this->Makefile->FindTargetToUse(exename.c_str());
+  if(importTarget)
     {
-    this->Makefile->AddNewTarget(cmTarget::EXECUTABLE, exename.c_str(), true);
+    // Make sure the target does not already exist.
+    if(existing)
+      {
+      cmOStringStream e;
+      e << "cannot create imported target \"" << exename
+        << "\" because another target with the same name already exists.";
+      this->SetError(e.str().c_str());
+      return false;
+      }
+
+    // Create the imported target.
+    this->Makefile->AddImportedTarget(exename.c_str(), cmTarget::EXECUTABLE);
     return true;
     }
+  else
+    {
+    // Make sure the target does not conflict with an imported target.
+    // This should really enforce global name uniqueness for targets
+    // built within the project too, but that may break compatiblity
+    // with projects in which it was accidentally working.
+    if(existing && existing->IsImported())
+      {
+      cmOStringStream e;
+      e << "cannot create target \"" << exename
+        << "\" because an imported target with the same name already exists.";
+      this->SetError(e.str().c_str());
+      return false;
+      }
+    }
 
   if (s == args.end())
     {
diff --git a/Source/cmAddExecutableCommand.h b/Source/cmAddExecutableCommand.h
index daedc82..4ac11cc 100644
--- a/Source/cmAddExecutableCommand.h
+++ b/Source/cmAddExecutableCommand.h
@@ -90,6 +90,24 @@ public:
       "If EXCLUDE_FROM_ALL is given the target will not be built by default. "
       "It will be built only if the user explicitly builds the target or "
       "another target that requires the target depends on it."
+      "\n"
+      "The add_executable command can also create IMPORTED executable "
+      "targets using this signature:\n"
+      "  add_executable(<name> IMPORTED)\n"
+      "An IMPORTED executable target references an executable file located "
+      "outside the project.  "
+      "No rules are generated to build it.  "
+      "The target name has scope in the directory in which it is created "
+      "and below.  "
+      "It may be referenced like any target built within the project.  "
+      "IMPORTED executables are useful for convenient reference from "
+      "commands like add_custom_command.  "
+      "Details about the imported executable are specified by setting "
+      "properties whose names begin in \"IMPORTED_\".  "
+      "The most important such property is IMPORTED_LOCATION "
+      "(and its per-configuration version IMPORTED_LOCATION_<CONFIG>) "
+      "which specifies the location of the main executable file on disk.  "
+      "See documentation of the IMPORTED_* properties for more information."
       ;
     }
 
diff --git a/Source/cmAddLibraryCommand.cxx b/Source/cmAddLibraryCommand.cxx
index 4cc7e7a..9406a35 100644
--- a/Source/cmAddLibraryCommand.cxx
+++ b/Source/cmAddLibraryCommand.cxx
@@ -46,6 +46,7 @@ bool cmAddLibraryCommand
   // If the second argument is "SHARED" or "STATIC", then it controls
   // the type of library.  Otherwise, it is treated as a source or
   // source list name. There may be two keyword arguments, check for them
+  bool haveSpecifiedType = false;
   while ( s != args.end() )
     {
     std::string libType = *s;
@@ -53,23 +54,26 @@ bool cmAddLibraryCommand
       {
       ++s;
       type = cmTarget::STATIC_LIBRARY;
+      haveSpecifiedType = true;
       }
     else if(libType == "SHARED")
       {
       ++s;
       type = cmTarget::SHARED_LIBRARY;
+      haveSpecifiedType = true;
       }
     else if(libType == "MODULE")
       {
       ++s;
       type = cmTarget::MODULE_LIBRARY;
+      haveSpecifiedType = true;
       }
     else if(*s == "EXCLUDE_FROM_ALL")
       {
       ++s;
       excludeFromAll = true;
       }
-    else if(*s == "IMPORT")
+    else if(*s == "IMPORTED")
       {
       ++s;
       importTarget = true;
@@ -98,11 +102,46 @@ bool cmAddLibraryCommand
     type = cmTarget::STATIC_LIBRARY;
     }
 
-  if (importTarget)
+  // The IMPORTED signature requires a type to be specified explicitly.
+  if(importTarget && !haveSpecifiedType)
     {
-    this->Makefile->AddNewTarget(type, libName.c_str(), true);
+    this->SetError("called with IMPORTED argument but no library type.");
+    return false;
+    }
+
+  // Check for an existing target with this name.
+  cmTarget* existing = this->Makefile->FindTargetToUse(libName.c_str());
+  if(importTarget)
+    {
+    // Make sure the target does not already exist.
+    if(existing)
+      {
+      cmOStringStream e;
+      e << "cannot create imported target \"" << libName
+        << "\" because another target with the same name already exists.";
+      this->SetError(e.str().c_str());
+      return false;
+      }
+
+    // Create the imported target.
+    this->Makefile->AddImportedTarget(libName.c_str(), type);
     return true;
     }
+  else
+    {
+    // Make sure the target does not conflict with an imported target.
+    // This should really enforce global name uniqueness for targets
+    // built within the project too, but that may break compatiblity
+    // with projects in which it was accidentally working.
+    if(existing && existing->IsImported())
+      {
+      cmOStringStream e;
+      e << "cannot create target \"" << libName
+        << "\" because an imported target with the same name already exists.";
+      this->SetError(e.str().c_str());
+      return false;
+      }
+    }
 
   if (s == args.end())
     {
diff --git a/Source/cmAddLibraryCommand.h b/Source/cmAddLibraryCommand.h
index 6b0f7a4..9b95b86 100644
--- a/Source/cmAddLibraryCommand.h
+++ b/Source/cmAddLibraryCommand.h
@@ -73,7 +73,26 @@ public:
       "to STATIC.\n"
       "If EXCLUDE_FROM_ALL is given the target will not be built by default. "
       "It will be built only if the user explicitly builds the target or "
-      "another target that requires the target depends on it.";
+      "another target that requires the target depends on it."
+      "\n"
+      "The add_library command can also create IMPORTED library "
+      "targets using this signature:\n"
+      "  add_library(<name> <SHARED|STATIC|MODULE> IMPORTED)\n"
+      "An IMPORTED library target references a library file located "
+      "outside the project.  "
+      "No rules are generated to build it.  "
+      "The target name has scope in the directory in which it is created "
+      "and below.  "
+      "It may be referenced like any target built within the project.  "
+      "IMPORTED libraries are useful for convenient reference from "
+      "commands like target_link_libraries.  "
+      "Details about the imported library are specified by setting "
+      "properties whose names begin in \"IMPORTED_\".  "
+      "The most important such property is IMPORTED_LOCATION "
+      "(and its per-configuration version IMPORTED_LOCATION_<CONFIG>) "
+      "which specifies the location of the main library file on disk.  "
+      "See documentation of the IMPORTED_* properties for more information."
+      ;
     }
   
   cmTypeMacro(cmAddLibraryCommand, cmCommand);
diff --git a/Source/cmComputeLinkDepends.cxx b/Source/cmComputeLinkDepends.cxx
index 6056431..b4cb92e 100644
--- a/Source/cmComputeLinkDepends.cxx
+++ b/Source/cmComputeLinkDepends.cxx
@@ -158,7 +158,7 @@ std::vector<cmComputeLinkDepends::LinkEntry> const&
 cmComputeLinkDepends::Compute()
 {
   // Follow the link dependencies of the target to be linked.
-  this->AddLinkEntries(-1, this->Target->GetOriginalLinkLibraries());
+  this->AddTargetLinkEntries(-1, this->Target->GetOriginalLinkLibraries());
 
   // Complete the breadth-first search of dependencies.
   while(!this->BFSQueue.empty())
@@ -222,8 +222,7 @@ int cmComputeLinkDepends::AddLinkEntry(std::string const& item)
   int index = lei->second;
   LinkEntry& entry = this->EntryList[index];
   entry.Item = item;
-  entry.Target =
-    this->GlobalGenerator->FindTarget(0, entry.Item.c_str(), false);
+  entry.Target = this->Makefile->FindTargetToUse(entry.Item.c_str());
 
   // If the item has dependencies queue it to follow them.
   if(entry.Target)
@@ -264,8 +263,15 @@ void cmComputeLinkDepends::FollowLinkEntry(BFSEntry const& qe)
   if(entry.Target)
     {
     // Follow the target dependencies.
-    this->AddLinkEntries(depender_index,
-                         entry.Target->GetOriginalLinkLibraries());
+    if(entry.Target->IsImported())
+      {
+      this->AddImportedLinkEntries(depender_index, entry.Target);
+      }
+    else
+      {
+      this->AddTargetLinkEntries(depender_index,
+                                 entry.Target->GetOriginalLinkLibraries());
+      }
     }
   else
     {
@@ -274,6 +280,18 @@ void cmComputeLinkDepends::FollowLinkEntry(BFSEntry const& qe)
     }
 }
 
+//----------------------------------------------------------------------------
+void cmComputeLinkDepends::AddImportedLinkEntries(int depender_index,
+                                                  cmTarget* target)
+{
+  if(std::vector<std::string> const* libs =
+     target->GetImportedLinkLibraries(this->Config))
+    {
+    this->AddLinkEntries(depender_index, *libs);
+    }
+}
+
+//----------------------------------------------------------------------------
 void cmComputeLinkDepends::AddVarLinkEntries(int depender_index,
                                              const char* value)
 {
@@ -283,39 +301,49 @@ void cmComputeLinkDepends::AddVarLinkEntries(int depender_index,
   std::vector<std::string> deplist;
   cmSystemTools::ExpandListArgument(value, deplist);
 
-  // Construct the vector of type/value pairs from the variable.
-  LinkLibraryVectorType libs;
-  cmTarget::LinkLibraryType linkType = cmTarget::GENERAL;
+  // Compute which library configuration to link.
+  cmTarget::LinkLibraryType linkType = cmTarget::OPTIMIZED;
+  if(this->Config && cmSystemTools::UpperCase(this->Config) == "DEBUG")
+    {
+    linkType = cmTarget::DEBUG;
+    }
+
+  // Look for entries meant for this configuration.
+  std::vector<std::string> actual_libs;
+  cmTarget::LinkLibraryType llt = cmTarget::GENERAL;
   for(std::vector<std::string>::const_iterator di = deplist.begin();
       di != deplist.end(); ++di)
     {
     if(*di == "debug")
       {
-      linkType = cmTarget::DEBUG;
+      llt = cmTarget::DEBUG;
       }
     else if(*di == "optimized")
       {
-      linkType = cmTarget::OPTIMIZED;
+      llt = cmTarget::OPTIMIZED;
       }
     else if(*di == "general")
       {
-      linkType = cmTarget::GENERAL;
+      llt = cmTarget::GENERAL;
       }
     else if(!di->empty())
       {
-      cmTarget::LibraryID lib(*di, linkType);
-      libs.push_back(lib);
+      if(llt == cmTarget::GENERAL || llt == linkType)
+        {
+        actual_libs.push_back(*di);
+        }
       linkType = cmTarget::GENERAL;
       }
     }
 
   // Add the entries from this list.
-  this->AddLinkEntries(depender_index, libs);
+  this->AddLinkEntries(depender_index, actual_libs);
 }
 
 //----------------------------------------------------------------------------
-void cmComputeLinkDepends::AddLinkEntries(int depender_index,
-                                          LinkLibraryVectorType const& libs)
+void
+cmComputeLinkDepends::AddTargetLinkEntries(int depender_index,
+                                           LinkLibraryVectorType const& libs)
 {
   // Compute which library configuration to link.
   cmTarget::LinkLibraryType linkType = cmTarget::OPTIMIZED;
@@ -324,23 +352,42 @@ void cmComputeLinkDepends::AddLinkEntries(int depender_index,
     linkType = cmTarget::DEBUG;
     }
 
+  // Look for entries meant for this configuration.
+  std::vector<std::string> actual_libs;
+  for(cmTarget::LinkLibraryVectorType::const_iterator li = libs.begin();
+      li != libs.end(); ++li)
+    {
+    if(li->second == cmTarget::GENERAL || li->second == linkType)
+      {
+      actual_libs.push_back(li->first);
+      }
+    }
+
+  // Add these entries.
+  this->AddLinkEntries(depender_index, actual_libs);
+}
+
+//----------------------------------------------------------------------------
+void
+cmComputeLinkDepends::AddLinkEntries(int depender_index,
+                                     std::vector<std::string> const& libs)
+{
   // Track inferred dependency sets implied by this list.
   std::map<int, DependSet> dependSets;
 
-  // Loop over the libraries linked directly by the target.
-  for(cmTarget::LinkLibraryVectorType::const_iterator li = libs.begin();
+  // Loop over the libraries linked directly by the depender.
+  for(std::vector<std::string>::const_iterator li = libs.begin();
       li != libs.end(); ++li)
     {
-    // Skip entries that will resolve to the target getting linked.
-    // Skip libraries not meant for the current configuration.
-    if(li->first == this->Target->GetName() || li->first.empty() ||
-       !(li->second == cmTarget::GENERAL || li->second == linkType))
+    // Skip entries that will resolve to the target getting linked or
+    // are empty.
+    if(*li == this->Target->GetName() || li->empty())
       {
       continue;
       }
 
     // Add a link entry for this item.
-    int dependee_index = this->AddLinkEntry(li->first);
+    int dependee_index = this->AddLinkEntry(*li);
 
     // The depender must come before the dependee.
     if(depender_index >= 0)
diff --git a/Source/cmComputeLinkDepends.h b/Source/cmComputeLinkDepends.h
index 646adca..881d50f 100644
--- a/Source/cmComputeLinkDepends.h
+++ b/Source/cmComputeLinkDepends.h
@@ -66,9 +66,12 @@ private:
   typedef cmTarget::LinkLibraryVectorType LinkLibraryVectorType;
 
   int AddLinkEntry(std::string const& item);
+  void AddImportedLinkEntries(int depender_index, cmTarget* target);
   void AddVarLinkEntries(int depender_index, const char* value);
+  void AddTargetLinkEntries(int depender_index,
+                            LinkLibraryVectorType const& libs);
   void AddLinkEntries(int depender_index,
-                      LinkLibraryVectorType const& libs);
+                      std::vector<std::string> const& libs);
 
   // One entry for each unique item.
   std::vector<LinkEntry> EntryList;
diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx
index 1ec1ba3..4d0d93a 100644
--- a/Source/cmComputeLinkInformation.cxx
+++ b/Source/cmComputeLinkInformation.cxx
@@ -301,11 +301,8 @@ void cmComputeLinkInformation::AddItem(std::string const& item,
 {
   // Compute the proper name to use to link this library.
   const char* config = this->Config;
-  bool implib = this->UseImportLibrary;
-  bool impexe = (tgt &&
-                 tgt->GetType() == cmTarget::EXECUTABLE &&
-                 tgt->GetPropertyAsBool("ENABLE_EXPORTS"));
-  if(impexe && !implib && !this->LoaderFlag)
+  bool impexe = (tgt && tgt->IsExecutableWithExports());
+  if(impexe && !this->UseImportLibrary && !this->LoaderFlag)
     {
     // Skip linking to executables on platforms with no import
     // libraries or loader flags.
@@ -325,13 +322,18 @@ void cmComputeLinkInformation::AddItem(std::string const& item,
       // platform.  Add it now.
       std::string linkItem;
       linkItem = this->LoaderFlag;
-      std::string exe = tgt->GetFullPath(config, implib);
+      std::string exe = tgt->GetFullPath(config, this->UseImportLibrary);
       linkItem += exe;
       this->Items.push_back(Item(linkItem, true));
       this->Depends.push_back(exe);
       }
     else
       {
+      // Decide whether to use an import library.
+      bool implib =
+        (this->UseImportLibrary &&
+         (impexe || tgt->GetType() == cmTarget::SHARED_LIBRARY));
+
       // Pass the full path to the target file.
       std::string lib = tgt->GetFullPath(config, implib);
       this->Depends.push_back(lib);
@@ -950,18 +952,8 @@ cmComputeLinkInformation::AddLibraryRuntimeInfo(std::string const& fullPath,
 
   // Try to get the soname of the library.  Only files with this name
   // could possibly conflict.
-  std::string soName;
-  const char* soname  = 0;
-  if(!target->IsImported())
-    {
-    std::string name;
-    std::string realName;
-    std::string impName;
-    std::string pdbName;
-    target->GetLibraryNames(name, soName, realName, impName, pdbName,
-                            this->Config);
-    soname = soName.c_str();
-    }
+  std::string soName = target->GetSOName(this->Config);
+  const char* soname = soName.empty()? 0 : soName.c_str();
 
   // Add the library runtime entry.
   this->AddLibraryRuntimeInfo(fullPath, soname);
diff --git a/Source/cmExportBuildFileGenerator.cxx b/Source/cmExportBuildFileGenerator.cxx
new file mode 100644
index 0000000..0412c90
--- /dev/null
+++ b/Source/cmExportBuildFileGenerator.cxx
@@ -0,0 +1,117 @@
+/*=========================================================================
+
+  Program:   CMake - Cross-Platform Makefile Generator
+  Module:    $RCSfile$
+  Language:  C++
+  Date:      $Date$
+  Version:   $Revision$
+
+  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 "cmExportBuildFileGenerator.h"
+
+//----------------------------------------------------------------------------
+bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os)
+{
+  // Create all the imported targets.
+  for(std::vector<cmTarget*>::const_iterator
+        tei = this->Exports->begin();
+      tei != this->Exports->end(); ++tei)
+    {
+    cmTarget* te = *tei;
+    this->ExportedTargets.insert(te);
+    this->GenerateImportTargetCode(os, te);
+    }
+
+  // Generate import file content for each configuration.
+  for(std::vector<std::string>::const_iterator
+        ci = this->Configurations.begin();
+      ci != this->Configurations.end(); ++ci)
+    {
+    this->GenerateImportConfig(os, ci->c_str());
+    }
+
+  return true;
+}
+
+//----------------------------------------------------------------------------
+void
+cmExportBuildFileGenerator
+::GenerateImportTargetsConfig(std::ostream& os,
+                              const char* config, std::string const& suffix)
+{
+  for(std::vector<cmTarget*>::const_iterator
+        tei = this->Exports->begin();
+      tei != this->Exports->end(); ++tei)
+    {
+    // Collect import properties for this target.
+    cmTarget* target = *tei;
+    ImportPropertyMap properties;
+    this->SetImportLocationProperty(config, suffix, target, properties);
+    if(!properties.empty())
+      {
+      // Get the rest of the target details.
+      this->SetImportDetailProperties(config, suffix,
+                                      target, properties);
+
+      // TOOD: PUBLIC_HEADER_LOCATION
+      // this->GenerateImportProperty(config, te->HeaderGenerator,
+      //                              properties);
+
+      // Generate code in the export file.
+      this->GenerateImportPropertyCode(os, config, target, properties);
+      }
+    }
+}
+
+//----------------------------------------------------------------------------
+void
+cmExportBuildFileGenerator
+::SetImportLocationProperty(const char* config, std::string const& suffix,
+                            cmTarget* target, ImportPropertyMap& properties)
+{
+  // Get the makefile in which to lookup target information.
+  cmMakefile* mf = target->GetMakefile();
+
+  // Add the main target file.
+  {
+  std::string prop = "IMPORTED_LOCATION";
+  prop += suffix;
+  std::string value = target->GetFullPath(config, false);
+  properties[prop] = value;
+  }
+
+  // Check whether this is a DLL platform.
+  bool dll_platform =
+    (mf->IsOn("WIN32") || mf->IsOn("CYGWIN") || mf->IsOn("MINGW"));
+
+  // Add the import library for windows DLLs.
+  if(dll_platform &&
+     (target->GetType() == cmTarget::SHARED_LIBRARY ||
+      target->IsExecutableWithExports()) &&
+     mf->GetDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX"))
+    {
+    std::string prop = "IMPORTED_IMPLIB";
+    prop += suffix;
+    std::string value = target->GetFullPath(config, true);
+    properties[prop] = value;
+    }
+}
+
+//----------------------------------------------------------------------------
+void
+cmExportBuildFileGenerator
+::ComplainAboutMissingTarget(cmTarget* target, const char* dep)
+{
+  cmOStringStream e;
+  e << "WARNING: EXPORT(...) includes target " << target->GetName()
+    << " which links to target \"" << dep
+    << "\" that is not in the export set.";
+  cmSystemTools::Message(e.str().c_str());
+}
diff --git a/Source/cmExportBuildFileGenerator.h b/Source/cmExportBuildFileGenerator.h
new file mode 100644
index 0000000..0bb79cc
--- /dev/null
+++ b/Source/cmExportBuildFileGenerator.h
@@ -0,0 +1,55 @@
+/*=========================================================================
+
+  Program:   CMake - Cross-Platform Makefile Generator
+  Module:    $RCSfile$
+  Language:  C++
+  Date:      $Date$
+  Version:   $Revision$
+
+  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 cmExportBuildFileGenerator_h
+#define cmExportBuildFileGenerator_h
+
+#include "cmExportFileGenerator.h"
+
+/** \class cmExportBuildFileGenerator
+ * \brief Generate a file exporting targets from a build tree.
+ *
+ * cmExportBuildFileGenerator generates a file exporting targets from
+ * a build tree.  A single file exports information for all
+ * configurations built.
+ *
+ * This is used to implement the EXPORT() command.
+ */
+class cmExportBuildFileGenerator: public cmExportFileGenerator
+{
+public:
+  /** Set the list of targets to export.  */
+  void SetExports(std::vector<cmTarget*> const* exports)
+    { this->Exports = exports; }
+
+protected:
+  // Implement virtual methods from the superclass.
+  virtual bool GenerateMainFile(std::ostream& os);
+  virtual void GenerateImportTargetsConfig(std::ostream& os,
+                                           const char* config,
+                                           std::string const& suffix);
+  virtual void ComplainAboutMissingTarget(cmTarget* target, const char* dep);
+
+  /** Fill in properties indicating built file locations.  */
+  void SetImportLocationProperty(const char* config,
+                                 std::string const& suffix,
+                                 cmTarget* target,
+                                 ImportPropertyMap& properties);
+
+  std::vector<cmTarget*> const* Exports;
+};
+
+#endif
diff --git a/Source/cmExportCommand.cxx b/Source/cmExportCommand.cxx
index 3dca7d8..70c024e 100644
--- a/Source/cmExportCommand.cxx
+++ b/Source/cmExportCommand.cxx
@@ -20,14 +20,13 @@
 #include "cmGeneratedFileStream.h"
 #include "cmake.h"
 
-#include <cmsys/auto_ptr.hxx>
+#include "cmExportBuildFileGenerator.h"
 
 cmExportCommand::cmExportCommand()
 :cmCommand()
 ,ArgumentGroup()
 ,Targets(&Helper, "TARGETS")
-,Append(&Helper, "APPEND", &ArgumentGroup)
-,Prefix(&Helper, "PREFIX", &ArgumentGroup)
+,Namespace(&Helper, "NAMESPACE", &ArgumentGroup)
 ,Filename(&Helper, "FILE", &ArgumentGroup)
 {
   // at first TARGETS
@@ -53,151 +52,131 @@ bool cmExportCommand
   if (!unknownArgs.empty())
     {
     this->SetError("Unknown arguments.");
-    cmSystemTools::SetFatalErrorOccured();
     return false;
     }
 
   if (this->Targets.WasFound() == false)
     {
     this->SetError("TARGETS option missing.");
-    cmSystemTools::SetFatalErrorOccured();
     return false;
     }
 
-
-  if ( !this->Makefile->CanIWriteThisFile(this->Filename.GetString().c_str()) )
+  if(!this->Filename.WasFound())
     {
-    std::string e = "attempted to write a file: " + this->Filename.GetString()
-      + " into a source directory.";
-    this->SetError(e.c_str());
-    cmSystemTools::SetFatalErrorOccured();
+    this->SetError("FILE <filename> option missing.");
     return false;
     }
 
-  if((this->Targets.GetVector().empty())||(this->Filename.GetString().empty()))
+  // Make sure the file has a .cmake extension.
+  if(cmSystemTools::GetFilenameLastExtension(this->Filename.GetCString())
+     != ".cmake")
     {
-    return true;
+    cmOStringStream e;
+    e << "FILE option given filename \"" << this->Filename.GetString()
+      << "\" which does not have an extension of \".cmake\".\n";
+    this->SetError(e.str().c_str());
+    return false;
     }
 
-  // Use copy-if-different if not appending.
-  cmsys::auto_ptr<std::ofstream> foutPtr;
-  if(this->Append.IsEnabled())
+  // Get the file to write.
+  std::string fname = this->Filename.GetString();
+  if(cmSystemTools::FileIsFullPath(fname.c_str()))
     {
-    cmsys::auto_ptr<std::ofstream> ap(
-      new std::ofstream(this->Filename.GetString().c_str(), std::ios::app));
-    foutPtr = ap;
+    if(!this->Makefile->CanIWriteThisFile(fname.c_str()))
+      {
+      cmOStringStream e;
+      e << "FILE option given filename \"" << fname
+        << "\" which is in the source tree.\n";
+      this->SetError(e.str().c_str());
+      return false;
+      }
     }
   else
     {
-    cmsys::auto_ptr<cmGeneratedFileStream> ap(
-      new cmGeneratedFileStream(this->Filename.GetString().c_str(), true));
-    ap->SetCopyIfDifferent(true);
-    foutPtr = ap;
+    // Interpret relative paths with respect to the current build dir.
+    fname = this->Makefile->GetCurrentOutputDirectory();
+    fname += "/";
+    fname += this->Filename.GetString();
     }
-  std::ostream& fout = *foutPtr.get();
 
-  if (!fout)
+  // If no targets are to be exported we are done.
+  if(this->Targets.GetVector().empty())
     {
-    cmSystemTools::Error("Error Writing ", this->Filename.GetString().c_str());
-    cmSystemTools::ReportLastSystemError("");
     return true;
     }
 
-  // the following code may move into an "export generator"
-  // Compute the set of configurations.
-  std::vector<std::string> configurationTypes;
-  if(const char* types =
-     this->Makefile->GetDefinition("CMAKE_CONFIGURATION_TYPES"))
-    {
-    cmSystemTools::ExpandListArgument(types, configurationTypes);
-    }
-  if(configurationTypes.empty())
-    {
-    const char* config = this->Makefile->GetDefinition("CMAKE_BUILD_TYPE");
-    if (config!=0)
-      {
-      configurationTypes.push_back(config);
-      }
-    }
-
-  for(std::vector<std::string>::const_iterator 
+  // Collect the targets to be exported.
+  std::vector<cmTarget*> targets;
+  for(std::vector<std::string>::const_iterator
       currentTarget = this->Targets.GetVector().begin();
       currentTarget != this->Targets.GetVector().end();
       ++currentTarget)
     {
-    cmTarget* target = this->Makefile->GetLocalGenerator()->
-             GetGlobalGenerator()->FindTarget(0, currentTarget->c_str(), true);
-    if (target == 0)
+    if(cmTarget* target =
+       this->Makefile->GetLocalGenerator()->
+       GetGlobalGenerator()->FindTarget(0, currentTarget->c_str()))
+      {
+      if((target->GetType() == cmTarget::EXECUTABLE) ||
+         (target->GetType() == cmTarget::STATIC_LIBRARY) ||
+         (target->GetType() == cmTarget::SHARED_LIBRARY) ||
+         (target->GetType() == cmTarget::MODULE_LIBRARY))
+        {
+        targets.push_back(target);
+        }
+      else
+        {
+        cmOStringStream e;
+        e << "given target \"" << *currentTarget
+          << "\" which is not an executable or library.";
+        this->SetError(e.str().c_str());
+        return false;
+        }
+      }
+    else
       {
-      std::string e = "detected unknown target: " + *currentTarget;
-      this->SetError(e.c_str());
-      cmSystemTools::SetFatalErrorOccured();
+      cmOStringStream e;
+      e << "given target \"" << *currentTarget
+        << "\" which is not built by this project.";
+      this->SetError(e.str().c_str());
       return false;
       }
     }
 
-  for(std::vector<std::string>::const_iterator 
-      currentTarget = this->Targets.GetVector().begin();
-      currentTarget != this->Targets.GetVector().end();
-      ++currentTarget)
+  // Setup export file generation.
+  cmExportBuildFileGenerator ebfg;
+  ebfg.SetExportFile(fname.c_str());
+  ebfg.SetNamespace(this->Namespace.GetCString());
+  ebfg.SetExports(&targets);
+
+  // Compute the set of configurations exported.
+  if(const char* types =
+     this->Makefile->GetDefinition("CMAKE_CONFIGURATION_TYPES"))
     {
-    // Look for a CMake target with the given name, which is an executable
-    // and which can be run
-    cmTarget* target = this->Makefile->GetLocalGenerator()->
-             GetGlobalGenerator()->FindTarget(0, currentTarget->c_str(), true);
-    if ((target != 0)
-       && ((target->GetType() == cmTarget::EXECUTABLE)
-        || (target->GetType() == cmTarget::STATIC_LIBRARY)
-        || (target->GetType() == cmTarget::SHARED_LIBRARY)
-        || (target->GetType() == cmTarget::MODULE_LIBRARY)))
+    std::vector<std::string> configurationTypes;
+    cmSystemTools::ExpandListArgument(types, configurationTypes);
+    for(std::vector<std::string>::const_iterator
+          ci = configurationTypes.begin();
+        ci != configurationTypes.end(); ++ci)
       {
-      switch (target->GetType())
-        {
-        case cmTarget::EXECUTABLE:
-          fout << "ADD_EXECUTABLE(" 
-               << this->Prefix.GetString().c_str() << currentTarget->c_str()
-               << " IMPORT )\n";
-          break;
-        case cmTarget::STATIC_LIBRARY:
-          fout << "ADD_LIBRARY(" 
-               << this->Prefix.GetString().c_str() << currentTarget->c_str()
-               << " STATIC IMPORT )\n";
-          break;
-        case cmTarget::SHARED_LIBRARY:
-          fout << "ADD_LIBRARY(" 
-               << this->Prefix.GetString().c_str() << currentTarget->c_str()
-               << " SHARED IMPORT )\n";
-          break;
-        case cmTarget::MODULE_LIBRARY:
-          fout << "ADD_LIBRARY(" 
-               << this->Prefix.GetString().c_str() << currentTarget->c_str()
-               << " MODULE IMPORT )\n";
-          break;
-        default:  // should never happen
-          break;
-        }
-
-      fout << "SET_TARGET_PROPERTIES(" << this->Prefix.GetString().c_str()
-                                 << currentTarget->c_str() << " PROPERTIES \n"
-        <<"                      LOCATION \""<< target->GetLocation(0)<<"\"\n";
-      for(std::vector<std::string>::const_iterator
-          currentConfig = configurationTypes.begin();
-          currentConfig != configurationTypes.end();
-          ++currentConfig)
-        {
-        if (!currentConfig->empty())
-          {
-          const char* loc = target->GetLocation(currentConfig->c_str());
-          if (loc && *loc)
-            {
-            fout << "                      " << currentConfig->c_str()
-                                            << "_LOCATION \"" << loc << "\"\n";
-            }
-          }
-        }
-      fout << "                     )\n\n";
+      ebfg.AddConfiguration(ci->c_str());
       }
     }
+  else if(const char* config =
+          this->Makefile->GetDefinition("CMAKE_BUILD_TYPE"))
+    {
+    ebfg.AddConfiguration(config);
+    }
+  else
+    {
+    ebfg.AddConfiguration("");
+    }
+
+  // Generate the import file.
+  if(!ebfg.GenerateImportFile())
+    {
+    this->SetError("could not write export file.");
+    return false;
+    }
 
   return true;
 }
diff --git a/Source/cmExportCommand.h b/Source/cmExportCommand.h
index c79f46d..f424501 100644
--- a/Source/cmExportCommand.h
+++ b/Source/cmExportCommand.h
@@ -55,7 +55,7 @@ public:
   virtual const char* GetTerseDocumentation()
     {
     return
-      "Write out the dependency information for all targets of a project.";
+      "Export targets from the build tree for use by outside projects.";
     }
 
   /**
@@ -64,15 +64,23 @@ public:
   virtual const char* GetFullDocumentation()
     {
     return
-      "  export(TARGETS tgt1 ... tgtN [PREFIX <prefix>] FILE <filename> "
-      "[APPEND])\n"
-      "Create a file that can be included into a CMake listfile with the "
-      "INCLUDE command.  The file will contain a number of SET commands "
-      "that will set all the variables needed for library dependency "
-      "information.  This should be the last command in the top level "
-      "CMakeLists.txt file of the project.  If the APPEND option is "
-      "specified, the SET commands will be appended to the given file "
-      "instead of replacing it.";
+      "  export(TARGETS [target1 [target2 [...]]] [NAMESPACE <namespace>]\n"
+      "         FILE <filename>)\n"
+      "Create a file <filename> that may be included by outside projects to "
+      "import targets from the current project's build tree.  "
+      "This is useful during cross-compiling to build utility executables "
+      "that can run on the host platform in one project and then import "
+      "them into another project being compiled for the target platform.  "
+      "If the NAMESPACE option is given the <namespace> string will be "
+      "prepended to all target names written to the file.  "
+      "If a library target is included in the export but "
+      "a target to which it links is not included the behavior is "
+      "unspecified."
+      "\n"
+      "The file created by this command is specific to the build tree and "
+      "should never be installed.  "
+      "See the install(EXPORT) command to export targets from an "
+      "installation tree.";
     }
 
   cmTypeMacro(cmExportCommand, cmCommand);
@@ -80,8 +88,7 @@ public:
 private:
   cmCommandArgumentGroup ArgumentGroup;
   cmCAStringVector Targets;
-  cmCAEnabler Append;
-  cmCAString Prefix;
+  cmCAString Namespace;
   cmCAString Filename;
 };
 
diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx
new file mode 100644
index 0000000..ec4bc33
--- /dev/null
+++ b/Source/cmExportFileGenerator.cxx
@@ -0,0 +1,281 @@
+/*=========================================================================
+
+  Program:   CMake - Cross-Platform Makefile Generator
+  Module:    $RCSfile$
+  Language:  C++
+  Date:      $Date$
+  Version:   $Revision$
+
+  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 "cmExportFileGenerator.h"
+
+#include "cmGeneratedFileStream.h"
+#include "cmMakefile.h"
+#include "cmSystemTools.h"
+#include "cmTarget.h"
+
+//----------------------------------------------------------------------------
+void cmExportFileGenerator::AddConfiguration(const char* config)
+{
+  this->Configurations.push_back(config);
+}
+
+//----------------------------------------------------------------------------
+void cmExportFileGenerator::SetExportFile(const char* mainFile)
+{
+  this->MainImportFile = mainFile;
+  this->FileDir =
+    cmSystemTools::GetFilenamePath(this->MainImportFile);
+  this->FileBase =
+    cmSystemTools::GetFilenameWithoutLastExtension(this->MainImportFile);
+  this->FileExt =
+    cmSystemTools::GetFilenameLastExtension(this->MainImportFile);
+}
+
+//----------------------------------------------------------------------------
+bool cmExportFileGenerator::GenerateImportFile()
+{
+  // Open the output file to generate it.
+  cmGeneratedFileStream exportFileStream(this->MainImportFile.c_str(), true);
+  if(!exportFileStream)
+    {
+    std::string se = cmSystemTools::GetLastSystemError();
+    cmOStringStream e;
+    e << "cannot write to file \"" << this->MainImportFile
+      << "\": " << se;
+    cmSystemTools::Error(e.str().c_str());
+    return false;
+    }
+  std::ostream& os = exportFileStream;
+
+  // Start with the import file header.
+  this->GenerateImportHeaderCode(os);
+
+  // Create all the imported targets.
+  bool result = this->GenerateMainFile(os);
+
+  // End with the import file footer.
+  this->GenerateImportFooterCode(os);
+
+  return result;
+}
+
+//----------------------------------------------------------------------------
+void cmExportFileGenerator::GenerateImportConfig(std::ostream& os,
+                                                 const char* config)
+{
+  // Construct the property configuration suffix.
+  std::string suffix = "_";
+  if(config && *config)
+    {
+    suffix += cmSystemTools::UpperCase(config);
+    }
+  else
+    {
+    suffix += "NOCONFIG";
+    }
+
+  // Generate the per-config target information.
+  this->GenerateImportTargetsConfig(os, config, suffix);
+}
+
+//----------------------------------------------------------------------------
+void
+cmExportFileGenerator
+::SetImportDetailProperties(const char* config, std::string const& suffix,
+                            cmTarget* target, ImportPropertyMap& properties)
+{
+  // Get the makefile in which to lookup target information.
+  cmMakefile* mf = target->GetMakefile();
+
+  // Add the soname for unix shared libraries.
+  if(target->GetType() == cmTarget::SHARED_LIBRARY ||
+     target->GetType() == cmTarget::MODULE_LIBRARY)
+    {
+    // Check whether this is a DLL platform.
+    bool dll_platform =
+      (mf->IsOn("WIN32") || mf->IsOn("CYGWIN") || mf->IsOn("MINGW"));
+    if(!dll_platform)
+      {
+      std::string soname = target->GetSOName(config);
+      std::string prop = "IMPORTED_SONAME";
+      prop += suffix;
+      properties[prop] = soname;
+      }
+    }
+
+  // Add the transitive link dependencies for this configuration.
+  {
+  // Compute which library configuration to link.
+  cmTarget::LinkLibraryType linkType = cmTarget::OPTIMIZED;
+  if(config && cmSystemTools::UpperCase(config) == "DEBUG")
+    {
+    linkType = cmTarget::DEBUG;
+    }
+
+  // Construct the property value.
+  cmTarget::LinkLibraryVectorType const& libs =
+    target->GetOriginalLinkLibraries();
+  std::string link_libs;
+  const char* sep = "";
+  for(cmTarget::LinkLibraryVectorType::const_iterator li = libs.begin();
+      li != libs.end(); ++li)
+    {
+    // Skip entries that will resolve to the target itself, are empty,
+    // or are not meant for this configuration.
+    if(li->first == target->GetName() || li->first.empty() ||
+       !(li->second == cmTarget::GENERAL || li->second == linkType))
+      {
+      continue;
+      }
+
+    // Separate this from the previous entry.
+    link_libs += sep;
+    sep = ";";
+
+    // Append this entry.
+    if(cmTarget* tgt = mf->FindTargetToUse(li->first.c_str()))
+      {
+      // This is a target.  Make sure it is included in the export.
+      if(this->ExportedTargets.find(tgt) != this->ExportedTargets.end())
+        {
+        // The target is in the export.  Append it with the export
+        // namespace.
+        link_libs += this->Namespace;
+        link_libs += li->first;
+        }
+      else
+        {
+        // The target is not in the export.  This is probably
+        // user-error.  Warn but add it anyway.
+        this->ComplainAboutMissingTarget(target, li->first.c_str());
+        link_libs += li->first;
+        }
+      }
+    else
+      {
+      // Append the raw name.
+      link_libs += li->first;
+      }
+    }
+
+  // Store the property.
+  std::string prop = "IMPORTED_LINK_LIBRARIES";
+  prop += suffix;
+  properties[prop] = link_libs;
+  }
+}
+
+//----------------------------------------------------------------------------
+void cmExportFileGenerator::GenerateImportHeaderCode(std::ostream& os,
+                                                     const char* config)
+{
+  os << "#----------------------------------------------------------------\n"
+     << "# Generated CMake target import file";
+  if(config)
+    {
+    os << " for configuration \"" << config << "\".\n";
+    }
+  else
+    {
+    os << ".\n";
+    }
+  os << "#----------------------------------------------------------------\n"
+     << "\n";
+  this->GenerateImportVersionCode(os);
+}
+
+//----------------------------------------------------------------------------
+void cmExportFileGenerator::GenerateImportFooterCode(std::ostream& os)
+{
+  os << "# Commands beyond this point should not need to know the version.\n"
+     << "SET(CMAKE_IMPORT_FILE_VERSION)\n";
+}
+
+//----------------------------------------------------------------------------
+void cmExportFileGenerator::GenerateImportVersionCode(std::ostream& os)
+{
+  // Store an import file format version.  This will let us change the
+  // format later while still allowing old import files to work.
+  os << "# Commands may need to know the format version.\n"
+     << "SET(CMAKE_IMPORT_FILE_VERSION 1)\n"
+     << "\n";
+}
+
+//----------------------------------------------------------------------------
+void
+cmExportFileGenerator
+::GenerateImportTargetCode(std::ostream& os, cmTarget* target)
+{
+  // Construct the imported target name.
+  std::string targetName = this->Namespace;
+  targetName += target->GetName();
+
+  // Create the imported target.
+  os << "# Create imported target " << targetName << "\n";
+  switch(target->GetType())
+    {
+    case cmTarget::EXECUTABLE:
+      os << "ADD_EXECUTABLE(" << targetName << " IMPORTED)\n";
+      break;
+    case cmTarget::STATIC_LIBRARY:
+      os << "ADD_LIBRARY(" << targetName << " STATIC IMPORTED)\n";
+      break;
+    case cmTarget::SHARED_LIBRARY:
+      os << "ADD_LIBRARY(" << targetName << " SHARED IMPORTED)\n";
+      break;
+    case cmTarget::MODULE_LIBRARY:
+      os << "ADD_LIBRARY(" << targetName << " MODULE IMPORTED)\n";
+      break;
+    default:  // should never happen
+      break;
+    }
+  if(target->IsExecutableWithExports())
+    {
+    os << "SET_PROPERTY(TARGET " << targetName
+       << " PROPERTY IMPORTED_ENABLE_EXPORTS 1)\n";
+    }
+  os << "\n";
+}
+
+//----------------------------------------------------------------------------
+void
+cmExportFileGenerator
+::GenerateImportPropertyCode(std::ostream& os, const char* config,
+                             cmTarget* target,
+                             ImportPropertyMap const& properties)
+{
+  // Construct the imported target name.
+  std::string targetName = this->Namespace;
+  targetName += target->GetName();
+
+  // Set the import properties.
+  os << "# Import target \"" << targetName << "\" for configuration \""
+     << config << "\"\n";
+  os << "SET_PROPERTY(TARGET " << targetName
+     << " APPEND PROPERTY IMPORTED_CONFIGURATIONS ";
+  if(config && *config)
+    {
+    os << cmSystemTools::UpperCase(config);
+    }
+  else
+    {
+    os << "NOCONFIG";
+    }
+  os << ")\n";
+  os << "SET_TARGET_PROPERTIES(" << targetName << " PROPERTIES\n";
+  for(ImportPropertyMap::const_iterator pi = properties.begin();
+      pi != properties.end(); ++pi)
+    {
+    os << "  " << pi->first << " \"" << pi->second << "\"\n";
+    }
+  os << "  )\n"
+     << "\n";
+}
diff --git a/Source/cmExportFileGenerator.h b/Source/cmExportFileGenerator.h
new file mode 100644
index 0000000..22592d7
--- /dev/null
+++ b/Source/cmExportFileGenerator.h
@@ -0,0 +1,96 @@
+/*=========================================================================
+
+  Program:   CMake - Cross-Platform Makefile Generator
+  Module:    $RCSfile$
+  Language:  C++
+  Date:      $Date$
+  Version:   $Revision$
+
+  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 cmExportFileGenerator_h
+#define cmExportFileGenerator_h
+
+#include "cmCommand.h"
+
+/** \class cmExportFileGenerator
+ * \brief Generate a file exporting targets from a build or install tree.
+ *
+ * cmExportFileGenerator is the superclass for
+ * cmExportBuildFileGenerator and cmExportInstallFileGenerator.  It
+ * contains common code generation routines for the two kinds of
+ * export implementations.
+ */
+class cmExportFileGenerator
+{
+public:
+  /** Set the full path to the export file to generate.  */
+  void SetExportFile(const char* mainFile);
+
+  /** Set the namespace in which to place exported target names.  */
+  void SetNamespace(const char* ns) { this->Namespace = ns; }
+
+  /** Add a configuration to be exported.  */
+  void AddConfiguration(const char* config);
+
+  /** Actually generate the export file.  Returns whether there was an
+      error.  */
+  bool GenerateImportFile();
+protected:
+
+  typedef std::map<cmStdString, cmStdString> ImportPropertyMap;
+
+  // Generate per-configuration target information to the given output
+  // stream.
+  void GenerateImportConfig(std::ostream& os, const char* config);
+
+  // Methods to implement export file code generation.
+  void GenerateImportHeaderCode(std::ostream& os, const char* config = 0);
+  void GenerateImportFooterCode(std::ostream& os);
+  void GenerateImportVersionCode(std::ostream& os);
+  void GenerateImportTargetCode(std::ostream& os, cmTarget* target);
+  void GenerateImportPropertyCode(std::ostream& os, const char* config,
+                                  cmTarget* target,
+                                  ImportPropertyMap const& properties);
+
+  // Collect properties with detailed information about targets beyond
+  // their location on disk.
+  void SetImportDetailProperties(const char* config,
+                                 std::string const& suffix, cmTarget* target,
+                                 ImportPropertyMap& properties);
+
+  /** Each subclass knows how to generate its kind of export file.  */
+  virtual bool GenerateMainFile(std::ostream& os) = 0;
+
+  /** Each subclass knows where the target files are located.  */
+  virtual void GenerateImportTargetsConfig(std::ostream& os,
+                                           const char* config,
+                                           std::string const& suffix) = 0;
+
+  /** Each subclass knows how to complain about a target that is
+      missing from an export set.  */
+  virtual void ComplainAboutMissingTarget(cmTarget*, const char* dep) = 0;
+
+  // The namespace in which the exports are placed in the generated file.
+  std::string Namespace;
+
+  // The set of configurations to export.
+  std::vector<std::string> Configurations;
+
+  // The file to generate.
+  std::string MainImportFile;
+  std::string FileDir;
+  std::string FileBase;
+  std::string FileExt;
+
+  // The set of targets included in the export.
+  std::set<cmTarget*> ExportedTargets;
+};
+
+#endif
diff --git a/Source/cmExportInstallFileGenerator.cxx b/Source/cmExportInstallFileGenerator.cxx
new file mode 100644
index 0000000..8266a96
--- /dev/null
+++ b/Source/cmExportInstallFileGenerator.cxx
@@ -0,0 +1,259 @@
+/*=========================================================================
+
+  Program:   CMake - Cross-Platform Makefile Generator
+  Module:    $RCSfile$
+  Language:  C++
+  Date:      $Date$
+  Version:   $Revision$
+
+  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 "cmExportInstallFileGenerator.h"
+
+#include "cmGeneratedFileStream.h"
+#include "cmInstallExportGenerator.h"
+#include "cmInstallTargetGenerator.h"
+
+//----------------------------------------------------------------------------
+cmExportInstallFileGenerator
+::cmExportInstallFileGenerator(cmInstallExportGenerator* iegen):
+  InstallExportGenerator(iegen)
+{
+}
+
+//----------------------------------------------------------------------------
+bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
+{
+  // Create all the imported targets.
+  for(std::vector<cmTargetExport*>::const_iterator
+        tei = this->ExportSet->begin();
+      tei != this->ExportSet->end(); ++tei)
+    {
+    cmTargetExport* te = *tei;
+    this->ExportedTargets.insert(te->Target);
+    this->GenerateImportTargetCode(os, te->Target);
+    }
+
+  // Now load per-configuration properties for them.
+  os << "# Load information for each installed configuration.\n"
+     << "GET_FILENAME_COMPONENT(_DIR \"${CMAKE_CURRENT_LIST_FILE}\" PATH)\n"
+     << "FILE(GLOB CONFIG_FILES \"${_DIR}/"
+     << this->FileBase << "-*" << this->FileExt << "\")\n"
+     << "FOREACH(f ${CONFIG_FILES})\n"
+     << "  INCLUDE(${f})\n"
+     << "ENDFOREACH(f)\n"
+     << "\n";
+
+  // Generate an import file for each configuration.
+  bool result = true;
+  for(std::vector<std::string>::const_iterator
+        ci = this->Configurations.begin();
+      ci != this->Configurations.end(); ++ci)
+    {
+    if(!this->GenerateImportFileConfig(ci->c_str()))
+      {
+      result = false;
+      }
+    }
+  return result;
+}
+
+//----------------------------------------------------------------------------
+bool
+cmExportInstallFileGenerator::GenerateImportFileConfig(const char* config)
+{
+  // Skip configurations not enabled for this export.
+  if(!this->InstallExportGenerator->InstallsForConfig(config))
+    {
+    return true;
+    }
+
+  // Construct the name of the file to generate.
+  std::string fileName = this->FileDir;
+  fileName += "/";
+  fileName += this->FileBase;
+  fileName += "-";
+  if(config && *config)
+    {
+    fileName += cmSystemTools::LowerCase(config);
+    }
+  else
+    {
+    fileName += "noconfig";
+    }
+  fileName += this->FileExt;
+
+  // Open the output file to generate it.
+  cmGeneratedFileStream exportFileStream(fileName.c_str(), true);
+  if(!exportFileStream)
+    {
+    std::string se = cmSystemTools::GetLastSystemError();
+    cmOStringStream e;
+    e << "cannot write to file \"" << fileName.c_str()
+      << "\": " << se;
+    cmSystemTools::Error(e.str().c_str());
+    return false;
+    }
+  std::ostream& os = exportFileStream;
+
+  // Start with the import file header.
+  this->GenerateImportHeaderCode(os, config);
+
+  // Generate the per-config target information.
+  this->GenerateImportConfig(os, config);
+
+  // End with the import file footer.
+  this->GenerateImportFooterCode(os);
+
+  // Record this per-config import file.
+  this->ConfigImportFiles[config] = fileName;
+
+  return true;
+}
+
+//----------------------------------------------------------------------------
+void
+cmExportInstallFileGenerator
+::GenerateImportTargetsConfig(std::ostream& os,
+                              const char* config, std::string const& suffix)
+{
+  // Add code to compute the installation prefix relative to the
+  // import file location.
+  const char* installDest = this->InstallExportGenerator->GetDestination();
+  if(!cmSystemTools::FileIsFullPath(installDest))
+    {
+    std::string dest = installDest;
+    os << "# Compute the installation prefix relative to this file.\n"
+       << "GET_FILENAME_COMPONENT(_IMPORT_PREFIX "
+       << "\"${CMAKE_CURRENT_LIST_FILE}\" PATH)\n";
+    while(!dest.empty())
+      {
+      os <<
+        "GET_FILENAME_COMPONENT(_IMPORT_PREFIX \"${_IMPORT_PREFIX}\" PATH)\n";
+      dest = cmSystemTools::GetFilenamePath(dest);
+      }
+    os << "\n";
+
+    // Import location properties may reference this variable.
+    this->ImportPrefix = "${_IMPORT_PREFIX}/";
+    }
+
+  // Add each target in the set to the export.
+  for(std::vector<cmTargetExport*>::const_iterator
+        tei = this->ExportSet->begin();
+      tei != this->ExportSet->end(); ++tei)
+    {
+    // Collect import properties for this target.
+    cmTargetExport* te = *tei;
+    ImportPropertyMap properties;
+    this->SetImportLocationProperty(config, suffix,
+                                    te->ArchiveGenerator, properties);
+    this->SetImportLocationProperty(config, suffix,
+                                    te->LibraryGenerator, properties);
+    this->SetImportLocationProperty(config, suffix,
+                                    te->RuntimeGenerator, properties);
+
+    // TODO: Frameworks?
+    // TODO: Bundles?
+
+    // If any file location was set for the target add it to the
+    // import file.
+    if(!properties.empty())
+      {
+      // Get the rest of the target details.
+      this->SetImportDetailProperties(config, suffix,
+                                      te->Target, properties);
+
+      // TOOD: PUBLIC_HEADER_LOCATION
+      // this->GenerateImportProperty(config, te->HeaderGenerator,
+      //                              properties);
+
+      // Generate code in the export file.
+      this->GenerateImportPropertyCode(os, config, te->Target, properties);
+      }
+    }
+
+  // Cleanup the import prefix variable.
+  if(!this->ImportPrefix.empty())
+    {
+    os << "# Cleanup temporary variables.\n"
+       << "SET(_IMPORT_PREFIX)\n"
+       << "\n";
+    }
+}
+
+//----------------------------------------------------------------------------
+void
+cmExportInstallFileGenerator
+::SetImportLocationProperty(const char* config, std::string const& suffix,
+                            cmInstallTargetGenerator* itgen,
+                            ImportPropertyMap& properties)
+{
+  // Skip rules that do not match this configuration.
+  if(!(itgen && itgen->InstallsForConfig(config)))
+    {
+    return;
+    }
+
+  {
+  // Construct the property name.
+  std::string prop = (itgen->IsImportLibrary()?
+                      "IMPORTED_IMPLIB" : "IMPORTED_LOCATION");
+  prop += suffix;
+
+  // Construct the installed location of the target.
+  std::string dest = itgen->GetDestination();
+  std::string value;
+  if(!cmSystemTools::FileIsFullPath(dest.c_str()))
+    {
+    // The target is installed relative to the installation prefix.
+    if(this->ImportPrefix.empty())
+      {
+      this->ComplainAboutImportPrefix(itgen);
+      }
+    value = this->ImportPrefix;
+    }
+  value += dest;
+  value += "/";
+
+  // Append the installed file name.
+  value += itgen->GetInstallFilename(config);
+
+  // Store the property.
+  properties[prop] = value;
+  }
+}
+
+//----------------------------------------------------------------------------
+void
+cmExportInstallFileGenerator
+::ComplainAboutImportPrefix(cmInstallTargetGenerator* itgen)
+{
+  const char* installDest = this->InstallExportGenerator->GetDestination();
+  cmOStringStream e;
+  e << "INSTALL(EXPORT \"" << this->Name << "\") given absolute "
+    << "DESTINATION \"" << installDest << "\" but the export "
+    << "references an installation of target \""
+    << itgen->GetTarget()->GetName() << "\" which has relative "
+    << "DESTINATION \"" << itgen->GetDestination() << "\".";
+  cmSystemTools::Error(e.str().c_str());
+}
+
+//----------------------------------------------------------------------------
+void
+cmExportInstallFileGenerator
+::ComplainAboutMissingTarget(cmTarget* target, const char* dep)
+{
+  cmOStringStream e;
+  e << "WARNING: INSTALL(EXPORT \"" << this->Name << "\" ...) "
+    << "includes target " << target->GetName()
+    << " which links to target \"" << dep
+    << "\" that is not in the export set.";
+  cmSystemTools::Message(e.str().c_str());
+}
diff --git a/Source/cmExportInstallFileGenerator.h b/Source/cmExportInstallFileGenerator.h
new file mode 100644
index 0000000..ecae0b7
--- /dev/null
+++ b/Source/cmExportInstallFileGenerator.h
@@ -0,0 +1,122 @@
+/*=========================================================================
+
+  Program:   CMake - Cross-Platform Makefile Generator
+  Module:    $RCSfile$
+  Language:  C++
+  Date:      $Date$
+  Version:   $Revision$
+
+  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 cmExportInstallFileGenerator_h
+#define cmExportInstallFileGenerator_h
+
+#include "cmExportFileGenerator.h"
+
+class cmInstallExportGenerator;
+class cmInstallFilesGenerator;
+class cmInstallTargetGenerator;
+class cmTargetExport;
+
+/** \class cmExportInstallFileGenerator
+ * \brief Generate a file exporting targets from an install tree.
+ *
+ * cmExportInstallFileGenerator generates files exporting targets from
+ * install an installation tree.  The files are placed in a temporary
+ * location for installation by cmInstallExportGenerator.  One main
+ * file is generated that creates the imported targets and loads
+ * per-configuration files.  Target locations and settings for each
+ * configuration are written to these per-configuration files.  After
+ * installation the main file loads the configurations that have been
+ * installed.
+ *
+ * This is used to implement the INSTALL(EXPORT) command.
+ */
+class cmExportInstallFileGenerator: public cmExportFileGenerator
+{
+public:
+  /** Construct with the export installer that will install the
+      files.  */
+  cmExportInstallFileGenerator(cmInstallExportGenerator* iegen);
+
+  /** Set the name of the export associated with the files.  This is
+      the name given to the install(EXPORT) command mode.  */
+  void SetName(const char* name) { this->Name = name; }
+
+  /** Set the set of targets to be exported.  These are the targets
+      associated with the export name.  */
+  void SetExportSet(std::vector<cmTargetExport*> const* eSet)
+    { this->ExportSet = eSet; }
+
+  /** Get the per-config file generated for each configuraiton.  This
+      maps from the configuration name to the file temporary location
+      for installation.  */
+  std::map<cmStdString, cmStdString> const& GetConfigImportFiles()
+    { return this->ConfigImportFiles; }
+protected:
+
+  // Implement virtual methods from the superclass.
+  virtual bool GenerateMainFile(std::ostream& os);
+  virtual void GenerateImportTargetsConfig(std::ostream& os,
+                                           const char* config,
+                                           std::string const& suffix);
+  virtual void ComplainAboutMissingTarget(cmTarget* target, const char* dep);
+
+  /** Generate a per-configuration file for the targets.  */
+  bool GenerateImportFileConfig(const char* config);
+
+  /** Fill in properties indicating installed file locations.  */
+  void SetImportLocationProperty(const char* config,
+                                 std::string const& suffix,
+                                 cmInstallTargetGenerator* itgen,
+                                 ImportPropertyMap& properties);
+
+  void ComplainAboutImportPrefix(cmInstallTargetGenerator* itgen);
+
+  cmInstallExportGenerator* InstallExportGenerator;
+  std::string Name;
+  std::vector<cmTargetExport*> const* ExportSet;
+
+  std::string ImportPrefix;
+
+  // The import file generated for each configuration.
+  std::map<cmStdString, cmStdString> ConfigImportFiles;
+};
+
+/*
+  cmTargetExport is used in cmGlobalGenerator to collect the install
+  generators for targets associated with an export.
+*/
+class cmTargetExport
+{
+public:
+  cmTargetExport(cmTarget* tgt,
+                 cmInstallTargetGenerator* archive,
+                 cmInstallTargetGenerator* runtime,
+                 cmInstallTargetGenerator* library,
+                 cmInstallTargetGenerator* framework,
+                 cmInstallTargetGenerator* bundle,
+                 cmInstallFilesGenerator* headers
+                ) : Target(tgt), ArchiveGenerator(archive),
+                    RuntimeGenerator(runtime), LibraryGenerator(library),
+                    FrameworkGenerator(framework), BundleGenerator(bundle),
+                    HeaderGenerator(headers) {}
+
+  cmTarget* Target;
+  cmInstallTargetGenerator* ArchiveGenerator;
+  cmInstallTargetGenerator* RuntimeGenerator;
+  cmInstallTargetGenerator* LibraryGenerator;
+  cmInstallTargetGenerator* FrameworkGenerator;
+  cmInstallTargetGenerator* BundleGenerator;
+  cmInstallFilesGenerator* HeaderGenerator;
+private:
+  cmTargetExport();
+};
+
+#endif
diff --git a/Source/cmGetPropertyCommand.cxx b/Source/cmGetPropertyCommand.cxx
index 0a37b97..7622cf2 100644
--- a/Source/cmGetPropertyCommand.cxx
+++ b/Source/cmGetPropertyCommand.cxx
@@ -260,9 +260,7 @@ bool cmGetPropertyCommand::HandleTargetMode()
     return false;
     }
 
-  if(cmTarget* target =
-     this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
-     ->FindTarget(0, this->Name.c_str(), true))
+  if(cmTarget* target = this->Makefile->FindTargetToUse(this->Name.c_str()))
     {
     return this->StoreResult(target->GetProperty(this->PropertyName.c_str()));
     }
diff --git a/Source/cmGetTargetPropertyCommand.cxx b/Source/cmGetTargetPropertyCommand.cxx
index 963e16a..97b4d7f 100644
--- a/Source/cmGetTargetPropertyCommand.cxx
+++ b/Source/cmGetTargetPropertyCommand.cxx
@@ -28,9 +28,7 @@ bool cmGetTargetPropertyCommand
   std::string var = args[0].c_str();
   const char* targetName = args[1].c_str();
 
-  cmTarget *tgt = this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
-    ->FindTarget(0, targetName, true);
-  if (tgt)
+  if(cmTarget* tgt = this->Makefile->FindTargetToUse(targetName))
     {
     cmTarget& target = *tgt;
     const char *prop = target.GetProperty(args[2].c_str());
diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx
index 448d457..6c1af53 100644
--- a/Source/cmGlobalGenerator.cxx
+++ b/Source/cmGlobalGenerator.cxx
@@ -25,7 +25,7 @@
 #include "cmMakefile.h"
 #include "cmSourceFile.h"
 #include "cmVersion.h"
-#include "cmInstallExportGenerator.h"
+#include "cmExportInstallFileGenerator.h"
 
 #include <cmsys/Directory.hxx>
 
@@ -693,7 +693,6 @@ void cmGlobalGenerator::Configure()
   this->LocalGenerators.clear();
   this->TargetDependencies.clear();
   this->TotalTargets.clear();
-  this->ImportedTotalTargets.clear();
   this->LocalGeneratorToTargetMap.clear();
   this->ProjectMap.clear();
 
@@ -1321,9 +1320,8 @@ cmLocalGenerator* cmGlobalGenerator::FindLocalGenerator(const char* start_dir)
 
 
 //----------------------------------------------------------------------------
-cmTarget* cmGlobalGenerator::FindTarget(const char* project,
-                                        const char* name,
-                                        bool useImportedTargets)
+cmTarget*
+cmGlobalGenerator::FindTarget(const char* project, const char* name)
 {
   // if project specific
   if(project)
@@ -1331,8 +1329,7 @@ cmTarget* cmGlobalGenerator::FindTarget(const char* project,
     std::vector<cmLocalGenerator*>* gens = &this->ProjectMap[project];
     for(unsigned int i = 0; i < gens->size(); ++i)
       {
-      cmTarget* ret = (*gens)[i]->GetMakefile()->FindTarget(name,
-                                                           useImportedTargets);
+      cmTarget* ret = (*gens)[i]->GetMakefile()->FindTarget(name);
       if(ret)
         {
         return ret;
@@ -1348,16 +1345,6 @@ cmTarget* cmGlobalGenerator::FindTarget(const char* project,
       {
       return i->second;
       }
-
-    if ( useImportedTargets )
-      {
-      std::map<cmStdString,cmTarget *>::iterator importedTarget =
-        this->ImportedTotalTargets.find ( name );
-      if ( importedTarget != this->ImportedTotalTargets.end() )
-        {
-        return importedTarget->second;
-        }
-      }
     }
   return 0;
 }
@@ -1370,7 +1357,7 @@ bool cmGlobalGenerator::NameResolvesToFramework(const std::string& libname)
     return true;
     }
 
-  if(cmTarget* tgt = this->FindTarget(0, libname.c_str(), true))
+  if(cmTarget* tgt = this->FindTarget(0, libname.c_str()))
     {
     if(tgt->GetType() == cmTarget::SHARED_LIBRARY &&
        tgt->GetPropertyAsBool("FRAMEWORK"))
@@ -1758,12 +1745,12 @@ cmGlobalGenerator::ConsiderTargetDepends(cmTarget const* depender,
 {
   // Check the target's makefile first.
   cmTarget const* dependee =
-    depender->GetMakefile()->FindTarget(dependee_name, false);
+    depender->GetMakefile()->FindTarget(dependee_name);
 
   // Then search globally.
   if(!dependee)
     {
-    dependee = this->FindTarget(0, dependee_name, false);
+    dependee = this->FindTarget(0, dependee_name);
     }
 
   // If not found then skip then the dependee.
@@ -1842,14 +1829,8 @@ cmGlobalGenerator
 
 void cmGlobalGenerator::AddTarget(cmTargets::value_type &v)
 {
-  if (v.second.IsImported())
-    {
-    this->ImportedTotalTargets[v.first] = &v.second;
-    }
-  else
-    {
-    this->TotalTargets[v.first] = &v.second;
-    }
+  assert(!v.second.IsImported());
+  this->TotalTargets[v.first] = &v.second;
 }
 
 void cmGlobalGenerator::SetExternalMakefileProjectGenerator(
diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h
index dfbf1ad..4654a41 100644
--- a/Source/cmGlobalGenerator.h
+++ b/Source/cmGlobalGenerator.h
@@ -186,9 +186,7 @@ public:
   void FindMakeProgram(cmMakefile*);
 
   ///! Find a target by name by searching the local generators.
-  cmTarget* FindTarget(const char* project, 
-                       const char* name, 
-                       bool useImportedTargets);
+  cmTarget* FindTarget(const char* project, const char* name);
 
   /** Determine if a name resolves to a framework on disk or a built target
       that is a framework. */
@@ -297,9 +295,8 @@ private:
   std::map<cmStdString, cmStdString> ExtensionToLanguage;
   std::map<cmStdString, int> LanguageToLinkerPreference; 
 
-  // this is used to improve performance 
+  // this is used to improve performance
   std::map<cmStdString,cmTarget *> TotalTargets;
-  std::map<cmStdString,cmTarget *> ImportedTotalTargets;
 
   cmExternalMakefileProjectGenerator* ExtraGenerator;
 
diff --git a/Source/cmGlobalVisualStudio6Generator.cxx b/Source/cmGlobalVisualStudio6Generator.cxx
index f7b4137..723ac7c 100644
--- a/Source/cmGlobalVisualStudio6Generator.cxx
+++ b/Source/cmGlobalVisualStudio6Generator.cxx
@@ -399,7 +399,7 @@ void cmGlobalVisualStudio6Generator::WriteProject(std::ostream& fout,
       if(j->first != dspname)
         {
         // is the library part of this DSW ? If so add dependency
-        if(this->FindTarget(0, j->first.c_str(), false))
+        if(this->FindTarget(0, j->first.c_str()))
           {
           fout << "Begin Project Dependency\n";
           fout << "Project_Dep_Name " << j->first.c_str() << "\n";
diff --git a/Source/cmGlobalVisualStudio71Generator.cxx b/Source/cmGlobalVisualStudio71Generator.cxx
index 2c35a41..48efee1 100644
--- a/Source/cmGlobalVisualStudio71Generator.cxx
+++ b/Source/cmGlobalVisualStudio71Generator.cxx
@@ -338,8 +338,7 @@ cmGlobalVisualStudio71Generator
       if(j->first != dspname)
         {
         // is the library part of this SLN ? If so add dependency
-        if(this->FindTarget(this->CurrentProject.c_str(), 
-                            j->first.c_str(), false))
+        if(this->FindTarget(this->CurrentProject.c_str(), j->first.c_str()))
           {
           fout << "\t\t{" << this->GetGUID(j->first.c_str()) << "} = {"
                << this->GetGUID(j->first.c_str()) << "}\n";
diff --git a/Source/cmGlobalVisualStudio7Generator.cxx b/Source/cmGlobalVisualStudio7Generator.cxx
index 1b95e2a..f3dcc60 100644
--- a/Source/cmGlobalVisualStudio7Generator.cxx
+++ b/Source/cmGlobalVisualStudio7Generator.cxx
@@ -611,8 +611,7 @@ cmGlobalVisualStudio7Generator
       if(j->first != dspname)
         {
         // is the library part of this SLN ? If so add dependency
-        if(this->FindTarget(this->CurrentProject.c_str(), 
-                            j->first.c_str(), false))
+        if(this->FindTarget(this->CurrentProject.c_str(), j->first.c_str()))
           {
           std::string guid = this->GetGUID(j->first.c_str());
           if(guid.size() == 0)
diff --git a/Source/cmGlobalVisualStudio8Generator.cxx b/Source/cmGlobalVisualStudio8Generator.cxx
index 31b3ab4..7a39459 100644
--- a/Source/cmGlobalVisualStudio8Generator.cxx
+++ b/Source/cmGlobalVisualStudio8Generator.cxx
@@ -138,7 +138,7 @@ void cmGlobalVisualStudio8Generator::Generate()
       mf->AddUtilityCommand(CMAKE_CHECK_BUILD_SYSTEM_TARGET, false,
                             no_working_directory, no_depends,
                             noCommandLines);
-      cmTarget* tgt = mf->FindTarget(CMAKE_CHECK_BUILD_SYSTEM_TARGET, false);
+      cmTarget* tgt = mf->FindTarget(CMAKE_CHECK_BUILD_SYSTEM_TARGET);
       if(!tgt)
         {
         cmSystemTools::Error("Error adding target " 
diff --git a/Source/cmGlobalVisualStudioGenerator.cxx b/Source/cmGlobalVisualStudioGenerator.cxx
index 2319b04..b824590 100644
--- a/Source/cmGlobalVisualStudioGenerator.cxx
+++ b/Source/cmGlobalVisualStudioGenerator.cxx
@@ -270,7 +270,7 @@ cmGlobalVisualStudioGenerator::FixUtilityDependsForTarget(cmTarget& target)
         target.GetUtilities().begin();
       ui != target.GetUtilities().end(); ++ui)
     {
-    if(cmTarget* depTarget = this->FindTarget(0, ui->c_str(), false))
+    if(cmTarget* depTarget = this->FindTarget(0, ui->c_str()))
       {
       if(depTarget->GetType() == cmTarget::STATIC_LIBRARY ||
          depTarget->GetType() == cmTarget::SHARED_LIBRARY ||
@@ -315,7 +315,7 @@ cmGlobalVisualStudioGenerator::CreateUtilityDependTarget(cmTarget& target)
     this->CreateGUID(altNameStr.c_str());
 
     // The intermediate target should depend on the original target.
-    if(cmTarget* alt = this->FindTarget(0, altNameStr.c_str(), false))
+    if(cmTarget* alt = this->FindTarget(0, altNameStr.c_str()))
       {
       alt->AddUtility(target.GetName());
       }
@@ -371,7 +371,7 @@ cmGlobalVisualStudioGenerator::GetUtilityForTarget(cmTarget& target,
     {
     // The depender is a target that links.  Lookup the dependee to
     // see if it provides an alternative dependency name.
-    if(cmTarget* depTarget = this->FindTarget(0, name, false))
+    if(cmTarget* depTarget = this->FindTarget(0, name))
       {
       // Check for an alternative name created by FixUtilityDepends.
       if(const char* altName =
diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx
index cc7e7f8..19394f2 100644
--- a/Source/cmGlobalXCodeGenerator.cxx
+++ b/Source/cmGlobalXCodeGenerator.cxx
@@ -279,7 +279,7 @@ cmGlobalXCodeGenerator::AddExtraTargets(cmLocalGenerator* root,
   mf->AddUtilityCommand("ALL_BUILD", true, no_depends,
                         no_working_directory,
                         "echo", "Build all projects");
-  cmTarget* allbuild = mf->FindTarget("ALL_BUILD", false);
+  cmTarget* allbuild = mf->FindTarget("ALL_BUILD");
 
   // Add XCODE depend helper 
   std::string dir = mf->GetCurrentOutputDirectory();
@@ -1346,7 +1346,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target,
   std::string pnprefix;
   std::string pnbase;
   std::string pnsuffix;
-  target.GetFullName(pnprefix, pnbase, pnsuffix, configName);
+  target.GetFullNameComponents(pnprefix, pnbase, pnsuffix, configName);
 
   // Store the product name for all target types.
   buildSettings->AddAttribute("PRODUCT_NAME",
@@ -2046,7 +2046,7 @@ void cmGlobalXCodeGenerator
       {
       // Add this dependency.
       cmTarget* t = this->FindTarget(this->CurrentProject.c_str(),
-                                     lib->first.c_str(), false);
+                                     lib->first.c_str());
       cmXCodeObject* dptarget = this->FindXCodeTarget(t);
       if(dptarget)
         {
@@ -2062,7 +2062,7 @@ void cmGlobalXCodeGenerator
       i != cmtarget->GetUtilities().end(); ++i)
     {
     cmTarget* t = this->FindTarget(this->CurrentProject.c_str(),
-                                   i->c_str(), false);
+                                   i->c_str());
     // if the target is in this project then make target depend
     // on it.  It may not be in this project if this is a sub
     // project from the top.
diff --git a/Source/cmIncludeExternalMSProjectCommand.cxx b/Source/cmIncludeExternalMSProjectCommand.cxx
index d1f2a78..2ab46c8 100644
--- a/Source/cmIncludeExternalMSProjectCommand.cxx
+++ b/Source/cmIncludeExternalMSProjectCommand.cxx
@@ -51,8 +51,7 @@ bool cmIncludeExternalMSProjectCommand
 
     // Create a target instance for this utility.
     cmTarget* target=this->Makefile->AddNewTarget(cmTarget::UTILITY, 
-                                                  utility_name.c_str(), 
-                                                  false);
+                                                  utility_name.c_str());
     target->SetProperty("EXCLUDE_FROM_ALL","FALSE");
     std::vector<std::string> no_outputs;
     cmCustomCommandLines commandLines;
diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx
index 915cd4b..6c742b9 100644
--- a/Source/cmInstallCommand.cxx
+++ b/Source/cmInstallCommand.cxx
@@ -300,7 +300,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
       ++targetIt)
     {
       // Lookup this target in the current directory.
-      if(cmTarget* target=this->Makefile->FindTarget(targetIt->c_str(), false))
+      if(cmTarget* target=this->Makefile->FindTarget(targetIt->c_str()))
         {
         // Found the target.  Check its type.
         if(target->GetType() != cmTarget::EXECUTABLE &&
@@ -489,7 +489,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
         // library.  Install it to the archive destination if it
         // exists.
         if(dll_platform && !archiveArgs.GetDestination().empty() &&
-           target.GetPropertyAsBool("ENABLE_EXPORTS"))
+           target.IsExecutableWithExports())
           {
           // The import library uses the ARCHIVE properties.
           archiveGenerator = CreateInstallTargetGenerator(target, 
@@ -1069,13 +1069,9 @@ cmInstallCommand::HandleDirectoryMode(std::vector<std::string> const& args)
     return false;
     }
 
-  // Compute destination path.
-  std::string dest;
-  cmInstallCommandArguments::ComputeDestination(destination, dest);
-
   // Create the directory install generator.
   this->Makefile->AddInstallGenerator(
-    new cmInstallDirectoryGenerator(dirs, dest.c_str(),
+    new cmInstallDirectoryGenerator(dirs, destination,
                                     permissions_file.c_str(),
                                     permissions_dir.c_str(),
                                     configurations,
@@ -1095,12 +1091,12 @@ bool cmInstallCommand::HandleExportMode(std::vector<std::string> const& args)
 {
   // This is the EXPORT mode.
   cmInstallCommandArguments ica;
-  cmCAStringVector exports(&ica.Parser, "EXPORT");
-  cmCAString prefix(&ica.Parser, "PREFIX", &ica.ArgumentGroup);
+  cmCAString exp(&ica.Parser, "EXPORT");
+  cmCAString name_space(&ica.Parser, "NAMESPACE", &ica.ArgumentGroup);
   cmCAString filename(&ica.Parser, "FILE", &ica.ArgumentGroup);
-  exports.Follows(0);
+  exp.Follows(0);
 
-  ica.ArgumentGroup.Follows(&exports);
+  ica.ArgumentGroup.Follows(&exp);
   std::vector<std::string> unknownArgs;
   ica.Parse(&args, &unknownArgs);
 
@@ -1118,44 +1114,66 @@ bool cmInstallCommand::HandleExportMode(std::vector<std::string> const& args)
     return false;
     }
 
-  std::string cmakeDir = this->Makefile->GetHomeOutputDirectory();
-  cmakeDir += cmake::GetCMakeFilesDirectory();
-  for(std::vector<std::string>::const_iterator 
-      exportIt = exports.GetVector().begin();
-      exportIt != exports.GetVector().end();
-      ++exportIt)
+  // Make sure there is a destination.
+  if(ica.GetDestination().empty())
     {
-    const std::vector<cmTargetExport*>* exportSet = this->
-                          Makefile->GetLocalGenerator()->GetGlobalGenerator()->
-                          GetExportSet(exportIt->c_str());
-    if (exportSet == 0)
-      {
-      cmOStringStream e;
-      e << "EXPORT given unknown export name \"" << exportIt->c_str() << "\".";
-      this->SetError(e.str().c_str());
-      return false;
-      }
+    // A destination is required.
+    cmOStringStream e;
+    e << args[0] << " given no DESTINATION!";
+    this->SetError(e.str().c_str());
+    return false;
+    }
 
-    // Create the export install generator.
-    cmInstallExportGenerator* exportGenerator = new cmInstallExportGenerator(
-                    ica.GetDestination().c_str(), ica.GetPermissions().c_str(),
-                    ica.GetConfigurations(),0 , filename.GetCString(), 
-                    prefix.GetCString(), cmakeDir.c_str());
+  // Check the file name.
+  std::string fname = filename.GetString();
+  if(fname.find_first_of(":/\\") != fname.npos)
+    {
+    cmOStringStream e;
+    e << args[0] << " given invalid export file name \"" << fname << "\".  "
+      << "The FILE argument may not contain a path.  "
+      << "Specify the path in the DESTINATION argument.";
+    this->SetError(e.str().c_str());
+    return false;
+    }
 
-    if (exportGenerator->SetExportSet(exportIt->c_str(),exportSet))
-      {
-      this->Makefile->AddInstallGenerator(exportGenerator);
-      }
-    else
+  // Check the file extension.
+  if(!fname.empty() &&
+     cmSystemTools::GetFilenameLastExtension(fname) != ".cmake")
+    {
+    cmOStringStream e;
+    e << args[0] << " given invalid export file name \"" << fname << "\".  "
+      << "The FILE argument must specify a name ending in \".cmake\".";
+    this->SetError(e.str().c_str());
+    return false;
+    }
+
+  // Construct the file name.
+  if(fname.empty())
+    {
+    fname = exp.GetString();
+    fname += ".cmake";
+
+    if(fname.find_first_of(":/\\") != fname.npos)
       {
       cmOStringStream e;
-      e << "EXPORT failed, maybe a target is exported more than once.";
+      e << args[0] << " given export name \"" << exp.GetString() << "\".  "
+        << "This name cannot be safely converted to a file name.  "
+        << "Specify a different export name or use the FILE option to set "
+        << "a file name explicitly.";
       this->SetError(e.str().c_str());
-      delete exportGenerator;
       return false;
       }
     }
 
+  // Create the export install generator.
+  cmInstallExportGenerator* exportGenerator =
+    new cmInstallExportGenerator(
+      exp.GetCString(), ica.GetDestination().c_str(),
+      ica.GetPermissions().c_str(), ica.GetConfigurations(),
+      ica.GetComponent().c_str(), fname.c_str(),
+      name_space.GetCString(), this->Makefile);
+  this->Makefile->AddInstallGenerator(exportGenerator);
+
   return true;
 }
 
diff --git a/Source/cmInstallCommand.h b/Source/cmInstallCommand.h
index f0f69e0..0f5eb16 100644
--- a/Source/cmInstallCommand.h
+++ b/Source/cmInstallCommand.h
@@ -98,7 +98,7 @@ public:
       "file to be installed does not exist.  "
       "\n"
       "The TARGETS signature:\n"
-      "  install(TARGETS targets...\n"
+      "  install(TARGETS targets... [EXPORT <export-name>]\n"
       "          [[ARCHIVE|LIBRARY|RUNTIME]\n"
       "           [DESTINATION <dir>]\n"
       "           [PERMISSIONS permissions...]\n"
@@ -145,6 +145,12 @@ public:
       "On non-DLL platforms mySharedLib will be installed to <prefix>/lib "
       "and /some/full/path."
       "\n"
+      "The EXPORT option associates the installed target files with an "
+      "export called <export-name>.  "
+      "It must appear before any RUNTIME, LIBRARY, or ARCHIVE options.  "
+      "See documentation of the install(EXPORT ...) signature below for "
+      "details."
+      "\n"
       "Installing a target with EXCLUDE_FROM_ALL set to true has "
       "undefined behavior."
       "\n"
@@ -248,6 +254,45 @@ public:
       "For example, the code\n"
       "  install(CODE \"MESSAGE(\\\"Sample install message.\\\")\")\n"
       "will print a message during installation.\n"
+      ""
+      "The EXPORT signature:\n"
+      "  install(EXPORT <export-name> DESTINATION <dir>\n"
+      "          [NAMESPACE <namespace>] [FILE <name>.cmake]\n"
+      "          [PERMISSIONS permissions...]\n"
+      "          [CONFIGURATIONS [Debug|Release|...]]\n"
+      "          [COMPONENT <component>])\n"
+      "The EXPORT form generates and installs a CMake file containing code "
+      "to import targets from the installation tree into another project.  "
+      "Target installations are associated with the export <export-name> "
+      "using the EXPORT option of the install(TARGETS ...) signature "
+      "documented above.  The NAMESPACE option will prepend <namespace> to "
+      "the target names as they are written to the import file.  "
+      "By default the generated file will be called <export-name>.cmake but "
+      "the FILE option may be used to specify a different name.  The value "
+      "given to the FILE option must be a file name with the \".cmake\" "
+      "extension.  "
+      "If a CONFIGURATIONS option is given then the file will only be "
+      "installed when one of the named configurations is installed.  "
+      "Additionally, the generated import file will reference only the "
+      "matching target configurations.  "
+      "If a COMPONENT option is specified that does not match that given "
+      "to the targets associated with <export-name> the behavior is "
+      "undefined.  "
+      "If a library target is included in the export but "
+      "a target to which it links is not included the behavior is "
+      "unspecified."
+      "\n"
+      "The EXPORT form is useful to help outside projects use targets built "
+      "and installed by the current project.  For example, the code\n"
+      "  install(TARGETS myexe EXPORT myproj DESTINATION bin)\n"
+      "  install(EXPORT myproj NAMESPACE mp_ DESTINATION lib/myproj)\n"
+      "will install the executable myexe to <prefix>/bin and code to import "
+      "it in the file \"<prefix>/lib/myproj/myproj.cmake\".  "
+      "An outside project may load this file with the include command "
+      "and reference the myexe executable from the installation tree using "
+      "the imported target name mp_myexe as if the target were built "
+      "in its own tree."
+      "\n"
       "NOTE: This command supercedes the INSTALL_TARGETS command and the "
       "target properties PRE_INSTALL_SCRIPT and POST_INSTALL_SCRIPT.  "
       "It also replaces the FILES forms of the INSTALL_FILES and "
diff --git a/Source/cmInstallCommandArguments.cxx b/Source/cmInstallCommandArguments.cxx
index 9cba5bf..506954c 100644
--- a/Source/cmInstallCommandArguments.cxx
+++ b/Source/cmInstallCommandArguments.cxx
@@ -44,9 +44,9 @@ cmInstallCommandArguments::cmInstallCommandArguments()
 
 const std::string& cmInstallCommandArguments::GetDestination() const
 {
-  if (!this->AbsDestination.empty())
+  if (!this->DestinationString.empty())
     {
-    return this->AbsDestination;
+    return this->DestinationString;
     }
   if (this->GenericArguments!=0)
     {
@@ -128,8 +128,8 @@ bool cmInstallCommandArguments::Finalize()
     {
     return false;
     }
-  this->ComputeDestination(this->Destination.GetString(),this->AbsDestination);
-
+  this->DestinationString = this->Destination.GetString();
+  cmSystemTools::ConvertToUnixSlashes(this->DestinationString);
   return true;
 }
 
@@ -174,23 +174,3 @@ bool cmInstallCommandArguments::CheckPermissions(
   // This is not a valid permission.
   return false;
 }
-
-//----------------------------------------------------------------------------
-void cmInstallCommandArguments::ComputeDestination(const std::string& inDest, 
-                                                   std::string& absDest)
-{
-  if((inDest.size()>0) && !(cmSystemTools::FileIsFullPath(inDest.c_str())))
-    {
-    // Relative paths are treated with respect to the installation prefix.
-    absDest = "${CMAKE_INSTALL_PREFIX}/";
-    absDest += inDest;
-    }
-  else
-    {
-    // Full paths are absolute.
-    absDest = inDest;
-    }
-  // Format the path nicely.  Note this also removes trailing slashes.
-  cmSystemTools::ConvertToUnixSlashes(absDest);
-}
-
diff --git a/Source/cmInstallCommandArguments.h b/Source/cmInstallCommandArguments.h
index 430e537..7fc35a0 100644
--- a/Source/cmInstallCommandArguments.h
+++ b/Source/cmInstallCommandArguments.h
@@ -43,8 +43,6 @@ class cmInstallCommandArguments
     // once HandleDirectoryMode() is also switched to using 
     // cmInstallCommandArguments then these two functions can become non-static
     // private member functions without arguments
-    static void ComputeDestination(const std::string& inDest, 
-                                   std::string& absDest);
     static bool CheckPermissions(const std::string& onePerm, 
                                  std::string& perm);
     cmCommandArgumentsHelper Parser;
@@ -57,7 +55,7 @@ class cmInstallCommandArguments
     cmCAStringVector Configurations;
     cmCAEnabler Optional;
 
-    std::string AbsDestination;
+    std::string DestinationString;
     std::string PermissionsString;
 
     cmInstallCommandArguments* GenericArguments;
diff --git a/Source/cmInstallDirectoryGenerator.cxx b/Source/cmInstallDirectoryGenerator.cxx
index 350a4fd..110e6b6 100644
--- a/Source/cmInstallDirectoryGenerator.cxx
+++ b/Source/cmInstallDirectoryGenerator.cxx
@@ -48,8 +48,7 @@ cmInstallDirectoryGenerator::GenerateScriptActions(std::ostream& os,
   bool not_optional = false;
   const char* no_properties = 0;
   const char* no_rename = 0;
-  this->AddInstallRule(os, this->Destination.c_str(),
-                       cmTarget::INSTALL_DIRECTORY,
+  this->AddInstallRule(os, cmTarget::INSTALL_DIRECTORY,
                        this->Directories,
                        not_optional, no_properties,
                        this->FilePermissions.c_str(),
diff --git a/Source/cmInstallExportGenerator.cxx b/Source/cmInstallExportGenerator.cxx
index ed04ebc..81971aa 100644
--- a/Source/cmInstallExportGenerator.cxx
+++ b/Source/cmInstallExportGenerator.cxx
@@ -14,259 +14,198 @@
      PURPOSE.  See the above copyright notices for more information.
 
 =========================================================================*/
+#include "cmInstallExportGenerator.h"
 
 #include <stdio.h>
 
+#include "cmake.h"
 #include "cmInstallTargetGenerator.h"
 #include "cmGeneratedFileStream.h"
 #include "cmTarget.h"
+#include "cmMakefile.h"
+#include "cmLocalGenerator.h"
+#include "cmGlobalGenerator.h"
 
-#include "cmInstallExportGenerator.h"
 #include "cmInstallFilesGenerator.h"
 
+#include "cmExportInstallFileGenerator.h"
+
+//----------------------------------------------------------------------------
 cmInstallExportGenerator::cmInstallExportGenerator(
+  const char* name,
   const char* destination,
   const char* file_permissions,
   std::vector<std::string> const& configurations,
   const char* component,
-  const char* filename, const char* prefix, const char* tempOutputDir)
+  const char* filename, const char* name_space,
+  cmMakefile* mf)
   :cmInstallGenerator(destination, configurations, component)
+  ,Name(name)
   ,FilePermissions(file_permissions)
-  ,Filename(filename)
-  ,Prefix(prefix)
-  ,TempOutputDir(tempOutputDir)
+  ,FileName(filename)
+  ,Namespace(name_space)
+  ,Makefile(mf)
+{
+  this->EFGen = new cmExportInstallFileGenerator(this);
+}
+
+//----------------------------------------------------------------------------
+cmInstallExportGenerator::~cmInstallExportGenerator()
 {
+  delete this->EFGen;
 }
 
-/* Helper function which adds the install locations from the generator
-to the properties for this target.
-*/
-bool cmInstallExportGenerator::AddInstallLocations(cmTargetWithProperties* twp,
-                                           cmInstallTargetGenerator* generator,
-                                           const char* prefix)
+//----------------------------------------------------------------------------
+void cmInstallExportGenerator::ComputeTempDir()
 {
-  if (generator == 0) // nothing to do
+  // Choose a temporary directory in which to generate the import
+  // files to be installed.
+  this->TempDir = this->Makefile->GetCurrentOutputDirectory();
+  this->TempDir += cmake::GetCMakeFilesDirectory();
+  this->TempDir += "/Export";
+  if(this->Destination.empty())
     {
-    return true;
+    return;
     }
-
-  if (prefix == 0)
+  else
     {
-    prefix = "";
+    this->TempDir += "/";
     }
 
-  const std::vector<std::string>& configs = generator->GetConfigurations();
-  if (configs.empty())
+  // Enforce a maximum length.
+  bool useMD5 = false;
+#if defined(_WIN32) || defined(__CYGWIN__)
+  std::string::size_type const max_total_len = 250;
+#else
+  std::string::size_type const max_total_len = 1000;
+#endif
+  if(this->TempDir.size() < max_total_len)
     {
-    std::string propertyName = prefix;
-    propertyName += "LOCATION";
-    // check that this property doesn't exist yet and add it then
-    if (twp->Properties.find(propertyName.c_str()) == twp->Properties.end())
+    // Keep the total path length below the limit.
+    std::string::size_type max_len = max_total_len - this->TempDir.size();
+    if(this->Destination.size() > max_len)
       {
-      std::string destinationFilename = generator->GetDestination();
-      destinationFilename += "/";
-      destinationFilename += generator->GetInstallFilename(0);
-      twp->Properties[propertyName.c_str()] = destinationFilename;
-      }
-    else
-      {
-      return false;
+      useMD5 = true;
       }
     }
   else
     {
-    for(std::vector<std::string>::const_iterator configIt = configs.begin();
-        configIt != configs.end();
-        ++configIt)
-      {
-      std::string propertyName = configIt->c_str();
-      propertyName +=  "_";
-      propertyName += prefix;
-      propertyName += "LOCATION";
-      // check that this property doesn't exist yet and add it then
-      if (twp->Properties.find(propertyName.c_str()) == twp->Properties.end())
-        {
-        std::string destinationFilename = generator->GetDestination();
-        destinationFilename += "/";
-        destinationFilename +=generator->GetInstallFilename(configIt->c_str());
-        twp->Properties[propertyName.c_str()] = destinationFilename;
-        }
-      else
-        {
-        return false;
-        }
-      }
-    }
-  return true;
-}
-
-
-bool cmInstallExportGenerator::AddInstallLocations(cmTargetWithProperties* twp,
-                                           cmInstallFilesGenerator* generator,
-                                           const char* propertyName)
-{
-  if (generator == 0) // nothing to do
-    {
-    return true;
+    useMD5 = true;
     }
-
-  if ((propertyName == 0) || (*propertyName == '\0'))
+  if(useMD5)
     {
-    return false;
+    // Replace the destination path with a hash to keep it short.
+    this->TempDir +=
+      cmSystemTools::ComputeStringMD5(this->Destination.c_str());
     }
-
-  // check that this property doesn't exist yet and add it then
-  if (twp->Properties.find(propertyName) == twp->Properties.end())
+  else
     {
-    twp->Properties[propertyName] = generator->GetDestination();
-    return true;
+    std::string dest = this->Destination;
+    // Avoid unix full paths.
+    if(dest[0] == '/')
+      {
+      dest[0] = '_';
+      }
+    // Avoid windows full paths by removing colons.
+    cmSystemTools::ReplaceString(dest, ":", "_");
+    // Avoid relative paths that go up the tree.
+    cmSystemTools::ReplaceString(dest, "../", "__/");
+    // Avoid spaces.
+    cmSystemTools::ReplaceString(dest, " ", "_");
+    this->TempDir += dest;
     }
-
-  return false;
 }
 
-
-bool cmInstallExportGenerator::SetExportSet(const char* name,
-                                       const std::vector<cmTargetExport*>* set)
+//----------------------------------------------------------------------------
+void cmInstallExportGenerator::GenerateScript(std::ostream& os)
 {
-  if ((name == 0) || (*name == 0) || (set==0))
+  // Get the export set requested.
+  ExportSet const* exportSet =
+    this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
+    ->GetExportSet(this->Name.c_str());
+
+  // Skip empty sets.
+  if(!exportSet)
     {
-    return false;
+    cmOStringStream e;
+    e << "INSTALL(EXPORT) given unknown export \"" << this->Name << "\"";
+    cmSystemTools::Error(e.str().c_str());
+    return;
     }
 
-  this->Name = name;
-
-  /* iterate over all targets in the set.
-  If a cmTargetWithProperties with the same name already exists in this 
-  generator, add the new properties to it. If the property already exists, 
-  fail with an error.
-  If no cmTargetWithProperties exists, create a new one.
-  */
-  for(std::vector<cmTargetExport*>::const_iterator it=set->begin();
-      it != set->end();
-      ++it)
+  // Create the temporary directory in which to store the files.
+  this->ComputeTempDir();
+  cmSystemTools::MakeDirectory(this->TempDir.c_str());
+
+  // Construct a temporary location for the file.
+  this->MainImportFile = this->TempDir;
+  this->MainImportFile += "/";
+  this->MainImportFile += this->FileName;
+
+  // Generate the import file for this export set.
+  this->EFGen->SetName(this->Name.c_str());
+  this->EFGen->SetExportSet(exportSet);
+  this->EFGen->SetExportFile(this->MainImportFile.c_str());
+  this->EFGen->SetNamespace(this->Namespace.c_str());
+  if(this->ConfigurationTypes->empty())
     {
-    std::string targetName = (*it)->Target->GetName();
-
-    cmTargetWithProperties* targetWithProps = 0;
-    for(unsigned int i=0; i<this->Targets.size(); i++)
-      {
-      if (targetName == this->Targets[i]->Target->GetName())
-        {
-        targetWithProps = this->Targets[i];
-        break;
-        }
-      }
-
-    if (targetWithProps == 0)
+    if(this->ConfigurationName && *this->ConfigurationName)
       {
-      targetWithProps = new cmTargetWithProperties((*it)->Target);
-      this->Targets.push_back(targetWithProps);
+      this->EFGen->AddConfiguration(this->ConfigurationName);
       }
-
-    if (this->AddInstallLocations(targetWithProps, (*it)->ArchiveGenerator, 
-                                  "ARCHIVE_") == false)
-      {
-      return false;
-      }
-    if (this->AddInstallLocations(targetWithProps, (*it)->RuntimeGenerator, 
-                                  "") == false)
-      {
-      return false;
-      }
-    if (this->AddInstallLocations(targetWithProps, (*it)->LibraryGenerator, 
-                                  "LIBRARY_") == false)
+    else
       {
-      return false;
+      this->EFGen->AddConfiguration("");
       }
-    if (this->AddInstallLocations(targetWithProps, (*it)->HeaderGenerator, 
-                                  "PUBLIC_HEADER_LOCATION") == false)
+    }
+  else
+    {
+    for(std::vector<std::string>::const_iterator
+          ci = this->ConfigurationTypes->begin();
+        ci != this->ConfigurationTypes->end(); ++ci)
       {
-      return false;
+      this->EFGen->AddConfiguration(ci->c_str());
       }
     }
+  this->EFGen->GenerateImportFile();
 
-  return true;
+  // Perform the main install script generation.
+  this->cmInstallGenerator::GenerateScript(os);
 }
 
-void cmInstallExportGenerator::GenerateScript(std::ostream& os)
+//----------------------------------------------------------------------------
+void
+cmInstallExportGenerator::GenerateScriptConfigs(std::ostream& os,
+                                                Indent const& indent)
 {
-  // for the case that somebody exports the same set with the same file name 
-  // to different locations make the temp filename unique
-  char buf[64];
-  sprintf(buf, "%p", this);
-  this->ExportFilename = this->TempOutputDir;
-  this->ExportFilename += "/";
-  this->ExportFilename += this->Filename;
-  this->ExportFilename += ".";
-  this->ExportFilename += buf;
-
-  cmGeneratedFileStream exportFileStream(this->ExportFilename.c_str());
-  if(!exportFileStream)
+  // Create the main install rules first.
+  this->cmInstallGenerator::GenerateScriptConfigs(os, indent);
+
+  // Now create a configuration-specific install rule for the import
+  // file of each configuration.
+  std::vector<std::string> files;
+  for(std::map<cmStdString, cmStdString>::const_iterator
+        i = this->EFGen->GetConfigImportFiles().begin();
+      i != this->EFGen->GetConfigImportFiles().end(); ++i)
     {
-    return;
+    files.push_back(i->second);
+    std::string config_test = this->CreateConfigTest(i->first.c_str());
+    os << indent << "IF(" << config_test << ")\n";
+    this->AddInstallRule(os, cmTarget::INSTALL_FILES, files, false, 0,
+                         this->FilePermissions.c_str(), 0, 0, 0,
+                         indent.Next());
+    os << indent << "ENDIF(" << config_test << ")\n";
+    files.clear();
     }
-
-  /* for every target add the IMPORT statements and set the properties
-    of the target.  */
-  for(std::vector<cmTargetWithProperties*>::const_iterator 
-      targetIt = this->Targets.begin();
-      targetIt != this->Targets.end();
-      ++targetIt)
-    {
-      switch ((*targetIt)->Target->GetType())
-        {
-        case cmTarget::EXECUTABLE:
-          exportFileStream << "ADD_EXECUTABLE(" << this->Prefix.c_str()
-                           << (*targetIt)->Target->GetName()
-                           << " IMPORT )\n";
-          break;
-        case cmTarget::STATIC_LIBRARY:
-          exportFileStream << "ADD_LIBRARY(" << this->Prefix.c_str() 
-                           << (*targetIt)->Target->GetName() 
-                           << " STATIC IMPORT )\n";
-          break;
-        case cmTarget::SHARED_LIBRARY:
-          exportFileStream << "ADD_LIBRARY(" << this->Prefix.c_str() 
-                           << (*targetIt)->Target->GetName()
-                           << " SHARED IMPORT )\n";
-          break;
-        case cmTarget::MODULE_LIBRARY:
-          exportFileStream << "ADD_LIBRARY(" << this->Prefix.c_str() 
-                           << (*targetIt)->Target->GetName()
-                           << " MODULE IMPORT )\n";
-          break;
-        default:  // should never happen
-          break;
-        }
-
-      exportFileStream << "SET_TARGET_PROPERTIES ( " << this->Prefix.c_str() 
-                       << (*targetIt)->Target->GetName() << " PROPERTIES \n";
-
-      for (std::map<std::string, std::string>::const_iterator
-           propIt = (*targetIt)->Properties.begin();
-           propIt != (*targetIt)->Properties.end();
-           ++propIt)
-        {
-        exportFileStream << "                     " << propIt->first 
-                         << " \"" << propIt->second << "\"\n";
-        }
-      exportFileStream << "                      )\n\n";
-    }
-
-  // Perform the main install script generation.
-  this->cmInstallGenerator::GenerateScript(os);
 }
 
 //----------------------------------------------------------------------------
 void cmInstallExportGenerator::GenerateScriptActions(std::ostream& os,
                                                      Indent const& indent)
 {
-  // install rule for the file created above
-  std::vector<std::string> exportFile;
-  exportFile.push_back(this->ExportFilename);
-  this->AddInstallRule(os, this->Destination.c_str(), cmTarget::INSTALL_FILES,
-                       exportFile, false, 0,
-                       this->FilePermissions.c_str(),
-                       0, this->Filename.c_str(), 0, indent);
+  // Install the main export file.
+  std::vector<std::string> files;
+  files.push_back(this->MainImportFile);
+  this->AddInstallRule(os, cmTarget::INSTALL_FILES, files, false, 0,
+                       this->FilePermissions.c_str(), 0, 0, 0, indent);
 }
diff --git a/Source/cmInstallExportGenerator.h b/Source/cmInstallExportGenerator.h
index ee0ae3e..24f4aac 100644
--- a/Source/cmInstallExportGenerator.h
+++ b/Source/cmInstallExportGenerator.h
@@ -19,42 +19,12 @@
 
 #include "cmInstallGenerator.h"
 
-class cmTarget;
-
-
-class cmInstallTargetGenerator;
+class cmExportInstallFileGenerator;
 class cmInstallFilesGenerator;
-
-/* cmInstallExportTarget is used in cmGlobalGenerator to collect the 
-install generators for the exported targets. These are then used by the 
-cmInstallExportGenerator.
-*/
-class cmTargetExport
-{
-public:
-  cmTargetExport(cmTarget* tgt, 
-                 cmInstallTargetGenerator* archive, 
-                 cmInstallTargetGenerator* runtime, 
-                 cmInstallTargetGenerator* library,
-                 cmInstallTargetGenerator* framework,
-                 cmInstallTargetGenerator* bundle,
-                 cmInstallFilesGenerator* headers
-                ) : Target(tgt), ArchiveGenerator(archive),
-                    RuntimeGenerator(runtime), LibraryGenerator(library),
-                    FrameworkGenerator(framework), BundleGenerator(bundle),
-                    HeaderGenerator(headers) {}
-
-  cmTarget* Target;
-  cmInstallTargetGenerator* ArchiveGenerator;
-  cmInstallTargetGenerator* RuntimeGenerator;
-  cmInstallTargetGenerator* LibraryGenerator;
-  cmInstallTargetGenerator* FrameworkGenerator;
-  cmInstallTargetGenerator* BundleGenerator;
-  cmInstallFilesGenerator* HeaderGenerator;
-private:
-  cmTargetExport();
-};
-
+class cmInstallTargetGenerator;
+class cmTarget;
+class cmTargetExport;
+class cmMakefile;
 
 /** \class cmInstallExportGenerator
  * \brief Generate rules for creating an export files.
@@ -62,45 +32,33 @@ private:
 class cmInstallExportGenerator: public cmInstallGenerator
 {
 public:
-  cmInstallExportGenerator(const char* dest, const char* file_permissions,
+  cmInstallExportGenerator(const char* name,
+                           const char* dest, const char* file_permissions,
                            const std::vector<std::string>& configurations,
                            const char* component,
-                           const char* filename, const char* prefix, 
-                           const char* tempOutputDir);
-
-  bool SetExportSet(const char* name, 
-                    const std::vector<cmTargetExport*>* exportSet);
+                           const char* filename, const char* name_space,
+                           cmMakefile* mf);
+  ~cmInstallExportGenerator();
 protected:
-  // internal class which collects all the properties which will be set
-  // in the export file for the target
-  class cmTargetWithProperties
-  {
-  public:
-    cmTargetWithProperties(cmTarget* target):Target(target) {}
-    cmTarget* Target;
-    std::map<std::string, std::string> Properties;
-  private:
-    cmTargetWithProperties();
-  };
+  typedef std::vector<cmTargetExport*> ExportSet;
 
   typedef cmInstallGeneratorIndent Indent;
   virtual void GenerateScript(std::ostream& os);
+  virtual void GenerateScriptConfigs(std::ostream& os, Indent const& indent);
   virtual void GenerateScriptActions(std::ostream& os, Indent const& indent);
-  static bool AddInstallLocations(cmTargetWithProperties *twp, 
-                                  cmInstallTargetGenerator* generator,
-                                  const char* prefix);
-  static bool AddInstallLocations(cmTargetWithProperties* twp,
-                                           cmInstallFilesGenerator* generator,
-                                           const char* propertyName);
+  void GenerateImportFile(ExportSet const* exportSet);
+  void GenerateImportFile(const char* config, ExportSet const* exportSet);
+  void ComputeTempDir();
 
   std::string Name;
   std::string FilePermissions;
-  std::string Filename;
-  std::string Prefix;
-  std::string TempOutputDir;
-  std::string ExportFilename;
+  std::string FileName;
+  std::string Namespace;
+  cmMakefile* Makefile;
 
-  std::vector<cmTargetWithProperties*> Targets;
+  std::string TempDir;
+  std::string MainImportFile;
+  cmExportInstallFileGenerator* EFGen;
 };
 
 #endif
diff --git a/Source/cmInstallFilesCommand.cxx b/Source/cmInstallFilesCommand.cxx
index 4b09ace..36e7e25 100644
--- a/Source/cmInstallFilesCommand.cxx
+++ b/Source/cmInstallFilesCommand.cxx
@@ -119,9 +119,8 @@ void cmInstallFilesCommand::FinalPass()
 void cmInstallFilesCommand::CreateInstallGenerator() const
 {
   // Construct the destination.  This command always installs under
-  // the prefix.
-  std::string destination = "${CMAKE_INSTALL_PREFIX}";
-  destination += this->Destination;
+  // the prefix.  We skip the leading slash given by the user.
+  std::string destination = this->Destination.substr(1);
   cmSystemTools::ConvertToUnixSlashes(destination);
 
   // Use a file install generator.
diff --git a/Source/cmInstallFilesGenerator.cxx b/Source/cmInstallFilesGenerator.cxx
index ef7eac7..843e315 100644
--- a/Source/cmInstallFilesGenerator.cxx
+++ b/Source/cmInstallFilesGenerator.cxx
@@ -47,7 +47,7 @@ void cmInstallFilesGenerator::GenerateScriptActions(std::ostream& os,
   // Write code to install the files.
   const char* no_properties = 0;
   const char* no_dir_permissions = 0;
-  this->AddInstallRule(os, this->Destination.c_str(),
+  this->AddInstallRule(os,
                        (this->Programs
                         ? cmTarget::INSTALL_PROGRAMS
                         : cmTarget::INSTALL_FILES),
diff --git a/Source/cmInstallGenerator.cxx b/Source/cmInstallGenerator.cxx
index 928b241..cd15965 100644
--- a/Source/cmInstallGenerator.cxx
+++ b/Source/cmInstallGenerator.cxx
@@ -55,7 +55,6 @@ cmInstallGenerator
 void cmInstallGenerator
 ::AddInstallRule(
                  std::ostream& os,
-                 const char* dest,
                  int type,
                  std::vector<std::string> const& files,
                  bool optional /* = false */,
@@ -81,6 +80,7 @@ void cmInstallGenerator
     default:                         stype = "FILE"; break;
     }
   os << indent;
+  std::string dest = this->GetInstallDestination();
   os << "FILE(INSTALL DESTINATION \"" << dest << "\" TYPE " << stype.c_str();
   if(optional)
     {
@@ -238,3 +238,40 @@ void cmInstallGenerator::GenerateScriptActions(std::ostream&, Indent const&)
 {
   // No actions for this generator.
 }
+
+//----------------------------------------------------------------------------
+bool cmInstallGenerator::InstallsForConfig(const char* config)
+{
+  // If this is not a configuration-specific rule then we install.
+  if(this->Configurations.empty())
+    {
+    return true;
+    }
+
+  // This is a configuration-specific rule.  Check if the config
+  // matches this rule.
+  std::string config_upper = cmSystemTools::UpperCase(config?config:"");
+  for(std::vector<std::string>::const_iterator i =
+        this->Configurations.begin();
+      i != this->Configurations.end(); ++i)
+    {
+    if(cmSystemTools::UpperCase(*i) == config_upper)
+      {
+      return true;
+      }
+    }
+  return false;
+}
+
+//----------------------------------------------------------------------------
+std::string cmInstallGenerator::GetInstallDestination() const
+{
+  std::string result;
+  if(!this->Destination.empty() &&
+     !cmSystemTools::FileIsFullPath(this->Destination.c_str()))
+    {
+    result = "${CMAKE_INSTALL_PREFIX}/";
+    }
+  result += this->Destination;
+  return result;
+}
diff --git a/Source/cmInstallGenerator.h b/Source/cmInstallGenerator.h
index 3abcf86..904bb2b 100644
--- a/Source/cmInstallGenerator.h
+++ b/Source/cmInstallGenerator.h
@@ -62,8 +62,8 @@ public:
   void Generate(std::ostream& os, const char* config,
                 std::vector<std::string> const& configurationTypes);
 
-  static void AddInstallRule(
-    std::ostream& os, const char* dest, int type,
+  void AddInstallRule(
+    std::ostream& os, int type,
     std::vector<std::string> const& files,
     bool optional = false,
     const char* properties = 0,
@@ -78,6 +78,14 @@ public:
     { return this->Destination.c_str(); }
   const std::vector<std::string>& GetConfigurations() const
     { return this->Configurations; }
+
+  /** Get the install destination as it should appear in the
+      installation script.  */
+  std::string GetInstallDestination() const;
+
+  /** Test if this generator installs something for a given configuration.  */
+  bool InstallsForConfig(const char*);
+
 protected:
   typedef cmInstallGeneratorIndent Indent;
   virtual void GenerateScript(std::ostream& os);
diff --git a/Source/cmInstallProgramsCommand.cxx b/Source/cmInstallProgramsCommand.cxx
index 8a29665..013728a 100644
--- a/Source/cmInstallProgramsCommand.cxx
+++ b/Source/cmInstallProgramsCommand.cxx
@@ -80,9 +80,8 @@ void cmInstallProgramsCommand::FinalPass()
     }
 
   // Construct the destination.  This command always installs under
-  // the prefix.
-  std::string destination = "${CMAKE_INSTALL_PREFIX}";
-  destination += this->Destination;
+  // the prefix.  We skip the leading slash given by the user.
+  std::string destination = this->Destination.substr(1);
   cmSystemTools::ConvertToUnixSlashes(destination);
 
   // Use a file install generator.
diff --git a/Source/cmInstallTargetGenerator.cxx b/Source/cmInstallTargetGenerator.cxx
index d6a9345..8a56329 100644
--- a/Source/cmInstallTargetGenerator.cxx
+++ b/Source/cmInstallTargetGenerator.cxx
@@ -113,22 +113,11 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(std::ostream& os,
 
   if(config && *config)
     {
-    std::string config_upper = cmSystemTools::UpperCase(config);
     // Skip this configuration for config-specific installation that
     // does not match it.
-    if(!this->Configurations.empty())
+    if(!this->InstallsForConfig(config))
       {
-      bool found = false;
-      for(std::vector<std::string>::const_iterator i =
-            this->Configurations.begin();
-          !found && i != this->Configurations.end(); ++i)
-        {
-        found = found || (cmSystemTools::UpperCase(*i) == config_upper);
-        }
-      if(!found)
-        {
-        return;
-        }
+      return;
       }
 
     // Generate a per-configuration block.
@@ -154,7 +143,7 @@ cmInstallTargetGenerator
                              Indent const& indent)
 {
   // Compute the full path to the main installed file for this target.
-  std::string toInstallPath = this->Destination;
+  std::string toInstallPath = this->GetInstallDestination();
   toInstallPath += "/";
   toInstallPath += this->GetInstallFilename(this->Target, config,
                                               this->ImportLibrary, false);
@@ -279,7 +268,7 @@ cmInstallTargetGenerator
   const char* no_rename = 0;
   const char* no_properties = 0;
   bool optional = this->Optional || this->ImportLibrary;
-  this->AddInstallRule(os, this->Destination.c_str(), type, files,
+  this->AddInstallRule(os, type, files,
                        optional, no_properties,
                        this->FilePermissions.c_str(), no_dir_permissions,
                        no_rename, literal_args.c_str(),
@@ -412,7 +401,7 @@ cmInstallTargetGenerator
       {
       if(cmTarget* tgt = this->Target->GetMakefile()->
          GetLocalGenerator()->GetGlobalGenerator()->
-         FindTarget(0, lib.c_str(), false))
+         FindTarget(0, lib.c_str()))
         {
         if(tgt->GetType() == cmTarget::SHARED_LIBRARY)
           {
diff --git a/Source/cmInstallTargetGenerator.h b/Source/cmInstallTargetGenerator.h
index e37a5ef..01d36bb 100644
--- a/Source/cmInstallTargetGenerator.h
+++ b/Source/cmInstallTargetGenerator.h
@@ -40,6 +40,9 @@ public:
   static std::string GetInstallFilename(cmTarget*target, const char* config, 
                                         bool implib, bool useSOName);
 
+  cmTarget* GetTarget() const { return this->Target; }
+  bool IsImportLibrary() const { return this->ImportLibrary; }
+
 protected:
   typedef cmInstallGeneratorIndent Indent;
   virtual void GenerateScript(std::ostream& os);
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index f49e1bd..4812572 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -1809,7 +1809,7 @@ std::string cmLocalGenerator::GetRealDependency(const char* inName,
     }
 
   // Look for a CMake target with the given name.
-  if(cmTarget* target = this->GlobalGenerator->FindTarget(0,name.c_str(),true))
+  if(cmTarget* target = this->Makefile->FindTargetToUse(name.c_str()))
     {
     // make sure it is not just a coincidence that the target name
     // found is part of the inName
@@ -1876,7 +1876,7 @@ std::string cmLocalGenerator::GetRealLocation(const char* inName,
   std::string outName=inName;
   // Look for a CMake target with the given name, which is an executable 
   // and which can be run
-  cmTarget* target = this->GlobalGenerator->FindTarget(0, inName, true);
+  cmTarget* target = this->Makefile->FindTargetToUse(inName);
   if ((target != 0)
        && (target->GetType() == cmTarget::EXECUTABLE)
        && ((this->Makefile->IsOn("CMAKE_CROSSCOMPILING") == false) 
@@ -2348,8 +2348,8 @@ cmLocalGenerator
       {
       // Compute the full install destination.  Note that converting
       // to unix slashes also removes any trailing slash.
-      std::string destination = "${CMAKE_INSTALL_PREFIX}";
-      destination += l->second.GetInstallPath();
+      // We also skip over the leading slash given by the user.
+      std::string destination = l->second.GetInstallPath().substr(1);
       cmSystemTools::ConvertToUnixSlashes(destination);
 
       // Generate the proper install generator for this target type.
@@ -2372,8 +2372,8 @@ cmLocalGenerator
           // destination.
           cmInstallTargetGenerator g1(l->second, destination.c_str(), true);
           g1.Generate(os, config, configurationTypes);
-          destination = "${CMAKE_INSTALL_PREFIX}";
-          destination += l->second.GetRuntimeInstallPath();
+          // We also skip over the leading slash given by the user.
+          destination = l->second.GetRuntimeInstallPath().substr(1);
           cmSystemTools::ConvertToUnixSlashes(destination);
           cmInstallTargetGenerator g2(l->second, destination.c_str(), false);
           g2.Generate(os, config, configurationTypes);
diff --git a/Source/cmLocalVisualStudio6Generator.cxx b/Source/cmLocalVisualStudio6Generator.cxx
index b462cd3..258d027 100644
--- a/Source/cmLocalVisualStudio6Generator.cxx
+++ b/Source/cmLocalVisualStudio6Generator.cxx
@@ -1061,8 +1061,7 @@ void cmLocalVisualStudio6Generator
       // Compute the proper name to use to link this library.
       std::string lib;
       std::string libDebug;
-      cmTarget* tgt = this->GlobalGenerator->FindTarget(0, j->first.c_str(),
-                                                        false);
+      cmTarget* tgt = this->GlobalGenerator->FindTarget(0, j->first.c_str());
       if(tgt)
         {
         lib = cmSystemTools::GetFilenameWithoutExtension
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index d75e9eb..1abd467 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -37,6 +37,8 @@
 
 #include <cmsys/RegularExpression.hxx>
 
+#include <cmsys/auto_ptr.hxx>
+
 #include <ctype.h> // for isspace
 
 // default is not to be building executables
@@ -176,6 +178,12 @@ cmMakefile::~cmMakefile()
     {
     delete *i;
     }
+  for(std::vector<cmTarget*>::iterator
+        i = this->ImportedTargetsOwned.begin();
+      i != this->ImportedTargetsOwned.end(); ++i)
+    {
+    delete *i;
+    }
   for(unsigned int i=0; i < this->UsedCommands.size(); i++)
     {
     delete this->UsedCommands[i];
@@ -824,7 +832,7 @@ void cmMakefile::AddUtilityCommand(const char* utilityName,
                                    bool escapeOldStyle, const char* comment)
 {
   // Create a target instance for this utility.
-  cmTarget* target = this->AddNewTarget(cmTarget::UTILITY, utilityName, false);
+  cmTarget* target = this->AddNewTarget(cmTarget::UTILITY, utilityName);
   if (excludeFromAll)
     {
     target->SetProperty("EXCLUDE_FROM_ALL", "TRUE");
@@ -1005,7 +1013,7 @@ void cmMakefile::AddLinkLibraryForTarget(const char *target,
   if ( i != this->Targets.end())
     {
     cmTarget* tgt =
-      this->GetCMakeInstance()->GetGlobalGenerator()->FindTarget(0,lib,false);
+      this->GetCMakeInstance()->GetGlobalGenerator()->FindTarget(0,lib);
     if(tgt)
       {
       bool allowModules = true;
@@ -1018,8 +1026,7 @@ void cmMakefile::AddLinkLibraryForTarget(const char *target,
       // if it is not a static or shared library then you can not link to it
       if(!((tgt->GetType() == cmTarget::STATIC_LIBRARY) ||
            (tgt->GetType() == cmTarget::SHARED_LIBRARY) ||
-           (tgt->GetType() == cmTarget::EXECUTABLE &&
-            tgt->GetPropertyAsBool("ENABLE_EXPORTS"))))
+           tgt->IsExecutableWithExports()))
         {
         cmOStringStream e;
         e << "Attempt to add link target " << lib << " of type: "
@@ -1162,6 +1169,9 @@ void cmMakefile::InitializeFromParent()
   // Copy include regular expressions.
   this->IncludeFileRegularExpression = parent->IncludeFileRegularExpression;
   this->ComplainFileRegularExpression = parent->ComplainFileRegularExpression;
+
+  // Imported targets.
+  this->ImportedTargets = parent->ImportedTargets;
 }
 
 void cmMakefile::ConfigureSubDirectory(cmLocalGenerator *lg2)
@@ -1467,7 +1477,7 @@ void cmMakefile::AddLibrary(const char* lname, cmTarget::TargetType type,
     type = cmTarget::STATIC_LIBRARY;
     }
 
-  cmTarget* target = this->AddNewTarget(type, lname, false);
+  cmTarget* target = this->AddNewTarget(type, lname);
   // Clear its dependencies. Otherwise, dependencies might persist
   // over changes in CMakeLists.txt, making the information stale and
   // hence useless.
@@ -1484,7 +1494,7 @@ cmTarget* cmMakefile::AddExecutable(const char *exeName,
                                     const std::vector<std::string> &srcs,
                                     bool excludeFromAll)
 {
-  cmTarget* target = this->AddNewTarget(cmTarget::EXECUTABLE, exeName, false);
+  cmTarget* target = this->AddNewTarget(cmTarget::EXECUTABLE, exeName);
   if(excludeFromAll)
     {
     target->SetProperty("EXCLUDE_FROM_ALL", "TRUE");
@@ -1494,26 +1504,16 @@ cmTarget* cmMakefile::AddExecutable(const char *exeName,
   return target;
 }
 
-
-cmTarget* cmMakefile::AddNewTarget(cmTarget::TargetType type, 
-                                   const char* name, 
-                                   bool isImported)
+//----------------------------------------------------------------------------
+cmTarget*
+cmMakefile::AddNewTarget(cmTarget::TargetType type, const char* name)
 {
   cmTargets::iterator it;
   cmTarget target;
   target.SetType(type, name);
   target.SetMakefile(this);
-  if (isImported)
-    {
-    target.MarkAsImported();
-    it=this->ImportedTargets.insert(
-                        cmTargets::value_type(target.GetName(), target)).first;
-    }
-  else
-    {
-    it=this->Targets.insert(
-                        cmTargets::value_type(target.GetName(), target)).first;
-    }
+  it=this->Targets.insert(
+      cmTargets::value_type(target.GetName(), target)).first;
   this->LocalGenerator->GetGlobalGenerator()->AddTarget(*it);
   return &it->second;
 }
@@ -2869,7 +2869,7 @@ bool cmMakefile::GetPropertyAsBool(const char* prop)
 }
 
 
-cmTarget* cmMakefile::FindTarget(const char* name, bool useImportedTargets)
+cmTarget* cmMakefile::FindTarget(const char* name)
 {
   cmTargets& tgts = this->GetTargets();
 
@@ -2879,15 +2879,6 @@ cmTarget* cmMakefile::FindTarget(const char* name, bool useImportedTargets)
     return &i->second;
     }
 
-  if (useImportedTargets)
-    {
-    cmTargets::iterator impTarget = this->ImportedTargets.find(name);
-    if (impTarget != this->ImportedTargets.end())
-      {
-      return &impTarget->second;
-      }
-    }
-
   return 0;
 }
 
@@ -3091,3 +3082,37 @@ void cmMakefile::DefineProperties(cmake *cm)
      "The same concept applies to the default build of other generators.",
      false);
 }
+
+//----------------------------------------------------------------------------
+cmTarget*
+cmMakefile::AddImportedTarget(const char* name, cmTarget::TargetType type)
+{
+  // Create the target.
+  cmsys::auto_ptr<cmTarget> target(new cmTarget);
+  target->SetType(type, name);
+  target->SetMakefile(this);
+  target->MarkAsImported();
+
+  // Add to the set of available imported targets.
+  this->ImportedTargets[name] = target.get();
+
+  // Transfer ownership to this cmMakefile object.
+  this->ImportedTargetsOwned.push_back(target.get());
+  return target.release();
+}
+
+//----------------------------------------------------------------------------
+cmTarget* cmMakefile::FindTargetToUse(const char* name)
+{
+  // Look for an imported target.  These take priority because they
+  // are more local in scope and do not have to be globally unique.
+  std::map<cmStdString, cmTarget*>::const_iterator
+    imported = this->ImportedTargets.find(name);
+  if(imported != this->ImportedTargets.end())
+    {
+    return imported->second;
+    }
+
+  // Look for a target built in this project.
+  return this->LocalGenerator->GetGlobalGenerator()->FindTarget(0, name);
+}
diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h
index e511851..5664e25 100644
--- a/Source/cmMakefile.h
+++ b/Source/cmMakefile.h
@@ -172,9 +172,10 @@ public:
   void AddDefineFlag(const char* definition);
   void RemoveDefineFlag(const char* definition);
 
-  cmTarget* AddNewTarget(cmTarget::TargetType type, 
-                         const char* name, 
-                         bool isImported);
+  /** Create a new imported target with the name and type given.  */
+  cmTarget* AddImportedTarget(const char* name, cmTarget::TargetType type);
+
+  cmTarget* AddNewTarget(cmTarget::TargetType type, const char* name);
   
   /**
    * Add an executable to the build.
@@ -436,10 +437,12 @@ public:
    * Get the list of targets, const version
    */
   const cmTargets &GetTargets() const { return this->Targets; }
-  const cmTargets &GetImportedTargets() const { return this->ImportedTargets; }
 
-  cmTarget* FindTarget(const char* name, bool useImportedTargets);
+  cmTarget* FindTarget(const char* name);
 
+  /** Find a target to use in place of the given name.  The target
+      returned may be imported or built within the project.  */
+  cmTarget* FindTargetToUse(const char* name);
 
   /**
    * Get a list of include directories in the build.
@@ -766,7 +769,6 @@ protected:
 
   // libraries, classes, and executables
   cmTargets Targets;
-  cmTargets ImportedTargets;
   std::vector<cmSourceFile*> SourceFiles;
 
   // Tests
@@ -842,6 +844,10 @@ private:
 
   // stack of list files being read 
   std::deque<cmStdString> ListFileStack;
+
+  cmTarget* FindBasicTarget(const char* name);
+  std::vector<cmTarget*> ImportedTargetsOwned;
+  std::map<cmStdString, cmTarget*> ImportedTargets;
 };
 
 
diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx
index 85d8565..e67b991 100644
--- a/Source/cmMakefileExecutableTargetGenerator.cxx
+++ b/Source/cmMakefileExecutableTargetGenerator.cxx
@@ -259,7 +259,7 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
     }
 
   // Add symbol export flags if necessary.
-  if(this->Target->GetPropertyAsBool("ENABLE_EXPORTS"))
+  if(this->Target->IsExecutableWithExports())
     {
     std::string export_flag_var = "CMAKE_EXE_EXPORTS_";
     export_flag_var += linkLanguage;
@@ -351,7 +351,7 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
     this->Makefile->GetRequiredDefinition(linkRuleVar.c_str());
   std::vector<std::string> commands1;
   cmSystemTools::ExpandListArgument(linkRule, real_link_commands);
-  if(this->Target->GetPropertyAsBool("ENABLE_EXPORTS"))
+  if(this->Target->IsExecutableWithExports())
     {
     // If a separate rule for creating an import library is specified
     // add it now.
diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx
index 37bd5f9..0c550ef 100644
--- a/Source/cmMakefileTargetGenerator.cxx
+++ b/Source/cmMakefileTargetGenerator.cxx
@@ -869,7 +869,7 @@ void cmMakefileTargetGenerator::WriteTargetDependRules()
   for(cmTarget::LinkLibraryVectorType::const_iterator j = libs.begin();
       j != libs.end(); ++j)
     {
-    if(cmTarget const* linkee = gg->FindTarget(0, j->first.c_str(), false))
+    if(cmTarget const* linkee = gg->FindTarget(0, j->first.c_str()))
       {
       if(emitted.insert(linkee).second)
         {
@@ -1371,7 +1371,7 @@ void cmMakefileTargetGenerator
       {
       // Depend on other CMake targets.
       if(cmTarget* tgt =
-         this->GlobalGenerator->FindTarget(0, lib->first.c_str(), false))
+         this->GlobalGenerator->FindTarget(0, lib->first.c_str()))
         {
         if(const char* location =
            tgt->GetLocation(this->LocalGenerator->ConfigurationName.c_str()))
diff --git a/Source/cmSetPropertyCommand.cxx b/Source/cmSetPropertyCommand.cxx
index 0922c1d..dbf71c2 100644
--- a/Source/cmSetPropertyCommand.cxx
+++ b/Source/cmSetPropertyCommand.cxx
@@ -220,9 +220,7 @@ bool cmSetPropertyCommand::HandleTargetMode()
   for(std::set<cmStdString>::const_iterator ni = this->Names.begin();
       ni != this->Names.end(); ++ni)
     {
-    if(cmTarget* target =
-       this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
-       ->FindTarget(0, ni->c_str(), true))
+    if(cmTarget* target = this->Makefile->FindTargetToUse(ni->c_str()))
       {
       // Handle the current target.
       if(!this->HandleTarget(target))
diff --git a/Source/cmSetTargetPropertiesCommand.cxx b/Source/cmSetTargetPropertiesCommand.cxx
index ccbe0d5..26615dc 100644
--- a/Source/cmSetTargetPropertiesCommand.cxx
+++ b/Source/cmSetTargetPropertiesCommand.cxx
@@ -95,9 +95,7 @@ bool cmSetTargetPropertiesCommand
                std::vector<std::string> &propertyPairs,
                cmMakefile *mf)
 {
-  cmTarget* target = 
-    mf->GetLocalGenerator()->GetGlobalGenerator()->FindTarget(0, tname, true);
-  if ( target)
+  if(cmTarget* target = mf->FindTargetToUse(tname))
     {
     // now loop through all the props and set them
     unsigned int k;
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index 274c3af..0fb6f7b 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -154,6 +154,96 @@ void cmTarget::DefineProperties(cmake *cm)
      "(such as \".lib\") on an import library name.");
 
   cm->DefineProperty
+    ("IMPORTED", cmProperty::TARGET,
+     "Read-only indication of whether a target is IMPORTED.",
+     "The boolean value of this property is true for targets created with "
+     "the IMPORTED option to add_executable or add_library.  "
+     "It is false for targets built within the project.");
+
+  cm->DefineProperty
+    ("IMPORTED_CONFIGURATIONS", cmProperty::TARGET,
+     "Configurations provided for an IMPORTED target.",
+     "Lists configuration names available for an IMPORTED target.  "
+     "The names correspond to configurations defined in the project from "
+     "which the target is imported.  "
+     "If the importing project uses a different set of configurations "
+     "the names may be mapped using the MAP_IMPORTED_CONFIG_<CONFIG> "
+     "property.  "
+     "Ignored for non-imported targets.");
+
+  cm->DefineProperty
+    ("IMPORTED_ENABLE_EXPORTS", cmProperty::TARGET,
+     "Enable linking to an IMPORTED executable target.",
+     "Indicates that an IMPORTED executable target exports symbols for "
+     "use by plugin modules.  "
+     "This is the imported target equivalent of the ENABLE_EXPORTS "
+     "property.");
+
+  cm->DefineProperty
+    ("IMPORTED_IMPLIB", cmProperty::TARGET,
+     "Full path to the import library for an IMPORTED target.",
+     "Specifies the location of the \".lib\" part of a windows DLL.  "
+     "Ignored for non-imported targets.");
+
+  cm->DefineProperty
+    ("IMPORTED_IMPLIB_<CONFIG>", cmProperty::TARGET,
+     "Per-configuration version of IMPORTED_IMPLIB property.",
+     "This property is used when loading settings for the <CONFIG> "
+     "configuration of an imported target.  "
+     "Configuration names correspond to those provided by the project "
+     "from which the target is imported.");
+
+  cm->DefineProperty
+    ("IMPORTED_LINK_LIBRARIES", cmProperty::TARGET,
+     "Transitive link dependencies of an IMPORTED target.",
+     "Lists dependencies that must be linked when an IMPORTED library "
+     "target is linked to another target.  "
+     "Ignored for non-imported targets.");
+
+  cm->DefineProperty
+    ("IMPORTED_LINK_LIBRARIES_<CONFIG>", cmProperty::TARGET,
+     "Per-configuration version of IMPORTED_LINK_LIBRARIES property.",
+     "This property is used when loading settings for the <CONFIG> "
+     "configuration of an imported target.  "
+     "Configuration names correspond to those provided by the project "
+     "from which the target is imported.");
+
+  cm->DefineProperty
+    ("IMPORTED_LOCATION", cmProperty::TARGET,
+     "Full path to the main file on disk for an IMPORTED target.",
+     "Specifies the location of an IMPORTED target file on disk.  "
+     "For executables this is the location of the executable file.  "
+     "For static libraries and modules this is the location of the "
+     "library or module.  "
+     "For shared libraries on non-DLL platforms this is the location of "
+     "the shared library.  "
+     "For DLLs this is the location of the \".dll\" part of the library.  "
+     "Ignored for non-imported targets.");
+
+  cm->DefineProperty
+    ("IMPORTED_LOCATION_<CONFIG>", cmProperty::TARGET,
+     "Per-configuration version of IMPORTED_LOCATION property.",
+     "This property is used when loading settings for the <CONFIG> "
+     "configuration of an imported target.  "
+     "Configuration names correspond to those provided by the project "
+     "from which the target is imported.");
+
+  cm->DefineProperty
+    ("IMPORTED_SONAME", cmProperty::TARGET,
+     "The \"soname\" of an IMPORTED target of shared library type.",
+     "Specifies the \"soname\" embedded in an imported shared library.  "
+     "This is meaningful only on platforms supporting the feature.  "
+     "Ignored for non-imported targets.");
+
+  cm->DefineProperty
+    ("IMPORTED_SONAME_<CONFIG>", cmProperty::TARGET,
+     "Per-configuration version of IMPORTED_SONAME property.",
+     "This property is used when loading settings for the <CONFIG> "
+     "configuration of an imported target.  "
+     "Configuration names correspond to those provided by the project "
+     "from which the target is imported.");
+
+  cm->DefineProperty
     ("EXCLUDE_FROM_ALL", cmProperty::TARGET,
      "Exclude the target from the all target.",
      "A property on a target that indicates if the target is excluded "
@@ -206,11 +296,37 @@ void cmTarget::DefineProperties(cmake *cm)
 
   cm->DefineProperty
     ("LOCATION", cmProperty::TARGET,
-     "Where a target will be written on disk.",
-     "A read only property on a target that indicates where that target "
-     "will be written. For libraries and executables this will be where "
-     "the file is written on disk. This property is computed based on a "
-     "number of other settings.");
+     "Deprecated.  Use LOCATION_<CONFIG> or avoid altogether.",
+     "This property is provided for compatibility with CMake 2.4 and below. "
+     "It was meant to get the location of an executable target's output file "
+     "for use in add_custom_command.  "
+     "In CMake 2.6 and above add_custom_command automatically recognizes a "
+     "target name in its COMMAND and DEPENDS options and computes the "
+     "target location.  Therefore this property need not be used.  "
+     "This property is not defined for IMPORTED targets because they "
+     "were not available in CMake 2.4 or below anyway.");
+
+  cm->DefineProperty
+    ("LOCATION_<CONFIG>", cmProperty::TARGET,
+     "Read-only property providing a target location on disk.",
+     "A read-only property that indicates where a target's main file is "
+     "located on disk for the configuration <CONFIG>.  "
+     "The property is defined only for library and executable targets.");
+
+  cm->DefineProperty
+    ("MAP_IMPORTED_CONFIG_<CONFIG>", cmProperty::TARGET,
+     "Map from project configuration to IMPORTED target's configuration.",
+     "List configurations of an imported target that may be used for "
+     "the current project's <CONFIG> configuration.  "
+     "Targets imported from another project may not provide the same set "
+     "of configuration names available in the current project.  "
+     "Setting this property tells CMake what imported configurations are "
+     "suitable for use when building the <CONFIG> configuration.  "
+     "The first configuration in the list found to be provided by the "
+     "imported target is selected.  If no matching configurations are "
+     "available the imported target is considered to be not found.  "
+     "This property is ignored for non-imported targets.",
+     false /* TODO: make this chained */ );
 
   cm->DefineProperty
     ("OUTPUT_NAME", cmProperty::TARGET,
@@ -481,6 +597,25 @@ void cmTarget::SetMakefile(cmMakefile* mf)
 }
 
 //----------------------------------------------------------------------------
+bool cmTarget::IsExecutableWithExports()
+{
+  if(this->GetType() == cmTarget::EXECUTABLE)
+    {
+    if(this->IsImported())
+      {
+      // The "IMPORTED_" namespace is used for properties exported
+      // from the project providing imported targets.
+      return this->GetPropertyAsBool("IMPORTED_ENABLE_EXPORTS");
+      }
+    else
+      {
+      return this->GetPropertyAsBool("ENABLE_EXPORTS");
+      }
+    }
+  return false;
+}
+
+//----------------------------------------------------------------------------
 class cmTargetTraceDependencies
 {
 public:
@@ -603,8 +738,7 @@ bool cmTargetTraceDependencies::IsUtility(std::string const& dep)
     }
 
   // Check for a non-imported target with this name.
-  if(cmTarget* t =
-     this->GlobalGenerator->FindTarget(0, util.c_str(), false))
+  if(cmTarget* t = this->GlobalGenerator->FindTarget(0, util.c_str()))
     {
     // If we find the target and the dep was given as a full path,
     // then make sure it was not a full path to something else, and
@@ -671,8 +805,7 @@ cmTargetTraceDependencies
     {
     std::string const& command = *cit->begin();
     // Look for a non-imported target with this name.
-    if(cmTarget* t =
-       this->GlobalGenerator->FindTarget(0, command.c_str(), false))
+    if(cmTarget* t = this->GlobalGenerator->FindTarget(0, command.c_str()))
       {
       if(t->GetType() == cmTarget::EXECUTABLE)
         {
@@ -1287,6 +1420,13 @@ void cmTarget::SetProperty(const char* prop, const char* value)
     }
 
   this->Properties.SetProperty(prop, value, cmProperty::TARGET);
+
+  // If imported information is being set, wipe out cached
+  // information.
+  if(this->IsImported() && strncmp(prop, "IMPORTED", 8) == 0)
+    {
+    this->ImportInfoMap.clear();
+    }
 }
 
 //----------------------------------------------------------------------------
@@ -1297,6 +1437,13 @@ void cmTarget::AppendProperty(const char* prop, const char* value)
     return;
     }
   this->Properties.AppendProperty(prop, value, cmProperty::TARGET);
+
+  // If imported information is being set, wipe out cached
+  // information.
+  if(this->IsImported() && strncmp(prop, "IMPORTED", 8) == 0)
+    {
+    this->ImportInfoMap.clear();
+    }
 }
 
 //----------------------------------------------------------------------------
@@ -1319,10 +1466,11 @@ const char* cmTarget::GetDirectory(const char* config, bool implib)
 }
 
 //----------------------------------------------------------------------------
-const char* cmTarget::ImportedGetDirectory(const char* config, bool)
+const char* cmTarget::ImportedGetDirectory(const char* config, bool implib)
 {
-  const char* location=this->GetLocation(config);
-  this->Directory = cmSystemTools::GetFilenamePath(location);
+  this->Directory =
+    cmSystemTools::GetFilenamePath(
+      this->ImportedGetFullPath(config, implib));
   return this->Directory.c_str();
 }
 
@@ -1360,18 +1508,8 @@ const char* cmTarget::GetLocation(const char* config)
 //----------------------------------------------------------------------------
 const char* cmTarget::ImportedGetLocation(const char* config)
 {
-  if ((config) && (strlen(config)))
-    {
-    std::string propertyName=cmSystemTools::UpperCase(config);
-    propertyName+="_LOCATION";
-    const char* configLocation=this->GetProperty(propertyName.c_str());
-    if ((configLocation) && (strlen(configLocation)))
-      {
-      return configLocation;
-      }
-    }
-
-  return this->GetProperty("LOCATION");
+  this->Location = this->ImportedGetFullPath(config, false);
+  return this->Location.c_str();
 }
 
 //----------------------------------------------------------------------------
@@ -1484,38 +1622,41 @@ const char *cmTarget::GetProperty(const char* prop,
     return 0;
     }
 
-  // don't use GetLocation() for imported targets, because there this
-  // calls GetProperty() to get the location...
-  if (!this->IsImported())
+  // Watch for special "computed" properties that are dependent on
+  // other properties or variables.  Always recompute them.
+  if(this->GetType() == cmTarget::EXECUTABLE ||
+     this->GetType() == cmTarget::STATIC_LIBRARY ||
+     this->GetType() == cmTarget::SHARED_LIBRARY ||
+     this->GetType() == cmTarget::MODULE_LIBRARY)
     {
-    // watch for special "computed" properties that are dependent on other
-    // properties or variables, always recompute them
-    if (!strcmp(prop,"LOCATION"))
+    if(!this->IsImported() && strcmp(prop,"LOCATION") == 0)
       {
       // Set the LOCATION property of the target.  Note that this
       // cannot take into account the per-configuration name of the
       // target because the configuration type may not be known at
-      // CMake time.  We should deprecate this feature and instead
-      // support transforming an executable target name given as the
-      // command part of custom commands into the proper path at
-      // build time.  Alternatively we could put environment
-      // variable settings in all custom commands that hold the name
-      // of the target for each configuration and then give a
-      // reference to the variable in the location.
+      // CMake time.  It is now deprecated as described in the
+      // documentation.
       this->SetProperty("LOCATION", this->GetLocation(0));
       }
 
-    // Per-configuration location can be computed.
-    int len = static_cast<int>(strlen(prop));
-    if(len > 9 && strcmp(prop+len-9, "_LOCATION") == 0)
+    // Support "LOCATION_<CONFIG>".
+    if(strncmp(prop, "LOCATION_", 9) == 0)
       {
-      std::string configName(prop, len-9);
+      std::string configName = prop+9;
       this->SetProperty(prop, this->GetLocation(configName.c_str()));
       }
-
-    if(strcmp(prop, "OBJECT_FILES") == 0)
+    else
       {
-      this->ComputeObjectFiles();
+      // Support "<CONFIG>_LOCATION" for compatiblity.
+      int len = static_cast<int>(strlen(prop));
+      if(len > 9 && strcmp(prop+len-9, "_LOCATION") == 0)
+        {
+        std::string configName(prop, len-9);
+        if(configName != "IMPORTED")
+          {
+          this->SetProperty(prop, this->GetLocation(configName.c_str()));
+          }
+        }
       }
     }
 
@@ -1750,15 +1891,57 @@ std::string cmTarget::GetPDBName(const char* config)
 }
 
 //----------------------------------------------------------------------------
+std::string cmTarget::GetSOName(const char* config)
+{
+  if(this->IsImported())
+    {
+    // Lookup the imported soname.
+    if(cmTarget::ImportInfo const* info = this->GetImportInfo(config))
+      {
+      return info->SOName;
+      }
+    else
+      {
+      return "";
+      }
+    }
+  else
+    {
+    // Compute the soname that will be built.
+    std::string name;
+    std::string soName;
+    std::string realName;
+    std::string impName;
+    std::string pdbName;
+    this->GetLibraryNames(name, soName, realName, impName, pdbName, config);
+    return soName;
+    }
+}
+
+//----------------------------------------------------------------------------
 std::string cmTarget::GetFullName(const char* config, bool implib)
 {
-  return this->GetFullNameInternal(this->GetType(), config, implib);
+  if(this->IsImported())
+    {
+    return this->GetFullNameImported(config, implib);
+    }
+  else
+    {
+    return this->GetFullNameInternal(this->GetType(), config, implib);
+    }
+}
+
+//----------------------------------------------------------------------------
+std::string cmTarget::GetFullNameImported(const char* config, bool implib)
+{
+  return cmSystemTools::GetFilenameName(
+    this->ImportedGetFullPath(config, implib));
 }
 
 //----------------------------------------------------------------------------
-void cmTarget::GetFullName(std::string& prefix, std::string& base,
-                           std::string& suffix, const char* config,
-                           bool implib)
+void cmTarget::GetFullNameComponents(std::string& prefix, std::string& base,
+                                     std::string& suffix, const char* config,
+                                     bool implib)
 {
   this->GetFullNameInternal(this->GetType(), config, implib,
                             prefix, base, suffix);
@@ -1767,6 +1950,19 @@ void cmTarget::GetFullName(std::string& prefix, std::string& base,
 //----------------------------------------------------------------------------
 std::string cmTarget::GetFullPath(const char* config, bool implib)
 {
+  if(this->IsImported())
+    {
+    return this->ImportedGetFullPath(config, implib);
+    }
+  else
+    {
+    return this->NormalGetFullPath(config, implib);
+    }
+}
+
+//----------------------------------------------------------------------------
+std::string cmTarget::NormalGetFullPath(const char* config, bool implib)
+{
   // Start with the output directory for the target.
   std::string fpath = this->GetDirectory(config, implib);
   fpath += "/";
@@ -1777,8 +1973,31 @@ std::string cmTarget::GetFullPath(const char* config, bool implib)
 }
 
 //----------------------------------------------------------------------------
-std::string cmTarget::GetFullNameInternal(TargetType type, const char* config,
-                                          bool implib)
+std::string cmTarget::ImportedGetFullPath(const char* config, bool implib)
+{
+  if(cmTarget::ImportInfo const* info = this->GetImportInfo(config))
+    {
+    if(implib)
+      {
+      return info->ImportLibrary;
+      }
+    else
+      {
+      return info->Location;
+      }
+    }
+  else
+    {
+    std::string result = this->GetName();
+    result += "-NOTFOUND";
+    return result;
+    }
+}
+
+//----------------------------------------------------------------------------
+std::string
+cmTarget::GetFullNameInternal(TargetType type, const char* config,
+                              bool implib)
 {
   std::string prefix;
   std::string base;
@@ -1795,43 +2014,6 @@ void cmTarget::GetFullNameInternal(TargetType type,
                                    std::string& outBase,
                                    std::string& outSuffix)
 {
-  if (this->IsImported())
-    {
-    this->ImportedGetFullNameInternal(type, config, implib,
-                                      outPrefix, outBase, outSuffix);
-    }
-  else
-    {
-    this->NormalGetFullNameInternal(type, config, implib,
-                                    outPrefix, outBase, outSuffix);
-    }
-}
-
-//----------------------------------------------------------------------------
-void cmTarget::ImportedGetFullNameInternal(TargetType ,
-                                           const char* config,
-                                           bool ,
-                                           std::string& outPrefix,
-                                           std::string& outBase,
-                                           std::string& outSuffix)
-{
-  // find the basename, suffix and prefix from getLocation()
-  // implib ?
-  std::string location=this->GetLocation(config);
-  outBase=cmSystemTools::GetFilenameWithoutExtension(location);
-  outSuffix = cmSystemTools::GetFilenameExtension(location);
-  outPrefix = "";
-}
-
-
-//----------------------------------------------------------------------------
-void cmTarget::NormalGetFullNameInternal(TargetType type,
-                                         const char* config,
-                                         bool implib,
-                                         std::string& outPrefix,
-                                         std::string& outBase,
-                                         std::string& outSuffix)
-{
   // Use just the target name for non-main target types.
   if(type != cmTarget::STATIC_LIBRARY &&
      type != cmTarget::SHARED_LIBRARY &&
@@ -2019,6 +2201,14 @@ void cmTarget::GetLibraryNamesInternal(std::string& name,
                                        TargetType type,
                                        const char* config)
 {
+  // This should not be called for imported targets.
+  // TODO: Split cmTarget into a class hierarchy to get compile-time
+  // enforcement of the limited imported target API.
+  if(this->IsImported())
+    {
+    abort();
+    }
+
   // Construct the name of the soname flag variable for this language.
   const char* ll =
     this->GetLinkerLanguage(
@@ -2140,6 +2330,14 @@ void cmTarget::GetExecutableNamesInternal(std::string& name,
                                           TargetType type,
                                           const char* config)
 {
+  // This should not be called for imported targets.
+  // TODO: Split cmTarget into a class hierarchy to get compile-time
+  // enforcement of the limited imported target API.
+  if(this->IsImported())
+    {
+    abort();
+    }
+
   // This versioning is supported only for executables and then only
   // when the platform supports symbolic links.
 #if defined(_WIN32) && !defined(__CYGWIN__)
@@ -2554,8 +2752,7 @@ const char* cmTarget::GetExportMacro()
   // Define the symbol for targets that export symbols.
   if(this->GetType() == cmTarget::SHARED_LIBRARY ||
      this->GetType() == cmTarget::MODULE_LIBRARY ||
-     this->GetType() == cmTarget::EXECUTABLE &&
-     this->GetPropertyAsBool("ENABLE_EXPORTS"))
+     this->IsExecutableWithExports())
     {
     if(const char* custom_export_name = this->GetProperty("DEFINE_SYMBOL"))
       {
@@ -2618,3 +2815,208 @@ bool cmTarget::IsChrpathAvailable()
 
   return true;
 }
+
+//----------------------------------------------------------------------------
+cmTarget::ImportInfo const*
+cmTarget::GetImportInfo(const char* config)
+{
+  // There is no imported information for non-imported targets.
+  if(!this->IsImported())
+    {
+    return 0;
+    }
+
+  // Lookup/compute/cache the import information for this
+  // configuration.
+  std::string config_upper;
+  if(config && *config)
+    {
+    config_upper = cmSystemTools::UpperCase(config);
+    }
+  else
+    {
+    config_upper = "NOCONFIG";
+    }
+  ImportInfoMapType::const_iterator i =
+    this->ImportInfoMap.find(config_upper);
+  if(i == this->ImportInfoMap.end())
+    {
+    ImportInfo info;
+    this->ComputeImportInfo(config_upper, info);
+    ImportInfoMapType::value_type entry(config_upper, info);
+    i = this->ImportInfoMap.insert(entry).first;
+    }
+
+  // If the location is empty then the target is not available for
+  // this configuration.
+  if(i->second.Location.empty())
+    {
+    return 0;
+    }
+
+  // Return the import information.
+  return &i->second;
+}
+
+//----------------------------------------------------------------------------
+void cmTarget::ComputeImportInfo(std::string const& desired_config,
+                                 ImportInfo& info)
+{
+  // This method finds information about an imported target from its
+  // properties.  The "IMPORTED_" namespace is reserved for properties
+  // defined by the project exporting the target.
+
+  // Track the configuration-specific property suffix.
+  std::string suffix = "_";
+  suffix += desired_config;
+
+  // Look for a mapping from the current project's configuration to
+  // the imported project's configuration.
+  std::vector<std::string> mappedConfigs;
+  {
+  std::string mapProp = "MAP_IMPORTED_CONFIG_";
+  mapProp += desired_config;
+  if(const char* mapValue = this->GetProperty(mapProp.c_str()))
+    {
+    cmSystemTools::ExpandListArgument(mapValue, mappedConfigs);
+    }
+  }
+
+  // If a mapping was found, check its configurations.
+  const char* loc = 0;
+  for(std::vector<std::string>::const_iterator mci = mappedConfigs.begin();
+      !loc && mci != mappedConfigs.end(); ++mci)
+    {
+    // Look for this configuration.
+    std::string mcUpper = cmSystemTools::UpperCase(mci->c_str());
+    std::string locProp = "IMPORTED_LOCATION_";
+    locProp += mcUpper;
+    loc = this->GetProperty(locProp.c_str());
+
+    // If it was found, use it for all properties below.
+    if(loc)
+      {
+      suffix = "_";
+      suffix += mcUpper;
+      }
+    }
+
+  // If we needed to find one of the mapped configurations but did not
+  // then the target is not found.  The project does not want any
+  // other configuration.
+  if(!mappedConfigs.empty() && !loc)
+    {
+    return;
+    }
+
+  // If we have not yet found it then there are no mapped
+  // configurations.  Look for an exact-match.
+  if(!loc)
+    {
+    std::string locProp = "IMPORTED_LOCATION";
+    locProp += suffix;
+    loc = this->GetProperty(locProp.c_str());
+    }
+
+  // If we have not yet found it then there are no mapped
+  // configurations and no exact match.
+  if(!loc)
+    {
+    // The suffix computed above is not useful.
+    suffix = "";
+
+    // Look for a configuration-less location.  This may be set by
+    // manually-written code.
+    loc = this->GetProperty("IMPORTED_LOCATION");
+    }
+
+  // If we have not yet found it then the project is willing to try
+  // any available configuration.
+  if(!loc)
+    {
+    std::vector<std::string> availableConfigs;
+    if(const char* iconfigs = this->GetProperty("IMPORTED_CONFIGURATIONS"))
+      {
+      cmSystemTools::ExpandListArgument(iconfigs, availableConfigs);
+      }
+    for(std::vector<std::string>::const_iterator
+          aci = availableConfigs.begin();
+        !loc && aci != availableConfigs.end(); ++aci)
+      {
+      suffix = "_";
+      suffix += cmSystemTools::UpperCase(availableConfigs[0]);
+      std::string locProp = "IMPORTED_LOCATION";
+      locProp += suffix;
+      loc = this->GetProperty(locProp.c_str());
+      }
+    }
+
+  // If we have not yet found it then the target is not available.
+  if(!loc)
+    {
+    return;
+    }
+
+  // A provided configuration has been chosen.  Load the
+  // configuration's properties.
+  info.Location = loc;
+
+  // Get the soname.
+  if(this->GetType() == cmTarget::SHARED_LIBRARY)
+    {
+    std::string soProp = "IMPORTED_SONAME";
+    soProp += suffix;
+    if(const char* config_soname = this->GetProperty(soProp.c_str()))
+      {
+      info.SOName = config_soname;
+      }
+    else if(const char* soname = this->GetProperty("IMPORTED_SONAME"))
+      {
+      info.SOName = soname;
+      }
+    }
+
+  // Get the import library.
+  if(this->GetType() == cmTarget::SHARED_LIBRARY ||
+     this->IsExecutableWithExports())
+    {
+    std::string impProp = "IMPORTED_IMPLIB";
+    impProp += suffix;
+    if(const char* config_implib = this->GetProperty(impProp.c_str()))
+      {
+      info.ImportLibrary = config_implib;
+      }
+    else if(const char* implib = this->GetProperty("IMPORTED_IMPLIB"))
+      {
+      info.ImportLibrary = implib;
+      }
+    }
+
+  // Get the link dependencies.
+  {
+  std::string linkProp = "IMPORTED_LINK_LIBRARIES";
+  linkProp += suffix;
+  if(const char* config_libs = this->GetProperty(linkProp.c_str()))
+    {
+    cmSystemTools::ExpandListArgument(config_libs, info.LinkLibraries);
+    }
+  else if(const char* libs = this->GetProperty("IMPORTED_LINK_LIBRARIES"))
+    {
+    cmSystemTools::ExpandListArgument(libs, info.LinkLibraries);
+    }
+  }
+}
+
+//----------------------------------------------------------------------------
+std::vector<std::string> const*
+cmTarget::GetImportedLinkLibraries(const char* config)
+{
+  if(cmTarget::ImportInfo const* info = this->GetImportInfo(config))
+    {
+    return &info->LinkLibraries;
+    }
+  else
+    {
+    return 0;
+    }
+}
diff --git a/Source/cmTarget.h b/Source/cmTarget.h
index 50e8429..b983629 100644
--- a/Source/cmTarget.h
+++ b/Source/cmTarget.h
@@ -194,6 +194,11 @@ public:
 
   bool IsImported() const {return this->IsImportedTarget;}
 
+  /** Get link libraries for the given configuration of an imported
+      target.  */
+  std::vector<std::string> const*
+  GetImportedLinkLibraries(const char* config);
+
   /** Get the directory in which this target will be built.  If the
       configuration name is given then the generator will add its
       subdirectory for that configuration.  Otherwise just the canonical
@@ -226,13 +231,16 @@ public:
   /** Get the full name of the target according to the settings in its
       makefile.  */
   std::string GetFullName(const char* config=0, bool implib = false);
-  void GetFullName(std::string& prefix,
-                   std::string& base, std::string& suffix,
-                   const char* config=0, bool implib = false);
+  void GetFullNameComponents(std::string& prefix,
+                             std::string& base, std::string& suffix,
+                             const char* config=0, bool implib = false);
 
   /** Get the name of the pdb file for the target.  */
   std::string GetPDBName(const char* config=0);
 
+  /** Get the soname of the target.  Allowed only for a shared library.  */
+  std::string GetSOName(const char* config);
+
   /** Get the full path to the target according to the settings in its
       makefile and the configuration type.  */
   std::string GetFullPath(const char* config=0, bool implib = false);
@@ -308,6 +316,10 @@ public:
   // until we have per-target object file properties.
   void GetLanguages(std::set<cmStdString>& languages) const;
 
+  /** Return whether this target is an executable with symbol exports
+      enabled.  */
+  bool IsExecutableWithExports();
+
 private:
   /**
    * A list of direct dependencies. Use in conjunction with DependencyMap.
@@ -393,20 +405,14 @@ private:
   const char* ImportedGetLocation(const char* config);
   const char* NormalGetLocation(const char* config);
 
-  void NormalGetFullNameInternal(TargetType type, const char* config,
-                                 bool implib,
-                                 std::string& outPrefix,
-                                 std::string& outBase,
-                                 std::string& outSuffix);
-  void ImportedGetFullNameInternal(TargetType type, const char* config,
-                                   bool implib,
-                                   std::string& outPrefix,
-                                   std::string& outBase,
-                                   std::string& outSuffix);
+  std::string GetFullNameImported(const char* config, bool implib);
 
   const char* ImportedGetDirectory(const char* config, bool implib);
   const char* NormalGetDirectory(const char* config, bool implib);
 
+  std::string ImportedGetFullPath(const char* config, bool implib);
+  std::string NormalGetFullPath(const char* config, bool implib);
+
 private:
   std::string Name;
   std::vector<cmCustomCommand> PreBuildCommands;
@@ -436,6 +442,19 @@ private:
   bool DLLPlatform;
   bool IsImportedTarget;
 
+  // Cache import information from properties for each configuration.
+  struct ImportInfo
+  {
+    std::string Location;
+    std::string SOName;
+    std::string ImportLibrary;
+    std::vector<std::string> LinkLibraries;
+  };
+  typedef std::map<cmStdString, ImportInfo> ImportInfoMapType;
+  ImportInfoMapType ImportInfoMap;
+  ImportInfo const* GetImportInfo(const char* config);
+  void ComputeImportInfo(std::string const& desired_config, ImportInfo& info);
+
   // The cmMakefile instance that owns this target.  This should
   // always be set.
   cmMakefile* Makefile;
-- 
cgit v0.12