[cmake-commits] king committed CMakeLists.txt 1.388 1.389 cmAddDependenciesCommand.cxx 1.16 1.17 cmAddExecutableCommand.cxx 1.32 1.33 cmAddExecutableCommand.h 1.19 1.20 cmAddLibraryCommand.cxx 1.33 1.34 cmAddLibraryCommand.h 1.20 1.21 cmComputeLinkDepends.cxx 1.2 1.3 cmComputeLinkDepends.h 1.1 1.2 cmComputeLinkInformation.cxx 1.8 1.9 cmExportBuildFileGenerator.cxx NONE 1.1 cmExportBuildFileGenerator.h NONE 1.1 cmExportCommand.cxx 1.7 1.8 cmExportCommand.h 1.6 1.7 cmExportFileGenerator.cxx NONE 1.1 cmExportFileGenerator.h NONE 1.1 cmExportInstallFileGenerator.cxx NONE 1.1 cmExportInstallFileGenerator.h NONE 1.1 cmGetPropertyCommand.cxx 1.5 1.6 cmGetTargetPropertyCommand.cxx 1.10 1.11 cmGlobalGenerator.cxx 1.218 1.219 cmGlobalGenerator.h 1.102 1.103 cmGlobalVisualStudio6Generator.cxx 1.74 1.75 cmGlobalVisualStudio71Generator.cxx 1.45 1.46 cmGlobalVisualStudio7Generator.cxx 1.95 1.96 cmGlobalVisualStudio8Generator.cxx 1.33 1.34 cmGlobalVisualStudioGenerator.cxx 1.9 1.10 cmGlobalXCodeGenerator.cxx 1.180 1.181 cmIncludeExternalMSProjectCommand.cxx 1.22 1.23 cmInstallCommand.cxx 1.39 1.40 cmInstallCommand.h 1.24 1.25 cmInstallCommandArguments.cxx 1.2 1.3 cmInstallCommandArguments.h 1.3 1.4 cmInstallDirectoryGenerator.cxx 1.5 1.6 cmInstallExportGenerator.cxx 1.7 1.8 cmInstallExportGenerator.h 1.4 1.5 cmInstallFilesCommand.cxx 1.28 1.29 cmInstallFilesGenerator.cxx 1.9 1.10 cmInstallGenerator.cxx 1.14 1.15 cmInstallGenerator.h 1.12 1.13 cmInstallProgramsCommand.cxx 1.20 1.21 cmInstallTargetGenerator.cxx 1.50 1.51 cmInstallTargetGenerator.h 1.20 1.21 cmLocalGenerator.cxx 1.260 1.261 cmLocalVisualStudio6Generator.cxx 1.138 1.139 cmMakefile.cxx 1.430 1.431 cmMakefile.h 1.221 1.222 cmMakefileExecutableTargetGenerator.cxx 1.39 1.40 cmMakefileTargetGenerator.cxx 1.86 1.87 cmSetPropertyCommand.cxx 1.4 1.5 cmSetTargetPropertiesCommand.cxx 1.8 1.9 cmTarget.cxx 1.179 1.180 cmTarget.h 1.96 1.97

cmake-commits at cmake.org cmake-commits at cmake.org
Mon Jan 28 08:38:39 EST 2008


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

Modified Files:
	CMakeLists.txt cmAddDependenciesCommand.cxx 
	cmAddExecutableCommand.cxx cmAddExecutableCommand.h 
	cmAddLibraryCommand.cxx cmAddLibraryCommand.h 
	cmComputeLinkDepends.cxx cmComputeLinkDepends.h 
	cmComputeLinkInformation.cxx cmExportCommand.cxx 
	cmExportCommand.h cmGetPropertyCommand.cxx 
	cmGetTargetPropertyCommand.cxx cmGlobalGenerator.cxx 
	cmGlobalGenerator.h cmGlobalVisualStudio6Generator.cxx 
	cmGlobalVisualStudio71Generator.cxx 
	cmGlobalVisualStudio7Generator.cxx 
	cmGlobalVisualStudio8Generator.cxx 
	cmGlobalVisualStudioGenerator.cxx cmGlobalXCodeGenerator.cxx 
	cmIncludeExternalMSProjectCommand.cxx cmInstallCommand.cxx 
	cmInstallCommand.h cmInstallCommandArguments.cxx 
	cmInstallCommandArguments.h cmInstallDirectoryGenerator.cxx 
	cmInstallExportGenerator.cxx cmInstallExportGenerator.h 
	cmInstallFilesCommand.cxx cmInstallFilesGenerator.cxx 
	cmInstallGenerator.cxx cmInstallGenerator.h 
	cmInstallProgramsCommand.cxx cmInstallTargetGenerator.cxx 
	cmInstallTargetGenerator.h cmLocalGenerator.cxx 
	cmLocalVisualStudio6Generator.cxx cmMakefile.cxx cmMakefile.h 
	cmMakefileExecutableTargetGenerator.cxx 
	cmMakefileTargetGenerator.cxx cmSetPropertyCommand.cxx 
	cmSetTargetPropertiesCommand.cxx cmTarget.cxx cmTarget.h 
