ソースを参照

export(): Process the export() command at generate time.

Make the API for adding targets string based so that it can easily
use cmGeneratorTarget.

Teach the cmIncludeCommand to generate the exported file at
configure-time instead if it is to be include()d.

The RunCMake.ExportWithoutLanguage test now needs a dummy header.h
file as expected error from export() is now reported after the
missing file error.
Stephen Kelly 13 年 前
コミット
66b290e7e2

+ 10 - 11
Source/cmExportBuildFileGenerator.cxx

@@ -21,20 +21,19 @@ cmExportBuildFileGenerator::cmExportBuildFileGenerator()
 //----------------------------------------------------------------------------
 //----------------------------------------------------------------------------
 bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os)
 bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os)
 {
 {
-  std::vector<cmTarget*> allTargets;
   {
   {
   std::string expectedTargets;
   std::string expectedTargets;
   std::string sep;
   std::string sep;
-  for(std::vector<cmTarget*>::const_iterator
-        tei = this->Exports->begin();
-      tei != this->Exports->end(); ++tei)
+  for(std::vector<std::string>::const_iterator
+        tei = this->Targets.begin();
+      tei != this->Targets.end(); ++tei)
     {
     {
-    expectedTargets += sep + this->Namespace + (*tei)->GetExportName();
+    cmTarget *te = this->Makefile->FindTargetToUse(tei->c_str());
+    expectedTargets += sep + this->Namespace + te->GetExportName();
     sep = " ";
     sep = " ";
-    cmTarget* te = *tei;
     if(this->ExportedTargets.insert(te).second)
     if(this->ExportedTargets.insert(te).second)
       {
       {
-      allTargets.push_back(te);
+      this->Exports.push_back(te);
       }
       }
     else
     else
       {
       {
@@ -57,8 +56,8 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os)
 
 
   // Create all the imported targets.
   // Create all the imported targets.
   for(std::vector<cmTarget*>::const_iterator
   for(std::vector<cmTarget*>::const_iterator
-        tei = allTargets.begin();
-      tei != allTargets.end(); ++tei)
+        tei = this->Exports.begin();
+      tei != this->Exports.end(); ++tei)
     {
     {
     cmTarget* te = *tei;
     cmTarget* te = *tei;
     this->GenerateImportTargetCode(os, te);
     this->GenerateImportTargetCode(os, te);
@@ -113,8 +112,8 @@ cmExportBuildFileGenerator
                             std::vector<std::string> &missingTargets)
                             std::vector<std::string> &missingTargets)
 {
 {
   for(std::vector<cmTarget*>::const_iterator
   for(std::vector<cmTarget*>::const_iterator
-        tei = this->Exports->begin();
-      tei != this->Exports->end(); ++tei)
+        tei = this->Exports.begin();
+      tei != this->Exports.end(); ++tei)
     {
     {
     // Collect import properties for this target.
     // Collect import properties for this target.
     cmTarget* target = *tei;
     cmTarget* target = *tei;

+ 9 - 3
Source/cmExportBuildFileGenerator.h

@@ -30,8 +30,13 @@ public:
   cmExportBuildFileGenerator();
   cmExportBuildFileGenerator();
 
 
   /** Set the list of targets to export.  */
   /** Set the list of targets to export.  */
-  void SetExports(std::vector<cmTarget*> const* exports)
-    { this->Exports = exports; }
+  void SetTargets(std::vector<std::string> const& targets)
+    { this->Targets = targets; }
+  std::vector<std::string> const& GetTargets() const
+    { return this->Targets; }
+  void AppendTargets(std::vector<std::string> const& targets)
+    { this->Targets.insert(this->Targets.end(),
+      targets.begin(), targets.end()); }
 
 
   /** Set whether to append generated code to the output file.  */
   /** Set whether to append generated code to the output file.  */
   void SetAppendMode(bool append) { this->AppendMode = append; }
   void SetAppendMode(bool append) { this->AppendMode = append; }
@@ -65,7 +70,8 @@ protected:
 
 
   std::string InstallNameDir(cmTarget* target, const std::string& config);
   std::string InstallNameDir(cmTarget* target, const std::string& config);
 
 
-  std::vector<cmTarget*> const* Exports;
+  std::vector<std::string> Targets;
+  std::vector<cmTarget*> Exports;
   cmMakefile* Makefile;
   cmMakefile* Makefile;
   cmListFileBacktrace Backtrace;
   cmListFileBacktrace Backtrace;
 };
 };

+ 20 - 51
Source/cmExportCommand.cxx

@@ -108,8 +108,6 @@ bool cmExportCommand
     fname += this->Filename.GetString();
     fname += this->Filename.GetString();
     }
     }
 
 
-  // Collect the targets to be exported.
-  std::vector<cmTarget*> targets;
   for(std::vector<std::string>::const_iterator
   for(std::vector<std::string>::const_iterator
       currentTarget = this->Targets.GetVector().begin();
       currentTarget = this->Targets.GetVector().begin();
       currentTarget != this->Targets.GetVector().end();
       currentTarget != this->Targets.GetVector().end();
@@ -128,15 +126,7 @@ bool cmExportCommand
        this->Makefile->GetLocalGenerator()->
        this->Makefile->GetLocalGenerator()->
        GetGlobalGenerator()->FindTarget(0, currentTarget->c_str()))
        GetGlobalGenerator()->FindTarget(0, currentTarget->c_str()))
       {
       {
-      if((target->GetType() == cmTarget::EXECUTABLE) ||
-         (target->GetType() == cmTarget::STATIC_LIBRARY) ||
-         (target->GetType() == cmTarget::SHARED_LIBRARY) ||
-         (target->GetType() == cmTarget::MODULE_LIBRARY) ||
-         (target->GetType() == cmTarget::INTERFACE_LIBRARY))
-        {
-        targets.push_back(target);
-        }
-      else if(target->GetType() == cmTarget::OBJECT_LIBRARY)
+      if(target->GetType() == cmTarget::OBJECT_LIBRARY)
         {
         {
         cmOStringStream e;
         cmOStringStream e;
         e << "given OBJECT library \"" << *currentTarget
         e << "given OBJECT library \"" << *currentTarget
@@ -144,37 +134,28 @@ bool cmExportCommand
         this->SetError(e.str().c_str());
         this->SetError(e.str().c_str());
         return false;
         return false;
         }
         }
-      else
-        {
-        cmOStringStream e;
-        e << "given target \"" << *currentTarget
-          << "\" which is not an executable or library.";
-        this->SetError(e.str().c_str());
-        return false;
-        }
       }
       }
-    else
+    }
+
+  cmGlobalGenerator *gg = this->Makefile->GetLocalGenerator()
+                                        ->GetGlobalGenerator();
+  if (this->Append.IsEnabled())
+    {
+    if (cmExportBuildFileGenerator *ebfg = gg->GetExportedTargetsFile(fname))
       {
       {
-      cmOStringStream e;
-      e << "given target \"" << *currentTarget
-        << "\" which is not built by this project.";
-      this->SetError(e.str().c_str());
-      return false;
+      ebfg->AppendTargets(this->Targets.GetVector());
+      return true;
       }
       }
     }
     }
 
 
   // Setup export file generation.
   // Setup export file generation.
-  cmExportBuildFileGenerator ebfg;
-  ebfg.SetExportFile(fname.c_str());
-  ebfg.SetNamespace(this->Namespace.GetCString());
-  ebfg.SetAppendMode(this->Append.IsEnabled());
-  ebfg.SetExports(&targets);
-  ebfg.SetMakefile(this->Makefile);
-  ebfg.SetExportOld(this->ExportOld.IsEnabled());
-
-  cmGlobalGenerator *gg = this->Makefile->GetLocalGenerator()
-                                        ->GetGlobalGenerator();
-  gg->AddExportedTargetsFile(fname);
+  cmExportBuildFileGenerator *ebfg = new cmExportBuildFileGenerator;
+  ebfg->SetExportFile(fname.c_str());
+  ebfg->SetNamespace(this->Namespace.GetCString());
+  ebfg->SetAppendMode(this->Append.IsEnabled());
+  ebfg->SetTargets(this->Targets.GetVector());
+  ebfg->SetMakefile(this->Makefile);
+  ebfg->SetExportOld(this->ExportOld.IsEnabled());
 
 
   // Compute the set of configurations exported.
   // Compute the set of configurations exported.
   std::vector<std::string> configurationTypes;
   std::vector<std::string> configurationTypes;
@@ -185,27 +166,15 @@ bool cmExportCommand
           ci = configurationTypes.begin();
           ci = configurationTypes.begin();
         ci != configurationTypes.end(); ++ci)
         ci != configurationTypes.end(); ++ci)
       {
       {
-      ebfg.AddConfiguration(ci->c_str());
+      ebfg->AddConfiguration(ci->c_str());
       }
       }
     }
     }
   else
   else
     {
     {
-    ebfg.AddConfiguration("");
+    ebfg->AddConfiguration("");
     }
     }
 
 
-  // Generate the import file.
-  if(!ebfg.GenerateImportFile() && this->ErrorMessage.empty())
-    {
-    this->SetError("could not write export file.");
-    return false;
-    }
-
-  // Report generated error message if any.
-  if(!this->ErrorMessage.empty())
-    {
-    this->SetError(this->ErrorMessage.c_str());
-    return false;
-    }
+  gg->AddBuildExportSet(ebfg);
 
 
   return true;
   return true;
 }
 }

