From b4e8f49b95bc13939347623b2b9f236e22bd37ec Mon Sep 17 00:00:00 2001 From: Alex Neundorf Date: Sun, 30 Sep 2012 10:22:06 +0200 Subject: [PATCH 1/6] cmDependsC: remove unused member variable Alex --- Source/cmDependsC.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/Source/cmDependsC.h b/Source/cmDependsC.h index bd9a4b7b4..74f764d2a 100644 --- a/Source/cmDependsC.h +++ b/Source/cmDependsC.h @@ -32,8 +32,6 @@ public: virtual ~cmDependsC(); protected: - typedef std::vector t_CharBuffer; - // Implement writing/checking methods required by superclass. virtual bool WriteDependencies(const char *src, const char *file, @@ -82,7 +80,6 @@ protected: const std::map* ValidDeps; std::set Encountered; std::queue Unscanned; - t_CharBuffer Buffer; std::map FileCache; std::map HeaderLocationCache; From 3e7d97d45d167ddab5ebef6a6fd936df3441c4c9 Mon Sep 17 00:00:00 2001 From: Alex Neundorf Date: Sun, 30 Sep 2012 10:57:59 +0200 Subject: [PATCH 2/6] cmDependsC: remove code duplication This patch reduces a bit code duplication by changing the way how the case that we already have valid dependencies for a file is handled. Instead of having the code for writing the depend-files twice, we now fill the existing dependencies into the same set and then write it out once at the end of cmDependsC::WriteDependencies() Alex Inspired-by: Michael Wild --- Source/cmDependsC.cxx | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/Source/cmDependsC.cxx b/Source/cmDependsC.cxx index 44841a900..b76042988 100644 --- a/Source/cmDependsC.cxx +++ b/Source/cmDependsC.cxx @@ -113,32 +113,26 @@ bool cmDependsC::WriteDependencies(const char *src, const char *obj, return false; } + std::set dependencies; + bool haveDeps = false; + if (this->ValidDeps != 0) { std::map::const_iterator tmpIt = this->ValidDeps->find(obj); if (tmpIt!= this->ValidDeps->end()) { - // Write the dependencies to the output stream. Makefile rules - // written by the original local generator for this directory - // convert the dependencies to paths relative to the home output - // directory. We must do the same here. - internalDepends << obj << std::endl; for(DependencyVector::const_iterator i=tmpIt->second.begin(); i != tmpIt->second.end(); ++i) { - makeDepends << obj << ": " << - this->LocalGenerator->Convert(i->c_str(), - cmLocalGenerator::HOME_OUTPUT, - cmLocalGenerator::MAKEFILE) - << std::endl; - internalDepends << " " << i->c_str() << std::endl; + dependencies.insert(*i); } - makeDepends << std::endl; - return true; + haveDeps = true; } } + if (!haveDeps) + { // Walk the dependency graph starting with the source file. bool first = true; UnscannedEntry root; @@ -146,7 +140,6 @@ bool cmDependsC::WriteDependencies(const char *src, const char *obj, this->Unscanned.push(root); this->Encountered.clear(); this->Encountered.insert(src); - std::set dependencies; std::set scanned; // Use reserve to allocate enough memory for tempPathStr @@ -269,6 +262,7 @@ bool cmDependsC::WriteDependencies(const char *src, const char *obj, first = false; } + } // Write the dependencies to the output stream. Makefile rules // written by the original local generator for this directory From ecc77d09b8996b59bf22bc36e06fa4bb52d665ee Mon Sep 17 00:00:00 2001 From: Alex Neundorf Date: Sun, 30 Sep 2012 11:05:45 +0200 Subject: [PATCH 3/6] cmDependsC: fix indentation This is intentionally a separate commit, so the parent commit which changes the logic is small and not mixed with formatting (indentation) changes. So, this patch here does not change any logic. Alex --- Source/cmDependsC.cxx | 228 +++++++++++++++++++++--------------------- 1 file changed, 114 insertions(+), 114 deletions(-) diff --git a/Source/cmDependsC.cxx b/Source/cmDependsC.cxx index b76042988..6d4ac235a 100644 --- a/Source/cmDependsC.cxx +++ b/Source/cmDependsC.cxx @@ -132,137 +132,137 @@ bool cmDependsC::WriteDependencies(const char *src, const char *obj, } if (!haveDeps) - { - // Walk the dependency graph starting with the source file. - bool first = true; - UnscannedEntry root; - root.FileName = src; - this->Unscanned.push(root); - this->Encountered.clear(); - this->Encountered.insert(src); - std::set scanned; - - // Use reserve to allocate enough memory for tempPathStr - // so that during the loops no memory is allocated or freed - std::string tempPathStr; - tempPathStr.reserve(4*1024); - - while(!this->Unscanned.empty()) { - // Get the next file to scan. - UnscannedEntry current = this->Unscanned.front(); - this->Unscanned.pop(); + // Walk the dependency graph starting with the source file. + bool first = true; + UnscannedEntry root; + root.FileName = src; + this->Unscanned.push(root); + this->Encountered.clear(); + this->Encountered.insert(src); + std::set scanned; - // If not a full path, find the file in the include path. - std::string fullName; - if(first || cmSystemTools::FileIsFullPath(current.FileName.c_str())) - { - if(cmSystemTools::FileExists(current.FileName.c_str(), true)) - { - fullName = current.FileName; - } - } - else if(!current.QuotedLocation.empty() && - cmSystemTools::FileExists(current.QuotedLocation.c_str(), true)) - { - // The include statement producing this entry was a double-quote - // include and the included file is present in the directory of - // the source containing the include statement. - fullName = current.QuotedLocation; - } - else - { - std::map::iterator - headerLocationIt=this->HeaderLocationCache.find(current.FileName); - if (headerLocationIt!=this->HeaderLocationCache.end()) - { - fullName=headerLocationIt->second; - } - else for(std::vector::const_iterator i = - this->IncludePath.begin(); i != this->IncludePath.end(); ++i) - { - // Construct the name of the file as if it were in the current - // include directory. Avoid using a leading "./". + // Use reserve to allocate enough memory for tempPathStr + // so that during the loops no memory is allocated or freed + std::string tempPathStr; + tempPathStr.reserve(4*1024); - tempPathStr = ""; - if((*i) == ".") - { - tempPathStr += current.FileName; - } - else - { - tempPathStr += *i; - tempPathStr+="/"; - tempPathStr+=current.FileName; - } + while(!this->Unscanned.empty()) + { + // Get the next file to scan. + UnscannedEntry current = this->Unscanned.front(); + this->Unscanned.pop(); - // Look for the file in this location. - if(cmSystemTools::FileExists(tempPathStr.c_str(), true)) + // If not a full path, find the file in the include path. + std::string fullName; + if(first || cmSystemTools::FileIsFullPath(current.FileName.c_str())) + { + if(cmSystemTools::FileExists(current.FileName.c_str(), true)) { - fullName = tempPathStr; - HeaderLocationCache[current.FileName]=fullName; - break; + fullName = current.FileName; } } - } - - // Complain if the file cannot be found and matches the complain - // regex. - if(fullName.empty() && - this->IncludeRegexComplain.find(current.FileName.c_str())) - { - cmSystemTools::Error("Cannot find file \"", - current.FileName.c_str(), "\"."); - return false; - } - - // Scan the file if it was found and has not been scanned already. - if(!fullName.empty() && (scanned.find(fullName) == scanned.end())) - { - // Record scanned files. - scanned.insert(fullName); - - // Check whether this file is already in the cache - std::map::iterator fileIt= - this->FileCache.find(fullName); - if (fileIt!=this->FileCache.end()) + else if(!current.QuotedLocation.empty() && + cmSystemTools::FileExists(current.QuotedLocation.c_str(), true)) { - fileIt->second->Used=true; - dependencies.insert(fullName); - for (std::vector::const_iterator incIt= - fileIt->second->UnscannedEntries.begin(); - incIt!=fileIt->second->UnscannedEntries.end(); ++incIt) - { - if (this->Encountered.find(incIt->FileName) == - this->Encountered.end()) - { - this->Encountered.insert(incIt->FileName); - this->Unscanned.push(*incIt); - } - } + // The include statement producing this entry was a double-quote + // include and the included file is present in the directory of + // the source containing the include statement. + fullName = current.QuotedLocation; } else { - - // Try to scan the file. Just leave it out if we cannot find - // it. - std::ifstream fin(fullName.c_str()); - if(fin) + std::map::iterator + headerLocationIt=this->HeaderLocationCache.find(current.FileName); + if (headerLocationIt!=this->HeaderLocationCache.end()) { - // Add this file as a dependency. - dependencies.insert(fullName); + fullName=headerLocationIt->second; + } + else for(std::vector::const_iterator i = + this->IncludePath.begin(); i != this->IncludePath.end(); ++i) + { + // Construct the name of the file as if it were in the current + // include directory. Avoid using a leading "./". - // Scan this file for new dependencies. Pass the directory - // containing the file to handle double-quote includes. - std::string dir = cmSystemTools::GetFilenamePath(fullName); - this->Scan(fin, dir.c_str(), fullName); + tempPathStr = ""; + if((*i) == ".") + { + tempPathStr += current.FileName; + } + else + { + tempPathStr += *i; + tempPathStr+="/"; + tempPathStr+=current.FileName; + } + + // Look for the file in this location. + if(cmSystemTools::FileExists(tempPathStr.c_str(), true)) + { + fullName = tempPathStr; + HeaderLocationCache[current.FileName]=fullName; + break; + } } } - } - first = false; + // Complain if the file cannot be found and matches the complain + // regex. + if(fullName.empty() && + this->IncludeRegexComplain.find(current.FileName.c_str())) + { + cmSystemTools::Error("Cannot find file \"", + current.FileName.c_str(), "\"."); + return false; + } + + // Scan the file if it was found and has not been scanned already. + if(!fullName.empty() && (scanned.find(fullName) == scanned.end())) + { + // Record scanned files. + scanned.insert(fullName); + + // Check whether this file is already in the cache + std::map::iterator fileIt= + this->FileCache.find(fullName); + if (fileIt!=this->FileCache.end()) + { + fileIt->second->Used=true; + dependencies.insert(fullName); + for (std::vector::const_iterator incIt= + fileIt->second->UnscannedEntries.begin(); + incIt!=fileIt->second->UnscannedEntries.end(); ++incIt) + { + if (this->Encountered.find(incIt->FileName) == + this->Encountered.end()) + { + this->Encountered.insert(incIt->FileName); + this->Unscanned.push(*incIt); + } + } + } + else + { + + // Try to scan the file. Just leave it out if we cannot find + // it. + std::ifstream fin(fullName.c_str()); + if(fin) + { + // Add this file as a dependency. + dependencies.insert(fullName); + + // Scan this file for new dependencies. Pass the directory + // containing the file to handle double-quote includes. + std::string dir = cmSystemTools::GetFilenamePath(fullName); + this->Scan(fin, dir.c_str(), fullName); + } + } + } + + first = false; + } } - } // Write the dependencies to the output stream. Makefile rules // written by the original local generator for this directory From e74ff7c29fc764af63ed3f5195ecc64730c07939 Mon Sep 17 00:00:00 2001 From: Alex Neundorf Date: Sun, 30 Sep 2012 17:53:01 +0200 Subject: [PATCH 4/6] cmDepends: allow multiple dependees per depender This patch is heavily inspired by Michael Wild. The interfaces cmDepends::Write and cmDepends::WriteDependencies where extended to allow multiple dependees (sources) per depender (object). cmDepends::Write first collect all dependencies into a std::set before passing it to cmDepends::WriteDependencies. cmDependsC::WriteDependencies also first collects all explicit and implicit dependencies into a std::set and only then writes depend.{internal,make}. The implementation of cmDependsFortran simply loops over all sources and proceeds as before, whereas the cmDependsJava implementation is as trivial as before. This is for preventing exponential growth of depend.{internal,make} in the next commit which fixes dependency-vector erasure in cmDepends::CheckDependencies. Inspired-by: Michael Wild --- Source/cmDepends.cxx | 13 +++++++-- Source/cmDepends.h | 6 ++-- Source/cmDependsC.cxx | 33 +++++++++++++-------- Source/cmDependsC.h | 4 +-- Source/cmDependsFortran.cxx | 58 ++++++++++++++++++++----------------- Source/cmDependsFortran.h | 2 +- Source/cmDependsJava.cxx | 6 ++-- Source/cmDependsJava.h | 3 +- 8 files changed, 75 insertions(+), 50 deletions(-) diff --git a/Source/cmDepends.cxx b/Source/cmDepends.cxx index 166a58461..ebe8a6820 100644 --- a/Source/cmDepends.cxx +++ b/Source/cmDepends.cxx @@ -50,6 +50,7 @@ bool cmDepends::Write(std::ostream &makeDepends, std::vector pairs; cmSystemTools::ExpandListArgument(srcStr, pairs); + std::map > dependencies; for(std::vector::iterator si = pairs.begin(); si != pairs.end();) { @@ -62,9 +63,14 @@ bool cmDepends::Write(std::ostream &makeDepends, obj = this->LocalGenerator->Convert(obj.c_str(), cmLocalGenerator::HOME_OUTPUT, cmLocalGenerator::MAKEFILE); + dependencies[obj].insert(src); + } + for(std::map >::const_iterator + it = dependencies.begin(); it != dependencies.end(); ++it) + { // Write the dependencies for this pair. - if(!this->WriteDependencies(src.c_str(), obj.c_str(), + if(!this->WriteDependencies(it->second, it->first, makeDepends, internalDepends)) { return false; @@ -134,8 +140,9 @@ void cmDepends::Clear(const char *file) } //---------------------------------------------------------------------------- -bool cmDepends::WriteDependencies(const char*, const char*, - std::ostream&, std::ostream&) +bool cmDepends::WriteDependencies( + const std::set&, const std::string&, + std::ostream&, std::ostream&) { // This should be implemented by the subclass. return false; diff --git a/Source/cmDepends.h b/Source/cmDepends.h index f7dc8811e..d787eddc6 100644 --- a/Source/cmDepends.h +++ b/Source/cmDepends.h @@ -76,8 +76,10 @@ protected: // Write dependencies for the target file to the given stream. // Return true for success and false for failure. - virtual bool WriteDependencies(const char *src, const char* obj, - std::ostream& makeDepends, std::ostream& internalDepends); + virtual bool WriteDependencies(const std::set& sources, + const std::string& obj, + std::ostream& makeDepends, + std::ostream& internalDepends); // Check dependencies for the target file in the given stream. // Return false if dependencies must be regenerated and true diff --git a/Source/cmDependsC.cxx b/Source/cmDependsC.cxx index 6d4ac235a..43b7b8a60 100644 --- a/Source/cmDependsC.cxx +++ b/Source/cmDependsC.cxx @@ -98,16 +98,18 @@ cmDependsC::~cmDependsC() } //---------------------------------------------------------------------------- -bool cmDependsC::WriteDependencies(const char *src, const char *obj, - std::ostream& makeDepends, std::ostream& internalDepends) +bool cmDependsC::WriteDependencies(const std::set& sources, + const std::string& obj, + std::ostream& makeDepends, + std::ostream& internalDepends) { // Make sure this is a scanning instance. - if(!src || src[0] == '\0') + if(sources.empty() || sources.begin()->empty()) { cmSystemTools::Error("Cannot scan dependencies without a source file."); return false; } - if(!obj || obj[0] == '\0') + if(obj.empty()) { cmSystemTools::Error("Cannot scan dependencies without an object file."); return false; @@ -134,12 +136,18 @@ bool cmDependsC::WriteDependencies(const char *src, const char *obj, if (!haveDeps) { // Walk the dependency graph starting with the source file. - bool first = true; - UnscannedEntry root; - root.FileName = src; - this->Unscanned.push(root); + int srcFiles = (int)sources.size(); this->Encountered.clear(); - this->Encountered.insert(src); + + for(std::set::const_iterator srcIt = sources.begin(); + srcIt != sources.end(); ++srcIt) + { + UnscannedEntry root; + root.FileName = *srcIt; + this->Unscanned.push(root); + this->Encountered.insert(*srcIt); + } + std::set scanned; // Use reserve to allocate enough memory for tempPathStr @@ -155,7 +163,8 @@ bool cmDependsC::WriteDependencies(const char *src, const char *obj, // If not a full path, find the file in the include path. std::string fullName; - if(first || cmSystemTools::FileIsFullPath(current.FileName.c_str())) + if((srcFiles>0) + || cmSystemTools::FileIsFullPath(current.FileName.c_str())) { if(cmSystemTools::FileExists(current.FileName.c_str(), true)) { @@ -260,7 +269,7 @@ bool cmDependsC::WriteDependencies(const char *src, const char *obj, } } - first = false; + srcFiles--; } } @@ -269,7 +278,7 @@ bool cmDependsC::WriteDependencies(const char *src, const char *obj, // convert the dependencies to paths relative to the home output // directory. We must do the same here. internalDepends << obj << std::endl; - for(std::set::iterator i=dependencies.begin(); + for(std::set::const_iterator i=dependencies.begin(); i != dependencies.end(); ++i) { makeDepends << obj << ": " << diff --git a/Source/cmDependsC.h b/Source/cmDependsC.h index 74f764d2a..16dfad7bc 100644 --- a/Source/cmDependsC.h +++ b/Source/cmDependsC.h @@ -33,8 +33,8 @@ public: protected: // Implement writing/checking methods required by superclass. - virtual bool WriteDependencies(const char *src, - const char *file, + virtual bool WriteDependencies(const std::set& sources, + const std::string& obj, std::ostream& makeDepends, std::ostream& internalDepends); diff --git a/Source/cmDependsFortran.cxx b/Source/cmDependsFortran.cxx index 3e660587d..e41e5ea86 100644 --- a/Source/cmDependsFortran.cxx +++ b/Source/cmDependsFortran.cxx @@ -170,44 +170,50 @@ cmDependsFortran::~cmDependsFortran() } //---------------------------------------------------------------------------- -bool cmDependsFortran::WriteDependencies(const char *src, const char *obj, - std::ostream&, std::ostream&) +bool cmDependsFortran::WriteDependencies( + const std::set& sources, const std::string& obj, + std::ostream&, std::ostream&) { // Make sure this is a scanning instance. - if(!src || src[0] == '\0') + if(sources.empty() || sources.begin()->empty()) { - 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') + if(obj.empty()) { cmSystemTools::Error("Cannot scan dependencies without an object file."); return false; } - // Get the information object for this source. - cmDependsFortranSourceInfo& info = - this->Internal->CreateObjectInfo(obj, src); - - // Make a copy of the macros defined via ADD_DEFINITIONS - std::set ppDefines(this->PPDefinitions.begin(), - this->PPDefinitions.end()); - - // Create the parser object. The constructor takes ppMacro and info per - // reference, so we may look into the resulting objects later. - cmDependsFortranParser parser(this, ppDefines, info); - - // Push on the starting file. - cmDependsFortranParser_FilePush(&parser, src); - - // Parse the translation unit. - if(cmDependsFortran_yyparse(parser.Scanner) != 0) + bool okay = true; + for(std::set::const_iterator it = sources.begin(); + it != sources.end(); ++it) { - // Failed to parse the file. Report failure to write dependencies. - return false; - } + const std::string& src = *it; + // Get the information object for this source. + cmDependsFortranSourceInfo& info = + this->Internal->CreateObjectInfo(obj.c_str(), src.c_str()); - return true; + // Make a copy of the macros defined via ADD_DEFINITIONS + std::set ppDefines(this->PPDefinitions.begin(), + this->PPDefinitions.end()); + + // Create the parser object. The constructor takes ppMacro and info per + // reference, so we may look into the resulting objects later. + cmDependsFortranParser parser(this, ppDefines, info); + + // Push on the starting file. + cmDependsFortranParser_FilePush(&parser, src.c_str()); + + // Parse the translation unit. + if(cmDependsFortran_yyparse(parser.Scanner) != 0) + { + // Failed to parse the file. Report failure to write dependencies. + okay = false; + } + } + return okay; } //---------------------------------------------------------------------------- diff --git a/Source/cmDependsFortran.h b/Source/cmDependsFortran.h index cdfde6ea9..cb40796c8 100644 --- a/Source/cmDependsFortran.h +++ b/Source/cmDependsFortran.h @@ -66,7 +66,7 @@ protected: // Implement writing/checking methods required by superclass. virtual bool WriteDependencies( - const char *src, const char *file, + const std::set& sources, const std::string& file, std::ostream& makeDepends, std::ostream& internalDepends); // Actually write the depenencies to the streams. diff --git a/Source/cmDependsJava.cxx b/Source/cmDependsJava.cxx index ba0e8fbe6..949d46515 100644 --- a/Source/cmDependsJava.cxx +++ b/Source/cmDependsJava.cxx @@ -25,11 +25,11 @@ cmDependsJava::~cmDependsJava() } //---------------------------------------------------------------------------- -bool cmDependsJava::WriteDependencies(const char *src, const char *, - std::ostream&, std::ostream&) +bool cmDependsJava::WriteDependencies(const std::set& sources, + const std::string&, std::ostream&, std::ostream&) { // Make sure this is a scanning instance. - if(!src || src[0] == '\0') + if(sources.empty() || sources.begin()->empty()) { cmSystemTools::Error("Cannot scan dependencies without an source file."); return false; diff --git a/Source/cmDependsJava.h b/Source/cmDependsJava.h index bf7e234dc..22af53f8d 100644 --- a/Source/cmDependsJava.h +++ b/Source/cmDependsJava.h @@ -29,7 +29,8 @@ public: protected: // Implement writing/checking methods required by superclass. - virtual bool WriteDependencies(const char *src, const char *file, + virtual bool WriteDependencies( + const std::set& sources, const std::string& file, std::ostream& makeDepends, std::ostream& internalDepends); virtual bool CheckDependencies(std::istream& internalDepends, const char* internalDependsFileName, From c66f03adf93fc402141ed5dc17d39bae1af3bbfd Mon Sep 17 00:00:00 2001 From: Michael Wild Date: Mon, 14 Dec 2009 18:06:51 +0100 Subject: [PATCH 5/6] cmDepends: No dependency-vector erasure in CheckDependencies Some dependency-generators (such as cmDependsFortran) generate multiple entries per depender, so erasing the dependency vector for each depender found loses earlier dependencies. Signed-off-by: Michael Wild --- Source/cmDepends.cxx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Source/cmDepends.cxx b/Source/cmDepends.cxx index ebe8a6820..74a0ccb21 100644 --- a/Source/cmDepends.cxx +++ b/Source/cmDepends.cxx @@ -181,8 +181,10 @@ bool cmDepends::CheckDependencies(std::istream& internalDepends, // kdelibs/khtml this reduces the number of calls from 184k down to 92k, // or the time for cmake -E cmake_depends from 0.3 s down to 0.21 s. dependerExists = cmSystemTools::FileExists(this->Depender); - DependencyVector tmp; - validDeps[this->Depender] = tmp; + // If we erase validDeps[this->Depender] by overwriting it with an empty + // vector, we lose dependencies for dependers that have multiple + // entries. No need to initialize the entry, std::map will do so on first + // access. currentDependencies = &validDeps[this->Depender]; continue; } From 05f162ce9571d1ec7dee6f4c4b76126526247b14 Mon Sep 17 00:00:00 2001 From: Alex Neundorf Date: Sun, 30 Sep 2012 18:34:57 +0200 Subject: [PATCH 6/6] AddCustomCommand: Handle multiple IMPLICIT_DEPENDS files (#10048) The code handling IMPLICIT_DEPENDS was only able to track a single file, the latest file replaced earlier files in the list. The documentation now mentions that the language has to be prefixed to every file and the test now uses two implicit dependencies, where only the second is modified to trigger re-running of the custom command. Alex Inspired-by: Michael Wild --- Source/cmAddCustomCommandCommand.h | 5 ++++- Source/cmLocalUnixMakefileGenerator3.cxx | 10 +++++++--- Source/cmLocalUnixMakefileGenerator3.h | 3 ++- Tests/BuildDepends/Project/CMakeLists.txt | 3 ++- Tests/BuildDepends/Project/dep_custom2.cxx | 2 ++ 5 files changed, 17 insertions(+), 6 deletions(-) create mode 100644 Tests/BuildDepends/Project/dep_custom2.cxx diff --git a/Source/cmAddCustomCommandCommand.h b/Source/cmAddCustomCommandCommand.h index c5252b794..1cc1e3a75 100644 --- a/Source/cmAddCustomCommandCommand.h +++ b/Source/cmAddCustomCommandCommand.h @@ -68,7 +68,8 @@ public: " [COMMAND command2 [ARGS] [args2...] ...]\n" " [MAIN_DEPENDENCY depend]\n" " [DEPENDS [depends...]]\n" - " [IMPLICIT_DEPENDS depend1 ...]\n" + " [IMPLICIT_DEPENDS depend1\n" + " [ depend2] ...]\n" " [WORKING_DIRECTORY dir]\n" " [COMMENT comment] [VERBATIM] [APPEND])\n" "This defines a command to generate specified OUTPUT file(s). " @@ -142,6 +143,8 @@ public: "dependencies of an input file. The language given specifies the " "programming language whose corresponding dependency scanner should " "be used. Currently only C and CXX language scanners are supported. " + "The language has to be specified for every file in the " + "IMPLICIT_DEPENDS list. " "Dependencies discovered from the scanning are added to those of " "the custom command at build time. Note that the IMPLICIT_DEPENDS " "option is currently supported only for Makefile generators and " diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx index db93529dd..820d25a9d 100644 --- a/Source/cmLocalUnixMakefileGenerator3.cxx +++ b/Source/cmLocalUnixMakefileGenerator3.cxx @@ -1939,8 +1939,12 @@ void cmLocalUnixMakefileGenerator3 for(ImplicitDependFileMap::const_iterator pi = implicitPairs.begin(); pi != implicitPairs.end(); ++pi) { - cmakefileStream << " \"" << pi->second << "\" "; - cmakefileStream << "\"" << pi->first << "\"\n"; + for(cmDepends::DependencyVector::const_iterator di = pi->second.begin(); + di != pi->second.end(); ++ di) + { + cmakefileStream << " \"" << *di << "\" "; + cmakefileStream << "\"" << pi->first << "\"\n"; + } } cmakefileStream << " )\n"; @@ -2204,7 +2208,7 @@ cmLocalUnixMakefileGenerator3::AddImplicitDepends(cmTarget const& tgt, const char* obj, const char* src) { - this->ImplicitDepends[tgt.GetName()][lang][obj] = src; + this->ImplicitDepends[tgt.GetName()][lang][obj].push_back(src); } //---------------------------------------------------------------------------- diff --git a/Source/cmLocalUnixMakefileGenerator3.h b/Source/cmLocalUnixMakefileGenerator3.h index e3749590b..703369e1c 100644 --- a/Source/cmLocalUnixMakefileGenerator3.h +++ b/Source/cmLocalUnixMakefileGenerator3.h @@ -209,7 +209,8 @@ public: // File pairs for implicit dependency scanning. The key of the map // is the depender and the value is the explicit dependee. - struct ImplicitDependFileMap: public std::map {}; + struct ImplicitDependFileMap: + public std::map {}; struct ImplicitDependLanguageMap: public std::map {}; struct ImplicitDependTargetMap: diff --git a/Tests/BuildDepends/Project/CMakeLists.txt b/Tests/BuildDepends/Project/CMakeLists.txt index 01f5f6267..542c716b4 100644 --- a/Tests/BuildDepends/Project/CMakeLists.txt +++ b/Tests/BuildDepends/Project/CMakeLists.txt @@ -64,7 +64,8 @@ if("${CMAKE_GENERATOR}" MATCHES "Make") # Test the IMPLICIT_DEPENDS feature. set(ZOT_DEPENDS IMPLICIT_DEPENDS CXX ${CMAKE_CURRENT_SOURCE_DIR}/dep.cxx) set(ZOT_CUSTOM_DEP - IMPLICIT_DEPENDS CXX ${CMAKE_CURRENT_SOURCE_DIR}/dep_custom.cxx) + IMPLICIT_DEPENDS CXX ${CMAKE_CURRENT_SOURCE_DIR}/dep_custom.cxx + CXX ${CMAKE_CURRENT_SOURCE_DIR}/dep_custom2.cxx ) else() # No IMPLICIT_DEPENDS...just depend directly. set(ZOT_DEPENDS DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/zot.hxx.in) diff --git a/Tests/BuildDepends/Project/dep_custom2.cxx b/Tests/BuildDepends/Project/dep_custom2.cxx new file mode 100644 index 000000000..ac9dee120 --- /dev/null +++ b/Tests/BuildDepends/Project/dep_custom2.cxx @@ -0,0 +1,2 @@ +#include +// some comment