From e4843d83a4a7523f4f2c0c5912fb4b01f0b74830 Mon Sep 17 00:00:00 2001 From: Bill Hoffman Date: Fri, 28 Dec 2001 17:00:05 -0500 Subject: [PATCH] ENH: remove the rule to run make depend from the top with each change in any cmakelist file. Instead, run make depend in the current directory if a source file changes, or if a .h file changes or is removed --- Source/cmNMakeMakefileGenerator.cxx | 9 +- Source/cmUnixMakefileGenerator.cxx | 188 ++++++++++++++++++++++------ Source/cmUnixMakefileGenerator.h | 9 +- 3 files changed, 166 insertions(+), 40 deletions(-) diff --git a/Source/cmNMakeMakefileGenerator.cxx b/Source/cmNMakeMakefileGenerator.cxx index 4e4b3ed54..5b945a12a 100644 --- a/Source/cmNMakeMakefileGenerator.cxx +++ b/Source/cmNMakeMakefileGenerator.cxx @@ -260,7 +260,7 @@ void cmNMakeMakefileGenerator::BuildInSubDirectory(std::ostream& fout, } std::string currentDir = m_Makefile->GetCurrentOutputDirectory(); cmSystemTools::ConvertToWindowsSlashes(currentDir); - fout << "\tcd " << cmSystemTools::EscapeSpaces(currentDir.c_str()) << "\n"; + fout << "\tcd " << cmSystemTools::EscapeSpaces(currentDir.c_str()) << "\n\n"; } @@ -720,8 +720,11 @@ void cmNMakeMakefileGenerator::OutputBuildLibraryInDir(std::ostream& fout, std::string currentDir = m_Makefile->GetCurrentOutputDirectory(); cmSystemTools::ConvertToWindowsSlashes(currentDir); fout << cmSystemTools::EscapeSpaces(fullpath) - << ":\n\tcd " << cmSystemTools::EscapeSpaces(path) - << "\n\t$(MAKE) $(MAKESILENT) " << cmSystemTools::EscapeSpaces(fullpath) + << ":\n\tcd " << cmSystemTools::EscapeSpaces(path) << "\n" + << "\t$(MAKE) -$(MAKEFLAGS) $(MAKESILENT) cmake.depends\n" + << "\t$(MAKE) -$(MAKEFLAGS) $(MAKESILENT) cmake.check_depends\n" + << "\t$(MAKE) -$(MAKEFLAGS) $(MAKESILENT) -f cmake.check_depends\n" + << "\t$(MAKE) $(MAKESILENT) " << cmSystemTools::EscapeSpaces(fullpath) << "\n\tcd " << cmSystemTools::EscapeSpaces(currentDir.c_str()) << "\n"; } diff --git a/Source/cmUnixMakefileGenerator.cxx b/Source/cmUnixMakefileGenerator.cxx index ca4e0899b..d1e369003 100644 --- a/Source/cmUnixMakefileGenerator.cxx +++ b/Source/cmUnixMakefileGenerator.cxx @@ -247,13 +247,16 @@ void cmUnixMakefileGenerator::OutputMakefile(const char* file) fout << "\n\n\n"; this->OutputMakeVariables(fout); // Set up the default target as the VERY first target, so that make with no arguments will run it - this->OutputMakeRule(fout, - "Default target executed when no arguments are given to make", - "default_target", - 0, - "$(MAKE) -$(MAKEFLAGS) $(MAKESILENT) cmake.depends_mark", - "$(MAKE) -$(MAKEFLAGS) $(MAKESILENT) all"); - + this-> + OutputMakeRule(fout, + "Default target executed when no arguments are given to make, first make sure cmake.depends is up-to-date, then check the sources, then build the all target", + "default_target", + 0, + "$(MAKE) -$(MAKEFLAGS) $(MAKESILENT) cmake.depends", + "$(MAKE) -$(MAKEFLAGS) $(MAKESILENT) cmake.check_depends", + "$(MAKE) -$(MAKEFLAGS) $(MAKESILENT) -f cmake.check_depends", + "$(MAKE) -$(MAKEFLAGS) $(MAKESILENT) all"); + this->OutputTargetRules(fout); this->OutputDependLibs(fout); this->OutputTargets(fout); @@ -269,7 +272,26 @@ void cmUnixMakefileGenerator::OutputMakefile(const char* file) return; } dependout << "# .o dependencies in this directory." << std::endl; - this->OutputObjectDepends(dependout); + + std::string checkDepend = m_Makefile->GetStartOutputDirectory(); + checkDepend += "/cmake.check_depends"; + std::ofstream checkdependout(checkDepend.c_str()); + if(!checkdependout) + { + cmSystemTools::Error("Error can not open for write: ", checkDepend.c_str()); + return; + } + checkdependout << "# This file is used as a tag file, that all sources depend on. If a source changes, then the rule to rebuild this file will cause cmake.depends to be rebuilt." << std::endl; + // if there were any depends output, then output the check depends + // information inot checkdependout + if(this->OutputObjectDepends(dependout)) + { + this->OutputCheckDepends(checkdependout); + } + else + { + checkdependout << "all:\n\tcd .\n"; + } } this->OutputCustomRules(fout); this->OutputMakeRules(fout); @@ -878,7 +900,10 @@ void cmUnixMakefileGenerator::OutputBuildLibraryInDir(std::ostream& fout, } fout << cmSystemTools::EscapeSpaces(fullpath) << ":\n\tcd " << cmSystemTools::EscapeSpaces(path) - << "; $(MAKE) $(MAKESILENT) " << makeTarget << "\n\n"; + << "; $(MAKE) -$(MAKEFLAGS) $(MAKESILENT) cmake.depends" + << "; $(MAKE) -$(MAKEFLAGS) $(MAKESILENT) cmake.check_depends" + << "; $(MAKE) -$(MAKEFLAGS) $(MAKESILENT) -f cmake.check_depends" + << "; $(MAKE) $(MAKESILENT) " << makeTarget << "\n\n"; } bool cmUnixMakefileGenerator::SamePath(const char* path1, const char* path2) @@ -984,6 +1009,7 @@ void cmUnixMakefileGenerator::BuildInSubDirectory(std::ostream& fout, fout << "\t@cd " << directory << "; $(MAKE) -$(MAKEFLAGS) " << target2 << "\n"; } + fout << "\n"; } @@ -1054,9 +1080,11 @@ void cmUnixMakefileGenerator::OutputSubDirectoryRules(std::ostream& fout) { return; } - this->OutputSubDirectoryVars(fout, "SUBDIR_BUILD", "build", - "cmake.depends_mark", - "all", + this->OutputSubDirectoryVars(fout, + "SUBDIR_BUILD", + "default_target", + "default_target", + 0, SubDirectories); this->OutputSubDirectoryVars(fout, "SUBDIR_CLEAN", "clean", "clean", @@ -1078,8 +1106,9 @@ void cmUnixMakefileGenerator::OutputSubDirectoryRules(std::ostream& fout) // Output the depend information for all the classes // in the makefile. These would have been generated // by the class cmMakeDepend GenerateMakefile -void cmUnixMakefileGenerator::OutputObjectDepends(std::ostream& fout) +bool cmUnixMakefileGenerator::OutputObjectDepends(std::ostream& fout) { + bool ret = false; // Iterate over every target. std::map& targets = m_Makefile->GetTargets(); for(std::map::const_iterator target = targets.begin(); @@ -1100,16 +1129,80 @@ void cmUnixMakefileGenerator::OutputObjectDepends(std::ostream& fout) source->GetDepends().begin(); dep != source->GetDepends().end(); ++dep) { - fout << " \\\n" << cmSystemTools::EscapeSpaces(dep->c_str()); + fout << " \\\n" + << this->ConvertToNativePath(cmSystemTools::EscapeSpaces( + dep->c_str()).c_str()); + ret = true; } fout << "\n\n"; } } } } + return ret; } + +// Output the depend information for all the classes +// in the makefile. These would have been generated +// by the class cmMakeDepend GenerateMakefile +void cmUnixMakefileGenerator::OutputCheckDepends(std::ostream& fout) +{ + std::set emitted; + // Iterate over every target. + std::map& targets = m_Makefile->GetTargets(); + this->OutputMakeVariables(fout); + fout << "default:\n"; + fout << "\t$(MAKE) -$(MAKEFLAGS) $(MAKESILENT) -f cmake.check_depends all\n" + << "\t$(MAKE) -$(MAKEFLAGS) $(MAKESILENT) -f cmake.check_depends cmake.depends\n\n"; + fout << "all: "; + for(std::map::const_iterator target = targets.begin(); + target != targets.end(); ++target) + { + // Iterate over every source for this target. + const std::vector& sources = target->second.GetSourceFiles(); + for(std::vector::const_iterator source = sources.begin(); + source != sources.end(); ++source) + { + if(!source->IsAHeaderFileOnly()) + { + if(!source->GetDepends().empty()) + { + for(std::vector::const_iterator dep = + source->GetDepends().begin(); + dep != source->GetDepends().end(); ++dep) + { + std::string dependfile = + this->ConvertToNativePath(cmSystemTools::EscapeSpaces( + dep->c_str()).c_str()); + if(emitted.insert(dependfile).second) + { + fout << " \\\n" << dependfile ; + } + } + } + } + } + } + fout << "\n\n# if any of these files changes run make dependlocal\n"; + fout << "cmake.depends: "; + std::set::iterator i; + for(i = emitted.begin(); i != emitted.end(); ++i) + { + fout << " \\\n" << *i; + } + fout << "\n\t$(MAKE) -$(MAKEFLAGS) $(MAKESILENT) dependlocal\n\n"; + fout << "\n\n"; + fout << "# if a .h file is removed then run make dependlocal\n\n"; + for(std::set::iterator i = emitted.begin(); + i != emitted.end(); ++i) + { + fout << *i << ":\n" + << "\t$(MAKE) -$(MAKEFLAGS) $(MAKESILENT) dependlocal\n\n"; + } +} + // Output each custom rule in the following format: // output: source depends... // (tab) command... @@ -1482,7 +1575,7 @@ void cmUnixMakefileGenerator::OutputMakeRules(std::ostream& fout) this->OutputMakeRule(fout, "Default build rule", "all", - "cmake.depends_mark $(TARGETS) $(SUBDIR_BUILD)", + "cmake.depends $(TARGETS) $(SUBDIR_BUILD)", 0); if (m_Makefile->IsOn("QT_WRAP_CPP") || m_Makefile->IsOn("QT_WRAP_UI") || @@ -1506,33 +1599,56 @@ void cmUnixMakefileGenerator::OutputMakeRules(std::ostream& fout) "-@ $(RM) $(CLEAN_OBJECT_FILES) $(EXECUTABLES)" " $(TARGETS)"); } - fout << "\n#Rule to build the cmake.depends and Makefile as side effect\n"; - fout << "cmake.depends_mark: $(CMAKE_MAKEFILE_SOURCES)\n"; - this->BuildInSubDirectory(fout, - m_Makefile->GetHomeOutputDirectory(), - "depend", 0); - const char* depend_subdirs = 0; - if(!m_Makefile->GetSubDirectories().empty()) - { - this->OutputMakeRule(fout, - "Rule to force build of cmake.depend in subdirectories", - "depend_subdirs", - "$(SUBDIR_DEPEND)", - 0 - ); - depend_subdirs = "$(MAKE) -$(MAKEFLAGS) $(MAKESILENT) depend_subdirs"; - } + this->OutputMakeRule(fout, + "Rule to build the cmake.depends and Makefile as side effect, if a source cmakelist file is out of date.", + "cmake.depends", + "$(CMAKE_MAKEFILE_SOURCES) ", + "$(CMAKE_COMMAND) " + "-S$(CMAKE_CURRENT_SOURCE) -O$(CMAKE_CURRENT_BINARY) " + "-H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)" + ); this->OutputMakeRule(fout, "Rule to force the build of cmake.depends", "depend", + "$(SUBDIR_DEPEND)", + "$(CMAKE_COMMAND) " + "-S$(CMAKE_CURRENT_SOURCE) -O$(CMAKE_CURRENT_BINARY) " + "-H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)"); + this->OutputMakeRule(fout, + "Rule to force the build of cmake.depends " + "in the current directory only.", + "dependlocal", 0, "$(CMAKE_COMMAND) " "-S$(CMAKE_CURRENT_SOURCE) -O$(CMAKE_CURRENT_BINARY) " - "-H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)", - "-$(RM) cmake.depends_mark", - "echo mark > cmake.depends_mark", - depend_subdirs - ); + "-H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)"); + + // collect up all the sources + std::string allsources; + std::map& targets = m_Makefile->GetTargets(); + for(std::map::const_iterator target = targets.begin(); + target != targets.end(); ++target) + { + // Iterate over every source for this target. + const std::vector& sources = target->second.GetSourceFiles(); + for(std::vector::const_iterator source = sources.begin(); + source != sources.end(); ++source) + { + if(!source->IsAHeaderFileOnly()) + { + allsources += source->GetFullPath(); + allsources += " "; + } + } + } + this->OutputMakeRule(fout, + "rule to rebuild cmake.depends if a source file is changed.", + "cmake.check_depends", + allsources.c_str(), + "$(CMAKE_COMMAND) " + "-S$(CMAKE_CURRENT_SOURCE) -O$(CMAKE_CURRENT_BINARY) " + "-H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)"); + this->OutputMakeRule(fout, "Rebuild CMakeCache.txt file", "rebuild_cache", diff --git a/Source/cmUnixMakefileGenerator.h b/Source/cmUnixMakefileGenerator.h index e7f771e5c..f30c535c0 100644 --- a/Source/cmUnixMakefileGenerator.h +++ b/Source/cmUnixMakefileGenerator.h @@ -91,7 +91,14 @@ public: * in the makefile. These would have been generated * by the class cmMakeDepend. */ - virtual void OutputObjectDepends(std::ostream&); + virtual bool OutputObjectDepends(std::ostream&); + + /** + * Output the check depend information for all the classes + * in the makefile. These would have been generated + * by the class cmMakeDepend. + */ + virtual void OutputCheckDepends(std::ostream&); /** * Try to determine system infomation such as shared library