From 4b1c392c9c441437a00d0be3c2da0fd0b103777f Mon Sep 17 00:00:00 2001 From: Ken Martin Date: Wed, 11 May 2005 08:45:16 -0400 Subject: [PATCH] ENH: snapshot --- Source/cmGlobalUnixMakefileGenerator3.cxx | 64 ++--- Source/cmGlobalUnixMakefileGenerator3.h | 3 - Source/cmLocalUnixMakefileGenerator3.cxx | 318 ++++++++++++++++++++-- Source/cmLocalUnixMakefileGenerator3.h | 24 +- 4 files changed, 328 insertions(+), 81 deletions(-) diff --git a/Source/cmGlobalUnixMakefileGenerator3.cxx b/Source/cmGlobalUnixMakefileGenerator3.cxx index 466196999..14cf35ff1 100644 --- a/Source/cmGlobalUnixMakefileGenerator3.cxx +++ b/Source/cmGlobalUnixMakefileGenerator3.cxx @@ -332,7 +332,7 @@ void cmGlobalUnixMakefileGenerator3::WriteDependMakefile() // Write the do not edit header. lg->WriteDisclaimer(makefileStream); - lg->WriteMakeVariables(makefileStream); + //lg->WriteMakeVariables(makefileStream); // add the generic dependency std::vector depends; @@ -354,7 +354,8 @@ void cmGlobalUnixMakefileGenerator3::WriteDependMakefile() static_cast(m_LocalGenerators[i]); if (!lg2->GetExcludeAll()) { - lg2->WriteTargetIncludes(makefileStream,"depend.make","depend"); + lg2->WriteMainTargetIncludes(makefileStream,"depend.make","depend"); + lg2->WriteMainTargetRules(makefileStream,"depend.make","depend"); } } } @@ -406,7 +407,9 @@ void cmGlobalUnixMakefileGenerator3::WriteBuildMakefile() } if (!exclude) { - lg2->WriteTargetIncludes(makefileStream,"build.make","build"); + lg2->WriteMainTargetIncludes(makefileStream,"build.make","build"); + lg2->WriteMainTargetRules(makefileStream,"build.make","build"); + lg2->WriteMainTargetRules(makefileStream,"build.make","requires"); } } } @@ -444,7 +447,8 @@ void cmGlobalUnixMakefileGenerator3::WriteCleanMakefile() { cmLocalUnixMakefileGenerator3 *lg2 = static_cast(m_LocalGenerators[i]); - lg2->WriteTargetIncludes(makefileStream,"clean.make","clean"); + lg2->WriteMainTargetIncludes(makefileStream,"clean.make","clean"); + lg2->WriteMainTargetRules(makefileStream,"clean.make","clean"); // add the directory based rules lg2->WriteLocalCleanRule(makefileStream); } @@ -468,57 +472,20 @@ void cmGlobalUnixMakefileGenerator3 // Check the build system in this directory. depends.push_back("cmake_check_build_system"); - commands.push_back(this->GetRecursiveMakeCall("depend.make",0)); - commands.push_back(this->GetRecursiveMakeCall("build.make",0)); + commands.push_back(lg->GetRecursiveMakeCall("depend.make",0)); + commands.push_back(lg->GetRecursiveMakeCall("depend.make","requires")); + commands.push_back(lg->GetRecursiveMakeCall("build.make",0)); // Write the rule. lg->WriteMakeRule(makefileStream, "The main all target", "all", depends, commands); // write the clean commands.clear(); - commands.push_back(this->GetRecursiveMakeCall("clean.make",0)); + commands.push_back(lg->GetRecursiveMakeCall("clean.make",0)); lg->WriteMakeRule(makefileStream, "default clean target", "clean", depends, commands); } -//---------------------------------------------------------------------------- -std::string -cmGlobalUnixMakefileGenerator3 -::GetRecursiveMakeCall(const char *Makefile, const char* tgt) -{ - cmLocalUnixMakefileGenerator3 *lg = - static_cast(m_LocalGenerators[0]); - - // Call make on the given file. - std::string cmd; - cmd += "$(MAKE) -f "; - cmd += Makefile; - cmd += " "; - - // Pass down verbosity level. - if(lg->GetMakeSilentFlag().size()) - { - cmd += lg->GetMakeSilentFlag(); - cmd += " "; - } - - // Most unix makes will pass the command line flags to make down to - // sub-invoked makes via an environment variable. However, some - // makes do not support that, so you have to pass the flags - // explicitly. - if(lg->GetPassMakeflags()) - { - cmd += "-$(MAKEFLAGS) "; - } - - // Add the target. - if (tgt && tgt[0] != '\0') - { - cmd += tgt; - } - return cmd; -} - //---------------------------------------------------------------------------- void cmGlobalUnixMakefileGenerator3 @@ -548,10 +515,13 @@ cmGlobalUnixMakefileGenerator3 commands.clear(); makeTargetName = localName; makeTargetName += "/depend"; - commands.push_back(this->GetRecursiveMakeCall("depend.make",makeTargetName.c_str())); + commands.push_back(lg->GetRecursiveMakeCall("depend.make",makeTargetName.c_str())); + makeTargetName = localName; + makeTargetName += "/requires"; + commands.push_back(lg->GetRecursiveMakeCall("depend.make",makeTargetName.c_str())); makeTargetName = localName; makeTargetName += "/build"; - commands.push_back(this->GetRecursiveMakeCall("build.make",makeTargetName.c_str())); + commands.push_back(lg->GetRecursiveMakeCall("build.make",makeTargetName.c_str())); // Write the rule. lg->WriteMakeRule(ruleFileStream, "Convenience name for target.", diff --git a/Source/cmGlobalUnixMakefileGenerator3.h b/Source/cmGlobalUnixMakefileGenerator3.h index 5fb62b1c6..eb8d8da84 100644 --- a/Source/cmGlobalUnixMakefileGenerator3.h +++ b/Source/cmGlobalUnixMakefileGenerator3.h @@ -67,9 +67,6 @@ protected: void WriteAllRules(cmLocalUnixMakefileGenerator3 *lg, std::ostream& makefileStream); - /** used to create a recursive make call */ - std::string GetRecursiveMakeCall(const char *makefile, const char* tgt); - void WriteConvenienceRules(std::ostream& ruleFileStream, cmLocalUnixMakefileGenerator3 *); }; diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx index 07ea08a97..0604a8c48 100644 --- a/Source/cmLocalUnixMakefileGenerator3.cxx +++ b/Source/cmLocalUnixMakefileGenerator3.cxx @@ -79,6 +79,9 @@ void cmLocalUnixMakefileGenerator3::Generate() this->WriteCustomCommands(); + // write the local Makefile + this->WriteLocalMakefile(); + // Write the cmake file with information for this directory. this->WriteDirectoryInformationFile(); } @@ -635,6 +638,27 @@ cmLocalUnixMakefileGenerator3 // Add this to the set of provides-requires objects on the target. provides_requires.push_back(objectRequires); } + + // If the language needs provides-requires mode, create the + // corresponding targets. + if(strcmp(lang, "Fortran") == 0) + { + std::string objectRequires = obj; + std::string objectProvides = obj; + objectRequires += ".requires"; + objectProvides += ".provides"; + + // Add the provides target to build the object file. + std::vector no_commands; + std::vector p_depends; + p_depends.push_back(obj); + this->WriteMakeRule(ruleFileStream, 0, + objectProvides.c_str(), p_depends, no_commands); + + // Add this to the set of provides-requires objects on the target. + provides_requires.push_back(objectRequires); + } + } //---------------------------------------------------------------------------- @@ -699,27 +723,6 @@ cmLocalUnixMakefileGenerator3 // The object file should be checked for dependency integrity. m_CheckDependFiles[lang].insert(relativeObj); - // If the language needs provides-requires mode, create the - // corresponding targets. -/* - if(strcmp(lang, "Fortran") == 0) - { - std::string objectRequires = obj; - std::string objectProvides = obj; - objectRequires += ".requires"; - objectProvides += ".provides"; - - // Add the provides target to build the object file. - std::vector no_commands; - std::vector p_depends; - p_depends.push_back(obj); - this->WriteMakeRule(ruleFileStream, 0, - objectProvides.c_str(), p_depends, no_commands); - - // Add this to the set of provides-requires objects on the target. - provides_requires.push_back(objectRequires); - } -*/ } //---------------------------------------------------------------------------- @@ -1041,9 +1044,9 @@ cmLocalUnixMakefileGenerator3 << "\n"; } -void cmLocalUnixMakefileGenerator3::WriteTargetIncludes(std::ostream& makefileStream, - const char *file, - const char *rule) +void cmLocalUnixMakefileGenerator3::WriteMainTargetIncludes(std::ostream& makefileStream, + const char *file, + const char *rule) { std::vector depends; std::vector no_commands; @@ -1096,12 +1099,31 @@ void cmLocalUnixMakefileGenerator3::WriteTargetIncludes(std::ostream& makefileSt << m_IncludeDirective << " " << this->ConvertToOutputForExisting(tname.c_str()).c_str() << "\n"; - + } + } +} + +void cmLocalUnixMakefileGenerator3::WriteMainTargetRules(std::ostream& makefileStream, + const char *file, + const char *rule) +{ + std::vector depends; + std::vector no_commands; + + for (cmTargets::const_iterator l = m_Makefile->GetTargets().begin(); + l != m_Makefile->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 && !strcmp(rule,"build"))) + { // Add this to the list of depends rules in this directory. if(l->second.IsInAll()) { // add the dependency - tname = this->GetRelativeTargetDirectory(l->second); + std::string tname = this->GetRelativeTargetDirectory(l->second); tname += "/"; tname += rule; depends.clear(); @@ -1374,6 +1396,71 @@ cmLocalUnixMakefileGenerator3 } } +//---------------------------------------------------------------------------- +void +cmLocalUnixMakefileGenerator3 +::WriteTargetRequiresRule(std::ostream& ruleFileStream, const cmTarget& target, + const std::vector& provides_requires) +{ + // Create the driving make target. + std::string dir = m_Makefile->GetStartOutputDirectory(); + dir += "/"; + dir += this->GetTargetDirectory(target); + std::string targetRequires = dir; + targetRequires += "/requires"; + targetRequires = + m_GlobalGenerator->ConvertToHomeRelativeOutputPath(targetRequires.c_str()); + + std::string buildTarget = dir; + buildTarget += "/build"; + buildTarget = + m_GlobalGenerator->ConvertToHomeRelativeOutputPath(buildTarget.c_str()); + + std::string comment = "Directory-level requires rule for this target."; + if(provides_requires.empty()) + { + // No provides-requires mode objects in this target. Anything + // that requires the target can build it directly. + std::vector no_commands; + std::vector depends; + depends.push_back(buildTarget); + this->WriteMakeRule(ruleFileStream, comment.c_str(), + targetRequires.c_str(), depends, no_commands); + } + else + { + // There are provides-requires mode objects in this target. Use + // provides-requires mode to build the target itself. + std::string targetProvides = dir; + targetProvides += "/provides"; + targetProvides = + m_GlobalGenerator->ConvertToHomeRelativeOutputPath(targetProvides.c_str()); + { + std::vector no_commands; + std::vector depends; + depends.push_back(buildTarget); + this->WriteMakeRule(ruleFileStream, 0, + targetProvides.c_str(), depends, no_commands); + } + { + // Build list of require-level dependencies. + std::vector depends; + for(std::vector::const_iterator + pr = provides_requires.begin(); + pr != provides_requires.end(); ++pr) + { + depends.push_back(*pr); + } + + // Write the requires rule for this target. + std::vector commands; + //commands.push_back(this->GetRecursiveMakeCall(targetProvides.c_str())); + this->WriteMakeRule(ruleFileStream, comment.c_str(), + targetRequires.c_str(), depends, commands); + } + } +} + //---------------------------------------------------------------------------- void cmLocalUnixMakefileGenerator3 @@ -1551,6 +1638,9 @@ cmLocalUnixMakefileGenerator3 cleanFiles.push_back(cleanObjs); cleanFiles.push_back(targetOutPath.c_str()); this->WriteTargetCleanRule(ruleFileName, target, cleanFiles, objects, external_objects); + + // Write the driving make target. + this->WriteTargetRequiresRule(ruleFileStream, target, provides_requires); } //---------------------------------------------------------------------------- @@ -1873,6 +1963,9 @@ cmLocalUnixMakefileGenerator3 cleanFiles.push_back(cleanObjs); cleanFiles.push_back(targetOutPath.c_str()); this->WriteTargetCleanRule(ruleFileName, target, cleanFiles, objects, external_objects); + + // Write the driving make target. + this->WriteTargetRequiresRule(ruleFileStream, target, provides_requires); } //---------------------------------------------------------------------------- @@ -2834,6 +2927,144 @@ cmLocalUnixMakefileGenerator3 return false; } +//---------------------------------------------------------------------------- +void cmLocalUnixMakefileGenerator3::WriteLocalMakefile() +{ + // only write the locla Makefile if we are not at the top + if (!m_Parent) + { + return; + } + + // generate the includes + std::string ruleFileName = "Makefile"; + + // Open the rule file. This should be copy-if-different because the + // rules may depend on this file itself. + std::string ruleFileNameFull = this->ConvertToFullPath(ruleFileName); + cmGeneratedFileStream ruleFileStream(ruleFileNameFull.c_str()); + ruleFileStream.SetCopyIfDifferent(true); + if(!ruleFileStream) + { + return; + } + this->WriteDisclaimer(ruleFileStream); + + this->WriteMakeVariables(ruleFileStream); + + std::vector all_depends; + std::vector depends; + std::vector commands; + + // Write the empty all rule. + this->WriteMakeRule(ruleFileStream, "The main all target", "all", depends, commands); + + // recursively write our targets + this->WriteLocalMakefileTargets(ruleFileStream, all_depends); + + // write out the all rule depends + commands.clear(); + this->WriteMakeRule(ruleFileStream, "The main all target", "all", all_depends, commands); + +} + +void cmLocalUnixMakefileGenerator3 +::WriteLocalMakefileTargets(std::ostream& ruleFileStream, + std::vector& all_depends) +{ + std::vector depends; + std::vector commands; + + // for each target we just provide a rule to cd up to the top and do a make + // on the target + const cmTargets& targets = m_Makefile->GetTargets(); + std::string localName; + 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)) + { + // Add a rule to build the target by name. + localName = this->GetRelativeTargetDirectory(t->second); + commands.clear(); + depends.clear(); + all_depends.push_back(localName); + + this->CreateJumpCommand(commands,localName); + this->WriteMakeRule(ruleFileStream, "Convenience name for target.", + localName.c_str(), depends, commands); + + // Add a target with the canonical name (no prefix, suffix or path). + if(localName != t->second.GetName()) + { + commands.clear(); + depends.push_back(localName); + this->WriteMakeRule(ruleFileStream, "Convenience name for target.", + t->second.GetName(), depends, commands); + } + } + } + + // for all children recurse + std::vector subdirs = this->GetChildren(); + + // for each subdir recurse + std::vector::iterator sdi = subdirs.begin(); + for (; sdi != subdirs.end(); ++sdi) + { + cmLocalUnixMakefileGenerator3 * lg = + static_cast(*sdi); + lg->WriteLocalMakefileTargets(ruleFileStream,all_depends); + } +} + +void cmLocalUnixMakefileGenerator3::CreateJumpCommand(std::vector& commands, + std::string& localName) +{ + if(m_WindowsShell) + { + // On Windows we must perform each step separately and then change + // back because the shell keeps the working directory between + // commands. + std::string cmd = "cd "; + 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())); + + // Change back to the starting directory. Any trailing slash must be + // removed to avoid problems with Borland Make. + std::string back = + cmSystemTools::RelativePath(m_Makefile->GetHomeOutputDirectory(), + m_Makefile->GetStartOutputDirectory()); + if(back.size() && back[back.size()-1] == '/') + { + back = back.substr(0, back.size()-1); + } + cmd = "cd "; + cmd += this->ConvertToOutputForExisting(back.c_str()); + commands.push_back(cmd); + } + else + { + // On UNIX we must construct a single shell command to change + // directory and build because make resets the directory between + // each command. + std::string cmd = "cd "; + cmd += this->ConvertToOutputForExisting(m_Makefile->GetHomeOutputDirectory()); + + // Build the target for this pass. + cmd += " && "; + cmd += this->GetRecursiveMakeCall("Makefile",localName.c_str()); + + // Add the command as a single line. + commands.push_back(cmd); + } +} + //---------------------------------------------------------------------------- void cmLocalUnixMakefileGenerator3::CheckDependencies(cmMakefile* mf, bool verbose) @@ -2875,3 +3106,38 @@ void cmLocalUnixMakefileGenerator3::CheckDependencies(cmMakefile* mf, } } +//---------------------------------------------------------------------------- +std::string +cmLocalUnixMakefileGenerator3 +::GetRecursiveMakeCall(const char *Makefile, const char* tgt) +{ + // Call make on the given file. + std::string cmd; + cmd += "$(MAKE) -f "; + cmd += Makefile; + cmd += " "; + + // Passg down verbosity level. + if(this->GetMakeSilentFlag().size()) + { + cmd += this->GetMakeSilentFlag(); + cmd += " "; + } + + // Most unix makes will pass the command line flags to make down to + // sub-invoked makes via an environment variable. However, some + // makes do not support that, so you have to pass the flags + // explicitly. + if(this->GetPassMakeflags()) + { + cmd += "-$(MAKEFLAGS) "; + } + + // Add the target. + if (tgt && tgt[0] != '\0') + { + cmd += tgt; + } + return cmd; +} + diff --git a/Source/cmLocalUnixMakefileGenerator3.h b/Source/cmLocalUnixMakefileGenerator3.h index ac4c04b8e..3e4f2f3a7 100644 --- a/Source/cmLocalUnixMakefileGenerator3.h +++ b/Source/cmLocalUnixMakefileGenerator3.h @@ -77,6 +77,9 @@ public: void SetMakeSilentFlag(const char* s) { m_MakeSilentFlag = s; } std::string &GetMakeSilentFlag() { return m_MakeSilentFlag; } + /** used to create a recursive make call */ + std::string GetRecursiveMakeCall(const char *makefile, const char* tgt); + @@ -124,11 +127,12 @@ public: /** write some extra rules suahc as make test etc */ void WriteSpecialTargetsTop(std::ostream& makefileStream); + void WriteMainTargetIncludes(std::ostream& makefileStream,const char *file, + const char *rule); + void WriteMainTargetRules(std::ostream& makefileStream,const char *file, + const char *rule); - - void WriteTargetIncludes(std::ostream& makefileStream,const char *file, - const char *rule); void WriteSpecialTargetsBottom(std::ostream& makefileStream); std::string ConvertToRelativeOutputPath(const char* p); std::string GetRelativeTargetDirectory(const cmTarget& target); @@ -143,6 +147,13 @@ public: protected: + // write the target rules for the local Makefile into the stream + void WriteLocalMakefileTargets(std::ostream& ruleFileStream, + std::vector& all_depends); + + // create the cd to home commands + void CreateJumpCommand(std::vector& commands, std::string & localName); + // these two methods just compute reasonable values for m_LibraryOutputPath and // m_ExecutableOutputPath void ConfigureOutputPaths(); @@ -244,7 +255,7 @@ protected: const char* extraLinkFlags, const std::vector& provides_requires); - + void WriteLocalMakefile(); @@ -268,7 +279,10 @@ protected: const std::vector& files, const std::vector& objects, const std::vector& external_objects); - + void WriteTargetRequiresRule(std::ostream& ruleFileStream, + const cmTarget& target, + const std::vector& provides_requires); + std::string GetTargetDirectory(const cmTarget& target); std::string GetSubdirTargetName(const char* pass, const char* subdir); std::string GetObjectFileName(const cmTarget& target,