Added Files:
	cmExportBuildFileGenerator.cxx cmExportBuildFileGenerator.h 
	cmExportFileGenerator.cxx cmExportFileGenerator.h 
	cmExportInstallFileGenerator.cxx 
	cmExportInstallFileGenerator.h 
Log Message:
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


Index: cmComputeLinkDepends.h
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmComputeLinkDepends.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- cmComputeLinkDepends.h	27 Jan 2008 18:42:49 -0000	1.1
+++ cmComputeLinkDepends.h	28 Jan 2008 13:38:35 -0000	1.2
@@ -66,9 +66,12 @@
   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;

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

  Program:   CMake - Cross-Platform Makefile Generator
  Module:    $RCSfile: cmExportFileGenerator.h,v $
  Language:  C++
  Date:      $Date: 2008/01/28 13:38:35 $
  Version:   $Revision: 1.1 $

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

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

=========================================================================*/
#ifndef 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

Index: cmInstallGenerator.cxx
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmInstallGenerator.cxx,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -d -r1.14 -r1.15
--- cmInstallGenerator.cxx	20 Aug 2007 20:59:06 -0000	1.14
+++ cmInstallGenerator.cxx	28 Jan 2008 13:38:35 -0000	1.15
@@ -55,7 +55,6 @@
 void cmInstallGenerator
 ::AddInstallRule(
                  std::ostream& os,
-                 const char* dest,
                  int type,
                  std::vector<std::string> const& files,
                  bool optional /* = false */,
@@ -81,6 +80,7 @@
     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 @@
 {
   // 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;
+}

Index: cmExportCommand.h
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmExportCommand.h,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- cmExportCommand.h	23 Jan 2008 15:27:59 -0000	1.6
+++ cmExportCommand.h	28 Jan 2008 13:38:35 -0000	1.7
@@ -55,7 +55,7 @@
   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 @@
   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 @@
 private:
   cmCommandArgumentGroup ArgumentGroup;
   cmCAStringVector Targets;
-  cmCAEnabler Append;
-  cmCAString Prefix;
+  cmCAString Namespace;
   cmCAString Filename;
 };
 

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

  Program:   CMake - Cross-Platform Makefile Generator
  Module:    $RCSfile: cmExportFileGenerator.cxx,v $
  Language:  C++
  Date:      $Date: 2008/01/28 13:38:35 $
  Version:   $Revision: 1.1 $

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

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

=========================================================================*/
#include "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";
}

Index: cmGlobalVisualStudio71Generator.cxx
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmGlobalVisualStudio71Generator.cxx,v
retrieving revision 1.45
retrieving revision 1.46
diff -u -d -r1.45 -r1.46
--- cmGlobalVisualStudio71Generator.cxx	23 Dec 2007 18:13:44 -0000	1.45
+++ cmGlobalVisualStudio71Generator.cxx	28 Jan 2008 13:38:35 -0000	1.46
@@ -338,8 +338,7 @@
       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";

Index: cmInstallDirectoryGenerator.cxx
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmInstallDirectoryGenerator.cxx,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- cmInstallDirectoryGenerator.cxx	2 Jul 2007 18:56:57 -0000	1.5
+++ cmInstallDirectoryGenerator.cxx	28 Jan 2008 13:38:35 -0000	1.6
@@ -48,8 +48,7 @@
   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(),

