summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Source/cmGlobalUnixMakefileGenerator3.cxx284
-rw-r--r--Source/cmGlobalUnixMakefileGenerator3.h37
-rw-r--r--Source/cmLocalUnixMakefileGenerator3.cxx8
3 files changed, 309 insertions, 20 deletions
diff --git a/Source/cmGlobalUnixMakefileGenerator3.cxx b/Source/cmGlobalUnixMakefileGenerator3.cxx
index f00af8d..eedf4da 100644
--- a/Source/cmGlobalUnixMakefileGenerator3.cxx
+++ b/Source/cmGlobalUnixMakefileGenerator3.cxx
@@ -98,6 +98,7 @@ void cmGlobalUnixMakefileGenerator3::Generate()
// write the main makefile
this->WriteMainMakefile();
+ this->WriteMainMakefile2();
this->WriteMainCMakefile();
}
@@ -168,6 +169,73 @@ void cmGlobalUnixMakefileGenerator3::WriteMainMakefile()
lg->WriteSpecialTargetsBottom(makefileStream);
}
+void cmGlobalUnixMakefileGenerator3::WriteMainMakefile2()
+{
+ // Open the output file. This should not be copy-if-different
+ // because the check-build-system step compares the makefile time to
+ // see if the build system must be regenerated.
+ std::string makefileName =
+ this->GetCMakeInstance()->GetHomeOutputDirectory();
+ makefileName += "/Makefile2";
+ cmGeneratedFileStream makefileStream(makefileName.c_str());
+ if(!makefileStream)
+ {
+ return;
+ }
+
+ // get a local generator for some useful methods
+ cmLocalUnixMakefileGenerator3 *lg =
+ static_cast<cmLocalUnixMakefileGenerator3 *>(m_LocalGenerators[0]);
+
+ // Write the do not edit header.
+ lg->WriteDisclaimer(makefileStream);
+
+ // Write the main entry point target. This must be the VERY first
+ // target so that make with no arguments will run it.
+ // Just depend on the all target to drive the build.
+ std::vector<std::string> depends;
+ std::vector<std::string> no_commands;
+ depends.push_back("all");
+
+ // Write the rule.
+ lg->WriteMakeRule(makefileStream,
+ "Default target executed when no arguments are "
+ "given to make.",
+ "default_target",
+ depends,
+ no_commands);
+
+ // Write and empty all:
+ lg->WriteMakeRule(makefileStream,
+ "The main recursive all target", "all",
+ no_commands, no_commands);
+
+ lg->WriteMakeVariables(makefileStream);
+
+ // write the target convenience rules
+ unsigned int i;
+ for (i = 0; i < m_LocalGenerators.size(); ++i)
+ {
+ lg = static_cast<cmLocalUnixMakefileGenerator3 *>(m_LocalGenerators[i]);
+ // are any parents excluded
+ bool exclude = false;
+ cmLocalGenerator *lg3 = lg;
+ while (lg3)
+ {
+ if (lg3->GetExcludeAll())
+ {
+ exclude = true;
+ break;
+ }
+ lg3 = lg3->GetParent();
+ }
+ this->WriteConvenienceRules2(makefileStream,lg,exclude);
+ }
+
+ lg = static_cast<cmLocalUnixMakefileGenerator3 *>(m_LocalGenerators[0]);
+ lg->WriteSpecialTargetsBottom(makefileStream);
+}
+
//----------------------------------------------------------------------------
void cmGlobalUnixMakefileGenerator3::WriteMainCMakefile()
@@ -340,20 +408,17 @@ void cmGlobalUnixMakefileGenerator3
// Check the build system in this directory.
depends.push_back("cmake_check_build_system");
-
- commands.push_back(lg->GetRecursiveMakeCall("Makefile","all/all"));
+ commands.push_back(lg->GetRecursiveMakeCall("Makefile2","all"));
// Write the rule.
lg->WriteMakeRule(makefileStream, "The main all target", "all", depends, commands);
- // Write and empty all/all:
- commands.clear();
- lg->WriteMakeRule(makefileStream, "The main recursive all target", "all/all",
- commands, commands);
-
// write the clean
+ depends.clear();
+ commands.clear();
+ commands.push_back(lg->GetRecursiveMakeCall("Makefile2","clean"));
lg->WriteMakeRule(makefileStream, "The main clean target", "clean",
- commands, commands);
+ depends, commands);
}
@@ -425,7 +490,137 @@ cmGlobalUnixMakefileGenerator3
// write the directory rule
commands.clear();
commands.push_back
- (lg->GetRecursiveMakeCall("Makefile",makeTargetName.c_str()));
+ (lg->GetRecursiveMakeCall("Makefile2",makeTargetName.c_str()));
+
+ // Write the rule.
+ lg->WriteMakeRule(ruleFileStream, "Convenience name for directory.",
+ localName.c_str(), depends, commands);
+
+ // Write the rule.
+ commands.clear();
+ lg->WriteMakeRule(ruleFileStream, "Convenience name for directory.",
+ makeTargetName.c_str(), all_tgts, commands);
+ }
+
+ // now do the clean targets
+ if (lg->GetParent())
+ {
+ std::string dir = lg->GetMakefile()->GetStartOutputDirectory();
+ dir = lg->Convert(dir.c_str(),cmLocalGenerator::HOME_OUTPUT,cmLocalGenerator::MAKEFILE);
+ makeTargetName = dir;
+ makeTargetName += "/clean";
+
+ std::vector<std::string> all_tgts;
+
+ // for all of out targets
+ for (cmTargets::const_iterator l = lg->GetMakefile()->GetTargets().begin();
+ l != lg->GetMakefile()->GetTargets().end(); l++)
+ {
+ if((l->second.GetType() == cmTarget::EXECUTABLE) ||
+ (l->second.GetType() == cmTarget::STATIC_LIBRARY) ||
+ (l->second.GetType() == cmTarget::SHARED_LIBRARY) ||
+ (l->second.GetType() == cmTarget::MODULE_LIBRARY) ||
+ (l->second.GetType() == cmTarget::UTILITY))
+ {
+ // Add this to the list of depends rules in this directory.
+ std::string tname = lg->GetRelativeTargetDirectory(l->second);
+ tname += "/clean";
+ all_tgts.push_back(tname);
+ }
+ }
+
+ // write the directory rule add in the subdirs
+ std::vector<cmLocalGenerator *> subdirs = lg->GetChildren();
+
+ // for each subdir add the directory depend
+ std::vector<cmLocalGenerator *>::iterator sdi = subdirs.begin();
+ for (; sdi != subdirs.end(); ++sdi)
+ {
+ cmLocalUnixMakefileGenerator3 * lg2 =
+ static_cast<cmLocalUnixMakefileGenerator3 *>(*sdi);
+ dir = lg2->GetMakefile()->GetStartOutputDirectory();
+ dir += "/clean";
+ dir = lg2->Convert(dir.c_str(),cmLocalGenerator::HOME_OUTPUT,
+ cmLocalGenerator::MAKEFILE);
+ all_tgts.push_back(dir);
+ }
+
+ // write the directory clean rule
+ commands.clear();
+ lg->WriteMakeRule(ruleFileStream, "Convenience name for directory clean.",
+ makeTargetName.c_str(), all_tgts, commands);
+ }
+}
+
+//----------------------------------------------------------------------------
+void
+cmGlobalUnixMakefileGenerator3
+::WriteDirectoryRules2(std::ostream& ruleFileStream,
+ cmLocalUnixMakefileGenerator3 *lg)
+{
+ std::vector<std::string> depends;
+ std::vector<std::string> commands;
+ std::string localName;
+ std::string makeTargetName;
+
+ depends.push_back("cmake_check_build_system");
+ if (lg->GetParent())
+ {
+ std::string dir = lg->GetMakefile()->GetStartOutputDirectory();
+ dir = lg->Convert(dir.c_str(),cmLocalGenerator::HOME_OUTPUT,cmLocalGenerator::MAKEFILE);
+
+ lg->WriteDivider(ruleFileStream);
+ ruleFileStream
+ << "# Directory level rules for directory "
+ << dir << "\n\n";
+
+ localName = dir;
+ localName += "/directorystart";
+ makeTargetName = dir;
+ makeTargetName += "/directory";
+
+ std::vector<std::string> all_tgts;
+
+ // for all of out targets
+ for (cmTargets::const_iterator l = lg->GetMakefile()->GetTargets().begin();
+ l != lg->GetMakefile()->GetTargets().end(); l++)
+ {
+ if((l->second.GetType() == cmTarget::EXECUTABLE) ||
+ (l->second.GetType() == cmTarget::STATIC_LIBRARY) ||
+ (l->second.GetType() == cmTarget::SHARED_LIBRARY) ||
+ (l->second.GetType() == cmTarget::MODULE_LIBRARY) ||
+ (l->second.GetType() == cmTarget::UTILITY))
+ {
+ // Add this to the list of depends rules in this directory.
+ if(l->second.IsInAll())
+ {
+ std::string tname = lg->GetRelativeTargetDirectory(l->second);
+ tname += "/all";
+ all_tgts.push_back(tname);
+ }
+ }
+ }
+
+ // write the directory rule add in the subdirs
+ std::vector<cmLocalGenerator *> subdirs = lg->GetChildren();
+
+ // for each subdir add the directory depend
+ std::vector<cmLocalGenerator *>::iterator sdi = subdirs.begin();
+ for (; sdi != subdirs.end(); ++sdi)
+ {
+ cmLocalUnixMakefileGenerator3 * lg2 =
+ static_cast<cmLocalUnixMakefileGenerator3 *>(*sdi);
+ dir = lg2->GetMakefile()->GetStartOutputDirectory();
+ dir += "/directory";
+ dir = lg2->Convert(dir.c_str(),cmLocalGenerator::HOME_OUTPUT,
+ cmLocalGenerator::MAKEFILE);
+ all_tgts.push_back(dir);
+ }
+
+ // write the directory rule
+ commands.clear();
+ commands.push_back
+ (lg->GetRecursiveMakeCall("Makefile2",makeTargetName.c_str()));
// Write the rule.
lg->WriteMakeRule(ruleFileStream, "Convenience name for directory.",
@@ -494,13 +689,69 @@ cmGlobalUnixMakefileGenerator3
cmLocalUnixMakefileGenerator3 *lg,
bool exclude)
{
+ // Keep track of targets already listed.
+ std::set<cmStdString> emitted;
+
+ std::vector<std::string> depends;
+ std::vector<std::string> commands;
+ std::string localName;
+ std::string makeTargetName;
+
+ // write the directory level rules for this local gen
+ //this->WriteDirectoryRules(ruleFileStream,lg);
+
+ depends.push_back("cmake_check_build_system");
+
+ // for each target Generate the rule files for each target.
+ const cmTargets& targets = lg->GetMakefile()->GetTargets();
+ bool needRequiresStep = this->NeedRequiresStep(lg);
+ for(cmTargets::const_iterator t = targets.begin(); t != targets.end(); ++t)
+ {
+ if((t->second.GetType() == cmTarget::EXECUTABLE) ||
+ (t->second.GetType() == cmTarget::STATIC_LIBRARY) ||
+ (t->second.GetType() == cmTarget::SHARED_LIBRARY) ||
+ (t->second.GetType() == cmTarget::MODULE_LIBRARY) ||
+ (t->second.GetType() == cmTarget::UTILITY))
+ {
+ // Don't emit the same rule twice (e.g. two targets with the same
+ // simple name)
+ if(emitted.insert(t->second.GetName()).second)
+ {
+ // Add a rule to build the target by name.
+ lg->WriteDivider(ruleFileStream);
+ ruleFileStream
+ << "# Target rules for targets named "
+ << t->second.GetName() << "\n\n";
+
+ // Write the rule.
+ commands.clear();
+ commands.push_back(lg->GetRecursiveMakeCall("Makefile2",
+ t->second.GetName()));
+ depends.clear();
+ depends.push_back("cmake_check_build_system");
+ lg->WriteMakeRule(ruleFileStream,
+ "Build rule for target.",
+ t->second.GetName(), depends, commands);
+ }
+ }
+ }
+}
+
+
+//----------------------------------------------------------------------------
+void
+cmGlobalUnixMakefileGenerator3
+::WriteConvenienceRules2(std::ostream& ruleFileStream,
+ cmLocalUnixMakefileGenerator3 *lg,
+ bool exclude)
+{
std::vector<std::string> depends;
std::vector<std::string> commands;
std::string localName;
std::string makeTargetName;
// write the directory level rules for this local gen
- this->WriteDirectoryRules(ruleFileStream,lg);
+ this->WriteDirectoryRules2(ruleFileStream,lg);
depends.push_back("cmake_check_build_system");
@@ -561,16 +812,18 @@ cmGlobalUnixMakefileGenerator3
depends.push_back(localName);
commands.clear();
lg->WriteMakeRule(ruleFileStream, "All Build rule for target.",
- "all/all", depends, commands);
+ "all", depends, commands);
}
-
+
// Write the rule.
commands.clear();
- commands.push_back(lg->GetRecursiveMakeCall("Makefile",localName.c_str()));
+ commands.push_back(lg->GetRecursiveMakeCall("Makefile2",
+ localName.c_str()));
depends.clear();
depends.push_back("cmake_check_build_system");
localName = lg->GetRelativeTargetDirectory(t->second);
- lg->WriteMakeRule(ruleFileStream, "Build rule for subir invocation for target.",
+ lg->WriteMakeRule(ruleFileStream,
+ "Build rule for subdir invocation for target.",
localName.c_str(), depends, commands);
// Add a target with the canonical name (no prefix, suffix or path).
@@ -579,7 +832,7 @@ cmGlobalUnixMakefileGenerator3
depends.push_back(localName);
lg->WriteMakeRule(ruleFileStream, "Convenience name for target.",
t->second.GetName(), depends, commands);
-
+
// add the clean rule
makeTargetName = localName;
makeTargetName += "/clean";
@@ -598,7 +851,6 @@ cmGlobalUnixMakefileGenerator3
}
-
//----------------------------------------------------------------------------
void
cmGlobalUnixMakefileGenerator3
diff --git a/Source/cmGlobalUnixMakefileGenerator3.h b/Source/cmGlobalUnixMakefileGenerator3.h
index 79f2d21..d43f1ab 100644
--- a/Source/cmGlobalUnixMakefileGenerator3.h
+++ b/Source/cmGlobalUnixMakefileGenerator3.h
@@ -26,7 +26,34 @@ class cmLocalUnixMakefileGenerator3;
* \brief Write a Unix makefiles.
*
* cmGlobalUnixMakefileGenerator3 manages UNIX build process for a tree
+
+
+ The basic approach of this generator is to produce Makefiles that will all
+ be run with the current working directory set to the Home Output
+ directory. The one exception to this is the subdirectory Makefiles which are
+ created as a convenience and just cd up to the Home Output directory and
+ invoke the main Makefiles.
+
+ The make process starts with Makefile. Makefile should only contain the
+ targets the user is likely to invoke directly from a make command line. No
+ internal targets should be in this file. Makefile2 contains the internal
+ targets that are required to make the process work.
+
+ Makefile2 in turn will recursively make targets in the correct order. Each
+ target has its own directory <target>.dir and its own makefile build.make in
+ that directory. Also in that directory is a couple makefiles per source file
+ used by the target. Typically these are named source.obj.build.make and
+ source.obj.build.depend.make. The source.obj.build.make contains the rules
+ for building, cleaning, and computing dependencies for the given source
+ file. The build.depend.make contains additional dependencies that were
+ computed during dependency scanning. An additional file called
+ source.obj.depend is used as a marker to indicate when dependencies must be
+ rescanned.
+
+ Rules for custom commands follow the same model as rules for source files.
+
*/
+
class cmGlobalUnixMakefileGenerator3 : public cmGlobalGenerator
{
public:
@@ -59,6 +86,7 @@ public:
protected:
void WriteMainMakefile();
+ void WriteMainMakefile2();
void WriteMainCMakefile();
void WriteMainCMakefileLanguageRules(cmGeneratedFileStream& cmakefileStream);
void WriteAllRules(cmLocalUnixMakefileGenerator3 *lg,
@@ -68,12 +96,19 @@ protected:
void WriteConvenienceRules(std::ostream& ruleFileStream,
cmLocalUnixMakefileGenerator3 *,
bool exclude);
+ void WriteConvenienceRules2(std::ostream& ruleFileStream,
+ cmLocalUnixMakefileGenerator3 *,
+ bool exclude);
+
void WriteDirectoryRules(std::ostream& ruleFileStream,
cmLocalUnixMakefileGenerator3 *lg);
+ void WriteDirectoryRules2(std::ostream& ruleFileStream,
+ cmLocalUnixMakefileGenerator3 *lg);
void AppendGlobalTargetDepends(std::vector<std::string>& depends,
const cmTarget& target);
- void AppendAnyGlobalDepend(std::vector<std::string>& depends, const char* name);
+ void AppendAnyGlobalDepend(std::vector<std::string>& depends,
+ const char* name);
// does this generator need a requires step for any of its targets
bool NeedRequiresStep(cmLocalUnixMakefileGenerator3 *lg);
diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx
index 2f62478..7211b24 100644
--- a/Source/cmLocalUnixMakefileGenerator3.cxx
+++ b/Source/cmLocalUnixMakefileGenerator3.cxx
@@ -2782,11 +2782,13 @@ void cmLocalUnixMakefileGenerator3::CreateJumpCommand(std::vector<std::string>&
// back because the shell keeps the working directory between
// commands.
std::string cmd = "cd ";
- cmd += this->ConvertToOutputForExisting(m_Makefile->GetHomeOutputDirectory());
+ cmd += this->ConvertToOutputForExisting
+ (m_Makefile->GetHomeOutputDirectory());
commands.push_back(cmd);
// Build the target for this pass.
- commands.push_back(this->GetRecursiveMakeCall("Makefile",localName.c_str()));
+ commands.push_back(this->GetRecursiveMakeCall
+ ("Makefile2",localName.c_str()));
// Change back to the starting directory. Any trailing slash must be
// removed to avoid problems with Borland Make.
@@ -2811,7 +2813,7 @@ void cmLocalUnixMakefileGenerator3::CreateJumpCommand(std::vector<std::string>&
// Build the target for this pass.
cmd += " && ";
- cmd += this->GetRecursiveMakeCall("Makefile",localName.c_str());
+ cmd += this->GetRecursiveMakeCall("Makefile2",localName.c_str());
// Add the command as a single line.
commands.push_back(cmd);