+ 3 - 1
Source/cmExportCommand.h

@@ -85,7 +85,9 @@ public:
       "should never be installed.  "
       "should never be installed.  "
       "See the install(EXPORT) command to export targets from an "
       "See the install(EXPORT) command to export targets from an "
       "installation tree."
       "installation tree."
-      CM_LOCATION_UNDEFINED_BEHAVIOR("passing it to this command")
+      "\n"
+      "The properties set on the generated IMPORTED targets will have the "
+      "same values as the final values of the input TARGETS."
       "\n"
       "\n"
       "  export(PACKAGE <name>)\n"
       "  export(PACKAGE <name>)\n"
       "Store the current build directory in the CMake user package registry "
       "Store the current build directory in the CMake user package registry "

+ 6 - 0
Source/cmExportFileGenerator.cxx

@@ -51,6 +51,12 @@ void cmExportFileGenerator::SetExportFile(const char* mainFile)
     cmSystemTools::GetFilenameLastExtension(this->MainImportFile);
     cmSystemTools::GetFilenameLastExtension(this->MainImportFile);
 }
 }
 
 
+//----------------------------------------------------------------------------
+const char* cmExportFileGenerator::GetMainExportFileName() const
+{
+  return this->MainImportFile.c_str();
+}
+
 //----------------------------------------------------------------------------
 //----------------------------------------------------------------------------
 bool cmExportFileGenerator::GenerateImportFile()
 bool cmExportFileGenerator::GenerateImportFile()
 {
 {

+ 2 - 0
Source/cmExportFileGenerator.h

@@ -33,9 +33,11 @@ public:
 
 
   /** Set the full path to the export file to generate.  */
   /** Set the full path to the export file to generate.  */
   void SetExportFile(const char* mainFile);
   void SetExportFile(const char* mainFile);
+  const char *GetMainExportFileName() const;
 
 
   /** Set the namespace in which to place exported target names.  */
   /** Set the namespace in which to place exported target names.  */
   void SetNamespace(const char* ns) { this->Namespace = ns; }
   void SetNamespace(const char* ns) { this->Namespace = ns; }
+  std::string GetNamespace() const { return this->Namespace; }
 
 
   void SetExportOld(bool exportOld) { this->ExportOld = exportOld; }
   void SetExportOld(bool exportOld) { this->ExportOld = exportOld; }
 
 

+ 56 - 0
Source/cmGlobalGenerator.cxx

@@ -27,6 +27,7 @@
 #include "cmGeneratorTarget.h"
 #include "cmGeneratorTarget.h"
 #include "cmGeneratorExpression.h"
 #include "cmGeneratorExpression.h"
 #include "cmGeneratorExpressionEvaluationFile.h"
 #include "cmGeneratorExpressionEvaluationFile.h"
+#include "cmExportBuildFileGenerator.h"
 
 
 #include <cmsys/Directory.hxx>
 #include <cmsys/Directory.hxx>
 
 
@@ -77,6 +78,12 @@ cmGlobalGenerator::~cmGlobalGenerator()
     {
     {
     delete *li;
     delete *li;
     }
     }
+  for(std::map<std::string, cmExportBuildFileGenerator*>::iterator
+        i = this->BuildExportSets.begin();
+      i != this->BuildExportSets.end(); ++i)
+    {
+    delete i->second;
+    }
   this->LocalGenerators.clear();
   this->LocalGenerators.clear();
 
 
   if (this->ExtraGenerator)
   if (this->ExtraGenerator)
@@ -183,6 +190,34 @@ void cmGlobalGenerator::ResolveLanguageCompiler(const std::string &lang,
                          doc.c_str(), cmCacheManager::FILEPATH);
                          doc.c_str(), cmCacheManager::FILEPATH);
 }
 }
 
 
