ENH: Unified WriteDependRules, WriteBuildRules, WriteCleanRules, and the future WriteInstallRules into a single WritePassRules method. Also added WriteTargetDependsRule and WriteTargetCleanRule methods to unify writing of depend and clean rules for each target.

This commit is contained in:
Brad King 2004-11-19 09:32:18 -05:00
parent e32928aaff
commit 4352c2faae
2 changed files with 161 additions and 195 deletions

View File

@ -24,13 +24,16 @@
#include <queue> #include <queue>
// Quick-switch for generating old makefiles. // Quick-switch for generating old makefiles.
#if 0 #if 1
# define CMLUMG_MAKEFILE_NAME "Makefile" # define CMLUMG_MAKEFILE_NAME "Makefile"
#else #else
# define CMLUMG_WRITE_OLD_MAKEFILE # define CMLUMG_WRITE_OLD_MAKEFILE
# define CMLUMG_MAKEFILE_NAME "Makefile2" # define CMLUMG_MAKEFILE_NAME "Makefile2"
#endif #endif
// TODO: Add "help" target.
// TODO: Add install targets to m_InstallTargets list.
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
cmLocalUnixMakefileGenerator2::cmLocalUnixMakefileGenerator2() cmLocalUnixMakefileGenerator2::cmLocalUnixMakefileGenerator2()
{ {
@ -130,16 +133,24 @@ void cmLocalUnixMakefileGenerator2::GenerateMakefile()
this->WriteAllRules(makefileStream); this->WriteAllRules(makefileStream);
// Write dependency generation rules. // Write dependency generation rules.
this->WriteDependRules(makefileStream); this->WritePassRules(makefileStream, "depend",
"Build dependencies for this directory.",
m_DependTargets);
// Write main build rules. // Write main build rules.
this->WriteBuildRules(makefileStream); this->WritePassRules(makefileStream, "build",
"Build targets in this directory.",
m_BuildTargets);
// Write install rules.
this->WritePassRules(makefileStream, "install",
"Install files from this directory.",
m_InstallTargets);
// Write clean rules. // Write clean rules.
this->WriteCleanRules(makefileStream); this->WritePassRules(makefileStream, "clean",
"Clean targets in this directory.",
// TODO: Write install rules. m_CleanTargets);
//this->WriteInstallRules(makefileStream);
// Write include statements to get rules for this directory. // Write include statements to get rules for this directory.
this->WriteRuleFileIncludes(makefileStream); this->WriteRuleFileIncludes(makefileStream);
@ -299,28 +310,7 @@ cmLocalUnixMakefileGenerator2
<< "\n"; << "\n";
} }
// Write the dependency generation rule. // Write the rule for this target type.
{
std::vector<std::string> depends;
std::vector<std::string> no_commands;
std::string depEcho = "Building dependencies for ";
depEcho += target.GetName();
depEcho += "...";
std::string depTarget = dir;
depTarget += "/";
depTarget += target.GetName();
depTarget += ".depends";
for(std::vector<std::string>::const_iterator obj = objects.begin();
obj != objects.end(); ++obj)
{
depends.push_back((*obj)+".depends");
}
depends.push_back(ruleFileName);
this->WriteMakeRule(ruleFileStream, 0, depEcho.c_str(),
depTarget.c_str(), depends, no_commands);
}
// Write the build rule.
switch(target.GetType()) switch(target.GetType())
{ {
case cmTarget::STATIC_LIBRARY: case cmTarget::STATIC_LIBRARY:
@ -1002,157 +992,33 @@ cmLocalUnixMakefileGenerator2
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void void
cmLocalUnixMakefileGenerator2::WriteDependRules(std::ostream& makefileStream) cmLocalUnixMakefileGenerator2
::WritePassRules(std::ostream& makefileStream,
const char* pass,
const char* comment,
const std::vector<std::string>& depends)
{ {
// Write section header. // Write section header.
this->WriteDivider(makefileStream); this->WriteDivider(makefileStream);
makefileStream makefileStream
<< "# Rules for computing dependencies.\n" << "# Rules for the " << pass << " pass.\n"
<< "\n"; << "\n";
// TODO: Unify WriteDependRules, WriteBuildRules, WriteCleanRules, // Write rules to traverse the directory tree for this pass.
// etc. They are mostly duplicate code. std::string passLocal = pass;
passLocal += ".local";
// TODO: Add registered files for cleaning. this->WriteDriverRules(makefileStream, pass, passLocal.c_str());
// Write rules to traverse the directory tree building dependencies.
this->WriteDriverRules(makefileStream, "depend", "depend.local");
// Write the rule to build dependencies in this directory. It just
// depends on all targets' dependencies.
const cmTargets& targets = m_Makefile->GetTargets();
std::vector<std::string> depends;
std::vector<std::string> commands;
for(cmTargets::const_iterator t = targets.begin(); t != targets.end(); ++t)
{
// TODO: Dispatch generation of each target type.
if((t->second.GetType() == cmTarget::EXECUTABLE) ||
(t->second.GetType() == cmTarget::STATIC_LIBRARY) ||
(t->second.GetType() == cmTarget::SHARED_LIBRARY) ||
(t->second.GetType() == cmTarget::MODULE_LIBRARY))
{
if(t->second.IsInAll())
{
std::string dep = this->GetTargetDirectory(t->second);
dep += "/";
dep += t->first;
dep += ".depends";
depends.push_back(dep);
}
}
}
// If there are no dependencies, use empty commands. // If there are no dependencies, use empty commands.
std::vector<std::string> commands;
if(depends.empty()) if(depends.empty())
{ {
commands = m_EmptyCommands; commands = m_EmptyCommands;
} }
// Write the rule. // Write the rule.
this->WriteMakeRule(makefileStream, this->WriteMakeRule(makefileStream, comment, 0, passLocal.c_str(),
"Build dependencies for this directory.", depends, commands);
0,
"depend.local",
depends,
commands);
}
//----------------------------------------------------------------------------
void
cmLocalUnixMakefileGenerator2::WriteBuildRules(std::ostream& makefileStream)
{
// Write section header.
this->WriteDivider(makefileStream);
makefileStream
<< "# Rules for building targets.\n"
<< "\n";
// Write rules to traverse the directory tree building targets.
this->WriteDriverRules(makefileStream, "build", "build.local");
// Write the rule to build targets in this directory. It just
// depends on all targets.
const cmTargets& targets = m_Makefile->GetTargets();
std::vector<std::string> depends;
std::vector<std::string> commands;
for(cmTargets::const_iterator t = targets.begin(); t != targets.end(); ++t)
{
// TODO: Dispatch generation of each target type.
if((t->second.GetType() == cmTarget::EXECUTABLE) ||
(t->second.GetType() == cmTarget::STATIC_LIBRARY) ||
(t->second.GetType() == cmTarget::SHARED_LIBRARY) ||
(t->second.GetType() == cmTarget::MODULE_LIBRARY))
{
if(t->second.IsInAll())
{
depends.push_back(t->first);
}
}
}
// If there are no dependencies, use empty commands.
if(depends.empty())
{
commands = m_EmptyCommands;
}
// Write the rule.
this->WriteMakeRule(makefileStream,
"Build targets in this directory.",
0,
"build.local",
depends,
commands);
}
//----------------------------------------------------------------------------
void
cmLocalUnixMakefileGenerator2::WriteCleanRules(std::ostream& makefileStream)
{
// Write section header.
this->WriteDivider(makefileStream);
makefileStream
<< "# Rules for cleaning targets.\n"
<< "\n";
// Write rules to traverse the directory tree cleaning targets.
this->WriteDriverRules(makefileStream, "clean", "clean.local");
// Write the rule to clean targets in this directory. It just
// depends on all targets' clean rules.
const cmTargets& targets = m_Makefile->GetTargets();
std::vector<std::string> depends;
std::vector<std::string> commands;
for(cmTargets::const_iterator t = targets.begin(); t != targets.end(); ++t)
{
// TODO: Dispatch generation of each target type.
if((t->second.GetType() == cmTarget::EXECUTABLE) ||
(t->second.GetType() == cmTarget::STATIC_LIBRARY) ||
(t->second.GetType() == cmTarget::SHARED_LIBRARY) ||
(t->second.GetType() == cmTarget::MODULE_LIBRARY))
{
if(t->second.IsInAll())
{
std::string clean = t->first;
clean += ".clean";
depends.push_back(clean);
}
}
}
// If there are no dependencies, use empty commands.
if(depends.empty())
{
commands = m_EmptyCommands;
}
// Write the rule.
this->WriteMakeRule(makefileStream,
"Clean targets in this directory.",
0,
"clean.local",
depends,
commands);
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@ -1336,9 +1202,9 @@ cmLocalUnixMakefileGenerator2
// Build comment to describe purpose. // Build comment to describe purpose.
std::string comment = "Driver target for "; std::string comment = "Driver target for ";
comment += order; comment += order;
comment += "-order subdirectories during "; comment += "-order subdirectories during the ";
comment += pass; comment += pass;
comment += "."; comment += " pass.";
// Build the make target name. // Build the make target name.
std::string tgt = pass; std::string tgt = pass;
@ -1431,6 +1297,9 @@ cmLocalUnixMakefileGenerator2
const cmTarget& target, const cmTarget& target,
std::vector<std::string>& objects) std::vector<std::string>& objects)
{ {
// Write the dependency generation rule.
this->WriteTargetDependsRule(ruleFileStream, ruleFileName, target, objects);
std::vector<std::string> commands; std::vector<std::string> commands;
// Build list of dependencies. // Build list of dependencies.
@ -1554,19 +1423,17 @@ cmLocalUnixMakefileGenerator2
// Write convenience targets. // Write convenience targets.
this->WriteConvenienceRules(ruleFileStream, target, targetFullPath.c_str()); this->WriteConvenienceRules(ruleFileStream, target, targetFullPath.c_str());
// Write clean target. TODO: Unify with all target and object file // Write clean target.
// cleaning rules. std::vector<std::string> cleanFiles;
std::string remove = "$(CMAKE_COMMAND) -E remove -f "; cleanFiles.push_back(this->ConvertToRelativeOutputPath(targetFullPath.c_str()));
remove += this->ConvertToRelativeOutputPath(targetFullPath.c_str()); cleanFiles.push_back(objs);
remove += " "; this->WriteTargetCleanRule(ruleFileStream, target, cleanFiles);
remove += objs;
std::string cleanTarget = target.GetName(); // Add this to the list of build rules in this directory.
cleanTarget += ".clean"; if(target.IsInAll())
commands.clear(); {
depends.clear(); m_BuildTargets.push_back(target.GetName());
commands.push_back(remove); }
this->WriteMakeRule(ruleFileStream, 0, 0, cleanTarget.c_str(),
depends, commands);
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@ -1656,6 +1523,9 @@ cmLocalUnixMakefileGenerator2
const char* linkRuleVar, const char* linkRuleVar,
const char* extraFlags) const char* extraFlags)
{ {
// Write the dependency generation rule.
this->WriteTargetDependsRule(ruleFileStream, ruleFileName, target, objects);
// TODO: Merge the methods that call this method to avoid // TODO: Merge the methods that call this method to avoid
// code duplication. // code duplication.
std::vector<std::string> commands; std::vector<std::string> commands;
@ -1725,18 +1595,22 @@ cmLocalUnixMakefileGenerator2
} }
// Add a command to remove any existing files for this library. // Add a command to remove any existing files for this library.
std::vector<std::string> cleanFiles;
std::string remove = "$(CMAKE_COMMAND) -E remove -f "; std::string remove = "$(CMAKE_COMMAND) -E remove -f ";
remove += targetFullPathReal; remove += targetFullPathReal;
cleanFiles.push_back(targetFullPathReal);
if(targetFullPathSO != targetFullPathReal) if(targetFullPathSO != targetFullPathReal)
{ {
remove += " "; remove += " ";
remove += targetFullPathSO; remove += targetFullPathSO;
cleanFiles.push_back(targetFullPathSO);
} }
if(targetFullPath != targetFullPathSO && if(targetFullPath != targetFullPathSO &&
targetFullPath != targetFullPathReal) targetFullPath != targetFullPathReal)
{ {
remove += " "; remove += " ";
remove += targetFullPath; remove += targetFullPath;
cleanFiles.push_back(targetFullPath);
} }
commands.push_back(remove); commands.push_back(remove);
@ -1811,17 +1685,15 @@ cmLocalUnixMakefileGenerator2
// Write convenience targets. // Write convenience targets.
this->WriteConvenienceRules(ruleFileStream, target, targetFullPath.c_str()); this->WriteConvenienceRules(ruleFileStream, target, targetFullPath.c_str());
// Write clean target. TODO: Unify with all target and object file // Write clean target.
// cleaning rules. cleanFiles.push_back(objs);
std::string cleanTarget = target.GetName(); this->WriteTargetCleanRule(ruleFileStream, target, cleanFiles);
cleanTarget += ".clean";
commands.clear(); // Add this to the list of build rules in this directory.
depends.clear(); if(target.IsInAll())
remove += " "; {
remove += objs; m_BuildTargets.push_back(target.GetName());
commands.push_back(remove); }
this->WriteMakeRule(ruleFileStream, 0, 0, cleanTarget.c_str(),
depends, commands);
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@ -1862,6 +1734,86 @@ cmLocalUnixMakefileGenerator2
<< "\n"; << "\n";
} }
//----------------------------------------------------------------------------
void
cmLocalUnixMakefileGenerator2
::WriteTargetDependsRule(std::ostream& ruleFileStream,
const char* ruleFileName,
const cmTarget& target,
const std::vector<std::string>& objects)
{
std::vector<std::string> depends;
std::vector<std::string> no_commands;
// Construct the output message for the rule.
std::string depEcho = "Building dependencies for ";
depEcho += target.GetName();
depEcho += "...";
// Construct the name of the dependency generation target.
std::string depTarget = this->GetTargetDirectory(target);
depTarget += "/";
depTarget += target.GetName();
depTarget += ".depends";
// This target drives dependency generation for all object files.
for(std::vector<std::string>::const_iterator obj = objects.begin();
obj != objects.end(); ++obj)
{
depends.push_back((*obj)+".depends");
}
// Depend on the rule file itself.
depends.push_back(ruleFileName);
// Write the rule.
this->WriteMakeRule(ruleFileStream, 0, depEcho.c_str(),
depTarget.c_str(), depends, no_commands);
// Add this to the list of depend rules in this directory.
if(target.IsInAll())
{
m_DependTargets.push_back(depTarget);
}
}
//----------------------------------------------------------------------------
void
cmLocalUnixMakefileGenerator2
::WriteTargetCleanRule(std::ostream& ruleFileStream,
const cmTarget& target,
const std::vector<std::string>& files)
{
std::vector<std::string> no_depends;
std::vector<std::string> commands;
// TODO: Add registered files for cleaning.
// Construct the clean target name.
std::string cleanTarget = target.GetName();
cleanTarget += ".clean";
// Construct the clean command.
std::string remove = "$(CMAKE_COMMAND) -E remove -f";
for(std::vector<std::string>::const_iterator f = files.begin();
f != files.end(); ++f)
{
remove += " ";
remove += *f;
}
commands.push_back(remove);
// Write the rule.
this->WriteMakeRule(ruleFileStream, 0, 0, cleanTarget.c_str(),
no_depends, commands);
// Add this to the list of clean rules in this directory.
if(target.IsInAll())
{
m_CleanTargets.push_back(cleanTarget);
}
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
std::string std::string
cmLocalUnixMakefileGenerator2 cmLocalUnixMakefileGenerator2

View File

@ -82,9 +82,9 @@ protected:
void WriteSpecialTargetsBottom(std::ostream& makefileStream); void WriteSpecialTargetsBottom(std::ostream& makefileStream);
void WriteRuleFileIncludes(std::ostream& makefileStream); void WriteRuleFileIncludes(std::ostream& makefileStream);
void WriteAllRules(std::ostream& makefileStream); void WriteAllRules(std::ostream& makefileStream);
void WriteDependRules(std::ostream& makefileStream); void WritePassRules(std::ostream& makefileStream,
void WriteBuildRules(std::ostream& makefileStream); const char* pass, const char* comment,
void WriteCleanRules(std::ostream& makefileStream); const std::vector<std::string>& depends);
void WriteDriverRules(std::ostream& makefileStream, const char* pass, void WriteDriverRules(std::ostream& makefileStream, const char* pass,
const char* local1, const char* local2=0); const char* local1, const char* local2=0);
void WriteSubdirRules(std::ostream& makefileStream, const char* pass); void WriteSubdirRules(std::ostream& makefileStream, const char* pass);
@ -123,6 +123,13 @@ protected:
void WriteObjectsVariable(std::ostream& ruleFileStream, void WriteObjectsVariable(std::ostream& ruleFileStream,
const cmTarget& target, const cmTarget& target,
std::vector<std::string>& objects); std::vector<std::string>& objects);
void WriteTargetDependsRule(std::ostream& ruleFileStream,
const char* ruleFileName,
const cmTarget& target,
const std::vector<std::string>& objects);
void WriteTargetCleanRule(std::ostream& ruleFileStream,
const cmTarget& target,
const std::vector<std::string>& files);
std::string GetTargetDirectory(const cmTarget& target); std::string GetTargetDirectory(const cmTarget& target);
std::string GetSubdirTargetName(const char* pass, const char* subdir); std::string GetSubdirTargetName(const char* pass, const char* subdir);
std::string GetObjectFileName(const cmTarget& target, std::string GetObjectFileName(const cmTarget& target,
@ -168,6 +175,13 @@ private:
// Set of custom rule files that have been generated. // Set of custom rule files that have been generated.
std::set<cmStdString> m_CustomRuleFiles; std::set<cmStdString> m_CustomRuleFiles;
// List of target-level rules for each pass. These are populated by
// target rule file writing methods.
std::vector<std::string> m_DependTargets;
std::vector<std::string> m_BuildTargets;
std::vector<std::string> m_InstallTargets;
std::vector<std::string> m_CleanTargets;
}; };
#endif #endif