Index: cmGlobalGenerator.cxx
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmGlobalGenerator.cxx,v
retrieving revision 1.218
retrieving revision 1.219
diff -u -d -r1.218 -r1.219
--- cmGlobalGenerator.cxx	22 Jan 2008 14:13:03 -0000	1.218
+++ cmGlobalGenerator.cxx	28 Jan 2008 13:38:35 -0000	1.219
@@ -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 @@
   this->LocalGenerators.clear();
   this->TargetDependencies.clear();
   this->TotalTargets.clear();
-  this->ImportedTotalTargets.clear();
   this->LocalGeneratorToTargetMap.clear();
   this->ProjectMap.clear();
 
@@ -1321,9 +1320,8 @@
 
 
 //----------------------------------------------------------------------------
-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 @@
     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 @@
       {
       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 @@
     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 @@
 {
   // 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 @@
 
 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(

Index: cmAddLibraryCommand.cxx
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmAddLibraryCommand.cxx,v
retrieving revision 1.33
retrieving revision 1.34
diff -u -d -r1.33 -r1.34
--- cmAddLibraryCommand.cxx	23 Jan 2008 15:27:59 -0000	1.33
+++ cmAddLibraryCommand.cxx	28 Jan 2008 13:38:35 -0000	1.34
@@ -46,6 +46,7 @@
   // 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 @@
       {
       ++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 @@
     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())
     {

Index: cmTarget.h
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmTarget.h,v
retrieving revision 1.96
retrieving revision 1.97
diff -u -d -r1.96 -r1.97
--- cmTarget.h	22 Jan 2008 14:13:03 -0000	1.96
+++ cmTarget.h	28 Jan 2008 13:38:36 -0000	1.97
@@ -194,6 +194,11 @@
 
   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 @@
   /** 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 @@
   // 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 @@
   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 @@
   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;

Index: CMakeLists.txt
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/CMakeLists.txt,v
retrieving revision 1.388
retrieving revision 1.389
diff -u -d -r1.388 -r1.389
--- CMakeLists.txt	27 Jan 2008 18:42:49 -0000	1.388
+++ CMakeLists.txt	28 Jan 2008 13:38:35 -0000	1.389
@@ -121,6 +121,12 @@
   cmExprLexer.cxx
   cmExprParser.cxx
   cmExprParserHelper.cxx
+  cmExportBuildFileGenerator.h
+  cmExportBuildFileGenerator.cxx
+  cmExportFileGenerator.h
+  cmExportFileGenerator.cxx
+  cmExportInstallFileGenerator.h
+  cmExportInstallFileGenerator.cxx
   cmExtraEclipseCDT4Generator.cxx
   cmExtraEclipseCDT4Generator.h
   cmFileTimeComparison.cxx

Index: cmMakefileTargetGenerator.cxx
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmMakefileTargetGenerator.cxx,v
retrieving revision 1.86
retrieving revision 1.87
diff -u -d -r1.86 -r1.87
--- cmMakefileTargetGenerator.cxx	18 Jan 2008 00:29:43 -0000	1.86
+++ cmMakefileTargetGenerator.cxx	28 Jan 2008 13:38:36 -0000	1.87
@@ -869,7 +869,7 @@
   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 @@
       {
       // 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()))

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

  Program:   CMake - Cross-Platform Makefile Generator
  Module:    $RCSfile: cmExportBuildFileGenerator.cxx,v $
  Language:  C++
  Date:      $Date: 2008/01/28 13:38:35 $
  Version:   $Revision: 1.1 $

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

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

=========================================================================*/
#include "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());
}

Index: cmInstallCommand.h
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmInstallCommand.h,v
retrieving revision 1.24
retrieving revision 1.25
diff -u -d -r1.24 -r1.25
--- cmInstallCommand.h	23 Jan 2008 15:27:59 -0000	1.24
+++ cmInstallCommand.h	28 Jan 2008 13:38:35 -0000	1.25
@@ -98,7 +98,7 @@
       "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 @@
       "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 @@
       "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 "

Index: cmTarget.cxx
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmTarget.cxx,v
retrieving revision 1.179
retrieving revision 1.180
diff -u -d -r1.179 -r1.180
--- cmTarget.cxx	27 Jan 2008 18:42:49 -0000	1.179
+++ cmTarget.cxx	28 Jan 2008 13:38:36 -0000	1.180
@@ -154,6 +154,96 @@
      "(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 @@
 
   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 @@
 }
 
 //----------------------------------------------------------------------------
+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 @@
     }
 
   // 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 @@
     {
     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 @@
     }
 
   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 @@
     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::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::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 @@
     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::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);
