Browse Source

Merge topic 'more-cps-metadata'

755a24ccae CPS: Add export support for [default_]license
fba540daf6 project: Add SPDX_LICENSE argument
f0b419c473 Help: Tweak project DESCRIPTION documentation

Acked-by: Kitware Robot <[email protected]>
Tested-by: buildbot <[email protected]>
Merge-request: !10894
Brad King 8 months ago
parent
commit
6d30bda5b9
42 changed files with 277 additions and 44 deletions
  1. 3 1
      Help/command/export.rst
  2. 28 2
      Help/command/install.rst
  3. 32 7
      Help/command/project.rst
  4. 6 3
      Help/manual/cmake-variables.7.rst
  5. 3 3
      Help/prop_tgt/SPDX_LICENSE.rst
  6. 41 0
      Help/variable/CMAKE_PROJECT_SPDX_LICENSE.rst
  7. 11 0
      Help/variable/PROJECT-NAME_SPDX_LICENSE.rst
  8. 12 0
      Help/variable/PROJECT_SPDX_LICENSE.rst
  9. 4 1
      Source/cmExportPackageInfoGenerator.cxx
  10. 2 0
      Source/cmExportPackageInfoGenerator.h
  11. 7 0
      Source/cmPackageInfoArguments.cxx
  12. 5 0
      Source/cmPackageInfoArguments.h
  13. 5 2
      Source/cmProjectCommand.cxx
  14. 2 0
      Tests/RunCMake/ExportPackageInfo/Appendix-check.cmake
  15. 11 2
      Tests/RunCMake/ExportPackageInfo/Appendix.cmake
  16. 6 0
      Tests/RunCMake/ExportPackageInfo/BadArgs2-stderr.txt
  17. 8 6
      Tests/RunCMake/ExportPackageInfo/BadArgs2.cmake
  18. 12 0
      Tests/RunCMake/ExportPackageInfo/BadArgs4-stderr.txt
  19. 12 9
      Tests/RunCMake/ExportPackageInfo/BadArgs4.cmake
  20. 2 0
      Tests/RunCMake/ExportPackageInfo/Metadata-check.cmake
  21. 2 0
      Tests/RunCMake/ExportPackageInfo/Metadata.cmake
  22. 3 0
      Tests/RunCMake/ExportPackageInfo/ProjectMetadata-check.cmake
  23. 2 0
      Tests/RunCMake/ExportPackageInfo/ProjectMetadata.cmake
  24. 2 0
      Tests/RunCMake/InstallPackageInfo/Appendix-check.cmake
  25. 13 2
      Tests/RunCMake/InstallPackageInfo/Appendix.cmake
  26. 6 0
      Tests/RunCMake/InstallPackageInfo/BadArgs2-stderr.txt
  27. 8 6
      Tests/RunCMake/InstallPackageInfo/BadArgs2.cmake
  28. 2 0
      Tests/RunCMake/InstallPackageInfo/Metadata-check.cmake
  29. 2 0
      Tests/RunCMake/InstallPackageInfo/Metadata.cmake
  30. 3 0
      Tests/RunCMake/InstallPackageInfo/ProjectMetadata-check.cmake
  31. 2 0
      Tests/RunCMake/InstallPackageInfo/ProjectMetadata.cmake
  32. 1 0
      Tests/RunCMake/project/Omissions.cmake
  33. 1 0
      Tests/RunCMake/project/ProjectLicense-stdout.txt
  34. 5 0
      Tests/RunCMake/project/ProjectLicense.cmake
  35. 1 0
      Tests/RunCMake/project/ProjectLicense2-result.txt
  36. 1 0
      Tests/RunCMake/project/ProjectLicense2-stderr.txt
  37. 1 0
      Tests/RunCMake/project/ProjectLicense2.cmake
  38. 2 0
      Tests/RunCMake/project/ProjectLicenseNoArg-stderr.txt
  39. 1 0
      Tests/RunCMake/project/ProjectLicenseNoArg.cmake
  40. 2 0
      Tests/RunCMake/project/ProjectLicenseNoArg2-stderr.txt
  41. 1 0
      Tests/RunCMake/project/ProjectLicenseNoArg2.cmake
  42. 4 0
      Tests/RunCMake/project/RunCMakeTest.cmake

+ 3 - 1
Help/command/export.rst

@@ -141,7 +141,9 @@ Exporting Targets to the |CPS|
           [VERSION_SCHEMA <string>]]
           [VERSION_SCHEMA <string>]]
          [DEFAULT_TARGETS <target>...]
          [DEFAULT_TARGETS <target>...]
          [DEFAULT_CONFIGURATIONS <config>...]
          [DEFAULT_CONFIGURATIONS <config>...]
-         [DESCRIPTION <project-description-string>]
+         [LICENSE <license-string>]
+         [DEFAULT_LICENSE <license-string>]
+         [DESCRIPTION <description-string>]
          [HOMEPAGE_URL <url-string>])
          [HOMEPAGE_URL <url-string>])
 
 
 .. versionadded:: 4.1
 .. versionadded:: 4.1

+ 28 - 2
Help/command/install.rst

@@ -1001,7 +1001,9 @@ Signatures
              [VERSION_SCHEMA <string>]]
              [VERSION_SCHEMA <string>]]
             [DEFAULT_TARGETS <target>...]
             [DEFAULT_TARGETS <target>...]
             [DEFAULT_CONFIGURATIONS <config>...]
             [DEFAULT_CONFIGURATIONS <config>...]
-            [DESCRIPTION <project-description-string>]
+            [LICENSE <license-string>]
+            [DEFAULT_LICENSE <license-string>]
+            [DESCRIPTION <description-string>]
             [HOMEPAGE_URL <url-string>]
             [HOMEPAGE_URL <url-string>]
             [PERMISSIONS <permission>...]
             [PERMISSIONS <permission>...]
             [CONFIGURATIONS <config>...]
             [CONFIGURATIONS <config>...]
@@ -1059,7 +1061,25 @@ Signatures
     configurations exists.  If not specified, CMake will fall back to the
     configurations exists.  If not specified, CMake will fall back to the
     package's available configurations in an unspecified order.
     package's available configurations in an unspecified order.
 
 
-  ``DESCRIPTION <project-description-string>``
+  ``LICENSE <license-string>``
+    .. versionadded:: 4.2
+
+    A |SPDX|_ (SPDX) `License Expression`_ that describes the license(s) of the
+    project as a whole, including documentation, resources, or other materials
+    distributed with the project, in addition to software artifacts.  See the
+    SPDX `License List`_ for a list of commonly used licenses and their
+    identifiers.
+
+    The license of individual components is taken from the
+    :prop_tgt:`SPDX_LICENSE` property of their respective targets.
+
+  ``DEFAULT_LICENSE <license-string>``
+    .. versionadded:: 4.2
+
+    A |SPDX|_ (SPDX) `License Expression`_ that describes the license(s) of any
+    components which do not otherwise specify their license(s).
+
+  ``DESCRIPTION <description-string>``
     .. versionadded:: 4.1
     .. versionadded:: 4.1
 
 
     An informational description of the project.  It is recommended that this
     An informational description of the project.  It is recommended that this
@@ -1291,3 +1311,9 @@ and by CPack. You can also invoke this script manually with
 
 
 .. _cps-version_schema: https://cps-org.github.io/cps/schema.html#version-schema
 .. _cps-version_schema: https://cps-org.github.io/cps/schema.html#version-schema
 .. |cps-version_schema| replace:: ``version_schema``
 .. |cps-version_schema| replace:: ``version_schema``
+
+.. _SPDX: https://spdx.dev/
+.. |SPDX| replace:: System Package Data Exchange
+
+.. _License Expression: https://spdx.github.io/spdx-spec/v3.0.1/annexes/spdx-license-expressions/
+.. _License List: https://spdx.org/licenses/

+ 32 - 7
Help/command/project.rst

@@ -12,7 +12,8 @@ Synopsis
  project(<PROJECT-NAME>
  project(<PROJECT-NAME>
          [VERSION <major>[.<minor>[.<patch>[.<tweak>]]]]
          [VERSION <major>[.<minor>[.<patch>[.<tweak>]]]]
          [COMPAT_VERSION <major>[.<minor>[.<patch>[.<tweak>]]]]
          [COMPAT_VERSION <major>[.<minor>[.<patch>[.<tweak>]]]]
-         [DESCRIPTION <project-description-string>]
+         [SPDX_LICENSE <license-string>]
+         [DESCRIPTION <description-string>]
          [HOMEPAGE_URL <url-string>]
          [HOMEPAGE_URL <url-string>]
          [LANGUAGES <language-name>...])
          [LANGUAGES <language-name>...])
 
 
@@ -106,7 +107,30 @@ The options are:
     ``CMakeLists.txt``, then the compatibility version is also stored in the
     ``CMakeLists.txt``, then the compatibility version is also stored in the
     variable :variable:`CMAKE_PROJECT_COMPAT_VERSION`.
     variable :variable:`CMAKE_PROJECT_COMPAT_VERSION`.
 
 
-``DESCRIPTION <project-description-string>``
+``SPDX_LICENSE <license-string>``
+  .. versionadded:: 4.2
+
+  Optional.
+  Sets the variables
+
+  * :variable:`PROJECT_SPDX_LICENSE`,
+    :variable:`<PROJECT-NAME>_SPDX_LICENSE`
+
+  to ``<license-string>``, which shall be a |SPDX|_ (SPDX)
+  `License Expression`_ that describes the license(s) of the project as a
+  whole, including documentation, resources, or other materials distributed
+  with the project, in addition to software artifacts. See the SPDX
+  `License List`_ for a list of commonly used licenses and their identifiers.
+  See the :prop_tgt:`SPDX_LICENSE` property for specifying the license(s) on
+  individual software artifacts.
+
+.. _SPDX: https://spdx.dev/
+.. |SPDX| replace:: System Package Data Exchange
+
+.. _License Expression: https://spdx.github.io/spdx-spec/v3.0.1/annexes/spdx-license-expressions/
+.. _License List: https://spdx.org/licenses/
+
+``DESCRIPTION <description-string>``
   .. versionadded:: 3.9
   .. versionadded:: 3.9
 
 
   Optional.
   Optional.
@@ -114,7 +138,7 @@ The options are:
 
 
   * :variable:`PROJECT_DESCRIPTION`, :variable:`<PROJECT-NAME>_DESCRIPTION`
   * :variable:`PROJECT_DESCRIPTION`, :variable:`<PROJECT-NAME>_DESCRIPTION`
 
 
-  to ``<project-description-string>``.
+  to ``<description-string>``.
   It is recommended that this description is a relatively short string,
   It is recommended that this description is a relatively short string,
   usually no more than a few words.
   usually no more than a few words.
 
 
@@ -149,10 +173,11 @@ By default ``C`` and ``CXX`` are enabled if no language options are given.
 Specify language ``NONE``, or use the ``LANGUAGES`` keyword and list no languages,
 Specify language ``NONE``, or use the ``LANGUAGES`` keyword and list no languages,
 to skip enabling any languages.
 to skip enabling any languages.
 
 
-The variables set through the ``VERSION``, ``COMPAT_VERSION``, ``DESCRIPTION``
-and ``HOMEPAGE_URL`` options are intended for use as default values in package
-metadata and documentation. The :command:`export` and :command:`install`
-commands use these accordingly when generating |CPS| package descriptions.
+The variables set through the ``VERSION``, ``COMPAT_VERSION``,
+``SPDX_LICENSE``, ``DESCRIPTION`` and ``HOMEPAGE_URL`` options are
+intended for use as default values in package metadata and documentation.
+The :command:`export` and :command:`install` commands use these accordingly
+when generating |CPS| package descriptions.
 
 
 .. |CPS| replace:: Common Package Specification
 .. |CPS| replace:: Common Package Specification
 
 

+ 6 - 3
Help/manual/cmake-variables.7.rst

@@ -98,15 +98,16 @@ Variables that Provide Information
    /variable/CMAKE_OBJDUMP
    /variable/CMAKE_OBJDUMP
    /variable/CMAKE_PARENT_LIST_FILE
    /variable/CMAKE_PARENT_LIST_FILE
    /variable/CMAKE_PATCH_VERSION
    /variable/CMAKE_PATCH_VERSION
+   /variable/CMAKE_PROJECT_COMPAT_VERSION
    /variable/CMAKE_PROJECT_DESCRIPTION
    /variable/CMAKE_PROJECT_DESCRIPTION
    /variable/CMAKE_PROJECT_HOMEPAGE_URL
    /variable/CMAKE_PROJECT_HOMEPAGE_URL
    /variable/CMAKE_PROJECT_NAME
    /variable/CMAKE_PROJECT_NAME
+   /variable/CMAKE_PROJECT_SPDX_LICENSE
    /variable/CMAKE_PROJECT_VERSION
    /variable/CMAKE_PROJECT_VERSION
    /variable/CMAKE_PROJECT_VERSION_MAJOR
    /variable/CMAKE_PROJECT_VERSION_MAJOR
    /variable/CMAKE_PROJECT_VERSION_MINOR
    /variable/CMAKE_PROJECT_VERSION_MINOR
    /variable/CMAKE_PROJECT_VERSION_PATCH
    /variable/CMAKE_PROJECT_VERSION_PATCH
    /variable/CMAKE_PROJECT_VERSION_TWEAK
    /variable/CMAKE_PROJECT_VERSION_TWEAK
-   /variable/CMAKE_PROJECT_COMPAT_VERSION
    /variable/CMAKE_RANLIB
    /variable/CMAKE_RANLIB
    /variable/CMAKE_ROOT
    /variable/CMAKE_ROOT
    /variable/CMAKE_RULE_MESSAGES
    /variable/CMAKE_RULE_MESSAGES
@@ -154,28 +155,30 @@ Variables that Provide Information
    /variable/CMAKE_XCODE_BUILD_SYSTEM
    /variable/CMAKE_XCODE_BUILD_SYSTEM
    /variable/CMAKE_XCODE_PLATFORM_TOOLSET
    /variable/CMAKE_XCODE_PLATFORM_TOOLSET
    /variable/PROJECT-NAME_BINARY_DIR
    /variable/PROJECT-NAME_BINARY_DIR
+   /variable/PROJECT-NAME_COMPAT_VERSION
    /variable/PROJECT-NAME_DESCRIPTION
    /variable/PROJECT-NAME_DESCRIPTION
    /variable/PROJECT-NAME_HOMEPAGE_URL
    /variable/PROJECT-NAME_HOMEPAGE_URL
    /variable/PROJECT-NAME_IS_TOP_LEVEL
    /variable/PROJECT-NAME_IS_TOP_LEVEL
    /variable/PROJECT-NAME_SOURCE_DIR
    /variable/PROJECT-NAME_SOURCE_DIR
+   /variable/PROJECT-NAME_SPDX_LICENSE
    /variable/PROJECT-NAME_VERSION
    /variable/PROJECT-NAME_VERSION
    /variable/PROJECT-NAME_VERSION_MAJOR
    /variable/PROJECT-NAME_VERSION_MAJOR
    /variable/PROJECT-NAME_VERSION_MINOR
    /variable/PROJECT-NAME_VERSION_MINOR
    /variable/PROJECT-NAME_VERSION_PATCH
    /variable/PROJECT-NAME_VERSION_PATCH
    /variable/PROJECT-NAME_VERSION_TWEAK
    /variable/PROJECT-NAME_VERSION_TWEAK
-   /variable/PROJECT-NAME_COMPAT_VERSION
    /variable/PROJECT_BINARY_DIR
    /variable/PROJECT_BINARY_DIR
+   /variable/PROJECT_COMPAT_VERSION
    /variable/PROJECT_DESCRIPTION
    /variable/PROJECT_DESCRIPTION
    /variable/PROJECT_HOMEPAGE_URL
    /variable/PROJECT_HOMEPAGE_URL
    /variable/PROJECT_IS_TOP_LEVEL
    /variable/PROJECT_IS_TOP_LEVEL
    /variable/PROJECT_NAME
    /variable/PROJECT_NAME
    /variable/PROJECT_SOURCE_DIR
    /variable/PROJECT_SOURCE_DIR
+   /variable/PROJECT_SPDX_LICENSE
    /variable/PROJECT_VERSION
    /variable/PROJECT_VERSION
    /variable/PROJECT_VERSION_MAJOR
    /variable/PROJECT_VERSION_MAJOR
    /variable/PROJECT_VERSION_MINOR
    /variable/PROJECT_VERSION_MINOR
    /variable/PROJECT_VERSION_PATCH
    /variable/PROJECT_VERSION_PATCH
    /variable/PROJECT_VERSION_TWEAK
    /variable/PROJECT_VERSION_TWEAK
-   /variable/PROJECT_COMPAT_VERSION
 
 
 Variables that Change Behavior
 Variables that Change Behavior
 ==============================
 ==============================

+ 3 - 3
Help/prop_tgt/SPDX_LICENSE.rst

@@ -3,9 +3,9 @@ SPDX_LICENSE
 
 
 .. versionadded:: 4.1
 .. versionadded:: 4.1
 
 
-Specify the license of a target using a |SPDX|_ (SPDX) `License Expression`_.
-See the SPDX `License List`_ for a list of commonly used licenses and their
-identifiers.
+Specify the license(s) of a target using a |SPDX|_ (SPDX)
+`License Expression`_. See the SPDX `License List`_ for a list of commonly used
+licenses and their identifiers.
 
 
 .. _SPDX: https://spdx.dev/
 .. _SPDX: https://spdx.dev/
 .. |SPDX| replace:: System Package Data Exchange
 .. |SPDX| replace:: System Package Data Exchange

+ 41 - 0
Help/variable/CMAKE_PROJECT_SPDX_LICENSE.rst

@@ -0,0 +1,41 @@
+CMAKE_PROJECT_SPDX_LICENSE
+--------------------------
+
+.. versionadded:: 4.2
+
+.. note::
+
+  Experimental. Gated by ``CMAKE_EXPERIMENTAL_EXPORT_PACKAGE_INFO``.
+
+The license(s) of the top level project.
+
+This variable holds the license expression of the project as specified in the
+top level CMakeLists.txt file by a :command:`project` command.  In the event
+that the top level CMakeLists.txt contains multiple :command:`project` calls,
+the most recently called one from that top level CMakeLists.txt will determine
+the value that ``CMAKE_PROJECT_SPDX_LICENSE`` contains.  For example, consider
+the following top level CMakeLists.txt:
+
+.. code-block:: cmake
+
+  cmake_minimum_required(VERSION 4.2)
+  project(First SPDX_LICENSE "BSD-3-Clause")
+  project(Second SPDX_LICENSE "BSD-3-Clause AND CC-BY-SA-4.0")
+  add_subdirectory(sub)
+  project(Third SPDX_LICENSE "BSD-3-Clause AND CC0-1.0")
+
+And ``sub/CMakeLists.txt`` with the following contents:
+
+.. code-block:: cmake
+
+  project(SubProj SPDX_LICENSE Apache-2.0)
+  message("CMAKE_PROJECT_SPDX_LICENSE = ${CMAKE_PROJECT_SPDX_LICENSE}")
+
+The most recently seen :command:`project` command from the top level
+CMakeLists.txt would be ``project(Second ...)``, so this will print::
+
+  CMAKE_PROJECT_SPDX_LICENSE = BSD-3-Clause AND CC-BY-SA-4.0
+
+To obtain the version from the most recent call to :command:`project` in
+the current directory scope or above, see the :variable:`PROJECT_SPDX_LICENSE`
+variable.

+ 11 - 0
Help/variable/PROJECT-NAME_SPDX_LICENSE.rst

@@ -0,0 +1,11 @@
+<PROJECT-NAME>_SPDX_LICENSE
+---------------------------
+
+.. versionadded:: 4.2
+
+.. note::
+
+  Experimental. Gated by ``CMAKE_EXPERIMENTAL_EXPORT_PACKAGE_INFO``.
+
+Value given to the ``SPDX_LICENSE`` option of the most recent call to the
+:command:`project` command with project name ``<PROJECT-NAME>``, if any.

+ 12 - 0
Help/variable/PROJECT_SPDX_LICENSE.rst

@@ -0,0 +1,12 @@
+PROJECT_SPDX_LICENSE
+--------------------
+
+.. versionadded:: 4.2
+
+.. note::
+
+  Experimental. Gated by ``CMAKE_EXPERIMENTAL_EXPORT_PACKAGE_INFO``.
+
+Value given to the ``SPDX_LICENSE`` option of the most recent call to the
+:command:`project` command, if any. To obtain the compatibility version of the
+top level project, see the :variable:`CMAKE_PROJECT_SPDX_LICENSE` variable.

+ 4 - 1
Source/cmExportPackageInfoGenerator.cxx

