Browse Source

Merge topic 'export-sets'

80112da Merge topic 'AutomocUseTargetProperties' into export-sets
955b966 exports: add a test for exporting dependent targets
6f50a04 exports: define a CMAKE_FIND_PACKAGE_NAME var set by find_package()
0cfd055 exports: move the handling of missing targets into subclasses
190f2c8 exports: fix build with MSVC6
8b5f448 exports: first try at error handling if a target is missing
87f4c01 exports: accept a missing target if it is exported exactly once
999061a exports: store pointers to all installations of each export set
64b3a6c exports: cmGlobalGenerator::ExportSets destructor will clear it
81cdab5 exports: Hold an ExportSet pointer in cm*Export*Generator
5c898fb exports: Add cmExportSetMap class
d13ec1a exports: Create class cmExportSet
4e2347c exports: Rename cmGlobalGenerator::AddTargetToExport{s,}
e846e70 exports: Remove cmTargetExport constructor
81c66c8 exports: Move cmTargetExport to a dedicated header file
ae4ab62 find_package: add support for a <package>_NOT_FOUND_MESSAGE variable
...
Brad King 13 years ago
parent
commit
49c7b649f9

+ 3 - 0
Modules/FindPackageHandleStandardArgs.cmake

@@ -120,6 +120,9 @@ macro(_FPHSA_HANDLE_FAILURE_CONFIG_MODE)
         list(GET ${_NAME}_CONSIDERED_VERSIONS ${currentConfigIndex} version)
         list(GET ${_NAME}_CONSIDERED_VERSIONS ${currentConfigIndex} version)
         set(configsText "${configsText}    ${filename} (version ${version})\n")
         set(configsText "${configsText}    ${filename} (version ${version})\n")
       endforeach()
       endforeach()
+      if (${_NAME}_NOT_FOUND_MESSAGE)
+        set(configsText "${configsText}    Reason given by package: ${${_NAME}_NOT_FOUND_MESSAGE}\n")
+      endif()
       _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE} ${VERSION_MSG}, checked the following files:\n${configsText}")
       _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE} ${VERSION_MSG}, checked the following files:\n${configsText}")
 
 
     else()
     else()

+ 4 - 1
Modules/readme.txt

@@ -18,6 +18,9 @@ XXX_VERSION_YY          Expect Version YY if true. Make sure at most one of thes
 XXX_WRAP_YY             If False, do not try to use the relevent CMake wrapping command.
 XXX_WRAP_YY             If False, do not try to use the relevent CMake wrapping command.
 XXX_YY_FOUND            If False, optional YY part of XXX sytem is not available.
 XXX_YY_FOUND            If False, optional YY part of XXX sytem is not available.
 XXX_FOUND               Set to false, or undefined, if we haven't found, or don't want to use XXX.
 XXX_FOUND               Set to false, or undefined, if we haven't found, or don't want to use XXX.
+XXX_NOT_FOUND_MESSAGE   Should be set by config-files in the case that it has set XXX_FOUND to FALSE.
+                        The contained message will be printed by the find_package() command and by
+                        find_package_handle_standard_args() to inform the user about the problem.
 XXX_RUNTIME_LIBRARY_DIRS Optionally, the runtime library search path for use when running an executable linked to shared libraries.
 XXX_RUNTIME_LIBRARY_DIRS Optionally, the runtime library search path for use when running an executable linked to shared libraries.
                          The list should be used by user code to create the PATH on windows or LD_LIBRARY_PATH on unix.
                          The list should be used by user code to create the PATH on windows or LD_LIBRARY_PATH on unix.
                          This should not be a cache entry.
                          This should not be a cache entry.
@@ -124,7 +127,7 @@ If neither the QUIET nor REQUIRED options are given then the
 FindXXX.cmake module should look for the package and complain without
 FindXXX.cmake module should look for the package and complain without
 error if the module is not found.
 error if the module is not found.
 
 
-A package can be provide sub-components.
+A package can provide sub-components.
 Those components can be listed after the COMPONENTS (or REQUIRED)
 Those components can be listed after the COMPONENTS (or REQUIRED)
 or OPTIONAL_COMPONENTS keywords.  The set of all listed components will be
 or OPTIONAL_COMPONENTS keywords.  The set of all listed components will be
 specified in a XXX_FIND_COMPONENTS variable.
 specified in a XXX_FIND_COMPONENTS variable.

+ 5 - 0
Source/CMakeLists.txt

@@ -176,6 +176,10 @@ set(SRCS
   cmExportFileGenerator.cxx
   cmExportFileGenerator.cxx
   cmExportInstallFileGenerator.h
   cmExportInstallFileGenerator.h
   cmExportInstallFileGenerator.cxx
   cmExportInstallFileGenerator.cxx
+  cmExportSet.h
+  cmExportSet.cxx
+  cmExportSetMap.h
+  cmExportSetMap.cxx
   cmExtraCodeBlocksGenerator.cxx
   cmExtraCodeBlocksGenerator.cxx
   cmExtraCodeBlocksGenerator.h
   cmExtraCodeBlocksGenerator.h
   cmExtraEclipseCDT4Generator.cxx
   cmExtraEclipseCDT4Generator.cxx
@@ -259,6 +263,7 @@ set(SRCS
   cmSystemTools.h
   cmSystemTools.h
   cmTarget.cxx
   cmTarget.cxx
   cmTarget.h
   cmTarget.h
+  cmTargetExport.h
   cmTest.cxx
   cmTest.cxx
   cmTest.h
   cmTest.h
   cmTestGenerator.cxx
   cmTestGenerator.cxx

+ 22 - 1
Source/cmExportBuildFileGenerator.cxx

@@ -72,8 +72,9 @@ cmExportBuildFileGenerator
     if(!properties.empty())
     if(!properties.empty())
       {
       {
       // Get the rest of the target details.
       // Get the rest of the target details.
+      std::vector<std::string> missingTargets;
       this->SetImportDetailProperties(config, suffix,
       this->SetImportDetailProperties(config, suffix,
-                                      target, properties);
+                                      target, properties, missingTargets);
 
 
       // TOOD: PUBLIC_HEADER_LOCATION
       // TOOD: PUBLIC_HEADER_LOCATION
       // This should wait until the build feature propagation stuff
       // This should wait until the build feature propagation stuff
@@ -82,6 +83,7 @@ cmExportBuildFileGenerator
       //                              properties);
       //                              properties);
 
 
       // Generate code in the export file.
       // Generate code in the export file.
+      this->GenerateMissingTargetsCheckCode(os, missingTargets);
       this->GenerateImportPropertyCode(os, config, target, properties);
       this->GenerateImportPropertyCode(os, config, target, properties);
       }
       }
     }
     }
@@ -131,6 +133,25 @@ cmExportBuildFileGenerator
     }
     }
 }
 }
 
 
+//----------------------------------------------------------------------------
+void
+cmExportBuildFileGenerator::HandleMissingTarget(
+  std::string& link_libs, std::vector<std::string>&,
+  cmMakefile*, cmTarget* depender, cmTarget* dependee)
+{
+  // The target is not in the export.
+  if(!this->AppendMode)
+    {
+    // We are not appending, so all exported targets should be
+    // known here.  This is probably user-error.
+    this->ComplainAboutMissingTarget(depender, dependee);
+    }
+  // Assume the target will be exported by another command.
+  // Append it with the export namespace.
+  link_libs += this->Namespace;
+  link_libs += dependee->GetName();
+}
+
 //----------------------------------------------------------------------------
 //----------------------------------------------------------------------------
 void
 void
 cmExportBuildFileGenerator
 cmExportBuildFileGenerator