+    }
 }
 
 //----------------------------------------------------------------------------
-void cmTarget::GetFullName(std::string& prefix, std::string& base,
-                           std::string& suffix, const char* config,
-                           bool implib)
+std::string cmTarget::GetFullNameImported(const char* config, bool implib)
+{
+  return cmSystemTools::GetFilenameName(
+    this->ImportedGetFullPath(config, 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 @@
 //----------------------------------------------------------------------------
 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::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 @@
                                    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 @@
                                        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 @@
                                           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 @@
   // 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 @@
 
   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;
+    }
+}

Index: cmAddExecutableCommand.cxx
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmAddExecutableCommand.cxx,v
retrieving revision 1.32
retrieving revision 1.33
diff -u -d -r1.32 -r1.33
--- cmAddExecutableCommand.cxx	23 Jan 2008 15:27:59 -0000	1.32
+++ cmAddExecutableCommand.cxx	28 Jan 2008 13:38:35 -0000	1.33
@@ -51,7 +51,7 @@
       ++s;
       excludeFromAll = true;
       }
-    else if(*s == "IMPORT")
+    else if(*s == "IMPORTED")
      {
      ++s;
      importTarget = true;
@@ -61,12 +61,60 @@
       break;
       }
     }
-    
-  if (importTarget)
+
+  // Special modifiers are not allowed with IMPORTED signature.
+  if(importTarget && (use_win32 || use_macbundle || excludeFromAll))
     {
-    this->Makefile->AddNewTarget(cmTarget::EXECUTABLE, exename.c_str(), true);
+    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)
+    {
+    // 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())
     {

Index: cmInstallGenerator.h
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmInstallGenerator.h,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -d -r1.12 -r1.13
--- cmInstallGenerator.h	2 Jul 2007 18:56:57 -0000	1.12
+++ cmInstallGenerator.h	28 Jan 2008 13:38:35 -0000	1.13
@@ -62,8 +62,8 @@
   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 @@
     { 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);

Index: cmGlobalVisualStudio8Generator.cxx
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmGlobalVisualStudio8Generator.cxx,v
retrieving revision 1.33
retrieving revision 1.34
diff -u -d -r1.33 -r1.34
--- cmGlobalVisualStudio8Generator.cxx	2 Jan 2008 20:55:18 -0000	1.33
+++ cmGlobalVisualStudio8Generator.cxx	28 Jan 2008 13:38:35 -0000	1.34
@@ -138,7 +138,7 @@
       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 " 

Index: cmGlobalXCodeGenerator.cxx
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmGlobalXCodeGenerator.cxx,v
retrieving revision 1.180
retrieving revision 1.181
diff -u -d -r1.180 -r1.181
--- cmGlobalXCodeGenerator.cxx	22 Jan 2008 14:13:03 -0000	1.180
+++ cmGlobalXCodeGenerator.cxx	28 Jan 2008 13:38:35 -0000	1.181
@@ -279,7 +279,7 @@
   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 @@
   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 @@
       {
       // 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 @@
       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.

Index: cmGetTargetPropertyCommand.cxx
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmGetTargetPropertyCommand.cxx,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -d -r1.10 -r1.11
--- cmGetTargetPropertyCommand.cxx	23 Jan 2008 15:27:59 -0000	1.10
+++ cmGetTargetPropertyCommand.cxx	28 Jan 2008 13:38:35 -0000	1.11
@@ -28,9 +28,7 @@
   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());

Index: cmLocalVisualStudio6Generator.cxx
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmLocalVisualStudio6Generator.cxx,v
retrieving revision 1.138
retrieving revision 1.139
diff -u -d -r1.138 -r1.139
--- cmLocalVisualStudio6Generator.cxx	22 Jan 2008 14:13:03 -0000	1.138
+++ cmLocalVisualStudio6Generator.cxx	28 Jan 2008 13:38:35 -0000	1.139
@@ -1061,8 +1061,7 @@
       // 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

Index: cmIncludeExternalMSProjectCommand.cxx
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmIncludeExternalMSProjectCommand.cxx,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -d -r1.22 -r1.23
--- cmIncludeExternalMSProjectCommand.cxx	23 Jan 2008 15:27:59 -0000	1.22
+++ cmIncludeExternalMSProjectCommand.cxx	28 Jan 2008 13:38:35 -0000	1.23
@@ -51,8 +51,7 @@
 
     // 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;

Index: cmInstallCommand.cxx
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmInstallCommand.cxx,v
retrieving revision 1.39
retrieving revision 1.40
diff -u -d -r1.39 -r1.40
--- cmInstallCommand.cxx	23 Jan 2008 15:27:59 -0000	1.39
+++ cmInstallCommand.cxx	28 Jan 2008 13:38:35 -0000	1.40
@@ -300,7 +300,7 @@
       ++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 @@
         // 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 @@
     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 @@
 {
   // 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 @@
     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;
 }
 

Index: cmGetPropertyCommand.cxx
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmGetPropertyCommand.cxx,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- cmGetPropertyCommand.cxx	23 Jan 2008 15:27:59 -0000	1.5
+++ cmGetPropertyCommand.cxx	28 Jan 2008 13:38:35 -0000	1.6
@@ -260,9 +260,7 @@
     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()));
     }

