Skip to content

Commit

Permalink
ENH: Improve performance of check build system by creating another fi…
Browse files Browse the repository at this point in the history
…le that is simpler to parse and therefore much faster overall
  • Loading branch information
Andy Cedilnik committed Oct 12, 2005
1 parent a51dfef commit f18e7c7
Show file tree
Hide file tree
Showing 9 changed files with 177 additions and 197 deletions.
109 changes: 102 additions & 7 deletions Source/cmDepends.cxx
Expand Up @@ -18,28 +18,34 @@

#include "cmGeneratedFileStream.h"
#include "cmSystemTools.h"
#include "cmFileTimeComparison.h"

#include <assert.h>

//----------------------------------------------------------------------------
cmDepends::cmDepends()
cmDepends::cmDepends(): m_Verbose(false), m_FileComparison(0),
m_MaxPath(cmSystemTools::GetMaximumFilePathLength()),
m_Dependee(new char[m_MaxPath]),
m_Depender(new char[m_MaxPath])
{
m_Verbose = false;
}

//----------------------------------------------------------------------------
cmDepends::~cmDepends()
{
delete [] m_Dependee;
delete [] m_Depender;
}

//----------------------------------------------------------------------------
bool cmDepends::Write(const char *src, const char *obj, std::ostream &fout)
bool cmDepends::Write(const char *src, const char *obj,
std::ostream &makeDepends, std::ostream &internalDepends)
{
return this->WriteDependencies(src, obj, fout);
return this->WriteDependencies(src, obj, makeDepends, internalDepends);
}

//----------------------------------------------------------------------------
void cmDepends::Check(const char *file)
void cmDepends::Check(const char *makeFile, const char *internalFile)
{
// Dependency checks must be done in proper working directory.
std::string oldcwd = ".";
Expand All @@ -52,11 +58,12 @@ void cmDepends::Check(const char *file)
}

// Check whether dependencies must be regenerated.
std::ifstream fin(file);
std::ifstream fin(internalFile);
if(!(fin && this->CheckDependencies(fin)))
{
// Clear all dependencies so they will be regenerated.
this->Clear(file);
this->Clear(makeFile);
this->Clear(internalFile);
}

// Restore working directory.
Expand All @@ -82,6 +89,7 @@ void cmDepends::Clear(const char *file)
std::string markFile = file;
markFile += ".mark";
cmSystemTools::RemoveFile(markFile.c_str());
std::cout << "Remove mark file: " << markFile.c_str() << std::endl;

// Write an empty dependency file.
cmGeneratedFileStream depFileStream(file);
Expand All @@ -90,3 +98,90 @@ void cmDepends::Clear(const char *file)
<< "# This may be replaced when dependencies are built." << std::endl;
}

//----------------------------------------------------------------------------
bool cmDepends::CheckDependencies(std::istream& internalDepends)
{
// Parse dependencies from the stream. If any dependee is missing
// or newer than the depender then dependencies should be
// regenerated.
bool okay = true;
while(internalDepends.getline(m_Dependee, m_MaxPath))
{
if ( m_Dependee[0] == 0 || m_Dependee[0] == '#' || m_Dependee[0] == '\r' )
{
continue;
}
size_t len = internalDepends.gcount()-1;
if ( m_Dependee[len-1] == '\r' )
{
len --;
m_Dependee[len] = 0;
}
if ( m_Dependee[0] != ' ' )
{
memcpy(m_Depender, m_Dependee, len+1);
continue;
}
/*
// Parse the dependency line.
if(!this->ParseDependency(line.c_str()))
{
continue;
}
*/

// Dependencies must be regenerated if the dependee does not exist
// or if the depender exists and is older than the dependee.
bool regenerate = false;
const char* dependee = m_Dependee+1;
const char* depender = m_Depender;
if(!cmSystemTools::FileExists(dependee))
{
// The dependee does not exist.
regenerate = true;

// Print verbose output.
if(m_Verbose)
{
cmOStringStream msg;
msg << "Dependee \"" << dependee
<< "\" does not exist for depender \""
<< depender << "\"." << std::endl;
cmSystemTools::Stdout(msg.str().c_str());
}
}
else if(cmSystemTools::FileExists(depender))
{
// The dependee and depender both exist. Compare file times.
int result = 0;
if((!m_FileComparison->FileTimeCompare(depender, dependee,
&result) || result < 0))
{
// The depender is older than the dependee.
regenerate = true;

// Print verbose output.
if(m_Verbose)
{
cmOStringStream msg;
msg << "Dependee \"" << dependee
<< "\" is newer than depender \""
<< depender << "\"." << std::endl;
cmSystemTools::Stdout(msg.str().c_str());
}
}
}
if(regenerate)
{
// Dependencies must be regenerated.
okay = false;

// Remove the depender to be sure it is rebuilt.
cmSystemTools::RemoveFile(depender);
}
}

return okay;
}


21 changes: 16 additions & 5 deletions Source/cmDepends.h
Expand Up @@ -19,6 +19,8 @@

#include "cmStandardIncludes.h"

class cmFileTimeComparison;

/** \class cmDepends
* \brief Dependency scanner superclass.
*
Expand All @@ -43,32 +45,41 @@ class cmDepends
virtual ~cmDepends();

/** Write dependencies for the target file. */
bool Write(const char *src, const char *obj, std::ostream &os);
bool Write(const char *src, const char *obj,
std::ostream &makeDepends, std::ostream &internalDepends);

