Invocation of buildtool modules.

svn path=/branches/xmlbuildsystem/; revision=12891
This commit is contained in:
Casper Hornstrup 2005-01-08 19:38:51 +00:00
parent 30e8e25cb7
commit 87d6ec37a6
14 changed files with 365 additions and 27 deletions

View file

@ -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">

View file

@ -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>

View file

@ -33,7 +33,7 @@ MingwModuleHandler::ReplaceExtension ( const string& filename,
string
MingwModuleHandler::GetModuleArchiveFilename ( const Module& module ) const
{
return ReplaceExtension ( FixupTargetFilename(module.GetPath ()).c_str (),
return ReplaceExtension ( FixupTargetFilename ( module.GetPath () ).c_str (),
".a" );
}
@ -50,7 +50,38 @@ MingwModuleHandler::GetImportLibraryDependencies ( const Module& module ) const
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;
}
@ -74,9 +105,8 @@ MingwModuleHandler::GetSourceFilenames ( const Module& module ) const
string
MingwModuleHandler::GetObjectFilename ( const string& sourceFilename ) const
{
return
FixupTargetFilename ( ReplaceExtension ( sourceFilename,
".o" ) );
return FixupTargetFilename ( ReplaceExtension ( sourceFilename,
".o" ) );
}
string
@ -144,7 +174,7 @@ string
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 @@ MingwModuleHandler::GenerateObjectFileTargets ( const Module& module,
{
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 @@ MingwModuleHandler::GenerateArchiveTarget ( const Module& module,
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,6 +286,52 @@ MingwModuleHandler::GenerateArchiveTargetTarget ( const Module& module ) const
"${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 @@ void
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 @@ void
MingwKernelModuleHandler::Process ( const Module& module )
{
GenerateKernelModuleTarget ( module );
GenerateInvocations ( module );
}
void
@ -369,6 +449,7 @@ void
MingwStaticLibraryModuleHandler::Process ( const Module& module )
{
GenerateStaticLibraryModuleTarget ( module );
GenerateInvocations ( module );
}
void

View file

@ -15,6 +15,8 @@ protected:
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 @@ protected:
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,

View file

@ -27,6 +27,7 @@ OBJECTS = $(BASE_OBJECTS) rbuild.o
TESTS = \
tests/definetest.o \
tests/includetest.o \
tests/invoketest.o \
tests/moduletest.o \
tests/projecttest.o

View file

@ -54,6 +54,14 @@ Module::~Module ()
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 @@ Module::ProcessXML()
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 @@ Module::ProcessXMLSubElement ( const XMLElement& e,
{
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 @@ Module::ProcessXMLSubElement ( const XMLElement& e,
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,6 +176,33 @@ Module::GetPath () const
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 @@ File::ProcessXML()
{
}
Library::Library ( const XMLElement& _node,
const Module& _module,
const string& _name )
@ -189,3 +239,82 @@ Library::ProcessXML()
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() );
}

View file

@ -27,6 +27,8 @@ class Include;
class Define;
class File;
class Library;
class Invoke;
class Dependency;
class Project
{
@ -73,7 +75,9 @@ public:
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 @@ public:
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 @@ public:
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 );

View file

@ -12,6 +12,12 @@ public:
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 @@ private:
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 @@ public:
void Run();
};
class InvokeTest : public BaseTest
{
public:
void Run();
};
#endif /* __TEST_H */

View file

@ -22,6 +22,30 @@ void BaseTest::Assert(const char *message, ...)
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 @@ private:
tests.push_back(new ModuleTest());
tests.push_back(new DefineTest());
tests.push_back(new IncludeTest());
tests.push_back(new InvokeTest());
}
};

View file

@ -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>

View file

@ -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>

View file

@ -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);
}

View file

@ -24,6 +24,10 @@ void ModuleTest::Run()
ARE_EQUAL(1, module2.libraries.size());
Library& library1 = *module2.libraries[0];
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);
}

9
reactos/tools/tools.xml Normal file
View file

@ -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>