Browse Source

Merge topic 'cps-validate-version'

cc508826b4 CPS: Validate package version
fb66a14da2 cmExportFileGenerator: Allow other message types

Acked-by: Kitware Robot <[email protected]>
Tested-by: buildbot <[email protected]>
Merge-request: !11458
Brad King 2 days ago
parent
commit
d6b76cdc87
25 changed files with 250 additions and 18 deletions
  1. 3 5
      Source/cmExportBuildFileGenerator.cxx
  2. 2 1
      Source/cmExportBuildFileGenerator.h
  3. 1 1
      Source/cmExportBuildPackageInfoGenerator.cxx
  4. 8 1
      Source/cmExportFileGenerator.h
  5. 3 3
      Source/cmExportInstallFileGenerator.cxx
  6. 2 1
      Source/cmExportInstallFileGenerator.h
  7. 1 1
      Source/cmExportInstallPackageInfoGenerator.cxx
  8. 59 0
      Source/cmExportPackageInfoGenerator.cxx
  9. 7 1
      Source/cmExportPackageInfoGenerator.h
  10. 20 3
      Source/cmExportTryCompileFileGenerator.cxx
  11. 2 1
      Source/cmExportTryCompileFileGenerator.h
  12. 7 0
      Tests/RunCMake/ExportPackageInfo/RunCMakeTest.cmake
  13. 38 0
      Tests/RunCMake/ExportPackageInfo/VersionCheck.cmake
  14. 1 0
      Tests/RunCMake/ExportPackageInfo/VersionCheckError-result.txt
  15. 2 0
      Tests/RunCMake/ExportPackageInfo/VersionCheckError-stderr.txt
  16. 5 0
      Tests/RunCMake/ExportPackageInfo/VersionCheckError.cmake
  17. 3 0
      Tests/RunCMake/ExportPackageInfo/VersionCheckWarning-stderr.txt
  18. 15 0
      Tests/RunCMake/ExportPackageInfo/VersionCheckWarning.cmake
  19. 7 0
      Tests/RunCMake/InstallPackageInfo/RunCMakeTest.cmake
  20. 38 0
      Tests/RunCMake/InstallPackageInfo/VersionCheck.cmake
  21. 1 0
      Tests/RunCMake/InstallPackageInfo/VersionCheckError-result.txt
  22. 2 0
      Tests/RunCMake/InstallPackageInfo/VersionCheckError-stderr.txt
  23. 5 0
      Tests/RunCMake/InstallPackageInfo/VersionCheckError.cmake
  24. 3 0
      Tests/RunCMake/InstallPackageInfo/VersionCheckWarning-stderr.txt
  25. 15 0
      Tests/RunCMake/InstallPackageInfo/VersionCheckWarning.cmake

+ 3 - 5
Source/cmExportBuildFileGenerator.cxx

@@ -16,7 +16,6 @@
 #include "cmList.h"
 #include "cmLocalGenerator.h"
 #include "cmMakefile.h"
-#include "cmMessageType.h"
 #include "cmStateTypes.h"
 #include "cmStringAlgorithms.h"
 #include "cmTarget.h"
@@ -242,12 +241,11 @@ void cmExportBuildFileGenerator::ComplainAboutDuplicateTarget(
   this->ReportError(e.str());
 }
 
