more efficient detection of C++ modules, fixed bug in C++ pch support, always clean...
[reactos.git] / reactos / tools / rbuild / module.cpp
index 4d9b3ee..0ffae73 100644 (file)
@@ -1,5 +1,3 @@
-// module.cpp\r
-\r
 #include "pch.h"\r
 #include <assert.h>\r
 \r
@@ -21,77 +19,835 @@ FixSeparator ( const string& s )
        return s2;\r
 }\r
 \r
-Module::Module ( Project* project,\r
-                 const XMLElement& moduleNode,\r
-                 const string& moduleName,\r
-                 const string& modulePath )\r
-       : project(project),\r
-         node(moduleNode),\r
-         name(moduleName),\r
-         path(modulePath)\r
+string\r
+GetExtension ( const string& filename )\r
 {\r
-       type = GetModuleType ( *moduleNode.GetAttribute ( "type", true ) );\r
+       size_t index = filename.find_last_of ( '/' );\r
+       if (index == string::npos) index = 0;\r
+       string tmp = filename.substr( index, filename.size() - index );\r
+       size_t ext_index = tmp.find_last_of( '.' );\r
+       if (ext_index != string::npos) \r
+               return filename.substr ( index + ext_index, filename.size() );\r
+       return "";\r
 }\r
 \r
-Module::~Module ()\r
+string\r
+GetDirectory ( const string& filename )\r
+{\r
+       size_t index = filename.find_last_of ( CSEP );\r
+       if ( index == string::npos )\r
+               return filename;\r
+       else\r
+               return filename.substr ( 0, index );\r
+}\r
+\r
+string\r
+NormalizeFilename ( const string& filename )\r
+{\r
+       Path path;\r
+       string normalizedPath = path.Fixup ( filename, true );\r
+       string relativeNormalizedPath = path.RelativeFromWorkingDirectory ( normalizedPath );\r
+       return FixSeparator ( relativeNormalizedPath );\r
+}\r
+\r
+IfableData::~IfableData()\r
 {\r
        size_t i;\r
        for ( i = 0; i < files.size(); i++ )\r
                delete files[i];\r
+       for ( i = 0; i < includes.size(); i++ )\r
+               delete includes[i];\r
+       for ( i = 0; i < defines.size(); i++ )\r
+               delete defines[i];\r
        for ( i = 0; i < libraries.size(); i++ )\r
                delete libraries[i];\r
+       for ( i = 0; i < properties.size(); i++ )\r
+               delete properties[i];\r
+       for ( i = 0; i < ifs.size(); i++ )\r
+               delete ifs[i];\r
+}\r
+\r
+void IfableData::ProcessXML ()\r
+{\r
+       size_t i;\r
+       for ( i = 0; i < files.size (); i++ )\r
+               files[i]->ProcessXML ();\r
+       for ( i = 0; i < includes.size (); i++ )\r
+               includes[i]->ProcessXML ();\r
+       for ( i = 0; i < defines.size (); i++ )\r
+               defines[i]->ProcessXML ();\r
+       for ( i = 0; i < libraries.size (); i++ )\r
+               libraries[i]->ProcessXML ();\r
+       for ( i = 0; i < properties.size(); i++ )\r
+               properties[i]->ProcessXML ();\r
+       for ( i = 0; i < ifs.size (); i++ )\r
+               ifs[i]->ProcessXML ();\r
+}\r
+\r
+Module::Module ( const Project& project,\r
+                 const XMLElement& moduleNode,\r
+                 const string& modulePath )\r
+       : project (project),\r
+         node (moduleNode),\r
+         importLibrary (NULL),\r
+         bootstrap (NULL),\r
+         pch (NULL),\r
+         cplusplus (false)\r
+{\r
+       if ( node.name != "module" )\r
+               throw Exception ( "internal tool error: Module created with non-<module> node" );\r
+\r
+       path = FixSeparator ( modulePath );\r
+\r
+       const XMLAttribute* att = moduleNode.GetAttribute ( "name", true );\r
+       assert(att);\r
+       name = att->value;\r
+\r
+       att = moduleNode.GetAttribute ( "type", true );\r
+       assert(att);\r
+       type = GetModuleType ( node.location, *att );\r
+\r
+       att = moduleNode.GetAttribute ( "extension", false );\r
+       if ( att != NULL )\r
+               extension = att->value;\r
+       else\r
+               extension = GetDefaultModuleExtension ();\r
+\r
+       att = moduleNode.GetAttribute ( "entrypoint", false );\r
+       if ( att != NULL )\r
+               entrypoint = att->value;\r
+       else\r
+               entrypoint = GetDefaultModuleEntrypoint ();\r
+\r
+       att = moduleNode.GetAttribute ( "baseaddress", false );\r
+       if ( att != NULL )\r
+               baseaddress = att->value;\r
+       else\r
+               baseaddress = GetDefaultModuleBaseaddress ();\r
+\r
+       att = moduleNode.GetAttribute ( "mangledsymbols", false );\r
+       if ( att != NULL )\r
+               mangledSymbols = att->value != "false";\r
+       else\r
+               mangledSymbols = false;\r
+}\r
+\r
+Module::~Module ()\r
+{\r
+       size_t i;\r
+       for ( i = 0; i < invocations.size(); i++ )\r
+               delete invocations[i];\r
+       for ( i = 0; i < dependencies.size(); i++ )\r
+               delete dependencies[i];\r
+       for ( i = 0; i < compilerFlags.size(); i++ )\r
+               delete compilerFlags[i];\r
+       for ( i = 0; i < linkerFlags.size(); i++ )\r
+               delete linkerFlags[i];\r
+       if ( pch )\r
+               delete pch;\r
 }\r
 \r
 void\r