Index: cmMakefileExecutableTargetGenerator.cxx
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmMakefileExecutableTargetGenerator.cxx,v
retrieving revision 1.39
retrieving revision 1.40
diff -u -d -r1.39 -r1.40
--- cmMakefileExecutableTargetGenerator.cxx	28 Dec 2007 19:59:06 -0000	1.39
+++ cmMakefileExecutableTargetGenerator.cxx	28 Jan 2008 13:38:36 -0000	1.40
@@ -259,7 +259,7 @@
     }
 
   // 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 @@
     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.

Index: cmGlobalVisualStudio7Generator.cxx
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmGlobalVisualStudio7Generator.cxx,v
retrieving revision 1.95
retrieving revision 1.96
diff -u -d -r1.95 -r1.96
--- cmGlobalVisualStudio7Generator.cxx	15 Jan 2008 19:00:52 -0000	1.95
+++ cmGlobalVisualStudio7Generator.cxx	28 Jan 2008 13:38:35 -0000	1.96
@@ -611,8 +611,7 @@
       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)

Index: cmInstallExportGenerator.h
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmInstallExportGenerator.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- cmInstallExportGenerator.h	27 Aug 2007 20:04:57 -0000	1.4
+++ cmInstallExportGenerator.h	28 Jan 2008 13:38:35 -0000	1.5
@@ -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 @@
 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

Index: cmGlobalGenerator.h
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmGlobalGenerator.h,v
retrieving revision 1.102
retrieving revision 1.103
diff -u -d -r1.102 -r1.103
--- cmGlobalGenerator.h	22 Jan 2008 14:13:03 -0000	1.102
+++ cmGlobalGenerator.h	28 Jan 2008 13:38:35 -0000	1.103
@@ -186,9 +186,7 @@
   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 @@
   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;
 

Index: cmInstallCommandArguments.h
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmInstallCommandArguments.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- cmInstallCommandArguments.h	31 Aug 2007 20:52:32 -0000	1.3
+++ cmInstallCommandArguments.h	28 Jan 2008 13:38:35 -0000	1.4
@@ -43,8 +43,6 @@
     // 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 @@
     cmCAStringVector Configurations;
     cmCAEnabler Optional;
 
-    std::string AbsDestination;
+    std::string DestinationString;
     std::string PermissionsString;
 
     cmInstallCommandArguments* GenericArguments;

Index: cmAddExecutableCommand.h
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmAddExecutableCommand.h,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -d -r1.19 -r1.20
--- cmAddExecutableCommand.h	23 Jan 2008 15:27:59 -0000	1.19
+++ cmAddExecutableCommand.h	28 Jan 2008 13:38:35 -0000	1.20
@@ -90,6 +90,24 @@
       "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."
       ;
     }
 