+void cmGlobalGenerator::AddBuildExportSet(cmExportBuildFileGenerator* gen)
+{
+  this->BuildExportSets[gen->GetMainExportFileName()] = gen;
+}
+
+bool cmGlobalGenerator::GenerateImportFile(const std::string &file)
+{
+  std::map<std::string, cmExportBuildFileGenerator*>::iterator it
+                                          = this->BuildExportSets.find(file);
+  if (it != this->BuildExportSets.end())
+    {
+    bool result = it->second->GenerateImportFile();
+    delete it->second;
+    it->second = 0;
+    this->BuildExportSets.erase(it);
+    return result;
+    }
+  return false;
+}
+
+bool
+cmGlobalGenerator::IsExportedTargetsFile(const std::string &filename) const
+{
+  const std::map<std::string, cmExportBuildFileGenerator*>::const_iterator it
+                                      = this->BuildExportSets.find(filename);
+  return it != this->BuildExportSets.end();
+}
+
 // Find the make program for the generator, required for try compiles
 // Find the make program for the generator, required for try compiles
 void cmGlobalGenerator::FindMakeProgram(cmMakefile* mf)
 void cmGlobalGenerator::FindMakeProgram(cmMakefile* mf)
 {
 {
@@ -966,6 +1001,14 @@ void cmGlobalGenerator::Configure()
     }
     }
 }
 }
 
 