+ 8 - 2
Source/cmExportBuildFileGenerator.h

@@ -45,8 +45,14 @@ protected:
   virtual void GenerateImportTargetsConfig(std::ostream& os,
   virtual void GenerateImportTargetsConfig(std::ostream& os,
                                            const char* config,
                                            const char* config,
                                            std::string const& suffix);
                                            std::string const& suffix);
-  virtual void ComplainAboutMissingTarget(cmTarget* depender,
-                                          cmTarget* dependee);
+  virtual void HandleMissingTarget(std::string& link_libs,
+                                   std::vector<std::string>& missingTargets,
+                                   cmMakefile* mf,
+                                   cmTarget* depender,
+                                   cmTarget* dependee);
+
+  void ComplainAboutMissingTarget(cmTarget* depender,
+                                  cmTarget* dependee);
 
 
   /** Fill in properties indicating built file locations.  */
   /** Fill in properties indicating built file locations.  */
   void SetImportLocationProperty(const char* config,
   void SetImportLocationProperty(const char* config,

+ 40 - 16
Source/cmExportFileGenerator.cxx

@@ -11,10 +11,15 @@
 ============================================================================*/
 ============================================================================*/
 #include "cmExportFileGenerator.h"
 #include "cmExportFileGenerator.h"
 
 
+#include "cmExportSet.h"
 #include "cmGeneratedFileStream.h"
 #include "cmGeneratedFileStream.h"
+#include "cmGlobalGenerator.h"
+#include "cmInstallExportGenerator.h"
+#include "cmLocalGenerator.h"
 #include "cmMakefile.h"
 #include "cmMakefile.h"
 #include "cmSystemTools.h"
 #include "cmSystemTools.h"
 #include "cmTarget.h"
 #include "cmTarget.h"
+#include "cmTargetExport.h"
 #include "cmVersion.h"
 #include "cmVersion.h"
 
 
 #include <cmsys/auto_ptr.hxx>
 #include <cmsys/auto_ptr.hxx>
@@ -123,7 +128,9 @@ void cmExportFileGenerator::GenerateImportConfig(std::ostream& os,
 void
 void
 cmExportFileGenerator
 cmExportFileGenerator
 ::SetImportDetailProperties(const char* config, std::string const& suffix,
 ::SetImportDetailProperties(const char* config, std::string const& suffix,
-                            cmTarget* target, ImportPropertyMap& properties)
+                            cmTarget* target, ImportPropertyMap& properties,
+                            std::vector<std::string>& missingTargets
+                           )
 {
 {
   // Get the makefile in which to lookup target information.
   // Get the makefile in which to lookup target information.
   cmMakefile* mf = target->GetMakefile();
   cmMakefile* mf = target->GetMakefile();
@@ -159,13 +166,13 @@ cmExportFileGenerator
     {
     {
     this->SetImportLinkProperty(suffix, target,
     this->SetImportLinkProperty(suffix, target,
                                 "IMPORTED_LINK_INTERFACE_LANGUAGES",
                                 "IMPORTED_LINK_INTERFACE_LANGUAGES",
-                                iface->Languages, properties);
+                                iface->Languages, properties, missingTargets);
     this->SetImportLinkProperty(suffix, target,
     this->SetImportLinkProperty(suffix, target,
                                 "IMPORTED_LINK_INTERFACE_LIBRARIES",
                                 "IMPORTED_LINK_INTERFACE_LIBRARIES",
-                                iface->Libraries, properties);
+                                iface->Libraries, properties, missingTargets);
     this->SetImportLinkProperty(suffix, target,
     this->SetImportLinkProperty(suffix, target,
                                 "IMPORTED_LINK_DEPENDENT_LIBRARIES",
                                 "IMPORTED_LINK_DEPENDENT_LIBRARIES",
-                                iface->SharedDeps, properties);
+                                iface->SharedDeps, properties, missingTargets);
     if(iface->Multiplicity > 0)
     if(iface->Multiplicity > 0)
       {
       {
       std::string prop = "IMPORTED_LINK_INTERFACE_MULTIPLICITY";
       std::string prop = "IMPORTED_LINK_INTERFACE_MULTIPLICITY";
@@ -184,7 +191,9 @@ cmExportFileGenerator
                         cmTarget* target,
                         cmTarget* target,
                         const char* propName,
                         const char* propName,
                         std::vector<std::string> const& libs,
                         std::vector<std::string> const& libs,
-                        ImportPropertyMap& properties)
+                        ImportPropertyMap& properties,
+                        std::vector<std::string>& missingTargets
+                       )
 {
 {
   // Skip the property if there are no libraries.
   // Skip the property if there are no libraries.
   if(libs.empty())
   if(libs.empty())
@@ -224,17 +233,7 @@ cmExportFileGenerator
         }
         }
       else
       else
         {
         {
-        // The target is not in the export.
-        if(!this->AppendMode)
-          {
-          // We are not appending, so all exported targets should be
-          // known here.  This is probably user-error.
-          this->ComplainAboutMissingTarget(target, tgt);
-          }
-        // Assume the target will be exported by another command.
-        // Append it with the export namespace.
-        link_libs += this->Namespace;
-        link_libs += *li;
+        this->HandleMissingTarget(link_libs, missingTargets, mf, target, tgt);
         }
         }
       }
       }
     else
     else
@@ -250,6 +249,7 @@ cmExportFileGenerator
   properties[prop] = link_libs;
   properties[prop] = link_libs;
 }
 }
 
 
+
 //----------------------------------------------------------------------------
 //----------------------------------------------------------------------------
 void cmExportFileGenerator::GenerateImportHeaderCode(std::ostream& os,
 void cmExportFileGenerator::GenerateImportHeaderCode(std::ostream& os,
                                                      const char* config)
                                                      const char* config)
@@ -380,6 +380,30 @@ cmExportFileGenerator
 }
 }
 
 
 
 
+//----------------------------------------------------------------------------
+void cmExportFileGenerator::GenerateMissingTargetsCheckCode(std::ostream& os,
+                                const std::vector<std::string>& missingTargets)
+{
+  os << "# Make sure the targets which have been exported in some other \n"
+        "# export set exist.\n";
+  for(unsigned int i=0; i<missingTargets.size(); ++i)
+    {
+    os << "IF(NOT TARGET \"" << missingTargets[i] << "\" )\n"
+       << "  IF(CMAKE_FIND_PACKAGE_NAME)\n"
+       << "    SET( ${CMAKE_FIND_PACKAGE_NAME}_FOUND FALSE)\n"
+       << "    SET( ${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE "
+       << "\"Required imported target \\\"" << missingTargets[i]
+       << "\\\" not found ! \")\n"
+       << "  ELSE()\n"
+       << "    MESSAGE(FATAL_ERROR \"Required imported target \\\""
+       << missingTargets[i] << "\\\" not found ! \")\n"
+       << "  ENDIF()\n"
+       << "ENDIF()\n";
+    }
+  os << "\n";
+}
+
+
 //----------------------------------------------------------------------------
 //----------------------------------------------------------------------------
 void
 void
 cmExportFileGenerator::GenerateImportedFileCheckLoop(std::ostream& os)
 cmExportFileGenerator::GenerateImportedFileCheckLoop(std::ostream& os)

+ 13 - 6
Source/cmExportFileGenerator.h

@@ -60,17 +60,21 @@ protected:
                                       ImportPropertyMap const& properties,
                                       ImportPropertyMap const& properties,
                                const std::set<std::string>& importedLocations);
                                const std::set<std::string>& importedLocations);
   void GenerateImportedFileCheckLoop(std::ostream& os);
   void GenerateImportedFileCheckLoop(std::ostream& os);