/** Check dependencies for the target file. */
void Check(const char *file);
void Check(const char *makeFile, const char* internalFile);

/** Clear dependencies for the target file so they will be regenerated. */
void Clear(const char *file);

/** Set the file comparison object */
void SetFileComparison(cmFileTimeComparison* fc) { m_FileComparison = fc; }

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& os)=0;
virtual bool WriteDependencies(const char *src, const char* obj,
std::ostream& makeDepends, std::ostream& internalDepends)=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& internalDepends);

// The directory in which the build rule for the target file is executed.
std::string m_Directory;
std::string m_CompileDirectory;

// Flag for verbose output.
bool m_Verbose;
cmFileTimeComparison* m_FileComparison;

size_t m_MaxPath;
char* m_Dependee;
char* m_Depender;

private:
cmDepends(cmDepends const&); // Purposely not implemented.
Expand Down
150 changes: 6 additions & 144 deletions Source/cmDependsC.cxx
Expand Up @@ -45,8 +45,8 @@ cmDependsC::~cmDependsC()
}

//----------------------------------------------------------------------------
bool cmDependsC::WriteDependencies(const char *src,
const char *obj, std::ostream& os)
bool cmDependsC::WriteDependencies(const char *src, const char *obj,
std::ostream& makeDepends, std::ostream& internalDepends)
{
// Make sure this is a scanning instance.
if(!src || src[0] == '\0')
Expand Down Expand Up @@ -161,88 +161,20 @@ bool cmDependsC::WriteDependencies(const char *src,
}

// Write the dependencies to the output stream.
internalDepends << obj << std::endl;
for(std::set<cmStdString>::iterator i=dependencies.begin();
i != dependencies.end(); ++i)
{
os << obj << ": "
makeDepends << obj << ": "
<< cmSystemTools::ConvertToOutputPath(i->c_str()).c_str()
<< std::endl;
internalDepends << " " << i->c_str() << std::endl;
}
os << std::endl;
makeDepends << std::endl;

return true;
}

//----------------------------------------------------------------------------
bool cmDependsC::CheckDependencies(std::istream& is)
{
// Parse dependencies from the stream. If any dependee is missing
// or newer than the depender then dependencies should be
// regenerated.
bool okay = true;
std::string line;
std::string depender;
std::string dependee;
while(cmSystemTools::GetLineFromStream(is, line))
{
// Parse the dependency line.
if(!this->ParseDependency(line.c_str(), depender, dependee))
{
continue;
}

// Dependencies must be regenerated if the dependee does not exist
// or if the depender exists and is older than the dependee.
bool regenerate = false;
if(!cmSystemTools::FileExists(dependee.c_str()))
{
// The dependee does not exist.
regenerate = true;

// Print verbose output.
if(m_Verbose)
{
cmOStringStream msg;
msg << "Dependee \"" << dependee
<< "\" does not exist for depender \""
<< depender << "\"." << std::endl;
cmSystemTools::Stdout(msg.str().c_str());
}
}
else if(cmSystemTools::FileExists(depender.c_str()))
{
// The dependee and depender both exist. Compare file times.
int result = 0;
if((!cmSystemTools::FileTimeCompare(depender.c_str(), dependee.c_str(),
&result) || result < 0))
{
// The depender is older than the dependee.
regenerate = true;

// Print verbose output.
if(m_Verbose)
{
cmOStringStream msg;
msg << "Dependee \"" << dependee
<< "\" is newer than depender \""
<< depender << "\"." << std::endl;
cmSystemTools::Stdout(msg.str().c_str());
}
}
}
if(regenerate)
{
// Dependencies must be regenerated.
okay = false;

// Remove the depender to be sure it is rebuilt.
cmSystemTools::RemoveFile(depender.c_str());
}
}

return okay;
}

//----------------------------------------------------------------------------
void cmDependsC::Scan(std::istream& is, const char* directory)
{
Expand Down Expand Up @@ -282,76 +214,6 @@ void cmDependsC::Scan(std::istream& is, const char* directory)
}
}

//----------------------------------------------------------------------------
bool cmDependsC::ParseDependency(const char* line, std::string& depender,
std::string& dependee)
{
// Start with empty names.
depender = "";
dependee = "";

// Get the left-hand-side of the dependency.
const char* c = this->ParseFileName(line, depender);

// Skip the ':' separator.
for(;c && *c && isspace(*c);++c);
if(!c || !*c || *c != ':')
{
return false;
}
++c;

// Get the right-hand-side of the dependency.
return this->ParseFileName(c, dependee)?true:false;
}

//----------------------------------------------------------------------------
const char* cmDependsC::ParseFileName(const char* in, std::string& name)
{
// Skip leading whitespace.
const char* c = in;
for(;c && *c && isspace(*c);++c);

// If this is an empty line or a comment line return failure.
if(!c || !*c || *c == '#')
{
return 0;
}

// Parse the possibly quoted file 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)
{
if(*c == '"')
{
quoted = !quoted;
}
// handle unquoted escaped spaces
else if(!quoted && *c == '\\' && isspace(*(c+1)))
{
*pos = *(++c);
pos++;
}
else
{
*pos = *c;
pos++;
}
}
*pos =0;
name += buf;
delete [] buf;
// Return the ending position.
return c;
}

//----------------------------------------------------------------------------
bool cmDependsC::FileExistsOrIsGenerated(const std::string& fname,
std::set<cmStdString>& scanned,
Expand Down

0 comments on commit f18e7c7

Please sign in to comment.