@@ -39,6 +39,8 @@ cmExportPackageInfoGenerator::cmExportPackageInfoGenerator(
   , PackageVersionSchema(std::move(arguments.VersionSchema))
   , PackageVersionSchema(std::move(arguments.VersionSchema))
   , PackageDescription(std::move(arguments.Description))
   , PackageDescription(std::move(arguments.Description))
   , PackageWebsite(std::move(arguments.Website))
   , PackageWebsite(std::move(arguments.Website))
+  , PackageLicense(std::move(arguments.License))
+  , DefaultLicense(std::move(arguments.DefaultLicense))
   , DefaultTargets(std::move(arguments.DefaultTargets))
   , DefaultTargets(std::move(arguments.DefaultTargets))
   , DefaultConfigurations(std::move(arguments.DefaultConfigs))
   , DefaultConfigurations(std::move(arguments.DefaultConfigs))
 {
 {
@@ -127,7 +129,8 @@ Json::Value cmExportPackageInfoGenerator::GeneratePackageInfo() const
 
 
   SetProperty(package, "description", this->PackageDescription);
   SetProperty(package, "description", this->PackageDescription);
   SetProperty(package, "website", this->PackageWebsite);
   SetProperty(package, "website", this->PackageWebsite);
-  // TODO: license
+  SetProperty(package, "license", this->PackageLicense);
+  SetProperty(package, "default_license", this->DefaultLicense);
 
 
   return package;
   return package;
 }
 }

+ 2 - 0
Source/cmExportPackageInfoGenerator.h

@@ -110,6 +110,8 @@ private:
   std::string const PackageVersionSchema;
   std::string const PackageVersionSchema;
   std::string const PackageDescription;
   std::string const PackageDescription;
   std::string const PackageWebsite;
   std::string const PackageWebsite;
+  std::string const PackageLicense;
+  std::string const DefaultLicense;
   std::vector<std::string> DefaultTargets;
   std::vector<std::string> DefaultTargets;
   std::vector<std::string> DefaultConfigurations;
   std::vector<std::string> DefaultConfigurations;
 
 

+ 7 - 0
Source/cmPackageInfoArguments.cxx

@@ -60,6 +60,8 @@ bool cmPackageInfoArguments::Check(cmExecutionStatus& status,
     ENFORCE_REQUIRES("PACKAGE_INFO", this->LowerCase, "LOWER_CASE_FILE");
     ENFORCE_REQUIRES("PACKAGE_INFO", this->LowerCase, "LOWER_CASE_FILE");
     ENFORCE_REQUIRES("PACKAGE_INFO", this->Appendix, "APPENDIX");
     ENFORCE_REQUIRES("PACKAGE_INFO", this->Appendix, "APPENDIX");
     ENFORCE_REQUIRES("PACKAGE_INFO", this->Version, "VERSION");
     ENFORCE_REQUIRES("PACKAGE_INFO", this->Version, "VERSION");
+    ENFORCE_REQUIRES("PACKAGE_INFO", this->License, "LICENSE");
+    ENFORCE_REQUIRES("PACKAGE_INFO", this->DefaultLicense, "DEFAULT_LICENSE");
     ENFORCE_REQUIRES("PACKAGE_INFO", this->Description, "DESCRIPTION");
     ENFORCE_REQUIRES("PACKAGE_INFO", this->Description, "DESCRIPTION");
     ENFORCE_REQUIRES("PACKAGE_INFO", this->Website, "HOMEPAGE_URL");
     ENFORCE_REQUIRES("PACKAGE_INFO", this->Website, "HOMEPAGE_URL");
     ENFORCE_REQUIRES("PACKAGE_INFO", this->DefaultTargets, "DEFAULT_TARGETS");
     ENFORCE_REQUIRES("PACKAGE_INFO", this->DefaultTargets, "DEFAULT_TARGETS");
@@ -73,6 +75,7 @@ bool cmPackageInfoArguments::Check(cmExecutionStatus& status,
   // Check for incompatible options.
   // Check for incompatible options.
   if (!this->Appendix.empty()) {
   if (!this->Appendix.empty()) {
     ENFORCE_EXCLUSIVE("APPENDIX", this->Version, "VERSION");
     ENFORCE_EXCLUSIVE("APPENDIX", this->Version, "VERSION");
+    ENFORCE_EXCLUSIVE("APPENDIX", this->License, "LICENSE");
     ENFORCE_EXCLUSIVE("APPENDIX", this->Description, "DESCRIPTION");
     ENFORCE_EXCLUSIVE("APPENDIX", this->Description, "DESCRIPTION");
     ENFORCE_EXCLUSIVE("APPENDIX", this->Website, "HOMEPAGE_URL");
     ENFORCE_EXCLUSIVE("APPENDIX", this->Website, "HOMEPAGE_URL");
     ENFORCE_EXCLUSIVE("APPENDIX", this->DefaultTargets, "DEFAULT_TARGETS");
     ENFORCE_EXCLUSIVE("APPENDIX", this->DefaultTargets, "DEFAULT_TARGETS");
@@ -136,6 +139,10 @@ bool cmPackageInfoArguments::SetMetadataFromProject(cmExecutionStatus& status)
     }
     }
   }
   }
 
 
+  if (this->License.empty()) {
+    mapProjectValue(this->License, "SPDX_LICENSE"_s);
+  }
+
   if (this->Description.empty()) {
   if (this->Description.empty()) {
     mapProjectValue(this->Description, "DESCRIPTION"_s);
     mapProjectValue(this->Description, "DESCRIPTION"_s);
   }
   }

+ 5 - 0
Source/cmPackageInfoArguments.h

@@ -56,6 +56,8 @@ public:
   ArgumentParser::NonEmpty<std::string> Version;
   ArgumentParser::NonEmpty<std::string> Version;
   ArgumentParser::NonEmpty<std::string> VersionCompat;
   ArgumentParser::NonEmpty<std::string> VersionCompat;
   ArgumentParser::NonEmpty<std::string> VersionSchema;
   ArgumentParser::NonEmpty<std::string> VersionSchema;
+  ArgumentParser::NonEmpty<std::string> License;
+  ArgumentParser::NonEmpty<std::string> DefaultLicense;
   ArgumentParser::NonEmpty<std::string> Description;
   ArgumentParser::NonEmpty<std::string> Description;
   ArgumentParser::NonEmpty<std::string> Website;
   ArgumentParser::NonEmpty<std::string> Website;
   ArgumentParser::NonEmpty<std::vector<std::string>> DefaultTargets;
   ArgumentParser::NonEmpty<std::vector<std::string>> DefaultTargets;
@@ -84,6 +86,9 @@ private:
          &cmPackageInfoArguments::DefaultTargets);
          &cmPackageInfoArguments::DefaultTargets);
     Bind(self, parser, "DEFAULT_CONFIGURATIONS"_s,
     Bind(self, parser, "DEFAULT_CONFIGURATIONS"_s,
          &cmPackageInfoArguments::DefaultConfigs);
          &cmPackageInfoArguments::DefaultConfigs);
+    Bind(self, parser, "LICENSE"_s, &cmPackageInfoArguments::License);
+    Bind(self, parser, "DEFAULT_LICENSE"_s,
+         &cmPackageInfoArguments::DefaultLicense);
     Bind(self, parser, "DESCRIPTION"_s, &cmPackageInfoArguments::Description);
     Bind(self, parser, "DESCRIPTION"_s, &cmPackageInfoArguments::Description);
     Bind(self, parser, "HOMEPAGE_URL"_s, &cmPackageInfoArguments::Website);
     Bind(self, parser, "HOMEPAGE_URL"_s, &cmPackageInfoArguments::Website);
 
 

+ 5 - 2
Source/cmProjectCommand.cxx

