From 46a3cfdd7b2a77a308a6ac3fbca3b675c4f44fe7 Mon Sep 17 00:00:00 2001
From: Mike Buland <eichlan@xagasoft.com>
Date: Tue, 1 Aug 2006 06:27:43 +0000
Subject: It builds fine, and can build other things as well, like squirrelmud,
 and clean.

I need to fix the dependancy tracking so that it will only check if it needs to,
sort of like pymake.  And does each file as it gets to it.
---
 build.conf         |  7 +++---
 src/build.l        |  1 +
 src/build.y        |  5 +++++
 src/builder.h      |  4 +++-
 src/filetarget.cpp | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++--
 src/filetarget.h   |  9 +++++++-
 src/main.cpp       |  7 ++++--
 src/perform.cpp    |  1 +
 src/perform.h      |  1 +
 src/performcmd.cpp |  2 +-
 src/rule.cpp       | 11 ++++++++++
 11 files changed, 100 insertions(+), 11 deletions(-)

diff --git a/build.conf b/build.conf
index 1d7c6a2..b24d7d0 100644
--- a/build.conf
+++ b/build.conf
@@ -1,14 +1,13 @@
 # This is a build file for build
 
 default action: check build
+"clean" action: clean build
 
 create file build from files in src using rule exe
 
 set CXXFLAGS += "-Ilibbu++/src"
 set LDFLAGS += "-Llibbu++ -lbu++"
 
-for build set LDFLAGS += -lreadline
-
 build requires src/libbu++/libbu++.a
 
 /(.*)\.o$/ requires from command "g++ {CXXFLAGS} -M {re:1}.c*"
@@ -19,8 +18,8 @@ rule exe matches all /(.*)\.o$/ perform command ...
 rule cpp matches one /(.*)\.c(pp)?$/ produces "{re:1}.o" perform command ...
 	"g++ {CXXFLAGS} -c -o {target} {match}"
 
-rule bison matches one /(.*)\.y$/ produces "{re:1}.tab.c", "{re:1}.tab.h" ...
-	perform command "bison -v -b{re:1} {match}"
+rule bison matches one /(.*)\.y$/ produces "{re:1}.tab.c", "{re:1}.tab.h", ...
+	"{re:1}.output" perform command "bison -v -b{re:1} {match}"
 
 rule flex matches one /(.*)\.l$/ produces "{re:1}.yy.c" perform ...
 	command "flex --bison-bridge --bison-locations -o {target} {match}"
diff --git a/src/build.l b/src/build.l
index a88f90d..a18cbeb 100644
--- a/src/build.l
+++ b/src/build.l
@@ -40,6 +40,7 @@ std::string strbuf;
 "produces"							return TOK_PRODUCES;
 "command"							return TOK_COMMAND;
 "check"								return TOK_CHECK;
+"clean"								return TOK_CLEAN;
 
 "..."\n								/* elipsis line continuation */
 \n+									return TOK_EOL;
diff --git a/src/build.y b/src/build.y
index ecc5d59..4d87a86 100644
--- a/src/build.y
+++ b/src/build.y
@@ -49,6 +49,7 @@ void yyerror( YYLTYPE *locp, Builder &bld, char const *msg );
 %token TOK_PRODUCES				"produces"
 %token TOK_COMMAND				"command"
 %token TOK_CHECK				"check"
+%token TOK_CLEAN				"clean"
 %token TOK_EOL					"end of line"
 %token ',' ':' '='
 
@@ -162,6 +163,10 @@ action: TOK_CHECK STRING
 	    {
 			bld.add( new Command( Command::cmdCheck, $2 ) );
 		}
+	  | TOK_CLEAN STRING
+	    {
+			bld.add( new Command( Command::cmdClean, $2 ) );
+		}
 	  ;
 
 setexpr: STRING '=' STRING
diff --git a/src/builder.h b/src/builder.h
index f21e411..f27a042 100644
--- a/src/builder.h
+++ b/src/builder.h
@@ -100,8 +100,10 @@ public:
 		return mTarget[sName];
 	}
 
-	std::list<std::string> getRequires( const char *sReq )
+	std::list<std::string> *getRequires( const char *sReq )
 	{
+		if( mRequires.find(sReq) == mRequires.end() )
+			return NULL;
 		return mRequires[sReq];
 	}
 
diff --git a/src/filetarget.cpp b/src/filetarget.cpp
index 1880c35..f9367a4 100644
--- a/src/filetarget.cpp
+++ b/src/filetarget.cpp
@@ -1,6 +1,7 @@
 #include <errno.h>
 #include <dirent.h>
 
+#include "perform.h"
 #include "rule.h"
 #include "filetarget.h"
 #include "builder.h" // for BuildException
@@ -66,8 +67,11 @@ void FileTarget::addInputDir( const char *sDir )
 	closedir( dir );
 }
 