+  void GenerateMissingTargetsCheckCode(std::ostream& os,
+                               const std::vector<std::string>& missingTargets);
 
 
 
 
   // Collect properties with detailed information about targets beyond
   // Collect properties with detailed information about targets beyond
   // their location on disk.
   // their location on disk.
   void SetImportDetailProperties(const char* config,
   void SetImportDetailProperties(const char* config,
                                  std::string const& suffix, cmTarget* target,
                                  std::string const& suffix, cmTarget* target,
-                                 ImportPropertyMap& properties);
+                                 ImportPropertyMap& properties,
+                                 std::vector<std::string>& missingTargets);
   void SetImportLinkProperty(std::string const& suffix,
   void SetImportLinkProperty(std::string const& suffix,
                              cmTarget* target, const char* propName,
                              cmTarget* target, const char* propName,
                              std::vector<std::string> const& libs,
                              std::vector<std::string> const& libs,
-                             ImportPropertyMap& properties);
+                             ImportPropertyMap& properties,
+                             std::vector<std::string>& missingTargets);
 
 
   /** Each subclass knows how to generate its kind of export file.  */
   /** Each subclass knows how to generate its kind of export file.  */
   virtual bool GenerateMainFile(std::ostream& os) = 0;
   virtual bool GenerateMainFile(std::ostream& os) = 0;
@@ -80,10 +84,13 @@ protected:
                                            const char* config,
                                            const char* config,
                                            std::string const& suffix) = 0;
                                            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* depender,
-                                          cmTarget* dependee) = 0;
+  /** Each subclass knows how to deal with a target that is  missing from an
+   *  export set.  */
+  virtual void HandleMissingTarget(std::string& link_libs,
+                                   std::vector<std::string>& missingTargets,
+                                   cmMakefile* mf,
+                                   cmTarget* depender,
+                                   cmTarget* dependee) = 0;
 
 
   // The namespace in which the exports are placed in the generated file.
   // The namespace in which the exports are placed in the generated file.
   std::string Namespace;
   std::string Namespace;

+ 106 - 18
Source/cmExportInstallFileGenerator.cxx

@@ -11,14 +11,19 @@
 ============================================================================*/
 ============================================================================*/
 #include "cmExportInstallFileGenerator.h"
 #include "cmExportInstallFileGenerator.h"
 
 
+#include "cmExportSet.h"
+#include "cmExportSetMap.h"
 #include "cmGeneratedFileStream.h"
 #include "cmGeneratedFileStream.h"
+#include "cmGlobalGenerator.h"
+#include "cmLocalGenerator.h"
 #include "cmInstallExportGenerator.h"
 #include "cmInstallExportGenerator.h"
 #include "cmInstallTargetGenerator.h"
 #include "cmInstallTargetGenerator.h"
+#include "cmTargetExport.h"
 
 
 //----------------------------------------------------------------------------
 //----------------------------------------------------------------------------
 cmExportInstallFileGenerator
 cmExportInstallFileGenerator
 ::cmExportInstallFileGenerator(cmInstallExportGenerator* iegen):
 ::cmExportInstallFileGenerator(cmInstallExportGenerator* iegen):
-  InstallExportGenerator(iegen)
+  IEGen(iegen)
 {
 {
 }
 }
 
 
