Browse Source

Makefiles: Process ADDTIONAL_CLEAN_FILES dir prop at directory level

In the "Unix Makefiles" generator, the `ADDTIONAL_CLEAN_FILES` directory
property was evaluated on a per target basis. This had two drawbacks:
- per directory clean files were repeated in every target clean script
- per directory clean files weren't removed in directories without targets
  (issue #8164)

This patch moves the `ADDTIONAL_CLEAN_FILES` directory property processing
from the target to the directory level clean target.

Fixes: #8164 "ADDITIONAL_CLEAN_FILES directory property not respected if no
              target present in directory"
Sebastian Holtermann 6 years ago
parent
commit
1ded3599d6

+ 9 - 5
Source/cmGlobalUnixMakefileGenerator3.cxx

@@ -398,7 +398,8 @@ void cmGlobalUnixMakefileGenerator3::WriteMainCMakefileLanguageRules(
 
 void cmGlobalUnixMakefileGenerator3::WriteDirectoryRule2(
   std::ostream& ruleFileStream, cmLocalUnixMakefileGenerator3* lg,
-  const char* pass, bool check_all, bool check_relink)
+  const char* pass, bool check_all, bool check_relink,
+  std::vector<std::string> const& commands)
 {
   // Get the relative path to the subdirectory from the top.
   std::string makeTarget = lg->GetCurrentBinaryDirectory();
@@ -454,9 +455,8 @@ void cmGlobalUnixMakefileGenerator3::WriteDirectoryRule2(
     doc += pass;
     doc += "\" directory target.";
   }
-  std::vector<std::string> no_commands;
-  lg->WriteMakeRule(ruleFileStream, doc.c_str(), makeTarget, depends,
-                    no_commands, true);
+  lg->WriteMakeRule(ruleFileStream, doc.c_str(), makeTarget, depends, commands,
+                    true);
 }
 
 void cmGlobalUnixMakefileGenerator3::WriteDirectoryRules2(
@@ -480,7 +480,11 @@ void cmGlobalUnixMakefileGenerator3::WriteDirectoryRules2(
   this->WriteDirectoryRule2(ruleFileStream, lg, "all", true, false);
 
   // Write directory-level rules for "clean".
-  this->WriteDirectoryRule2(ruleFileStream, lg, "clean", false, false);
+  {
+    std::vector<std::string> cmds;
+    lg->AppendDirectoryCleanCommand(cmds);
+    this->WriteDirectoryRule2(ruleFileStream, lg, "clean", false, false, cmds);
+  }
 
   // Write directory-level rules for "preinstall".
   this->WriteDirectoryRule2(ruleFileStream, lg, "preinstall", true, true);

+ 2 - 1
Source/cmGlobalUnixMakefileGenerator3.h

@@ -165,7 +165,8 @@ protected:
 
   void WriteDirectoryRule2(std::ostream& ruleFileStream,
                            cmLocalUnixMakefileGenerator3* lg, const char* pass,
-                           bool check_all, bool check_relink);
+                           bool check_all, bool check_relink,
+                           std::vector<std::string> const& commands = {});
   void WriteDirectoryRules2(std::ostream& ruleFileStream,
                             cmLocalUnixMakefileGenerator3* lg);
 

+ 51 - 0
Source/cmLocalUnixMakefileGenerator3.cxx

@@ -15,6 +15,7 @@
 #include "cmCustomCommandGenerator.h"
 #include "cmFileTimeCache.h"
 #include "cmGeneratedFileStream.h"
+#include "cmGeneratorExpression.h"
 #include "cmGeneratorTarget.h"
 #include "cmGlobalGenerator.h"
 #include "cmGlobalUnixMakefileGenerator3.h"
@@ -1089,6 +1090,56 @@ void cmLocalUnixMakefileGenerator3::AppendCleanCommand(
   }
 }
 
+void cmLocalUnixMakefileGenerator3::AppendDirectoryCleanCommand(
+  std::vector<std::string>& commands)
+{
+  std::vector<std::string> cleanFiles;
+  // Look for additional files registered for cleaning in this directory.
+  if (const char* prop_value =
+        this->Makefile->GetProperty("ADDITIONAL_CLEAN_FILES")) {
+    cmGeneratorExpression ge;
+    std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(prop_value);
+    cmSystemTools::ExpandListArgument(
+      cge->Evaluate(this,
+                    this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE")),
+      cleanFiles);
+  }
+  if (cleanFiles.empty()) {
+    return;
+  }
+
+  cmLocalGenerator* rootLG =
+    this->GetGlobalGenerator()->GetLocalGenerators().at(0);
+  std::string const& binaryDir = rootLG->GetCurrentBinaryDirectory();
+  std::string const& currentBinaryDir = this->GetCurrentBinaryDirectory();
+  std::string cleanfile = currentBinaryDir;
+  cleanfile += "/CMakeFiles/cmake_directory_clean.cmake";
+  // Write clean script
+  {
+    std::string cleanfilePath = cmSystemTools::CollapseFullPath(cleanfile);
+    cmsys::ofstream fout(cleanfilePath.c_str());
+    if (!fout) {
+      cmSystemTools::Error("Could not create " + cleanfilePath);
+      return;
+    }
+    fout << "file(REMOVE_RECURSE\n";
+    for (std::string const& cfl : cleanFiles) {
+      std::string fc = rootLG->MaybeConvertToRelativePath(
+        binaryDir, cmSystemTools::CollapseFullPath(cfl, currentBinaryDir));
+      fout << "  " << cmOutputConverter::EscapeForCMake(fc) << "\n";
+    }
+    fout << ")\n";
+  }
+  // Create command
+  {
+    std::string remove = "$(CMAKE_COMMAND) -P ";
+    remove += this->ConvertToOutputFormat(
+      rootLG->MaybeConvertToRelativePath(binaryDir, cleanfile),
+      cmOutputConverter::SHELL);
+    commands.push_back(std::move(remove));
+  }
+}
+
 void cmLocalUnixMakefileGenerator3::AppendEcho(
   std::vector<std::string>& commands, std::string const& text, EchoColor color,
   EchoProgress const* progress)

+ 1 - 0
Source/cmLocalUnixMakefileGenerator3.h

@@ -227,6 +227,7 @@ protected:
                           const std::set<std::string>& files,
                           cmGeneratorTarget* target,
                           const char* filename = nullptr);
+  void AppendDirectoryCleanCommand(std::vector<std::string>& commands);
 
   // Helper methods for dependency updates.
   bool ScanDependencies(std::string const& targetDir,

+ 0 - 12
Source/cmMakefileTargetGenerator.cxx

@@ -172,18 +172,6 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules()
     this->CleanFiles.insert(files.begin(), files.end());
   }
 
-  // Look for additional files registered for cleaning in this directory.
-  if (const char* prop_value =
-        this->Makefile->GetProperty("ADDITIONAL_CLEAN_FILES")) {
-    std::vector<std::string> const files = evaluatedFiles(prop_value);
-    // For relative path support
-    std::string const& binaryDir =
-      this->LocalGenerator->GetCurrentBinaryDirectory();
-    for (std::string const& cfl : files) {
-      this->CleanFiles.insert(cmSystemTools::CollapseFullPath(cfl, binaryDir));
-    }
-  }
-
   // Look for additional files registered for cleaning in this target.
   if (const char* prop_value =
         this->GeneratorTarget->GetProperty("ADDITIONAL_CLEAN_FILES")) {