Browse Source

cmNinjaTargetGenerator: write out export information for the collator

The collator will use this to know where the target's export information
needs to go so that module properties may be provided.
Ben Boeckel 3 years ago
parent
commit
95402a0bd7

+ 79 - 0
Source/cmNinjaTargetGenerator.cxx

@@ -21,12 +21,16 @@
 
 
 #include "cmComputeLinkInformation.h"
 #include "cmComputeLinkInformation.h"
 #include "cmCustomCommandGenerator.h"
 #include "cmCustomCommandGenerator.h"
+#include "cmExportBuildFileGenerator.h"
+#include "cmExportSet.h"
 #include "cmFileSet.h"
 #include "cmFileSet.h"
 #include "cmGeneratedFileStream.h"
 #include "cmGeneratedFileStream.h"
 #include "cmGeneratorExpression.h"
 #include "cmGeneratorExpression.h"
 #include "cmGeneratorTarget.h"
 #include "cmGeneratorTarget.h"
 #include "cmGlobalNinjaGenerator.h"
 #include "cmGlobalNinjaGenerator.h"
+#include "cmInstallExportGenerator.h"
 #include "cmInstallFileSetGenerator.h"
 #include "cmInstallFileSetGenerator.h"
+#include "cmInstallGenerator.h"
 #include "cmLocalGenerator.h"
 #include "cmLocalGenerator.h"
 #include "cmLocalNinjaGenerator.h"
 #include "cmLocalNinjaGenerator.h"
 #include "cmMakefile.h"
 #include "cmMakefile.h"
@@ -42,6 +46,7 @@
 #include "cmStringAlgorithms.h"
 #include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 #include "cmSystemTools.h"
 #include "cmTarget.h"
 #include "cmTarget.h"
+#include "cmTargetExport.h"
 #include "cmValue.h"
 #include "cmValue.h"
 #include "cmake.h"
 #include "cmake.h"
 
 
@@ -1752,6 +1757,80 @@ void cmNinjaTargetGenerator::WriteTargetDependInfo(std::string const& lang,
     }
     }
   }
   }
 
 
+  tdi["config"] = config;
+
+  // Add information about the export sets that this target is a member of.
+  Json::Value& tdi_exports = tdi["exports"] = Json::arrayValue;
+  std::string export_name = this->GeneratorTarget->GetExportName();
+
+  auto const& all_install_exports =
+    this->GetGlobalGenerator()->GetExportSets();
+  for (auto const& exp : all_install_exports) {
+    // Ignore exports sets which are not for this target.
+    auto const& targets = exp.second.GetTargetExports();
+    auto tgt_export =
+      std::find_if(targets.begin(), targets.end(),
+                   [this](std::unique_ptr<cmTargetExport> const& te) {
+                     return te->Target == this->GeneratorTarget;
+                   });
+    if (tgt_export == targets.end()) {
+      continue;
+    }
+
+    auto const* installs = exp.second.GetInstallations();
+    for (auto const* install : *installs) {
+      Json::Value tdi_export_info = Json::objectValue;
+
+      auto const& ns = install->GetNamespace();
+      auto const& dest = install->GetDestination();
+      auto const& cxxm_dir = install->GetCxxModuleDirectory();
+      auto const& export_prefix = install->GetTempDir();
+
+      tdi_export_info["namespace"] = ns;
+      tdi_export_info["export-name"] = export_name;
+      tdi_export_info["destination"] = dest;
+      tdi_export_info["cxx-module-info-dir"] = cxxm_dir;
+      tdi_export_info["export-prefix"] = export_prefix;
+      tdi_export_info["install"] = true;
+
+      tdi_exports.append(tdi_export_info);
+    }
+  }
+
+  auto const& all_build_exports =
+    this->GetMakefile()->GetExportBuildFileGenerators();
+  for (auto const& exp : all_build_exports) {
+    std::vector<std::string> targets;
+    exp->GetTargets(targets);
+
+    // Ignore exports sets which are not for this target.
+    auto const& name = this->GeneratorTarget->GetName();
+    bool has_current_target =
+      std::any_of(targets.begin(), targets.end(),
+                  [name](std::string const& tname) { return tname == name; });
+    if (!has_current_target) {
+      continue;
+    }
+
+    Json::Value tdi_export_info = Json::objectValue;
+
+    auto const& ns = exp->GetNamespace();
+    auto const& main_fn = exp->GetMainExportFileName();
+    auto const& cxxm_dir = exp->GetCxxModuleDirectory();
+    auto dest = cmsys::SystemTools::GetParentDirectory(main_fn);
+    auto const& export_prefix =
+      cmSystemTools::GetFilenamePath(exp->GetMainExportFileName());
+
+    tdi_export_info["namespace"] = ns;
+    tdi_export_info["export-name"] = export_name;
+    tdi_export_info["destination"] = dest;
+    tdi_export_info["cxx-module-info-dir"] = cxxm_dir;
+    tdi_export_info["export-prefix"] = export_prefix;
+    tdi_export_info["install"] = false;
+
+    tdi_exports.append(tdi_export_info);
+  }
+
   std::string const tdin = this->GetTargetDependInfoPath(lang, config);
   std::string const tdin = this->GetTargetDependInfoPath(lang, config);
   cmGeneratedFileStream tdif(tdin);
   cmGeneratedFileStream tdif(tdin);
   tdif << tdi;
   tdif << tdi;