-void cmExportBuildFileGenerator::ReportError(
-  std::string const& errorMessage) const
+void cmExportBuildFileGenerator::IssueMessage(MessageType type,
+                                              std::string const& message) const
 {
   this->LG->GetGlobalGenerator()->GetCMakeInstance()->IssueMessage(
-    MessageType::FATAL_ERROR, errorMessage,
-    this->LG->GetMakefile()->GetBacktrace());
+    type, message, this->LG->GetMakefile()->GetBacktrace());
 }
 
 std::string cmExportBuildFileGenerator::InstallNameDir(

+ 2 - 1
Source/cmExportBuildFileGenerator.h

@@ -86,7 +86,8 @@ protected:
   void ComplainAboutDuplicateTarget(
     std::string const& targetName) const override;
 
-  void ReportError(std::string const& errorMessage) const override;
+  void IssueMessage(MessageType type,
+                    std::string const& message) const override;
 
   /** Fill in properties indicating built file locations.  */
   void SetImportLocationProperty(std::string const& config,

+ 1 - 1
Source/cmExportBuildPackageInfoGenerator.cxx

@@ -32,7 +32,7 @@ bool cmExportBuildPackageInfoGenerator::GenerateMainFile(std::ostream& os)
     return false;
   }
 
-  if (!this->CheckDefaultTargets()) {
+  if (!this->CheckPackage()) {
     return false;
   }
 

+ 8 - 1
Source/cmExportFileGenerator.h

@@ -13,6 +13,7 @@
 #include <cm/string_view>
 
 #include "cmGeneratorExpression.h"
+#include "cmMessageType.h"
 
 class cmExportSet;
 class cmGeneratorTarget;
@@ -120,7 +121,13 @@ protected:
     cmGeneratorExpression::PreprocessContext preprocessRule,
     ImportPropertyMap& properties);
 
-  virtual void ReportError(std::string const& errorMessage) const = 0;
+  virtual void IssueMessage(MessageType type,
+                            std::string const& message) const = 0;
+
+  void ReportError(std::string const& errorMessage) const
+  {
+    this->IssueMessage(MessageType::FATAL_ERROR, errorMessage);
+  }
 
   struct ExportInfo
   {

+ 3 - 3
Source/cmExportInstallFileGenerator.cxx

@@ -335,11 +335,11 @@ void cmExportInstallFileGenerator::ComplainAboutDuplicateTarget(
   this->ReportError(e.str());
 }
 
-void cmExportInstallFileGenerator::ReportError(
-  std::string const& errorMessage) const
+void cmExportInstallFileGenerator::IssueMessage(
+  MessageType type, std::string const& message) const
 {
   this->IEGen->GetLocalGenerator()->GetCMakeInstance()->IssueMessage(
-    MessageType::FATAL_ERROR, errorMessage,
+    type, message,
     this->IEGen->GetLocalGenerator()->GetMakefile()->GetBacktrace());
 }
 

+ 2 - 1
Source/cmExportInstallFileGenerator.h

@@ -94,7 +94,8 @@ protected:
 
   ExportInfo FindExportInfo(cmGeneratorTarget const* target) const override;
 
-  void ReportError(std::string const& errorMessage) const override;
+  void IssueMessage(MessageType type,
+                    std::string const& message) const override;
 
   /** Generate a per-configuration file for the targets.  */
   virtual bool GenerateImportFileConfig(std::string const& config);

+ 1 - 1
Source/cmExportInstallPackageInfoGenerator.cxx

@@ -66,7 +66,7 @@ bool cmExportInstallPackageInfoGenerator::GenerateMainFile(std::ostream& os)
     }
   }
 
-  if (!this->CheckDefaultTargets()) {
+  if (!this->CheckPackage()) {
     return false;
   }
 

+ 59 - 0
Source/cmExportPackageInfoGenerator.cxx

@@ -16,6 +16,8 @@
 #include <cm3p/json/value.h>
 #include <cm3p/json/writer.h>
 
+#include "cmsys/RegularExpression.hxx"
+
 #include "cmArgumentParserTypes.h"
 #include "cmExportSet.h"
 #include "cmFindPackageStack.h"
@@ -88,6 +90,63 @@ void BuildArray(Json::Value& object, std::string const& property,
     }
   }
 }