+cmExportBuildFileGenerator*
+cmGlobalGenerator::GetExportedTargetsFile(const std::string &filename) const
+{
+  std::map<std::string, cmExportBuildFileGenerator*>::const_iterator it
+    = this->BuildExportSets.find(filename);
+  return it == this->BuildExportSets.end() ? 0 : it->second;
+}
+
 bool cmGlobalGenerator::CheckALLOW_DUPLICATE_CUSTOM_TARGETS()
 bool cmGlobalGenerator::CheckALLOW_DUPLICATE_CUSTOM_TARGETS()
 {
 {
   // If the property is not enabled then okay.
   // If the property is not enabled then okay.
@@ -1091,6 +1134,19 @@ void cmGlobalGenerator::Generate()
     }
     }
   this->SetCurrentLocalGenerator(0);
   this->SetCurrentLocalGenerator(0);
 
 
+  for (std::map<std::string, cmExportBuildFileGenerator*>::iterator
+      it = this->BuildExportSets.begin(); it != this->BuildExportSets.end();
+      ++it)
+    {
+    if (!it->second->GenerateImportFile()
+        && !cmSystemTools::GetErrorOccuredFlag())
+      {
+      this->GetCMakeInstance()
+          ->IssueMessage(cmake::FATAL_ERROR, "Could not write export file.",
+                        cmListFileBacktrace());
+      return;
+      }
+    }
   // Update rule hashes.
   // Update rule hashes.
   this->CheckRuleHashes();
   this->CheckRuleHashes();
 
 

+ 9 - 13
Source/cmGlobalGenerator.h

@@ -31,6 +31,7 @@ class cmExternalMakefileProjectGenerator;
 class cmTarget;
 class cmTarget;
 class cmInstallTargetGenerator;
 class cmInstallTargetGenerator;
 class cmInstallFilesGenerator;
 class cmInstallFilesGenerator;
