浏览代码

ENH: add INSTALL(EXPORT ...) mode and INSTALL( TARGETS ... EXPORT <set> ) ,
tests still have to be added

Alex

Alexander Neundorf 18 年之前
父节点
当前提交
c0d000d234

+ 1 - 0
Source/CMakeLists.txt

@@ -115,6 +115,7 @@ SET(SRCS
   cmGlobalUnixMakefileGenerator3.h
   cmGlobalUnixMakefileGenerator3.h
   cmInstallGenerator.h
   cmInstallGenerator.h
   cmInstallGenerator.cxx
   cmInstallGenerator.cxx
+  cmInstallExportGenerator.cxx
   cmInstallFilesGenerator.h
   cmInstallFilesGenerator.h
   cmInstallFilesGenerator.cxx
   cmInstallFilesGenerator.cxx
   cmInstallScriptGenerator.h
   cmInstallScriptGenerator.h

+ 40 - 2
Source/cmGlobalGenerator.cxx

@@ -21,6 +21,7 @@
 #include "cmMakefile.h"
 #include "cmMakefile.h"
 #include "cmSourceFile.h"
 #include "cmSourceFile.h"
 #include "cmVersion.h"
 #include "cmVersion.h"
+#include "cmInstallExportGenerator.h"
 
 
 #include <stdlib.h> // required for atof
 #include <stdlib.h> // required for atof
 
 
@@ -56,8 +57,7 @@ cmGlobalGenerator::cmGlobalGenerator()
 cmGlobalGenerator::~cmGlobalGenerator()
 cmGlobalGenerator::~cmGlobalGenerator()
 {
 {
   // Delete any existing cmLocalGenerators
   // Delete any existing cmLocalGenerators
-  unsigned int i;
-  for (i = 0; i < this->LocalGenerators.size(); ++i)
+  for (unsigned int i = 0; i < this->LocalGenerators.size(); ++i)
     {
     {
     delete this->LocalGenerators[i];
     delete this->LocalGenerators[i];
     }
     }
@@ -67,6 +67,17 @@ cmGlobalGenerator::~cmGlobalGenerator()
     {
     {
     delete this->ExtraGenerator;
     delete this->ExtraGenerator;
     }
     }
+
+  for (std::map<cmStdString, std::vector<cmTargetExport*> >::iterator 
+       setIt = this->ExportSets.begin();
+       setIt != this->ExportSets.end();
+       ++setIt)
+    {
+      for (unsigned int i = 0; i < setIt->second.size(); ++i)
+        {
+        delete setIt->second[i];
+        }
+    }
 }
 }
 
 
 // Find the make program for the generator, required for try compiles
 // Find the make program for the generator, required for try compiles
@@ -1014,6 +1025,33 @@ void cmGlobalGenerator::AddInstallComponent(const char* component)
     }
     }
 }
 }
 
 
