From 3c7e81d3baba06cb1bf37de84aeaa6cad277652a Mon Sep 17 00:00:00 2001 From: Mike Buland Date: Wed, 6 Jan 2010 17:05:45 +0000 Subject: Wow, ok, well, I added some more error handling, that's positive, also switched conditions and functions to a plugger system like views, and all of them now load builtin and external plugins flawlessly. It's actually a lot of fun. I also added the example/test plugin condition "random" it randomly builds targets...it's not really useful... --- src/conditionalways.cpp | 4 +++ src/conditionfileexists.cpp | 41 ++++++++++++++++++++++++ src/conditionfileexists.h | 16 ++++++++++ src/conditionfiletime.cpp | 4 +++ src/conditionnever.cpp | 4 +++ src/conditionplugger.cpp | 43 +++++++++++++++++++++++++ src/conditionplugger.h | 17 ++++++++++ src/context.cpp | 48 +++++++++++++--------------- src/functiondirname.cpp | 4 +++ src/functiondirs.cpp | 4 +++ src/functionexecute.cpp | 4 +++ src/functionexists.cpp | 4 +++ src/functionfilename.cpp | 4 +++ src/functionfiles.cpp | 4 +++ src/functiongetmakedeps.cpp | 4 +++ src/functionmatches.cpp | 4 +++ src/functionplugger.cpp | 59 +++++++++++++++++++++++++++++++++++ src/functionplugger.h | 17 ++++++++++ src/functionreplace.cpp | 4 +++ src/functiontargets.cpp | 4 +++ src/functiontostring.cpp | 4 +++ src/functionunlink.cpp | 4 +++ src/main.cpp | 40 ++++++++++++++++++++++++ src/plugins/pluginConditionRandom.cpp | 31 ++++++++++++++++++ src/profile.cpp | 25 +++------------ src/viewplugger.cpp | 24 ++++++++++++++ 26 files changed, 374 insertions(+), 47 deletions(-) create mode 100644 src/conditionfileexists.cpp create mode 100644 src/conditionfileexists.h create mode 100644 src/conditionplugger.cpp create mode 100644 src/conditionplugger.h create mode 100644 src/functionplugger.cpp create mode 100644 src/functionplugger.h create mode 100644 src/plugins/pluginConditionRandom.cpp (limited to 'src') diff --git a/src/conditionalways.cpp b/src/conditionalways.cpp index 077b5b5..8c245f4 100644 --- a/src/conditionalways.cpp +++ b/src/conditionalways.cpp @@ -1,6 +1,10 @@ #include "conditionalways.h" #include "target.h" +#include +PluginInterface3( pluginConditionAlways, always, ConditionAlways, Condition, + "Mike Buland", 0, 1 ); + ConditionAlways::ConditionAlways() { } diff --git a/src/conditionfileexists.cpp b/src/conditionfileexists.cpp new file mode 100644 index 0000000..0585351 --- /dev/null +++ b/src/conditionfileexists.cpp @@ -0,0 +1,41 @@ +#include "conditionfileexists.h" +#include "target.h" + +#include +#include +#include + +#include +using namespace Bu; + +#include +PluginInterface3( pluginConditionFileExists, fileExists, ConditionFileExists, + Condition, "Mike Buland", 0, 1 ); + +ConditionFileExists::ConditionFileExists() +{ +} + +ConditionFileExists::~ConditionFileExists() +{ +} + +bool ConditionFileExists::shouldExec( class Runner &r, Target &rTarget ) +{ + for( StrList::const_iterator j = rTarget.getOutputList().begin(); j; j++ ) + { + // If any input exists, then return true, we should exec. + if( !access( (*j).getStr(), F_OK ) ) + { + return true; + } + } + + return false; +} + +Condition *ConditionFileExists::clone() +{ + return new ConditionFileExists(); +} + diff --git a/src/conditionfileexists.h b/src/conditionfileexists.h new file mode 100644 index 0000000..6f30297 --- /dev/null +++ b/src/conditionfileexists.h @@ -0,0 +1,16 @@ +#ifndef CONDITION_FILE_EXISTS_H +#define CONDITION_FILE_EXISTS_H + +#include "condition.h" + +class ConditionFileExists : public Condition +{ +public: + ConditionFileExists(); + virtual ~ConditionFileExists(); + + virtual bool shouldExec( class Runner &r, class Target &rTarget ); + virtual Condition *clone(); +}; + +#endif diff --git a/src/conditionfiletime.cpp b/src/conditionfiletime.cpp index 148ffac..43df53b 100644 --- a/src/conditionfiletime.cpp +++ b/src/conditionfiletime.cpp @@ -8,6 +8,10 @@ #include using namespace Bu; +#include +PluginInterface3( pluginConditionFileTime, fileTime, ConditionFileTime, + Condition, "Mike Buland", 0, 1 ); + ConditionFileTime::ConditionFileTime() { } diff --git a/src/conditionnever.cpp b/src/conditionnever.cpp index 1ab4375..f99feb6 100644 --- a/src/conditionnever.cpp +++ b/src/conditionnever.cpp @@ -1,6 +1,10 @@ #include "conditionnever.h" #include "target.h" +#include +PluginInterface3( pluginConditionNever, never, ConditionNever, Condition, + "Mike Buland", 0, 1 ); + ConditionNever::ConditionNever() { } diff --git a/src/conditionplugger.cpp b/src/conditionplugger.cpp new file mode 100644 index 0000000..3edfa00 --- /dev/null +++ b/src/conditionplugger.cpp @@ -0,0 +1,43 @@ +#include "conditionplugger.h" + +#include +#include + +extern Bu::PluginInfo pluginConditionAlways; +extern Bu::PluginInfo pluginConditionNever; +extern Bu::PluginInfo pluginConditionFileTime; +extern Bu::PluginInfo pluginConditionFileExists; + +ConditionPlugger::ConditionPlugger() +{ + registerBuiltinPlugin( &pluginConditionAlways ); + registerBuiltinPlugin( &pluginConditionNever ); + registerBuiltinPlugin( &pluginConditionFileTime ); + registerBuiltinPlugin( &pluginConditionFileExists ); + + DIR *dir = opendir("/usr/lib/build"); + if( !dir ) + return; + struct dirent *de; + while( (de = readdir( dir )) ) + { + if( strncmp("pluginCondition", de->d_name, 15 ) ) + continue; + + Bu::FString sFile("/usr/lib/build/"); + sFile += de->d_name; + char *s = de->d_name; + for(; *s && *s != '.'; s++ ) { } + registerExternalPlugin( + sFile, + Bu::FString( de->d_name, (ptrdiff_t)s-(ptrdiff_t)de->d_name ) + ); + } + + closedir( dir ); +} + +ConditionPlugger::~ConditionPlugger() +{ +} + diff --git a/src/conditionplugger.h b/src/conditionplugger.h new file mode 100644 index 0000000..71fa7e3 --- /dev/null +++ b/src/conditionplugger.h @@ -0,0 +1,17 @@ +#ifndef CONDITION_PLUGGER_H +#define CONDITION_PLUGGER_H + +#include "condition.h" +#include +#include + +class ConditionPlugger : public Bu::Plugger, + public Bu::Singleton +{ +friend class Bu::Singleton; +private: + ConditionPlugger(); + virtual ~ConditionPlugger(); +}; + +#endif diff --git a/src/context.cpp b/src/context.cpp index efe8098..64b3bd0 100644 --- a/src/context.cpp +++ b/src/context.cpp @@ -7,18 +7,7 @@ #include "profile.h" #include "view.h" -#include "functionreplace.h" -#include "functionexists.h" -#include "functionfiles.h" -#include "functionexecute.h" -#include "functionmatches.h" -#include "functiontostring.h" -#include "functionunlink.h" -#include "functiontargets.h" -#include "functiondirs.h" -#include "functiongetmakedeps.h" -#include "functionfilename.h" -#include "functiondirname.h" +#include "functionplugger.h" #include #include @@ -27,18 +16,6 @@ using namespace Bu; Context::Context() : pView( NULL ) { - addFunction( new FunctionReplace() ); - addFunction( new FunctionExists() ); - addFunction( new FunctionFiles() ); - addFunction( new FunctionExecute() ); - addFunction( new FunctionMatches() ); - addFunction( new FunctionToString() ); - addFunction( new FunctionUnlink() ); - addFunction( new FunctionTargets() ); - addFunction( new FunctionDirs() ); - addFunction( new FunctionGetMakeDeps() ); - addFunction( new FunctionFileName() ); - addFunction( new FunctionDirName() ); pushScope(); } @@ -178,7 +155,16 @@ Variable Context::call( const Bu::FString &sName, Variable &input, { if( !hFunction.has( sName ) ) { - throw Bu::ExceptionBase("Unknown function called: %s", sName.getStr() ); + // Try to load the function... + try + { + addFunction( FunctionPlugger::getInstance().instantiate( sName ) ); + } + catch(...) + { + throw Bu::ExceptionBase("Unknown function called: %s", + sName.getStr() ); + } } return hFunction.get( sName )->call( input, lParams ); } @@ -290,8 +276,16 @@ void Context::buildTargetTree( Runner &r ) continue; StrList lNewIns; // The new "changed" inputs for this target - - Rule *pMaster = hRule.get( (*i)->getRule() ); + + Rule *pMaster; + try + { + pMaster = hRule.get( (*i)->getRule() ); + } + catch( Bu::HashException &e ) + { + throw Bu::ExceptionBase("Unknown rule: %s", (*i)->getRule().getStr() ); + } for( StrList::const_iterator j = (*i)->getInputList().begin(); j; j++ ) { diff --git a/src/functiondirname.cpp b/src/functiondirname.cpp index e8b728b..f72d181 100644 --- a/src/functiondirname.cpp +++ b/src/functiondirname.cpp @@ -1,5 +1,9 @@ #include "functiondirname.h" +#include +PluginInterface3( pluginFunctionDirName, dirName, FunctionDirName, Function, + "Mike Buland", 0, 1 ); + FunctionDirName::FunctionDirName() { } diff --git a/src/functiondirs.cpp b/src/functiondirs.cpp index fb64ef3..dee3c4c 100644 --- a/src/functiondirs.cpp +++ b/src/functiondirs.cpp @@ -5,6 +5,10 @@ #include #include +#include +PluginInterface3( pluginFunctionDirs, dirs, FunctionDirs, Function, + "Mike Buland", 0, 1 ); + FunctionDirs::FunctionDirs() { } diff --git a/src/functionexecute.cpp b/src/functionexecute.cpp index 619d2c2..f692036 100644 --- a/src/functionexecute.cpp +++ b/src/functionexecute.cpp @@ -6,6 +6,10 @@ #include using namespace Bu; +#include +PluginInterface3( pluginFunctionExecute, execute, FunctionExecute, Function, + "Mike Buland", 0, 1 ); + FunctionExecute::FunctionExecute() { } diff --git a/src/functionexists.cpp b/src/functionexists.cpp index d2aa9e9..2207f84 100644 --- a/src/functionexists.cpp +++ b/src/functionexists.cpp @@ -2,6 +2,10 @@ #include +#include +PluginInterface3( pluginFunctionExists, exists, FunctionExists, Function, + "Mike Buland", 0, 1 ); + FunctionExists::FunctionExists() { } diff --git a/src/functionfilename.cpp b/src/functionfilename.cpp index 21a4655..57aada9 100644 --- a/src/functionfilename.cpp +++ b/src/functionfilename.cpp @@ -1,5 +1,9 @@ #include "functionfilename.h" +#include +PluginInterface3( pluginFunctionFileName, fileName, FunctionFileName, Function, + "Mike Buland", 0, 1 ); + FunctionFileName::FunctionFileName() { } diff --git a/src/functionfiles.cpp b/src/functionfiles.cpp index e708d45..e0f8268 100644 --- a/src/functionfiles.cpp +++ b/src/functionfiles.cpp @@ -5,6 +5,10 @@ #include #include +#include +PluginInterface3( pluginFunctionFiles, files, FunctionFiles, Function, + "Mike Buland", 0, 1 ); + FunctionFiles::FunctionFiles() { } diff --git a/src/functiongetmakedeps.cpp b/src/functiongetmakedeps.cpp index 008a509..cc6cbbb 100644 --- a/src/functiongetmakedeps.cpp +++ b/src/functiongetmakedeps.cpp @@ -6,6 +6,10 @@ #include using namespace Bu; +#include +PluginInterface3( pluginFunctionGetMakeDeps, getMakeDeps, FunctionGetMakeDeps, + Function, "Mike Buland", 0, 1 ); + FunctionGetMakeDeps::FunctionGetMakeDeps() { } diff --git a/src/functionmatches.cpp b/src/functionmatches.cpp index 4e4b7ff..5b96fa8 100644 --- a/src/functionmatches.cpp +++ b/src/functionmatches.cpp @@ -2,6 +2,10 @@ #include +#include +PluginInterface3( pluginFunctionMatches, matches, FunctionMatches, Function, + "Mike Buland", 0, 1 ); + FunctionMatches::FunctionMatches() { } diff --git a/src/functionplugger.cpp b/src/functionplugger.cpp new file mode 100644 index 0000000..83435ae --- /dev/null +++ b/src/functionplugger.cpp @@ -0,0 +1,59 @@ +#include "functionplugger.h" + +#include +#include + +extern Bu::PluginInfo pluginFunctionDirName; +extern Bu::PluginInfo pluginFunctionDirs; +extern Bu::PluginInfo pluginFunctionExecute; +extern Bu::PluginInfo pluginFunctionExists; +extern Bu::PluginInfo pluginFunctionFileName; +extern Bu::PluginInfo pluginFunctionFiles; +extern Bu::PluginInfo pluginFunctionGetMakeDeps; +extern Bu::PluginInfo pluginFunctionMatches; +extern Bu::PluginInfo pluginFunctionReplace; +extern Bu::PluginInfo pluginFunctionTargets; +extern Bu::PluginInfo pluginFunctionToString; +extern Bu::PluginInfo pluginFunctionUnlink; + +FunctionPlugger::FunctionPlugger() +{ + registerBuiltinPlugin( &pluginFunctionDirName ); + registerBuiltinPlugin( &pluginFunctionDirs ); + registerBuiltinPlugin( &pluginFunctionExecute ); + registerBuiltinPlugin( &pluginFunctionExists ); + registerBuiltinPlugin( &pluginFunctionFileName ); + registerBuiltinPlugin( &pluginFunctionFiles ); + registerBuiltinPlugin( &pluginFunctionGetMakeDeps ); + registerBuiltinPlugin( &pluginFunctionMatches ); + registerBuiltinPlugin( &pluginFunctionReplace ); + registerBuiltinPlugin( &pluginFunctionTargets ); + registerBuiltinPlugin( &pluginFunctionToString ); + registerBuiltinPlugin( &pluginFunctionUnlink ); + + DIR *dir = opendir("/usr/lib/build"); + if( !dir ) + return; + struct dirent *de; + while( (de = readdir( dir )) ) + { + if( strncmp("pluginFunction", de->d_name, 15 ) ) + continue; + + Bu::FString sFile("/usr/lib/build/"); + sFile += de->d_name; + char *s = de->d_name; + for(; *s && *s != '.'; s++ ) { } + registerExternalPlugin( + sFile, + Bu::FString( de->d_name, (ptrdiff_t)s-(ptrdiff_t)de->d_name ) + ); + } + + closedir( dir ); +} + +FunctionPlugger::~FunctionPlugger() +{ +} + diff --git a/src/functionplugger.h b/src/functionplugger.h new file mode 100644 index 0000000..30022f6 --- /dev/null +++ b/src/functionplugger.h @@ -0,0 +1,17 @@ +#ifndef FUNCTION_PLUGGER_H +#define FUNCTION_PLUGGER_H + +#include "function.h" +#include +#include + +class FunctionPlugger : public Bu::Plugger, + public Bu::Singleton +{ +friend class Bu::Singleton; +private: + FunctionPlugger(); + virtual ~FunctionPlugger(); +}; + +#endif diff --git a/src/functionreplace.cpp b/src/functionreplace.cpp index d269083..b341e44 100644 --- a/src/functionreplace.cpp +++ b/src/functionreplace.cpp @@ -1,5 +1,9 @@ #include "functionreplace.h" +#include +PluginInterface3( pluginFunctionReplace, replace, FunctionReplace, Function, + "Mike Buland", 0, 1 ); + FunctionReplace::FunctionReplace() { } diff --git a/src/functiontargets.cpp b/src/functiontargets.cpp index 93fbb96..adafdfb 100644 --- a/src/functiontargets.cpp +++ b/src/functiontargets.cpp @@ -2,6 +2,10 @@ #include "context.h" #include "target.h" +#include +PluginInterface3( pluginFunctionTargets, targets, FunctionTargets, Function, + "Mike Buland", 0, 1 ); + FunctionTargets::FunctionTargets() { } diff --git a/src/functiontostring.cpp b/src/functiontostring.cpp index 0c04091..1d614ce 100644 --- a/src/functiontostring.cpp +++ b/src/functiontostring.cpp @@ -4,6 +4,10 @@ #include using namespace Bu; +#include +PluginInterface3( pluginFunctionToString, toString, FunctionToString, Function, + "Mike Buland", 0, 1 ); + FunctionToString::FunctionToString() { } diff --git a/src/functionunlink.cpp b/src/functionunlink.cpp index addcfd9..d8ad899 100644 --- a/src/functionunlink.cpp +++ b/src/functionunlink.cpp @@ -5,6 +5,10 @@ #include using namespace Bu; +#include +PluginInterface3( pluginFunctionUnlink, unlink, FunctionUnlink, Function, + "Mike Buland", 0, 1 ); + FunctionUnlink::FunctionUnlink() { } diff --git a/src/main.cpp b/src/main.cpp index 1bed895..c0b8dd3 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -5,6 +5,8 @@ #include "target.h" #include "viewplugger.h" +#include "functionplugger.h" +#include "conditionplugger.h" #include "cache.h" @@ -50,6 +52,8 @@ public: addHelpBanner("The following options do things other than build:"); addOption( iInfoLevel, 'i', "info", "Display some basic info about the " "loaded build config, including available targets."); + addOption( slot( this, &Options::onListPlugins), "list-plugins", + "List all available plugins."); addHelpBanner("The following options control general execution:"); addOption( sView, 'v', "view", sViews ); @@ -115,6 +119,42 @@ public: return 0; } + int onListPlugins( StrArray /*sParams*/ ) + { + StrList lViews = ViewPlugger::getInstance().getPluginList(); + sio << "Available view plugins:" << sio.nl << "\t"; + for( StrList::iterator i = lViews.begin(); i; i++ ) + { + if( i != lViews.begin() ) + sio << ", "; + sio << *i; + } + + StrList lFuncs = FunctionPlugger::getInstance().getPluginList(); + sio << sio.nl << sio.nl << "Available function plugins:" + << sio.nl << "\t"; + for( StrList::iterator i = lFuncs.begin(); i; i++ ) + { + if( i != lFuncs.begin() ) + sio << ", "; + sio << *i; + } + + StrList lConds = ConditionPlugger::getInstance().getPluginList(); + sio << sio.nl << sio.nl << "Available condition plugins:" + << sio.nl << "\t"; + for( StrList::iterator i = lConds.begin(); i; i++ ) + { + if( i != lConds.begin() ) + sio << ", "; + sio << *i; + } + + sio << sio.nl << sio.nl; + + return 0; + } + Bu::FString sView; Bu::FString sAction; Bu::FString sConfig; diff --git a/src/plugins/pluginConditionRandom.cpp b/src/plugins/pluginConditionRandom.cpp new file mode 100644 index 0000000..42a4e00 --- /dev/null +++ b/src/plugins/pluginConditionRandom.cpp @@ -0,0 +1,31 @@ +#include "condition.h" +#include + +class ConditionRandom : public Condition +{ +public: + ConditionRandom() + { + } + + virtual ~ConditionRandom() + { + } + + virtual bool shouldExec( class Runner &, class Target & ) + { + if( (random()/(double)RAND_MAX) >= .5 ) + return true; + return false; + } + + virtual Condition *clone() + { + return new ConditionRandom(); + } +}; + +#include +PluginInterface3( pluginConditionRandom, random, ConditionRandom, Condition, + "Mike Buland", 0, 1 ); + diff --git a/src/profile.cpp b/src/profile.cpp index 878a6e9..fd21097 100644 --- a/src/profile.cpp +++ b/src/profile.cpp @@ -4,9 +4,7 @@ #include "astleaf.h" #include "condition.h" -#include "conditionfiletime.h" -#include "conditionalways.h" -#include "conditionnever.h" +#include "conditionplugger.h" #include using namespace Bu; @@ -64,7 +62,7 @@ Profile *Profile::genDefaultClean() pAst->openBranch(); pAst->addNode( AstNode::typeString, "clean" ); pAst->openBranch(); - pAst->addNode( AstNode::typeCondition, "always" ); + pAst->addNode( AstNode::typeCondition, "fileExists" ); pAst->addNode( AstNode::typeFunction ); pAst->openBranch(); pAst->addNode( AstNode::typeString, "unlink" ); @@ -89,28 +87,15 @@ void Profile::setCondition() if( (*i)->getType() == AstNode::typeCondition ) { Bu::FString sCond = dynamic_cast(*i)->getStrValue(); - if( sCond == "filetime" ) - { - delete pCond; - pCond = new ConditionFileTime(); - } - else if( sCond == "always" ) - { - delete pCond; - pCond = new ConditionAlways(); - } - else if( sCond == "never" ) - { - delete pCond; - pCond = new ConditionNever(); - } + delete pCond; + pCond = ConditionPlugger::getInstance().instantiate( sCond ); } } if( pCond == NULL ) { // The default condition - pCond = new ConditionFileTime(); + pCond = ConditionPlugger::getInstance().instantiate("fileTime"); } } diff --git a/src/viewplugger.cpp b/src/viewplugger.cpp index 6046f82..58f3605 100644 --- a/src/viewplugger.cpp +++ b/src/viewplugger.cpp @@ -1,11 +1,35 @@ #include "viewplugger.h" +#include +#include + extern Bu::PluginInfo pluginViewDefault; extern Bu::PluginInfo pluginViewMake; ViewPlugger::ViewPlugger() { registerBuiltinPlugin( &pluginViewDefault ); registerBuiltinPlugin( &pluginViewMake ); + + DIR *dir = opendir("/usr/lib/build"); + if( !dir ) + return; + struct dirent *de; + while( (de = readdir( dir )) ) + { + if( strncmp("pluginView", de->d_name, 15 ) ) + continue; + + Bu::FString sFile("/usr/lib/build/"); + sFile += de->d_name; + char *s = de->d_name; + for(; *s && *s != '.'; s++ ) { } + registerExternalPlugin( + sFile, + Bu::FString( de->d_name, (ptrdiff_t)s-(ptrdiff_t)de->d_name ) + ); + } + + closedir( dir ); } ViewPlugger::~ViewPlugger() -- cgit v1.2.3