+ 34 - 0
Tests/RunCMake/CXXModules/NinjaDependInfoExport-check.cmake

@@ -0,0 +1,34 @@
+include("${CMAKE_CURRENT_LIST_DIR}/check-json.cmake")
+
+if (RunCMake_GENERATOR_IS_MULTI_CONFIG)
+  set(have_file 0)
+  foreach (config IN ITEMS Release Debug RelWithDebInfo MinSizeRel)
+    if (NOT EXISTS "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/ninja-exports-public.dir/${config}/CXXDependInfo.json")
+      continue ()
+    endif ()
+    set(have_file 1)
+
+    set(CMAKE_BUILD_TYPE "${config}")
+
+    file(READ "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/ninja-exports-public.dir/${config}/CXXDependInfo.json" actual_contents)
+    file(READ "${CMAKE_CURRENT_LIST_DIR}/expect/NinjaDependInfoExport-public.json" expect_contents)
+    check_json("${actual_contents}" "${expect_contents}")
+
+    file(READ "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/ninja-exports-private.dir/${config}/CXXDependInfo.json" actual_contents)
+    file(READ "${CMAKE_CURRENT_LIST_DIR}/expect/NinjaDependInfoExport-private.json" expect_contents)
+    check_json("${actual_contents}" "${expect_contents}")
+  endforeach ()
+
+  if (NOT have_file)
+    list(APPEND RunCMake_TEST_FAILED
+      "No recognized build configurations found.")
+  endif ()
+else ()
+  file(READ "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/ninja-exports-public.dir/CXXDependInfo.json" actual_contents)
+  file(READ "${CMAKE_CURRENT_LIST_DIR}/expect/NinjaDependInfoExport-public.json" expect_contents)
+  check_json("${actual_contents}" "${expect_contents}")
+
+  file(READ "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/ninja-exports-private.dir/CXXDependInfo.json" actual_contents)
+  file(READ "${CMAKE_CURRENT_LIST_DIR}/expect/NinjaDependInfoExport-private.json" expect_contents)
+  check_json("${actual_contents}" "${expect_contents}")
+endif ()

+ 11 - 0
Tests/RunCMake/CXXModules/NinjaDependInfoExport-stderr.txt

@@ -0,0 +1,11 @@
+CMake Warning \(dev\) at NinjaDependInfoExport.cmake:14 \(target_sources\):
+  CMake's C\+\+ module support is experimental.  It is meant only for
+  experimentation and feedback to CMake developers.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:6 \(include\)
+This warning is for project developers.  Use -Wno-dev to suppress it.
+
+CMake Warning \(dev\):
+  C\+\+20 modules support via CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP is
+  experimental.  It is meant only for compiler developers to try.
+This warning is for project developers.  Use -Wno-dev to suppress it.