+int nNew, nCache;
+
 void FileTarget::check( Builder &bld )
 {
+	nNew = nCache = 0;
 	Rule *pRule = bld.getRule( sRule );
 
 	std::list<Perform *> perf;
@@ -79,12 +83,67 @@ void FileTarget::check( Builder &bld )
 	for( std::list<Perform *>::iterator i = perf.begin();
 		 i != perf.end(); i++ )
 	{
-		std::list<std::string> lReqs = bld.getRequires( (*i)->getTarget() );
-		
+		time_t target = getTime( std::string((*i)->getTarget()) );
+		std::list<std::string> *lReqs = bld.getRequires( (*i)->getTarget() );
+		if( lReqs == NULL )
+		{
+			printf("No dependancies: %s\n", (*i)->getTarget() );
+			continue;
+		}
+		for( std::list<std::string>::iterator j = lReqs->begin();
+			 j != lReqs->end(); j++ )
+		{
+			if( getTime( *j ) > target )
+			{
+				(*i)->execute( bld );
+				updateTime( (*i)->getTarget() );
+				break;
+			}
+		}
 	}
+
+	printf("Cache hits %d, %d new (%f%%)\n", nCache, nNew, nCache/ (double)(nNew+nCache)*100.0 );
 }
 
 void FileTarget::clean( Builder &bld )
 {
+	Rule *pRule = bld.getRule( sRule );
+
+	std::list<Perform *> perf;
+	std::list<std::string> tmp = pRule->execute( bld, lInput, perf, getName() );
+	lOutput.insert( lOutput.end(), tmp.begin(), tmp.end() );
+
+	for( std::list<std::string>::iterator i = lOutput.begin();
+		 i != lOutput.end(); i++ )
+	{
+		unlink( (*i).c_str() );
+	}
+}
+
+time_t FileTarget::getTime( std::string str )
+{
+	std::map<std::string, time_t>::iterator i = mTimes.find( str );
+	if( i != mTimes.end() )
+	{
+		nCache++;
+		return (*i).second;
+	}
+
+	struct stat st;
+	stat( str.c_str(), &st );
+
+	mTimes[str] = st.st_mtime;
+
+	nNew++;
+
+	return st.st_mtime;
+}
+
+void FileTarget::updateTime( std::string str )
+{
+	struct stat st;
+	stat( str.c_str(), &st );
+
+	mTimes[str] = st.st_mtime;
 }
 
diff --git a/src/filetarget.h b/src/filetarget.h
index c872c0a..856e854 100644
--- a/src/filetarget.h
+++ b/src/filetarget.h
@@ -2,6 +2,10 @@
 #define FILE_TARGET_H
 
 #include <stdint.h>
+#include <map>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
 #include "target.h"
 
 class FileTarget : public Target
@@ -16,9 +20,12 @@ public:
 
 	virtual void check( class Builder &bld );
 	virtual void clean( class Builder &bld );
+
+	time_t getTime( std::string str );
+	void updateTime( std::string str );
 	
 private:
-	// start here with the file time cache
+	std::map<std::string, time_t> mTimes;
 
 };
 
diff --git a/src/main.cpp b/src/main.cpp
index ebf0cfd..ebfb745 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -1,12 +1,15 @@
 #include "builder.h"
 
-int main()
+int main( int argc, char *argv[] )
 {
 	Builder bld;
 
 	bld.load("build.conf");
 
-	bld.build();
+	if( argc >= 2 )
+		bld.build( argv[1] );
+	else
+		bld.build();
 /*
 	printf("\n\n----------\nDebug dump\n----------\n");
 	bld.debug();*/
diff --git a/src/perform.cpp b/src/perform.cpp
index d7082a0..c96d70f 100644
--- a/src/perform.cpp
+++ b/src/perform.cpp
@@ -8,3 +8,4 @@ Perform::Perform( const char *sTarget ) :
 Perform::~Perform()
 {
 }
+
diff --git a/src/perform.h b/src/perform.h
index 2eb8cb0..914f3b0 100644
--- a/src/perform.h
+++ b/src/perform.h
@@ -2,6 +2,7 @@
 #define PERFORM_H
 
 #include <stdint.h>
+#include "staticstring.h"
 
 class Perform
 {
diff --git a/src/performcmd.cpp b/src/performcmd.cpp
index 724f42b..d9b7977 100644
--- a/src/performcmd.cpp
+++ b/src/performcmd.cpp
@@ -3,7 +3,7 @@
 
 PerformCmd::PerformCmd( const char *sCmd, const char *sTarget ) :
 	Perform( sTarget ),
-	sCommand( sCmd ),
+	sCommand( sCmd )
 {
 }
 
diff --git a/src/rule.cpp b/src/rule.cpp
index 979075b..ce37e93 100644
--- a/src/rule.cpp
+++ b/src/rule.cpp
@@ -77,6 +77,7 @@ Perform *Rule::buildCommand( Builder &bld, const char *sCmd, Builder::varmap *va
 
 std::list<std::string> Rule::execute( Builder &bld, std::list<std::string> lInput, std::list<Perform *> &lPerf, const char *sTarget )
 {
+	bld.requiresRegexp( false );
 	std::list<Rule *> lRule = bld.findRuleChain( this );
 	/*
 	if( !lRule.empty() )
@@ -134,11 +135,21 @@ std::list<std::string> Rule::execute( Builder &bld, std::list<std::string> lInpu
 						revars
 						);
 					lPerf.push_back( p );
+
+					bld.requires(
+						(*revars)["target"].c_str(),
+						(*revars)["match"].c_str()
+						);
 				}
 				else if( mHow == matchAll )
 				{
 					sMatches += " ";
 					sMatches += (*i);
+
+					bld.requires(
+						sTarget,
+						(*i).c_str()
+						);
 				}
 			}
 			delete revars;
-- 
cgit v1.2.3