+
+bool CheckSimpleVersion(std::string const& version)
+{
+  cmsys::RegularExpression regex("^[0-9]+([.][0-9]+)*([-+].*)?$");
+  return regex.find(version);
+}
+}
+
+bool cmExportPackageInfoGenerator::CheckVersion() const
+{
+  if (!this->PackageVersion.empty()) {
+    std::string const& schema = [&] {
+      if (this->PackageVersionSchema.empty()) {
+        return std::string{ "simple" };
+      }
+      return cmSystemTools::LowerCase(this->PackageVersionSchema);
+    }();
+    bool (*validator)(std::string const&) = nullptr;
+    bool result = true;
+
+    if (schema == "simple"_s) {
+      validator = &CheckSimpleVersion;
+    } else if (schema == "dpkg"_s || schema == "rpm"_s ||
+               schema == "pep440"_s) {
+      // TODO
+      // We don't validate these at this time. Eventually, we would like to do
+      // so, but will probably need to introduce a policy whether to treat
+      // invalid versions as an error.
+    } else if (schema != "custom"_s) {
+      this->IssueMessage(MessageType::AUTHOR_WARNING,
+                         cmStrCat("Package \""_s, this->GetPackageName(),
+                                  "\" uses unrecognized version schema \""_s,
+                                  this->PackageVersionSchema, "\"."_s));
+    }
+
+    if (validator) {
+      if (!(*validator)(this->PackageVersion)) {
+        this->ReportError(cmStrCat("Package \""_s, this->GetPackageName(),
+                                   "\" version \""_s, this->PackageVersion,
+                                   "\" does not conform to the \""_s, schema,
+                                   "\" schema."_s));
+        result = false;
+      }
+      if (!this->PackageVersionCompat.empty() &&
+          !(*validator)(this->PackageVersionCompat)) {
+        this->ReportError(
+          cmStrCat("Package \""_s, this->GetPackageName(),
+                   "\" compatibility version \""_s, this->PackageVersionCompat,
+                   "\" does not conform to the \""_s, schema, "\" schema."_s));
+        result = false;
+      }
+    }
+
+    return result;
+  }
+
+  return true;
 }
 
 bool cmExportPackageInfoGenerator::CheckDefaultTargets() const

+ 7 - 1
Source/cmExportPackageInfoGenerator.h

@@ -47,7 +47,10 @@ protected:
   // Methods to implement export file code generation.
   bool GenerateImportFile(std::ostream& os) override;
 
-  bool CheckDefaultTargets() const;
+  bool CheckPackage() const
+  {
+    return this->CheckVersion() && this->CheckDefaultTargets();
+  }
 
   Json::Value GeneratePackageInfo() const;
   Json::Value* GenerateImportTarget(Json::Value& components,
@@ -82,6 +85,9 @@ protected:
                         cmGeneratorTarget const* linkedTarget) override;
 
 private:
+  bool CheckVersion() const;
+  bool CheckDefaultTargets() const;
+
   void GenerateInterfaceLinkProperties(
     bool& result, Json::Value& component, cmGeneratorTarget const* target,
     ImportPropertyMap const& properties) const;

+ 20 - 3
Source/cmExportTryCompileFileGenerator.cxx

@@ -6,6 +6,7 @@
 #include <utility>
 
 #include <cm/memory>
+#include <cmext/string_view>
 
 #include "cmFileSet.h"
 #include "cmGenExContext.h"
@@ -16,6 +17,7 @@
 #include "cmList.h"
 #include "cmLocalGenerator.h"
 #include "cmMakefile.h"
+#include "cmMessageType.h"
 #include "cmOutputConverter.h"
 #include "cmStateTypes.h"
 #include "cmStringAlgorithms.h"
@@ -31,10 +33,25 @@ cmExportTryCompileFileGenerator::cmExportTryCompileFileGenerator(
   gg->CreateImportedGenerationObjects(mf, targets, this->Exports);
 }
 
-void cmExportTryCompileFileGenerator::ReportError(
-  std::string const& errorMessage) const
+void cmExportTryCompileFileGenerator::IssueMessage(
+  MessageType type, std::string const& message) const
 {
-  cmSystemTools::Error(errorMessage);
+  switch (type) {
+    case MessageType::FATAL_ERROR:
+    case MessageType::AUTHOR_ERROR:
+    case MessageType::INTERNAL_ERROR:
+    case MessageType::DEPRECATION_ERROR:
+      cmSystemTools::Error(message);
+      break;
+    case MessageType::WARNING:
+    case MessageType::AUTHOR_WARNING:
+    case MessageType::DEPRECATION_WARNING:
+      cmSystemTools::Message(cmStrCat("CMake Warning: "_s, message),
+                             "Warning");
+      break;
+    default:
+      cmSystemTools::Message(message);
+  }
 }
 
 bool cmExportTryCompileFileGenerator::GenerateMainFile(std::ostream& os)

+ 2 - 1
Source/cmExportTryCompileFileGenerator.h

@@ -30,7 +30,8 @@ protected:
   // Implement virtual methods from the superclass.
   void ComplainAboutDuplicateTarget(
     std::string const& /*targetName*/) const override {};