+ 85 - 0
Tests/RunCMake/CXXModules/NinjaDependInfoExport.cmake

@@ -0,0 +1,85 @@
+# Fake out that we have dyndep; we only need to generate, not actually build
+# here.
+set(CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP 1)
+set(CMAKE_EXPERIMENTAL_CXX_SCANDEP_SOURCE "")
+
+enable_language(CXX)
+
+if (NOT CMAKE_GENERATOR MATCHES "Ninja")
+  message(FATAL_ERROR
+    "This test requires a 'Ninja' generator to be used.")
+endif ()
+
+add_library(ninja-exports-public)
+target_sources(ninja-exports-public
+  PRIVATE
+    sources/module-impl.cxx
+    sources/module-internal-part-impl.cxx
+    sources/module-part-impl.cxx
+    sources/module-use.cxx
+  PUBLIC
+    FILE_SET modules TYPE CXX_MODULES
+    BASE_DIRS
+      "${CMAKE_CURRENT_SOURCE_DIR}/sources"
+    FILES
+      sources/module.cxx
+      sources/module-part.cxx
+    FILE_SET internal_partitions TYPE CXX_MODULES FILES
+      sources/module-internal-part.cxx)
+target_compile_features(ninja-exports-public
+  PRIVATE
+    cxx_std_20)
+set_property(TARGET ninja-exports-public
+  PROPERTY EXPORT_NAME "with-public")
+
+install(TARGETS ninja-exports-public
+  EXPORT exp
+  FILE_SET modules
+    DESTINATION "lib/cxx"
+    COMPONENT "modules"
+  FILE_SET internal_partitions
+    DESTINATION "lib/cxx/internals"
+    COMPONENT "modules-internal")
+
+add_library(ninja-exports-private)
+target_sources(ninja-exports-private
+  PRIVATE
+    sources/module-impl.cxx
+    sources/module-internal-part-impl.cxx
+    sources/module-part-impl.cxx
+    sources/module-use.cxx
+  PRIVATE
+    FILE_SET modules TYPE CXX_MODULES
+    BASE_DIRS
+      "${CMAKE_CURRENT_SOURCE_DIR}/sources"
+    FILES
+      sources/module.cxx
+      sources/module-part.cxx
+    FILE_SET internal_partitions TYPE CXX_MODULES FILES
+      sources/module-internal-part.cxx)
+target_compile_features(ninja-exports-private
+  PRIVATE
+    cxx_std_20)
+set_property(TARGET ninja-exports-private
+  PROPERTY EXPORT_NAME "with-private")
+
+install(TARGETS ninja-exports-private
+  EXPORT exp)
+
+# Test multiple build exports.
+export(EXPORT exp
+  FILE "${CMAKE_BINARY_DIR}/lib/cmake/export1/export1-targets.cmake"
+  NAMESPACE export1::
+  CXX_MODULES_DIRECTORY "cxx-modules")
+export(EXPORT exp
+  FILE "${CMAKE_BINARY_DIR}/lib/cmake/export2/export2-targets.cmake"
+  CXX_MODULES_DIRECTORY "cxx-modules")
+
+# Test multiple install exports.
+install(EXPORT exp
+  DESTINATION "lib/cmake/export1"
+  NAMESPACE export1::
+  CXX_MODULES_DIRECTORY "cxx-modules")
+install(EXPORT exp
+  DESTINATION "lib/cmake/export2"
+  CXX_MODULES_DIRECTORY "cxx-modules")

+ 1 - 0
Tests/RunCMake/CXXModules/RunCMakeTest.cmake

@@ -77,6 +77,7 @@ run_cmake(ExportInstallCxxModules)
 # Generator-specific tests.
 # Generator-specific tests.
 if (RunCMake_GENERATOR MATCHES "Ninja")
 if (RunCMake_GENERATOR MATCHES "Ninja")
   run_cmake(NinjaDependInfoFileSet)
   run_cmake(NinjaDependInfoFileSet)
