Invocation of buildtool modules.
Modified: branches/xmlbuildsystem/reactos/ReactOS.xml
Modified: branches/xmlbuildsystem/reactos/ntoskrnl/module.xml
Modified: branches/xmlbuildsystem/reactos/tools/rbuild/backend/mingw/modulehandler.cpp
Modified: branches/xmlbuildsystem/reactos/tools/rbuild/backend/mingw/modulehandler.h
Modified: branches/xmlbuildsystem/reactos/tools/rbuild/makefile
Modified: branches/xmlbuildsystem/reactos/tools/rbuild/module.cpp
Modified: branches/xmlbuildsystem/reactos/tools/rbuild/rbuild.h
Modified: branches/xmlbuildsystem/reactos/tools/rbuild/test.h
Modified: branches/xmlbuildsystem/reactos/tools/rbuild/tests/alltests.cpp
Added: branches/xmlbuildsystem/reactos/tools/rbuild/tests/data/invoke.xml
Modified: branches/xmlbuildsystem/reactos/tools/rbuild/tests/data/module.xml
Added: branches/xmlbuildsystem/reactos/tools/rbuild/tests/invoketest.cpp
Modified: branches/xmlbuildsystem/reactos/tools/rbuild/tests/moduletest.cpp
Added: branches/xmlbuildsystem/reactos/tools/tools.xml

Modified: branches/xmlbuildsystem/reactos/ReactOS.xml
--- branches/xmlbuildsystem/reactos/ReactOS.xml	2005-01-08 18:11:46 UTC (rev 12890)
+++ branches/xmlbuildsystem/reactos/ReactOS.xml	2005-01-08 19:38:51 UTC (rev 12891)
@@ -1,13 +1,11 @@
 <?xml version="1.0"?>
 <!DOCTYPE project SYSTEM "tools/rbuild/project.dtd">
 <project name="ReactOS" makefile="Makefile.auto" xmlns:xi="http://www.w3.org/2001/XInclude">
-	<define name="_M_IX86"></define>
+	<define name="_M_IX86" />
 	<include>include</include>
 	<include>w32api/include</include>
 	<directory name="tools">
-		<module name="depends" type="buildtool">
-			<file>depends.c</file>
-		</module>
+		<xi:include href="tools/tools.xml" />
 	</directory>
 	<directory name="iface">
 		<directory name="native">

Modified: branches/xmlbuildsystem/reactos/ntoskrnl/module.xml
--- branches/xmlbuildsystem/reactos/ntoskrnl/module.xml	2005-01-08 18:11:46 UTC (rev 12890)
+++ branches/xmlbuildsystem/reactos/ntoskrnl/module.xml	2005-01-08 19:38:51 UTC (rev 12891)
@@ -1,10 +1,11 @@
 <module name="ntoskrnl" type="kernelmodedll" extension=".exe">
+	<dependency>buildno</dependency>
 	<define name="_SEH_NO_NATIVE_NLG" />
 	<define name="_DISABLE_TIDENTS" />
 	<define name="__NTOSKRNL__" />
 	<define name="__3GB__" />
-	<include>.</include>
 	<include base="kjs">./include</include>
+	<include base="ntoskrnl">include</include>
 	<library>kjs</library>
 	<directory name="cc">
 		<file>cacheman.c</file>

Modified: branches/xmlbuildsystem/reactos/tools/rbuild/backend/mingw/modulehandler.cpp
--- branches/xmlbuildsystem/reactos/tools/rbuild/backend/mingw/modulehandler.cpp	2005-01-08 18:11:46 UTC (rev 12890)
+++ branches/xmlbuildsystem/reactos/tools/rbuild/backend/mingw/modulehandler.cpp	2005-01-08 19:38:51 UTC (rev 12891)
@@ -33,7 +33,7 @@
 string
 MingwModuleHandler::GetModuleArchiveFilename ( const Module& module ) const
 {
-	return ReplaceExtension ( FixupTargetFilename(module.GetPath ()).c_str (),
+	return ReplaceExtension ( FixupTargetFilename ( module.GetPath () ).c_str (),
 	                          ".a" );
 }
 
@@ -50,12 +50,43 @@
 			dependencies += " ";
 		const Module* importedModule = module.project.LocateModule ( module.libraries[i]->name );
 		assert ( importedModule != NULL );
-		dependencies += FixupTargetFilename(importedModule->GetPath ()).c_str ();
+		dependencies += FixupTargetFilename ( importedModule->GetPath () ).c_str ();
 	}
 	return dependencies;
 }
 
 string
