summaryrefslogtreecommitdiffstats
path: root/Source
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2012-11-06 19:13:58 (GMT)
committerCMake Topic Stage <kwrobot@kitware.com>2012-11-06 19:13:58 (GMT)
commit3be0a7b4bf22d8b13b53070b8ec40755033f8237 (patch)
treec12c31e0d8db2ec587e378984b6d5e178bc37e1d /Source
parent93a324975cb26ba05481e422f5e3e5abc72c8d3b (diff)
parent05f162ce9571d1ec7dee6f4c4b76126526247b14 (diff)
downloadCMake-3be0a7b4bf22d8b13b53070b8ec40755033f8237.zip
CMake-3be0a7b4bf22d8b13b53070b8ec40755033f8237.tar.gz
CMake-3be0a7b4bf22d8b13b53070b8ec40755033f8237.tar.bz2
Merge topic 'FixImplicitDepends2'
05f162c AddCustomCommand: Handle multiple IMPLICIT_DEPENDS files (#10048) c66f03a cmDepends: No dependency-vector erasure in CheckDependencies e74ff7c cmDepends: allow multiple dependees per depender ecc77d0 cmDependsC: fix indentation 3e7d97d cmDependsC: remove code duplication b4e8f49 cmDependsC: remove unused member variable
Diffstat (limited to 'Source')
-rw-r--r--Source/cmAddCustomCommandCommand.h5
-rw-r--r--Source/cmDepends.cxx19
-rw-r--r--Source/cmDepends.h6
-rw-r--r--Source/cmDependsC.cxx243
-rw-r--r--Source/cmDependsC.h7
-rw-r--r--Source/cmDependsFortran.cxx52
-rw-r--r--Source/cmDependsFortran.h2
-rw-r--r--Source/cmDependsJava.cxx6
-rw-r--r--Source/cmDependsJava.h3
-rw-r--r--Source/cmLocalUnixMakefileGenerator3.cxx10
-rw-r--r--Source/cmLocalUnixMakefileGenerator3.h3
11 files changed, 191 insertions, 165 deletions
diff --git a/Source/cmAddCustomCommandCommand.h b/Source/cmAddCustomCommandCommand.h
index c5252b7..1cc1e3a 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 <lang1> depend1 ...]\n"
+ " [IMPLICIT_DEPENDS <lang1> depend1\n"
+ " [<lang2> 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/cmDepends.cxx b/Source/cmDepends.cxx
index 166a584..74a0ccb 100644
--- a/Source/cmDepends.cxx
+++ b/Source/cmDepends.cxx
@@ -50,6 +50,7 @@ bool cmDepends::Write(std::ostream &makeDepends,
std::vector<std::string> pairs;
cmSystemTools::ExpandListArgument(srcStr, pairs);
+ std::map<std::string, std::set<std::string> > dependencies;
for(std::vector<std::string>::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<std::string, std::set<std::string> >::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<std::string>&, const std::string&,
+ std::ostream&, std::ostream&)
{
// This should be implemented by the subclass.
return false;
@@ -174,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;
}
diff --git a/Source/cmDepends.h b/Source/cmDepends.h
index f7dc881..d787edd 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<std::string>& 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 44841a9..43b7b8a 100644
--- a/Source/cmDependsC.cxx
+++ b/Source/cmDependsC.cxx
@@ -98,176 +98,179 @@ cmDependsC::~cmDependsC()
}
//----------------------------------------------------------------------------
-bool cmDependsC::WriteDependencies(const char *src, const char *obj,
- std::ostream& makeDepends, std::ostream& internalDepends)
+bool cmDependsC::WriteDependencies(const std::set<std::string>& 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;
}
+ std::set<cmStdString> dependencies;
+ bool haveDeps = false;
+
if (this->ValidDeps != 0)
{
std::map<std::string, DependencyVector>::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;
}
}
- // 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<cmStdString> dependencies;
- std::set<cmStdString> scanned;
+ if (!haveDeps)
+ {
+ // Walk the dependency graph starting with the source file.
+ int srcFiles = (int)sources.size();
+ this->Encountered.clear();
+
+ for(std::set<std::string>::const_iterator srcIt = sources.begin();
+ srcIt != sources.end(); ++srcIt)
+ {
+ UnscannedEntry root;
+ root.FileName = *srcIt;
+ this->Unscanned.push(root);
+ this->Encountered.insert(*srcIt);
+ }
- // 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);
+ std::set<cmStdString> scanned;
- while(!this->Unscanned.empty())
- {
- // Get the next file to scan.
- UnscannedEntry current = this->Unscanned.front();
- this->Unscanned.pop();
+ // 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);
- // If not a full path, find the file in the include path.
- std::string fullName;
- if(first || cmSystemTools::FileIsFullPath(current.FileName.c_str()))
+ while(!this->Unscanned.empty())
{
- if(cmSystemTools::FileExists(current.FileName.c_str(), true))
+ // Get the next file to scan.
+ UnscannedEntry current = this->Unscanned.front();
+ this->Unscanned.pop();
+
+ // If not a full path, find the file in the include path.
+ std::string fullName;
+ if((srcFiles>0)
+ || cmSystemTools::FileIsFullPath(current.FileName.c_str()))
{
- fullName = current.FileName;
+ 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<cmStdString, cmStdString>::iterator
- headerLocationIt=this->HeaderLocationCache.find(current.FileName);
- if (headerLocationIt!=this->HeaderLocationCache.end())
+ else if(!current.QuotedLocation.empty() &&
+ cmSystemTools::FileExists(current.QuotedLocation.c_str(), true))
{
- fullName=headerLocationIt->second;
+ // 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 for(std::vector<std::string>::const_iterator i =
- this->IncludePath.begin(); i != this->IncludePath.end(); ++i)
+ else
{
- // Construct the name of the file as if it were in the current
- // include directory. Avoid using a leading "./".
-
- tempPathStr = "";
- if((*i) == ".")
+ std::map<cmStdString, cmStdString>::iterator
+ headerLocationIt=this->HeaderLocationCache.find(current.FileName);
+ if (headerLocationIt!=this->HeaderLocationCache.end())
{
- tempPathStr += current.FileName;
+ fullName=headerLocationIt->second;
}
- else
+ else for(std::vector<std::string>::const_iterator i =
+ this->IncludePath.begin(); i != this->IncludePath.end(); ++i)
{
- tempPathStr += *i;
- tempPathStr+="/";
- tempPathStr+=current.FileName;
- }
+ // Construct the name of the file as if it were in the current
+ // include directory. Avoid using a leading "./".
- // Look for the file in this location.
- if(cmSystemTools::FileExists(tempPathStr.c_str(), true))
- {
- fullName = tempPathStr;
- HeaderLocationCache[current.FileName]=fullName;
- break;
+ 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;
+ }
}
}
- }
-
- // 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);
+ // 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;
+ }
- // Check whether this file is already in the cache
- std::map<cmStdString, cmIncludeLines*>::iterator fileIt=
- this->FileCache.find(fullName);
- if (fileIt!=this->FileCache.end())
+ // Scan the file if it was found and has not been scanned already.
+ if(!fullName.empty() && (scanned.find(fullName) == scanned.end()))
{
- fileIt->second->Used=true;
- dependencies.insert(fullName);
- for (std::vector<UnscannedEntry>::const_iterator incIt=
- fileIt->second->UnscannedEntries.begin();
- incIt!=fileIt->second->UnscannedEntries.end(); ++incIt)
+ // Record scanned files.
+ scanned.insert(fullName);
+
+ // Check whether this file is already in the cache
+ std::map<cmStdString, cmIncludeLines*>::iterator fileIt=
+ this->FileCache.find(fullName);
+ if (fileIt!=this->FileCache.end())
{
- if (this->Encountered.find(incIt->FileName) ==
- this->Encountered.end())
+ fileIt->second->Used=true;
+ dependencies.insert(fullName);
+ for (std::vector<UnscannedEntry>::const_iterator incIt=
+ fileIt->second->UnscannedEntries.begin();
+ incIt!=fileIt->second->UnscannedEntries.end(); ++incIt)
{
- this->Encountered.insert(incIt->FileName);
- this->Unscanned.push(*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)
+ else
{
- // 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);
+ // 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;
+ srcFiles--;
+ }
}
// Write the dependencies to the output stream. Makefile rules
@@ -275,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<cmStdString>::iterator i=dependencies.begin();
+ for(std::set<cmStdString>::const_iterator i=dependencies.begin();
i != dependencies.end(); ++i)
{
makeDepends << obj << ": " <<
diff --git a/Source/cmDependsC.h b/Source/cmDependsC.h
index bd9a4b7..16dfad7 100644
--- a/Source/cmDependsC.h
+++ b/Source/cmDependsC.h
@@ -32,11 +32,9 @@ public:
virtual ~cmDependsC();
protected:
- typedef std::vector<char> t_CharBuffer;
-
// Implement writing/checking methods required by superclass.
- virtual bool WriteDependencies(const char *src,
- const char *file,
+ virtual bool WriteDependencies(const std::set<std::string>& sources,
+ const std::string& obj,
std::ostream& makeDepends,
std::ostream& internalDepends);
@@ -82,7 +80,6 @@ protected:
const std::map<std::string, DependencyVector>* ValidDeps;
std::set<cmStdString> Encountered;
std::queue<UnscannedEntry> Unscanned;
- t_CharBuffer Buffer;
std::map<cmStdString, cmIncludeLines *> FileCache;
std::map<cmStdString, cmStdString> HeaderLocationCache;
diff --git a/Source/cmDependsFortran.cxx b/Source/cmDependsFortran.cxx
index 3e66058..e41e5ea 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<std::string>& 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);
+ bool okay = true;
+ for(std::set<std::string>::const_iterator it = sources.begin();
+ it != sources.end(); ++it)
+ {
+ const std::string& src = *it;
+ // Get the information object for this source.
+ cmDependsFortranSourceInfo& info =
+ this->Internal->CreateObjectInfo(obj.c_str(), src.c_str());
- // Make a copy of the macros defined via ADD_DEFINITIONS
- std::set<std::string> ppDefines(this->PPDefinitions.begin(),
- this->PPDefinitions.end());
+ // Make a copy of the macros defined via ADD_DEFINITIONS
+ std::set<std::string> 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);
+ // 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);
+ // 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.
- return false;
+ // Parse the translation unit.
+ if(cmDependsFortran_yyparse(parser.Scanner) != 0)
+ {
+ // Failed to parse the file. Report failure to write dependencies.
+ okay = false;
+ }
}
-
- return true;
+ return okay;
}
//----------------------------------------------------------------------------
diff --git a/Source/cmDependsFortran.h b/Source/cmDependsFortran.h
index cdfde6e..cb40796 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<std::string>& 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 ba0e8fb..949d465 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<std::string>& 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 bf7e234..22af53f 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<std::string>& sources, const std::string& file,
std::ostream& makeDepends, std::ostream& internalDepends);
virtual bool CheckDependencies(std::istream& internalDepends,
const char* internalDependsFileName,
diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx
index db93529..820d25a 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 e374959..703369e 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<cmStdString, cmStdString> {};
+ struct ImplicitDependFileMap:
+ public std::map<cmStdString, cmDepends::DependencyVector> {};
struct ImplicitDependLanguageMap:
public std::map<cmStdString, ImplicitDependFileMap> {};
struct ImplicitDependTargetMap: