Files
reactos/reactos/tools/rbuild/module.cpp
T
Casper Hornstrup 40a6da67c4 * KernelModeDriver module support
* Build afd.sys


svn path=/branches/xmlbuildsystem/; revision=13078
2005-01-16 13:51:33 +00:00

566 lines
13 KiB
C++

// module.cpp
#include "pch.h"
#include <assert.h>
#include "rbuild.h"
using std::string;
using std::vector;
string
FixSeparator ( const string& s )
{
string s2(s);
char* p = strchr ( &s2[0], CBAD_SEP );
while ( p )
{
*p++ = CSEP;
p = strchr ( p, CBAD_SEP );
}
return s2;
}
Module::Module ( const Project& project,
const XMLElement& moduleNode,
const string& modulePath )
: project (project),
node (moduleNode),
importLibrary (NULL)
{
if ( node.name != "module" )
throw Exception ( "internal tool error: Module created with non-<module> node" );
path = FixSeparator ( modulePath );
const XMLAttribute* att = moduleNode.GetAttribute ( "name", true );
assert(att);
name = att->value;
att = moduleNode.GetAttribute ( "type", true );
assert(att);
type = GetModuleType ( node.location, *att );
att = moduleNode.GetAttribute ( "extension", false );
if (att != NULL)
extension = att->value;
else
extension = GetDefaultModuleExtension ();
}
Module::~Module ()
{
size_t i;
for ( i = 0; i < files.size(); i++ )
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];
for ( i = 0; i < ifs.size(); i++ )
delete ifs[i];
for ( i = 0; i < linkerFlags.size(); i++ )
delete linkerFlags[i];
}
void
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 < libraries.size(); i++ )
libraries[i]->ProcessXML ();
for ( i = 0; i < includes.size(); i++ )
includes[i]->ProcessXML ();
for ( i = 0; i < defines.size(); i++ )
defines[i]->ProcessXML ();
for ( i = 0; i < invocations.size(); i++ )
invocations[i]->ProcessXML ();
for ( i = 0; i < dependencies.size(); i++ )
dependencies[i]->ProcessXML ();
for ( i = 0; i < ifs.size(); i++ )
ifs[i]->ProcessXML();
for ( i = 0; i < linkerFlags.size(); i++ )
linkerFlags[i]->ProcessXML();
}
void
Module::ProcessXMLSubElement ( const XMLElement& e,
const string& path,
If* pIf /*= NULL*/ )
{
bool subs_invalid = false;
string subpath ( path );
if ( e.name == "file" && e.value.size () > 0 )
{
File* pFile = new File ( FixSeparator ( path + CSEP + e.value ) );
if ( pIf )
pIf->files.push_back ( pFile );
else
files.push_back ( pFile );
subs_invalid = true;
}
else if ( e.name == "library" && e.value.size () )
{
if ( pIf )
throw InvalidBuildFileException (
e.location,
"<library> is not a valid sub-element of <if>" );
libraries.push_back ( new Library ( e, *this, e.value ) );
subs_invalid = true;
}
else if ( e.name == "directory" )
{
const XMLAttribute* att = e.GetAttribute ( "name", true );
assert(att);
subpath = FixSeparator ( path + CSEP + att->value );
}
else if ( e.name == "include" )
{
Include* include = new Include ( project, this, e );
if ( pIf )
pIf->includes.push_back ( include );
else
includes.push_back ( include );
subs_invalid = true;
}
else if ( e.name == "define" )
{
Define* pDefine = new Define ( project, this, e );
if ( pIf )
pIf->defines.push_back ( pDefine );
else
defines.push_back ( pDefine );
subs_invalid = true;
}
else if ( e.name == "invoke" )
{
if ( pIf )
throw InvalidBuildFileException (
e.location,
"<invoke> is not a valid sub-element of <if>" );
invocations.push_back ( new Invoke ( e, *this ) );
subs_invalid = false;
}
else if ( e.name == "dependency" )
{
if ( pIf )
throw InvalidBuildFileException (
e.location,
"<dependency> is not a valid sub-element of <if>" );
dependencies.push_back ( new Dependency ( e, *this ) );
subs_invalid = true;
}
else if ( e.name == "importlibrary" )
{
if ( pIf )
throw InvalidBuildFileException (
e.location,
"<importlibrary> is not a valid sub-element of <if>" );
if ( importLibrary )
throw InvalidBuildFileException (
e.location,
"Only one <importlibrary> is valid per module" );
importLibrary = new ImportLibrary ( e, *this );
subs_invalid = true;
}
else if ( e.name == "if" )
{
If* pOldIf = pIf;
pIf = new If ( e, project, this );
if ( pOldIf )
pOldIf->ifs.push_back ( pIf );
else
ifs.push_back ( pIf );
subs_invalid = false;
}
else if ( e.name == "linkerflag" )
{
linkerFlags.push_back ( new LinkerFlag ( project, this, e ) );
subs_invalid = true;
}
else if ( e.name == "property" )
{
throw InvalidBuildFileException (
e.location,
"<property> is not a valid sub-element of <module>" );
}
if ( subs_invalid && e.subElements.size() > 0 )
throw InvalidBuildFileException (
e.location,
"<%s> cannot have sub-elements",
e.name.c_str() );
for ( size_t i = 0; i < e.subElements.size (); i++ )
ProcessXMLSubElement ( *e.subElements[i], subpath, pIf );
}
ModuleType
Module::GetModuleType ( const string& location, const XMLAttribute& attribute )
{
if ( attribute.value == "buildtool" )
return BuildTool;
if ( attribute.value == "staticlibrary" )
return StaticLibrary;
if ( attribute.value == "kernel" )
return Kernel;
if ( attribute.value == "kernelmodedll" )
return KernelModeDLL;
if ( attribute.value == "kernelmodedriver" )
return KernelModeDriver;
if ( attribute.value == "nativedll" )
return NativeDLL;
if ( attribute.value == "win32dll" )
return Win32DLL;
if ( attribute.value == "win32gui" )
return Win32GUI;
throw InvalidAttributeValueException ( location,
attribute.name,
attribute.value );
}
string
Module::GetDefaultModuleExtension () const
{
switch (type)
{
case BuildTool:
return EXEPOSTFIX;
case StaticLibrary:
return ".a";
case Kernel:
case Win32GUI:
return ".exe";
case KernelModeDLL:
case NativeDLL:
case Win32DLL:
return ".dll";
case KernelModeDriver:
return ".sys";
}
throw InvalidOperationException ( __FILE__,
__LINE__ );
}
bool
Module::HasImportLibrary () const
{
return importLibrary != NULL;
}
string
Module::GetTargetName () const
{
return name + extension;
}
string
Module::GetDependencyPath () const
{
if ( HasImportLibrary () )
{
return ssprintf ( "dk%snkm%slib%slib%s.a",
SSEP,
SSEP,
SSEP,
name.c_str () );
}
else
return GetPath();
}
string
Module::GetBasePath () const
{
return path;
}
string
Module::GetPath () const
{
return path + CSEP + GetTargetName ();
}
string
Module::GetPathWithPrefix ( const string& prefix ) const
{
return path + CSEP + prefix + GetTargetName ();
}
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)
{
}
void
File::ProcessXML()
{
}
Library::Library ( const XMLElement& _node,
const Module& _module,
const string& _name )
: node(_node),
module(_module),
name(_name)
{
if ( module.name == name )
throw InvalidBuildFileException (
node.location,
"module '%s' cannot link against itself",
name.c_str() );
}
void
Library::ProcessXML()
{
if ( !module.project.LocateModule ( name ) )
throw InvalidBuildFileException (
node.location,
"module '%s' is trying to link against non-existant module '%s'",
module.name.c_str(),
name.c_str() );
}
Invoke::Invoke ( const XMLElement& _node,
const Module& _module )
: node (_node),
module (_module)
{
}
void
Invoke::ProcessXML()
{
const XMLAttribute* att = node.GetAttribute ( "module", false );
if (att == NULL)
invokeModule = &module;
else
{
invokeModule = module.project.LocateModule ( att->value );
if ( invokeModule == NULL )
throw InvalidBuildFileException (
node.location,
"module '%s' is trying to invoke non-existant module '%s'",
module.name.c_str(),
att->value.c_str() );
}
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 == "input" )
{
for ( size_t i = 0; i < e.subElements.size (); i++ )
ProcessXMLSubElementInput ( *e.subElements[i] );
}
else 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::ProcessXMLSubElementInput ( const XMLElement& e )
{
bool subs_invalid = false;
if ( e.name == "inputfile" && e.value.size () > 0 )
{
input.push_back ( new InvokeFile ( e, 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() );
}
void
Invoke::ProcessXMLSubElementOutput ( const XMLElement& e )
{
bool subs_invalid = false;
if ( e.name == "outputfile" && e.value.size () > 0 )
{
output.push_back ( new InvokeFile ( e, 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++ )
{
InvokeFile& file = *output[i];
if ( targets.length () > 0 )
targets += " ";
targets += file.name;
}
return targets;
}
InvokeFile::InvokeFile ( const XMLElement& _node,
const string& _name )
: node (_node),
name (_name)
{
const XMLAttribute* att = _node.GetAttribute ( "switches", false );
if (att != NULL)
switches = att->value;
else
switches = "";
}
void
InvokeFile::ProcessXML()
{
}
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() );
}
ImportLibrary::ImportLibrary ( const XMLElement& _node,
const Module& _module )
: node (_node),
module (_module)
{
const XMLAttribute* att = _node.GetAttribute ( "basename", false );
if (att != NULL)
basename = att->value;
else
basename = module.name;
att = _node.GetAttribute ( "definition", true );
assert (att);
definition = FixSeparator(att->value);
}
If::If ( const XMLElement& node_,
const Project& project_,
const Module* module_ )
: node(node_), project(project_), module(module_)
{
const XMLAttribute* att;
att = node.GetAttribute ( "property", true );
assert(att);
property = att->value;
att = node.GetAttribute ( "value", true );
assert(att);
value = att->value;
}
If::~If ()
{
size_t i;
for ( i = 0; i < files.size(); i++ )
delete files[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 < ifs.size(); i++ )
delete ifs[i];
}
void
If::ProcessXML()
{
}
Property::Property ( const XMLElement& node_,
const Project& project_,
const Module* module_ )
: node(node_), project(project_), module(module_)
{
const XMLAttribute* att;
att = node.GetAttribute ( "name", true );
assert(att);
name = att->value;
att = node.GetAttribute ( "value", true );
assert(att);
value = att->value;
}
void
Property::ProcessXML()
{
}