Index: cmMakefile.cxx
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmMakefile.cxx,v
retrieving revision 1.430
retrieving revision 1.431
diff -u -d -r1.430 -r1.431
--- cmMakefile.cxx	24 Jan 2008 12:37:08 -0000	1.430
+++ cmMakefile.cxx	28 Jan 2008 13:38:35 -0000	1.431
@@ -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 @@
     {
     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 @@
                                    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 @@
   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 @@
       // 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 @@
   // 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 @@
     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 @@
                                     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 @@
   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 @@
 }
 
 
-cmTarget* cmMakefile::FindTarget(const char* name, bool useImportedTargets)
+cmTarget* cmMakefile::FindTarget(const char* name)
 {
   cmTargets& tgts = this->GetTargets();
 
@@ -2879,15 +2879,6 @@
     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 @@
      "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);
+}

Index: cmLocalGenerator.cxx
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmLocalGenerator.cxx,v
retrieving revision 1.260
retrieving revision 1.261
diff -u -d -r1.260 -r1.261
--- cmLocalGenerator.cxx	23 Jan 2008 18:30:55 -0000	1.260
+++ cmLocalGenerator.cxx	28 Jan 2008 13:38:35 -0000	1.261
@@ -1809,7 +1809,7 @@
     }
 
   // 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 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 @@
       {
       // 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 @@
           // 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);

Index: cmInstallExportGenerator.cxx
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmInstallExportGenerator.cxx,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- cmInstallExportGenerator.cxx	30 Aug 2007 20:22:01 -0000	1.7
+++ cmInstallExportGenerator.cxx	28 Jan 2008 13:38:35 -0000	1.8
@@ -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);
 }
 
-/* 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)
+//----------------------------------------------------------------------------
+cmInstallExportGenerator::~cmInstallExportGenerator()
 {
-  if (generator == 0) // nothing to do
+  delete this->EFGen;
+}
+
+//----------------------------------------------------------------------------
+void cmInstallExportGenerator::ComputeTempDir()
+{
+  // 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())
-      {
-      std::string destinationFilename = generator->GetDestination();
-      destinationFilename += "/";
-      destinationFilename += generator->GetInstallFilename(0);
-      twp->Properties[propertyName.c_str()] = destinationFilename;
-      }
-    else
+    // 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)
       {
-      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))
-    {
-    return false;
-    }
-
-  this->Name = name;
+  // Get the export set requested.
+  ExportSet const* exportSet =
+    this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
+    ->GetExportSet(this->Name.c_str());
 
-  /* 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)
+  // Skip empty sets.
+  if(!exportSet)
     {
-    std::string targetName = (*it)->Target->GetName();
+    cmOStringStream e;
+    e << "INSTALL(EXPORT) given unknown export \"" << this->Name << "\"";
+    cmSystemTools::Error(e.str().c_str());
+    return;
+    }
 
-    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;
-        }
-      }
+  // Create the temporary directory in which to store the files.
+  this->ComputeTempDir();
+  cmSystemTools::MakeDirectory(this->TempDir.c_str());
 
-    if (targetWithProps == 0)
-      {
-      targetWithProps = new cmTargetWithProperties((*it)->Target);
-      this->Targets.push_back(targetWithProps);
-      }
+  // Construct a temporary location for the file.
+  this->MainImportFile = this->TempDir;
+  this->MainImportFile += "/";
+  this->MainImportFile += this->FileName;
 
-    if (this->AddInstallLocations(targetWithProps, (*it)->ArchiveGenerator, 
-                                  "ARCHIVE_") == false)
-      {
-      return false;
-      }
-    if (this->AddInstallLocations(targetWithProps, (*it)->RuntimeGenerator, 
-                                  "") == false)
+  // 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())
+    {
+    if(this->ConfigurationName && *this->ConfigurationName)
       {
-      return false;
+      this->EFGen->AddConfiguration(this->ConfigurationName);
       }
-    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)
-    {
-    return;
-    }
+  // Create the main install rules first.
+  this->cmInstallGenerator::GenerateScriptConfigs(os, indent);
 
-  /* 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)
+  // 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)
     {
-      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";
+    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();
     }
-
-  // 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);
 }

Index: cmAddLibraryCommand.h
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmAddLibraryCommand.h,v
retrieving revision 1.20
retrieving revision 1.21
diff -u -d -r1.20 -r1.21
--- cmAddLibraryCommand.h	23 Jan 2008 15:27:59 -0000	1.20
+++ cmAddLibraryCommand.h	28 Jan 2008 13:38:35 -0000	1.21
@@ -73,7 +73,26 @@
       "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);

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

  Program:   CMake - Cross-Platform Makefile Generator
  Module:    $RCSfile: cmExportBuildFileGenerator.h,v $
  Language:  C++
  Date:      $Date: 2008/01/28 13:38:35 $
  Version:   $Revision: 1.1 $

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

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

=========================================================================*/
#ifndef 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

