ENH: Generalized driver targets and subdirectory traversal rules. The implementations of all, depend, build, clean, install, etc. now follow a common framework.

This commit is contained in:
Brad King 2004-11-03 11:02:44 -05:00
parent 30e685b41f
commit 7fdcb4e1e4
2 changed files with 150 additions and 82 deletions

View File

@ -124,11 +124,20 @@ void cmLocalUnixMakefileGenerator2::GenerateMakefile()
// Write special targets that belong at the top of the file. // Write special targets that belong at the top of the file.
this->WriteSpecialTargetsTop(makefileStream); this->WriteSpecialTargetsTop(makefileStream);
// Write the directory-level build rules. // Write rules to build dependencies and targets.
this->WriteAllRule(makefileStream); this->WriteAllRules(makefileStream);
// Write the subdirectory driver rules. // Write dependency generation rules.
this->WriteSubdirRules(makefileStream, "all"); this->WriteDependRules(makefileStream);
// Write main build rules.
this->WriteBuildRules(makefileStream);
// Write clean rules. TODO: CONTINUE HERE
//this->WriteCleanRules(makefileStream);
// TODO: Write install rules.
//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);
@ -835,72 +844,22 @@ cmLocalUnixMakefileGenerator2
<< "# Special targets provided by cmake.\n" << "# Special targets provided by cmake.\n"
<< "\n"; << "\n";
// Build command to run CMake to check if anything needs regenerating.
std::string cmakefileName = m_Makefile->GetStartOutputDirectory();
cmakefileName += "/" CMLUMG_MAKEFILE_NAME ".cmake";
std::string runRule =
"@$(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)";
runRule += " --check-build-system ";
runRule += this->ConvertToRelativeOutputPath(cmakefileName.c_str());
// Write the main entry point target. This must be the VERY first // Write the main entry point target. This must be the VERY first
// target so that make with no arguments will run it. The // target so that make with no arguments will run it.
// dependencies and commands generated for this rule must not depend
// on listfile contents because the build system check might
// regenerate the makefile but it might not get read again by make
// before the commands run.
{ {
// Just depend on the all target to drive the build.
std::vector<std::string> depends; std::vector<std::string> depends;
std::vector<std::string> commands; std::vector<std::string> no_commands;
// Check the build system in this directory. depends.push_back("all");
depends.push_back("cmake_check_build_system");
// Recursively build pre-order directories.
commands.push_back(this->GetRecursiveMakeCall("all.subdirs.pre", true));
// Recursively build dependencies.
commands.push_back(this->GetRecursiveMakeCall("all.depends", true));
// Recursively build targets.
commands.push_back(this->GetRecursiveMakeCall("all.build", true));
// Recursively build post-order directories.
commands.push_back(this->GetRecursiveMakeCall("all.subdirs.post", true));
// Write the rule. // Write the rule.
std::string preEcho = "Entering directory ";
preEcho += m_Makefile->GetStartOutputDirectory();
std::string postEcho = "Finished directory ";
postEcho += m_Makefile->GetStartOutputDirectory();
this->WriteMakeRule(makefileStream, this->WriteMakeRule(makefileStream,
"Default target executed when no arguments are " "Default target executed when no arguments are "
"given to make.", "given to make.",
preEcho.c_str(), 0,
"all", "default_target",
depends, depends,
commands, no_commands);
postEcho.c_str());
}
// Write special "cmake_check_build_system" target to run cmake with
// the --check-build-system flag.
{
std::vector<std::string> no_depends;
std::vector<std::string> commands;
commands.push_back(runRule);
std::string preEcho = "Checking build system in ";
preEcho += m_Makefile->GetStartOutputDirectory();
preEcho += "...";
this->WriteMakeRule(makefileStream,
"Special rule to run CMake to check the build system "
"integrity.\n"
"No rule that depends on this can have "
"commands that come from listfiles\n"
"because they might be regenerated.",
preEcho.c_str(),
"cmake_check_build_system",
no_depends,
commands);
} }
// Write special "rebuild_cache" target to re-run cmake. // Write special "rebuild_cache" target to re-run cmake.
@ -957,6 +916,35 @@ cmLocalUnixMakefileGenerator2
<< "# Special targets to cleanup operation of make.\n" << "# Special targets to cleanup operation of make.\n"
<< "\n"; << "\n";
// Write special "cmake_check_build_system" target to run cmake with
// the --check-build-system flag.
{
// Build command to run CMake to check if anything needs regenerating.
std::string cmakefileName = m_Makefile->GetStartOutputDirectory();
cmakefileName += "/" CMLUMG_MAKEFILE_NAME ".cmake";
std::string runRule =
"@$(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)";
runRule += " --check-build-system ";
runRule += this->ConvertToRelativeOutputPath(cmakefileName.c_str());
std::vector<std::string> no_depends;
std::vector<std::string> commands;
commands.push_back(runRule);
std::string preEcho = "Checking build system in ";
preEcho += m_Makefile->GetStartOutputDirectory();
preEcho += "...";
this->WriteMakeRule(makefileStream,
"Special rule to run CMake to check the build system "
"integrity.\n"
"No rule that depends on this can have "
"commands that come from listfiles\n"
"because they might be regenerated.",
preEcho.c_str(),
"cmake_check_build_system",
no_depends,
commands);
}
std::vector<std::string> no_commands; std::vector<std::string> no_commands;
// Write special target to silence make output. This must be after // Write special target to silence make output. This must be after
@ -988,18 +976,35 @@ cmLocalUnixMakefileGenerator2
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void void
cmLocalUnixMakefileGenerator2 cmLocalUnixMakefileGenerator2
::WriteAllRule(std::ostream& makefileStream) ::WriteAllRules(std::ostream& makefileStream)
{ {
// Write section header. // Write section header.
this->WriteDivider(makefileStream); this->WriteDivider(makefileStream);
makefileStream makefileStream
<< "# Main rules for this directory.\n" << "# Rules to build dependencies and targets.\n"
<< "\n"; << "\n";
const cmTargets& targets = m_Makefile->GetTargets(); // Write rules to traverse the directory tree building dependencies
// and targets.
this->WriteDriverRules(makefileStream, "all", "depend.local", "build.local");
}
// Output top level dependency rule. //----------------------------------------------------------------------------
void
cmLocalUnixMakefileGenerator2::WriteDependRules(std::ostream& makefileStream)
{ {
// Write section header.
this->WriteDivider(makefileStream);
makefileStream
<< "# Rules for computing dependencies.\n"
<< "\n";
// 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> depends;
std::vector<std::string> commands; std::vector<std::string> commands;
for(cmTargets::const_iterator t = targets.begin(); t != targets.end(); ++t) for(cmTargets::const_iterator t = targets.begin(); t != targets.end(); ++t)
@ -1029,15 +1034,29 @@ cmLocalUnixMakefileGenerator2
// Write the rule. // Write the rule.
this->WriteMakeRule(makefileStream, this->WriteMakeRule(makefileStream,
"Main dependencies target for this directory.", "Build dependencies for this directory.",
0, 0,
"all.depends", "depend.local",
depends, depends,
commands); commands);
} }
// Output top level build rule. //----------------------------------------------------------------------------
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> depends;
std::vector<std::string> commands; std::vector<std::string> commands;
for(cmTargets::const_iterator t = targets.begin(); t != targets.end(); ++t) for(cmTargets::const_iterator t = targets.begin(); t != targets.end(); ++t)
@ -1063,12 +1082,62 @@ cmLocalUnixMakefileGenerator2
// Write the rule. // Write the rule.
this->WriteMakeRule(makefileStream, this->WriteMakeRule(makefileStream,
"Main build target for this directory.", "Build targets in this directory.",
0, 0,
"all.build", "build.local",
depends, depends,
commands); commands);
} }
//----------------------------------------------------------------------------
void
cmLocalUnixMakefileGenerator2
::WriteDriverRules(std::ostream& makefileStream, const char* pass,
const char* local1, const char* local2)
{
// Write a set of targets that will traverse the directory structure
// in order and build given local targets in each directory.
// The dependencies and commands generated for this rule must not
// depend on listfile contents because the build system check might
// regenerate the makefile but it might not get read again by make
// before the commands run.
std::vector<std::string> depends;
std::vector<std::string> commands;
// Check the build system in this directory.
depends.push_back("cmake_check_build_system");
// Recursively handle pre-order directories.
std::string preTarget = pass;
preTarget += ".pre-order";
commands.push_back(this->GetRecursiveMakeCall(preTarget.c_str(), true));
// Recursively build the local targets in this directory.
if(local1)
{
commands.push_back(this->GetRecursiveMakeCall(local1, true));
}
if(local2)
{
commands.push_back(this->GetRecursiveMakeCall(local2, true));
}
// Recursively handle post-order directories.
std::string postTarget = pass;
postTarget += ".post-order";
commands.push_back(this->GetRecursiveMakeCall(postTarget.c_str(), true));
// Write the rule.
std::string preEcho = "Entering directory ";
preEcho += m_Makefile->GetStartOutputDirectory();
std::string postEcho = "Finished directory ";
postEcho += m_Makefile->GetStartOutputDirectory();
this->WriteMakeRule(makefileStream, 0, preEcho.c_str(),
pass, depends, commands, postEcho.c_str());
// Write the subdirectory traversal rules.
this->WriteSubdirRules(makefileStream, pass);
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@ -1076,12 +1145,6 @@ void
cmLocalUnixMakefileGenerator2 cmLocalUnixMakefileGenerator2
::WriteSubdirRules(std::ostream& makefileStream, const char* pass) ::WriteSubdirRules(std::ostream& makefileStream, const char* pass)
{ {
// Write the section header.
this->WriteDivider(makefileStream);
makefileStream
<< "# Subdirectory driver targets for " << pass << "\n"
<< "\n";
// Iterate through subdirectories. Only entries in which the // Iterate through subdirectories. Only entries in which the
// boolean is true should be included. Keep track of the last // boolean is true should be included. Keep track of the last
// pre-order and last post-order rule created so that ordering can // pre-order and last post-order rule created so that ordering can
@ -1213,8 +1276,9 @@ cmLocalUnixMakefileGenerator2
// Build the make target name. // Build the make target name.
std::string tgt = pass; std::string tgt = pass;
tgt += ".subdirs."; tgt += ".";
tgt += order; tgt += order;
tgt += "-order";
// Write the rule. // Write the rule.
this->WriteMakeRule(makefileStream, comment.c_str(), 0, this->WriteMakeRule(makefileStream, comment.c_str(), 0,

View File

@ -81,7 +81,11 @@ protected:
void WriteSpecialTargetsTop(std::ostream& makefileStream); void WriteSpecialTargetsTop(std::ostream& makefileStream);
void WriteSpecialTargetsBottom(std::ostream& makefileStream); void WriteSpecialTargetsBottom(std::ostream& makefileStream);
void WriteRuleFileIncludes(std::ostream& makefileStream); void WriteRuleFileIncludes(std::ostream& makefileStream);
void WriteAllRule(std::ostream& makefileStream); void WriteAllRules(std::ostream& makefileStream);
void WriteDependRules(std::ostream& makefileStream);
void WriteBuildRules(std::ostream& makefileStream);
void WriteDriverRules(std::ostream& makefileStream, const char* pass,
const char* local1, const char* local2=0);
void WriteSubdirRules(std::ostream& makefileStream, const char* pass); void WriteSubdirRules(std::ostream& makefileStream, const char* pass);
void WriteSubdirRule(std::ostream& makefileStream, const char* pass, void WriteSubdirRule(std::ostream& makefileStream, const char* pass,
const char* subdir, std::string& last); const char* subdir, std::string& last);