浏览代码

cmake --install: Respect CMAKE_DEFAULT_CONFIGS

When `cmake --install` is run with no `--config` passed, use
`CMAKE_DEFAULT_CONFIGS` to determine which config(s) to install.

Fixes: #21475
Martin Duffy 11 月之前
父节点
当前提交
ea8e3107ec

+ 13 - 7
Source/cmGlobalGenerator.cxx

@@ -1796,15 +1796,21 @@ void cmGlobalGenerator::WriteJsonContent(const std::string& path,
 
 void cmGlobalGenerator::WriteInstallJson() const
 {
-  if (this->GetCMakeInstance()->GetState()->GetGlobalPropertyAsBool(
-        "INSTALL_PARALLEL")) {
-    Json::Value index(Json::objectValue);
-    index["InstallScripts"] = Json::arrayValue;
-    for (const auto& file : this->InstallScripts) {
-      index["InstallScripts"].append(file);
+  Json::Value index(Json::objectValue);
+  index["InstallScripts"] = Json::arrayValue;
+  for (const auto& file : this->InstallScripts) {
+    index["InstallScripts"].append(file);
+  }
+  index["Parallel"] =
+    this->GetCMakeInstance()->GetState()->GetGlobalPropertyAsBool(
+      "INSTALL_PARALLEL");
+  if (this->SupportsDefaultConfigs()) {
+    index["Configs"] = Json::arrayValue;
+    for (auto const& config : this->GetDefaultConfigs()) {
+      index["Configs"].append(config);
     }
-    this->WriteJsonContent("CMakeFiles/InstallScripts.json", index);
   }
+  this->WriteJsonContent("CMakeFiles/InstallScripts.json", index);
 }
 #endif
 

+ 6 - 0
Source/cmGlobalGenerator.h

@@ -678,6 +678,12 @@ public:
   void AddTestFile(std::string const& file);
   void AddCMakeFilesToRebuild(std::vector<std::string>& files) const;
 
+  virtual const std::set<std::string>& GetDefaultConfigs() const
+  {
+    static std::set<std::string> configs;
+    return configs;
+  }
+
 protected:
   // for a project collect all its targets by following depend
   // information, and also collect all the targets

+ 1 - 1
Source/cmGlobalNinjaGenerator.h

@@ -466,7 +466,7 @@ public:
 
   std::set<std::string> GetCrossConfigs(const std::string& config) const;
 
-  const std::set<std::string>& GetDefaultConfigs() const
+  const std::set<std::string>& GetDefaultConfigs() const override
   {
     return this->DefaultConfigs;
   }

+ 51 - 16
Source/cmInstallScriptHandler.cxx

@@ -33,41 +33,76 @@ using InstallScript = cmInstallScriptHandler::InstallScript;
 
 cmInstallScriptHandler::cmInstallScriptHandler(std::string _binaryDir,
                                                std::string _component,
+                                               std::string _config,
                                                std::vector<std::string>& args)
   : binaryDir(std::move(_binaryDir))
   , component(std::move(_component))
 {
   const std::string& file =
     cmStrCat(this->binaryDir, "/CMakeFiles/InstallScripts.json");
+  this->parallel = false;
+
+  auto addScript = [this, &args](std::string script,
+                                 std::string config) -> void {
+    this->commands.push_back(args);
+    if (!config.empty()) {
+      this->commands.back().insert(
+        this->commands.back().end() - 1,
+        cmStrCat("-DCMAKE_INSTALL_CONFIG_NAME=", config));
+    }
+    this->commands.back().emplace_back(script);
+    this->directories.push_back(cmSystemTools::GetFilenamePath(script));
+  };
+
+  int compare = 1;
   if (cmSystemTools::FileExists(file)) {
-    int compare;
     cmSystemTools::FileTimeCompare(
       cmStrCat(this->binaryDir, "/CMakeFiles/cmake.check_cache"), file,
       &compare);
-    if (compare < 1) {
+  }
+  if (compare < 1) {
+    Json::CharReaderBuilder rbuilder;
+    auto JsonReader =
+      std::unique_ptr<Json::CharReader>(rbuilder.newCharReader());
+    std::vector<char> content;
+    Json::Value value;
+    cmJSONState state(file, &value);
+    this->parallel = value["Parallel"].asBool();
+    if (this->parallel) {
       args.insert(args.end() - 1, "-DCMAKE_INSTALL_LOCAL_ONLY=1");
-      Json::CharReaderBuilder rbuilder;
-      auto JsonReader =
-        std::unique_ptr<Json::CharReader>(rbuilder.newCharReader());
-      std::vector<char> content;
-      Json::Value value;
-      cmJSONState state(file, &value);
-      for (auto const& script : value["InstallScripts"]) {
-        this->commands.push_back(args);
-        this->commands.back().emplace_back(script.asCString());
-        this->directories.push_back(
-          cmSystemTools::GetFilenamePath(script.asCString()));
+    }
+    if (_config.empty() && value.isMember("Configs")) {
+      for (auto const& config : value["Configs"]) {
+        this->configs.push_back(config.asCString());
+      }
+    } else {
+      this->configs.push_back(_config);
+    }
+    for (auto const& script : value["InstallScripts"]) {
+      for (auto const& config : configs) {
+        addScript(script.asCString(), config);
+      }
+      if (!this->parallel) {
+        break;
       }
     }
+  } else {
+    addScript(cmStrCat(this->binaryDir, "/cmake_install.cmake"), _config);
   }
 }
 
-bool cmInstallScriptHandler::isParallel()
+bool cmInstallScriptHandler::IsParallel()
+{
+  return this->parallel;
+}
+
+std::vector<std::vector<std::string>> cmInstallScriptHandler::GetCommands()
+  const
 {
-  return !this->commands.empty();
+  return this->commands;
 }
 
-int cmInstallScriptHandler::install(unsigned int j)
+int cmInstallScriptHandler::Install(unsigned int j)
 {
   cm::uv_loop_ptr loop;
   loop.init();

+ 7 - 3
Source/cmInstallScriptHandler.h

@@ -16,9 +16,11 @@ class cmInstallScriptHandler
 {
 public:
   cmInstallScriptHandler() = default;
-  cmInstallScriptHandler(std::string, std::string, std::vector<std::string>&);
-  bool isParallel();
-  int install(unsigned int j);
+  cmInstallScriptHandler(std::string, std::string, std::string,
+                         std::vector<std::string>&);
+  bool IsParallel();
+  int Install(unsigned int j);
+  std::vector<std::vector<std::string>> GetCommands() const;
   class InstallScript
   {
   public:
@@ -38,6 +40,8 @@ public:
 private:
   std::vector<std::vector<std::string>> commands;
   std::vector<std::string> directories;
+  std::vector<std::string> configs;
   std::string binaryDir;
   std::string component;
+  bool parallel;
 };

+ 1 - 1
Source/cmake.cxx

@@ -2933,7 +2933,7 @@ int cmake::Generate()
   this->SaveCache(this->GetHomeOutputDirectory());
 
 #if !defined(CMAKE_BOOTSTRAP)
-  this->GetGlobalGenerator()->WriteInstallJson();
+  this->GlobalGenerator->WriteInstallJson();
   this->FileAPI->WriteReplies();
 #endif
 

+ 29 - 34
Source/cmakemain.cxx

@@ -924,20 +924,6 @@ int do_install(int ac, char const* const* av)
     return 1;
   }
 
-  cmake cm(cmake::RoleScript, cmState::Script);
-
-  cmSystemTools::SetMessageCallback(
-    [&cm](const std::string& msg, const cmMessageMetadata& md) {
-      cmakemainMessageCallback(msg, md, &cm);
-    });
-  cm.SetProgressCallback([&cm](const std::string& msg, float prog) {
-    cmakemainProgressCallback(msg, prog, &cm);
-  });
-  cm.SetHomeDirectory("");
-  cm.SetHomeOutputDirectory("");
-  cm.SetDebugOutputOn(verbose);
-  cm.SetWorkingMode(cmake::SCRIPT_MODE);
-
   std::vector<std::string> args{ av[0] };
 
   if (!prefix.empty()) {
@@ -952,10 +938,6 @@ int do_install(int ac, char const* const* av)
     args.emplace_back("-DCMAKE_INSTALL_DO_STRIP=1");
   }
 
-  if (!config.empty()) {
-    args.emplace_back("-DCMAKE_INSTALL_CONFIG_NAME=" + config);
-  }
-
   if (!defaultDirectoryPermissions.empty()) {
     std::string parsedPermissionsVar;
     if (!parse_default_directory_permissions(defaultDirectoryPermissions,
@@ -970,25 +952,38 @@ int do_install(int ac, char const* const* av)
 
   args.emplace_back("-P");
 
-  auto handler = cmInstallScriptHandler(dir, component, args);
+  auto handler = cmInstallScriptHandler(dir, component, config, args);
   int ret = 0;
-  if (!handler.isParallel()) {
-    args.emplace_back(cmStrCat(dir, "/cmake_install.cmake"));
-    ret = int(bool(cm.Run(args)));
-  } else {
-    if (!jobs) {
-      jobs = 1;
-      auto envvar = cmSystemTools::GetEnvVar("CMAKE_INSTALL_PARALLEL_LEVEL");
-      if (envvar.has_value()) {
-        jobs = extract_job_number("", envvar.value());
-        if (jobs < 1) {
-          std::cerr << "Value of CMAKE_INSTALL_PARALLEL_LEVEL environment"
-                       " variable must be a positive integer.\n";
-          return 1;
-        }
+  if (!jobs && handler.IsParallel()) {
+    jobs = 1;
+    auto envvar = cmSystemTools::GetEnvVar("CMAKE_INSTALL_PARALLEL_LEVEL");
+    if (envvar.has_value()) {
+      jobs = extract_job_number("", envvar.value());
+      if (jobs < 1) {
+        std::cerr << "Value of CMAKE_INSTALL_PARALLEL_LEVEL environment"
+                     " variable must be a positive integer.\n";
+        return 1;
       }
     }
-    ret = handler.install(jobs);
+  }
+  if (handler.IsParallel()) {
+    ret = handler.Install(jobs);
+  } else {
+    for (auto const& cmd : handler.GetCommands()) {
+      cmake cm(cmake::RoleScript, cmState::Script);
+      cmSystemTools::SetMessageCallback(
+        [&cm](const std::string& msg, const cmMessageMetadata& md) {
+          cmakemainMessageCallback(msg, md, &cm);
+        });
+      cm.SetProgressCallback([&cm](const std::string& msg, float prog) {
+        cmakemainProgressCallback(msg, prog, &cm);
+      });
+      cm.SetHomeDirectory("");
+      cm.SetHomeOutputDirectory("");
+      cm.SetDebugOutputOn(verbose);
+      cm.SetWorkingMode(cmake::SCRIPT_MODE);
+      ret = int(bool(cm.Run(cmd)));
+    }
   }
 
   return int(ret > 0);

+ 1 - 0
Tests/RunCMake/CMakeLists.txt

@@ -240,6 +240,7 @@ if(CMAKE_GENERATOR MATCHES "Ninja")
   set_property(TEST RunCMake.Ninja APPEND PROPERTY LABELS "Fortran")
   set(NinjaMultiConfig_ARGS
     -DCYGWIN=${CYGWIN} -DMSYS=${MSYS}
+    -DCMAKE_EXECUTABLE_SUFFIX=${CMAKE_EXECUTABLE_SUFFIX}
     )
   if(ninja_test_with_qt_version)
     list(APPEND NinjaMultiConfig_ARGS

+ 0 - 2
Tests/RunCMake/InstallParallel/no-parallel-install-stdout.txt

@@ -1,5 +1,3 @@
-\-\- Install configuration:[^
-]*
 \-\- Installing:[^
 ]*
 \-\- Installing:[^

+ 5 - 20
Tests/RunCMake/InstallParallel/parallel-install-stdout.txt

@@ -1,30 +1,15 @@
-\[1\/5\] [^
-]*
-\-\- Install configuration:[^
-]*
+\[1\/5\] .*
 \-\- Installing:[^
 ]*
-\[2\/5\] [^
-]*
-\-\- Install configuration:[^
-]*
+\[2\/5\] .*
 \-\- Installing:[^
 ]*
-\[3\/5\] [^
-]*
-\-\- Install configuration:[^
-]*
+\[3\/5\] .*
 \-\- Installing:[^
 ]*
-\[4\/5\] [^
-]*
-\-\- Install configuration:[^
-]*
+\[4\/5\] .*
 \-\- Installing:[^
 ]*
-\[5\/5\] [^
-]*
-\-\- Install configuration:[^
-]*
+\[5\/5\] .*
 \-\- Installing:[^
 ]*

+ 13 - 0
Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake

@@ -470,6 +470,19 @@ run_cmake_command(OutputPathPrefix-clean-ninja "${RunCMake_MAKE_PROGRAM}" -f Out
 unset(RunCMake_TEST_NO_CLEAN)
 unset(RunCMake_TEST_BINARY_DIR)
 
+# cmake --install test
+block()
+  set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/cmake--install-build)
+  run_cmake_with_options(cmake--install
+    -DCMAKE_INSTALL_PREFIX=${RunCMake_TEST_BINARY_DIR}/install
+    -DCMAKE_CROSS_CONFIGS=all
+    -DCMAKE_DEFAULT_CONFIGS=Debug\\\\;Release
+    )
+  set(RunCMake_TEST_NO_CLEAN 1)
+  run_cmake_command(cmake--install-build ${CMAKE_COMMAND} --build .)
+  run_cmake_command(cmake--install-install ${CMAKE_COMMAND} --install .)
+endblock()
+
 # CudaSimple uses separable compilation, which is currently only supported on NVCC.
 if(CMake_TEST_CUDA)
   set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/CudaSimple-build)

+ 4 - 0
Tests/RunCMake/NinjaMultiConfig/cmake--install-install-check.cmake

@@ -0,0 +1,4 @@
+if (NOT EXISTS ${RunCMake_TEST_BINARY_DIR}/install/bin/Debug/exe${CMAKE_EXECUTABLE_SUFFIX} OR
+    NOT EXISTS ${RunCMake_TEST_BINARY_DIR}/install/bin/Release/exe${CMAKE_EXECUTABLE_SUFFIX})
+  set(RunCMake_TEST_FAILED "Multi-Config Install with CMAKE_DEFAULT_CONFIGS set did not install all specified configs by default")
+endif()

+ 1 - 0
Tests/RunCMake/NinjaMultiConfig/cmake--install.cmake

@@ -0,0 +1 @@
+include(${CMAKE_CURRENT_LIST_DIR}/Install.cmake)