diff options
-rw-r--r-- | Source/cmDepends.cxx | 78 | ||||
-rw-r--r-- | Source/cmDepends.h | 32 | ||||
-rw-r--r-- | Source/cmDependsC.cxx | 28 | ||||
-rw-r--r-- | Source/cmDependsC.h | 19 | ||||
-rw-r--r-- | Source/cmDependsFortran.cxx | 55 | ||||
-rw-r--r-- | Source/cmDependsFortran.h | 5 | ||||
-rw-r--r-- | Source/cmDependsJava.cxx | 14 | ||||
-rw-r--r-- | Source/cmDependsJava.h | 11 | ||||
-rw-r--r-- | Source/cmGlobalUnixMakefileGenerator3.cxx | 71 | ||||
-rw-r--r-- | Source/cmGlobalUnixMakefileGenerator3.h | 7 | ||||
-rw-r--r-- | Source/cmLocalGenerator.cxx | 20 | ||||
-rw-r--r-- | Source/cmLocalGenerator.h | 3 | ||||
-rw-r--r-- | Source/cmLocalUnixMakefileGenerator3.cxx | 572 | ||||
-rw-r--r-- | Source/cmLocalUnixMakefileGenerator3.h | 29 | ||||
-rw-r--r-- | Source/cmake.cxx | 2 |
15 files changed, 432 insertions, 514 deletions
diff --git a/Source/cmDepends.cxx b/Source/cmDepends.cxx index 165eee0b21..01c6e11fb4 100644 --- a/Source/cmDepends.cxx +++ b/Source/cmDepends.cxx @@ -32,55 +32,14 @@ cmDepends::~cmDepends() { } -void cmDepends::SetTargetFile(const char* dir, const char* targetFile, - const char *markExt, const char *makeExt) -{ - m_Directory = dir; - m_TargetFile = targetFile; - - // Construct the path to the make and mark files. Append - // appropriate extensions to their names. - m_DependsMarkFile = dir; - m_DependsMakeFile = dir; - m_DependsMakeFile += "/"; - m_DependsMarkFile += "/"; - m_DependsMakeFile += m_TargetFile; - m_DependsMarkFile += m_TargetFile; - m_DependsMakeFile += makeExt; - m_DependsMarkFile += markExt; - - if (!m_CompileDirectory.size()) - { - m_CompileDirectory = dir; - } -} - - //---------------------------------------------------------------------------- -bool cmDepends::Write() +bool cmDepends::Write(const char *src, const char *obj, std::ostream &fout) { - // Dependency generation must always be done in the current working - // directory. - assert(m_Directory == "."); - - // Try to generate dependencies for the target file. - cmGeneratedFileStream fout(m_DependsMakeFile.c_str()); - fout << "# Dependencies for " << m_TargetFile.c_str() << std::endl; - if(this->WriteDependencies(fout) && fout) - { - // Dependencies were generated. Touch the mark file. - std::ofstream fmark(m_DependsMarkFile.c_str()); - fmark << "Dependencies updated for " << m_TargetFile.c_str() << std::endl; - return true; - } - else - { - return false; - } + return this->WriteDependencies(src, obj, fout); } //---------------------------------------------------------------------------- -void cmDepends::Check() +void cmDepends::Check(const char *file) { // Dependency checks must be done in proper working directory. std::string oldcwd = "."; @@ -93,11 +52,11 @@ void cmDepends::Check() } // Check whether dependencies must be regenerated. - std::ifstream fin(m_DependsMakeFile.c_str()); + std::ifstream fin(file); if(!(fin && this->CheckDependencies(fin))) { // Clear all dependencies so they will be regenerated. - this->Clear(); + this->Clear(file); } // Restore working directory. @@ -108,37 +67,26 @@ void cmDepends::Check() } //---------------------------------------------------------------------------- -void cmDepends::Clear() +void cmDepends::Clear(const char *file) { // Print verbose output. if(m_Verbose) { cmOStringStream msg; - msg << "Clearing dependencies for \"" << m_TargetFile << "\"." << std::endl; + msg << "Clearing dependencies in \"" << file << "\"." << std::endl; cmSystemTools::Stdout(msg.str().c_str()); } // Remove the dependency mark file to be sure dependencies will be // regenerated. - cmSystemTools::RemoveFile(m_DependsMarkFile.c_str()); - + std::string markFile = file; + markFile += ".mark"; + cmSystemTools::RemoveFile(markFile.c_str()); + // Write an empty dependency file. - cmGeneratedFileStream depFileStream(m_DependsMakeFile.c_str()); + cmGeneratedFileStream depFileStream(file); depFileStream - << "# Empty dependencies file for " << m_TargetFile.c_str() << ".\n" + << "# Empty dependencies file\n" << "# This may be replaced when dependencies are built." << std::endl; } -//---------------------------------------------------------------------------- -const char* cmDepends::GetMakeFileName() -{ - // Skip over the directory part of the name. - return m_DependsMakeFile.c_str() + m_Directory.length() + 1; -} - -//---------------------------------------------------------------------------- -const char* cmDepends::GetMarkFileName() -{ - // Skip over the directory part of the name. - return m_DependsMarkFile.c_str() + m_Directory.length() + 1; -} diff --git a/Source/cmDepends.h b/Source/cmDepends.h index d659af6452..0ccd812bc1 100644 --- a/Source/cmDepends.h +++ b/Source/cmDepends.h @@ -33,10 +33,6 @@ public: path from the build directory to the target file. */ cmDepends(); - /** set the name directory and extensions of the target file to scan */ - void SetTargetFile(const char* dir, const char* targetFile, - const char *markExt, const char *makeExt); - /** at what level will the compile be done from */ void SetCompileDirectory(const char *dir) {m_CompileDirectory = dir;}; @@ -47,44 +43,30 @@ public: virtual ~cmDepends(); /** Write dependencies for the target file. */ - bool Write(); - + bool Write(const char *src, const char *obj, std::ostream &os); + /** Check dependencies for the target file. */ - void Check(); + void Check(const char *file); /** Clear dependencies for the target file so they will be regenerated. */ - void Clear(); - - /** Get the name of the dependency make file. */ - const char* GetMakeFileName(); - - /** Get the name of the dependency mark file. */ - const char* GetMarkFileName(); + void Clear(const char *file); protected: // Write dependencies for the target file to the given stream. // Return true for success and false for failure. - virtual bool WriteDependencies(std::ostream& os)=0; + virtual bool WriteDependencies(const char *src, + const char* obj, std::ostream& os)=0; // Check dependencies for the target file in the given stream. // Return false if dependencies must be regenerated and true // otherwise. - virtual bool CheckDependencies(std::istream& is)=0; + virtual bool CheckDependencies(std::istream& is) = 0; // The directory in which the build rule for the target file is executed. std::string m_Directory; std::string m_CompileDirectory; - // The name of the target file for which dependencies are maintained. - std::string m_TargetFile; - - // The name of the .depends.make file corresponding to the target. - std::string m_DependsMakeFile; - - // The name of the .depends file marking when dependencies were generated. - std::string m_DependsMarkFile; - // Flag for verbose output. bool m_Verbose; diff --git a/Source/cmDependsC.cxx b/Source/cmDependsC.cxx index 056c13c993..6d317a92cf 100644 --- a/Source/cmDependsC.cxx +++ b/Source/cmDependsC.cxx @@ -27,10 +27,8 @@ cmDependsC::cmDependsC() //---------------------------------------------------------------------------- // yummy look at all those constructor arguments -cmDependsC::cmDependsC(const char* sourceFile, - std::vector<std::string> const& includes, +cmDependsC::cmDependsC(std::vector<std::string> const& includes, const char* scanRegex, const char* complainRegex): - m_SourceFile(sourceFile), m_IncludePath(&includes), m_IncludeRegexLine("^[ \t]*#[ \t]*include[ \t]*[<\"]([^\">]+)([\">])"), m_IncludeRegexScan(scanRegex), @@ -44,12 +42,18 @@ cmDependsC::~cmDependsC() } //---------------------------------------------------------------------------- -bool cmDependsC::WriteDependencies(std::ostream& os) +bool cmDependsC::WriteDependencies(const char *src, + const char *obj, std::ostream& os) { // Make sure this is a scanning instance. - if(m_SourceFile == "") + if(!src || src[0] == '\0') { - cmSystemTools::Error("Cannot scan dependencies without an source file."); + cmSystemTools::Error("Cannot scan dependencies without a source file."); + return false; + } + if(!obj || obj[0] == '\0') + { + cmSystemTools::Error("Cannot scan dependencies without an object file."); return false; } if(!m_IncludePath) @@ -61,10 +65,10 @@ bool cmDependsC::WriteDependencies(std::ostream& os) // Walk the dependency graph starting with the source file. bool first = true; UnscannedEntry root; - root.FileName = m_SourceFile; + root.FileName = src; m_Unscanned.push(root); m_Encountered.clear(); - m_Encountered.insert(m_SourceFile); + m_Encountered.insert(src); std::set<cmStdString> dependencies; std::set<cmStdString> scanned; while(!m_Unscanned.empty()) @@ -155,7 +159,7 @@ bool cmDependsC::WriteDependencies(std::ostream& os) for(std::set<cmStdString>::iterator i=dependencies.begin(); i != dependencies.end(); ++i) { - os << m_TargetFile.c_str() << ": " + os << obj << ": " << cmSystemTools::ConvertToOutputPath(i->c_str()).c_str() << std::endl; } @@ -313,8 +317,12 @@ const char* cmDependsC::ParseFileName(const char* in, std::string& name) bool quoted = false; char* buf = new char[strlen(in)+1]; char* pos = buf; + + // for every character while we haven't hit the end of the string AND we + // are in a quoted string OR the current character isn't a : or the second + // character AND it isn't a space for(;*c && (quoted || - ((*c != ':' || pos > buf+1) && !isspace(*c))); ++c) + ((*c != ':' || pos > buf) && !isspace(*c))); ++c) { if(*c == '"') { diff --git a/Source/cmDependsC.h b/Source/cmDependsC.h index 2f16d7719c..fb2b29d81b 100644 --- a/Source/cmDependsC.h +++ b/Source/cmDependsC.h @@ -30,22 +30,16 @@ public: /** Checking instances need to know the build directory name and the relative path from the build directory to the target file. */ cmDependsC(); - - /** Scanning need to know the build directory name, the relative - path from the build directory to the target file, the source - file from which to start scanning, and the include file search - path. It also uses the include file regular expressions. - This is a good example of why constructors should not take arguments. - */ - cmDependsC(const char* sourceFile, std::vector<std::string> const& includes, + cmDependsC(std::vector<std::string> const& includes, const char* scanRegex, const char* complainRegex); /** Virtual destructor to cleanup subclasses properly. */ virtual ~cmDependsC(); - + protected: // Implement writing/checking methods required by superclass. - virtual bool WriteDependencies(std::ostream& os); + virtual bool WriteDependencies(const char *src, + const char *file, std::ostream& os); virtual bool CheckDependencies(std::istream& is); // Method to scan a single file. @@ -56,9 +50,6 @@ protected: std::string& dependee); const char* ParseFileName(const char* in, std::string& name); - // The source file from which to start scanning. - std::string m_SourceFile; - // The include file search path. std::vector<std::string> const* m_IncludePath; @@ -69,7 +60,7 @@ protected: // recursively and which to complain about not finding. cmsys::RegularExpression m_IncludeRegexScan; cmsys::RegularExpression m_IncludeRegexComplain; - + // Data structures for dependency graph walk. struct UnscannedEntry { diff --git a/Source/cmDependsFortran.cxx b/Source/cmDependsFortran.cxx index 4a9ac100c6..ec60a8f0b9 100644 --- a/Source/cmDependsFortran.cxx +++ b/Source/cmDependsFortran.cxx @@ -77,15 +77,12 @@ struct cmDependsFortranParser_s //---------------------------------------------------------------------------- cmDependsFortran::cmDependsFortran(): - m_SourceFile(), m_IncludePath(0) { } //---------------------------------------------------------------------------- -cmDependsFortran::cmDependsFortran(const char* sourceFile, - std::vector<std::string> const& includes): - m_SourceFile(sourceFile), +cmDependsFortran::cmDependsFortran(std::vector<std::string> const& includes): m_IncludePath(&includes) { } @@ -96,14 +93,20 @@ cmDependsFortran::~cmDependsFortran() } //---------------------------------------------------------------------------- -bool cmDependsFortran::WriteDependencies(std::ostream& os) +bool cmDependsFortran::WriteDependencies(const char *src, + const char *obj, std::ostream& os) { // Make sure this is a scanning instance. - if(m_SourceFile == "") + if(!src || src[0] == '\0') { cmSystemTools::Error("Cannot scan dependencies without an source file."); return false; } + if(!obj || obj[0] == '\0') + { + cmSystemTools::Error("Cannot scan dependencies without an object file."); + return false; + } if(!m_IncludePath) { cmSystemTools::Error("Cannot scan dependencies without an include path."); @@ -114,7 +117,7 @@ bool cmDependsFortran::WriteDependencies(std::ostream& os) cmDependsFortranParser parser(this); // Push on the starting file. - cmDependsFortranParser_FilePush(&parser, m_SourceFile.c_str()); + cmDependsFortranParser_FilePush(&parser, src); // Parse the translation unit. if(cmDependsFortran_yyparse(parser.Scanner) != 0) @@ -127,7 +130,7 @@ bool cmDependsFortran::WriteDependencies(std::ostream& os) for(std::set<cmStdString>::const_iterator i = parser.Includes.begin(); i != parser.Includes.end(); ++i) { - os << m_TargetFile.c_str() << ": " + os << obj << ": " << cmSystemTools::ConvertToOutputPath(i->c_str()).c_str() << std::endl; } @@ -141,25 +144,8 @@ bool cmDependsFortran::WriteDependencies(std::ostream& os) if(parser.Provides.find(*i) == parser.Provides.end()) { // since we require some things add them to our list of requirements - os << m_TargetFile.c_str() << ".requires: " << i->c_str() << ".mod.proxy" + os << obj << ".requires: " << i->c_str() << ".mod.proxy" << std::endl; -#if 0 - // Always use lower case for the mod stamp file name. - std::string m = cmSystemTools::LowerCase(*i); - os << m_TargetFile.c_str() << ": " << m.c_str() << ".mod.stamp" - << std::endl; - os << i->c_str() << ".mod.proxy:" << std::endl; - std::string stampName = m_Directory; - stampName += "/"; - stampName += m; - stampName += ".mod.stamp"; - if(!cmSystemTools::FileExists(stampName.c_str())) - { - std::ofstream stamp(stampName.c_str()); - stamp << "# Dummy stamp file in case nothing provides it." - << std::endl; - } -#endif } } @@ -167,14 +153,14 @@ bool cmDependsFortran::WriteDependencies(std::ostream& os) for(std::set<cmStdString>::const_iterator i = parser.Provides.begin(); i != parser.Provides.end(); ++i) { - os << i->c_str() << ".mod.proxy: " << m_TargetFile.c_str() + os << i->c_str() << ".mod.proxy: " << obj << ".provides" << std::endl; } // If any modules are provided then they must be converted to stamp files. if(!parser.Provides.empty()) { - os << m_TargetFile.c_str() << ".provides.build:\n"; + os << obj << ".provides.build:\n"; for(std::set<cmStdString>::const_iterator i = parser.Provides.begin(); i != parser.Provides.end(); ++i) { @@ -185,20 +171,9 @@ bool cmDependsFortran::WriteDependencies(std::ostream& os) os << "\t$(CMAKE_COMMAND) -E cmake_copy_f90_mod " << i->c_str() << " " << m.c_str() << ".mod.stamp\n"; } - os << "\t@touch " << m_TargetFile.c_str() << ".provides.build\n"; + os << "\t@touch " << obj << ".provides.build\n"; } -#if 0 - // if it provides something then connect the requires rule to the build rule - if(!parser.Provides.empty()) - { - os << m_TargetFile.c_str() << ".requires: " << m_TargetFile.c_str() - << ".requires.build" << std::endl; - // provide empty build rule for old gen for now, TODO remove later - os << m_TargetFile.c_str() << ".requires.build:" << std::endl; - } -#endif - /* // TODO: What about .mod files provided in another directory and found with a diff --git a/Source/cmDependsFortran.h b/Source/cmDependsFortran.h index 98db772e42..bc22eeab42 100644 --- a/Source/cmDependsFortran.h +++ b/Source/cmDependsFortran.h @@ -33,7 +33,7 @@ public: path from the build directory to the target file, the source file from which to start scanning, and the include file search path. */ - cmDependsFortran(const char* sourceFile, std::vector<std::string> const& includes); + cmDependsFortran(std::vector<std::string> const& includes); /** Virtual destructor to cleanup subclasses properly. */ virtual ~cmDependsFortran(); @@ -51,7 +51,8 @@ public: protected: // Implement writing/checking methods required by superclass. - virtual bool WriteDependencies(std::ostream& os); + virtual bool WriteDependencies(const char *src, + const char *file, std::ostream& os); virtual bool CheckDependencies(std::istream& is); // The source file from which to start scanning. diff --git a/Source/cmDependsJava.cxx b/Source/cmDependsJava.cxx index ae4e5251da..7e80e31057 100644 --- a/Source/cmDependsJava.cxx +++ b/Source/cmDependsJava.cxx @@ -20,14 +20,7 @@ #include "cmSystemTools.h" //---------------------------------------------------------------------------- -cmDependsJava::cmDependsJava(): - m_SourceFile() -{ -} - -//---------------------------------------------------------------------------- -cmDependsJava::cmDependsJava(const char* sourceFile): - m_SourceFile(sourceFile) +cmDependsJava::cmDependsJava() { } @@ -37,10 +30,11 @@ cmDependsJava::~cmDependsJava() } //---------------------------------------------------------------------------- -bool cmDependsJava::WriteDependencies(std::ostream&) +bool cmDependsJava::WriteDependencies(const char *src, + const char *file, std::ostream&) { // Make sure this is a scanning instance. - if(m_SourceFile == "") + if(!src || src[0] == '\0') { cmSystemTools::Error("Cannot scan dependencies without an source file."); return false; diff --git a/Source/cmDependsJava.h b/Source/cmDependsJava.h index 69466fc043..473567dedb 100644 --- a/Source/cmDependsJava.h +++ b/Source/cmDependsJava.h @@ -29,22 +29,15 @@ public: relative path from the build directory to the target file. */ cmDependsJava(); - /** Scanning need to know the build directory name, the relative - path from the build directory to the target file and the source - file to scan. */ - cmDependsJava(const char* sourceFile); - /** Virtual destructor to cleanup subclasses properly. */ virtual ~cmDependsJava(); protected: // Implement writing/checking methods required by superclass. - virtual bool WriteDependencies(std::ostream& os); + virtual bool WriteDependencies(const char *src, + const char *file, std::ostream& os); virtual bool CheckDependencies(std::istream& is); - // The source file from which to start scanning. - std::string m_SourceFile; - private: cmDependsJava(cmDependsJava const&); // Purposely not implemented. void operator=(cmDependsJava const&); // Purposely not implemented. diff --git a/Source/cmGlobalUnixMakefileGenerator3.cxx b/Source/cmGlobalUnixMakefileGenerator3.cxx index 2627afde5f..e550c2c7e7 100644 --- a/Source/cmGlobalUnixMakefileGenerator3.cxx +++ b/Source/cmGlobalUnixMakefileGenerator3.cxx @@ -328,67 +328,34 @@ void cmGlobalUnixMakefileGenerator3::WriteMainCMakefile() } cmakefileStream << " )\n\n"; - this->WriteMainCMakefileLanguageRules(cmakefileStream); + this->WriteMainCMakefileLanguageRules(cmakefileStream, m_LocalGenerators); } void cmGlobalUnixMakefileGenerator3 -::WriteMainCMakefileLanguageRules(cmGeneratedFileStream& cmakefileStream) +::WriteMainCMakefileLanguageRules(cmGeneratedFileStream& cmakefileStream, + std::vector<cmLocalGenerator *> &lGenerators) { cmLocalUnixMakefileGenerator3 *lg; - // now write all the language stuff - // Set the set of files to check for dependency integrity. - // loop over all of the local generators to collect this - std::set<cmStdString> checkSetLangs; - for (unsigned int i = 0; i < m_LocalGenerators.size(); ++i) - { - lg = static_cast<cmLocalUnixMakefileGenerator3 *>(m_LocalGenerators[i]); - std::map<cmStdString,cmLocalUnixMakefileGenerator3::IntegrityCheckSet>& checkSet = - lg->GetIntegrityCheckSet(); - for(std::map<cmStdString, - cmLocalUnixMakefileGenerator3::IntegrityCheckSet>::const_iterator - l = checkSet.begin(); l != checkSet.end(); ++l) - { - checkSetLangs.insert(l->first); - } - } - - // list the languages + // now list all the target info files cmakefileStream << "# The set of files whose dependency integrity should be checked:\n"; cmakefileStream - << "SET(CMAKE_DEPENDS_LANGUAGES\n"; - for(std::set<cmStdString>::iterator - l = checkSetLangs.begin(); l != checkSetLangs.end(); ++l) + << "SET(CMAKE_DEPEND_INFO_FILES\n"; + for (unsigned int i = 0; i < lGenerators.size(); ++i) { - cmakefileStream << " \"" << l->c_str() << "\"\n"; - } - cmakefileStream << " )\n"; - - // now list the files for each language - for(std::set<cmStdString>::iterator - l = checkSetLangs.begin(); l != checkSetLangs.end(); ++l) - { - cmakefileStream - << "SET(CMAKE_DEPENDS_CHECK_" << l->c_str() << "\n"; - // now for each local gen get the checkset - for (unsigned int i = 0; i < m_LocalGenerators.size(); ++i) + lg = static_cast<cmLocalUnixMakefileGenerator3 *>(lGenerators[i]); + // for all of out targets + for (cmTargets::iterator l = lg->GetMakefile()->GetTargets().begin(); + l != lg->GetMakefile()->GetTargets().end(); l++) { - lg = static_cast<cmLocalUnixMakefileGenerator3 *>(m_LocalGenerators[i]); - // get the check set for this local gen and language - cmLocalUnixMakefileGenerator3::IntegrityCheckSet iCheckSet = - lg->GetIntegrityCheckSet()[*l]; - // for each file - for(cmLocalUnixMakefileGenerator3::IntegrityCheckSet::const_iterator csIter = - iCheckSet.begin(); - csIter != iCheckSet.end(); ++csIter) - { - cmakefileStream << " \"" << - lg->Convert(csIter->c_str(),cmLocalGenerator::HOME_OUTPUT).c_str() << "\"\n"; - } + std::string tname = lg->GetRelativeTargetDirectory(l->second); + tname += "/DependInfo.cmake"; + cmSystemTools::ConvertToUnixSlashes(tname); + cmakefileStream << " \"" << tname.c_str() << "\"\n"; } - cmakefileStream << " )\n"; } + cmakefileStream << " )\n"; } //---------------------------------------------------------------------------- @@ -768,7 +735,6 @@ cmGlobalUnixMakefileGenerator3 // for each target Generate the rule files for each target. cmTargets& targets = lg->GetMakefile()->GetTargets(); - bool needRequiresStep = this->NeedRequiresStep(lg); for(cmTargets::iterator t = targets.begin(); t != targets.end(); ++t) { if (((t->second.GetType() == cmTarget::EXECUTABLE) || @@ -779,6 +745,8 @@ cmGlobalUnixMakefileGenerator3 t->second.GetName() && strlen(t->second.GetName())) { + bool needRequiresStep = + this->NeedRequiresStep(lg,t->second.GetName()); // Add a rule to build the target by name. localName = lg->GetRelativeTargetDirectory(t->second); std::string makefileName = localName; @@ -1006,10 +974,10 @@ cmGlobalUnixMakefileGenerator3::WriteHelpRule(std::ostream& ruleFileStream) bool cmGlobalUnixMakefileGenerator3 -::NeedRequiresStep(cmLocalUnixMakefileGenerator3 *lg) +::NeedRequiresStep(cmLocalUnixMakefileGenerator3 *lg,const char *name) { std::map<cmStdString,cmLocalUnixMakefileGenerator3::IntegrityCheckSet>& - checkSet = lg->GetIntegrityCheckSet(); + checkSet = lg->GetIntegrityCheckSet()[name]; for(std::map<cmStdString, cmLocalUnixMakefileGenerator3::IntegrityCheckSet>::const_iterator l = checkSet.begin(); l != checkSet.end(); ++l) @@ -1022,6 +990,5 @@ bool cmGlobalUnixMakefileGenerator3 return true; } } - return false; } diff --git a/Source/cmGlobalUnixMakefileGenerator3.h b/Source/cmGlobalUnixMakefileGenerator3.h index a17c389fbf..aebc086c48 100644 --- a/Source/cmGlobalUnixMakefileGenerator3.h +++ b/Source/cmGlobalUnixMakefileGenerator3.h @@ -83,12 +83,15 @@ public: * requests that they Generate. */ virtual void Generate(); + + + void WriteMainCMakefileLanguageRules(cmGeneratedFileStream& cmakefileStream, + std::vector<cmLocalGenerator *> &); protected: void WriteMainMakefile(); void WriteMainMakefile2(); void WriteMainCMakefile(); - void WriteMainCMakefileLanguageRules(cmGeneratedFileStream& cmakefileStream); void WriteAllRules(cmLocalUnixMakefileGenerator3 *lg, std::ostream& makefileStream); void WriteHelpRule(std::ostream& ruleFileStream); @@ -111,7 +114,7 @@ protected: const char* name, std::set<cmStdString>& emitted); // does this generator need a requires step for any of its targets - bool NeedRequiresStep(cmLocalUnixMakefileGenerator3 *lg); + bool NeedRequiresStep(cmLocalUnixMakefileGenerator3 *lg, const char *); }; diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index eb36a4f32c..4f620a92b1 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -62,6 +62,17 @@ void cmLocalGenerator::Configure() } } + this->SetupPathConversions(); + + // Check whether relative paths should be used for optionally + // relative paths. + m_UseRelativePaths = m_Makefile->IsOn("CMAKE_USE_RELATIVE_PATHS"); + + this->Configured = true; +} + +void cmLocalGenerator::SetupPathConversions() +{ // Setup the current output directory components for use by // Convert std::string outdir; @@ -76,15 +87,10 @@ void cmLocalGenerator::Configure() cmSystemTools::SplitPath(outdir.c_str(), m_HomeOutputDirectoryComponents); outdir = cmSystemTools::CollapseFullPath(m_Makefile->GetStartOutputDirectory()); - cmSystemTools::SplitPath(outdir.c_str(), m_StartOutputDirectoryComponents); - - // Check whether relative paths should be used for optionally - // relative paths. - m_UseRelativePaths = m_Makefile->IsOn("CMAKE_USE_RELATIVE_PATHS"); - - this->Configured = true; +cmSystemTools::SplitPath(outdir.c_str(), m_StartOutputDirectoryComponents); } + void cmLocalGenerator::SetGlobalGenerator(cmGlobalGenerator *gg) { m_GlobalGenerator = gg; diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h index b5809fd656..3c88e62cc4 100644 --- a/Source/cmLocalGenerator.h +++ b/Source/cmLocalGenerator.h @@ -97,6 +97,9 @@ public: OutputFormat output = UNCHANGED, bool optional = false); + ///! Call this prior to using Convert + void SetupPathConversions(); + /** * Convert the given path to an output path that is optionally * relative based on the cache option CMAKE_USE_RELATIVE_PATHS. The diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx index 736ca83ae4..d5d939ca8b 100644 --- a/Source/cmLocalUnixMakefileGenerator3.cxx +++ b/Source/cmLocalUnixMakefileGenerator3.cxx @@ -18,7 +18,7 @@ #include "cmDepends.h" #include "cmGeneratedFileStream.h" -#include "cmGlobalGenerator.h" +#include "cmGlobalUnixMakefileGenerator3.h" #include "cmMakefile.h" #include "cmSourceFile.h" #include "cmake.h" @@ -174,23 +174,18 @@ void cmLocalUnixMakefileGenerator3 // Generate the rule files for each custom command. // get the classes from the source lists then add them to the groups const std::vector<cmSourceFile*> &classes = target.GetSourceFiles(); - std::string objTarget; for(std::vector<cmSourceFile*>::const_iterator i = classes.begin(); i != classes.end(); i++) { if(cmCustomCommand* cc = (*i)->GetCustomCommand()) { cc->Used(); - objTarget = this->GenerateCustomRuleFile(*cc,tgtDir.c_str()); + this->GenerateCustomRuleFile(*cc,tgtDir.c_str(),ruleFileStream); if (clean) { cleanFiles.push_back (this->Convert(cc->GetOutput(),HOME_OUTPUT,SHELL)); } - ruleFileStream - << m_IncludeDirective << " " - << this->ConvertToOutputForExisting(objTarget.c_str()).c_str() - << "\n"; } } } @@ -309,6 +304,49 @@ cmLocalUnixMakefileGenerator3 std::string dir = this->GetTargetDirectory(target); cmSystemTools::MakeDirectory(this->ConvertToFullPath(dir).c_str()); + // Generate the build-time dependencies file for this target. + std::string depBase = dir; + depBase += "/"; + depBase += target.GetName(); + + // Construct the rule file name. + std::string ruleFileName = dir; + ruleFileName += "/build.make"; + + // 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, HOME_OUTPUT); + + // Include the dependencies for the target. + std::string depPath = dir; + depPath += "/depend.make"; + depPath = this->ConvertToFullPath(depPath.c_str()); + depPath = this->Convert(depPath.c_str(),HOME_OUTPUT,MAKEFILE); + ruleFileStream + << "# Include any dependencies generated for this target.\n" + << m_IncludeDirective << " " + << depPath + << "\n\n"; + + // make sure the depend file exists + if (!cmSystemTools::FileExists(depPath.c_str())) + { + // Write an empty dependency file. + cmGeneratedFileStream depFileStream(depPath.c_str()); + depFileStream + << "# Empty dependencies file for " << target.GetName() << ".\n" + << "# This may be replaced when dependencies are built." << std::endl; + } + // First generate the object rule files. Save a list of all object // files for this target. std::vector<std::string> objects; @@ -323,7 +361,8 @@ cmLocalUnixMakefileGenerator3 if(!m_GlobalGenerator->IgnoreFile((*source)->GetSourceExtension().c_str())) { // Generate this object file's rule file. - this->WriteObjectRuleFiles(target, *(*source), objects); + this->WriteObjectRuleFiles(target, *(*source), objects, + ruleFileStream); } else if((*source)->GetPropertyAsBool("EXTERNAL_OBJECT")) { @@ -332,28 +371,6 @@ cmLocalUnixMakefileGenerator3 } } } - - // Generate the build-time dependencies file for this target. - std::string depBase = dir; - depBase += "/"; - depBase += target.GetName(); - - // Construct the rule file name. - std::string ruleFileName = dir; - ruleFileName += "/build.make"; - - // 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, HOME_OUTPUT); // write the custom commands for this target std::vector<std::string> cleanFiles; @@ -368,24 +385,6 @@ cmLocalUnixMakefileGenerator3 // Include the rule file for each object. std::string relPath = this->GetHomeRelativeOutputPath(); std::string objTarget; - if(!objects.empty()) - { - ruleFileStream - << "# Include make rules for object files.\n"; - for(std::vector<std::string>::const_iterator obj = objects.begin(); - obj != objects.end(); ++obj) - { - objTarget = relPath; - objTarget += *obj; - objTarget += ".build.make"; - ruleFileStream - << m_IncludeDirective << " " - << this->ConvertToOutputForExisting(objTarget.c_str()).c_str() - << "\n"; - } - ruleFileStream - << "\n"; - } // Write the rule for this target type. switch(target.GetType()) @@ -427,20 +426,10 @@ cmLocalUnixMakefileGenerator3 ::WriteObjectDependRules(std::ostream& ruleFileStream, std::string &obj, const char * lang, - const cmSourceFile& source, + cmSourceFile& source, std::vector<std::string>& depends, std::string& depMakeFile) { - // Generate the build-time dependencies file for this object file. - std::string depMarkFile; - if(!this->GenerateDependsMakeFile(lang, obj.c_str(), - depMakeFile, depMarkFile)) - { - cmSystemTools::Error("No dependency checker available for language \"", - lang, "\"."); - return; - } - // Create the list of dependencies known at cmake time. These are // shared between the object file and dependency scanning rule. depends.push_back(source.GetFullPath()); @@ -454,40 +443,6 @@ cmLocalUnixMakefileGenerator3 depends.push_back(i->c_str()); } } - - // Write the dependency generation rule. - std::string relativeObj = this->GetHomeRelativeOutputPath(); - relativeObj += obj; - std::vector<std::string> commands; - std::string depEcho = "Scanning "; - depEcho += lang; - depEcho += " dependencies of "; - depEcho += this->Convert(relativeObj.c_str(),NONE,SHELL); - this->AppendEcho(commands, depEcho.c_str()); - - // Add a command to call CMake to scan dependencies. CMake will - // touch the corresponding depends file after scanning dependencies. - cmOStringStream depCmd; - // TODO: Account for source file properties and directory-level - // definitions when scanning for dependencies. - depCmd << "$(CMAKE_COMMAND) -E cmake_depends " - << " \"" - << m_GlobalGenerator->GetName() << "\" " - << this->Convert(m_Makefile->GetHomeOutputDirectory(),FULL,SHELL) - << " " - << this->Convert(m_Makefile->GetStartOutputDirectory(),FULL,SHELL) - << " " - << lang << " " - << relativeObj.c_str() << " " - << this->Convert(source.GetFullPath().c_str(),HOME_OUTPUT,SHELL); - commands.push_back(depCmd.str()); - - // compute the target - std::string relPath = this->GetHomeRelativeOutputPath(); - relPath += depMarkFile; - // Write the rule. - this->WriteMakeRule(ruleFileStream, 0, - relPath.c_str(), depends, commands); } @@ -497,24 +452,16 @@ cmLocalUnixMakefileGenerator3 ::WriteObjectBuildFile(std::string &obj, const char *lang, cmTarget& target, - const cmSourceFile& source, + cmSourceFile& source, std::vector<std::string>& depends, - std::string &depMakeFile) + std::string &depMakeFile, + std::ostream &ruleFileStream) { // Open the rule file for writing. This should be copy-if-different // because the rules may depend on this file itself. - std::string ruleFileName = obj; - ruleFileName += ".build.make"; + std::string ruleFileName = this->GetTargetDirectory(target); + ruleFileName += "/build.make"; std::string ruleFileNameFull = this->ConvertToFullPath(ruleFileName); - cmGeneratedFileStream ruleFileStream(ruleFileNameFull.c_str()); - ruleFileStream.SetCopyIfDifferent(true); - if(!ruleFileStream) - { - return; - } - this->WriteDisclaimer(ruleFileStream); - ruleFileStream - << "# Rule file for object file " << obj.c_str() << ".\n\n"; // generate the depend scanning rule this->WriteObjectDependRules(ruleFileStream, obj, lang, source, @@ -522,16 +469,6 @@ cmLocalUnixMakefileGenerator3 this->AppendRuleDepend(depends, ruleFileNameFull.c_str()); - // Include the dependencies for the target. - std::string depPath = this->GetHomeRelativeOutputPath(); - depPath += depMakeFile; - depMakeFile = this->Convert(depPath.c_str(),HOME_OUTPUT,MAKEFILE); - ruleFileStream - << "# Include any dependencies generated for this rule.\n" - << m_IncludeDirective << " " - << depMakeFile - << "\n\n"; - // Write the build rule. // Build the set of compiler flags. std::string flags; @@ -649,8 +586,9 @@ cmLocalUnixMakefileGenerator3 //---------------------------------------------------------------------------- void cmLocalUnixMakefileGenerator3 -::WriteObjectRuleFiles(cmTarget& target, const cmSourceFile& source, - std::vector<std::string>& objects) +::WriteObjectRuleFiles(cmTarget& target, cmSourceFile& source, + std::vector<std::string>& objects, + std::ostream &ruleFileStream) { // Identify the language of the source file. const char* lang = this->GetSourceFileLanguage(source); @@ -698,50 +636,25 @@ cmLocalUnixMakefileGenerator3 std::string depMakeFile; // generate the build rule file - this->WriteObjectBuildFile(obj, lang, target, source, depends, depMakeFile); + this->WriteObjectBuildFile(obj, lang, target, source, depends, depMakeFile, + ruleFileStream); // The object file should be checked for dependency integrity. - m_CheckDependFiles[lang].insert(relativeObj); - + m_CheckDependFiles[target.GetName()][lang].insert(&source); + // add this to the list of objects for this local generator m_LocalObjectFiles[cmSystemTools::GetFilenameName(obj)].push_back(&target); } //---------------------------------------------------------------------------- -std::string +void cmLocalUnixMakefileGenerator3 -::GenerateCustomRuleFile(const cmCustomCommand& cc, const char *dir) +::GenerateCustomRuleFile(const cmCustomCommand& cc, const char *dir, + std::ostream &ruleFileStream) { // Convert the output name to a relative path if possible. std::string output = this->Convert(cc.GetOutput(),START_OUTPUT); - // Construct the name of the rule file by transforming the output - // name to a valid file name. Since the output is already a file - // everything but the path characters is valid. - std::string customName = output; - cmSystemTools::ReplaceString(customName, "../", "___"); - cmSystemTools::ReplaceString(customName, "/", "_"); - cmSystemTools::ReplaceString(customName, ":", "_"); - std::string ruleFileName = dir; - ruleFileName += "/"; - ruleFileName += customName; - ruleFileName += ".build.make"; - - // what is the relative path to the rule file - std::string relRuleFile = this->Convert(ruleFileName.c_str(),HOME_OUTPUT); - - // Open the rule file. This should be copy-if-different because the - // rules may depend on this file itself. - cmGeneratedFileStream ruleFileStream(ruleFileName.c_str()); - ruleFileStream.SetCopyIfDifferent(true); - if(!ruleFileStream) - { - return relRuleFile; - } - this->WriteDisclaimer(ruleFileStream); - ruleFileStream - << "# Custom command rule file for " << output.c_str() << ".\n\n"; - // Collect the commands. std::vector<std::string> commands; std::string preEcho = "Generating "; @@ -753,9 +666,6 @@ cmLocalUnixMakefileGenerator3 std::vector<std::string> depends; this->AppendCustomDepend(depends, cc); - // Add a dependency on the rule file itself. - this->AppendRuleDepend(depends, relRuleFile.c_str()); - // Write the rule. const char* comment = 0; if(cc.GetComment() && *cc.GetComment()) @@ -764,8 +674,6 @@ cmLocalUnixMakefileGenerator3 } this->WriteMakeRule(ruleFileStream, comment, cc.GetOutput(), depends, commands); - - return relRuleFile; } //---------------------------------------------------------------------------- @@ -850,19 +758,17 @@ cmLocalUnixMakefileGenerator3 { // Construct a checker for the given language. std::auto_ptr<cmDepends> - checker(this->GetDependsChecker(lang, - m_Makefile->GetStartOutputDirectory(), - objFile, false)); + checker(this->GetDependsChecker(lang,false)); if(checker.get()) { - // Save the make and mark file names. - depMakeFile = checker->GetMakeFileName(); - depMarkFile = checker->GetMarkFileName(); - // Check the dependencies. Ths is required because we need at least an // empty foo.obj.depends.make for make to include, so at cmake time the // ::Check() method will generate that if it does not exist - checker->Check(); + + + // Todo: could just make sure that file exists, + // use different method not check + checker->Check(objFile); return true; } @@ -1885,13 +1791,62 @@ cmLocalUnixMakefileGenerator3 cmTarget& target, const std::vector<std::string>& objects) { + // must write the targets depend info file + std::string dir = this->GetTargetDirectory(target); + std::string infoFileName = dir; + infoFileName += "/DependInfo.cmake"; + std::string ruleFileNameFull = this->ConvertToFullPath(infoFileName); + cmGeneratedFileStream infoFileStream(ruleFileNameFull.c_str()); + infoFileStream.SetCopyIfDifferent(true); + if(!infoFileStream) + { + return; + } + cmGlobalUnixMakefileGenerator3 *gg = + static_cast<cmGlobalUnixMakefileGenerator3 *>(m_GlobalGenerator); + this->WriteDependLanguageInfo(infoFileStream,target); + + // and now write the rule to use it std::vector<std::string> depends; - std::vector<std::string> no_commands; + std::vector<std::string> commands; // Construct the name of the dependency generation target. std::string depTarget = this->GetRelativeTargetDirectory(target); depTarget += "/depend"; + + std::string depMark = depTarget; + depMark += ".make.mark"; + depends.push_back(depMark); + + this->WriteMakeRule(ruleFileStream, 0, + depTarget.c_str(), depends, commands); + depends.clear(); + + // Write the dependency generation rule. + std::string depEcho = "Scanning dependencies of target "; + depEcho += target.GetName(); + this->AppendEcho(commands, depEcho.c_str()); + + // Add a command to call CMake to scan dependencies. CMake will + // touch the corresponding depends file after scanning dependencies. + cmOStringStream depCmd; + // TODO: Account for source file properties and directory-level + // definitions when scanning for dependencies. + depCmd << "$(CMAKE_COMMAND) -E cmake_depends " + << " \"" + << m_GlobalGenerator->GetName() << "\" " + << this->Convert(m_Makefile->GetHomeOutputDirectory(),FULL,SHELL) + << " " + << this->Convert(m_Makefile->GetStartOutputDirectory(),FULL,SHELL) + << " " + << this->Convert(ruleFileNameFull.c_str(),FULL,SHELL); + commands.push_back(depCmd.str()); + + // Write the rule. + this->WriteMakeRule(ruleFileStream, 0, + depMark.c_str(), depends, commands); +#if 0 // This target drives dependency generation for all object files. std::string relPath = this->GetHomeRelativeOutputPath(); std::string objTarget; @@ -1903,10 +1858,7 @@ cmLocalUnixMakefileGenerator3 objTarget += ".depend"; depends.push_back(objTarget); } - - // Write the rule. - this->WriteMakeRule(ruleFileStream, 0, - depTarget.c_str(), depends, no_commands); +#endif } //---------------------------------------------------------------------------- @@ -2632,8 +2584,6 @@ cmLocalUnixMakefileGenerator3 //---------------------------------------------------------------------------- cmDepends* cmLocalUnixMakefileGenerator3::GetDependsChecker(const std::string& lang, - const char* dir, - const char* objFile, bool verbose) { cmDepends *ret = 0; @@ -2653,8 +2603,6 @@ cmLocalUnixMakefileGenerator3::GetDependsChecker(const std::string& lang, #endif if (ret) { - ret->SetTargetFile(dir, objFile, ".depend",".build.depend.make"); - ret->SetCompileDirectory(m_Makefile->GetHomeOutputDirectory()); ret->SetVerbose(verbose); } return ret; @@ -2666,17 +2614,11 @@ cmLocalUnixMakefileGenerator3 ::ScanDependencies(std::vector<std::string> const& args) { // Format of arguments is: - // $(CMAKE_COMMAND), cmake_depends, home_output_dir, start_output_dir, GeneratorName, <lang>, <obj>, <src> + // $(CMAKE_COMMAND), cmake_depends, GeneratorName, home_output_dir, start_output_dir, info file // The caller has ensured that all required arguments exist. - // The language for which we are scanning dependencies. - std::string const& lang = args[5]; - - // The file to which to write dependencies. - const char* objFile = args[6].c_str(); - - // The source file at which to start the scan. - const char* srcFile = args[7].c_str(); + // The info file for this target + std::string const& infoFile = args[5]; // Read the directory information file. cmake cm; @@ -2686,7 +2628,9 @@ cmLocalUnixMakefileGenerator3 lg->SetGlobalGenerator(&gg); cmMakefile* mf = lg->GetMakefile(); mf->SetHomeOutputDirectory(args[3].c_str()); - mf->SetStartOutputDirectory(args[4].c_str()); + mf->SetStartOutputDirectory(args[4].c_str()); + lg->SetupPathConversions(); + bool haveDirectoryInfo = false; std::string dirInfoFile = args[4]; dirInfoFile += "/CMakeDirectoryInformation.cmake"; @@ -2696,6 +2640,13 @@ cmLocalUnixMakefileGenerator3 haveDirectoryInfo = true; } + // read in the target info file + if(!mf->ReadListFile(0, infoFile.c_str()) || + cmSystemTools::GetErrorOccuredFlag()) + { + cmSystemTools::Error("Target DependInfo.cmake file not found"); + } + // Test whether we need to force Unix paths. if(haveDirectoryInfo) { @@ -2711,66 +2662,116 @@ cmLocalUnixMakefileGenerator3 { cmSystemTools::Error("Directory Information file not found"); } - - // Get the set of include directories. - std::vector<std::string> includes; - if(haveDirectoryInfo) + // create the file stream for the depends file + std::string dir = cmSystemTools::GetFilenamePath(infoFile); + dir += "/depend.make"; + + // Open the rule file. This should be copy-if-different because the + // rules may depend on this file itself. + std::string ruleFileNameFull = dir; + cmGeneratedFileStream ruleFileStream(ruleFileNameFull.c_str()); + ruleFileStream.SetCopyIfDifferent(true); + if(!ruleFileStream) { - std::string includePathVar = "CMAKE_"; - includePathVar += lang; - includePathVar += "_INCLUDE_PATH"; - if(const char* includePath = mf->GetDefinition(includePathVar.c_str())) + return false; + } + this->WriteDisclaimer(ruleFileStream); + + // for each language we need to scan, scan it + const char *langStr = mf->GetSafeDefinition("CMAKE_DEPENDS_LANGUAGES"); + std::vector<std::string> langs; + cmSystemTools::ExpandListArgument(langStr, langs); + for (std::vector<std::string>::iterator li = + langs.begin(); li != langs.end(); ++li) + { + // construct the checker + std::string lang = li->c_str(); + + // Get the set of include directories. + std::vector<std::string> includes; + if(haveDirectoryInfo) { - cmSystemTools::ExpandListArgument(includePath, includes); + std::string includePathVar = "CMAKE_"; + includePathVar += lang; + includePathVar += "_INCLUDE_PATH"; + if(const char* includePath = mf->GetDefinition(includePathVar.c_str())) + { + cmSystemTools::ExpandListArgument(includePath, includes); + } } - } - - // Get the include file regular expression. - std::string includeRegexScan = "^.*$"; - std::string includeRegexComplain = "^$"; - if(haveDirectoryInfo) - { - std::string scanRegexVar = "CMAKE_"; - scanRegexVar += lang; - scanRegexVar += "_INCLUDE_REGEX_SCAN"; - if(const char* scanRegex = mf->GetDefinition(scanRegexVar.c_str())) + + // Get the include file regular expression. + std::string includeRegexScan = "^.*$"; + std::string includeRegexComplain = "^$"; + if(haveDirectoryInfo) { - includeRegexScan = scanRegex; + std::string scanRegexVar = "CMAKE_"; + scanRegexVar += lang; + scanRegexVar += "_INCLUDE_REGEX_SCAN"; + if(const char* scanRegex = mf->GetDefinition(scanRegexVar.c_str())) + { + includeRegexScan = scanRegex; + } + std::string complainRegexVar = "CMAKE_"; + complainRegexVar += lang; + complainRegexVar += "_INCLUDE_REGEX_COMPLAIN"; + if(const char* complainRegex = mf->GetDefinition(complainRegexVar.c_str())) + { + includeRegexComplain = complainRegex; + } } - std::string complainRegexVar = "CMAKE_"; - complainRegexVar += lang; - complainRegexVar += "_INCLUDE_REGEX_COMPLAIN"; - if(const char* complainRegex = mf->GetDefinition(complainRegexVar.c_str())) + + // Create the scanner for this language + cmDepends *scanner = 0; + if(lang == "C" || lang == "CXX" || lang == "RC") { - includeRegexComplain = complainRegex; + // TODO: Handle RC (resource files) dependencies correctly. + scanner = new cmDependsC(includes, + includeRegexScan.c_str(), + includeRegexComplain.c_str()); } - } - - // Dispatch the scan for each language. - if(lang == "C" || lang == "CXX" || lang == "RC") - { - // TODO: Handle RC (resource files) dependencies correctly. - cmDependsC scanner(srcFile, includes, - includeRegexScan.c_str(), includeRegexComplain.c_str()); - scanner.SetTargetFile(".",objFile,".depend",".build.depend.make"); - return scanner.Write(); - } #ifdef CMAKE_BUILD_WITH_CMAKE - else if(lang == "Fortran") - { - cmDependsFortran scanner(srcFile, includes); - scanner.SetTargetFile(".",objFile,".depend",".build.depend.make"); - return scanner.Write(); - } - else if(lang == "Java") - { - cmDependsJava scanner(srcFile); - scanner.SetTargetFile(".",objFile,".depend",".build.depend.make"); - return scanner.Write(); - } + else if(lang == "Fortran") + { + scanner = new cmDependsFortran(includes); + } + else if(lang == "Java") + { + scanner = new cmDependsJava(); + } #endif - return false; + + // for each file we need to scan + std::string srcLang = "CMAKE_DEPENDS_CHECK_"; + srcLang += lang; + const char *srcStr = mf->GetSafeDefinition(srcLang.c_str()); + std::vector<std::string> srcs; + cmSystemTools::ExpandListArgument(srcStr, srcs); + for (std::vector<std::string>::iterator si = + srcs.begin(); si != srcs.end(); ++si) + { + std::string &src = *si; + ++si; + // make sure the object file is relative to home output + std::string obj = *si; + obj = lg->Convert(obj.c_str(),HOME_OUTPUT,MAKEFILE); + scanner->Write(src.c_str(),obj.c_str(),ruleFileStream); + } + + // free the scanner for this language + if (scanner) + { + delete scanner; + } + } + + // dependencies were generated, so touch the mark file + dir += ".mark"; + std::ofstream fmark(dir.c_str()); + fmark << "Dependencies updated>" << std::endl; + + return true; } //---------------------------------------------------------------------------- @@ -2942,45 +2943,31 @@ void cmLocalUnixMakefileGenerator3::CheckDependencies(cmMakefile* mf, bool verbose, bool clear) { - // Get the list of languages that may have sources to check. - const char* langDef = mf->GetDefinition("CMAKE_DEPENDS_LANGUAGES"); - if(!langDef) + // Get the list of target files to check + const char* infoDef = mf->GetDefinition("CMAKE_DEPEND_INFO_FILES"); + if(!infoDef) { return; } - std::vector<std::string> languages; - cmSystemTools::ExpandListArgument(langDef, languages); + std::vector<std::string> files; + cmSystemTools::ExpandListArgument(infoDef, files); - // For each language get the set of files to check. - for(std::vector<std::string>::iterator l = languages.begin(); - l != languages.end(); ++l) + // For each info file run the check + cmDependsC checker; + checker.SetVerbose(verbose); + for(std::vector<std::string>::iterator l = files.begin(); + l != files.end(); ++l) { - std::string depCheck = "CMAKE_DEPENDS_CHECK_"; - depCheck += *l; - if(const char* fileDef = mf->GetDefinition(depCheck.c_str())) + // either clear or check the files + std::string dependFile = cmSystemTools::GetFilenamePath(l->c_str()); + dependFile += "/depend.make"; + if (clear) { - // Check each file. The current working directory is already - // correct. - std::vector<std::string> files; - cmSystemTools::ExpandListArgument(fileDef, files); - for(std::vector<std::string>::iterator f = files.begin(); - f != files.end(); ++f) - { - // Construct a checker for the given language. - std::auto_ptr<cmDepends> - checker(this->GetDependsChecker(*l, ".", f->c_str(), verbose)); - if(checker.get()) - { - if (clear) - { - checker->Clear(); - } - else - { - checker->Check(); - } - } - } + checker.Clear(dependFile.c_str()); + } + else + { + checker.Check(dependFile.c_str()); } } } @@ -3063,3 +3050,58 @@ cmLocalUnixMakefileGenerator3::WriteHelpRule(std::ostream& ruleFileStream) no_depends, commands); ruleFileStream << "\n\n"; } + +void cmLocalUnixMakefileGenerator3 +::WriteDependLanguageInfo(std::ostream& cmakefileStream, cmTarget &target) +{ + // now write all the language stuff + // Set the set of files to check for dependency integrity. + std::set<cmStdString> checkSetLangs; + std::map<cmStdString,cmLocalUnixMakefileGenerator3::IntegrityCheckSet>& + checkSet = this->GetIntegrityCheckSet()[target.GetName()]; + for(std::map<cmStdString, + cmLocalUnixMakefileGenerator3::IntegrityCheckSet>::const_iterator + l = checkSet.begin(); l != checkSet.end(); ++l) + { + checkSetLangs.insert(l->first); + } + + // list the languages + cmakefileStream + << "# The set of files whose dependency integrity should be checked:\n"; + cmakefileStream + << "SET(CMAKE_DEPENDS_LANGUAGES\n"; + for(std::set<cmStdString>::iterator + l = checkSetLangs.begin(); l != checkSetLangs.end(); ++l) + { + cmakefileStream << " \"" << l->c_str() << "\"\n"; + } + cmakefileStream << " )\n"; + + // now list the files for each language + for(std::set<cmStdString>::iterator + l = checkSetLangs.begin(); l != checkSetLangs.end(); ++l) + { + cmakefileStream + << "SET(CMAKE_DEPENDS_CHECK_" << l->c_str() << "\n"; + // get the check set for this local gen and language + cmLocalUnixMakefileGenerator3::IntegrityCheckSet iCheckSet = + checkSet[*l]; + // for each file + for(cmLocalUnixMakefileGenerator3::IntegrityCheckSet::const_iterator + csIter = iCheckSet.begin(); + csIter != iCheckSet.end(); ++csIter) + { + cmakefileStream << " \"" << (*csIter)->GetFullPath() << "\"\n"; + // Get the full path name of the object file. + std::string obj = this->GetObjectFileName(target, **csIter); + cmakefileStream << " \"" << + this->Convert(obj.c_str(), + cmLocalGenerator::FULL).c_str() << "\"\n"; + } + cmakefileStream << " )\n"; + } + + + +} diff --git a/Source/cmLocalUnixMakefileGenerator3.h b/Source/cmLocalUnixMakefileGenerator3.h index df27dadb27..97f7f10f49 100644 --- a/Source/cmLocalUnixMakefileGenerator3.h +++ b/Source/cmLocalUnixMakefileGenerator3.h @@ -140,8 +140,9 @@ public: // List the files for which to check dependency integrity. Each // language has its own list because integrity may be checked // differently. - struct IntegrityCheckSet: public std::set<cmStdString> {}; - std::map<cmStdString, IntegrityCheckSet> &GetIntegrityCheckSet() + struct IntegrityCheckSet: public std::set<cmSourceFile *> {}; + struct IntegrityCheckSetMap: public std::map<cmStdString, IntegrityCheckSet> {}; + std::map<cmStdString, IntegrityCheckSetMap> &GetIntegrityCheckSet() { return m_CheckDependFiles;} void AppendTargetDepends(std::vector<std::string>& depends, @@ -155,6 +156,9 @@ public: protected: + // write the depend info + void WriteDependLanguageInfo(std::ostream& cmakefileStream, cmTarget &tgt); + // write the target rules for the local Makefile into the stream void WriteLocalMakefileTargets(std::ostream& ruleFileStream); @@ -195,22 +199,24 @@ protected: // create the rule files for an object void WriteObjectRuleFiles(cmTarget& target, - const cmSourceFile& source, - std::vector<std::string>& objects); + cmSourceFile& source, + std::vector<std::string>& objects, + std::ostream &filestr); // write the build rule for an object void WriteObjectBuildFile(std::string &obj, const char *lang, cmTarget& target, - const cmSourceFile& source, + cmSourceFile& source, std::vector<std::string>& depends, - std::string &depMakeFile); + std::string &depMakeFile, + std::ostream &filestr); // write the depend.make file for an object void WriteObjectDependRules(std::ostream& ruleFileStream, std::string& obj, const char *lang, - const cmSourceFile& source, + cmSourceFile& source, std::vector<std::string>& depends, std::string& depMarkFile); @@ -222,13 +228,12 @@ protected: // return the appropriate depends checker cmDepends* GetDependsChecker(const std::string& lang, - const char* dir, - const char* objFile, bool verbose); - std::string GenerateCustomRuleFile(const cmCustomCommand& cc, - const char *dir); + void GenerateCustomRuleFile(const cmCustomCommand& cc, + const char *dir, + std::ostream &ruleStream); // these three make some simple changes and then call WriteLibraryRule void WriteStaticLibraryRule(std::ostream& ruleFileStream, @@ -327,7 +332,7 @@ protected: void ComputeHomeRelativeOutputPath(); private: - std::map<cmStdString, IntegrityCheckSet> m_CheckDependFiles; + std::map<cmStdString, IntegrityCheckSetMap> m_CheckDependFiles; //========================================================================== // Configuration settings. diff --git a/Source/cmake.cxx b/Source/cmake.cxx index c64e3b295d..bcb67a177f 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -887,7 +887,7 @@ int cmake::CMakeCommand(std::vector<std::string>& args) } // Internal CMake dependency scanning support. - else if (args[1] == "cmake_depends" && args.size() >= 8) + else if (args[1] == "cmake_depends" && args.size() >= 6) { cmake cm; cmGlobalGenerator *ggd = cm.CreateGlobalGenerator(args[2].c_str()); |