@@ -38,6 +38,7 @@ struct ProjectArguments : ArgumentParser::ParseResult
   cm::optional<std::string> ProjectName;
   cm::optional<std::string> ProjectName;
   cm::optional<std::string> Version;
   cm::optional<std::string> Version;
   cm::optional<std::string> CompatVersion;
   cm::optional<std::string> CompatVersion;
+  cm::optional<std::string> License;
   cm::optional<std::string> Description;
   cm::optional<std::string> Description;
   cm::optional<std::string> HomepageURL;
   cm::optional<std::string> HomepageURL;
   cm::optional<ArgumentParser::MaybeEmpty<std::vector<std::string>>> Languages;
   cm::optional<ArgumentParser::MaybeEmpty<std::vector<std::string>>> Languages;
@@ -73,11 +74,12 @@ bool cmProjectCommand(std::vector<std::string> const& args,
     .Bind("LANGUAGES"_s, prArgs.Languages);
     .Bind("LANGUAGES"_s, prArgs.Languages);
 
 
   cmMakefile& mf = status.GetMakefile();
   cmMakefile& mf = status.GetMakefile();
-  bool enableCompatVersion = cmExperimental::HasSupportEnabled(
+  bool enablePackageInfo = cmExperimental::HasSupportEnabled(
     mf, cmExperimental::Feature::ExportPackageInfo);
     mf, cmExperimental::Feature::ExportPackageInfo);
 
 
-  if (enableCompatVersion) {
+  if (enablePackageInfo) {
     parser.Bind("COMPAT_VERSION"_s, prArgs.CompatVersion);
     parser.Bind("COMPAT_VERSION"_s, prArgs.CompatVersion);
+    parser.Bind("SPDX_LICENSE"_s, prArgs.License);
   }
   }
 
 
   parser.Parse(args, &unparsedArgs, 0);
   parser.Parse(args, &unparsedArgs, 0);
@@ -263,6 +265,7 @@ bool cmProjectCommand(std::vector<std::string> const& args,
   createVariables("VERSION_PATCH"_s, version_components[2]);
   createVariables("VERSION_PATCH"_s, version_components[2]);
   createVariables("VERSION_TWEAK"_s, version_components[3]);
   createVariables("VERSION_TWEAK"_s, version_components[3]);
   createVariables("COMPAT_VERSION"_s, prArgs.CompatVersion.value_or(""));
   createVariables("COMPAT_VERSION"_s, prArgs.CompatVersion.value_or(""));
+  createVariables("SPDX_LICENSE"_s, prArgs.License.value_or(""));
   createVariables("DESCRIPTION"_s, prArgs.Description.value_or(""));
   createVariables("DESCRIPTION"_s, prArgs.Description.value_or(""));
   createVariables("HOMEPAGE_URL"_s, prArgs.HomepageURL.value_or(""));
   createVariables("HOMEPAGE_URL"_s, prArgs.HomepageURL.value_or(""));
 
 

+ 2 - 0
Tests/RunCMake/ExportPackageInfo/Appendix-check.cmake

@@ -5,11 +5,13 @@ set(out_dir "${RunCMake_BINARY_DIR}/Appendix-build")
 file(READ "${out_dir}/foo.cps" content)
 file(READ "${out_dir}/foo.cps" content)
 expect_value("${content}" "foo" "name")
 expect_value("${content}" "foo" "name")
 expect_value("${content}" "interface" "components" "mammal" "type")
 expect_value("${content}" "interface" "components" "mammal" "type")
+expect_value("${content}" "LGPL-3.0-or-later" "default_license")
 expect_value("${content}" "1.0" "version")
 expect_value("${content}" "1.0" "version")
 
 
 file(READ "${out_dir}/foo-dog.cps" content)
 file(READ "${out_dir}/foo-dog.cps" content)
 expect_value("${content}" "foo" "name")
 expect_value("${content}" "foo" "name")
 expect_value("${content}" "interface" "components" "canine" "type")
 expect_value("${content}" "interface" "components" "canine" "type")
+expect_value("${content}" "GPL-3.0-or-later" "default_license")
 expect_missing("${content}" "version")
 expect_missing("${content}" "version")
 
 
 expect_array("${content}" 1 "components" "canine" "requires")
 expect_array("${content}" 1 "components" "canine" "requires")

+ 11 - 2
Tests/RunCMake/ExportPackageInfo/Appendix.cmake

@@ -5,5 +5,14 @@ target_link_libraries(canine INTERFACE mammal)
 install(TARGETS mammal EXPORT mammal DESTINATION .)
 install(TARGETS mammal EXPORT mammal DESTINATION .)
 install(TARGETS canine EXPORT canine DESTINATION .)
 install(TARGETS canine EXPORT canine DESTINATION .)
 
 
-export(EXPORT mammal PACKAGE_INFO foo VERSION 1.0)
-export(EXPORT canine PACKAGE_INFO foo APPENDIX dog)
+export(
+  EXPORT mammal
+  PACKAGE_INFO foo
+  VERSION 1.0
+  DEFAULT_LICENSE "LGPL-3.0-or-later")
+
+export(
+  EXPORT canine
+  PACKAGE_INFO foo
+  APPENDIX dog
+  DEFAULT_LICENSE "GPL-3.0-or-later")

+ 6 - 0
Tests/RunCMake/ExportPackageInfo/BadArgs2-stderr.txt

@@ -4,6 +4,12 @@ Call Stack \(most recent call first\):
   CMakeLists\.txt:3 \(include\)
   CMakeLists\.txt:3 \(include\)
 
 
 
 
+CMake Error at BadArgs2\.cmake:[0-9]+ \(export\):
+  export APPENDIX and LICENSE are mutually exclusive\.
+Call Stack \(most recent call first\):
+  CMakeLists\.txt:3 \(include\)
+
+
 CMake Error at BadArgs2\.cmake:[0-9]+ \(export\):
 CMake Error at BadArgs2\.cmake:[0-9]+ \(export\):
   export APPENDIX and DESCRIPTION are mutually exclusive\.
   export APPENDIX and DESCRIPTION are mutually exclusive\.
 Call Stack \(most recent call first\):
 Call Stack \(most recent call first\):

+ 8 - 6
Tests/RunCMake/ExportPackageInfo/BadArgs2.cmake

@@ -1,8 +1,10 @@
 add_library(foo INTERFACE)
 add_library(foo INTERFACE)
 install(TARGETS foo EXPORT foo DESTINATION .)
 install(TARGETS foo EXPORT foo DESTINATION .)
-export(EXPORT foo PACKAGE_INFO foo APPENDIX test VERSION 1.0)
-export(EXPORT foo PACKAGE_INFO foo APPENDIX test DESCRIPTION "Test")
-export(EXPORT foo PACKAGE_INFO foo APPENDIX test HOMEPAGE_URL "example.com")
-export(EXPORT foo PACKAGE_INFO foo APPENDIX test DEFAULT_TARGETS foo)
-export(EXPORT foo PACKAGE_INFO foo APPENDIX test DEFAULT_CONFIGURATIONS Release)
-export(EXPORT foo PACKAGE_INFO foo APPENDIX test PROJECT foo)
+set(args EXPORT foo PACKAGE_INFO foo APPENDIX test)
+export(${args} VERSION 1.0)
+export(${args} LICENSE "BSD-3-Clause AND CC-BY-SA-4.0")
+export(${args} DESCRIPTION "Test")
+export(${args} HOMEPAGE_URL "example.com")
+export(${args} DEFAULT_TARGETS foo)
+export(${args} DEFAULT_CONFIGURATIONS Release)
+export(${args} PROJECT foo)

+ 12 - 0
Tests/RunCMake/ExportPackageInfo/BadArgs4-stderr.txt

@@ -16,6 +16,18 @@ Call Stack \(most recent call first\):
   CMakeLists\.txt:3 \(include\)
   CMakeLists\.txt:3 \(include\)
 
 
 
 
+CMake Error at BadArgs4\.cmake:[0-9]+ \(export\):
+  export LICENSE requires PACKAGE_INFO\.
+Call Stack \(most recent call first\):
+  CMakeLists\.txt:3 \(include\)
+
+
+CMake Error at BadArgs4\.cmake:[0-9]+ \(export\):
+  export DEFAULT_LICENSE requires PACKAGE_INFO\.
+Call Stack \(most recent call first\):
+  CMakeLists\.txt:3 \(include\)
+
+
 CMake Error at BadArgs4\.cmake:[0-9]+ \(export\):
 CMake Error at BadArgs4\.cmake:[0-9]+ \(export\):
   export DESCRIPTION requires PACKAGE_INFO\.
   export DESCRIPTION requires PACKAGE_INFO\.
 Call Stack \(most recent call first\):
 Call Stack \(most recent call first\):

+ 12 - 9
Tests/RunCMake/ExportPackageInfo/BadArgs4.cmake

@@ -1,11 +1,14 @@
 add_library(foo INTERFACE)
 add_library(foo INTERFACE)
 install(TARGETS foo EXPORT foo DESTINATION .)
 install(TARGETS foo EXPORT foo DESTINATION .)
-export(EXPORT foo LOWER_CASE_FILE)
-export(EXPORT foo APPENDIX test)
-export(EXPORT foo VERSION 1.0)
-export(EXPORT foo DESCRIPTION "Test")
-export(EXPORT foo HOMEPAGE_URL "example.com")
-export(EXPORT foo DEFAULT_TARGETS foo)
-export(EXPORT foo DEFAULT_CONFIGURATIONS Release)
-export(EXPORT foo PROJECT foo)
-export(EXPORT foo NO_PROJECT_METADATA)
+set(args EXPORT foo)
+export(${args} LOWER_CASE_FILE)
+export(${args} APPENDIX test)
+export(${args} VERSION 1.0)
+export(${args} LICENSE "BSD-3-Clause AND CC-BY-SA-4.0")
+export(${args} DEFAULT_LICENSE "BSD-3-Clause")
+export(${args} DESCRIPTION "Test")
+export(${args} HOMEPAGE_URL "example.com")
+export(${args} DEFAULT_TARGETS foo)
+export(${args} DEFAULT_CONFIGURATIONS Release)
+export(${args} PROJECT foo)
+export(${args} NO_PROJECT_METADATA)

+ 2 - 0
Tests/RunCMake/ExportPackageInfo/Metadata-check.cmake

@@ -15,5 +15,7 @@ expect_array("${content}" 2 "configurations")
 expect_value("${content}" "release" "configurations" 0)
 expect_value("${content}" "release" "configurations" 0)
 expect_value("${content}" "debug" "configurations" 1)
 expect_value("${content}" "debug" "configurations" 1)
 
 
+expect_value("${content}" "BSD-3-Clause" "default_license")
+expect_value("${content}" "BSD-3-Clause AND CC-BY-SA-4.0" "license")
 expect_value("${content}" "Sample package" "description")
 expect_value("${content}" "Sample package" "description")
 expect_value("${content}" "https://www.example.com/package/foo" "website")
 expect_value("${content}" "https://www.example.com/package/foo" "website")

+ 2 - 0
Tests/RunCMake/ExportPackageInfo/Metadata.cmake

@@ -8,6 +8,8 @@ export(
   COMPAT_VERSION 1.2.0
   COMPAT_VERSION 1.2.0
   DEFAULT_TARGETS foo
   DEFAULT_TARGETS foo
   DEFAULT_CONFIGURATIONS release debug
   DEFAULT_CONFIGURATIONS release debug
+  LICENSE "BSD-3-Clause AND CC-BY-SA-4.0"
+  DEFAULT_LICENSE "BSD-3-Clause"
   DESCRIPTION "Sample package"
   DESCRIPTION "Sample package"
   HOMEPAGE_URL "https://www.example.com/package/foo"
   HOMEPAGE_URL "https://www.example.com/package/foo"
   )
   )

+ 3 - 0
Tests/RunCMake/ExportPackageInfo/ProjectMetadata-check.cmake

@@ -6,6 +6,7 @@ file(READ "${out_dir}/foo.cps" content)
 expect_value("${content}" "foo" "name")
 expect_value("${content}" "foo" "name")
 expect_value("${content}" "1.2.3" "version")
 expect_value("${content}" "1.2.3" "version")
 expect_value("${content}" "1.1.0" "compat_version")
 expect_value("${content}" "1.1.0" "compat_version")
+expect_value("${content}" "BSD-3-Clause" "license")
 expect_value("${content}" "Sample package" "description")
 expect_value("${content}" "Sample package" "description")
 expect_value("${content}" "https://www.example.com/package/foo" "website")
 expect_value("${content}" "https://www.example.com/package/foo" "website")
 
 
@@ -13,6 +14,7 @@ file(READ "${out_dir}/test1.cps" content)
 expect_value("${content}" "test1" "name")
 expect_value("${content}" "test1" "name")
 expect_value("${content}" "1.2.3" "version")
 expect_value("${content}" "1.2.3" "version")
 expect_value("${content}" "1.1.0" "compat_version")
 expect_value("${content}" "1.1.0" "compat_version")
+expect_value("${content}" "BSD-3-Clause" "license")
 expect_value("${content}" "Sample package" "description")
 expect_value("${content}" "Sample package" "description")
 expect_value("${content}" "https://www.example.com/package/foo" "website")
 expect_value("${content}" "https://www.example.com/package/foo" "website")
 
 
@@ -20,5 +22,6 @@ file(READ "${out_dir}/test2.cps" content)
 expect_value("${content}" "test2" "name")
 expect_value("${content}" "test2" "name")
 expect_value("${content}" "1.4.7" "version")
 expect_value("${content}" "1.4.7" "version")
 expect_missing("${content}" "compat_version")
 expect_missing("${content}" "compat_version")
+expect_value("${content}" "Apache-2.0" "license")
 expect_value("${content}" "Don't inherit" "description")
 expect_value("${content}" "Don't inherit" "description")
 expect_value("${content}" "https://www.example.com/package/bar" "website")
 expect_value("${content}" "https://www.example.com/package/bar" "website")

+ 2 - 0
Tests/RunCMake/ExportPackageInfo/ProjectMetadata.cmake

@@ -1,6 +1,7 @@
 project(foo
 project(foo
   VERSION 1.2.3
   VERSION 1.2.3
   COMPAT_VERSION 1.1.0
   COMPAT_VERSION 1.1.0
+  SPDX_LICENSE "BSD-3-Clause"
   DESCRIPTION "Sample package"
   DESCRIPTION "Sample package"
   HOMEPAGE_URL "https://www.example.com/package/foo"
   HOMEPAGE_URL "https://www.example.com/package/foo"
   )
   )
@@ -27,6 +28,7 @@ export(
   PROJECT foo
   PROJECT foo
   PACKAGE_INFO test2
   PACKAGE_INFO test2
   VERSION 1.4.7
   VERSION 1.4.7
+  LICENSE "Apache-2.0"
   DESCRIPTION "Don't inherit"
   DESCRIPTION "Don't inherit"
   HOMEPAGE_URL "https://www.example.com/package/bar"
   HOMEPAGE_URL "https://www.example.com/package/bar"
   )
   )