-  void ReportError(std::string const& errorMessage) const override;
+  void IssueMessage(MessageType type,
+                    std::string const& message) const override;
 
   bool GenerateMainFile(std::ostream& os) override;
 

+ 7 - 0
Tests/RunCMake/ExportPackageInfo/RunCMakeTest.cmake

@@ -4,6 +4,10 @@ include(RunCMake)
 run_cmake(ExperimentalGate)
 run_cmake(ExperimentalWarning)
 
+# Test version check author warning
+# TODO Move to be with other tests when experimental gate is removed.
+run_cmake(VersionCheckWarning)
+
 # Enable experimental feature and suppress warnings
 set(RunCMake_TEST_OPTIONS
   -Wno-dev
@@ -49,3 +53,6 @@ run_cmake(FileSetHeaders)
 run_cmake(DependencyVersionCMake)
 run_cmake(DependencyVersionCps)
 run_cmake(TransitiveSymbolicComponent)
+run_cmake(VersionCheck)
+# run_cmake(VersionCheckWarning)
+run_cmake(VersionCheckError)

+ 38 - 0
Tests/RunCMake/ExportPackageInfo/VersionCheck.cmake

@@ -0,0 +1,38 @@
+add_library(foo INTERFACE)
+install(TARGETS foo EXPORT foo DESTINATION .)
+
+# Try exporting a 'properly' simple version.
+export(EXPORT foo PACKAGE_INFO foo1 VERSION 1.2.3)
+
+# Try exporting a version with many components.
+export(EXPORT foo PACKAGE_INFO foo2 VERSION 1.21.23.33.37.42.9.0.12)
+
+# Try exporting a version with a label.
+export(EXPORT foo PACKAGE_INFO foo3 VERSION "1.2.3+git1234abcd")
+
+# Try exporting a version with a different label.
+export(EXPORT foo PACKAGE_INFO foo4 VERSION "1.2.3-0.example")
+
+# Try exporting with the schema explicitly specified.
+export(
+  EXPORT foo
+  PACKAGE_INFO foo5
+  VERSION "1.2.3-0.example"
+  VERSION_SCHEMA "simple"
+)
+
+# Try exporting with a custom-schema version.
+export(
+  EXPORT foo
+  PACKAGE_INFO foo6
+  VERSION "foo!test"
+  VERSION_SCHEMA "custom"
+)
+
+# Try exporting with a recognized but not-checked schema.
+export(
+  EXPORT foo
+  PACKAGE_INFO foo7
+  VERSION "invalid"
+  VERSION_SCHEMA "pep440"
+)

+ 1 - 0
Tests/RunCMake/ExportPackageInfo/VersionCheckError-result.txt

@@ -0,0 +1 @@
+1

+ 2 - 0
Tests/RunCMake/ExportPackageInfo/VersionCheckError-stderr.txt

@@ -0,0 +1,2 @@
+CMake Error in CMakeLists\.txt:
+  Package "foo" version "1.2.3rc1" does not conform to the "simple" schema\.

+ 5 - 0
Tests/RunCMake/ExportPackageInfo/VersionCheckError.cmake

@@ -0,0 +1,5 @@
+add_library(foo INTERFACE)
+install(TARGETS foo EXPORT foo DESTINATION .)
+
+# Try exporting a non-conforming version.
+export(EXPORT foo PACKAGE_INFO foo VERSION "1.2.3rc1")

+ 3 - 0
Tests/RunCMake/ExportPackageInfo/VersionCheckWarning-stderr.txt

@@ -0,0 +1,3 @@
+CMake Warning \(dev\) in CMakeLists\.txt:
+  Package "foo" uses unrecognized version schema "unrecognized"\.
+This warning is for project developers\.  Use -Wno-dev to suppress it\.

+ 15 - 0
Tests/RunCMake/ExportPackageInfo/VersionCheckWarning.cmake

@@ -0,0 +1,15 @@
+set(
+  CMAKE_EXPERIMENTAL_EXPORT_PACKAGE_INFO
+  "b80be207-778e-46ba-8080-b23bba22639e"
+)
+
+add_library(foo INTERFACE)
+install(TARGETS foo EXPORT foo DESTINATION .)
+
+# Try exporting with an unrecognized schema.
+export(
+  EXPORT foo
+  PACKAGE_INFO foo
+  VERSION "irrelevant"
+  VERSION_SCHEMA "unrecognized"
+)

+ 7 - 0
Tests/RunCMake/InstallPackageInfo/RunCMakeTest.cmake

@@ -4,6 +4,10 @@ include(RunCMake)
 run_cmake(ExperimentalGate)
 run_cmake(ExperimentalWarning)
 
+# Test version check author warning
+# TODO Move to be with other tests when experimental gate is removed.
+run_cmake(VersionCheckWarning)
+
 # Enable experimental feature and suppress warnings
 set(RunCMake_TEST_OPTIONS
   -Wno-dev
@@ -58,4 +62,7 @@ run_cmake(DependencyVersionCMake)
 run_cmake(DependencyVersionCps)
 run_cmake(TransitiveSymbolicComponent)
 run_cmake(InstallSymbolicComponent)
+run_cmake(VersionCheck)
+# run_cmake(VersionCheckWarning)
+run_cmake(VersionCheckError)
 run_cmake_install(Destination)

+ 38 - 0
Tests/RunCMake/InstallPackageInfo/VersionCheck.cmake

@@ -0,0 +1,38 @@
+add_library(foo INTERFACE)
+install(TARGETS foo EXPORT foo DESTINATION .)
+
+# Try exporting a 'properly' simple version.
+install(PACKAGE_INFO foo1 EXPORT foo VERSION 1.2.3)
+
+# Try exporting a version with many components.
+install(PACKAGE_INFO foo2 EXPORT foo VERSION 1.21.23.33.37.42.9.0.12)
+
+# Try exporting a version with a label.
+install(PACKAGE_INFO foo3 EXPORT foo VERSION "1.2.3+git1234abcd")
+
+# Try exporting a version with a different label.
+install(PACKAGE_INFO foo4 EXPORT foo VERSION "1.2.3-0.example")
+
+# Try exporting with the schema explicitly specified.
+install(
+  PACKAGE_INFO foo5
+  EXPORT foo
+  VERSION "1.2.3-0.example"
+  VERSION_SCHEMA "simple"
+)
+
+# Try exporting with a custom-schema version.
+install(
+  PACKAGE_INFO foo6
+  EXPORT foo
+  VERSION "foo!test"
+  VERSION_SCHEMA "custom"
+)
+
+# Try exporting with a recognized but not-checked schema.
+install(
+  PACKAGE_INFO foo7
+  EXPORT foo
+  VERSION "invalid"
+  VERSION_SCHEMA "pep440"
+)

+ 1 - 0
Tests/RunCMake/InstallPackageInfo/VersionCheckError-result.txt

@@ -0,0 +1 @@
+1

+ 2 - 0
Tests/RunCMake/InstallPackageInfo/VersionCheckError-stderr.txt

@@ -0,0 +1,2 @@
+CMake Error in CMakeLists\.txt:
+  Package "foo" version "1.2.3rc1" does not conform to the "simple" schema\.

+ 5 - 0
Tests/RunCMake/InstallPackageInfo/VersionCheckError.cmake

@@ -0,0 +1,5 @@
+add_library(foo INTERFACE)
+install(TARGETS foo EXPORT foo DESTINATION .)
+
+# Try exporting a non-conforming version.
+install(PACKAGE_INFO foo EXPORT foo VERSION "1.2.3rc1")

+ 3 - 0
Tests/RunCMake/InstallPackageInfo/VersionCheckWarning-stderr.txt

@@ -0,0 +1,3 @@
+CMake Warning \(dev\) in CMakeLists\.txt:
+  Package "foo" uses unrecognized version schema "unrecognized"\.
+This warning is for project developers\.  Use -Wno-dev to suppress it\.

+ 15 - 0
Tests/RunCMake/InstallPackageInfo/VersionCheckWarning.cmake

@@ -0,0 +1,15 @@
+set(
+  CMAKE_EXPERIMENTAL_EXPORT_PACKAGE_INFO
+  "b80be207-778e-46ba-8080-b23bba22639e"
+)
+
+add_library(foo INTERFACE)
+install(TARGETS foo EXPORT foo DESTINATION .)
+
+# Try exporting with an unrecognized schema.
+install(
+  PACKAGE_INFO foo
+  EXPORT foo
+  VERSION "irrelevant"
+  VERSION_SCHEMA "unrecognized"
+)