Makefile: Tell GNU make to delete rule outputs on error (#15474)

Add .DELETE_ON_ERROR to the "build.make" files that contain the actual
build rules that generate files.  This tells GNU make to delete the
output of a rule if the recipe modifies the output but returns failure.
This is particularly useful for custom commands that use shell
redirection to produce a file.

Do not add .DELETE_ON_ERROR for Borland or Watcom make tools because
they may not tolerate it and would not honor it anyway.  Other make
tools that do not understand .DELETE_ON_ERROR will not be hurt.

Suggested-by: Andrey Vihrov <andrey.vihrov@gmail.com>
This commit is contained in:
Brad King 2015-03-30 16:32:26 -04:00
parent c1f8c6cdf9
commit 4adf1dad2a
4 changed files with 13 additions and 0 deletions

View File

@ -46,6 +46,7 @@ public:
cmMakefile *, bool optional); cmMakefile *, bool optional);
virtual bool AllowNotParallel() const { return false; } virtual bool AllowNotParallel() const { return false; }
virtual bool AllowDeleteOnError() const { return false; }
}; };
#endif #endif

View File

@ -128,6 +128,9 @@ public:
/** Does the make tool tolerate .NOTPARALLEL? */ /** Does the make tool tolerate .NOTPARALLEL? */
virtual bool AllowNotParallel() const { return true; } virtual bool AllowNotParallel() const { return true; }
/** Does the make tool tolerate .DELETE_ON_ERROR? */
virtual bool AllowDeleteOnError() const { return true; }
virtual void ComputeTargetObjectDirectory(cmGeneratorTarget* gt) const; virtual void ComputeTargetObjectDirectory(cmGeneratorTarget* gt) const;
protected: protected:
void WriteMainMakefile2(); void WriteMainMakefile2();

View File

@ -45,6 +45,7 @@ public:
cmMakefile *, bool optional); cmMakefile *, bool optional);
virtual bool AllowNotParallel() const { return false; } virtual bool AllowNotParallel() const { return false; }
virtual bool AllowDeleteOnError() const { return false; }
}; };
#endif #endif

View File

@ -122,6 +122,14 @@ void cmMakefileTargetGenerator::CreateRuleFile()
return; return;
} }
this->LocalGenerator->WriteDisclaimer(*this->BuildFileStream); this->LocalGenerator->WriteDisclaimer(*this->BuildFileStream);
if (this->GlobalGenerator->AllowDeleteOnError())
{
std::vector<std::string> no_depends;
std::vector<std::string> no_commands;
this->LocalGenerator->WriteMakeRule(
*this->BuildFileStream, "Delete rule output on recipe failure.",
".DELETE_ON_ERROR", no_depends, no_commands, false);
}
this->LocalGenerator->WriteSpecialTargetsTop(*this->BuildFileStream); this->LocalGenerator->WriteSpecialTargetsTop(*this->BuildFileStream);
} }