+  run_cmake(NinjaDependInfoExport)
 else ()
 else ()
   message(FATAL_ERROR
   message(FATAL_ERROR
     "Please add 'DependInfo' tests for the '${RunCMake_GENERATOR}' generator.")
     "Please add 'DependInfo' tests for the '${RunCMake_GENERATOR}' generator.")

+ 72 - 0
Tests/RunCMake/CXXModules/expect/NinjaDependInfoExport-private.json

@@ -0,0 +1,72 @@
+{
+  "compiler-id": "<IGNORE>",
+  "config": "<CONFIG>",
+  "cxx-modules": {
+    "CMakeFiles/ninja-exports-private.dir/sources/module-internal-part.cxx.o": {
+      "destination": null,
+      "name": "internal_partitions",
+      "relative-directory": "sources",
+      "source": "<SOURCE_DIR>/sources/module-internal-part.cxx",
+      "type": "CXX_MODULES",
+      "visibility": "PRIVATE"
+    },
+    "CMakeFiles/ninja-exports-private.dir/sources/module-part.cxx.o": {
+      "destination": null,
+      "name": "modules",
+      "relative-directory": "",
+      "source": "<SOURCE_DIR>/sources/module-part.cxx",
+      "type": "CXX_MODULES",
+      "visibility": "PRIVATE"
+    },
+    "CMakeFiles/ninja-exports-private.dir/sources/module.cxx.o": {
+      "destination": null,
+      "name": "modules",
+      "relative-directory": "",
+      "source": "<SOURCE_DIR>/sources/module.cxx",
+      "type": "CXX_MODULES",
+      "visibility": "PRIVATE"
+    }
+  },
+  "dir-cur-bld": "<BINARY_DIR>",
+  "dir-cur-src": "<SOURCE_DIR>",
+  "dir-top-bld": "<BINARY_DIR>",
+  "dir-top-src": "<SOURCE_DIR>",
+  "exports": [
+    {
+      "cxx-module-info-dir" : "cxx-modules",
+      "destination" : "lib/cmake/export1",
+      "export-name" : "with-private",
+      "export-prefix" : "<BINARY_DIR>/CMakeFiles/Export/d2e2673818fd2bd8c45c0e3ed0e38fcd",
+      "install" : true,
+      "namespace" : "export1::"
+    },
+    {
+      "cxx-module-info-dir" : "cxx-modules",
+      "destination" : "lib/cmake/export2",
+      "export-name" : "with-private",
+      "export-prefix" : "<BINARY_DIR>/CMakeFiles/Export/28cd47cb4c96ad5cadaa3fb1b0201ae8",
+      "install" : true,
+      "namespace" : ""
+    },
+    {
+      "cxx-module-info-dir" : "cxx-modules",
+      "destination" : "<BINARY_DIR>/lib/cmake/export1",
+      "export-name" : "with-private",
+      "export-prefix" : "<BINARY_DIR>/lib/cmake/export1",
+      "install" : false,
+      "namespace" : "export1::"
+    },
+    {
+      "cxx-module-info-dir" : "cxx-modules",
+      "destination" : "<BINARY_DIR>/lib/cmake/export2",
+      "export-name" : "with-private",
+      "export-prefix" : "<BINARY_DIR>/lib/cmake/export2",
+      "install" : false,
+      "namespace" : ""
+    }
+  ],
+  "include-dirs": [],
+  "language": "CXX",
+  "linked-target-dirs": [],
+  "module-dir": "<BINARY_DIR>/CMakeFiles/ninja-exports-private.dir"
+}

+ 72 - 0
Tests/RunCMake/CXXModules/expect/NinjaDependInfoExport-public.json

