Browse Source

exports: support `CXX_MODULES_DIRECTORY`

This directory will be used to store build-discovered information about
targets such as the modules provided by the files in the relevant
`FILE_SET` types.

A directory is used because basing the name on a `<FILE_NAME>-*.cmake`
pattern makes it end up being globbed in the configuration-dependent
information mechanism. Since old modules and targets may be around,
unconditionally including them may refer to targets that do not actually
exist.
Ben Boeckel 3 years ago
parent
commit
fe44cbe9e7

+ 14 - 2
Help/command/export.rst

@@ -25,7 +25,8 @@ Exporting Targets
 .. code-block:: cmake
 
   export(TARGETS <target>... [NAMESPACE <namespace>]
-         [APPEND] FILE <filename> [EXPORT_LINK_INTERFACE_LIBRARIES])
+         [APPEND] FILE <filename> [EXPORT_LINK_INTERFACE_LIBRARIES]
+         [CXX_MODULES_DIRECTORY <directory>])
 
 Creates a file ``<filename>`` that may be included by outside projects to
 import targets named by ``<target>...`` from the current project's build tree.
@@ -52,6 +53,16 @@ The options are:
   in the export, even when policy :policy:`CMP0022` is NEW.  This is useful
   to support consumers using CMake versions older than 2.8.12.
 
+``CXX_MODULES_DIRECTORY <directory>``
+
+.. note ::
+
+  Experimental. Gated by ``CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API``
+
+  Export C++ module properties to files under the given directory. Each file
+  will be named according to the target's export name (without any namespace).
+  These files will automatically be included from the export file.
+
 This signature requires all targets to be listed explicitly.  If a library
 target is included in the export, but a target to which it links is not
 included, the behavior is unspecified.  See the `export(EXPORT)`_ signature
@@ -95,7 +106,8 @@ Exporting Targets matching install(EXPORT)
 
 .. code-block:: cmake
 
-  export(EXPORT <export-name> [NAMESPACE <namespace>] [FILE <filename>])
+  export(EXPORT <export-name> [NAMESPACE <namespace>] [FILE <filename>]
+         [CXX_MODULES_DIRECTORY <directory>])
 
 Creates a file ``<filename>`` that may be included by outside projects to
 import targets from the current project's build tree.  This is the same

+ 15 - 2
Help/command/install.rst

@@ -790,9 +790,10 @@ Installing Exports
 .. code-block:: cmake
 
   install(EXPORT <export-name> DESTINATION <dir>
-          [NAMESPACE <namespace>] [[FILE <name>.cmake]|
+          [NAMESPACE <namespace>] [FILE <name>.cmake]
           [PERMISSIONS permissions...]
-          [CONFIGURATIONS [Debug|Release|...]]
+          [CONFIGURATIONS [Debug|Release|...]
+          [CXX_MODULES_DIRECTORY <directory>]
           [EXPORT_LINK_INTERFACE_LIBRARIES]
           [COMPONENT <component>]
           [EXCLUDE_FROM_ALL])
@@ -848,6 +849,18 @@ library is always installed if the headers and CMake export file are present.
   to an ndk build system complete with transitive dependencies, include flags
   and defines required to use the libraries.
 
+``CXX_MODULES_DIRECTORY``
+
+.. note ::
+
+  Experimental. Gated by ``CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API``
+
+  Specify a subdirectory to store C++ module information for targets in the
+  export set. This directory will be populated with files which add the
+  necessary target property information to the relevant targets. Note that
+  without this information, none of the C++ modules which are part of the
+  targets in the export set will support being imported in consuming targets.
+
 The ``EXPORT`` form is useful to help outside projects use targets built
 and installed by the current project.  For example, the code
 

+ 12 - 0
Source/cmExportBuildFileGenerator.h

@@ -47,6 +47,16 @@ public:
   }
   void SetExportSet(cmExportSet*);
 
+  /** Set the name of the C++ module directory.  */
+  void SetCxxModuleDirectory(std::string cxx_module_dir)
+  {
+    this->CxxModulesDirectory = std::move(cxx_module_dir);
+  }
+  const std::string& GetCxxModuleDirectory() const
+  {
+    return this->CxxModulesDirectory;
+  }
+
   /** Set whether to append generated code to the output file.  */
   void SetAppendMode(bool append) { this->AppendMode = append; }
 
@@ -88,4 +98,6 @@ protected:
   cmExportSet* ExportSet;
   std::vector<cmGeneratorTarget*> Exports;
   cmLocalGenerator* LG;
+  // The directory for C++ module information.
+  std::string CxxModulesDirectory;
 };

+ 9 - 0
Source/cmExportCommand.cxx

@@ -14,6 +14,7 @@
 
 #include "cmArgumentParser.h"
 #include "cmExecutionStatus.h"
+#include "cmExperimental.h"
 #include "cmExportBuildAndroidMKGenerator.h"
 #include "cmExportBuildFileGenerator.h"
 #include "cmExportSet.h"
@@ -61,6 +62,7 @@ bool cmExportCommand(std::vector<std::string> const& args,
     std::string Namespace;
     std::string Filename;
     std::string AndroidMKFile;
+    std::string CxxModulesDirectory;
     bool Append = false;
     bool ExportOld = false;
   };