+ 2 - 0
Tests/RunCMake/InstallPackageInfo/Appendix-check.cmake

@@ -5,11 +5,13 @@ set(out_dir "${RunCMake_BINARY_DIR}/Appendix-build/CMakeFiles/Export/510c5684a4a
 file(READ "${out_dir}/foo.cps" content)
 file(READ "${out_dir}/foo.cps" content)
 expect_value("${content}" "foo" "name")
 expect_value("${content}" "foo" "name")
 expect_value("${content}" "interface" "components" "mammal" "type")
 expect_value("${content}" "interface" "components" "mammal" "type")
+expect_value("${content}" "LGPL-3.0-or-later" "default_license")
 expect_value("${content}" "1.0" "version")
 expect_value("${content}" "1.0" "version")
 
 
 file(READ "${out_dir}/foo-dog.cps" content)
 file(READ "${out_dir}/foo-dog.cps" content)
 expect_value("${content}" "foo" "name")
 expect_value("${content}" "foo" "name")
 expect_value("${content}" "interface" "components" "canine" "type")
 expect_value("${content}" "interface" "components" "canine" "type")
+expect_value("${content}" "GPL-3.0-or-later" "default_license")
 expect_missing("${content}" "version")
 expect_missing("${content}" "version")
 
 
 expect_array("${content}" 1 "components" "canine" "requires")
 expect_array("${content}" 1 "components" "canine" "requires")

+ 13 - 2
Tests/RunCMake/InstallPackageInfo/Appendix.cmake

@@ -5,5 +5,16 @@ target_link_libraries(canine INTERFACE mammal)
 install(TARGETS mammal EXPORT mammal DESTINATION .)
 install(TARGETS mammal EXPORT mammal DESTINATION .)
 install(TARGETS canine EXPORT canine DESTINATION .)
 install(TARGETS canine EXPORT canine DESTINATION .)
 
 
-install(PACKAGE_INFO foo DESTINATION cps EXPORT mammal VERSION 1.0)
-install(PACKAGE_INFO foo DESTINATION cps EXPORT canine APPENDIX dog)
+install(
+  PACKAGE_INFO foo
+  DESTINATION cps
+  EXPORT mammal
+  VERSION 1.0
+  DEFAULT_LICENSE "LGPL-3.0-or-later")
+
+install(
+  PACKAGE_INFO foo
+  DESTINATION cps
+  EXPORT canine
+  APPENDIX dog
+  DEFAULT_LICENSE "GPL-3.0-or-later")

+ 6 - 0
Tests/RunCMake/InstallPackageInfo/BadArgs2-stderr.txt

@@ -4,6 +4,12 @@ Call Stack \(most recent call first\):
   CMakeLists\.txt:3 \(include\)
   CMakeLists\.txt:3 \(include\)
 
 
 
 
+CMake Error at BadArgs2.cmake:[0-9]+ \(install\):
+  install APPENDIX and LICENSE are mutually exclusive.
+Call Stack \(most recent call first\):
+  CMakeLists\.txt:3 \(include\)
+
+
 CMake Error at BadArgs2.cmake:[0-9]+ \(install\):
 CMake Error at BadArgs2.cmake:[0-9]+ \(install\):
   install APPENDIX and DESCRIPTION are mutually exclusive.
   install APPENDIX and DESCRIPTION are mutually exclusive.
 Call Stack \(most recent call first\):
 Call Stack \(most recent call first\):

+ 8 - 6
Tests/RunCMake/InstallPackageInfo/BadArgs2.cmake

@@ -1,8 +1,10 @@
 add_library(foo INTERFACE)
 add_library(foo INTERFACE)
 install(TARGETS foo EXPORT foo DESTINATION .)
 install(TARGETS foo EXPORT foo DESTINATION .)
-install(PACKAGE_INFO test EXPORT foo APPENDIX test VERSION 1.0)
-install(PACKAGE_INFO test EXPORT foo APPENDIX test DESCRIPTION "Test")
-install(PACKAGE_INFO test EXPORT foo APPENDIX test HOMEPAGE_URL "example.com")
-install(PACKAGE_INFO test EXPORT foo APPENDIX test DEFAULT_TARGETS foo)
-install(PACKAGE_INFO test EXPORT foo APPENDIX test DEFAULT_CONFIGURATIONS test)
-install(PACKAGE_INFO test EXPORT foo APPENDIX test PROJECT foo)
+set(args PACKAGE_INFO test EXPORT foo APPENDIX test)
+install(${args} VERSION 1.0)
+install(${args} LICENSE "BSD-3-Clause AND CC-BY-SA-4.0")
+install(${args} DESCRIPTION "Test")
+install(${args} HOMEPAGE_URL "example.com")
+install(${args} DEFAULT_TARGETS foo)
+install(${args} DEFAULT_CONFIGURATIONS test)
+install(${args} PROJECT foo)

+ 2 - 0
Tests/RunCMake/InstallPackageInfo/Metadata-check.cmake

@@ -15,5 +15,7 @@ expect_array("${content}" 2 "configurations")
 expect_value("${content}" "release" "configurations" 0)
 expect_value("${content}" "release" "configurations" 0)
 expect_value("${content}" "debug" "configurations" 1)
 expect_value("${content}" "debug" "configurations" 1)
 
 
+expect_value("${content}" "BSD-3-Clause" "default_license")
+expect_value("${content}" "BSD-3-Clause AND CC-BY-SA-4.0" "license")
 expect_value("${content}" "Sample package" "description")
 expect_value("${content}" "Sample package" "description")
 expect_value("${content}" "https://www.example.com/package/foo" "website")
 expect_value("${content}" "https://www.example.com/package/foo" "website")

+ 2 - 0
Tests/RunCMake/InstallPackageInfo/Metadata.cmake

@@ -9,6 +9,8 @@ install(
   COMPAT_VERSION 1.2.0
   COMPAT_VERSION 1.2.0
   DEFAULT_TARGETS foo
   DEFAULT_TARGETS foo
   DEFAULT_CONFIGURATIONS release debug
   DEFAULT_CONFIGURATIONS release debug
+  LICENSE "BSD-3-Clause AND CC-BY-SA-4.0"
+  DEFAULT_LICENSE "BSD-3-Clause"
   DESCRIPTION "Sample package"
   DESCRIPTION "Sample package"
   HOMEPAGE_URL "https://www.example.com/package/foo"
   HOMEPAGE_URL "https://www.example.com/package/foo"
   )
   )