+void cmGlobalGenerator::AddTargetToExports(const char* exportSetName, 
+                                           cmTarget* target, 
+                                           cmInstallTargetGenerator* archive,
+                                           cmInstallTargetGenerator* runTime,
+                                           cmInstallTargetGenerator* library)
+{
+  if ((exportSetName) && (*exportSetName) && (target))
+    {
+    cmTargetExport* te = new cmTargetExport(target, archive, runTime, library);
+    this->ExportSets[exportSetName].push_back(te);
+    }
+}
+
+const std::vector<cmTargetExport*>* cmGlobalGenerator::GetExportSet(
+                                                        const char* name) const
+{
+  std::map<cmStdString, std::vector<cmTargetExport*> >::const_iterator 
+                                     exportSetIt = this->ExportSets.find(name);
+  if (exportSetIt != this->ExportSets.end())
+    {
+    return &exportSetIt->second;
+    }
+
+  return 0;
+}
+
+
 void cmGlobalGenerator::EnableInstallTarget()
 void cmGlobalGenerator::EnableInstallTarget()
 {
 {
   this->InstallTargetEnabled = true;
   this->InstallTargetEnabled = true;

+ 14 - 1
Source/cmGlobalGenerator.h

@@ -27,6 +27,8 @@ class cmMakefile;
 class cmLocalGenerator;
 class cmLocalGenerator;
 class cmExternalMakefileProjectGenerator;
 class cmExternalMakefileProjectGenerator;
 class cmTarget;
 class cmTarget;
+class cmTargetExport;
+class cmInstallTargetGenerator;
 
 
 /** \class cmGlobalGenerator
 /** \class cmGlobalGenerator
  * \brief Responable for overseeing the generation process for the entire tree
  * \brief Responable for overseeing the generation process for the entire tree
@@ -129,8 +131,17 @@ public:
   const char* GetExtraGeneratorName() const;
   const char* GetExtraGeneratorName() const;
 
 
   void AddInstallComponent(const char* component);
   void AddInstallComponent(const char* component);
+
+  ///! Add one installed target to the sets of the exports
+  void AddTargetToExports(const char* exportSet, cmTarget* target, 
+                          cmInstallTargetGenerator* archive,
+                          cmInstallTargetGenerator* runTime,
+                          cmInstallTargetGenerator* library);
+  ///! Get the export target set with the   given name
+  const std::vector<cmTargetExport*>* GetExportSet(const char* name) const;
+
   void EnableInstallTarget();
   void EnableInstallTarget();
-  
+
   int TryCompileTimeout;
   int TryCompileTimeout;
   
   
   bool GetForceUnixPaths() {return this->ForceUnixPaths;}
   bool GetForceUnixPaths() {return this->ForceUnixPaths;}
@@ -231,6 +242,8 @@ protected:
   // Set of named installation components requested by the project.
   // Set of named installation components requested by the project.
   std::set<cmStdString> InstallComponents;
   std::set<cmStdString> InstallComponents;
   bool InstallTargetEnabled;
   bool InstallTargetEnabled;
+  // Sets of named target exports
+  std::map<cmStdString, std::vector<cmTargetExport*> > ExportSets;
 
 
   // Manifest of all targets that will be built for each configuration.
   // Manifest of all targets that will be built for each configuration.
   // This is computed just before local generators generate.
   // This is computed just before local generators generate.

+ 186 - 0
Source/cmInstallCommand.cxx

@@ -20,6 +20,7 @@
 #include "cmInstallFilesGenerator.h"
 #include "cmInstallFilesGenerator.h"
 #include "cmInstallScriptGenerator.h"
 #include "cmInstallScriptGenerator.h"
 #include "cmInstallTargetGenerator.h"
 #include "cmInstallTargetGenerator.h"
+#include "cmInstallExportGenerator.h"
 
 
 #include <cmsys/Glob.hxx>
 #include <cmsys/Glob.hxx>
 
 
@@ -62,6 +63,10 @@ bool cmInstallCommand::InitialPass(std::vector<std::string> const& args)
     {
     {
     return this->HandleDirectoryMode(args);
     return this->HandleDirectoryMode(args);
     }
     }
+  else if(args[0] == "EXPORT")
+    {
+    return this->HandleExportMode(args);
+    }
 
 
   // Unknown mode.
   // Unknown mode.
   cmStdString e = "called with unknown mode ";
   cmStdString e = "called with unknown mode ";
@@ -135,6 +140,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
   bool doing_permissions = false;
   bool doing_permissions = false;
   bool doing_component = false;
   bool doing_component = false;
   bool doing_configurations = false;
   bool doing_configurations = false;
+  bool doing_export = false;
   bool archive_settings = true;
   bool archive_settings = true;
   bool library_settings = true;
   bool library_settings = true;
   bool runtime_settings = true;
   bool runtime_settings = true;
@@ -148,6 +154,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
   std::string archive_component;
   std::string archive_component;
   std::string library_component;
   std::string library_component;
   std::string runtime_component;
   std::string runtime_component;
+  std::string exportName;
   std::vector<std::string> archive_configurations;
   std::vector<std::string> archive_configurations;
   std::vector<std::string> library_configurations;
   std::vector<std::string> library_configurations;
   std::vector<std::string> runtime_configurations;
   std::vector<std::string> runtime_configurations;
@@ -164,6 +171,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
       doing_permissions = false;
       doing_permissions = false;
       doing_component = false;
       doing_component = false;
       doing_configurations = false;
       doing_configurations = false;
+      doing_export = false;
       }
       }
     else if(args[i] == "PERMISSIONS")
     else if(args[i] == "PERMISSIONS")
       {
       {
@@ -173,6 +181,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
       doing_permissions = true;
       doing_permissions = true;
       doing_component = false;
       doing_component = false;
       doing_configurations = false;
       doing_configurations = false;
+      doing_export = false;
       }
       }
     else if(args[i] == "COMPONENT")
     else if(args[i] == "COMPONENT")
       {
       {
@@ -182,6 +191,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
       doing_permissions = false;
       doing_permissions = false;
       doing_component = true;
       doing_component = true;
       doing_configurations = false;
       doing_configurations = false;
+      doing_export = false;
       }
       }
     else if(args[i] == "CONFIGURATIONS")
     else if(args[i] == "CONFIGURATIONS")
       {
       {
@@ -191,6 +201,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
       doing_permissions = false;
       doing_permissions = false;
       doing_component = false;
       doing_component = false;
       doing_configurations = true;
       doing_configurations = true;
+      doing_export = false;
       }
       }
     else if(args[i] == "ARCHIVE")
     else if(args[i] == "ARCHIVE")
       {
       {
@@ -200,6 +211,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
       doing_permissions = false;
       doing_permissions = false;
       doing_component = false;
       doing_component = false;
       doing_configurations = false;
       doing_configurations = false;
+      doing_export = false;
       archive_settings = true;
       archive_settings = true;
       library_settings = false;
       library_settings = false;
       runtime_settings = false;
       runtime_settings = false;
@@ -212,6 +224,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
       doing_permissions = false;
       doing_permissions = false;
       doing_component = false;
       doing_component = false;
       doing_configurations = false;
       doing_configurations = false;
+      doing_export = false;
       archive_settings = false;
       archive_settings = false;
       library_settings = true;
       library_settings = true;
       runtime_settings = false;
       runtime_settings = false;
@@ -224,10 +237,21 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
       doing_permissions = false;
       doing_permissions = false;
       doing_component = false;
       doing_component = false;
       doing_configurations = false;
       doing_configurations = false;
+      doing_export = false;
       archive_settings = false;
       archive_settings = false;
       library_settings = false;
       library_settings = false;
       runtime_settings = true;
       runtime_settings = true;
       }
       }
+    else if(args[i] == "EXPORT")
+      {
+      // Switch to setting only runtime properties.
+      doing_targets = false;
+      doing_destination = false;
+      doing_permissions = false;
+      doing_component = false;
+      doing_configurations = false;
+      doing_export = true;
+      }
     else if(args[i] == "OPTIONAL")
     else if(args[i] == "OPTIONAL")
       {
       {
       // Set the optional property.
       // Set the optional property.
@@ -370,6 +394,11 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
         runtime_configurations.push_back(args[i]);
         runtime_configurations.push_back(args[i]);
         }
         }
       }
       }
+    else if(doing_export)
+      {
+      exportName = args[i];
+      doing_export = false;
+      }
     else
     else
       {
       {
       // Unknown argument.
       // Unknown argument.
@@ -566,6 +595,15 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
     this->Makefile->AddInstallGenerator(runtimeGenerator);
     this->Makefile->AddInstallGenerator(runtimeGenerator);
     this->Makefile->AddInstallGenerator(libraryGenerator);
     this->Makefile->AddInstallGenerator(libraryGenerator);
 
 
+    if (!exportName.empty())
+      {
+      this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
+                                       ->AddTargetToExports(exportName.c_str(),
+                                                            &target,
+                                                            archiveGenerator,
+                                                            runtimeGenerator,
+                                                            libraryGenerator);
+      }
     }
     }
 
 
   // Tell the global generator about any installation component names
   // Tell the global generator about any installation component names
@@ -1125,6 +1163,154 @@ cmInstallCommand::HandleDirectoryMode(std::vector<std::string> const& args)
   return true;
   return true;
 }
 }
 
 
+//----------------------------------------------------------------------------
+bool cmInstallCommand::HandleExportMode(std::vector<std::string> const& args)
+{
+  // This is the EXPORT mode.
+  bool doing_exports = true;
+  bool doing_destination = false;
+  bool doing_permissions = false;
+  bool doing_configurations = false;
+  bool doing_filename = false;
+  bool doing_prefix = false;
+  std::vector<std::string> exports;
+  const char* destination = 0;
+  std::string filename;
+  std::string permissions;
+  std::string prefix;
+  std::vector<std::string> configurations;
+  for(unsigned int i=1; i < args.size(); ++i)
+    {
+    if(args[i] == "DESTINATION")
+      {
+      // Switch to setting the destination property.
+      doing_exports = false;
+      doing_destination = true;
+      doing_permissions = false;
+      doing_configurations = false;
+      doing_filename = false;
+      doing_prefix = false;
+      }
+    else if(args[i] == "PERMISSIONS")
+      {
+      // Switch to setting the permissions property.
+      doing_exports = false;
+      doing_destination = false;
+      doing_permissions = true;
+      doing_configurations = false;
+      doing_filename = false;
+      doing_prefix = false;
+      }
+    else if(args[i] == "CONFIGURATIONS")
+      {
+      // Switch to setting the configurations property.
+      doing_exports = false;
+      doing_destination = false;
+      doing_permissions = false;
+      doing_configurations = true;
+      doing_filename = false;
+      doing_prefix = false;
+      }
+    else if(args[i] == "FILENAME")
+      {
+      // Switch to setting the rename property.
+      doing_exports = false;
+      doing_destination = false;
+      doing_permissions = false;
+      doing_configurations = false;
+      doing_filename = true;
+      doing_prefix = false;
+      }
+    else if(args[i] == "PREFIX")
+      {
+      // Switch to setting the rename property.
+      doing_exports = false;
+      doing_destination = false;
+      doing_permissions = false;
+      doing_configurations = false;
+      doing_filename = false;
+      doing_prefix = true;
+      }
+    else if(doing_exports)
+      {
+      // Store the file for installation.
+      exports.push_back(args[i]);
+      }
+    else if(doing_configurations)
+      {
+      configurations.push_back(args[i]);
+      }
+    else if(doing_destination)
+      {
+      destination = args[i].c_str();
+      doing_destination = false;
+      }
+    else if(doing_permissions)
+      {
+      // Check the requested permission.
+      if(!this->CheckPermissions(args[i], permissions))
+        {
+        cmOStringStream e;
+        e << args[0] << " given invalid permission \""
+          << args[i] << "\".";
+        this->SetError(e.str().c_str());
+        return false;
+        }
+      }
+    else if(doing_filename)
+      {
+      filename = args[i];
+      doing_filename = false;
+      }
+    else if(doing_prefix)
+      {
+      prefix = args[i];
+      doing_prefix = false;
+      }
+    else
+      {
+      // Unknown argument.
+      cmOStringStream e;
+      e << args[0] << " given unknown argument \"" << args[i] << "\".";
+      this->SetError(e.str().c_str());
+      return false;
+      }
+    }
+
+  std::string cmakeDir = this->Makefile->GetHomeOutputDirectory();
+  cmakeDir += cmake::GetCMakeFilesDirectory();
+  for(std::vector<std::string>::const_iterator exportIt = exports.begin();
+      exportIt != exports.end();
+      ++exportIt)
+    {
+
+    const std::vector<cmTargetExport*>* exportSet = this->
+                          Makefile->GetLocalGenerator()->GetGlobalGenerator()->
+                          GetExportSet(exportIt->c_str());
+    if (exportSet == 0)
+      {
+      return false;
+      }
+
+    // Create the export install generator.
+    cmInstallExportGenerator* exportGenerator = new cmInstallExportGenerator(
+                          destination, permissions.c_str(), configurations, 
+                          filename.c_str(), prefix.c_str(), cmakeDir.c_str());
+
+    if (exportGenerator->SetExportSet(exportIt->c_str(),exportSet))
+      {
+      this->Makefile->AddInstallGenerator(exportGenerator);
+      }
+    else
+      {
+      delete exportGenerator;
+      return false;
+      }
+    }
+
+  return true;
+}
+
 //----------------------------------------------------------------------------
 //----------------------------------------------------------------------------
 void cmInstallCommand::ComputeDestination(const char* destination,
 void cmInstallCommand::ComputeDestination(const char* destination,
                                           std::string& dest) const
                                           std::string& dest) const

+ 1 - 0
Source/cmInstallCommand.h

@@ -248,6 +248,7 @@ private:
   bool HandleTargetsMode(std::vector<std::string> const& args);
   bool HandleTargetsMode(std::vector<std::string> const& args);
   bool HandleFilesMode(std::vector<std::string> const& args);
   bool HandleFilesMode(std::vector<std::string> const& args);
   bool HandleDirectoryMode(std::vector<std::string> const& args);
   bool HandleDirectoryMode(std::vector<std::string> const& args);
+  bool HandleExportMode(std::vector<std::string> const& args);
   void ComputeDestination(const char* destination, std::string& dest) const;
   void ComputeDestination(const char* destination, std::string& dest) const;
   bool CheckPermissions(std::string const& arg, std::string& permissions)const;
   bool CheckPermissions(std::string const& arg, std::string& permissions)const;
 };
 };

+ 231 - 0
Source/cmInstallExportGenerator.cxx

@@ -0,0 +1,231 @@
+/*=========================================================================
+
+  Program:   CMake - Cross-Platform Makefile Generator
+  Module:    $RCSfile$
+  Language:  C++
+  Date:      $Date$
+  Version:   $Revision$
+
+  Copyright (c) 2002 Kitware, Inc., Insight Consortium.  All rights reserved.
+  See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
+
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+
+=========================================================================*/
+
+#include <stdio.h>
+
+#include "cmInstallTargetGenerator.h"
+#include "cmGeneratedFileStream.h"
+#include "cmTarget.h"
+
+#include "cmInstallExportGenerator.h"
+
+cmInstallExportGenerator::cmInstallExportGenerator(const char* destination,
+    const char* file_permissions,
+    std::vector<std::string> const& configurations,
+    const char* filename, const char* prefix, const char* tempOutputDir)
+  :cmInstallGenerator(destination)
+  ,FilePermissions(file_permissions)
+  ,Configurations(configurations)
+  ,Filename(filename)
+  ,Prefix(prefix)
+  ,TempOutputDir(tempOutputDir)
+{
+}
+
+/* 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)
+{
+  if (generator == 0) // nothing to do
+    {
+    return true;
+    }
+
+  if (prefix == 0)
+    {
+    prefix = "";
+    }
+
+  const std::vector<std::string>& configs = generator->GetConfigurations();
+  if (configs.empty())
+    {
+    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
+      {
+      return false;
+      }
+    }
+  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::SetExportSet(const char* name,
+                                       const std::vector<cmTargetExport*>* set)
+{
+  if ((name == 0) || (*name == 0) || (set==0))
+    {
+    return false;
+    }
+
+  this->Name = name;
+
+  /* iterate over all targets in the set.
+  If a cmTargetWithProperties with the same name already exists in this 
+  generator, add the new properties to it. If the property already exists, 
+  fail with an error.
+  If no cmTargetWithProperties exists, create a new one.
+  */
+  for(std::vector<cmTargetExport*>::const_iterator it=set->begin();
+      it != set->end();
+      ++it)
+    {
+    std::string targetName = (*it)->Target->GetName();
+
+    cmTargetWithProperties* targetWithProps = 0;
+    for(unsigned int i=0; i<this->Targets.size(); i++)
+      {
+      if (targetName == this->Targets[i]->Target->GetName())
+        {
+        targetWithProps = this->Targets[i];
+        }
+      }
+
+    if (targetWithProps == 0)
+      {
+      targetWithProps = new cmTargetWithProperties((*it)->Target);
+      this->Targets.push_back(targetWithProps);
+      }
+
+    if (this->AddInstallLocations(targetWithProps, (*it)->ArchiveGenerator, 
+                                  "ARCHIVE_") == false)
+      {
+      return false;
+      }
+    if (this->AddInstallLocations(targetWithProps, (*it)->RuntimeGenerator, 
+                                  "") == false)
+      {
+      return false;
+      }
+    if (this->AddInstallLocations(targetWithProps, (*it)->LibraryGenerator, 
+                                  "LIBRARY_") == false)
+      {
+      return false;
+      }
+    }
+
+  return true;
+}
+
+void cmInstallExportGenerator::GenerateScript(std::ostream& os)
+{
+  // 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];
+  snprintf(buf, 64, "%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;
+    }
+
+  /* for every target add the IMPORT statements and set the properties
+    of the target.  */
+  for(std::vector<cmTargetWithProperties*>::const_iterator 
+      targetIt = this->Targets.begin();
+      targetIt != this->Targets.end();
+      ++targetIt)
+    {
+      switch ((*targetIt)->Target->GetType())
+        {
+        case cmTarget::EXECUTABLE:
+          exportFileStream << "ADD_EXECUTABLE(" << this->Prefix.c_str() 
+                           << (*targetIt)->Target->GetName() 
+                           << " IMPORT )\n";
+          break;
+        case cmTarget::STATIC_LIBRARY:
+          exportFileStream << "ADD_LIBRARY(" << this->Prefix.c_str() 
+                           << (*targetIt)->Target->GetName() 
+                           << " STATIC IMPORT )\n";
+          break;
+        case cmTarget::SHARED_LIBRARY:
+          exportFileStream << "ADD_LIBRARY(" << this->Prefix.c_str() 
+                           << (*targetIt)->Target->GetName()
+                           << " SHARED IMPORT )\n";
+          break;
+        case cmTarget::MODULE_LIBRARY:
+          exportFileStream << "ADD_LIBRARY(" << this->Prefix.c_str() 
+                           << (*targetIt)->Target->GetName()
+                           << " MODULE IMPORT )\n";
+          break;
+        default:  // should never happen
+          break;
+        }
+
+      exportFileStream << "SET_TARGET_PROPERTIES ( " << this->Prefix.c_str() 
+                       << (*targetIt)->Target->GetName() << " PROPERTIES \n";
+
+      for (std::map<std::string, std::string>::const_iterator
+           propIt = (*targetIt)->Properties.begin();
+           propIt != (*targetIt)->Properties.end();
+           ++propIt)
+        {
+        exportFileStream << "                     " << propIt->first 
+                         << " \"" << propIt->second << "\"\n";
+        }
+      exportFileStream << "                      )\n\n";
+    }
+
+  // install rule for the file created above
+  this->AddInstallRule(os, this->Destination.c_str(), cmTarget::INSTALL_FILES, 
+                       this->ExportFilename.c_str(), false, 0, 
+                       this->FilePermissions.c_str(), 0, this->Configurations, 
+                       0, this->Filename.c_str(), 0);
+
+}
+

+ 92 - 0
Source/cmInstallExportGenerator.h

@@ -0,0 +1,92 @@
+/*=========================================================================
+
+  Program:   CMake - Cross-Platform Makefile Generator
+  Module:    $RCSfile$
+  Language:  C++
+  Date:      $Date$
+  Version:   $Revision$
+
+  Copyright (c) 2002 Kitware, Inc., Insight Consortium.  All rights reserved.
+  See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
+
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+
+=========================================================================*/
+#ifndef cmInstallExportGenerator_h
+#define cmInstallExportGenerator_h
+
+#include "cmInstallGenerator.h"
+
+class cmTarget;
+
+
+class cmInstallTargetGenerator;
+
+/* 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
+                ) : Target(tgt), ArchiveGenerator(archive),
+                    RuntimeGenerator(runtime), LibraryGenerator(library) {}
+
+  cmTarget* Target;
+  cmInstallTargetGenerator* ArchiveGenerator;
+  cmInstallTargetGenerator* RuntimeGenerator;
+  cmInstallTargetGenerator* LibraryGenerator;
+private:
+  cmTargetExport();
+};
+
+
+/** \class cmInstallExportGenerator
+ * \brief Generate rules for creating an export files.
+ */
+class cmInstallExportGenerator: public cmInstallGenerator
+{
+public:
+  cmInstallExportGenerator(const char* dest, const char* file_permissions,
+                           const std::vector<std::string>& configurations,
+                           const char* filename, const char* prefix, 
+                           const char* tempOutputDir);
+
+  bool SetExportSet(const char* name, 
+                    const std::vector<cmTargetExport*>* exportSet);
+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();
+  };
+
+  virtual void GenerateScript(std::ostream& os);
+  static bool AddInstallLocations(cmTargetWithProperties *twp, 
+                                  cmInstallTargetGenerator* generator,
+                                  const char* prefix);
+
+  std::string Name;
+  std::string FilePermissions;
+  const std::vector<std::string> Configurations;
+  std::string Filename;
+  std::string Prefix;
+  std::string TempOutputDir;
+  std::string ExportFilename;
+
+  std::vector<cmTargetWithProperties*> Targets;
+};
+
+#endif