+MingwModuleHandler::GetModuleDependencies ( const Module& module ) const
+{
+	if ( module.dependencies.size () == 0 )
+		return "";
+	
+	string dependencies ( "" );
+	for ( size_t i = 0; i < module.dependencies.size (); i++ )
+	{
+		if ( dependencies.size () > 0 )
+			dependencies += " ";
+		const Dependency* dependency = module.dependencies[i];
+		const Module* dependencyModule = dependency->dependencyModule;
+		dependencies += dependencyModule->GetTargets ();
+	}
+	return dependencies;
+}
+
+string
+MingwModuleHandler::GetAllDependencies ( const Module& module ) const
+{
+	string dependencies = GetImportLibraryDependencies ( module );
+	string s = GetModuleDependencies ( module );
+	if (s.length () > 0)
+	{
+		dependencies += " ";
+		dependencies += s;
+	}
+	return dependencies;
+}
+
+string
 MingwModuleHandler::GetSourceFilenames ( const Module& module ) const
 {
 	if ( module.files.size () == 0 )
@@ -74,9 +105,8 @@
 string
 MingwModuleHandler::GetObjectFilename ( const string& sourceFilename ) const
 {
-	return
-		FixupTargetFilename ( ReplaceExtension ( sourceFilename,
-		                                         ".o" ) );
+	return FixupTargetFilename ( ReplaceExtension ( sourceFilename,
+		                                            ".o" ) );
 }
 
 string
@@ -144,7 +174,7 @@
 MingwModuleHandler::GenerateGccIncludeParametersFromVector ( const vector<Include*>& includes ) const
 {
 	string parameters;
-	for (size_t i = 0; i < includes.size (); i++)
+	for ( size_t i = 0; i < includes.size (); i++ )
 	{
 		Include& include = *includes[i];
 		if (parameters.length () > 0)
@@ -191,10 +221,12 @@
 	{
 		string sourceFilename = module.files[i]->name;
 		string objectFilename = GetObjectFilename ( sourceFilename );
+		string dependencies = GetModuleDependencies ( module );
 		fprintf ( fMakefile,
-		          "%s: %s\n",
+		          "%s: %s %s\n",
 		          objectFilename.c_str (),
-		          sourceFilename.c_str() );
+		          sourceFilename.c_str (),
+		          dependencies.c_str ());
 		fprintf ( fMakefile,
 		          "\t%s -c %s -o %s %s\n",
 		          cc.c_str (),
@@ -234,10 +266,10 @@
 	          objectFilenames.c_str ());
 
 	fprintf ( fMakefile,
-	         "\t%s -rc %s %s\n\n",
-	         ar.c_str (),
-	         archiveFilename.c_str (),
-	         objectFilenames.c_str ());
+	          "\t%s -rc %s %s\n\n",
+	          ar.c_str (),
+	          archiveFilename.c_str (),
+	          objectFilenames.c_str ());
 }
 
 void
@@ -254,7 +286,53 @@
 	                        "${ar}" );
 }
 