-Module::ProcessXML ( const XMLElement& e,\r
-                     const string& path )\r
+Module::ProcessXML()\r
 {\r
+       size_t i;\r
+       for ( i = 0; i < node.subElements.size(); i++ )\r
+               ProcessXMLSubElement ( *node.subElements[i], path );\r
+       for ( i = 0; i < invocations.size(); i++ )\r
+               invocations[i]->ProcessXML ();\r
+       for ( i = 0; i < dependencies.size(); i++ )\r
+               dependencies[i]->ProcessXML ();\r
+       for ( i = 0; i < compilerFlags.size(); i++ )\r
+               compilerFlags[i]->ProcessXML();\r
+       for ( i = 0; i < linkerFlags.size(); i++ )\r
+               linkerFlags[i]->ProcessXML();\r
+       non_if_data.ProcessXML();\r
+       if ( pch )\r
+               pch->ProcessXML();\r
+}\r
+\r
+void\r
+Module::ProcessXMLSubElement ( const XMLElement& e,\r
+                               const string& path,\r
+                               If* pIf /*= NULL*/ )\r
+{\r
+       bool subs_invalid = false;\r
        string subpath ( path );\r
-       if ( e.name == "file" && e.value.size () )\r
+       if ( e.name == "file" && e.value.size () > 0 )\r
        {\r
-               files.push_back ( new File ( path + CSEP + e.value ) );\r
+               bool first = false;\r
+               const XMLAttribute* att = e.GetAttribute ( "first", false );\r
+               if ( att )\r
+               {\r
+                       if ( !stricmp ( att->value.c_str(), "true" ) )\r
+                               first = true;\r
+                       else if ( stricmp ( att->value.c_str(), "false" ) )\r
+                               throw InvalidBuildFileException (\r
+                                       e.location,\r
+                                       "attribute 'first' of <file> element can only be 'true' or 'false'" );\r
+               }\r
+               if ( !cplusplus )\r
+               {\r
+                       // check for c++ file\r
+                       string ext = GetExtension ( e.value );\r
+                       if ( !stricmp ( ext.c_str(), ".cpp" ) )\r
+                               cplusplus = true;\r
+                       else if ( !stricmp ( ext.c_str(), ".cc" ) )\r
+                               cplusplus = true;\r
+                       else if ( !stricmp ( ext.c_str(), ".cxx" ) )\r
+                               cplusplus = true;\r
+               }\r
+               File* pFile = new File ( FixSeparator ( path + CSEP + e.value ), first );\r
+               if ( pIf )\r
+                       pIf->data.files.push_back ( pFile );\r
+               else\r
+                       non_if_data.files.push_back ( pFile );\r
+               subs_invalid = true;\r
        }\r
        else if ( e.name == "library" && e.value.size () )\r
        {\r
-               libraries.push_back ( new Library ( e.value ) );\r
+               Library* pLibrary = new Library ( e, *this, e.value );\r
+               if ( pIf )\r
+                       pIf->data.libraries.push_back ( pLibrary );\r
+               else\r
+                       non_if_data.libraries.push_back ( pLibrary );\r
+               subs_invalid = true;\r
        }\r
        else if ( e.name == "directory" )\r
        {\r
                const XMLAttribute* att = e.GetAttribute ( "name", true );\r
                assert(att);\r
-               subpath = path + CSEP + att->value;\r
+               subpath = FixSeparator ( path + CSEP + att->value );\r
+       }\r
+       else if ( e.name == "include" )\r
+       {\r
+               Include* include = new Include ( project, this, e );\r
+               if ( pIf )\r
+                       pIf->data.includes.push_back ( include );\r
+               else\r
+                       non_if_data.includes.push_back ( include );\r
+               subs_invalid = true;\r
+       }\r
+       else if ( e.name == "define" )\r
+       {\r
+               Define* pDefine = new Define ( project, this, e );\r
+               if ( pIf )\r
+                       pIf->data.defines.push_back ( pDefine );\r
+               else\r
+                       non_if_data.defines.push_back ( pDefine );\r
+               subs_invalid = true;\r
+       }\r
+       else if ( e.name == "invoke" )\r
+       {\r
+               if ( pIf )\r
+                       throw InvalidBuildFileException (\r
+                               e.location,\r
+                               "<invoke> is not a valid sub-element of <if>" );\r
+               invocations.push_back ( new Invoke ( e, *this ) );\r
+               subs_invalid = false;\r
+       }\r
+       else if ( e.name == "dependency" )\r
+       {\r
+               if ( pIf )\r
+                       throw InvalidBuildFileException (\r
+                               e.location,\r
+                               "<dependency> is not a valid sub-element of <if>" );\r
+               dependencies.push_back ( new Dependency ( e, *this ) );\r
+               subs_invalid = true;\r
+       }\r
+       else if ( e.name == "importlibrary" )\r
+       {\r
+               if ( pIf )\r
+                       throw InvalidBuildFileException (\r
+                               e.location,\r
+                               "<importlibrary> is not a valid sub-element of <if>" );\r
+               if ( importLibrary )\r
+                       throw InvalidBuildFileException (\r
+                               e.location,\r
+                               "Only one <importlibrary> is valid per module" );\r
+               importLibrary = new ImportLibrary ( e, *this );\r
+               subs_invalid = true;\r
+       }\r
+       else if ( e.name == "if" )\r
+       {\r
+               If* pOldIf = pIf;\r
+               pIf = new If ( e, project, this );\r
+               if ( pOldIf )\r
+                       pOldIf->data.ifs.push_back ( pIf );\r
+               else\r
+                       non_if_data.ifs.push_back ( pIf );\r
+               subs_invalid = false;\r
+       }\r
+       else if ( e.name == "compilerflag" )\r
+       {\r
+               compilerFlags.push_back ( new CompilerFlag ( project, this, e ) );\r
+               subs_invalid = true;\r
+       }\r
+       else if ( e.name == "linkerflag" )\r
+       {\r
+               linkerFlags.push_back ( new LinkerFlag ( project, this, e ) );\r
+               subs_invalid = true;\r
+       }\r
+       else if ( e.name == "property" )\r
+       {\r
+               throw InvalidBuildFileException (\r
+                       e.location,\r
+                       "<property> is not a valid sub-element of <module>" );\r
+       }\r
+       else if ( e.name == "bootstrap" )\r
+       {\r
+               bootstrap = new Bootstrap ( project, this, e );\r
+               subs_invalid = true;\r
+       }\r
+       else if ( e.name == "pch" )\r
+       {\r
+               if ( pIf )\r
+                       throw InvalidBuildFileException (\r
+                               e.location,\r
+                               "<pch> is not a valid sub-element of <if>" );\r
+               if ( pch )\r
+                       throw InvalidBuildFileException (\r
+                               e.location,\r
+                               "Only one <pch> is valid per module" );\r
+               pch = new PchFile (\r
+                       e, *this, FixSeparator ( path + CSEP + e.value ) );\r
+               subs_invalid = true;\r
        }\r
+       if ( subs_invalid && e.subElements.size() > 0 )\r
+               throw InvalidBuildFileException (\r
+                       e.location,\r
+                       "<%s> cannot have sub-elements",\r
+                       e.name.c_str() );\r
        for ( size_t i = 0; i < e.subElements.size (); i++ )\r
-               ProcessXML ( *e.subElements[i], subpath );\r
+               ProcessXMLSubElement ( *e.subElements[i], subpath, pIf );\r
 }\r
 \r
 ModuleType\r
