浏览代码

Ninja: Add support for additional clean files

Additional clean files for the Ninja generator can be registered
via the new method `cmGlobalNinjaGenerator::AddAdditionalCleanFile`.
If there are additional clean files, a new rule `CLEAN_ADDITIONAL` and
a new build target `CMakeFiles/clean.additional` get generated.
The `clean` target will depend on `CMakeFiles/clean.additional`, if the target
exists.
Sebastian Holtermann 6 年之前
父节点
当前提交
7b23001f20
共有 2 个文件被更改,包括 104 次插入7 次删除
  1. 95 7
      Source/cmGlobalNinjaGenerator.cxx
  2. 9 0
      Source/cmGlobalNinjaGenerator.h

+ 95 - 7
Source/cmGlobalNinjaGenerator.cxx

@@ -852,6 +852,11 @@ std::string const& cmGlobalNinjaGenerator::ConvertToNinjaPath(
     .first->second;
 }
 
+void cmGlobalNinjaGenerator::AddAdditionalCleanFile(std::string fileName)
+{
+  this->AdditionalCleanFiles.emplace(std::move(fileName));
+}
+
 void cmGlobalNinjaGenerator::AddCXXCompileCommand(
   const std::string& commandLine, const std::string& sourceFile)
 {
@@ -1464,8 +1469,80 @@ bool cmGlobalNinjaGenerator::SupportsMultilineDepfile() const
   return this->NinjaSupportsMultilineDepfile;
 }
 
+bool cmGlobalNinjaGenerator::WriteTargetCleanAdditional(std::ostream& os)
+{
+  cmLocalGenerator* lgr = this->LocalGenerators.at(0);
+  std::string cleanScriptRel = "CMakeFiles/clean_additional.cmake";
+  std::string cleanScriptAbs = lgr->GetBinaryDirectory();
+  cleanScriptAbs += '/';
+  cleanScriptAbs += cleanScriptRel;
+
+  // Check if there are additional files to clean
+  if (this->AdditionalCleanFiles.empty()) {
+    // Remove cmake clean script file if it exists
+    cmSystemTools::RemoveFile(cleanScriptAbs);
+    return false;
+  }
+
+  // Write cmake clean script file
+  {
+    cmGeneratedFileStream fout(cleanScriptAbs);
+    if (!fout) {
+      return false;
+    }
+    fout << "# Additional clean files\n\n";
+    fout << "file(REMOVE_RECURSE\n";
+    for (std::string const& acf : this->AdditionalCleanFiles) {
+      fout << "  "
+           << cmOutputConverter::EscapeForCMake(ConvertToNinjaPath(acf))
+           << '\n';
+    }
+    fout << ")\n";
+  }
+  // Register clean script file
+  lgr->GetMakefile()->AddCMakeOutputFile(cleanScriptAbs);
+
+  // Write rule
+  {
+    std::string cmd = CMakeCmd();
+    cmd += " -P ";
+    cmd += lgr->ConvertToOutputFormat(this->NinjaOutputPath(cleanScriptRel),
+                                      cmOutputConverter::SHELL);
+    WriteRule(*this->RulesFileStream, "CLEAN_ADDITIONAL", cmd,
+              "Cleaning additional files...",
+              "Rule for cleaning additional files.",
+              /*depfile=*/"",
+              /*deptype=*/"",
+              /*rspfile=*/"",
+              /*rspcontent*/ "",
+              /*restat=*/"",
+              /*generator=*/false);
+  }
+
+  // Write build
+  {
+    cmNinjaDeps outputs;
+    outputs.emplace_back(
+      this->NinjaOutputPath(this->GetAdditionalCleanTargetName()));
+    WriteBuild(os, "Clean additional files.", "CLEAN_ADDITIONAL",
+               /*outputs=*/outputs,
+               /*implicitOuts=*/cmNinjaDeps(),
+               /*explicitDeps=*/cmNinjaDeps(),
+               /*implicitDeps=*/cmNinjaDeps(),
+               /*orderOnlyDeps=*/cmNinjaDeps(),
+               /*variables=*/cmNinjaVars());
+  }
+  // Return success
+  return true;
+}
+
 void cmGlobalNinjaGenerator::WriteTargetClean(std::ostream& os)
 {
+  // -- Additional clean target
+  bool additionalFiles = WriteTargetCleanAdditional(os);
+
+  // -- Default clean target
+  // Write rule
   WriteRule(*this->RulesFileStream, "CLEAN", NinjaCmd() + " -t clean",
             "Cleaning all built files...",
             "Rule for cleaning all built files.",
@@ -1475,13 +1552,24 @@ void cmGlobalNinjaGenerator::WriteTargetClean(std::ostream& os)
             /*rspcontent*/ "",
             /*restat=*/"",
             /*generator=*/false);
-  WriteBuild(os, "Clean all the built files.", "CLEAN",
-             /*outputs=*/cmNinjaDeps(1, this->NinjaOutputPath("clean")),
-             /*implicitOuts=*/cmNinjaDeps(),
-             /*explicitDeps=*/cmNinjaDeps(),
-             /*implicitDeps=*/cmNinjaDeps(),
-             /*orderOnlyDeps=*/cmNinjaDeps(),
-             /*variables=*/cmNinjaVars());
+
+  // Write build
+  {
+    cmNinjaDeps explicitDeps;
+    if (additionalFiles) {
+      explicitDeps.emplace_back(
+        this->NinjaOutputPath(this->GetAdditionalCleanTargetName()));
+    }
+    cmNinjaDeps outputs;
+    outputs.emplace_back(this->NinjaOutputPath(this->GetCleanTargetName()));
+    WriteBuild(os, "Clean all the built files.", "CLEAN",
+               /*outputs=*/outputs,
+               /*implicitOuts=*/cmNinjaDeps(),
+               /*explicitDeps=*/explicitDeps,
+               /*implicitDeps=*/cmNinjaDeps(),
+               /*orderOnlyDeps=*/cmNinjaDeps(),
+               /*variables=*/cmNinjaVars());
+  }
 }
 
 void cmGlobalNinjaGenerator::WriteTargetHelp(std::ostream& os)

+ 9 - 0
Source/cmGlobalNinjaGenerator.h

@@ -257,6 +257,13 @@ public:
   };
   MapToNinjaPathImpl MapToNinjaPath() { return MapToNinjaPathImpl(this); }
 
+  // -- Additional clean files
+  void AddAdditionalCleanFile(std::string fileName);
+  const char* GetAdditionalCleanTargetName() const
+  {
+    return "CMakeFiles/clean.additional";
+  }
+
   void AddCXXCompileCommand(const std::string& commandLine,
                             const std::string& sourceFile);
 
@@ -398,6 +405,7 @@ private:
   void WriteBuiltinTargets(std::ostream& os);
   void WriteTargetAll(std::ostream& os);
   void WriteTargetRebuildManifest(std::ostream& os);
+  bool WriteTargetCleanAdditional(std::ostream& os);
   void WriteTargetClean(std::ostream& os);
   void WriteTargetHelp(std::ostream& os);
 
@@ -470,6 +478,7 @@ private:
   std::string OutputPathPrefix;
   std::string TargetAll;
   std::string CMakeCacheFile;
+  std::set<std::string> AdditionalCleanFiles;
 };
 
 #endif // ! cmGlobalNinjaGenerator_h