From 8dd79b7b5a0309f9bc1185019a4af16b3b52aece Mon Sep 17 00:00:00 2001 From: Mike Buland Date: Sat, 5 Aug 2006 00:04:34 +0000 Subject: Build now uses a cachefile for all of it's requires that are generated from other means (running other programs). It's really fast, and seems to work pretty well. --- src/builder.cpp | 113 ++++++++++++++++++++++++----------------------------- src/builder.h | 9 ++++- src/cache.cpp | 78 ++++++++++++++++++++++++++++++++++++ src/cache.h | 33 ++++++++++++++++ src/filetarget.cpp | 5 ++- src/main.cpp | 27 +++++++++---- 6 files changed, 193 insertions(+), 72 deletions(-) create mode 100644 src/cache.cpp create mode 100644 src/cache.h diff --git a/src/builder.cpp b/src/builder.cpp index d3cb2c0..a21bc99 100644 --- a/src/builder.cpp +++ b/src/builder.cpp @@ -7,6 +7,8 @@ #include "build.tab.h" #include "rule.h" #include "viewer.h" +#include "cache.h" +#include "serializerbinary.h" subExceptionDef( BuildException ) @@ -21,6 +23,18 @@ Builder::Builder( Viewer &rView ) : Builder::~Builder() { + if( sCacheFile.getLength() > 0 ) + { + try + { + SerializerBinary ar( sCacheFile, Serializer::save ); + + ar << cRequires; + } + catch( ExceptionBase &e ) + { + } + } } void yyparse( Builder &bld ); @@ -53,6 +67,21 @@ void Builder::build( const char *sAct ) rView.endAction(); } +void Builder::setCache( const std::string &sFile ) +{ + sCacheFile = sFile.c_str(); + + try + { + SerializerBinary ar( sCacheFile, Serializer::load ); + + ar >> cRequires; + } + catch( ExceptionBase &e ) + { + } +} + void Builder::execute( Action *pAct ) { pAct->execute( *this ); @@ -247,75 +276,31 @@ void Builder::processRequires( std::list &lInput ) } } - // These are only done on request now, they were too expensive - /* - for( regreqlist::iterator i = lRequiresRegexpCommand.begin(); - i != lRequiresRegexpCommand.end(); i++ ) +} + +void Builder::genRequiresFor( const char *sName, time_t tNewTime ) +{ + Cache::Entry *ent = cRequires.get( sName ); + if( ent && tNewTime > 0 ) { - RegExp *re = (*i).first; - for( std::list::iterator j = lInput.begin(); - j != lInput.end(); j++ ) + if( ent->tCreated >= tNewTime ) { - if( re->execute( (*j).c_str() ) ) + for( std::list::iterator i = ent->lData.begin(); + i != ent->lData.end(); i++ ) { - varmap *revars = regexVars( re ); - std::string s = varRepl( (*i).second.c_str(), "", revars ); - FILE *fcmd = popen( s.c_str(), "r" ); - std::string rhs; - bool bHeader = true; - for(;;) - { - if( feof( fcmd ) ) - break; - int cc = fgetc( fcmd ); - if( cc == EOF ) - break; - unsigned char c = cc; - if( bHeader ) - { - if( c == ':' ) - bHeader = false; - } - else - { - if( c == ' ' || c == '\t' ) - { - if( rhs != "" ) - { - requiresNormal( - (*j).c_str(), - rhs.c_str() - ); - rhs = ""; - } - } - else - { - if( c == '\\' ) - c = fgetc( fcmd ); - if( c != '\n' ) - rhs += c; - } - } - } - if( rhs != "" ) - { - requiresNormal( - (*j).c_str(), - rhs.c_str() - ); - rhs = ""; - } - pclose( fcmd ); - delete revars; + requiresNormal( + sName, + (*i).c_str() + ); } + + return; } } - */ -} -void Builder::genRequiresFor( const char *sName ) -{ + ent = new Cache::Entry; + ent->tCreated = tNewTime; + for( regreqlist::iterator i = lRequiresRegexpCommand.begin(); i != lRequiresRegexpCommand.end(); i++ ) { @@ -352,6 +337,7 @@ void Builder::genRequiresFor( const char *sName ) sName, rhs.c_str() ); + ent->lData.push_back( rhs ); rhs = ""; } } @@ -370,6 +356,7 @@ void Builder::genRequiresFor( const char *sName ) sName, rhs.c_str() ); + ent->lData.push_back( rhs ); rhs = ""; } pclose( fcmd ); @@ -377,6 +364,8 @@ void Builder::genRequiresFor( const char *sName ) rView.endExtraRequiresCheck(); } } + + cRequires.put( sName, ent ); } std::map *Builder::regexVars( RegExp *re ) diff --git a/src/builder.h b/src/builder.h index 06e84f3..56a7b07 100644 --- a/src/builder.h +++ b/src/builder.h @@ -8,6 +8,7 @@ #include "exceptionbase.h" #include "staticstring.h" #include "regexp.h" +#include "cache.h" subExceptionDecl( BuildException ) @@ -17,6 +18,7 @@ class Command; class Rule; class Target; class Viewer; +class Cache; #define YY_DECL int yylex( YYSTYPE *yylval_param, YYLTYPE *yylloc_param, Builder &bld ) YY_DECL; @@ -48,6 +50,8 @@ public: { return rView; } + + void setCache( const std::string &sFile ); void add( Action *pAct ); void add( Command *pCmd ); void add( Rule *pRule ); @@ -59,7 +63,7 @@ public: void processRequires( std::list &lInput ); void requires( const char *sBase, const char *sReq ); void requiresFromCommand( const char *sBase, const char *sReq ); - void genRequiresFor( const char *sName ); + void genRequiresFor( const char *sName, time_t tNewTime ); void requiresRegexp( bool on ) { bReqRegexp = on; @@ -152,6 +156,9 @@ private: bool bReqRegexp; Viewer &rView; + + StaticString sCacheFile; + class Cache cRequires; }; void cleanList( std::list &lst ); diff --git a/src/cache.cpp b/src/cache.cpp new file mode 100644 index 0000000..43e69dc --- /dev/null +++ b/src/cache.cpp @@ -0,0 +1,78 @@ +#include "cache.h" +#include "serializer.h" + +Cache::Cache() +{ +} + +Cache::~Cache() +{ + for( std::map::iterator i = mCache.begin(); + i != mCache.end(); i++ ) + { + delete (*i).second; + } +} + +void Cache::serialize( class Serializer &ar ) +{ + if( ar.isLoading() ) + { + int sCache, sData; + ar >> sCache; + std::string sTmp; + + for( int i = 0; i < sCache; i++ ) + { + Entry *e = new Entry; + ar >> e->tCreated; + ar >> sData; + std::list &lData = e->lData; + for( int j = 0; j < sData; j++ ) + { + ar >> sTmp; + lData.push_back( sTmp ); + } + ar >> sTmp; + mCache[sTmp] = e; + } + } + else + { + ar << mCache.size(); + for( std::map::iterator i = mCache.begin(); + i != mCache.end(); i++ ) + { + ar << (*i).second->tCreated; + std::list &lData = (*i).second->lData; + ar << lData.size(); + for( std::list::iterator j = lData.begin(); + j != lData.end(); j++ ) + { + ar << (*j); + } + + std::string str = (*i).first; + ar << str; + } + } +} + +Cache::Entry *Cache::get( const std::string &id ) +{ + std::map::iterator i = mCache.find( id ); + if( i != mCache.end() ) + return (*i).second; + + return NULL; +} + +void Cache::put( const std::string &id, Entry *data ) +{ + std::map::iterator i = mCache.find( id ); + if( i != mCache.end() ) + delete (*i).second; + + mCache[id] = data; +} + diff --git a/src/cache.h b/src/cache.h new file mode 100644 index 0000000..944aa24 --- /dev/null +++ b/src/cache.h @@ -0,0 +1,33 @@ +#ifndef CACHE_H +#define CACHE_H + +#include +#include +#include "serializable.h" +#include +#include +#include + +class Cache : public Serializable +{ +public: + Cache(); + virtual ~Cache(); + + virtual void serialize( class Serializer &ar ); + + class Entry + { + public: + int tCreated; + std::list lData; + }; + + Entry *get( const std::string &id ); + void put( const std::string &id, Entry *data ); + +private: + std::map mCache; +}; + +#endif diff --git a/src/filetarget.cpp b/src/filetarget.cpp index e89cd5f..7a714a5 100644 --- a/src/filetarget.cpp +++ b/src/filetarget.cpp @@ -98,7 +98,8 @@ void FileTarget::check( Builder &bld ) for( std::list::iterator j = lReqs->begin(); j != lReqs->end(); j++ ) { - if( getTime( bld, *j ) > target ) + time_t srcfile = getTime( bld, *j ); + if( srcfile > target ) { bld.view().beginExecute(); (*i)->execute( bld ); @@ -113,7 +114,7 @@ void FileTarget::check( Builder &bld ) if( k == lReqs->end() ) { bExtraReqs = true; - bld.genRequiresFor( (*i)->getTarget() ); + bld.genRequiresFor( (*i)->getTarget(), srcfile ); } } } diff --git a/src/main.cpp b/src/main.cpp index 70a3ffc..009aac5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -8,13 +8,18 @@ class Param : public ParamProc { public: Param() : - sFile("build.conf") + sFile("build.conf"), + sCache("build.cache") { addHelpBanner("Build r?\n\n"); addParam("file", 'f', &sFile, "Set the input script, default: build.conf"); addParam('p', mkproc(Param::procViewPercent), "Switch to percent view."); + addParam("cache", &sCache, + "Set an alternative cache file." ); + addParam('d', &bDebug, + "Print out a debug dump of the read build.conf", "true" ); addParam("help", mkproc(ParamProc::help), "This help"); pViewer = new ViewerPlain; @@ -42,9 +47,11 @@ public: pViewer = new ViewerPercent; } + std::string sCache; std::string sFile; StaticString sAction; Viewer *pViewer; + bool bDebug; private: }; @@ -56,14 +63,20 @@ int main( int argc, char *argv[] ) Builder bld( *prm.pViewer ); + bld.setCache( prm.sCache ); bld.load( prm.sFile.c_str() ); - if( prm.sAction > 0 ) - bld.build( prm.sAction ); + if( prm.bDebug ) + { + printf("\n\n----------\nDebug dump\n----------\n"); + bld.debug(); + } else - bld.build(); -/* - printf("\n\n----------\nDebug dump\n----------\n"); - bld.debug();*/ + { + if( prm.sAction > 0 ) + bld.build( prm.sAction ); + else + bld.build(); + } } -- cgit v1.2.3