+string
+MingwModuleHandler::GetInvocationDependencies ( const Module& module ) const
+{
+	string dependencies;
+	for ( size_t i = 0; i < module.invocations.size (); i++ )
+	{
+		Invoke& invoke = *module.invocations[i];
+		if ( dependencies.length () > 0 )
+			dependencies += " ";
+		string invokeTarget = module.GetInvocationTarget ( i );
+		dependencies += invokeTarget;
+	}
+	return dependencies;
+}
+	
+void
+MingwModuleHandler::GenerateInvocations ( const Module& module ) const
+{
+	if ( module.invocations.size () == 0 )
+		return;
+	
+	if ( module.type != BuildTool )
+		throw InvalidBuildFileException ( module.node.location,
+		                                  "Only modules of type buildtool can be invoked." );
 
+	for ( size_t i = 0; i < module.invocations.size (); i++ )
+	{
+		Invoke& invoke = *module.invocations[i];
+		string invokeTarget = module.GetInvocationTarget ( i );
+		fprintf ( fMakefile,
+		          "%s: %s\n\n",
+   		          invoke.GetTargets ().c_str (),
+		          invokeTarget.c_str () );
+		fprintf ( fMakefile,
+		          "%s: %s\n",
+		          invokeTarget.c_str (),
+		          FixupTargetFilename ( module.GetPath () ).c_str () );
+		fprintf ( fMakefile,
+		          "\t%s\n\n",
+		          FixupTargetFilename ( module.GetPath () ).c_str () );
+		fprintf ( fMakefile,
+		          ".PNONY: %s\n\n",
+		          invokeTarget.c_str () );
+	}
+}
+
+
 MingwBuildToolModuleHandler::MingwBuildToolModuleHandler ( FILE* fMakefile )
 	: MingwModuleHandler ( fMakefile )
 {
@@ -270,12 +348,13 @@
 MingwBuildToolModuleHandler::Process ( const Module& module )
 {
 	GenerateBuildToolModuleTarget ( module );
+	GenerateInvocations ( module );
 }
 
 void
 MingwBuildToolModuleHandler::GenerateBuildToolModuleTarget ( const Module& module )
 {
-	string target ( FixupTargetFilename(module.GetPath()) );
+	string target ( FixupTargetFilename ( module.GetPath () ) );
 	string archiveFilename = GetModuleArchiveFilename ( module );
 	fprintf ( fMakefile, "%s: %s\n",
 	          target.c_str (),
@@ -304,6 +383,7 @@
 MingwKernelModuleHandler::Process ( const Module& module )
 {
 	GenerateKernelModuleTarget ( module );
+	GenerateInvocations ( module );
 }
 
 void
@@ -369,6 +449,7 @@
 MingwStaticLibraryModuleHandler::Process ( const Module& module )
 {
 	GenerateStaticLibraryModuleTarget ( module );
+	GenerateInvocations ( module );
 }
 
 void

Modified: branches/xmlbuildsystem/reactos/tools/rbuild/backend/mingw/modulehandler.h
--- branches/xmlbuildsystem/reactos/tools/rbuild/backend/mingw/modulehandler.h	2005-01-08 18:11:46 UTC (rev 12890)
+++ branches/xmlbuildsystem/reactos/tools/rbuild/backend/mingw/modulehandler.h	2005-01-08 19:38:51 UTC (rev 12891)
@@ -15,6 +15,8 @@
 	                               const std::string& newExtension ) const;
 	std::string GetModuleArchiveFilename ( const Module& module ) const;
 	std::string GetImportLibraryDependencies ( const Module& module ) const;
+	std::string GetModuleDependencies ( const Module& module ) const;
+	std::string GetAllDependencies ( const Module& module ) const;
 	std::string GetSourceFilenames ( const Module& module ) const;
 
 	std::string GetObjectFilename ( const std::string& sourceFilename ) const;
@@ -23,6 +25,8 @@
 	void GenerateObjectFileTargetsTarget ( const Module& module ) const;
 	void GenerateArchiveTargetHost ( const Module& module ) const;
 	void GenerateArchiveTargetTarget ( const Module& module ) const;
+	std::string GetInvocationDependencies ( const Module& module ) const;
+	void GenerateInvocations ( const Module& module ) const;
 	FILE* fMakefile;
 private:
 	std::string ConcatenatePaths ( const std::string& path1,

Modified: branches/xmlbuildsystem/reactos/tools/rbuild/makefile
--- branches/xmlbuildsystem/reactos/tools/rbuild/makefile	2005-01-08 18:11:46 UTC (rev 12890)
+++ branches/xmlbuildsystem/reactos/tools/rbuild/makefile	2005-01-08 19:38:51 UTC (rev 12891)
@@ -27,6 +27,7 @@
 TESTS = \
 	tests/definetest.o \
 	tests/includetest.o \
+	tests/invoketest.o \
 	tests/moduletest.o \
 	tests/projecttest.o
 

Modified: branches/xmlbuildsystem/reactos/tools/rbuild/module.cpp
--- branches/xmlbuildsystem/reactos/tools/rbuild/module.cpp	2005-01-08 18:11:46 UTC (rev 12890)
+++ branches/xmlbuildsystem/reactos/tools/rbuild/module.cpp	2005-01-08 19:38:51 UTC (rev 12891)
@@ -54,6 +54,14 @@
 		delete files[i];
 	for ( i = 0; i < libraries.size(); i++ )
 		delete libraries[i];
+	for ( i = 0; i < includes.size(); i++ )
+		delete includes[i];
+	for ( i = 0; i < defines.size(); i++ )
+		delete defines[i];
+	for ( i = 0; i < invocations.size(); i++ )
+		delete invocations[i];
+	for ( i = 0; i < dependencies.size(); i++ )
+		delete dependencies[i];
 }
 
 void
@@ -62,14 +70,18 @@
 	size_t i;
 	for ( i = 0; i < node.subElements.size(); i++ )
 		ProcessXMLSubElement ( *node.subElements[i], path );
-	for ( i = 0; i < files.size(); i++ )
-		files[i]->ProcessXML();
+	for ( i = 0; i < files.size (); i++ )
+		files[i]->ProcessXML ();
 	for ( i = 0; i < libraries.size(); i++ )
-		libraries[i]->ProcessXML();
+		libraries[i]->ProcessXML ();
 	for ( i = 0; i < includes.size(); i++ )
-		includes[i]->ProcessXML();
+		includes[i]->ProcessXML ();
 	for ( i = 0; i < defines.size(); i++ )
-		defines[i]->ProcessXML();
+		defines[i]->ProcessXML ();
+	for ( i = 0; i < invocations.size(); i++ )
+		invocations[i]->ProcessXML ();
+	for ( i = 0; i < dependencies.size(); i++ )
+		dependencies[i]->ProcessXML ();
 }
 
 void
@@ -78,7 +90,7 @@
 {
 	bool subs_invalid = false;
 	string subpath ( path );
-	if ( e.name == "file" && e.value.size () )
+	if ( e.name == "file" && e.value.size () > 0 )
 	{
 		files.push_back ( new File ( FixSeparator ( path + CSEP + e.value ) ) );
 		subs_invalid = true;
@@ -104,7 +116,17 @@
 		defines.push_back ( new Define ( project, this, e ) );
 		subs_invalid = true;
 	}
-	if ( subs_invalid && e.subElements.size() )
+	else if ( e.name == "invoke" )
+	{
+		invocations.push_back ( new Invoke ( e, *this ) );
+		subs_invalid = false;
+	}
+	else if ( e.name == "dependency" )
+	{
+		dependencies.push_back ( new Dependency ( e, *this ) );
+		subs_invalid = true;
+	}
+	if ( subs_invalid && e.subElements.size() > 0 )
 		throw InvalidBuildFileException (
 			e.location,
 			"<%s> cannot have sub-elements",
@@ -154,7 +176,34 @@
 	return path + CSEP + name + extension;
 }
 
+string
+Module::GetTargets () const
+{
+	if ( invocations.size () > 0 )
+	{
+		string targets ( "" );
+		for ( size_t i = 0; i < invocations.size (); i++ )
+		{
+			Invoke& invoke = *invocations[i];
+			if ( targets.length () > 0 )
+				targets += " ";
+			targets += invoke.GetTargets ();
+		}
+		return targets;
+	}
+	else
+		return GetPath ();
+}
 
+string
+Module::GetInvocationTarget ( const int index ) const
+{
+	return ssprintf ( "%s_invoke_%d",
+	                  name.c_str (),
+	                  index );
+}
+
+
 File::File ( const string& _name )
 	: name(_name)
 {
@@ -165,6 +214,7 @@
 {
 }
 
+
 Library::Library ( const XMLElement& _node,
                    const Module& _module,
                    const string& _name )
@@ -189,3 +239,82 @@
 			module.name.c_str(),
 			name.c_str() );
 }
+
+
+Invoke::Invoke ( const XMLElement& _node,
+                 const Module& _module )
+	: node(_node),
+	  module(_module)
+{
+}
+
+void
+Invoke::ProcessXML()
+{
+	for ( size_t i = 0; i < node.subElements.size (); i++ )
+		ProcessXMLSubElement ( *node.subElements[i] );
+}
+
+void
+Invoke::ProcessXMLSubElement ( const XMLElement& e )
+{
+	bool subs_invalid = false;
+	if ( e.name == "output" )
+	{
+		for ( size_t i = 0; i < e.subElements.size (); i++ )
+			ProcessXMLSubElementOutput ( *e.subElements[i] );
+	}
+	if ( subs_invalid && e.subElements.size() > 0 )
+		throw InvalidBuildFileException ( e.location,
+		                                  "<%s> cannot have sub-elements",
+		                                  e.name.c_str() );
+}
+
+void
+Invoke::ProcessXMLSubElementOutput ( const XMLElement& e )
+{
+	bool subs_invalid = false;
+	if ( e.name == "outputfile" && e.value.size () > 0 )
+	{
+		output.push_back ( new File ( FixSeparator ( module.path + CSEP + e.value ) ) );
+		subs_invalid = true;
+	}
+	if ( subs_invalid && e.subElements.size() > 0 )
+		throw InvalidBuildFileException ( e.location,
+		                                  "<%s> cannot have sub-elements",
+		                                  e.name.c_str() );
+}
+
+string
+Invoke::GetTargets () const
+{
+	string targets ( "" );
+	for ( size_t i = 0; i < output.size (); i++ )
+	{
+		File& file = *output[i];
+		if ( targets.length () > 0 )
+			targets += " ";
+		targets += file.name;
+	}
+	return targets;
+}
+
+
+Dependency::Dependency ( const XMLElement& _node,
+                         const Module& _module )
+	: node (_node),
+	  module (_module),
+	  dependencyModule (NULL)
+{
+}
+
+void
+Dependency::ProcessXML()
+{
+	dependencyModule = module.project.LocateModule ( node.value );
+	if ( dependencyModule == NULL )
+		throw InvalidBuildFileException ( node.location,
+		                                  "module '%s' depend on non-existant module '%s'",
+		                                  module.name.c_str(),
+		                                  node.value.c_str() );
+}

Modified: branches/xmlbuildsystem/reactos/tools/rbuild/rbuild.h
--- branches/xmlbuildsystem/reactos/tools/rbuild/rbuild.h	2005-01-08 18:11:46 UTC (rev 12890)
+++ branches/xmlbuildsystem/reactos/tools/rbuild/rbuild.h	2005-01-08 19:38:51 UTC (rev 12891)
@@ -27,6 +27,8 @@
 class Define;
 class File;
 class Library;
+class Invoke;
+class Dependency;
 
 class Project
 {
@@ -73,7 +75,9 @@
 	std::vector<Library*> libraries;
 	std::vector<Include*> includes;
 	std::vector<Define*> defines;
-
+	std::vector<Invoke*> invocations;
+	std::vector<Dependency*> dependencies;
+	
 	Module ( const Project& project,
 	         const XMLElement& moduleNode,
 	         const std::string& modulePath );
@@ -81,6 +85,8 @@
 	ModuleType GetModuleType (const XMLAttribute& attribute );
 	std::string GetBasePath() const;
 	std::string GetPath () const;
+	std::string GetTargets () const;
+	std::string GetInvocationTarget ( const int index ) const;
 	void ProcessXML();
 private:
 	std::string GetDefaultModuleExtension () const;
@@ -156,6 +162,38 @@
 	void ProcessXML();
 };
 
+
+class Invoke
+{
+public:
+	const XMLElement& node;
+	const Module& module;
+	std::vector<File*> output;
+
+	Invoke ( const XMLElement& _node,
+	         const Module& _module );
+
+	void ProcessXML();
+	std::string GetTargets () const;
+private:
+	void ProcessXMLSubElement ( const XMLElement& e );
+	void ProcessXMLSubElementOutput ( const XMLElement& e );
+};
+
+
+class Dependency
+{
+public:
+	const XMLElement& node;
+	const Module& module;
+	const Module* dependencyModule;
+
+	Dependency ( const XMLElement& _node,
+	             const Module& _module );
+
+	void ProcessXML();
+};
+
 extern std::string
 FixSeparator ( const std::string& s );
 

Modified: branches/xmlbuildsystem/reactos/tools/rbuild/test.h
--- branches/xmlbuildsystem/reactos/tools/rbuild/test.h	2005-01-08 18:11:46 UTC (rev 12890)
+++ branches/xmlbuildsystem/reactos/tools/rbuild/test.h	2005-01-08 19:38:51 UTC (rev 12891)
@@ -12,6 +12,12 @@
 	virtual void Run() = 0;
 protected:
 	void Assert(const char *message, ...);
+	void IsNull(void* reference,
+	            const char* file,
+	            int line);
+	void IsNotNull(void* reference,
+	               const char* file,
+	               int line);
 	void IsTrue(bool condition,
 	            const char* file,
 	            int line);
@@ -34,6 +40,8 @@
 	void Fail();
 };
 