+ 3 - 0
Tests/RunCMake/InstallPackageInfo/ProjectMetadata-check.cmake

@@ -6,6 +6,7 @@ file(READ "${out_dir}/foo.cps" content)
 expect_value("${content}" "foo" "name")
 expect_value("${content}" "foo" "name")
 expect_value("${content}" "1.2.3" "version")
 expect_value("${content}" "1.2.3" "version")
 expect_value("${content}" "1.1.0" "compat_version")
 expect_value("${content}" "1.1.0" "compat_version")
+expect_value("${content}" "BSD-3-Clause" "license")
 expect_value("${content}" "Sample package" "description")
 expect_value("${content}" "Sample package" "description")
 expect_value("${content}" "https://www.example.com/package/foo" "website")
 expect_value("${content}" "https://www.example.com/package/foo" "website")
 
 
@@ -13,6 +14,7 @@ file(READ "${out_dir}/test1.cps" content)
 expect_value("${content}" "test1" "name")
 expect_value("${content}" "test1" "name")
 expect_value("${content}" "1.2.3" "version")
 expect_value("${content}" "1.2.3" "version")
 expect_value("${content}" "1.1.0" "compat_version")
 expect_value("${content}" "1.1.0" "compat_version")
+expect_value("${content}" "BSD-3-Clause" "license")
 expect_value("${content}" "Sample package" "description")
 expect_value("${content}" "Sample package" "description")
 expect_value("${content}" "https://www.example.com/package/foo" "website")
 expect_value("${content}" "https://www.example.com/package/foo" "website")
 
 