@@ -36,10 +41,10 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
 {
 {
   // Create all the imported targets.
   // Create all the imported targets.
   for(std::vector<cmTargetExport*>::const_iterator
   for(std::vector<cmTargetExport*>::const_iterator
-        tei = this->ExportSet->begin();
-      tei != this->ExportSet->end(); ++tei)
+        tei = this->IEGen->GetExportSet()->GetTargetExports()->begin();
+      tei != this->IEGen->GetExportSet()->GetTargetExports()->end(); ++tei)
     {
     {
-    cmTargetExport* te = *tei;
+    cmTargetExport const* te = *tei;
     if(this->ExportedTargets.insert(te->Target).second)
     if(this->ExportedTargets.insert(te->Target).second)
       {
       {
       this->GenerateImportTargetCode(os, te->Target);
       this->GenerateImportTargetCode(os, te->Target);
@@ -47,8 +52,9 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
     else
     else
       {
       {
       cmOStringStream e;
       cmOStringStream e;
-      e << "INSTALL(EXPORT \"" << this->Name << "\" ...) "
-        << "includes target \"" << te->Target->GetName()
+      e << "INSTALL(EXPORT \""
+        << this->IEGen->GetExportSet()->GetName()
+        << "\" ...) " << "includes target \"" << te->Target->GetName()
         << "\" more than once in the export set.";
         << "\" more than once in the export set.";
       cmSystemTools::Error(e.str().c_str());
       cmSystemTools::Error(e.str().c_str());
       return false;
       return false;
@@ -84,7 +90,7 @@ bool
 cmExportInstallFileGenerator::GenerateImportFileConfig(const char* config)
 cmExportInstallFileGenerator::GenerateImportFileConfig(const char* config)
 {
 {
   // Skip configurations not enabled for this export.
   // Skip configurations not enabled for this export.
-  if(!this->InstallExportGenerator->InstallsForConfig(config))
+  if(!this->IEGen->InstallsForConfig(config))
     {
     {
     return true;
     return true;
     }
     }
@@ -140,7 +146,7 @@ cmExportInstallFileGenerator
 {
 {
   // Add code to compute the installation prefix relative to the
   // Add code to compute the installation prefix relative to the
   // import file location.
   // import file location.
-  const char* installDest = this->InstallExportGenerator->GetDestination();
+  const char* installDest = this->IEGen->GetDestination();
   if(!cmSystemTools::FileIsFullPath(installDest))
   if(!cmSystemTools::FileIsFullPath(installDest))
     {
     {
     std::string dest = installDest;
     std::string dest = installDest;
@@ -161,11 +167,11 @@ cmExportInstallFileGenerator
 
 
   // Add each target in the set to the export.
   // Add each target in the set to the export.
   for(std::vector<cmTargetExport*>::const_iterator
   for(std::vector<cmTargetExport*>::const_iterator
-        tei = this->ExportSet->begin();
-      tei != this->ExportSet->end(); ++tei)
+        tei = this->IEGen->GetExportSet()->GetTargetExports()->begin();
+      tei != this->IEGen->GetExportSet()->GetTargetExports()->end(); ++tei)
     {
     {
     // Collect import properties for this target.
     // Collect import properties for this target.
-    cmTargetExport* te = *tei;
+    cmTargetExport const* te = *tei;
     ImportPropertyMap properties;
     ImportPropertyMap properties;
     std::set<std::string> importedLocations;
     std::set<std::string> importedLocations;
     this->SetImportLocationProperty(config, suffix, te->ArchiveGenerator,
     this->SetImportLocationProperty(config, suffix, te->ArchiveGenerator,
@@ -185,8 +191,9 @@ cmExportInstallFileGenerator
     if(!properties.empty())
     if(!properties.empty())
       {
       {
       // Get the rest of the target details.
       // Get the rest of the target details.
+      std::vector<std::string> missingTargets;
       this->SetImportDetailProperties(config, suffix,
       this->SetImportDetailProperties(config, suffix,
-                                      te->Target, properties);
+                                      te->Target, properties, missingTargets);
 
 
       // TOOD: PUBLIC_HEADER_LOCATION
       // TOOD: PUBLIC_HEADER_LOCATION
       // This should wait until the build feature propagation stuff
       // This should wait until the build feature propagation stuff
@@ -195,6 +202,7 @@ cmExportInstallFileGenerator
       //                              properties);
       //                              properties);
 
 
       // Generate code in the export file.
       // Generate code in the export file.
+      this->GenerateMissingTargetsCheckCode(os, missingTargets);
       this->GenerateImportPropertyCode(os, config, te->Target, properties);
       this->GenerateImportPropertyCode(os, config, te->Target, properties);
       this->GenerateImportedFileChecksCode(os, te->Target, properties,
       this->GenerateImportedFileChecksCode(os, te->Target, properties,
                                            importedLocations);
                                            importedLocations);
@@ -304,14 +312,82 @@ cmExportInstallFileGenerator
     }
     }
 }
 }
 
 
+//----------------------------------------------------------------------------
+void
+cmExportInstallFileGenerator::HandleMissingTarget(
+  std::string& link_libs, std::vector<std::string>& missingTargets,
+  cmMakefile* mf, cmTarget* depender, cmTarget* dependee)
+{
+  std::string name = dependee->GetName();
+  std::vector<std::string> namespaces = this->FindNamespaces(mf, name);
+  int targetOccurrences = (int)namespaces.size();
+  if (targetOccurrences == 1)
+    {
+    std::string missingTarget = namespaces[0];
+    missingTarget += name;
+    link_libs += missingTarget;
+    missingTargets.push_back(missingTarget);
+    }
+  else
+    {
+    // We are not appending, so all exported targets should be
+    // known here.  This is probably user-error.
+    this->ComplainAboutMissingTarget(depender, dependee, targetOccurrences);
+    }
+}
+
+//----------------------------------------------------------------------------
+std::vector<std::string>
+cmExportInstallFileGenerator
+::FindNamespaces(cmMakefile* mf, const std::string& name)
+{
+  std::vector<std::string> namespaces;
+  cmGlobalGenerator* gg = mf->GetLocalGenerator()->GetGlobalGenerator();
+  const cmExportSetMap& exportSets = gg->GetExportSets();
+
+  for(cmExportSetMap::const_iterator expIt = exportSets.begin();
+      expIt != exportSets.end();
+      ++expIt)
+    {
+    const cmExportSet* exportSet = expIt->second;
+    std::vector<cmTargetExport*> const* targets =
+                                                 exportSet->GetTargetExports();
+
+    bool containsTarget = false;
+    for(unsigned int i=0; i<targets->size(); i++)
+      {
+      if (name == (*targets)[i]->Target->GetName())
+        {
+        containsTarget = true;
+        break;
+        }
+      }
+
+    if (containsTarget)
+      {
+      std::vector<cmInstallExportGenerator const*> const* installs =
+                                                 exportSet->GetInstallations();
+      for(unsigned int i=0; i<installs->size(); i++)
+        {
+        namespaces.push_back((*installs)[i]->GetNamespace());
+        }
+      }
+    }
+
+  return namespaces;
+}
+
+
 //----------------------------------------------------------------------------
 //----------------------------------------------------------------------------
 void
 void
 cmExportInstallFileGenerator
 cmExportInstallFileGenerator
 ::ComplainAboutImportPrefix(cmInstallTargetGenerator* itgen)
 ::ComplainAboutImportPrefix(cmInstallTargetGenerator* itgen)
 {
 {
-  const char* installDest = this->InstallExportGenerator->GetDestination();
+  const char* installDest = this->IEGen->GetDestination();
   cmOStringStream e;
   cmOStringStream e;
-  e << "INSTALL(EXPORT \"" << this->Name << "\") given absolute "
+  e << "INSTALL(EXPORT \""
+    << this->IEGen->GetExportSet()->GetName()
+    << "\") given absolute "
     << "DESTINATION \"" << installDest << "\" but the export "
     << "DESTINATION \"" << installDest << "\" but the export "
     << "references an installation of target \""
     << "references an installation of target \""
     << itgen->GetTarget()->GetName() << "\" which has relative "
     << itgen->GetTarget()->GetName() << "\" which has relative "
@@ -322,12 +398,24 @@ cmExportInstallFileGenerator
 //----------------------------------------------------------------------------
 //----------------------------------------------------------------------------
 void
 void
 cmExportInstallFileGenerator
 cmExportInstallFileGenerator
-::ComplainAboutMissingTarget(cmTarget* depender, cmTarget* dependee)
+::ComplainAboutMissingTarget(cmTarget* depender,
+                             cmTarget* dependee,
+                             int occurrences)
 {
 {
   cmOStringStream e;
   cmOStringStream e;
-  e << "INSTALL(EXPORT \"" << this->Name << "\" ...) "
+  e << "INSTALL(EXPORT \""
+    << this->IEGen->GetExportSet()->GetName()
+    << "\" ...) "
     << "includes target \"" << depender->GetName()
     << "includes target \"" << depender->GetName()
-    << "\" which requires target \"" << dependee->GetName()
-    << "\" that is not in the export set.";
+    << "\" which requires target \"" << dependee->GetName() << "\" ";
+  if (occurrences == 0)
+    {
+    e << "that is not in the export set.";
+    }
+  else
+    {
+    e << "that is not in this export set, but " << occurrences
+    << " times in others.";
+    }
   cmSystemTools::Error(e.str().c_str());
   cmSystemTools::Error(e.str().c_str());
 }
 }

+ 15 - 44
Source/cmExportInstallFileGenerator.h

@@ -18,6 +18,7 @@ class cmInstallExportGenerator;
 class cmInstallFilesGenerator;
 class cmInstallFilesGenerator;
 class cmInstallTargetGenerator;
 class cmInstallTargetGenerator;
 class cmTargetExport;
 class cmTargetExport;
+class cmExportSet;
 
 
 /** \class cmExportInstallFileGenerator
 /** \class cmExportInstallFileGenerator
  * \brief Generate a file exporting targets from an install tree.
  * \brief Generate a file exporting targets from an install tree.
@@ -40,15 +41,6 @@ public:
       files.  */
       files.  */
   cmExportInstallFileGenerator(cmInstallExportGenerator* iegen);
   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
   /** Get the per-config file generated for each configuraiton.  This
       maps from the configuration name to the file temporary location
       maps from the configuration name to the file temporary location
       for installation.  */
       for installation.  */
@@ -65,8 +57,19 @@ protected:
   virtual void GenerateImportTargetsConfig(std::ostream& os,
   virtual void GenerateImportTargetsConfig(std::ostream& os,
                                            const char* config,
                                            const char* config,
                                            std::string const& suffix);
                                            std::string const& suffix);
-  virtual void ComplainAboutMissingTarget(cmTarget* depender,
-                                          cmTarget* dependee);
+  virtual void HandleMissingTarget(std::string& link_libs,
+                                   std::vector<std::string>& missingTargets,
+                                   cmMakefile* mf,
+                                   cmTarget* depender,
+                                   cmTarget* dependee);
+
+  void ComplainAboutMissingTarget(cmTarget* depender,
+                                  cmTarget* dependee,
+                                  int occurrences);
+
+  std::vector<std::string> FindNamespaces(cmMakefile* mf,
+                                          const std::string& name);
+
 
 
   /** Generate a per-configuration file for the targets.  */
   /** Generate a per-configuration file for the targets.  */
   bool GenerateImportFileConfig(const char* config);
   bool GenerateImportFileConfig(const char* config);
@@ -81,9 +84,7 @@ protected:
 
 
   void ComplainAboutImportPrefix(cmInstallTargetGenerator* itgen);
   void ComplainAboutImportPrefix(cmInstallTargetGenerator* itgen);
 
 
-  cmInstallExportGenerator* InstallExportGenerator;
-  std::string Name;
-  std::vector<cmTargetExport*> const* ExportSet;
+  cmInstallExportGenerator* IEGen;
 
 
   std::string ImportPrefix;
   std::string ImportPrefix;
 
 
@@ -91,34 +92,4 @@ protected:
   std::map<cmStdString, cmStdString> ConfigImportFiles;
   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
 #endif

+ 32 - 0
Source/cmExportSet.cxx

@@ -0,0 +1,32 @@
+/*============================================================================
+  CMake - Cross Platform Makefile Generator
+  Copyright 2000-2012 Kitware, Inc., Insight Software Consortium
+
+  Distributed under the OSI-approved BSD License (the "License");
+  see accompanying file Copyright.txt for details.
+
+  This software is distributed WITHOUT ANY WARRANTY; without even the
+  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the License for more information.
+============================================================================*/
+
+#include "cmExportSet.h"
+#include "cmTargetExport.h"
+
+cmExportSet::~cmExportSet()
+{
+  for(unsigned int i = 0; i < this->TargetExports.size(); ++ i)
+    {
+    delete this->TargetExports[i];
+    }
+}
+
+void cmExportSet::AddTargetExport(cmTargetExport* te)
+{
+  this->TargetExports.push_back(te);
+}
+
+void cmExportSet::AddInstallation(cmInstallExportGenerator const* installation)
+{
+  this->Installations.push_back(installation);
+}

+ 46 - 0
Source/cmExportSet.h

@@ -0,0 +1,46 @@
+/*============================================================================
+  CMake - Cross Platform Makefile Generator
+  Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+
+  Distributed under the OSI-approved BSD License (the "License");
+  see accompanying file Copyright.txt for details.
+
+  This software is distributed WITHOUT ANY WARRANTY; without even the
+  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the License for more information.
+============================================================================*/
+#ifndef cmExportSet_h
+#define cmExportSet_h
+
+#include "cmSystemTools.h"
+class cmTargetExport;
+class cmInstallExportGenerator;
+
+/// A set of targets that were installed with the same EXPORT parameter.
+class cmExportSet
+{
+public:
+  /// Construct an empty export set named \a name
+  cmExportSet(const std::string &name) : Name(name) {}
+  /// Destructor
+  ~cmExportSet();
+
+  void AddTargetExport(cmTargetExport* tgt);
+
+  void AddInstallation(cmInstallExportGenerator const* installation);
+
+  std::string const& GetName() const { return this->Name; }
+
+  std::vector<cmTargetExport*> const* GetTargetExports() const
+     { return &this->TargetExports; }
+
+  std::vector<cmInstallExportGenerator const*> const* GetInstallations() const
+     { return &this->Installations; }
+
+private:
+  std::vector<cmTargetExport*> TargetExports;
+  std::string Name;
+  std::vector<cmInstallExportGenerator const*> Installations;
+};
+
+#endif

+ 34 - 0
Source/cmExportSetMap.cxx

@@ -0,0 +1,34 @@
+/*============================================================================
+  CMake - Cross Platform Makefile Generator
+  Copyright 2000-2012 Kitware, Inc., Insight Software Consortium
+
+  Distributed under the OSI-approved BSD License (the "License");
+  see accompanying file Copyright.txt for details.
+
+  This software is distributed WITHOUT ANY WARRANTY; without even the
+  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the License for more information.
+============================================================================*/
+
+#include "cmExportSetMap.h"
+#include "cmExportSet.h"
+
+cmExportSet* cmExportSetMap::operator[](const std::string &name)
+{
+  std::map<std::string, cmExportSet*>::iterator it = this->find(name);
+  if (it == this->end()) // Export set not found
+    {
+    it = this->insert(std::make_pair(name, new cmExportSet(name))).first;
+    }
+  return it->second;
+}
+
+cmExportSetMap::~cmExportSetMap()
+{
+  for(std::map<std::string, cmExportSet*>::iterator it = this->begin();
+      it != this->end();
+      ++ it)
+    {
+    delete it->second;
+    }
+}

+ 33 - 0
Source/cmExportSetMap.h

@@ -0,0 +1,33 @@
+/*============================================================================
+  CMake - Cross Platform Makefile Generator
+  Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+
+  Distributed under the OSI-approved BSD License (the "License");
+  see accompanying file Copyright.txt for details.
+
+  This software is distributed WITHOUT ANY WARRANTY; without even the
+  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the License for more information.
+============================================================================*/
+#ifndef cmExportSetMap_h
+#define cmExportSetMap_h
+
+#include "cmSystemTools.h"
+class cmExportSet;
+
+/// A name -> cmExportSet map with overloaded operator[].
+class cmExportSetMap : public std::map<std::string, cmExportSet*>
+{
+public:
+  /** \brief Overloaded operator[].
+   *
+   * The operator is overloaded because cmExportSet has no default constructor:
+   * we do not want unnamed export sets.
+   */
+  cmExportSet* operator[](const std::string &name);
+
+  /// Overloaded destructor deletes all member export sets.
+  ~cmExportSetMap();
+};
+
+#endif

+ 12 - 0
Source/cmFindPackageCommand.cxx

@@ -840,6 +840,8 @@ bool cmFindPackageCommand
 //----------------------------------------------------------------------------
 //----------------------------------------------------------------------------
 void cmFindPackageCommand::SetModuleVariables(const std::string& components)
 void cmFindPackageCommand::SetModuleVariables(const std::string& components)
 {
 {
+  this->AddFindDefinition("CMAKE_FIND_PACKAGE_NAME", this->Name.c_str());
+
   // Store the list of components.
   // Store the list of components.
   std::string components_var = this->Name + "_FIND_COMPONENTS";
   std::string components_var = this->Name + "_FIND_COMPONENTS";
   this->AddFindDefinition(components_var.c_str(), components.c_str());
   this->AddFindDefinition(components_var.c_str(), components.c_str());
@@ -1016,6 +1018,9 @@ bool cmFindPackageCommand::HandlePackageMode()
 
 
   std::string foundVar = this->Name;
   std::string foundVar = this->Name;
   foundVar += "_FOUND";
   foundVar += "_FOUND";
+  std::string notFoundMessageVar = this->Name;
+  notFoundMessageVar += "_NOT_FOUND_MESSAGE";
+  std::string notFoundMessage;
 
 
   // If the directory for the config file was found, try to read the file.
   // If the directory for the config file was found, try to read the file.
   bool result = true;
   bool result = true;
@@ -1033,6 +1038,7 @@ bool cmFindPackageCommand::HandlePackageMode()
       // has set Foo_FOUND to FALSE itself:
       // has set Foo_FOUND to FALSE itself:
       this->Makefile->RemoveDefinition(foundVar.c_str());
       this->Makefile->RemoveDefinition(foundVar.c_str());
       }
       }
+    this->Makefile->RemoveDefinition(notFoundMessageVar.c_str());
 
 
     // Set the version variables before loading the config file.
     // Set the version variables before loading the config file.
     // It may override them.
     // It may override them.
@@ -1051,6 +1057,8 @@ bool cmFindPackageCommand::HandlePackageMode()
         // we get here if the Config file has set Foo_FOUND actively to FALSE
         // we get here if the Config file has set Foo_FOUND actively to FALSE
         found = false;
         found = false;
         configFileSetFOUNDFalse = true;
         configFileSetFOUNDFalse = true;
+        notFoundMessage = this->Makefile->GetSafeDefinition(
+                                                   notFoundMessageVar.c_str());
         }
         }
       }
       }
     else
     else
@@ -1071,6 +1079,10 @@ bool cmFindPackageCommand::HandlePackageMode()
         "  " << this->FileFound << "\n"
         "  " << this->FileFound << "\n"
         "but it set " << foundVar << " to FALSE so package \"" <<
         "but it set " << foundVar << " to FALSE so package \"" <<
         this->Name << "\" is considered to be NOT FOUND.";
         this->Name << "\" is considered to be NOT FOUND.";
+      if (!notFoundMessage.empty())
+        {
+        e << " Reason given by package: \n" << notFoundMessage << "\n";
+        }
       }
       }
     // If there are files in ConsideredConfigs, it means that FooConfig.cmake
     // If there are files in ConsideredConfigs, it means that FooConfig.cmake
     // have been found, but they didn't have appropriate versions.
     // have been found, but they didn't have appropriate versions.

+ 4 - 50
Source/cmGlobalGenerator.cxx

@@ -21,7 +21,7 @@
 #include "cmQtAutomoc.h"
 #include "cmQtAutomoc.h"
 #include "cmSourceFile.h"
 #include "cmSourceFile.h"
 #include "cmVersion.h"
 #include "cmVersion.h"
-#include "cmExportInstallFileGenerator.h"
+#include "cmTargetExport.h"
 #include "cmComputeTargetDepends.h"
 #include "cmComputeTargetDepends.h"
 #include "cmGeneratedFileStream.h"
 #include "cmGeneratedFileStream.h"
 #include "cmGeneratorTarget.h"
 #include "cmGeneratorTarget.h"
@@ -76,12 +76,12 @@ cmGlobalGenerator::~cmGlobalGenerator()
     }
     }
 
 
   this->ClearGeneratorTargets();
   this->ClearGeneratorTargets();
-  this->ClearExportSets();
 }
 }
 
 
 void cmGlobalGenerator::ResolveLanguageCompiler(const std::string &lang,
 void cmGlobalGenerator::ResolveLanguageCompiler(const std::string &lang,
                                                 cmMakefile *mf,
                                                 cmMakefile *mf,
-                                                bool optional) {
+                                                bool optional)
+{
   std::string langComp = "CMAKE_";
   std::string langComp = "CMAKE_";
   langComp += lang;
   langComp += lang;
   langComp += "_COMPILER";
   langComp += "_COMPILER";
@@ -817,7 +817,7 @@ void cmGlobalGenerator::Configure()
 {
 {
   this->FirstTimeProgress = 0.0f;
   this->FirstTimeProgress = 0.0f;
   this->ClearGeneratorTargets();
   this->ClearGeneratorTargets();
-  this->ClearExportSets();
+  this->ExportSets.clear();
   // Delete any existing cmLocalGenerators
   // Delete any existing cmLocalGenerators
   unsigned int i;
   unsigned int i;
   for (i = 0; i < this->LocalGenerators.size(); ++i)
   for (i = 0; i < this->LocalGenerators.size(); ++i)
@@ -1489,52 +1489,6 @@ void cmGlobalGenerator::AddInstallComponent(const char* component)
     }
     }
 }
 }
 
 
-void cmGlobalGenerator::AddTargetToExports(const char* exportSetName,
-                                           cmTarget* target,
-                                           cmInstallTargetGenerator* archive,
-                                           cmInstallTargetGenerator* runTime,
-                                           cmInstallTargetGenerator* library,
-                                           cmInstallTargetGenerator* framework,
-                                           cmInstallTargetGenerator* bundle,
-                                           cmInstallFilesGenerator* headers)
-{
-  if ((exportSetName) && (*exportSetName) && (target))
-    {
-    cmTargetExport* te = new cmTargetExport(target, archive, runTime, library,
-                                            framework, bundle, headers);
-    this->ExportSets[exportSetName].push_back(te);
-    }
-}
-
-//----------------------------------------------------------------------------
-void cmGlobalGenerator::ClearExportSets()
-{
-  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];
-      }
-    }
-  this->ExportSets.clear();
-}
-
-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;

+ 10 - 20
Source/cmGlobalGenerator.h

@@ -18,14 +18,15 @@
 #include "cmTarget.h" // For cmTargets
 #include "cmTarget.h" // For cmTargets
 #include "cmTargetDepend.h" // For cmTargetDependSet
 #include "cmTargetDepend.h" // For cmTargetDependSet
 #include "cmSystemTools.h" // for cmSystemTools::OutputOption
 #include "cmSystemTools.h" // for cmSystemTools::OutputOption
+#include "cmExportSetMap.h" // For cmExportSetMap
 #include "cmGeneratorTarget.h"
 #include "cmGeneratorTarget.h"
+
 class cmake;
 class cmake;
 class cmGeneratorTarget;
 class cmGeneratorTarget;
 class cmMakefile;
 class cmMakefile;
 class cmLocalGenerator;
 class cmLocalGenerator;
 class cmExternalMakefileProjectGenerator;
 class cmExternalMakefileProjectGenerator;
 class cmTarget;
 class cmTarget;
-class cmTargetExport;
 class cmInstallTargetGenerator;
 class cmInstallTargetGenerator;
 class cmInstallFilesGenerator;
 class cmInstallFilesGenerator;
 
 
@@ -128,8 +129,8 @@ public:
   void SetCMakeInstance(cmake *cm);
   void SetCMakeInstance(cmake *cm);
 
 
   ///! Get the CMake instance
   ///! Get the CMake instance
-  cmake *GetCMakeInstance() { return this->CMakeInstance; };
-  const cmake *GetCMakeInstance() const { return this->CMakeInstance; };
+  cmake *GetCMakeInstance() { return this->CMakeInstance; }
+  const cmake *GetCMakeInstance() const { return this->CMakeInstance; }
 
 
   void SetConfiguredFilesPath(cmGlobalGenerator* gen);
   void SetConfiguredFilesPath(cmGlobalGenerator* gen);
   const std::vector<cmLocalGenerator *>& GetLocalGenerators() const {
   const std::vector<cmLocalGenerator *>& GetLocalGenerators() const {
@@ -152,18 +153,9 @@ public:
   void AddInstallComponent(const char* component);
   void AddInstallComponent(const char* component);
 
 
   const std::set<cmStdString>* GetInstallComponents() const
   const std::set<cmStdString>* GetInstallComponents() const
-  { return &InstallComponents; }
-
-  ///! Add one installed target to the sets of the exports
-  void AddTargetToExports(const char* exportSet, cmTarget* target,
-                          cmInstallTargetGenerator* archive,
-                          cmInstallTargetGenerator* runTime,
-                          cmInstallTargetGenerator* library,
-                          cmInstallTargetGenerator* framework,
-                          cmInstallTargetGenerator* bundle,
-                          cmInstallFilesGenerator* publicHeaders);
-  ///! Get the export target set with the   given name
-  const std::vector<cmTargetExport*>* GetExportSet(const char* name) const;
+    { return &this->InstallComponents; }
+
+  cmExportSetMap& GetExportSets() {return this->ExportSets;}
 
 
   /** Add a file to the manifest of generated targets for a configuration.  */
   /** Add a file to the manifest of generated targets for a configuration.  */
   void AddToManifest(const char* config, std::string const& f);
   void AddToManifest(const char* config, std::string const& f);
@@ -223,7 +215,7 @@ public:
   /** Get the manifest of all targets that will be built for each
   /** Get the manifest of all targets that will be built for each
       configuration.  This is valid during generation only.  */
       configuration.  This is valid during generation only.  */
   cmTargetManifest const& GetTargetManifest() const
   cmTargetManifest const& GetTargetManifest() const
-  { return this->TargetManifest; }
+    { return this->TargetManifest; }
 
 
   /** Get the content of a directory.  Directory listings are loaded
   /** Get the content of a directory.  Directory listings are loaded
       from disk at most once and cached.  During the generation step
       from disk at most once and cached.  During the generation step
@@ -329,15 +321,13 @@ protected:
   cmLocalGenerator* CurrentLocalGenerator;
   cmLocalGenerator* CurrentLocalGenerator;
   // map from project name to vector of local generators in that project
   // map from project name to vector of local generators in that project
   std::map<cmStdString, std::vector<cmLocalGenerator*> > ProjectMap;
   std::map<cmStdString, std::vector<cmLocalGenerator*> > ProjectMap;
-  std::map<cmLocalGenerator*, std::set<cmTarget *> >
-  LocalGeneratorToTargetMap;
+  std::map<cmLocalGenerator*, std::set<cmTarget *> > LocalGeneratorToTargetMap;
 
 
   // 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
   // Sets of named target exports
-  std::map<cmStdString, std::vector<cmTargetExport*> > ExportSets;
-  void ClearExportSets();
+  cmExportSetMap 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.

+ 14 - 5
Source/cmInstallCommand.cxx

@@ -17,6 +17,8 @@
 #include "cmInstallTargetGenerator.h"
 #include "cmInstallTargetGenerator.h"
 #include "cmInstallExportGenerator.h"
 #include "cmInstallExportGenerator.h"
 #include "cmInstallCommandArguments.h"
 #include "cmInstallCommandArguments.h"
+#include "cmTargetExport.h"
+#include "cmExportSet.h"
 
 
 #include <cmsys/Glob.hxx>
 #include <cmsys/Glob.hxx>
 
 
@@ -735,11 +737,16 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
     // this is not a namelink-only rule.
     // this is not a namelink-only rule.
     if(!exports.GetString().empty() && !namelinkOnly)
     if(!exports.GetString().empty() && !namelinkOnly)
       {
       {
+      cmTargetExport *te = new cmTargetExport;
+      te->Target = &target;
+      te->ArchiveGenerator = archiveGenerator;
+      te->BundleGenerator = bundleGenerator;
+      te->FrameworkGenerator = frameworkGenerator;
+      te->HeaderGenerator = publicHeaderGenerator;
+      te->LibraryGenerator = libraryGenerator;
+      te->RuntimeGenerator = runtimeGenerator;
       this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
       this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
-        ->AddTargetToExports(exports.GetCString(), &target,
-                             archiveGenerator, runtimeGenerator,
-                             libraryGenerator, frameworkGenerator,
-                             bundleGenerator, publicHeaderGenerator);
+        ->GetExportSets()[exports.GetString()]->AddTargetExport(te);
       }
       }
     }
     }
 
 
@@ -1264,7 +1271,9 @@ bool cmInstallCommand::HandleExportMode(std::vector<std::string> const& args)
   // Create the export install generator.
   // Create the export install generator.
   cmInstallExportGenerator* exportGenerator =
   cmInstallExportGenerator* exportGenerator =
     new cmInstallExportGenerator(
     new cmInstallExportGenerator(
-      exp.GetCString(), ica.GetDestination().c_str(),
+      this->Makefile->GetLocalGenerator()
+          ->GetGlobalGenerator()->GetExportSets()[exp.GetString()],
+      ica.GetDestination().c_str(),
       ica.GetPermissions().c_str(), ica.GetConfigurations(),
       ica.GetPermissions().c_str(), ica.GetConfigurations(),
       ica.GetComponent().c_str(), fname.c_str(),
       ica.GetComponent().c_str(), fname.c_str(),
       name_space.GetCString(), this->Makefile);
       name_space.GetCString(), this->Makefile);

+ 7 - 11
Source/cmInstallExportGenerator.cxx

@@ -23,10 +23,11 @@
 #include "cmInstallFilesGenerator.h"
 #include "cmInstallFilesGenerator.h"
 
 
 #include "cmExportInstallFileGenerator.h"
 #include "cmExportInstallFileGenerator.h"
+#include "cmExportSet.h"
 
 
 //----------------------------------------------------------------------------
 //----------------------------------------------------------------------------
 cmInstallExportGenerator::cmInstallExportGenerator(
 cmInstallExportGenerator::cmInstallExportGenerator(
-  const char* name,
+  cmExportSet* exportSet,
   const char* destination,
   const char* destination,
   const char* file_permissions,
   const char* file_permissions,
   std::vector<std::string> const& configurations,
   std::vector<std::string> const& configurations,
@@ -34,13 +35,14 @@ cmInstallExportGenerator::cmInstallExportGenerator(
   const char* filename, const char* name_space,
   const char* filename, const char* name_space,
   cmMakefile* mf)
   cmMakefile* mf)
   :cmInstallGenerator(destination, configurations, component)
   :cmInstallGenerator(destination, configurations, component)
-  ,Name(name)
+  ,ExportSet(exportSet)
   ,FilePermissions(file_permissions)
   ,FilePermissions(file_permissions)
   ,FileName(filename)
   ,FileName(filename)
   ,Namespace(name_space)
   ,Namespace(name_space)
   ,Makefile(mf)
   ,Makefile(mf)
 {
 {
   this->EFGen = new cmExportInstallFileGenerator(this);
   this->EFGen = new cmExportInstallFileGenerator(this);
+  exportSet->AddInstallation(this);
 }
 }
 
 
 //----------------------------------------------------------------------------
 //----------------------------------------------------------------------------
@@ -113,16 +115,12 @@ void cmInstallExportGenerator::ComputeTempDir()
 //----------------------------------------------------------------------------
 //----------------------------------------------------------------------------
 void cmInstallExportGenerator::GenerateScript(std::ostream& os)
 void cmInstallExportGenerator::GenerateScript(std::ostream& os)
 {
 {
-  // Get the export set requested.
-  ExportSet const* exportSet =
-    this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
-    ->GetExportSet(this->Name.c_str());
-
   // Skip empty sets.
   // Skip empty sets.
-  if(!exportSet)
+  if(ExportSet->GetTargetExports()->empty())
     {
     {
     cmOStringStream e;
     cmOStringStream e;
-    e << "INSTALL(EXPORT) given unknown export \"" << this->Name << "\"";
+    e << "INSTALL(EXPORT) given unknown export \""
+      << ExportSet->GetName() << "\"";
     cmSystemTools::Error(e.str().c_str());
     cmSystemTools::Error(e.str().c_str());
     return;
     return;
     }
     }
@@ -137,8 +135,6 @@ void cmInstallExportGenerator::GenerateScript(std::ostream& os)
   this->MainImportFile += this->FileName;
   this->MainImportFile += this->FileName;
 
 
   // Generate the import file for this export set.
   // 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->SetExportFile(this->MainImportFile.c_str());
   this->EFGen->SetNamespace(this->Namespace.c_str());
   this->EFGen->SetNamespace(this->Namespace.c_str());
   if(this->ConfigurationTypes->empty())
   if(this->ConfigurationTypes->empty())

+ 10 - 8
Source/cmInstallExportGenerator.h

@@ -17,8 +17,7 @@
 class cmExportInstallFileGenerator;
 class cmExportInstallFileGenerator;
 class cmInstallFilesGenerator;
 class cmInstallFilesGenerator;
 class cmInstallTargetGenerator;
 class cmInstallTargetGenerator;
-class cmTarget;
-class cmTargetExport;
+class cmExportSet;
 class cmMakefile;
 class cmMakefile;
 
 
 /** \class cmInstallExportGenerator
 /** \class cmInstallExportGenerator
@@ -27,24 +26,27 @@ class cmMakefile;
 class cmInstallExportGenerator: public cmInstallGenerator
 class cmInstallExportGenerator: public cmInstallGenerator
 {
 {
 public:
 public:
-  cmInstallExportGenerator(const char* name,
+  cmInstallExportGenerator(cmExportSet* exportSet,
                            const char* dest, const char* file_permissions,
                            const char* dest, const char* file_permissions,
                            const std::vector<std::string>& configurations,
                            const std::vector<std::string>& configurations,
                            const char* component,
                            const char* component,
                            const char* filename, const char* name_space,
                            const char* filename, const char* name_space,
                            cmMakefile* mf);
                            cmMakefile* mf);
   ~cmInstallExportGenerator();
   ~cmInstallExportGenerator();
-protected:
-  typedef std::vector<cmTargetExport*> ExportSet;
 
 
+  cmExportSet* GetExportSet() {return this->ExportSet;}
+
+  const std::string& GetNamespace() const { return this->Namespace; }
+
+protected:
   virtual void GenerateScript(std::ostream& os);
   virtual void GenerateScript(std::ostream& os);
   virtual void GenerateScriptConfigs(std::ostream& os, Indent const& indent);
   virtual void GenerateScriptConfigs(std::ostream& os, Indent const& indent);
   virtual void GenerateScriptActions(std::ostream& os, Indent const& indent);
   virtual void GenerateScriptActions(std::ostream& os, Indent const& indent);
-  void GenerateImportFile(ExportSet const* exportSet);
-  void GenerateImportFile(const char* config, ExportSet const* exportSet);
+  void GenerateImportFile(cmExportSet const* exportSet);
+  void GenerateImportFile(const char* config, cmExportSet const* exportSet);
   void ComputeTempDir();
   void ComputeTempDir();
 
 
-  std::string Name;
+  cmExportSet* ExportSet;
   std::string FilePermissions;
   std::string FilePermissions;
   std::string FileName;
   std::string FileName;
   std::string Namespace;
   std::string Namespace;

+ 39 - 0
Source/cmTargetExport.h

@@ -0,0 +1,39 @@
+/*============================================================================
+  CMake - Cross Platform Makefile Generator
+  Copyright 2000-2012 Kitware, Inc., Insight Software Consortium
+
+  Distributed under the OSI-approved BSD License (the "License");
+  see accompanying file Copyright.txt for details.
+
+  This software is distributed WITHOUT ANY WARRANTY; without even the
+  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the License for more information.
+============================================================================*/
+#ifndef cmTargetExport_h
+#define cmTargetExport_h
+
+class cmTarget;
+class cmInstallTargetGenerator;
+class cmInstallFilesGenerator;
+
+/** \brief A member of an ExportSet
+ *
+ * This struct holds pointers to target and all relevant generators.
+ */
+class cmTargetExport
+{
+public:
+  cmTarget* Target; ///< The target
+
+  ///@name Generators
+  ///@{
+  cmInstallTargetGenerator* ArchiveGenerator;
+  cmInstallTargetGenerator* RuntimeGenerator;
+  cmInstallTargetGenerator* LibraryGenerator;
+  cmInstallTargetGenerator* FrameworkGenerator;
+  cmInstallTargetGenerator* BundleGenerator;
+  cmInstallFilesGenerator* HeaderGenerator;
+  ///@}
+};
+
+#endif

+ 12 - 0
Tests/ExportImport/Export/CMakeLists.txt

@@ -87,6 +87,18 @@ target_link_libraries(testLibCycleA testLibCycleB)
 target_link_libraries(testLibCycleB testLibCycleA)
 target_link_libraries(testLibCycleB testLibCycleA)
 set_property(TARGET testLibCycleA PROPERTY LINK_INTERFACE_MULTIPLICITY 3)
 set_property(TARGET testLibCycleA PROPERTY LINK_INTERFACE_MULTIPLICITY 3)
 
 
+# Test exporting dependent libraries into different exports
+add_library(testLibRequired testLibRequired.c)
+add_library(testLibDepends testLibDepends.c)
+target_link_libraries(testLibDepends testLibRequired)
+
+install(TARGETS testLibRequired EXPORT RequiredExp DESTINATION lib )
+install(EXPORT RequiredExp NAMESPACE Req:: FILE testLibRequiredConfig.cmake DESTINATION lib/cmake/testLibRequired)
+
+install(TARGETS testLibDepends EXPORT DependsExp DESTINATION lib )
+install(EXPORT DependsExp FILE testLibDependsConfig.cmake DESTINATION lib/cmake/testLibDepends)
+
+
 # Install and export from install tree.
 # Install and export from install tree.
 install(
 install(
   TARGETS
   TARGETS

+ 4 - 0
Tests/ExportImport/Export/testLibDepends.c

@@ -0,0 +1,4 @@
+
+extern int testLibRequired(void);
+
+int testLibDepends(void) { return testLibRequired(); }

+ 1 - 0
Tests/ExportImport/Export/testLibRequired.c

@@ -0,0 +1 @@
+int testLibRequired(void) { return 0; }

+ 4 - 0
Tests/ExportImport/Import/A/CMakeLists.txt

@@ -4,6 +4,10 @@ include(${Import_BINARY_DIR}/../Export/ExportBuildTree.cmake)
 # Import targets from the exported install tree.
 # Import targets from the exported install tree.
 include(${CMAKE_INSTALL_PREFIX}/lib/exp/exp.cmake)
 include(${CMAKE_INSTALL_PREFIX}/lib/exp/exp.cmake)
 
 
+# Import two exports, where the Depends one depends on an exported target from the Required one:
+include(${CMAKE_INSTALL_PREFIX}/lib/cmake/testLibRequired/testLibRequiredConfig.cmake)
+include(${CMAKE_INSTALL_PREFIX}/lib/cmake/testLibDepends/testLibDependsConfig.cmake)
+
 # Try referencing an executable imported from the install tree.
 # Try referencing an executable imported from the install tree.
 add_custom_command(
 add_custom_command(
   OUTPUT ${Import_BINARY_DIR}/exp_generated.c
   OUTPUT ${Import_BINARY_DIR}/exp_generated.c

+ 2 - 0
bootstrap

@@ -199,6 +199,8 @@ CMAKE_CXX_SOURCES="\
   cmMakefile \
   cmMakefile \
   cmExportFileGenerator \
   cmExportFileGenerator \
   cmExportInstallFileGenerator \
   cmExportInstallFileGenerator \
+  cmExportSet \
+  cmExportSetMap \
   cmInstallDirectoryGenerator \
   cmInstallDirectoryGenerator \
   cmGeneratedFileStream \
   cmGeneratedFileStream \
   cmGeneratorTarget \
   cmGeneratorTarget \