+#define IS_NULL(reference) IsNull((void*)reference,__FILE__,__LINE__)
+#define IS_NOT_NULL(reference) IsNotNull((void*)reference,__FILE__,__LINE__)
 #define IS_TRUE(condition) IsTrue(condition,__FILE__,__LINE__)
 #define IS_FALSE(condition) IsFalse(condition,__FILE__,__LINE__)
 #define ARE_EQUAL(expected,actual) AreEqual(expected,actual,__FILE__,__LINE__)
@@ -66,4 +74,11 @@
 	void Run();
 };
 
+
+class InvokeTest : public BaseTest
+{
+public:
+	void Run();
+};
+
 #endif /* __TEST_H */

Modified: branches/xmlbuildsystem/reactos/tools/rbuild/tests/alltests.cpp
--- branches/xmlbuildsystem/reactos/tools/rbuild/tests/alltests.cpp	2005-01-08 18:11:46 UTC (rev 12890)
+++ branches/xmlbuildsystem/reactos/tools/rbuild/tests/alltests.cpp	2005-01-08 19:38:51 UTC (rev 12891)
@@ -22,6 +22,30 @@
 	Fail();
 }
 
+void BaseTest::IsNull(void* reference,
+                      const char* file,
+                      int line)
+{
+	if (reference != NULL)
+	{
+		Assert("Condition was not NULL at %s:%d\n",
+		       file,
+		       line);
+	}
+}
+
+void BaseTest::IsNotNull(void* reference,
+                         const char* file,
+                         int line)
+{
+	if (reference == NULL)
+	{
+		Assert("Condition was NULL at %s:%d\n",
+		       file,
+		       line);
+	}
+}
+
 void BaseTest::IsTrue(bool condition,
                       const char* file,
                       int line)