+class cmExportBuildFileGenerator;
 
 
 /** \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
@@ -293,18 +294,13 @@ public:
 
 
   void ProcessEvaluationFiles();
   void ProcessEvaluationFiles();
 
 
-  void AddExportedTargetsFile(const std::string &filename)
-  {
-    this->ExportedTargetsFiles.insert(filename);
-  }
-
-  bool IsExportedTargetsFile(const std::string &filename) const
-  {
-    const std::set<std::string>::const_iterator it
-                                  = this->ExportedTargetsFiles.find(filename);
-    return it != this->ExportedTargetsFiles.end();
-  }
-
+  std::map<std::string, cmExportBuildFileGenerator*>& GetBuildExportSets()
+    {return this->BuildExportSets;}
+  void AddBuildExportSet(cmExportBuildFileGenerator*);
+  bool IsExportedTargetsFile(const std::string &filename) const;
+  bool GenerateImportFile(const std::string &file);
+  cmExportBuildFileGenerator*
+  GetExportedTargetsFile(const std::string &filename) const;
 protected:
 protected:
   typedef std::vector<cmLocalGenerator*> GeneratorVector;
   typedef std::vector<cmLocalGenerator*> GeneratorVector;
   // for a project collect all its targets by following depend
   // for a project collect all its targets by following depend
@@ -356,6 +352,7 @@ protected:
   bool InstallTargetEnabled;
   bool InstallTargetEnabled;
   // Sets of named target exports
   // Sets of named target exports
   cmExportSetMap ExportSets;
   cmExportSetMap ExportSets;
+  std::map<std::string, cmExportBuildFileGenerator*> BuildExportSets;
 
 
   // 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.
@@ -384,7 +381,6 @@ private:
   std::map<cmStdString, cmStdString> ExtensionToLanguage;
   std::map<cmStdString, cmStdString> ExtensionToLanguage;
   std::map<cmStdString, int> LanguageToLinkerPreference;
   std::map<cmStdString, int> LanguageToLinkerPreference;
   std::map<cmStdString, cmStdString> LanguageToOriginalSharedLibFlags;
   std::map<cmStdString, cmStdString> LanguageToOriginalSharedLibFlags;
-  std::set<std::string> ExportedTargetsFiles;
 
 
   // Record hashes for rules and outputs.
   // Record hashes for rules and outputs.
   struct RuleHash { char Data[32]; };
   struct RuleHash { char Data[32]; };

+ 1 - 0
Source/cmIncludeCommand.cxx

@@ -127,6 +127,7 @@ bool cmIncludeCommand
         return false;
         return false;
         }
         }
       }
       }
+    gg->GenerateImportFile(fname_abs);
     }
     }
 
 
   std::string fullFilePath;
   std::string fullFilePath;

+ 1 - 1
Tests/RunCMake/CMP0022/CMP0022-export-stderr.txt

@@ -1,4 +1,4 @@
-CMake Error at CMP0022-export.cmake:11 \(export\):
+CMake Error in CMakeLists.txt:
   Target "cmp0022NEW" has policy CMP0022 enabled, but also has old-style
   Target "cmp0022NEW" has policy CMP0022 enabled, but also has old-style
   LINK_INTERFACE_LIBRARIES properties populated, but it was exported without
   LINK_INTERFACE_LIBRARIES properties populated, but it was exported without
   the EXPORT_LINK_INTERFACE_LIBRARIES to export the old-style properties
   the EXPORT_LINK_INTERFACE_LIBRARIES to export the old-style properties

+ 1 - 3
Tests/RunCMake/ExportWithoutLanguage/NoLanguage-stderr.txt

@@ -1,6 +1,4 @@
 CMake Error: CMake can not determine linker language for target: NoLanguage
 CMake Error: CMake can not determine linker language for target: NoLanguage
-CMake Error at NoLanguage.cmake:2 \(export\):
+CMake Error in CMakeLists.txt:
   Exporting the target "NoLanguage" is not allowed since its linker language
   Exporting the target "NoLanguage" is not allowed since its linker language
   cannot be determined
   cannot be determined
-Call Stack \(most recent call first\):
-  CMakeLists.txt:3 \(include\)

+ 2 - 0
Tests/RunCMake/ExportWithoutLanguage/header.h

@@ -0,0 +1,2 @@
+
+enum some_compilers { need_more_than_nothing };