@@ -20,5 +22,6 @@ file(READ "${out_dir}/test2.cps" content)
 expect_value("${content}" "test2" "name")
 expect_value("${content}" "test2" "name")
 expect_value("${content}" "1.4.7" "version")
 expect_value("${content}" "1.4.7" "version")
 expect_missing("${content}" "compat_version")
 expect_missing("${content}" "compat_version")
+expect_value("${content}" "Apache-2.0" "license")
 expect_value("${content}" "Don't inherit" "description")
 expect_value("${content}" "Don't inherit" "description")
 expect_value("${content}" "https://www.example.com/package/bar" "website")
 expect_value("${content}" "https://www.example.com/package/bar" "website")

+ 2 - 0
Tests/RunCMake/InstallPackageInfo/ProjectMetadata.cmake

@@ -1,6 +1,7 @@
 project(foo
 project(foo
   VERSION 1.2.3
   VERSION 1.2.3
   COMPAT_VERSION 1.1.0
   COMPAT_VERSION 1.1.0
+  SPDX_LICENSE "BSD-3-Clause"
   DESCRIPTION "Sample package"
   DESCRIPTION "Sample package"
   HOMEPAGE_URL "https://www.example.com/package/foo"
   HOMEPAGE_URL "https://www.example.com/package/foo"
   )
   )
@@ -30,6 +31,7 @@ install(
   EXPORT foo
   EXPORT foo
   PROJECT foo
   PROJECT foo
   VERSION 1.4.7
   VERSION 1.4.7
+  LICENSE "Apache-2.0"
   DESCRIPTION "Don't inherit"
   DESCRIPTION "Don't inherit"
   HOMEPAGE_URL "https://www.example.com/package/bar"
   HOMEPAGE_URL "https://www.example.com/package/bar"
   )
   )

+ 1 - 0
Tests/RunCMake/project/Omissions.cmake

@@ -20,5 +20,6 @@ expect_empty(VERSION_MINOR)
 expect_empty(VERSION_PATCH)
 expect_empty(VERSION_PATCH)
 expect_empty(VERSION_TWEAK)
 expect_empty(VERSION_TWEAK)
 expect_empty(COMPAT_VERSION)
 expect_empty(COMPAT_VERSION)
+expect_empty(SPDX_LICENSE)
 expect_empty(DESCRIPTION)
 expect_empty(DESCRIPTION)
 expect_empty(HOMEPAGE_URL)
 expect_empty(HOMEPAGE_URL)

+ 1 - 0
Tests/RunCMake/project/ProjectLicense-stdout.txt

@@ -0,0 +1 @@
+PROJECT_SPDX_LICENSE=BSD-3-Clause

+ 5 - 0
Tests/RunCMake/project/ProjectLicense.cmake

@@ -0,0 +1,5 @@
+project(ProjectLicenseTest SPDX_LICENSE "BSD-3-Clause" LANGUAGES)
+if(NOT PROJECT_SPDX_LICENSE)
+  message(FATAL_ERROR "PROJECT_SPDX_LICENSE expected to be set")
+endif()
+message(STATUS "PROJECT_SPDX_LICENSE=${PROJECT_SPDX_LICENSE}")

+ 1 - 0
Tests/RunCMake/project/ProjectLicense2-result.txt

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

+ 1 - 0
Tests/RunCMake/project/ProjectLicense2-stderr.txt

@@ -0,0 +1 @@
+  SPDX_LICENSE may be specified at most once.

+ 1 - 0
Tests/RunCMake/project/ProjectLicense2.cmake

@@ -0,0 +1 @@
+project(ProjectLicenseTest SPDX_LICENSE "BSD-3-Clause" SPDX_LICENSE "Apache-2.0" LANGUAGES)

+ 2 - 0
Tests/RunCMake/project/ProjectLicenseNoArg-stderr.txt

@@ -0,0 +1,2 @@
+  SPDX_LICENSE keyword not followed by a value or was followed by a value
+  that expanded to nothing.

+ 1 - 0
Tests/RunCMake/project/ProjectLicenseNoArg.cmake

@@ -0,0 +1 @@
+project(ProjectLicenseTest LANGUAGES NONE SPDX_LICENSE)

+ 2 - 0
Tests/RunCMake/project/ProjectLicenseNoArg2-stderr.txt

@@ -0,0 +1,2 @@
+  SPDX_LICENSE keyword not followed by a value or was followed by a value
+  that expanded to nothing.

+ 1 - 0
Tests/RunCMake/project/ProjectLicenseNoArg2.cmake

@@ -0,0 +1 @@
+project(ProjectLicenseTest SPDX_LICENSE LANGUAGES NONE)

+ 4 - 0
Tests/RunCMake/project/RunCMakeTest.cmake

@@ -66,6 +66,10 @@ run_cmake_with_options(ProjectCompatVersionInvalid ${opts})
 run_cmake_with_options(ProjectCompatVersionMissingVersion ${opts})
 run_cmake_with_options(ProjectCompatVersionMissingVersion ${opts})
 run_cmake_with_options(ProjectCompatVersionNewer ${opts})
 run_cmake_with_options(ProjectCompatVersionNewer ${opts})
 run_cmake_with_options(ProjectCompatVersionNoArg ${opts})
 run_cmake_with_options(ProjectCompatVersionNoArg ${opts})
+run_cmake_with_options(ProjectLicense ${opts})
+run_cmake_with_options(ProjectLicense2 ${opts})
+run_cmake_with_options(ProjectLicenseNoArg ${opts})
+run_cmake_with_options(ProjectLicenseNoArg2 ${opts})
 
 
 run_cmake(CMP0048-NEW)
 run_cmake(CMP0048-NEW)