@@ -149,6 +173,7 @@
 		tests.push_back(new ModuleTest());
 		tests.push_back(new DefineTest());
 		tests.push_back(new IncludeTest());
+		tests.push_back(new InvokeTest());
 	}
 };
 

Added: branches/xmlbuildsystem/reactos/tools/rbuild/tests/data/invoke.xml
--- branches/xmlbuildsystem/reactos/tools/rbuild/tests/data/invoke.xml	2005-01-08 18:11:46 UTC (rev 12890)
+++ branches/xmlbuildsystem/reactos/tools/rbuild/tests/data/invoke.xml	2005-01-08 19:38:51 UTC (rev 12891)
@@ -0,0 +1,13 @@
+<?xml version="1.0" ?>
+<project name="Project" makefile="Makefile">
+	<directory name="dir1">
+		<module name="module1" type="buildtool">
+			<file>file1.c</file>
+			<invoke>
+				<output>
+					<outputfile>file1.c</outputfile>
+				</output>
+			</invoke>
+		</module>
+	</directory>
+</project>

Modified: branches/xmlbuildsystem/reactos/tools/rbuild/tests/data/module.xml
--- branches/xmlbuildsystem/reactos/tools/rbuild/tests/data/module.xml	2005-01-08 18:11:46 UTC (rev 12890)
+++ branches/xmlbuildsystem/reactos/tools/rbuild/tests/data/module.xml	2005-01-08 19:38:51 UTC (rev 12891)
@@ -8,6 +8,7 @@
 	</directory>
 	<directory name="dir2">
 		<module name="module2" type="kernelmodedll">