Index: cmInstallTargetGenerator.cxx
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmInstallTargetGenerator.cxx,v
retrieving revision 1.50
retrieving revision 1.51
diff -u -d -r1.50 -r1.51
--- cmInstallTargetGenerator.cxx	10 Jan 2008 20:17:23 -0000	1.50
+++ cmInstallTargetGenerator.cxx	28 Jan 2008 13:38:35 -0000	1.51
@@ -113,22 +113,11 @@
 
   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 @@
                              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 @@
   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 @@
       {
       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)
           {

Index: cmGlobalVisualStudio6Generator.cxx
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmGlobalVisualStudio6Generator.cxx,v
retrieving revision 1.74
retrieving revision 1.75
diff -u -d -r1.74 -r1.75
--- cmGlobalVisualStudio6Generator.cxx	22 Oct 2007 16:48:39 -0000	1.74
+++ cmGlobalVisualStudio6Generator.cxx	28 Jan 2008 13:38:35 -0000	1.75
@@ -399,7 +399,7 @@
       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";

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

  Program:   CMake - Cross-Platform Makefile Generator
  Module:    $RCSfile: cmExportInstallFileGenerator.cxx,v $
  Language:  C++
  Date:      $Date: 2008/01/28 13:38:35 $
  Version:   $Revision: 1.1 $

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

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

=========================================================================*/
#include "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());
}

Index: cmGlobalVisualStudioGenerator.cxx
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmGlobalVisualStudioGenerator.cxx,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -d -r1.9 -r1.10
--- cmGlobalVisualStudioGenerator.cxx	21 Dec 2007 20:04:06 -0000	1.9
+++ cmGlobalVisualStudioGenerator.cxx	28 Jan 2008 13:38:35 -0000	1.10
@@ -270,7 +270,7 @@
         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 @@
     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 @@
     {
     // 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 =

Index: cmSetPropertyCommand.cxx
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmSetPropertyCommand.cxx,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- cmSetPropertyCommand.cxx	23 Jan 2008 15:27:59 -0000	1.4
+++ cmSetPropertyCommand.cxx	28 Jan 2008 13:38:36 -0000	1.5
@@ -220,9 +220,7 @@
   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))

Index: cmInstallTargetGenerator.h
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmInstallTargetGenerator.h,v
retrieving revision 1.20
retrieving revision 1.21
diff -u -d -r1.20 -r1.21
--- cmInstallTargetGenerator.h	19 Dec 2007 08:56:13 -0000	1.20
+++ cmInstallTargetGenerator.h	28 Jan 2008 13:38:35 -0000	1.21
@@ -40,6 +40,9 @@
   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);

Index: cmSetTargetPropertiesCommand.cxx
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmSetTargetPropertiesCommand.cxx,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -d -r1.8 -r1.9
--- cmSetTargetPropertiesCommand.cxx	23 Jan 2008 15:27:59 -0000	1.8
+++ cmSetTargetPropertiesCommand.cxx	28 Jan 2008 13:38:36 -0000	1.9
@@ -95,9 +95,7 @@
                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;

Index: cmInstallCommandArguments.cxx
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmInstallCommandArguments.cxx,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- cmInstallCommandArguments.cxx	24 Aug 2007 18:27:18 -0000	1.2
+++ cmInstallCommandArguments.cxx	28 Jan 2008 13:38:35 -0000	1.3
@@ -44,9 +44,9 @@
 
 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 @@
     {
     return false;
     }
-  this->ComputeDestination(this->Destination.GetString(),this->AbsDestination);
-
+  this->DestinationString = this->Destination.GetString();
+  cmSystemTools::ConvertToUnixSlashes(this->DestinationString);
   return true;
 }
 
@@ -174,23 +174,3 @@
   // 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);
-}
-