-Module::GetModuleType ( const XMLAttribute& attribute )\r
+Module::GetModuleType ( const string& location, const XMLAttribute& attribute )\r
 {\r
        if ( attribute.value == "buildtool" )\r
                return BuildTool;\r
        if ( attribute.value == "staticlibrary" )\r
                return StaticLibrary;\r
+       if ( attribute.value == "objectlibrary" )\r
+               return ObjectLibrary;\r
+       if ( attribute.value == "kernel" )\r
+               return Kernel;\r
        if ( attribute.value == "kernelmodedll" )\r
                return KernelModeDLL;\r
-       throw InvalidAttributeValueException ( attribute.name,\r
+       if ( attribute.value == "kernelmodedriver" )\r
+               return KernelModeDriver;\r
+       if ( attribute.value == "nativedll" )\r
+               return NativeDLL;\r
+       if ( attribute.value == "nativecui" )\r
+               return NativeCUI;\r
+       if ( attribute.value == "win32dll" )\r
+               return Win32DLL;\r
+       if ( attribute.value == "win32cui" )\r
+               return Win32CUI;\r
+       if ( attribute.value == "win32gui" )\r
+               return Win32GUI;\r
+       if ( attribute.value == "bootloader" )\r
+               return BootLoader;\r
+       if ( attribute.value == "bootsector" )\r
+               return BootSector;\r
+       if ( attribute.value == "iso" )\r
+               return Iso;\r
+       throw InvalidAttributeValueException ( location,\r
+                                              attribute.name,\r
                                               attribute.value );\r
 }\r
 \r
 string\r
-Module::GetPath ()\r
+Module::GetDefaultModuleExtension () const\r
+{\r
+       switch (type)\r
+       {\r
+               case BuildTool:\r
+                       return EXEPOSTFIX;\r
+               case StaticLibrary:\r
+                       return ".a";\r
+               case ObjectLibrary:\r
+                       return ".o";\r
+               case Kernel:\r
+               case NativeCUI:\r
+               case Win32CUI:\r
+               case Win32GUI:\r
+                       return ".exe";\r
+               case KernelModeDLL:\r
+               case NativeDLL:\r
+               case Win32DLL:\r
+                       return ".dll";\r
+               case KernelModeDriver:\r
+               case BootLoader:\r
+                       return ".sys";\r
+               case BootSector:\r
+                       return ".o";\r
+               case Iso:\r
+                       return ".iso";\r
+       }\r
+       throw InvalidOperationException ( __FILE__,\r
+                                         __LINE__ );\r
+}\r
+\r
+string\r
+Module::GetDefaultModuleEntrypoint () const\r
+{\r
+       switch (type)\r
+       {\r
+               case Kernel:\r
+                       return "_NtProcessStartup";\r
+               case KernelModeDLL:\r
+                       return "_DriverEntry@8";\r
+               case NativeDLL:\r
+                       return "_DllMainCRTStartup@12";\r
+               case NativeCUI:\r
+                       return "_NtProcessStartup@4";\r
+               case Win32DLL:\r
+                       return "_DllMain@12";\r
+               case Win32CUI:\r
+                       return "_mainCRTStartup";\r
+               case Win32GUI:\r
+                       return "_WinMainCRTStartup";\r
+               case KernelModeDriver:\r
+                       return "_DriverEntry@8";\r
+               case BuildTool:\r
+               case StaticLibrary:\r
+               case ObjectLibrary:\r
+               case BootLoader:\r
+               case BootSector:\r
+               case Iso:\r
+                       return "";\r
+       }\r
+       throw InvalidOperationException ( __FILE__,\r
+                                         __LINE__ );\r
+}\r
+\r
+string\r
+Module::GetDefaultModuleBaseaddress () const\r
+{\r
+       switch (type)\r
+       {\r
+               case Kernel:\r
+                       return "0xc0000000";\r
+               case KernelModeDLL:\r
+                       return "0x10000";\r
+               case NativeDLL:\r
+                       return "0x10000";\r
+               case NativeCUI:\r
+                       return "0x10000";\r
+               case Win32DLL:\r
+                       return "0x10000";\r
+               case Win32CUI:\r
+                       return "0x00400000";\r
+               case Win32GUI:\r
+                       return "0x00400000";\r
+               case KernelModeDriver:\r
+                       return "0x10000";\r
+               case BuildTool:\r
+               case StaticLibrary:\r
+               case ObjectLibrary:\r
+               case BootLoader:\r
+               case BootSector:\r
+               case Iso:\r
+                       return "";\r
+       }\r
+       throw InvalidOperationException ( __FILE__,\r
+                                         __LINE__ );\r
+}\r
+\r
+bool\r
+Module::HasImportLibrary () const\r
+{\r
+       return importLibrary != NULL;\r
+}\r
+\r
+string\r
+Module::GetTargetName () const\r
+{\r
+       return name + extension;\r
+}\r
+\r
+string\r
+Module::GetDependencyPath () const\r
+{\r
+       if ( HasImportLibrary () )\r
+       {\r
+               return ssprintf ( "dk%snkm%slib%slib%s.a",\r
+                                 SSEP,\r
+                                 SSEP,\r
+                                 SSEP,\r
+                                 name.c_str () );\r
+       }\r
+       else\r
+               return GetPath();\r
+}\r
+\r
+string\r
+Module::GetBasePath () const\r
+{\r
+       return path;\r
+}\r
+\r
+string\r
+Module::GetPath () const\r
+{\r
+       return path + CSEP + GetTargetName ();\r
+}\r
+\r
+string\r
+Module::GetPathWithPrefix ( const string& prefix ) const\r
+{\r
+       return path + CSEP + prefix + GetTargetName ();\r
+}\r
+\r
+string\r
+Module::GetTargets () const\r
+{\r
+       if ( invocations.size () > 0 )\r
+       {\r
+               string targets ( "" );\r
+               for ( size_t i = 0; i < invocations.size (); i++ )\r
+               {\r
+                       Invoke& invoke = *invocations[i];\r
+                       if ( targets.length () > 0 )\r
+                               targets += " ";\r
+                       targets += invoke.GetTargets ();\r
+               }\r
+               return targets;\r
+       }\r
+       else\r
+               return GetPath ();\r
+}\r
+\r
+string\r
+Module::GetInvocationTarget ( const int index ) const\r
+{\r
+       return ssprintf ( "%s_invoke_%d",\r
+                         name.c_str (),\r
+                         index );\r
+}\r
+\r
+bool\r
+Module::HasFileWithExtension (\r
+       const IfableData& data,\r
+       const std::string& extension ) const\r
+{\r
+       size_t i;\r
+       for ( i = 0; i < data.files.size (); i++ )\r
+       {\r
+               File& file = *data.files[i];\r
+               string file_ext = GetExtension ( file.name );\r
+               if ( !stricmp ( file_ext.c_str (), extension.c_str () ) )\r
+                       return true;\r
+       }\r
+       for ( i = 0; i < data.ifs.size (); i++ )\r
+       {\r
+               if ( HasFileWithExtension ( data.ifs[i]->data, extension ) )\r
+                       return true;\r
+       }\r
+       return false;\r
+}\r
+\r
+void\r
+Module::InvokeModule () const\r
+{\r
+       for ( size_t i = 0; i < invocations.size (); i++ )\r
+       {\r
+               Invoke& invoke = *invocations[i];\r
+               string command = invoke.invokeModule->GetPath () + " " + invoke.GetParameters ();\r
+               printf ( "Executing '%s'\n\n", command.c_str () );\r
+               int exitcode = system ( command.c_str () );\r
+               if ( exitcode != 0 )\r
+                       throw InvocationFailedException ( command,\r
+                                                         exitcode );\r
+       }\r
+}\r
+\r
+\r
+File::File ( const string& _name, bool _first )\r
+       : name(_name), first(_first)\r
+{\r
+}\r
+\r
+void\r
+File::ProcessXML()\r
+{\r
+}\r
+\r
+\r
+Library::Library ( const XMLElement& _node,\r
+                   const Module& _module,\r
+                   const string& _name )\r
+       : node(_node),\r
+         module(_module),\r
+         name(_name),\r
+         imported_module(_module.project.LocateModule(_name))\r
+{\r
+       if ( module.name == name )\r
+               throw InvalidBuildFileException (\r
+                       node.location,\r
+                       "module '%s' cannot link against itself",\r
+                       name.c_str() );\r
+       if ( !imported_module )\r
+               throw InvalidBuildFileException (\r
+                       node.location,\r
+                       "module '%s' trying to import non-existant module '%s'",\r
+                       module.name.c_str(),\r
+                       name.c_str() );\r
+}\r
+\r
+void\r
+Library::ProcessXML()\r
+{\r
+       if ( !module.project.LocateModule ( name ) )\r
+               throw InvalidBuildFileException (\r
+                       node.location,\r
+                       "module '%s' is trying to link against non-existant module '%s'",\r
+                       module.name.c_str(),\r
+                       name.c_str() );\r
+}\r
+\r
+\r
+Invoke::Invoke ( const XMLElement& _node,\r
+                 const Module& _module )\r
+       : node (_node),\r
+         module (_module)\r
+{\r
+}\r
+\r
+void\r
+Invoke::ProcessXML()\r
+{\r
+       const XMLAttribute* att = node.GetAttribute ( "module", false );\r
+       if (att == NULL)\r
+               invokeModule = &module;\r
+       else\r
+       {\r
+               invokeModule = module.project.LocateModule ( att->value );\r
+               if ( invokeModule == NULL )\r
+                       throw InvalidBuildFileException (\r
+                               node.location,\r
+                               "module '%s' is trying to invoke non-existant module '%s'",\r
+                               module.name.c_str(),\r
+                               att->value.c_str() );\r
+       }\r
+\r
+       for ( size_t i = 0; i < node.subElements.size (); i++ )\r
+               ProcessXMLSubElement ( *node.subElements[i] );\r
+}\r
+\r
+void\r
+Invoke::ProcessXMLSubElement ( const XMLElement& e )\r
+{\r
+       bool subs_invalid = false;\r
+       if ( e.name == "input" )\r
+       {\r
+               for ( size_t i = 0; i < e.subElements.size (); i++ )\r
+                       ProcessXMLSubElementInput ( *e.subElements[i] );\r
+       }\r
+       else if ( e.name == "output" )\r
+       {\r
+               for ( size_t i = 0; i < e.subElements.size (); i++ )\r
+                       ProcessXMLSubElementOutput ( *e.subElements[i] );\r
+       }\r
+       if ( subs_invalid && e.subElements.size() > 0 )\r
+               throw InvalidBuildFileException ( e.location,\r
+                                                 "<%s> cannot have sub-elements",\r
+                                                 e.name.c_str() );\r
+}\r
+\r
+void\r
+Invoke::ProcessXMLSubElementInput ( const XMLElement& e )\r
+{\r
+       bool subs_invalid = false;\r
+       if ( e.name == "inputfile" && e.value.size () > 0 )\r
+       {\r
+               input.push_back ( new InvokeFile ( e, FixSeparator ( module.path + CSEP + e.value ) ) );\r
+               subs_invalid = true;\r
+       }\r
+       if ( subs_invalid && e.subElements.size() > 0 )\r
+               throw InvalidBuildFileException ( e.location,\r
+                                                 "<%s> cannot have sub-elements",\r
+                                                 e.name.c_str() );\r
+}\r
+\r
+void\r
+Invoke::ProcessXMLSubElementOutput ( const XMLElement& e )\r
+{\r
+       bool subs_invalid = false;\r
+       if ( e.name == "outputfile" && e.value.size () > 0 )\r
+       {\r
+               output.push_back ( new InvokeFile ( e, FixSeparator ( module.path + CSEP + e.value ) ) );\r
+               subs_invalid = true;\r
+       }\r
+       if ( subs_invalid && e.subElements.size() > 0 )\r
+               throw InvalidBuildFileException ( e.location,\r
+                                                 "<%s> cannot have sub-elements",\r
+                                                 e.name.c_str() );\r
+}\r
+\r
+string\r
+Invoke::GetTargets () const\r
+{\r
+       string targets ( "" );\r
+       for ( size_t i = 0; i < output.size (); i++ )\r
+       {\r
+               InvokeFile& file = *output[i];\r
+               if ( targets.length () > 0 )\r
+                       targets += " ";\r
+               targets += NormalizeFilename ( file.name );\r
+       }\r
+       return targets;\r
+}\r
+\r
+string\r
+Invoke::GetParameters () const\r
+{\r
+       string parameters ( "" );\r
+       size_t i;\r
+       for ( i = 0; i < output.size (); i++ )\r
+       {\r
+               if ( parameters.length () > 0)\r
+                       parameters += " ";\r
+               InvokeFile& invokeFile = *output[i];\r
+               if ( invokeFile.switches.length () > 0 )\r
+               {\r
+                       parameters += invokeFile.switches;\r
+                       parameters += " ";\r
+               }\r
+               parameters += invokeFile.name;\r
+       }\r
+\r
+       for ( i = 0; i < input.size (); i++ )\r
+       {\r
+               if ( parameters.length () > 0 )\r
+                       parameters += " ";\r
+               InvokeFile& invokeFile = *input[i];\r
+               if ( invokeFile.switches.length () > 0 )\r
+               {\r
+                       parameters += invokeFile.switches;\r
+                       parameters += " ";\r
+               }\r
+               parameters += invokeFile.name ;\r
+       }\r
+\r
+       return parameters;\r
+}\r
+\r
+\r
+InvokeFile::InvokeFile ( const XMLElement& _node,\r
+                         const string& _name )\r
+       : node (_node),\r
+      name (_name)\r
+{\r
+       const XMLAttribute* att = _node.GetAttribute ( "switches", false );\r
+       if (att != NULL)\r
+               switches = att->value;\r
+       else\r
+               switches = "";\r
+}\r
+\r
+void\r
+InvokeFile::ProcessXML()\r
+{\r
+}\r
+\r
+\r
+Dependency::Dependency ( const XMLElement& _node,\r
+                         const Module& _module )\r
+       : node (_node),\r
+         module (_module),\r
+         dependencyModule (NULL)\r
+{\r
+}\r
+\r
+void\r
+Dependency::ProcessXML()\r
+{\r
+       dependencyModule = module.project.LocateModule ( node.value );\r
+       if ( dependencyModule == NULL )\r
+               throw InvalidBuildFileException ( node.location,\r
+                                                 "module '%s' depend on non-existant module '%s'",\r
+                                                 module.name.c_str(),\r
+                                                 node.value.c_str() );\r
+}\r
+\r
+\r
+ImportLibrary::ImportLibrary ( const XMLElement& _node,\r
+                               const Module& _module )\r
+       : node (_node),\r
+         module (_module)\r
 {\r
-       return FixSeparator (path) + CSEP + name + EXEPOSTFIX;\r
+       const XMLAttribute* att = _node.GetAttribute ( "basename", false );\r
+       if (att != NULL)\r
+               basename = att->value;\r
+       else\r
+               basename = module.name;\r
+\r
+       att = _node.GetAttribute ( "definition", true );\r
+       assert (att);\r
+       definition = FixSeparator(att->value);\r
 }\r
 \r
 \r
-File::File ( const string& _name )\r
-       : name(_name)\r
+If::If ( const XMLElement& node_,\r
+         const Project& project_,\r
+         const Module* module_ )\r
+       : node(node_), project(project_), module(module_)\r
+{\r
+       const XMLAttribute* att;\r
+\r
+       att = node.GetAttribute ( "property", true );\r
+       assert(att);\r
+       property = att->value;\r
+\r
+       att = node.GetAttribute ( "value", true );\r
+       assert(att);\r
+       value = att->value;\r
+}\r
+\r
+If::~If ()\r
+{\r
+}\r
+\r
+void\r
+If::ProcessXML()\r
 {\r
 }\r
 \r
 \r
-Library::Library ( const string& _name )\r
-       : name(_name)\r
+Property::Property ( const XMLElement& node_,\r
+                     const Project& project_,\r
+                     const Module* module_ )\r
+       : node(node_), project(project_), module(module_)\r
+{\r
+       const XMLAttribute* att;\r
+\r
+       att = node.GetAttribute ( "name", true );\r
+       assert(att);\r
+       name = att->value;\r
+\r
+       att = node.GetAttribute ( "value", true );\r
+       assert(att);\r
+       value = att->value;\r
+}\r
+\r
+void\r
+Property::ProcessXML()\r
+{\r
+}\r
+\r
+\r
+PchFile::PchFile (\r
+       const XMLElement& node_,\r
+       const Module& module_,\r
+       const string& header_ )\r
+       : node(node_), module(module_), header(header_)\r
+{\r
+}\r
+\r
+void\r
+PchFile::ProcessXML()\r
 {\r
 }\r