+			<dependency>module1</dependency>
 			<library>module1</library>
 			<file>file3.c</file>
 			<file>file4.c</file>

Added: branches/xmlbuildsystem/reactos/tools/rbuild/tests/invoketest.cpp
--- branches/xmlbuildsystem/reactos/tools/rbuild/tests/invoketest.cpp	2005-01-08 18:11:46 UTC (rev 12890)
+++ branches/xmlbuildsystem/reactos/tools/rbuild/tests/invoketest.cpp	2005-01-08 19:38:51 UTC (rev 12891)
@@ -0,0 +1,19 @@
+#include "test.h"
+
+using std::string;
+
+void InvokeTest::Run()
+{
+	string projectFilename ( "tests/data/invoke.xml" );
+	Project project ( projectFilename );
+	ARE_EQUAL(1, project.modules.size());
+
+	Module& module1 = *project.modules[0];
+	ARE_EQUAL(1, module1.invocations.size());
+
+	Invoke& invoke1 = *module1.invocations[0];
+	ARE_EQUAL(1, invoke1.output.size());
+
+	File& file1 = *invoke1.output[0];
+	ARE_EQUAL(".\\dir1\\file1.c", file1.name);
+}

Modified: branches/xmlbuildsystem/reactos/tools/rbuild/tests/moduletest.cpp
--- branches/xmlbuildsystem/reactos/tools/rbuild/tests/moduletest.cpp	2005-01-08 18:11:46 UTC (rev 12890)
+++ branches/xmlbuildsystem/reactos/tools/rbuild/tests/moduletest.cpp	2005-01-08 19:38:51 UTC (rev 12891)
@@ -24,6 +24,10 @@
 
 	ARE_EQUAL(1, module2.libraries.size());
 	Library& library1 = *module2.libraries[0];
+	ARE_EQUAL("module1", library1.name);
 
-	ARE_EQUAL("module1", library1.name);
+	ARE_EQUAL(1, module2.dependencies.size());
+	Dependency& module1dependency = *module2.dependencies[0];
+	IS_NOT_NULL(module1dependency.dependencyModule);
+	ARE_EQUAL("module1", module1dependency.dependencyModule->name);
 }

Added: branches/xmlbuildsystem/reactos/tools/tools.xml
--- branches/xmlbuildsystem/reactos/tools/tools.xml	2005-01-08 18:11:46 UTC (rev 12890)
+++ branches/xmlbuildsystem/reactos/tools/tools.xml	2005-01-08 19:38:51 UTC (rev 12891)
@@ -0,0 +1,9 @@
+<module name="buildno" type="buildtool">
+	<include base="buildno">.</include>
+	<file>buildno.c</file>
+	<invoke>
+		<output>
+			<outputfile>../include/reactos/buildno.h</outputfile>
+		</output>
+	</invoke>
+</module>