@@ -0,0 +1,72 @@
+{
+  "compiler-id": "<IGNORE>",
+  "config": "<CONFIG>",
+  "cxx-modules": {
+    "CMakeFiles/ninja-exports-public.dir/sources/module-internal-part.cxx.o": {
+      "destination": "lib/cxx/internals",
+      "name": "internal_partitions",
+      "relative-directory": "sources",
+      "source": "<SOURCE_DIR>/sources/module-internal-part.cxx",
+      "type": "CXX_MODULES",
+      "visibility": "PUBLIC"
+    },
+    "CMakeFiles/ninja-exports-public.dir/sources/module-part.cxx.o": {
+      "destination": "lib/cxx",
+      "name": "modules",
+      "relative-directory": "",
+      "source": "<SOURCE_DIR>/sources/module-part.cxx",
+      "type": "CXX_MODULES",
+      "visibility": "PUBLIC"
+    },
+    "CMakeFiles/ninja-exports-public.dir/sources/module.cxx.o": {
+      "destination": "lib/cxx",
+      "name": "modules",
+      "relative-directory": "",
+      "source": "<SOURCE_DIR>/sources/module.cxx",
+      "type": "CXX_MODULES",
+      "visibility": "PUBLIC"
+    }
+  },
+  "dir-cur-bld": "<BINARY_DIR>",
+  "dir-cur-src": "<SOURCE_DIR>",
+  "dir-top-bld": "<BINARY_DIR>",
+  "dir-top-src": "<SOURCE_DIR>",
+  "exports": [
+    {
+      "cxx-module-info-dir" : "cxx-modules",
+      "destination" : "lib/cmake/export1",
+      "export-name" : "with-public",
+      "export-prefix" : "<BINARY_DIR>/CMakeFiles/Export/d2e2673818fd2bd8c45c0e3ed0e38fcd",
+      "install" : true,
+      "namespace" : "export1::"
+    },
+    {
+      "cxx-module-info-dir" : "cxx-modules",
+      "destination" : "lib/cmake/export2",
+      "export-name" : "with-public",
+      "export-prefix" : "<BINARY_DIR>/CMakeFiles/Export/28cd47cb4c96ad5cadaa3fb1b0201ae8",
+      "install" : true,
+      "namespace" : ""
+    },
+    {
+      "cxx-module-info-dir" : "cxx-modules",
+      "destination" : "<BINARY_DIR>/lib/cmake/export1",
+      "export-name" : "with-public",
+      "export-prefix" : "<BINARY_DIR>/lib/cmake/export1",
+      "install" : false,
+      "namespace" : "export1::"
+    },
+    {
+      "cxx-module-info-dir" : "cxx-modules",
+      "destination" : "<BINARY_DIR>/lib/cmake/export2",
+      "export-name" : "with-public",
+      "export-prefix" : "<BINARY_DIR>/lib/cmake/export2",
+      "install" : false,
+      "namespace" : ""
+    }
+  ],
+  "include-dirs": [],
+  "language": "CXX",
+  "linked-target-dirs": [],
+  "module-dir": "<BINARY_DIR>/CMakeFiles/ninja-exports-public.dir"
+}

+ 1 - 0
Tests/RunCMake/CXXModules/expect/NinjaDependInfoFileSet-private.json

@@ -31,6 +31,7 @@
   "dir-cur-src": "<SOURCE_DIR>",
   "dir-cur-src": "<SOURCE_DIR>",
   "dir-top-bld": "<BINARY_DIR>",
   "dir-top-bld": "<BINARY_DIR>",
   "dir-top-src": "<SOURCE_DIR>",
   "dir-top-src": "<SOURCE_DIR>",
+  "exports": [],
   "include-dirs": [],
   "include-dirs": [],
   "language": "CXX",
   "language": "CXX",
   "linked-target-dirs": [],
   "linked-target-dirs": [],

+ 1 - 0
Tests/RunCMake/CXXModules/expect/NinjaDependInfoFileSet-public.json

@@ -31,6 +31,7 @@
   "dir-cur-src": "<SOURCE_DIR>",
   "dir-cur-src": "<SOURCE_DIR>",
   "dir-top-bld": "<BINARY_DIR>",
   "dir-top-bld": "<BINARY_DIR>",
   "dir-top-src": "<SOURCE_DIR>",
   "dir-top-src": "<SOURCE_DIR>",
+  "exports": [],
   "include-dirs": [],
   "include-dirs": [],
   "language": "CXX",
   "language": "CXX",
   "linked-target-dirs": [],
   "linked-target-dirs": [],