@@ -69,6 +71,12 @@ bool cmExportCommand(std::vector<std::string> const& args,
                   .Bind("NAMESPACE"_s, &Arguments::Namespace)
                   .Bind("FILE"_s, &Arguments::Filename);
 
+  bool const supportCxx20FileSetTypes = cmExperimental::HasSupportEnabled(
+    status.GetMakefile(), cmExperimental::Feature::CxxModuleCMakeApi);
+  if (supportCxx20FileSetTypes) {
+    parser.Bind("CXX_MODULES_DIRECTORY"_s, &Arguments::CxxModulesDirectory);
+  }
+
   if (args[0] == "EXPORT") {
     parser.Bind("EXPORT"_s, &Arguments::ExportSetName);
   } else {
@@ -211,6 +219,7 @@ bool cmExportCommand(std::vector<std::string> const& args,
   }
   ebfg->SetExportFile(fname.c_str());
   ebfg->SetNamespace(arguments.Namespace);
+  ebfg->SetCxxModuleDirectory(arguments.CxxModulesDirectory);
   ebfg->SetAppendMode(arguments.Append);
   if (exportSet != nullptr) {
     ebfg->SetExportSet(exportSet);

+ 10 - 3
Source/cmInstallCommand.cxx

@@ -1995,7 +1995,7 @@ bool HandleExportAndroidMKMode(std::vector<std::string> const& args,
     cm::make_unique<cmInstallExportGenerator>(
       &exportSet, ica.GetDestination(), ica.GetPermissions(),
       ica.GetConfigurations(), ica.GetComponent(), message,
-      ica.GetExcludeFromAll(), fname, name_space, exportOld, true,
+      ica.GetExcludeFromAll(), fname, name_space, "", exportOld, true,
       helper.Makefile->GetBacktrace()));
 
   return true;
@@ -2018,12 +2018,19 @@ bool HandleExportMode(std::vector<std::string> const& args,
   std::string name_space;
   bool exportOld = false;
   std::string filename;
+  std::string cxx_modules_directory;
 
   ica.Bind("EXPORT"_s, exp);
   ica.Bind("NAMESPACE"_s, name_space);
   ica.Bind("EXPORT_LINK_INTERFACE_LIBRARIES"_s, exportOld);
   ica.Bind("FILE"_s, filename);
 
+  bool const supportCxx20FileSetTypes = cmExperimental::HasSupportEnabled(
+    *helper.Makefile, cmExperimental::Feature::CxxModuleCMakeApi);
+  if (supportCxx20FileSetTypes) {
+    ica.Bind("CXX_MODULES_DIRECTORY"_s, cxx_modules_directory);
+  }
+
   std::vector<std::string> unknownArgs;
   ica.Parse(args, &unknownArgs);
 
@@ -2109,8 +2116,8 @@ bool HandleExportMode(std::vector<std::string> const& args,
     cm::make_unique<cmInstallExportGenerator>(
       &exportSet, ica.GetDestination(), ica.GetPermissions(),
       ica.GetConfigurations(), ica.GetComponent(), message,
-      ica.GetExcludeFromAll(), fname, name_space, exportOld, false,
-      helper.Makefile->GetBacktrace()));
+      ica.GetExcludeFromAll(), fname, name_space, cxx_modules_directory,
+      exportOld, false, helper.Makefile->GetBacktrace()));
 
   return true;
 }

+ 3 - 1
Source/cmInstallExportGenerator.cxx

@@ -23,7 +23,8 @@ cmInstallExportGenerator::cmInstallExportGenerator(
   cmExportSet* exportSet, std::string const& destination,
   std::string file_permissions, std::vector<std::string> const& configurations,
   std::string const& component, MessageLevel message, bool exclude_from_all,
-  std::string filename, std::string name_space, bool exportOld, bool android,
+  std::string filename, std::string name_space,
+  std::string cxx_modules_directory, bool exportOld, bool android,
   cmListFileBacktrace backtrace)
   : cmInstallGenerator(destination, configurations, component, message,
                        exclude_from_all, false, std::move(backtrace))
@@ -31,6 +32,7 @@ cmInstallExportGenerator::cmInstallExportGenerator(
   , FilePermissions(std::move(file_permissions))
   , FileName(std::move(filename))
   , Namespace(std::move(name_space))
+  , CxxModulesDirectory(std::move(cxx_modules_directory))
   , ExportOld(exportOld)
 {
   if (android) {

+ 7 - 1
Source/cmInstallExportGenerator.h

@@ -28,7 +28,8 @@ public:
                            const std::vector<std::string>& configurations,
                            std::string const& component, MessageLevel message,
                            bool exclude_from_all, std::string filename,
-                           std::string name_space, bool exportOld,
+                           std::string name_space,
+                           std::string cxx_modules_directory, bool exportOld,
                            bool android, cmListFileBacktrace backtrace);
   cmInstallExportGenerator(const cmInstallExportGenerator&) = delete;
   ~cmInstallExportGenerator() override;
@@ -50,6 +51,10 @@ public:
   std::string GetDestinationFile() const;
   std::string GetFileName() const { return this->FileName; }
   std::string GetTempDir() const;
+  std::string GetCxxModuleDirectory() const
+  {
+    return this->CxxModulesDirectory;
+  }
 
 protected:
   void GenerateScript(std::ostream& os) override;
@@ -64,6 +69,7 @@ protected:
   std::string const FilePermissions;
   std::string const FileName;
   std::string const Namespace;
+  std::string const CxxModulesDirectory;
   bool const ExportOld;
   cmLocalGenerator* LocalGenerator = nullptr;