فهرست منبع

Generate an early-return guard in target Export files.

Previously it was necessary for writers of Config files
which incude exported target files to write the guard themselves, but
this was not immediately obvious or documented. Options for them
would be to use a variable, or an INHERITED directory property in an
effort to avoid accidental name clashes in all contexts in
which find_package can be used.

Getting this right requires boiler plate code, so generate a simpler
check automatically instead.
Stephen Kelly 13 سال پیش
والد
کامیت
bf2ddceb4e
4فایلهای تغییر یافته به همراه61 افزوده شده و 0 حذف شده
  1. 14 0
      Source/cmExportBuildFileGenerator.cxx
  2. 31 0
      Source/cmExportFileGenerator.cxx
  3. 2 0
      Source/cmExportFileGenerator.h
  4. 14 0
      Source/cmExportInstallFileGenerator.cxx

+ 14 - 0
Source/cmExportBuildFileGenerator.cxx

@@ -22,6 +22,20 @@ cmExportBuildFileGenerator::cmExportBuildFileGenerator()
 //----------------------------------------------------------------------------
 //----------------------------------------------------------------------------
 bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os)
 bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os)
 {
 {
+  {
+  std::string expectedTargets;
+  std::string sep;
+  for(std::vector<cmTarget*>::const_iterator
+        tei = this->Exports->begin();
+      tei != this->Exports->end(); ++tei)
+    {
+    expectedTargets += sep + this->Namespace + (*tei)->GetName();
+    sep = " ";
+    }
+
+  this->GenerateExpectedTargetsCode(os, expectedTargets);
+  }
+
   // Create all the imported targets.
   // Create all the imported targets.
   for(std::vector<cmTarget*>::const_iterator
   for(std::vector<cmTarget*>::const_iterator
         tei = this->Exports->begin();
         tei = this->Exports->begin();

+ 31 - 0
Source/cmExportFileGenerator.cxx

@@ -286,6 +286,37 @@ void cmExportFileGenerator::GenerateImportVersionCode(std::ostream& os)
      << "\n";
      << "\n";
 }
 }
 
 
+//----------------------------------------------------------------------------
+void cmExportFileGenerator::GenerateExpectedTargetsCode(std::ostream& os,
+                                            const std::string &expectedTargets)
+{
+  os << "SET(_targetsDefined)\n"
+        "SET(_targetsNotDefined)\n"
+        "SET(_expectedTargets)\n"
+        "FOREACH(_expectedTarget " << expectedTargets << ")\n"
+        "  LIST(APPEND _expectedTargets ${_expectedTarget})\n"
+        "  IF(NOT TARGET ${_expectedTarget})\n"
+        "    LIST(APPEND _targetsNotDefined ${_expectedTarget})\n"
+        "  ENDIF(NOT TARGET ${_expectedTarget})\n"
+        "  IF(TARGET ${_expectedTarget})\n"
+        "    LIST(APPEND _targetsDefined ${_expectedTarget})\n"
+        "  ENDIF(TARGET ${_expectedTarget})\n"
+        "ENDFOREACH(_expectedTarget)\n"
+        "IF(\"${_targetsDefined}\" STREQUAL \"${_expectedTargets}\")\n"
+        "  SET(CMAKE_IMPORT_FILE_VERSION)\n"
+        "  CMAKE_POLICY(POP)\n"
+        "  RETURN()\n"
+        "ENDIF(\"${_targetsDefined}\" STREQUAL \"${_expectedTargets}\")\n"
+        "IF(NOT \"${_targetsDefined}\" STREQUAL \"\")\n"
+        "  MESSAGE(FATAL_ERROR \"Some (but not all) targets in this export "
+        "set were already defined.\\nTargets Defined: ${_targetsDefined}\\n"
+        "Targets not yet defined: ${_targetsNotDefined}\\n\")\n"
+        "ENDIF(NOT \"${_targetsDefined}\" STREQUAL \"\")\n"
+        "UNSET(_targetsDefined)\n"
+        "UNSET(_targetsNotDefined)\n"
+        "UNSET(_expectedTargets)\n"
+        "\n\n";
+}
 //----------------------------------------------------------------------------
 //----------------------------------------------------------------------------
 void
 void
 cmExportFileGenerator
 cmExportFileGenerator

+ 2 - 0
Source/cmExportFileGenerator.h

@@ -63,6 +63,8 @@ protected:
   void GenerateMissingTargetsCheckCode(std::ostream& os,
   void GenerateMissingTargetsCheckCode(std::ostream& os,
                                const std::vector<std::string>& missingTargets);
                                const std::vector<std::string>& missingTargets);
 
 
+  void GenerateExpectedTargetsCode(std::ostream& os,
+                                          const std::string &expectedTargets);
 
 
   // Collect properties with detailed information about targets beyond
   // Collect properties with detailed information about targets beyond
   // their location on disk.
   // their location on disk.

+ 14 - 0
Source/cmExportInstallFileGenerator.cxx

@@ -39,6 +39,20 @@ std::string cmExportInstallFileGenerator::GetConfigImportFileGlob()
 //----------------------------------------------------------------------------
 //----------------------------------------------------------------------------
 bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
 bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
 {
 {
+  {
+  std::string expectedTargets;
+  std::string sep;
+  for(std::vector<cmTargetExport*>::const_iterator
+        tei = this->IEGen->GetExportSet()->GetTargetExports()->begin();
+      tei != this->IEGen->GetExportSet()->GetTargetExports()->end(); ++tei)
+    {
+    expectedTargets += sep + this->Namespace + (*tei)->Target->GetName();
+    sep = " ";
+    }
+
+  this->GenerateExpectedTargetsCode(os, expectedTargets);
+  }
+
   // Create all the imported targets.
   // Create all the imported targets.
   for(std::vector<cmTargetExport*>::const_iterator
   for(std::vector<cmTargetExport*>::const_iterator
         tei = this->IEGen->GetExportSet()->GetTargetExports()->begin();
         tei = this->IEGen->GetExportSet()->GetTargetExports()->begin();