Index: cmComputeLinkDepends.cxx
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmComputeLinkDepends.cxx,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- cmComputeLinkDepends.cxx	27 Jan 2008 20:09:58 -0000	1.2
+++ cmComputeLinkDepends.cxx	28 Jan 2008 13:38:35 -0000	1.3
@@ -158,7 +158,7 @@
 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 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 @@
   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::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 @@
   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 @@
     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)

Index: cmMakefile.h
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmMakefile.h,v
retrieving revision 1.221
retrieving revision 1.222
diff -u -d -r1.221 -r1.222
--- cmMakefile.h	24 Jan 2008 12:37:08 -0000	1.221
+++ cmMakefile.h	28 Jan 2008 13:38:36 -0000	1.222
@@ -172,9 +172,10 @@
   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 @@
    * 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 @@
 
   // libraries, classes, and executables
   cmTargets Targets;
-  cmTargets ImportedTargets;
   std::vector<cmSourceFile*> SourceFiles;
 
   // Tests
@@ -842,6 +844,10 @@
 
   // stack of list files being read 
   std::deque<cmStdString> ListFileStack;
+
+  cmTarget* FindBasicTarget(const char* name);
+  std::vector<cmTarget*> ImportedTargetsOwned;
+  std::map<cmStdString, cmTarget*> ImportedTargets;
 };
 
 

Index: cmInstallFilesGenerator.cxx
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmInstallFilesGenerator.cxx,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -d -r1.9 -r1.10
--- cmInstallFilesGenerator.cxx	2 Jul 2007 18:56:57 -0000	1.9
+++ cmInstallFilesGenerator.cxx	28 Jan 2008 13:38:35 -0000	1.10
@@ -47,7 +47,7 @@
   // 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),

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

  Program:   CMake - Cross-Platform Makefile Generator
  Module:    $RCSfile: cmExportInstallFileGenerator.h,v $
  Language:  C++
  Date:      $Date: 2008/01/28 13:38:35 $
  Version:   $Revision: 1.1 $

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

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

=========================================================================*/
#ifndef 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

Index: cmAddDependenciesCommand.cxx
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmAddDependenciesCommand.cxx,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -d -r1.16 -r1.17
--- cmAddDependenciesCommand.cxx	23 Jan 2008 15:27:59 -0000	1.16
+++ cmAddDependenciesCommand.cxx	28 Jan 2008 13:38:35 -0000	1.17
@@ -32,7 +32,7 @@
 
   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();

Index: cmInstallFilesCommand.cxx
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmInstallFilesCommand.cxx,v
retrieving revision 1.28
retrieving revision 1.29
diff -u -d -r1.28 -r1.29
--- cmInstallFilesCommand.cxx	23 Jan 2008 15:27:59 -0000	1.28
+++ cmInstallFilesCommand.cxx	28 Jan 2008 13:38:35 -0000	1.29
@@ -119,9 +119,8 @@
 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.

Index: cmInstallProgramsCommand.cxx
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmInstallProgramsCommand.cxx,v
retrieving revision 1.20
retrieving revision 1.21
diff -u -d -r1.20 -r1.21
--- cmInstallProgramsCommand.cxx	23 Jan 2008 15:27:59 -0000	1.20
+++ cmInstallProgramsCommand.cxx	28 Jan 2008 13:38:35 -0000	1.21
@@ -80,9 +80,8 @@
     }
 
   // 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.

Index: cmComputeLinkInformation.cxx
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmComputeLinkInformation.cxx,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -d -r1.8 -r1.9
--- cmComputeLinkInformation.cxx	27 Jan 2008 18:42:49 -0000	1.8
+++ cmComputeLinkInformation.cxx	28 Jan 2008 13:38:35 -0000	1.9
@@ -301,11 +301,8 @@
 {
   // 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 @@
       // 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 @@
 
   // 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);

Index: cmExportCommand.cxx
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmExportCommand.cxx,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- cmExportCommand.cxx	23 Jan 2008 15:27:59 -0000	1.7
+++ cmExportCommand.cxx	28 Jan 2008 13:38:35 -0000	1.8
@@ -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 @@
   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()))
       {
-      std::string e = "detected unknown target: " + *currentTarget;
-      this->SetError(e.c_str());
-      cmSystemTools::SetFatalErrorOccured();
+      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
+      {
+      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;
 }



More information about the Cmake-commits mailing list