-Add a new module type 'cabinet' to handle .cab files generation
[reactos.git] / reactos / tools / rbuild / backend / mingw / modulehandler.cpp
index 95fb631..aebc7bb 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2005 Casper S. Hornstrup
+ *               2007-2008 HervĂ© Poussineau
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  */
 #include "../../pch.h"
 #include <assert.h>
+#include <algorithm>
 
 #include "../../rbuild.h"
 #include "mingw.h"
 #include "modulehandler.h"
+#include "rule.h"
 
+using std::set;
 using std::string;
 using std::vector;
 
-#define CLEAN_FILE(f) clean_files.push_back ( f );
+#define CLEAN_FILE(f) clean_files.push_back ( (f).name.length () > 0 ? backend->GetFullName ( f ) : backend->GetFullPath ( f ) );
+#define IsStaticLibrary( module ) ( ( module.type == StaticLibrary ) || ( module.type == HostStaticLibrary ) )
 
-static string ros_temp = "$(TEMPORARY)";
 MingwBackend*
 MingwModuleHandler::backend = NULL;
 FILE*
@@ -96,94 +100,64 @@ MingwModuleHandler::EnablePreCompiledHeaderSupport ()
        use_pch = true;
 }
 
-/* static*/ string
-MingwModuleHandler::RemoveVariables ( string path)
+/*static*/ const FileLocation*
+MingwModuleHandler::PassThruCacheDirectory (const FileLocation* file )
 {
-       size_t i = path.find ( '$' );
-       if ( i != string::npos )
+       switch ( file->directory )
        {
-               size_t j = path.find ( ')', i );
-               if ( j != string::npos )
-               {
-                       if ( j + 2 < path.length () && path[j + 1] == cSep )
-                               return path.substr ( j + 2);
-                       else
-                               return path.substr ( j + 1);
-               }
-       }
-       return path;
-}
-
-/*static*/ string
-MingwModuleHandler::PassThruCacheDirectory (
-       const string &file,
-       Directory* directoryTree )
-{
-       string directory ( GetDirectory ( RemoveVariables ( file ) ) );
-       if ( directoryTree == NULL )
-               return file;
-       string generatedFilesDirectory = backend->AddDirectoryTarget ( directory,
-                                                                      directoryTree );
-       if ( directory.find ( generatedFilesDirectory ) != string::npos )
-               /* This path already includes the generated files directory variable */
-               return file;
-       else
-       {
-               if ( file == "" )
-                       return generatedFilesDirectory;
-               return generatedFilesDirectory + sSep + file;
+               case SourceDirectory:
+                       break;
+               case IntermediateDirectory:
+                       backend->AddDirectoryTarget ( file->relative_path, backend->intermediateDirectory );
+                       break;
+               case OutputDirectory:
+                       backend->AddDirectoryTarget ( file->relative_path, backend->outputDirectory );
+                       break;
+               case InstallDirectory:
+                       backend->AddDirectoryTarget ( file->relative_path, backend->installDirectory );
+                       break;
+               default:
+                       throw InvalidOperationException ( __FILE__,
+                                                         __LINE__,
+                                                         "Invalid directory %d.",
+                                                         file->directory );
        }
-}
-
-/*static*/ string
-MingwModuleHandler::PassThruCacheDirectory (const FileLocation* fileLocation )
-{
-       return PassThruCacheDirectory ( fileLocation->filename,
-                                       fileLocation->directory );
-}
 
-/*static*/ Directory*
-MingwModuleHandler::GetTargetDirectoryTree (
-       const Module& module )
-{
-       if ( module.type == StaticLibrary )
-               return backend->intermediateDirectory;
-       return backend->outputDirectory;
+       return file;
 }
 
-/*static*/ string
+/* caller needs to delete the returned object */
+const FileLocation*
 MingwModuleHandler::GetTargetFilename (
        const Module& module,
        string_list* pclean_files )
 {
-       string target = PassThruCacheDirectory (
-               NormalizeFilename ( module.GetPath () ),
-               GetTargetDirectoryTree ( module ) );
+       FileLocation *target = new FileLocation ( *module.output );
        if ( pclean_files )
        {
                string_list& clean_files = *pclean_files;
-               CLEAN_FILE ( target );
+               CLEAN_FILE ( *target );
        }
        return target;
 }
 
-/*static*/ string
+/* caller needs to delete the returned object */
+const FileLocation*
 MingwModuleHandler::GetImportLibraryFilename (
        const Module& module,
        string_list* pclean_files )
 {
-       string target = PassThruCacheDirectory (
-               NormalizeFilename ( module.GetDependencyPath () ),
-               backend->intermediateDirectory );
+       FileLocation *target = new FileLocation ( *module.dependency );
        if ( pclean_files )
        {
                string_list& clean_files = *pclean_files;
-               CLEAN_FILE ( target );
+               CLEAN_FILE ( *target );
        }
        return target;
 }
 
-/*static*/ MingwModuleHandler*
+/* caller needs to delete the returned object */
+MingwModuleHandler*
 MingwModuleHandler::InstanciateHandler (
        const Module& module,
        MingwBackend* backend )
@@ -197,6 +171,9 @@ MingwModuleHandler::InstanciateHandler (
                case StaticLibrary:
                        handler = new MingwStaticLibraryModuleHandler ( module );
                        break;
+               case HostStaticLibrary:
+                       handler = new MingwHostStaticLibraryModuleHandler ( module );
+                       break;
                case ObjectLibrary:
                        handler = new MingwObjectLibraryModuleHandler ( module );
                        break;
@@ -222,11 +199,10 @@ MingwModuleHandler::InstanciateHandler (
                case Win32DLL:
                        handler = new MingwWin32DLLModuleHandler ( module );
                        break;
-               case Win32OCX: 
+               case Win32OCX:
                        handler = new MingwWin32OCXModuleHandler ( module );
                        break;
                case KernelModeDriver:
-        case ExportDriver: // maybe change this later
                        handler = new MingwKernelModeDriverModuleHandler ( module );
                        break;
                case BootLoader:
@@ -259,14 +235,23 @@ MingwModuleHandler::InstanciateHandler (
                case RpcClient:
                        handler = new MingwRpcClientModuleHandler ( module );
                        break;
+               case RpcProxy:
+                       handler = new MingwRpcProxyModuleHandler ( module );
+                       break;
                case Alias:
                        handler = new MingwAliasModuleHandler ( module );
                        break;
                case IdlHeader:
                        handler = new MingwIdlHeaderModuleHandler ( module );
                        break;
-               case TypeLib:
-                       handler = new MingwTypeLibModuleHandler ( module );
+               case Cabinet:
+                       handler = new MingwCabinetModuleHandler ( module );
+                       break;
+               case EmbeddedTypeLib:
+                       handler = new MingwEmbeddedTypeLibModuleHandler ( module );
+                       break;
+               case ElfExecutable:
+                       handler = new MingwElfExecutableModuleHandler ( module );
                        break;
                default:
                        throw UnknownModuleTypeException (
@@ -292,67 +277,71 @@ MingwModuleHandler::GetBasename ( const string& filename ) const
        return "";
 }
 
-FileLocation*
+/* caller needs to delete the returned object */
+const FileLocation*
 MingwModuleHandler::GetActualSourceFilename (
-       const FileLocation* fileLocation ) const
+       const FileLocation* file ) const
 {
-       string filename = fileLocation->filename;
-       string extension = GetExtension ( filename );
+       string filename = file->name;
+
+       string extension = GetExtension ( *file );
        if ( extension == ".spec" || extension == ".SPEC" )
        {
-               string basename = GetBasename ( filename );
-               PassThruCacheDirectory ( NormalizeFilename ( basename + ".stubs.c" ),
-                                        backend->intermediateDirectory );
-               return new FileLocation ( backend->intermediateDirectory, NormalizeFilename ( basename + ".stubs.c" ) );
-       }
-       else if ( extension == ".idl" || extension == ".IDL" )
-       {
-               string basename = GetBasename ( filename );
-               string newname;
-               if ( module.type == RpcServer )
-               {
-                       newname = basename + "_s.c";
-                       PassThruCacheDirectory ( NormalizeFilename ( newname ),
-                                                    backend->intermediateDirectory );
-                       return new FileLocation ( backend->intermediateDirectory, NormalizeFilename ( newname ) );
-               }
-               else if ( module.type == RpcClient )
-               {
-                       newname = basename + "_c.c";
-                       PassThruCacheDirectory ( NormalizeFilename ( newname ),
-                                                    backend->intermediateDirectory );
-                       return new FileLocation ( backend->intermediateDirectory, NormalizeFilename ( newname ) );
-               }
-               else if ( module.type == IdlHeader )
-               {
-                       newname = basename + ".h";
-                       PassThruCacheDirectory ( NormalizeFilename ( newname ),
-                                                    backend->intermediateDirectory );
-                       return new FileLocation ( fileLocation->directory, filename );
-               }
-               else
-               {
-                       return new FileLocation ( fileLocation->directory, filename );
-               }
+               const FileLocation *objectFile = GetObjectFilename ( file, module );
+               FileLocation *sourceFile = new FileLocation (
+                       objectFile->directory,
+                       objectFile->relative_path,
+                       ReplaceExtension ( objectFile->name, ".c" ) );
+               delete objectFile;
+               return sourceFile;
+       }
+       else if ( ( extension == ".idl" || extension == ".IDL" ) &&
+                 ( module.type == RpcServer || module.type == RpcClient || module.type == RpcProxy ) )
+       {
+               const FileLocation *objectFile = GetObjectFilename ( file, module );
+               FileLocation *sourceFile = new FileLocation (
+                       objectFile->directory,
+                       objectFile->relative_path,
+                       ReplaceExtension ( objectFile->name, ".c" ) );
+               delete objectFile;
+               return sourceFile;
+       }
+       else if ( extension == ".mc" || extension == ".MC" )
+       {
+               const FileLocation *objectFile = GetObjectFilename ( file, module );
+               FileLocation *sourceFile = new FileLocation (
+                       objectFile->directory,
+                       objectFile->relative_path,
+                       ReplaceExtension ( objectFile->name, ".rc" ) );
+               delete objectFile;
+               return sourceFile;
        }
        else
-               return new FileLocation ( fileLocation->directory, filename );
+               return new FileLocation ( *file );
 }
 
 string
 MingwModuleHandler::GetExtraDependencies (
-       const string& filename ) const
+       const FileLocation *file ) const
 {
-       string extension = GetExtension ( filename );
+       string extension = GetExtension ( *file );
        if ( extension == ".idl" || extension == ".IDL" )
        {
-               string basename = GetBasename ( filename );
-               if ( (module.type == RpcServer) || (module.type == RpcClient) )
-                       return GetRpcServerHeaderFilename ( basename ) + " " + GetRpcClientHeaderFilename ( basename );
-               else if ( module.type == IdlHeader )
-                       return GetIdlHeaderFilename ( basename );
-               else
+               const FileLocation *header;
+               switch ( module.type )
+               {
+                       case RpcServer: header = GetRpcServerHeaderFilename ( file ); break;
+                       case RpcClient: header = GetRpcClientHeaderFilename ( file ); break;
+                       case RpcProxy: header = GetRpcProxyHeaderFilename ( file ); break;
+                       case IdlHeader: header = GetIdlHeaderFilename ( file ); break;
+                       default: header = NULL; break;
+               }
+               if ( !header )
                        return "";
+
+               string dependencies = backend->GetFullName ( *header );
+               delete header;
+               return " " + dependencies;
        }
        else
                return "";
@@ -362,32 +351,32 @@ string
 MingwModuleHandler::GetCompilationUnitDependencies (
        const CompilationUnit& compilationUnit ) const
 {
-       if ( compilationUnit.files.size () <= 1 )
+       if ( compilationUnit.GetFiles ().size () <= 1 )
                return "";
        vector<string> sourceFiles;
-       for ( size_t i = 0; i < compilationUnit.files.size (); i++ )
+       for ( size_t i = 0; i < compilationUnit.GetFiles ().size (); i++ )
        {
-               File& file = *compilationUnit.files[i];
-               sourceFiles.push_back ( NormalizeFilename ( file.name ) );
+               const File& file = *compilationUnit.GetFiles ()[i];
+               sourceFiles.push_back ( backend->GetFullName ( file.file ) );
        }
-       return v2s ( sourceFiles, 10 );
+       return string ( " " ) + v2s ( sourceFiles, 10 );
 }
 
-string
+/* caller needs to delete the returned object */
+const FileLocation*
 MingwModuleHandler::GetModuleArchiveFilename () const
 {
-       if ( module.type == StaticLibrary )
+       if ( IsStaticLibrary ( module ) )
                return GetTargetFilename ( module, NULL );
-       return PassThruCacheDirectory ( ReplaceExtension (
-               NormalizeFilename ( module.GetPath () ),
-               ".temp.a" ),
-               backend->intermediateDirectory );
+       return new FileLocation ( IntermediateDirectory,
+                                 module.output->relative_path,
+                                 ReplaceExtension ( module.name, ".temp.a" ) );
 }
 
 bool
 MingwModuleHandler::IsGeneratedFile ( const File& file ) const
 {
-       string extension = GetExtension ( file.name );
+       string extension = GetExtension ( file.file );
        return ( extension == ".spec" || extension == ".SPEC" );
 }
 
@@ -401,26 +390,59 @@ MingwModuleHandler::ReferenceObjects (
                return true;
        if ( module.type == RpcClient )
                return true;
+       if ( module.type == RpcProxy )
+               return true;
        if ( module.type == IdlHeader )
                return true;
        return false;
 }
 
+void
+MingwModuleHandler::OutputCopyCommand ( const FileLocation& source,
+                                        const FileLocation& destination )
+{
+       fprintf ( fMakefile,
+                 "\t$(ECHO_CP)\n" );
+       fprintf ( fMakefile,
+                 "\t${cp} %s %s 1>$(NUL)\n",
+                 backend->GetFullName ( source ).c_str (),
+                 backend->GetFullName ( *PassThruCacheDirectory ( &destination ) ).c_str () );
+}
+
 string
 MingwModuleHandler::GetImportLibraryDependency (
        const Module& importedModule )
 {
        string dep;
        if ( ReferenceObjects ( importedModule ) )
+       {
+               const vector<CompilationUnit*>& compilationUnits = importedModule.non_if_data.compilationUnits;
+               size_t i;
+
                dep = GetTargetMacro ( importedModule );
+               for ( i = 0; i < compilationUnits.size (); i++ )
+               {
+                       CompilationUnit& compilationUnit = *compilationUnits[i];
+                       const FileLocation& compilationName = compilationUnit.GetFilename ();
+                       const FileLocation *objectFilename = GetObjectFilename ( &compilationName, importedModule );
+                       if ( GetExtension ( *objectFilename ) == ".h" )
+                               dep += ssprintf ( " $(%s_HEADERS)", importedModule.name.c_str () );
+                       else if ( GetExtension ( *objectFilename ) == ".rc" )
+                               dep += ssprintf ( " $(%s_MCHEADERS)", importedModule.name.c_str () );
+               }
+       }
        else
-               dep = GetImportLibraryFilename ( importedModule, NULL );
+       {
+               const FileLocation *library_target = GetImportLibraryFilename ( importedModule, NULL );
+               dep = backend->GetFullName ( *library_target );
+               delete library_target;
+       }
        return dep;
 }
 
 void
 MingwModuleHandler::GetTargets ( const Module& dependencyModule,
-                                    string_list& targets )
+                                 string_list& targets )
 {
        if ( dependencyModule.invocations.size () > 0 )
        {
@@ -450,11 +472,18 @@ MingwModuleHandler::GetModuleDependencies (
                GetTargets ( dependencyModule,
                             dependencies );
        }
-       GetDefinitionDependencies ( dependencies );
+       vector<FileLocation> v;
+       GetDefinitionDependencies ( v );
+
+       for ( size_t i = 0; i < v.size (); i++ )
+       {
+               const FileLocation& file = v[i];
+               dependencies.push_back ( backend->GetFullName ( file ) );
+       }
 }
 
 void
-MingwModuleHandler::GetSourceFilenames ( string_list& list,
+MingwModuleHandler::GetSourceFilenames ( vector<FileLocation>& list,
                                          bool includeGeneratedFiles ) const
 {
        size_t i;
@@ -464,10 +493,10 @@ MingwModuleHandler::GetSourceFilenames ( string_list& list,
        {
                if ( includeGeneratedFiles || !compilationUnits[i]->IsGeneratedFile () )
                {
-                       FileLocation* sourceFileLocation = GetActualSourceFilename (
-                               compilationUnits[i]->GetFilename ( backend->intermediateDirectory ) );
-                       list.push_back ( PassThruCacheDirectory ( sourceFileLocation->filename,
-                                                                 sourceFileLocation->directory ) );
+                       const FileLocation& compilationName = compilationUnits[i]->GetFilename ();
+                       const FileLocation* sourceFileLocation = GetActualSourceFilename ( &compilationName );
+                       list.push_back ( *sourceFileLocation );
+                       delete sourceFileLocation;
                }
        }
        // intentionally make a copy so that we can append more work in
@@ -487,10 +516,10 @@ MingwModuleHandler::GetSourceFilenames ( string_list& list,
                        CompilationUnit& compilationUnit = *compilationUnits[j];
                        if ( includeGeneratedFiles || !compilationUnit.IsGeneratedFile () )
                        {
-                               FileLocation* sourceFileLocation = GetActualSourceFilename (
-                                       compilationUnit.GetFilename ( backend->intermediateDirectory ) );
-                               list.push_back ( PassThruCacheDirectory ( sourceFileLocation->filename,
-                                                                         sourceFileLocation->directory ) );
+                               const FileLocation& compilationName = compilationUnit.GetFilename ();
+                               const FileLocation* sourceFileLocation = GetActualSourceFilename ( &compilationName );
+                               list.push_back ( *sourceFileLocation );
+                               delete sourceFileLocation;
                        }
                }
        }
@@ -498,22 +527,27 @@ MingwModuleHandler::GetSourceFilenames ( string_list& list,
 
 void
 MingwModuleHandler::GetSourceFilenamesWithoutGeneratedFiles (
-       string_list& list ) const
+       vector<FileLocation>& list ) const
 {
        GetSourceFilenames ( list, false );
 }
 
-string
+/* caller needs to delete the returned object */
+const FileLocation*
 MingwModuleHandler::GetObjectFilename (
-       const FileLocation* sourceFileLocation,
-       string_list* pclean_files ) const
+       const FileLocation* sourceFile,
+       const Module& module ) const
 {
-       string sourceFilename = sourceFileLocation->filename;
-       Directory* directoryTree;
+       DirectoryLocation destination_directory;
        string newExtension;
-       string extension = GetExtension ( sourceFilename );
-       if ( extension == ".rc" || extension == ".RC" )
-               newExtension = ".coff";
+       string extension = GetExtension ( *sourceFile );
+
+       if ( module.type == BootSector )
+               return new FileLocation ( *module.output );
+       else if ( extension == ".rc" || extension == ".RC" )
+               newExtension = "_" + module.name + ".coff";
+       else if ( extension == ".mc" || extension == ".MC" )
+               newExtension = ".rc";
        else if ( extension == ".spec" || extension == ".SPEC" )
                newExtension = ".stubs.o";
        else if ( extension == ".idl" || extension == ".IDL" )
@@ -522,28 +556,25 @@ MingwModuleHandler::GetObjectFilename (
                        newExtension = "_s.o";
                else if ( module.type == RpcClient )
                        newExtension = "_c.o";
+               else if ( module.type == RpcProxy )
+                       newExtension = "_p.o";
                else
                        newExtension = ".h";
        }
        else
-               newExtension = ".o";
+               newExtension = "_" + module.name + ".o";
 
        if ( module.type == BootSector )
-               directoryTree = backend->outputDirectory;
+               destination_directory = OutputDirectory;
        else
-               directoryTree = backend->intermediateDirectory;
+               destination_directory = IntermediateDirectory;
 
-       string obj_file = PassThruCacheDirectory (
-               NormalizeFilename ( ReplaceExtension (
-                       RemoveVariables ( sourceFilename ),
-                                                         newExtension ) ),
-                       directoryTree );
+       const FileLocation *obj_file = new FileLocation(
+               destination_directory,
+               sourceFile->relative_path,
+               ReplaceExtension ( sourceFile->name, newExtension ) );
+       PassThruCacheDirectory ( obj_file );
 
-       if ( pclean_files )
-       {
-               string_list& clean_files = *pclean_files;
-               CLEAN_FILE ( obj_file );
-       }
        return obj_file;
 }
 
@@ -581,27 +612,41 @@ MingwModuleHandler::GenerateCleanTarget () const
                  v2s ( referencedModuleNames, 10 ).c_str () );
        for ( size_t i = 0; i < clean_files.size(); i++ )
        {
-               if ( 9==((i+1)%10) )
+               if ( ( i + 1 ) % 10 == 9 )
                        fprintf ( fMakefile, " 2>$(NUL)\n\t-@${rm}" );
                fprintf ( fMakefile, " %s", clean_files[i].c_str() );
        }
        fprintf ( fMakefile, " 2>$(NUL)\n" );
+
+       if( ProxyMakefile::GenerateProxyMakefile(module) )
+       {
+               DirectoryLocation root;
+
+               if ( backend->configuration.GenerateProxyMakefilesInSourceTree )
+                       root = SourceDirectory;
+               else
+                       root = OutputDirectory;
+
+               FileLocation proxyMakefile ( root,
+                                            module.output->relative_path,
+                                           "GNUmakefile" );
+               fprintf ( fMakefile, "\t-@${rm} %s 2>$(NUL)\n",
+                         backend->GetFullName ( proxyMakefile ).c_str () );
+       }
+
        fprintf ( fMakefile, "clean: %s_clean\n\n", module.name.c_str() );
 }
 
 void
 MingwModuleHandler::GenerateInstallTarget () const
 {
-       if ( module.installName.length () == 0 )
+       if ( !module.install )
                return;
        fprintf ( fMakefile, ".PHONY: %s_install\n", module.name.c_str() );
-       string normalizedTargetFilename = MingwModuleHandler::PassThruCacheDirectory (
-               NormalizeFilename ( module.installBase + sSep + module.installName ),
-               backend->installDirectory );
        fprintf ( fMakefile,
                  "%s_install: %s\n",
                  module.name.c_str (),
-                 normalizedTargetFilename.c_str() );
+                 backend->GetFullName ( *module.install ).c_str () );
 }
 
 void
@@ -616,7 +661,7 @@ MingwModuleHandler::GenerateDependsTarget () const
        fprintf ( fMakefile,
                  "\t$(ECHO_RBUILD)\n" );
        fprintf ( fMakefile,
-                 "\t$(Q)$(RBUILD_TARGET) -dm%s mingw\n",
+                 "\t$(Q)$(RBUILD_TARGET) $(RBUILD_FLAGS) -dm%s mingw\n",
                  module.name.c_str () );
 }
 
@@ -632,21 +677,30 @@ MingwModuleHandler::GetObjectFilenames ()
        {
                if ( objectFilenames.size () > 0 )
                        objectFilenames += " ";
-               objectFilenames += GetObjectFilename ( compilationUnits[i]->GetFilename ( backend->intermediateDirectory ), NULL );
+               const FileLocation& compilationName = compilationUnits[i]->GetFilename ();
+               const FileLocation *object_file = GetObjectFilename ( &compilationName, module );
+               objectFilenames += backend->GetFullName ( *object_file );
+               delete object_file;
        }
        return objectFilenames;
 }
 
 /* static */ string
 MingwModuleHandler::GenerateGccDefineParametersFromVector (
-       const vector<Define*>& defines )
+       const vector<Define*>& defines,
+       set<string>& used_defs)
 {
        string parameters;
+
        for ( size_t i = 0; i < defines.size (); i++ )
        {
                Define& define = *defines[i];
+               if (used_defs.find(define.name) != used_defs.end())
+                       continue;
                if (parameters.length () > 0)
                        parameters += " ";
+               if (define.name.find('(') != string::npos)
+                       parameters += "$(QT)";
                parameters += "-D";
                parameters += define.name;
                if (define.value.length () > 0)
@@ -654,6 +708,9 @@ MingwModuleHandler::GenerateGccDefineParametersFromVector (
                        parameters += "=";
                        parameters += define.value;
                }
+               if (define.name.find('(') != string::npos)
+                       parameters += "$(QT)";
+               used_defs.insert(used_defs.begin(),define.name);
        }
        return parameters;
 }
@@ -661,8 +718,9 @@ MingwModuleHandler::GenerateGccDefineParametersFromVector (
 string
 MingwModuleHandler::GenerateGccDefineParameters () const
 {
-       string parameters = GenerateGccDefineParametersFromVector ( module.project.non_if_data.defines );
-       string s = GenerateGccDefineParametersFromVector ( module.non_if_data.defines );
+       set<string> used_defs;
+       string parameters = GenerateGccDefineParametersFromVector ( module.project.non_if_data.defines, used_defs );
+       string s = GenerateGccDefineParametersFromVector ( module.non_if_data.defines, used_defs );
        if ( s.length () > 0 )
        {
                parameters += " ";
@@ -693,14 +751,7 @@ MingwModuleHandler::GenerateGccIncludeParametersFromVector ( const vector<Includ
                Include& include = *includes[i];
                if ( parameters.length () > 0 )
                        parameters += " ";
-               if ( include.root == "intermediate" )
-                       path_prefix = backend->intermediateDirectory->name + cSep;
-               else if (include.root == "output" )
-                       path_prefix = backend->outputDirectory->name + cSep;
-               else
-                       path_prefix = "";
-
-               parameters += "-I" + path_prefix + include.directory;
+               parameters += "-I" + backend->GetFullPath ( *include.directory );;
        }
        return parameters;
 }
@@ -719,15 +770,14 @@ MingwModuleHandler::GenerateGccIncludeParameters () const
 }
 
 string
-MingwModuleHandler::GenerateCompilerParametersFromVector ( const vector<CompilerFlag*>& compilerFlags ) const
+MingwModuleHandler::GenerateCompilerParametersFromVector ( const vector<CompilerFlag*>& compilerFlags, const CompilerType type ) const
 {
        string parameters;
        for ( size_t i = 0; i < compilerFlags.size (); i++ )
        {
                CompilerFlag& compilerFlag = *compilerFlags[i];
-               if ( parameters.length () > 0 )
-                       parameters += " ";
-               parameters += compilerFlag.flag;
+               if ( compilerFlag.compiler == type )
+                       parameters += " " + compilerFlag.flag;
        }
        return parameters;
 }
@@ -773,12 +823,17 @@ void
 MingwModuleHandler::GenerateMacro (
        const char* assignmentOperation,
        const string& macro,
-       const IfableData& data )
+       const IfableData& data,
+       set<const Define *> *used_defs,
+       bool generatingCompilerMacro )
 {
        size_t i;
        bool generateAssignment;
 
-       generateAssignment = (use_pch && module.pch != NULL ) || data.includes.size () > 0 || data.defines.size () > 0 || data.compilerFlags.size () > 0;
+       if ( generatingCompilerMacro )
+               generateAssignment = (use_pch && module.pch != NULL ) || data.includes.size () > 0 || data.defines.size () > 0 || data.compilerFlags.size () > 0;
+       else
+               generateAssignment = (use_pch && module.pch != NULL ) || data.includes.size () > 0 || data.defines.size () > 0;
        if ( generateAssignment )
        {
                fprintf ( fMakefile,
@@ -787,60 +842,75 @@ MingwModuleHandler::GenerateMacro (
                          assignmentOperation );
        }
 
-       if ( use_pch && module.pch != NULL )
+       const FileLocation *pchFilename = GetPrecompiledHeaderFilename ();
+       if ( pchFilename )
        {
                fprintf ( fMakefile,
                          " -I%s",
-                         GetDirectory ( GetPrecompiledHeaderFilename () ).c_str () );
+                         backend->GetFullPath ( *pchFilename ).c_str () );
+               delete pchFilename;
        }
 
-       string compilerParameters = GenerateCompilerParametersFromVector ( data.compilerFlags );
-       if ( compilerParameters.size () > 0 )
+       if ( generatingCompilerMacro )
        {
-               fprintf (
-                       fMakefile,
-                       " %s",
-                       compilerParameters.c_str () );
+               string compilerParameters = GenerateCompilerParametersFromVector ( data.compilerFlags, CompilerTypeDontCare );
+               if ( compilerParameters.size () > 0 )
+               {
+                       fprintf (
+                               fMakefile,
+                               "%s",
+                               compilerParameters.c_str () );
+               }
        }
-
        for ( i = 0; i < data.includes.size(); i++ )
        {
                const Include& include = *data.includes[i];
-               string includeDirectory, path_prefix;
-               if ( include.baseModule != NULL &&
-                    ( include.baseModule->type == RpcServer ||
-                      include.baseModule->type == RpcClient ||
-                      include.baseModule->type == IdlHeader) )
-                       includeDirectory = PassThruCacheDirectory ( NormalizeFilename ( include.directory ),
-                                                                   backend->intermediateDirectory );
-               else
-                       includeDirectory = include.directory;
-
-               if ( include.root == "intermediate" )
-                       path_prefix = backend->intermediateDirectory->name + cSep;
-               else if (include.root == "output" )
-                       path_prefix = backend->outputDirectory->name + cSep;
-               else
-                       path_prefix = "";
-
+               const FileLocation* includeDirectory = include.directory;
                fprintf (
                        fMakefile,
-                       " -I%s%s",
-                       path_prefix.c_str(),
-                       includeDirectory.c_str() );
+                       " -I%s",
+                       backend->GetFullPath ( *includeDirectory ).c_str() );
        }
        for ( i = 0; i < data.defines.size(); i++ )
        {
-               Define& d = *data.defines[i];
+               const Define& define = *data.defines[i];
+               if ( used_defs )
+               {
+                       set<const Define *>::const_iterator last_define;
+                       for (last_define = used_defs->begin ();
+                            last_define != used_defs->end ();
+                            last_define++)
+                       {
+                               if ( (*last_define)->name != define.name )
+                                       continue;
+                               if ( !define.overridable )
+                               {
+                                       throw InvalidOperationException ( (*last_define)->node->location.c_str (),
+                                                                         0,
+                                                                         "Invalid override of define '%s', already defined at %s",
+                                                                         define.name.c_str (),
+                                                                         define.node->location.c_str () );
+                               }
+                               if ( backend->configuration.Verbose )
+                                       printf("%s: Overriding '%s' already defined at %s\n",
+                                               (*last_define)->node->location.c_str (), define.name.c_str (),
+                                               define.node->location.c_str () );
+                               break;
+                       }
+                       if ( last_define != used_defs->end () )
+                               continue;
+               }
                fprintf (
                        fMakefile,
                        " -D%s",
-                       d.name.c_str() );
-               if ( d.value.size() )
+                       define.name.c_str() );
+               if (define.value.length () > 0)
                        fprintf (
                                fMakefile,
                                "=%s",
-                               d.value.c_str() );
+                               define.value.c_str() );
+               if ( used_defs )
+                       used_defs->insert( used_defs->begin (), &define );
        }
        if ( generateAssignment )
        {
@@ -852,16 +922,21 @@ void
 MingwModuleHandler::GenerateMacros (
        const char* assignmentOperation,
        const IfableData& data,
-       const vector<LinkerFlag*>* linkerFlags )
+       const vector<LinkerFlag*>* linkerFlags,
+       set<const Define *>& used_defs )
 {
        size_t i;
 
        GenerateMacro ( assignmentOperation,
                        cflagsMacro,
-                       data );
+                       data,
+                       &used_defs,
+                       true );
        GenerateMacro ( assignmentOperation,
                        windresflagsMacro,
-                       data );
+                       data,
+                       NULL,
+                       false );
 
        if ( linkerFlags != NULL )
        {
@@ -911,7 +986,8 @@ MingwModuleHandler::GenerateMacros (
                        GenerateMacros (
                                "+=",
                                rIf.data,
-                               NULL );
+                               NULL,
+                               used_defs );
                        fprintf (
                                fMakefile,
                                "endif\n\n" );
@@ -922,7 +998,7 @@ MingwModuleHandler::GenerateMacros (
 void
 MingwModuleHandler::CleanupCompilationUnitVector ( vector<CompilationUnit*>& compilationUnits )
 {
-       for (size_t i = 0; i < compilationUnits.size (); i++)
+       for ( size_t i = 0; i < compilationUnits.size (); i++ )
                delete compilationUnits[i];
 }
 
@@ -931,15 +1007,86 @@ MingwModuleHandler::GetModuleSpecificCompilationUnits ( vector<CompilationUnit*>
 {
 }
 
+void
+MingwModuleHandler::GenerateSourceMacros (
+       const char* assignmentOperation,
+       const IfableData& data )
+{
+       size_t i;
+
+       const vector<CompilationUnit*>& compilationUnits = data.compilationUnits;
+       vector<const FileLocation *> headers;
+       if ( compilationUnits.size () > 0 )
+       {
+               fprintf (
+                       fMakefile,
+                       "%s %s",
+                       sourcesMacro.c_str (),
+                       assignmentOperation );
+               for ( i = 0; i < compilationUnits.size(); i++ )
+               {
+                       CompilationUnit& compilationUnit = *compilationUnits[i];
+                       const FileLocation& compilationName = compilationUnit.GetFilename ();
+                       fprintf (
+                               fMakefile,
+                               "%s%s",
+                               ( i%10 == 9 ? " \\\n\t" : " " ),
+                               backend->GetFullName ( compilationName ).c_str () );
+               }
+               fprintf ( fMakefile, "\n" );
+       }
+
+       const vector<If*>& ifs = data.ifs;
+       for ( i = 0; i < ifs.size(); i++ )
+       {
+               If& rIf = *ifs[i];
+               if ( rIf.data.defines.size()
+                       || rIf.data.includes.size()
+                       || rIf.data.libraries.size()
+                       || rIf.data.compilationUnits.size()
+                       || rIf.data.compilerFlags.size()
+                       || rIf.data.ifs.size() )
+               {
+                       fprintf (
+                               fMakefile,
+                               "%s (\"$(%s)\",\"%s\")\n",
+                               rIf.negated ? "ifneq" : "ifeq",
+                               rIf.property.c_str(),
+                               rIf.value.c_str() );
+                       GenerateSourceMacros (
+                               "+=",
+                               rIf.data );
+                       fprintf (
+                               fMakefile,
+                               "endif\n\n" );
+               }
+       }
+
+       vector<CompilationUnit*> sourceCompilationUnits;
+       GetModuleSpecificCompilationUnits ( sourceCompilationUnits );
+       for ( i = 0; i < sourceCompilationUnits.size (); i++ )
+       {
+               const FileLocation& compilationName = sourceCompilationUnits[i]->GetFilename ();
+               fprintf (
+                       fMakefile,
+                       "%s += %s\n",
+                       sourcesMacro.c_str(),
+                       backend->GetFullName ( compilationName ).c_str () );
+       }
+       CleanupCompilationUnitVector ( sourceCompilationUnits );
+}
+
 void
 MingwModuleHandler::GenerateObjectMacros (
        const char* assignmentOperation,
-       const IfableData& data,
-       const vector<LinkerFlag*>* linkerFlags )
+       const IfableData& data )
 {
        size_t i;
 
        const vector<CompilationUnit*>& compilationUnits = data.compilationUnits;
+       vector<const FileLocation *> headers;
+       vector<const FileLocation *> mcheaders;
+       vector<const FileLocation *> mcresources;
        if ( compilationUnits.size () > 0 )
        {
                for ( i = 0; i < compilationUnits.size (); i++ )
@@ -947,11 +1094,14 @@ MingwModuleHandler::GenerateObjectMacros (
                        CompilationUnit& compilationUnit = *compilationUnits[i];
                        if ( compilationUnit.IsFirstFile () )
                        {
+                               const FileLocation& compilationName = compilationUnit.GetFilename ();
+                               const FileLocation *object_file = GetObjectFilename ( &compilationName, module );
                                fprintf ( fMakefile,
                                        "%s := %s $(%s)\n",
                                        objectsMacro.c_str(),
-                                       GetObjectFilename ( compilationUnit.GetFilename ( backend->intermediateDirectory ), NULL ).c_str (),
+                                       backend->GetFullName ( *object_file ).c_str (),
                                        objectsMacro.c_str() );
+                               delete object_file;
                        }
                }
                fprintf (
@@ -964,15 +1114,85 @@ MingwModuleHandler::GenerateObjectMacros (
                        CompilationUnit& compilationUnit = *compilationUnits[i];
                        if ( !compilationUnit.IsFirstFile () )
                        {
-                               fprintf (
-                                       fMakefile,
-                                       "%s%s",
-                                       ( i%10 == 9 ? " \\\n\t" : " " ),
-                                       GetObjectFilename ( compilationUnit.GetFilename ( backend->intermediateDirectory ), NULL ).c_str () );
+                               const FileLocation& compilationName = compilationUnit.GetFilename ();
+                               const FileLocation *objectFilename = GetObjectFilename ( &compilationName, module );
+                               if ( GetExtension ( *objectFilename ) == ".h" )
+                                       headers.push_back ( objectFilename );
+                               else if ( GetExtension ( *objectFilename ) == ".rc" )
+                               {
+                                       const FileLocation *headerFilename = GetMcHeaderFilename ( &compilationUnit.GetFilename () );
+                                       mcheaders.push_back ( headerFilename );
+                                       mcresources.push_back ( objectFilename );
+                               }
+                               else
+                               {
+                                       fprintf (
+                                               fMakefile,
+                                               "%s%s",
+                                               ( i%10 == 9 ? " \\\n\t" : " " ),
+                                               backend->GetFullName ( *objectFilename ).c_str () );
+                                       delete objectFilename;
+                               }
                        }
                }
                fprintf ( fMakefile, "\n" );
        }
+       if ( headers.size () > 0 )
+       {
+               fprintf (
+                       fMakefile,
+                       "%s_HEADERS %s",
+                       module.name.c_str (),
+                       assignmentOperation );
+               for ( i = 0; i < headers.size (); i++ )
+               {
+                       fprintf (
+                               fMakefile,
+                               "%s%s",
+                               ( i%10 == 9 ? " \\\n\t" : " " ),
+                               backend->GetFullName ( *headers[i] ).c_str () );
+                       delete headers[i];
+               }
+               fprintf ( fMakefile, "\n" );
+       }
+
+       if ( mcheaders.size () > 0 )
+       {
+               fprintf (
+                       fMakefile,
+                       "%s_MCHEADERS %s",
+                       module.name.c_str (),
+                       assignmentOperation );
+               for ( i = 0; i < mcheaders.size (); i++ )
+               {
+                       fprintf (
+                               fMakefile,
+                               "%s%s",
+                               ( i%10 == 9 ? " \\\n\t" : " " ),
+                               backend->GetFullName ( *mcheaders[i] ).c_str () );
+                       delete mcheaders[i];
+               }
+               fprintf ( fMakefile, "\n" );
+       }
+
+       if ( mcresources.size () > 0 )
+       {
+               fprintf (
+                       fMakefile,
+                       "%s_RESOURCES %s",
+                       module.name.c_str (),
+                       assignmentOperation );
+               for ( i = 0; i < mcresources.size (); i++ )
+               {
+                       fprintf (
+                               fMakefile,
+                               "%s%s",
+                               ( i%10 == 9 ? " \\\n\t" : " " ),
+                               backend->GetFullName ( *mcresources[i] ).c_str () );
+                       delete mcresources[i];
+               }
+               fprintf ( fMakefile, "\n" );
+       }
 
        const vector<If*>& ifs = data.ifs;
        for ( i = 0; i < ifs.size(); i++ )
@@ -993,8 +1213,7 @@ MingwModuleHandler::GenerateObjectMacros (
                                rIf.value.c_str() );
                        GenerateObjectMacros (
                                "+=",
-                               rIf.data,
-                               NULL );
+                               rIf.data );
                        fprintf (
                                fMakefile,
                                "endif\n\n" );
@@ -1005,472 +1224,317 @@ MingwModuleHandler::GenerateObjectMacros (
        GetModuleSpecificCompilationUnits ( sourceCompilationUnits );
        for ( i = 0; i < sourceCompilationUnits.size (); i++ )
        {
+               const FileLocation& compilationName = sourceCompilationUnits[i]->GetFilename ();
+               const FileLocation *object_file = GetObjectFilename ( &compilationName, module );
                fprintf (
                        fMakefile,
                        "%s += %s\n",
                        objectsMacro.c_str(),
-                       GetObjectFilename ( sourceCompilationUnits[i]->GetFilename ( backend->intermediateDirectory ), NULL ).c_str () );
+                       backend->GetFullName ( *object_file ).c_str () );
+               delete object_file;
        }
        CleanupCompilationUnitVector ( sourceCompilationUnits );
 }
 
-string
+/* caller needs to delete the returned object */
+const FileLocation*
 MingwModuleHandler::GetPrecompiledHeaderFilename () const
 {
-       const string& basePchFilename = module.pch->file.name + ".gch";
-       return PassThruCacheDirectory ( NormalizeFilename ( basePchFilename ),
-                                       backend->intermediateDirectory );
-}
+       if ( !module.pch || !use_pch )
+               return NULL;
+       return new FileLocation ( IntermediateDirectory,
+                                 module.pch->file->relative_path,
+                                 ReplaceExtension ( module.pch->file->name, "_" + module.name + ".gch" ) );
+}
+
+Rule arRule1 ( "$(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)$(source_name_noext).a: $($(module_name)_OBJS) | $(INTERMEDIATE)$(SEP)$(source_dir)\n",
+               "$(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)$(source_name_noext).a",
+               "$(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)", NULL );
+Rule arRule2 ( "\t$(ECHO_AR)\n"
+              "\t${ar} -rc $@ $($(module_name)_OBJS)\n",
+              NULL );
+Rule arHostRule2 ( "\t$(ECHO_AR)\n"
+                   "\t${host_ar} -rc $@ $($(module_name)_OBJS)\n",
+                   NULL );
+Rule gasRule ( "$(source): ${$(module_name)_precondition}\n"
+               "$(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)$(source_name_noext)_$(module_name).o: $(source)$(dependencies) | $(INTERMEDIATE)$(SEP)$(source_dir)\n"
+               "\t$(ECHO_GAS)\n"
+               "\t${gcc} -x assembler-with-cpp -c $< -o $@ -D__ASM__ $($(module_name)_CFLAGS)\n",
+               "$(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)$(source_name_noext)_$(module_name).o",
+               "$(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)", NULL );
+Rule bootRule ( "$(source): ${$(module_name)_precondition}\n"
+                "$(module_output): $(source)$(dependencies) | $(OUTPUT)$(SEP)$(source_dir)\n"
+                "\t$(ECHO_NASM)\n"
+                "\t$(Q)${nasm} -f win32 $< -o $@ $($(module_name)_NASMFLAGS)\n",
+                "$(OUTPUT)$(SEP)$(source_dir)$(SEP)", NULL );
+Rule nasmRule ( "$(source): ${$(module_name)_precondition}\n"
+                "$(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)$(source_name_noext)_$(module_name).o: $(source)$(dependencies) | $(INTERMEDIATE)$(SEP)$(source_dir)\n"
+                "\t$(ECHO_NASM)\n"
+                "\t$(Q)${nasm} -f win32 $< -o $@ $($(module_name)_NASMFLAGS)\n",
+                "$(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)$(source_name_noext)_$(module_name).o",
+                "$(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)", NULL );
+Rule windresRule ( "$(source): ${$(module_name)_precondition}\n"
+                   "$(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)$(source_name_noext)_$(module_name).coff: $(source)$(dependencies) $(WRC_TARGET) | $(INTERMEDIATE)$(SEP)$(source_dir) $(TEMPORARY)\n"
+                   "\t$(ECHO_WRC)\n"
+                   "\t${gcc} -xc -E -DRC_INVOKED ${$(module_name)_RCFLAGS} $(source) > $(TEMPORARY)$(SEP)$(module_name).$(source_name_noext).rci.tmp\n"
+                   "\t$(Q)$(WRC_TARGET) ${$(module_name)_RCFLAGS} $(TEMPORARY)$(SEP)$(module_name).$(source_name_noext).rci.tmp $(TEMPORARY)$(SEP)$(module_name).$(source_name_noext).res.tmp\n"
+                   "\t-@${rm} $(TEMPORARY)$(SEP)$(module_name).$(source_name_noext).rci.tmp 2>$(NUL)\n"
+                   "\t${windres} $(TEMPORARY)$(SEP)$(module_name).$(source_name_noext).res.tmp -o $@\n"
+                   "\t-@${rm} $(TEMPORARY)$(SEP)$(module_name).$(source_name_noext).res.tmp 2>$(NUL)\n",
+                   "$(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)$(source_name_noext)_$(module_name).coff",
+                   "$(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)", NULL );
+Rule wmcRule ( "$(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)$(source_name_noext).rc $(INTERMEDIATE)$(SEP)include$(SEP)reactos$(SEP)$(source_name_noext).h: $(WMC_TARGET) $(source)\n"
+               "\t$(ECHO_WMC)\n"
+               "\t$(Q)$(WMC_TARGET) -i -H $(INTERMEDIATE)$(SEP)include$(SEP)reactos$(SEP)$(source_name_noext).h -o $(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)$(source_name_noext).rc $(source)\n",
+               "$(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)$(source_name_noext).rc", "$(INTERMEDIATE)$(SEP)include$(SEP)reactos$(SEP)$(source_name_noext).h", NULL );
+Rule winebuildRule ( "$(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)$(source_name_noext).spec.def: $(source)$(dependencies) $(WINEBUILD_TARGET) | $(INTERMEDIATE)$(SEP)$(source_dir)\n"
+                     "\t$(ECHO_WINEBLD)\n"
+                     "\t$(Q)$(WINEBUILD_TARGET) $(WINEBUILD_FLAGS) -o $(INTERMEDIATE)$(SEP)$(source_path)$(SEP)$(source_name_noext).spec.def --def -E $(source)\n"
+                     "$(INTERMEDIATE)$(SEP)$(source_path)$(SEP)$(source_name_noext).stubs.c: $(source_path)$(SEP)$(source_name_noext).spec $(WINEBUILD_TARGET)\n"
+                     "\t$(ECHO_WINEBLD)\n"
+                     "\t$(Q)$(WINEBUILD_TARGET) $(WINEBUILD_FLAGS) -o $(INTERMEDIATE)$(SEP)$(source_path)$(SEP)$(source_name_noext).stubs.c --pedll $(source_path)$(SEP)$(source_name_noext).spec\n"
+                     "$(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)$(source_name_noext).stubs.o: $(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)$(source_name_noext).stubs.c$(dependencies) | $(INTERMEDIATE)$(SEP)$(source_dir)\n"
+                     "\t$(ECHO_CC)\n"
+                     "\t${gcc} -c $< -o $@ $($(module_name)_CFLAGS)$(compiler_flags)\n",
+                     "$(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)$(source_name_noext).spec.def",
+                     "$(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)$(source_name_noext).stubs.c",
+                     "$(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)$(source_name_noext).stubs.o",
+                     "$(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)", NULL );
+Rule widlHeaderRule ( "$(source): ${$(module_name)_precondition}\n"
+                      "$(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)$(source_name_noext).h: $(source)$(dependencies) $(WIDL_TARGET) | $(INTERMEDIATE)$(SEP)$(source_dir)\n"
+                      "\t$(ECHO_WIDL)\n"
+                      "\t$(Q)$(WIDL_TARGET) $($(module_name)_WIDLFLAGS) -h -H $(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)$(source_name_noext).h $(source)\n",
+                      "$(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)$(source_name_noext).h",
+                      "$(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)", NULL );
+Rule widlServerRule ( "$(source): ${$(module_name)_precondition}\n"
+                      "$(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)$(source_name_noext)_s.c $(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)$(source_name_noext)_s.h: $(source)$(dependencies) $(WIDL_TARGET) | $(INTERMEDIATE)$(SEP)$(source_dir)\n"
+                      "\t$(ECHO_WIDL)\n"
+                      "\t$(Q)$(WIDL_TARGET) $($(module_name)_WIDLFLAGS) -h -H $(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)$(source_name_noext)_s.h -s -S $(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)$(source_name_noext)_s.c $(source)\n"
+                      "$(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)$(source_name_noext)_s.o: $(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)$(source_name_noext)_s.c $(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)$(source_name_noext)_s.h$(dependencies) | $(INTERMEDIATE)$(SEP)$(source_dir)\n"
+                      "\t$(ECHO_CC)\n"
+                      "\t${gcc} -c $< -o $@ $($(module_name)_CFLAGS)$(compiler_flags)\n",
+                      "$(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)$(source_name_noext)_s.h",
+                      "$(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)$(source_name_noext)_s.c",
+                      "$(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)$(source_name_noext)_s.o",
+                      "$(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)", NULL );
+Rule widlClientRule ( "$(source): ${$(module_name)_precondition}\n"
+                      "$(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)$(source_name_noext)_c.c $(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)$(source_name_noext)_c.h: $(source)$(dependencies) $(WIDL_TARGET) | $(INTERMEDIATE)$(SEP)$(source_dir)\n"
+                      "\t$(ECHO_WIDL)\n"
+                      "\t$(Q)$(WIDL_TARGET) $($(module_name)_WIDLFLAGS) -h -H $(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)$(source_name_noext)_c.h -c -C $(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)$(source_name_noext)_c.c $(source)\n"
+                      "$(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)$(source_name_noext)_c.o: $(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)$(source_name_noext)_c.c $(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)$(source_name_noext)_c.h$(dependencies) | $(INTERMEDIATE)$(SEP)$(source_dir)\n"
+                      "\t$(ECHO_CC)\n"
+                      "\t${gcc} -c $< -o $@ $($(module_name)_CFLAGS)$(compiler_flags)\n",
+                      "$(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)$(source_name_noext)_c.h",
+                      "$(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)$(source_name_noext)_c.c",
+                      "$(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)$(source_name_noext)_c.o",
+                      "$(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)", NULL );
+Rule widlProxyRule ( "$(source): ${$(module_name)_precondition}\n"
+                     "$(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)$(source_name_noext)_p.c $(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)$(source_name_noext)_p.h: $(source)$(dependencies) $(WIDL_TARGET) | $(INTERMEDIATE)$(SEP)$(source_dir)\n"
+                     "\t$(ECHO_WIDL)\n"
+                     "\t$(Q)$(WIDL_TARGET) $($(module_name)_WIDLFLAGS) -h -H $(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)$(source_name_noext)_p.h -p -P $(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)$(source_name_noext)_p.c $(source)\n"
+                     "$(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)$(source_name_noext)_p.o: $(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)$(source_name_noext)_p.c $(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)$(source_name_noext)_p.h$(dependencies) | $(INTERMEDIATE)$(SEP)$(source_dir)\n"
+                      "\t$(ECHO_CC)\n"
+                      "\t${gcc} -c $< -o $@ $($(module_name)_CFLAGS)$(compiler_flags)\n",
+                     "$(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)$(source_name_noext)_p.h",
+                     "$(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)$(source_name_noext)_p.c",
+                     "$(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)$(source_name_noext)_p.o",
+                     "$(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)", NULL );
+Rule widlTlbRule ( "$(source): ${$(module_name)_precondition}\n"
+                   "$(OUTPUT)$(SEP)$(source_dir)$(SEP)$(module_name).tlb: $(source)$(dependencies) $(WIDL_TARGET) | $(INTERMEDIATE)$(SEP)$(source_dir)\n"
+                   "\t$(ECHO_WIDL)\n"
+                   "\t$(Q)$(WIDL_TARGET) $($(module_name)_WIDLFLAGS) -t -T $(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)$(source_name_noext).tlb $(source)\n",
+                   "$(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)", NULL );
+Rule gccRule ( "$(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)$(source_name_noext)_$(module_name).o: $(source) ${$(module_name)_precondition}$(dependencies) | $(INTERMEDIATE)$(SEP)$(source_dir)\n"
+               "\t$(ECHO_CC)\n"
+               "\t${gcc} -c $< -o $@ $($(module_name)_CFLAGS)$(compiler_flags)\n",
+               "$(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)$(source_name_noext)_$(module_name).o", NULL );
+Rule gccHostRule ( "$(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)$(source_name_noext)_$(module_name).o: $(source) ${$(module_name)_precondition}$(dependencies) | $(INTERMEDIATE)$(SEP)$(source_dir)\n"
+                   "\t$(ECHO_CC)\n"
+                   "\t${host_gcc} -c $< -o $@ $($(module_name)_CFLAGS)$(compiler_flags)\n",
+                   "$(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)$(source_name_noext)_$(module_name).o", NULL );
+Rule gppRule ( "$(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)$(source_name_noext)_$(module_name).o: $(source) ${$(module_name)_precondition}$(dependencies) | $(INTERMEDIATE)$(SEP)$(source_dir)\n"
+               "\t$(ECHO_CC)\n"
+               "\t${gpp} -c $< -o $@ $($(module_name)_CFLAGS)$(compiler_flags)\n",
+               "$(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)$(source_name_noext)_$(module_name).o", NULL );
+Rule gppHostRule ( "$(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)$(source_name_noext)_$(module_name).o: $(source) ${$(module_name)_precondition}$(dependencies) | $(INTERMEDIATE)$(SEP)$(source_dir)\n"
+                   "\t$(ECHO_CC)\n"
+                   "\t${host_gpp} -c $< -o $@ $($(module_name)_CFLAGS)$(compiler_flags)\n",
+                   "$(INTERMEDIATE)$(SEP)$(source_dir)$(SEP)$(source_name_noext)_$(module_name).o", NULL );
+Rule emptyRule ( "", NULL );
 
 void
 MingwModuleHandler::GenerateGccCommand (
-       const FileLocation* sourceFileLocation,
-       const string& extraDependencies,
-       const string& cc,
-       const string& cflagsMacro )
-{
-       string sourceFilename = PassThruCacheDirectory ( sourceFileLocation );
-       string dependencies = sourceFilename;
-       if ( extraDependencies != "" )
-               dependencies += " " + extraDependencies;
-       if ( module.pch && use_pch )
-               dependencies += " " + GetPrecompiledHeaderFilename ();
-
-       /* WIDL generated headers may be used */
-       vector<string> rpcDependencies;
-       GetRpcHeaderDependencies ( rpcDependencies );
-       dependencies += " " + v2s ( rpcDependencies, 5 );
-       dependencies += " " + NormalizeFilename ( module.xmlbuildFile );
-
-       string objectFilename = GetObjectFilename (
-               sourceFileLocation, &clean_files );
-       fprintf ( fMakefile,
-                 "%s: %s | %s\n",
-                 objectFilename.c_str (),
-                 dependencies.c_str (),
-                 GetDirectory ( objectFilename ).c_str () );
-       fprintf ( fMakefile, "\t$(ECHO_CC)\n" );
-       fprintf ( fMakefile,
-                "\t%s -c $< -o $@ %s\n",
-                cc.c_str (),
-                cflagsMacro.c_str () );
-}
-
-void
-MingwModuleHandler::GenerateGccAssemblerCommand (
-       const FileLocation* sourceFileLocation,
-       const string& cc,
-       const string& cflagsMacro )
-{
-       string sourceFilename = PassThruCacheDirectory ( sourceFileLocation );
-       string dependencies = sourceFilename;
-       dependencies += " " + NormalizeFilename ( module.xmlbuildFile );
-       string objectFilename = GetObjectFilename (
-               sourceFileLocation, &clean_files );
-       fprintf ( fMakefile,
-                 "%s: %s | %s\n",
-                 objectFilename.c_str (),
-                 dependencies.c_str (),
-                 GetDirectory ( objectFilename ).c_str () );
-       fprintf ( fMakefile, "\t$(ECHO_GAS)\n" );
-       fprintf ( fMakefile,
-                 "\t%s -x assembler-with-cpp -c $< -o $@ -D__ASM__ %s\n",
-                 cc.c_str (),
-                 cflagsMacro.c_str () );
-}
-
-void
-MingwModuleHandler::GenerateNasmCommand (
-       const FileLocation* sourceFileLocation,
-       const string& nasmflagsMacro )
-{
-       string sourceFilename = PassThruCacheDirectory ( sourceFileLocation );
-       string dependencies = sourceFilename;
-       dependencies += " " + NormalizeFilename ( module.xmlbuildFile );
-       string objectFilename = GetObjectFilename (
-               sourceFileLocation, &clean_files );
-       fprintf ( fMakefile,
-                 "%s: %s | %s\n",
-                 objectFilename.c_str (),
-                 dependencies.c_str (),
-                 GetDirectory ( objectFilename ).c_str () );
-       fprintf ( fMakefile, "\t$(ECHO_NASM)\n" );
-       fprintf ( fMakefile,
-                 "\t%s -f win32 $< -o $@ %s\n",
-                 "$(Q)${nasm}",
-                 nasmflagsMacro.c_str () );
-}
-
-void
-MingwModuleHandler::GenerateWindresCommand (
-       const FileLocation* sourceFileLocation,
-       const string& windresflagsMacro )
-{
-       string sourceFilename = PassThruCacheDirectory ( sourceFileLocation );
-       string dependencies = sourceFilename;
-       dependencies += " " + NormalizeFilename ( module.xmlbuildFile );
-       string objectFilename = GetObjectFilename ( sourceFileLocation, &clean_files );
-       string sourceFilenamePart = ReplaceExtension ( GetFilename ( sourceFilename ), "" );
-       string rciFilename = ros_temp + module.name + "." + sourceFilenamePart + ".rci.tmp";
-       string resFilename = ros_temp + module.name + "." + sourceFilenamePart + ".res.tmp";
-       if ( module.useWRC )
-       {
-               fprintf ( fMakefile,
-                         "%s: %s $(WRC_TARGET) | %s\n",
-                         objectFilename.c_str (),
-                         dependencies.c_str (),
-                         GetDirectory ( objectFilename ).c_str () );
-               fprintf ( fMakefile, "\t$(ECHO_WRC)\n" );
-               fprintf ( fMakefile,
-                        "\t${gcc} -xc -E -DRC_INVOKED ${%s} %s > %s\n",
-                        windresflagsMacro.c_str (),
-                        sourceFilename.c_str (),
-                        rciFilename.c_str () );
-               fprintf ( fMakefile,
-                        "\t$(Q)$(WRC_TARGET) ${%s} %s %s\n",
-                        windresflagsMacro.c_str (),
-                        rciFilename.c_str (),
-                        resFilename.c_str () );
-               fprintf ( fMakefile,
-                        "\t-@${rm} %s 2>$(NUL)\n",
-                        rciFilename.c_str () );
-               fprintf ( fMakefile,
-                        "\t${windres} %s -o $@\n",
-                        resFilename.c_str () );
-               fprintf ( fMakefile,
-                        "\t-@${rm} %s 2>$(NUL)\n",
-                        resFilename.c_str () );
-       }
+       const FileLocation* sourceFile,
+       const Rule *rule,
+       const string& extraDependencies )
+{
+       const FileLocation *generatedSourceFileName = GetActualSourceFilename ( sourceFile );
+       const FileLocation *pchFilename = GetPrecompiledHeaderFilename ();
+       string dependencies = extraDependencies;
+
+       string flags;
+       string extension = GetExtension ( *sourceFile );
+       if ( extension == ".cc" || extension == ".cpp" || extension == ".cxx" )
+               flags = GenerateCompilerParametersFromVector ( module.non_if_data.compilerFlags, CompilerTypeCPP );
        else
+               flags = GenerateCompilerParametersFromVector ( module.non_if_data.compilerFlags, CompilerTypeCC );
+
+       if ( pchFilename )
        {
-               fprintf ( fMakefile,
-                         "%s: %s $(WRC_TARGET) | %s\n",
-                         objectFilename.c_str (),
-                         dependencies.c_str (),
-                         GetDirectory ( objectFilename ).c_str () );
-               fprintf ( fMakefile, "\t$(ECHO_WRC)\n" );
-               fprintf ( fMakefile,
-                        "\t${windres} $(%s) %s -o $@\n",
-                        windresflagsMacro.c_str (),
-                        sourceFilename.c_str () );
+               dependencies += " " + backend->GetFullName ( *pchFilename );
+               delete pchFilename;
        }
-}
 
-void
-MingwModuleHandler::GenerateWinebuildCommands (
-       const FileLocation* sourceFileLocation )
-{
-       string sourceFilename = PassThruCacheDirectory ( sourceFileLocation );
-       string dependencies = sourceFilename;
-       dependencies += " " + NormalizeFilename ( module.xmlbuildFile );
-
-       string basename = GetBasename ( sourceFilename );
-       string def_file = PassThruCacheDirectory (
-               basename + ".spec.def",
-               backend->intermediateDirectory );
-       CLEAN_FILE(def_file);
+       /* WIDL generated headers may be used */
+       vector<FileLocation> rpcDependencies;
+       GetRpcHeaderDependencies ( rpcDependencies );
+       if ( rpcDependencies.size () > 0 )
+               dependencies += " " + v2s ( backend, rpcDependencies, 5 );
 
-       string stub_file = PassThruCacheDirectory (
-               basename + ".stubs.c",
-               backend->intermediateDirectory );
-       CLEAN_FILE(stub_file)
+       rule->Execute ( fMakefile, backend, module, generatedSourceFileName, clean_files, dependencies, flags );
 
-       fprintf ( fMakefile,
-                 "%s: %s $(WINEBUILD_TARGET) | %s\n",
-                 def_file.c_str (),
-                 dependencies.c_str (),
-                 GetDirectory ( def_file ).c_str () );
-       fprintf ( fMakefile, "\t$(ECHO_WINEBLD)\n" );
-       fprintf ( fMakefile,
-                 "\t%s -o %s --def -E %s\n",
-                 "$(Q)$(WINEBUILD_TARGET)",
-                 def_file.c_str (),
-                 sourceFilename.c_str () );
-       fprintf ( fMakefile,
-                 "%s: %s $(WINEBUILD_TARGET)\n",
-                 stub_file.c_str (),
-                 sourceFilename.c_str () );
-       fprintf ( fMakefile, "\t$(ECHO_WINEBLD)\n" );
-       fprintf ( fMakefile,
-                 "\t%s -o %s --pedll %s\n",
-                 "$(Q)$(WINEBUILD_TARGET)",
-                 stub_file.c_str (),
-                 sourceFilename.c_str () );
+       delete generatedSourceFileName;
 }
 
 string
-MingwModuleHandler::GetWidlFlags ( const CompilationUnit& compilationUnit )
+MingwModuleHandler::GetPropertyValue ( const Module& module, const std::string& name )
 {
-       return compilationUnit.GetSwitches ();
+       for ( size_t i = 0; i < module.project.non_if_data.properties.size (); i++ )
+       {
+               const Property& property = *module.project.non_if_data.properties[i];
+               if ( property.name == name )
+                       return property.value;
+       }
+       return string ( "" );
 }
 
-string
-MingwModuleHandler::GetRpcServerHeaderFilename ( string basename ) const
+/* caller needs to delete the returned object */
+const FileLocation*
+MingwModuleHandler::GetRpcServerHeaderFilename ( const FileLocation *base ) const
 {
-       return PassThruCacheDirectory ( basename + "_s.h",
-                                       backend->intermediateDirectory );
+       string newname = GetBasename ( base->name ) + "_s.h";
+       return new FileLocation ( IntermediateDirectory, base->relative_path, newname );
 }
 
-void
-MingwModuleHandler::GenerateWidlCommandsServer (
-       const CompilationUnit& compilationUnit,
-       const string& widlflagsMacro )
+/* caller needs to delete the returned object */
+const FileLocation*
+MingwModuleHandler::GetRpcClientHeaderFilename ( const FileLocation *base ) const
 {
-       FileLocation* sourceFileLocation = compilationUnit.GetFilename ( backend->intermediateDirectory );
-       string filename = sourceFileLocation->filename;
-       string dependencies = filename;
-       dependencies += " " + NormalizeFilename ( module.xmlbuildFile );
-
-       string basename = GetBasename ( filename );
-
-       string generatedHeaderFilename = GetRpcServerHeaderFilename ( basename );
-       CLEAN_FILE(generatedHeaderFilename);
-
-       string generatedServerFilename = PassThruCacheDirectory (
-               basename + "_s.c",
-               backend->intermediateDirectory );
-       CLEAN_FILE(generatedServerFilename);
-
-       fprintf ( fMakefile,
-                 "%s %s: %s $(WIDL_TARGET) | %s\n",
-                 generatedServerFilename.c_str (),
-                 generatedHeaderFilename.c_str (),
-                 dependencies.c_str (),
-                 GetDirectory ( generatedServerFilename ).c_str () );
-       fprintf ( fMakefile, "\t$(ECHO_WIDL)\n" );
-       fprintf ( fMakefile,
-                 "\t%s %s %s -h -H %s -s -S %s %s\n",
-                 "$(Q)$(WIDL_TARGET)",
-                 GetWidlFlags ( compilationUnit ).c_str (),
-                 widlflagsMacro.c_str (),
-                 generatedHeaderFilename.c_str (),
-                 generatedServerFilename.c_str (),
-                 filename.c_str () );
+       string newname = GetBasename ( base->name ) + "_c.h";
+       return new FileLocation ( IntermediateDirectory, base->relative_path, newname );
 }
 
-string
-MingwModuleHandler::GetRpcClientHeaderFilename ( string basename ) const
+/* caller needs to delete the returned object */
+const FileLocation*
+MingwModuleHandler::GetRpcProxyHeaderFilename ( const FileLocation *base ) const
 {
-       return PassThruCacheDirectory ( basename + "_c.h",
-                                       backend->intermediateDirectory );
+       string newname = GetBasename ( base->name ) + "_p.h";
+       return new FileLocation ( IntermediateDirectory, base->relative_path, newname );
 }
 
-string
-MingwModuleHandler::GetIdlHeaderFilename ( string basename ) const
+/* caller needs to delete the returned object */
+const FileLocation*
+MingwModuleHandler::GetIdlHeaderFilename ( const FileLocation *base ) const
 {
-       return PassThruCacheDirectory ( basename + ".h",
-                                       backend->intermediateDirectory );
+       string newname = GetBasename ( base->name ) + ".h";
+       return new FileLocation ( IntermediateDirectory, base->relative_path, newname );
 }
 
-void
-MingwModuleHandler::GenerateWidlCommandsTypeLib (
-       const CompilationUnit& compilationUnit,
-       const string& widlflagsMacro )
+/* caller needs to delete the returned object */
+const FileLocation*
+MingwModuleHandler::GetMcHeaderFilename ( const FileLocation *base ) const
 {
-       FileLocation* sourceFileLocation = compilationUnit.GetFilename ( backend->intermediateDirectory );
-       string filename = sourceFileLocation->filename;
-       string dependencies = filename;
-       dependencies += " " + NormalizeFilename ( module.xmlbuildFile );
-
-       string TypeLibFilename = module.GetTargetName ();
-
-       fprintf ( fMakefile,
-                 "%s: %s $(WIDL_TARGET) | %s\n",
-                 GetTargetMacro ( module ).c_str (),
-                 dependencies.c_str (),
-                 GetDirectory ( TypeLibFilename ).c_str () );
-       fprintf ( fMakefile, "\t$(ECHO_WIDL)\n" );
-       fprintf ( fMakefile,
-                 "\t%s %s %s -t -T $@ %s\n",
-                 "$(Q)$(WIDL_TARGET)",
-                 GetWidlFlags ( compilationUnit ).c_str (),
-                 widlflagsMacro.c_str (),
-                         filename.c_str () );
-}
-
-void
-MingwModuleHandler::GenerateWidlCommandsClient (
-       const CompilationUnit& compilationUnit,
-       const string& widlflagsMacro )
-{
-       FileLocation* sourceFileLocation = compilationUnit.GetFilename ( backend->intermediateDirectory );
-       string filename = sourceFileLocation->filename;
-       string dependencies = filename;
-       dependencies += " " + NormalizeFilename ( module.xmlbuildFile );
-
-       string basename = GetBasename ( filename );
-
-       string generatedHeaderFilename = GetRpcClientHeaderFilename ( basename );
-       CLEAN_FILE(generatedHeaderFilename);
-
-       string generatedClientFilename = PassThruCacheDirectory (
-               basename + "_c.c",
-               backend->intermediateDirectory );
-       CLEAN_FILE(generatedClientFilename);
-
-       fprintf ( fMakefile,
-                 "%s %s: %s $(WIDL_TARGET) | %s\n",
-                 generatedClientFilename.c_str (),
-                 generatedHeaderFilename.c_str (),
-                 dependencies.c_str (),
-                 GetDirectory ( generatedClientFilename ).c_str () );
-       fprintf ( fMakefile, "\t$(ECHO_WIDL)\n" );
-       fprintf ( fMakefile,
-                 "\t%s %s %s -h -H %s -c -C %s %s\n",
-                 "$(Q)$(WIDL_TARGET)",
-                 GetWidlFlags ( compilationUnit ).c_str (),
-                 widlflagsMacro.c_str (),
-                 generatedHeaderFilename.c_str (),
-                 generatedClientFilename.c_str (),
-                 filename.c_str () );
-}
-
-void
-MingwModuleHandler::GenerateWidlCommandsIdlHeader (
-       const CompilationUnit& compilationUnit,
-       const string& widlflagsMacro )
-{
-       FileLocation* sourceFileLocation = compilationUnit.GetFilename ( backend->intermediateDirectory );
-       string filename = sourceFileLocation->filename;
-       string dependencies = filename;
-       dependencies += " " + NormalizeFilename ( module.xmlbuildFile );
-
-       string basename = GetBasename ( filename );
-
-       string generatedHeaderFilename = GetIdlHeaderFilename ( basename );
-       CLEAN_FILE(generatedHeaderFilename);
-
-       fprintf ( fMakefile,
-                 "%s: %s $(WIDL_TARGET) | %s\n",
-                 generatedHeaderFilename.c_str (),
-                 dependencies.c_str (),
-                 GetDirectory ( generatedHeaderFilename ).c_str () );
-       fprintf ( fMakefile, "\t$(ECHO_WIDL)\n" );
-       fprintf ( fMakefile,
-                 "\t%s %s %s -h -H %s %s\n",
-                 "$(Q)$(WIDL_TARGET)",
-                 GetWidlFlags ( compilationUnit ).c_str (),
-                 widlflagsMacro.c_str (),
-                 generatedHeaderFilename.c_str (),
-                 filename.c_str () );
-}
-
-void
-MingwModuleHandler::GenerateWidlCommands (
-       const CompilationUnit& compilationUnit,
-       const string& widlflagsMacro )
-{
-       if ( module.type == RpcServer )
-               GenerateWidlCommandsServer ( compilationUnit,
-                                            widlflagsMacro );
-       else if ( module.type == RpcClient )
-               GenerateWidlCommandsClient ( compilationUnit,
-                                            widlflagsMacro );
-       else if ( module.type == TypeLib )
-               GenerateWidlCommandsTypeLib ( compilationUnit,
-                                                                               widlflagsMacro );
-       else // applies also for other module.types which include idl files
-               GenerateWidlCommandsIdlHeader ( compilationUnit,
-                                               widlflagsMacro );
+       string newname = GetBasename ( base->name ) + ".h";
+       return new FileLocation ( IntermediateDirectory, "include/reactos" , newname );
 }
 
 void
 MingwModuleHandler::GenerateCommands (
        const CompilationUnit& compilationUnit,
-       const string& cc,
-       const string& cppc,
-       const string& cflagsMacro,
-       const string& nasmflagsMacro,
-       const string& windresflagsMacro,
-       const string& widlflagsMacro )
-{
-       FileLocation* sourceFileLocation = compilationUnit.GetFilename ( backend->intermediateDirectory );
-       string filename = sourceFileLocation->filename;
-       string extension = GetExtension ( filename );
-       if ( extension == ".c" || extension == ".C" )
-       {
-               GenerateGccCommand ( sourceFileLocation,
-                                    GetCompilationUnitDependencies ( compilationUnit ),
-                                    cc,
-                                    cflagsMacro );
-               return;
-       }
-       else if ( extension == ".cc" || extension == ".CC" ||
-                 extension == ".cpp" || extension == ".CPP" ||
-                 extension == ".cxx" || extension == ".CXX" )
-       {
-               GenerateGccCommand ( sourceFileLocation,
-                                    GetCompilationUnitDependencies ( compilationUnit ),
-                                    cppc,
-                                    cflagsMacro );
-               return;
-       }
-       else if ( extension == ".s" || extension == ".S" )
-       {
-               GenerateGccAssemblerCommand ( sourceFileLocation,
-                                             cc,
-                                             cflagsMacro );
-               return;
-       }
-       else if ( extension == ".asm" || extension == ".ASM" )
-       {
-               GenerateNasmCommand ( sourceFileLocation,
-                                     nasmflagsMacro );
-               return;
-       }
-       else if ( extension == ".rc" || extension == ".RC" )
+       const string& extraDependencies )
+{
+       const FileLocation& sourceFile = compilationUnit.GetFilename ();
+       string extension = GetExtension ( sourceFile );
+       std::transform ( extension.begin (), extension.end (), extension.begin (), tolower );
+
+       struct
+       {
+               HostType host;
+               ModuleType type;
+               string extension;
+               Rule* rule;
+       } rules[] = {
+               { HostDontCare, TypeDontCare, ".s", &gasRule },
+               { HostDontCare, BootSector, ".asm", &bootRule },
+               { HostDontCare, TypeDontCare, ".asm", &nasmRule },
+               { HostDontCare, TypeDontCare, ".rc", &windresRule },
+               { HostDontCare, TypeDontCare, ".mc", &wmcRule },
+               { HostDontCare, TypeDontCare, ".spec", &winebuildRule },
+               { HostDontCare, RpcServer, ".idl", &widlServerRule },
+               { HostDontCare, RpcClient, ".idl", &widlClientRule },
+               { HostDontCare, RpcProxy, ".idl", &widlProxyRule },
+               { HostDontCare, EmbeddedTypeLib, ".idl", &widlTlbRule },
+               { HostDontCare, TypeDontCare, ".idl", &widlHeaderRule },
+               { HostTrue, TypeDontCare, ".c", &gccHostRule },
+               { HostTrue, TypeDontCare, ".cc", &gppHostRule },
+               { HostTrue, TypeDontCare, ".cpp", &gppHostRule },
+               { HostTrue, TypeDontCare, ".cxx", &gppHostRule },
+               { HostFalse, TypeDontCare, ".c", &gccRule },
+               { HostFalse, TypeDontCare, ".cc", &gppRule },
+               { HostFalse, TypeDontCare, ".cpp", &gppRule },
+               { HostFalse, TypeDontCare, ".cxx", &gppRule },
+               { HostFalse, Cabinet, ".*", &emptyRule }
+       };
+       size_t i;
+       Rule *customRule = NULL;
+
+       for ( i = 0; i < sizeof ( rules ) / sizeof ( rules[0] ); i++ )
        {
-               GenerateWindresCommand ( sourceFileLocation,
-                                        windresflagsMacro );
-               return;
+               if ( rules[i].host != HostDontCare && rules[i].host != module.host )
+                       continue;
+               if ( rules[i].type != TypeDontCare && rules[i].type != module.type )
+                       continue;
+               if ( rules[i].extension != extension && rules[i].extension != ".*")
+                       continue;
+               customRule = rules[i].rule;
+               break;
        }
-       else if ( extension == ".spec" || extension == ".SPEC" )
+
+       if ( extension == ".c" || extension == ".cc" || extension == ".cpp" || extension == ".cxx" )
        {
-               GenerateWinebuildCommands ( sourceFileLocation );
-               GenerateGccCommand ( GetActualSourceFilename ( sourceFileLocation ),
-                                    "",
-                                    cc,
-                                    cflagsMacro );
-               return;
+               GenerateGccCommand ( &sourceFile,
+                                    customRule,
+                                    GetCompilationUnitDependencies ( compilationUnit ) + GetExtraDependencies ( &sourceFile ) + extraDependencies );
        }
-       else if ( extension == ".idl" || extension == ".IDL" )
+       else if ( customRule )
+               customRule->Execute ( fMakefile, backend, module, &sourceFile, clean_files );
+       else
        {
-               GenerateWidlCommands ( compilationUnit,
-                                      widlflagsMacro );
-               if ( (module.type == RpcServer) || (module.type == RpcClient) )
-               {
-                       GenerateGccCommand ( GetActualSourceFilename ( sourceFileLocation ),
-                                            GetExtraDependencies ( filename ),
-                                        cc,
-                                            cflagsMacro );
-               }
-               return;
+               throw InvalidOperationException ( __FILE__,
+                                                 __LINE__,
+                                                 "Unsupported filename extension '%s' in file '%s'",
+                                                 extension.c_str (),
+                                                 backend->GetFullName ( sourceFile ).c_str () );
        }
-
-       throw InvalidOperationException ( __FILE__,
-                                         __LINE__,
-                                         "Unsupported filename extension '%s' in file '%s'",
-                                         extension.c_str (),
-                                         filename.c_str () );
 }
 
 void
-MingwModuleHandler::GenerateBuildMapCode ( const char *mapTarget )
+MingwModuleHandler::GenerateBuildMapCode ( const FileLocation *mapTarget )
 {
        fprintf ( fMakefile,
                  "ifeq ($(ROS_BUILDMAP),full)\n" );
 
-       string mapFilename = PassThruCacheDirectory (
-               GetBasename ( module.GetPath () ) + ".map",
-               backend->outputDirectory );
+       FileLocation mapFilename ( OutputDirectory,
+                                  module.output->relative_path,
+                                  GetBasename ( module.output->name ) + ".map" );
        CLEAN_FILE ( mapFilename );
 
        fprintf ( fMakefile,
                  "\t$(ECHO_OBJDUMP)\n" );
        fprintf ( fMakefile,
                  "\t$(Q)${objdump} -d -S %s > %s\n",
-                         mapTarget ? mapTarget :  "$@",
-                 mapFilename.c_str () );
+                 mapTarget ? backend->GetFullName ( *mapTarget ).c_str () :  "$@",
+                 backend->GetFullName ( mapFilename ).c_str () );
 
        fprintf ( fMakefile,
                  "else\n" );
@@ -1481,8 +1545,8 @@ MingwModuleHandler::GenerateBuildMapCode ( const char *mapTarget )
                  "\t$(ECHO_NM)\n" );
        fprintf ( fMakefile,
                  "\t$(Q)${nm} --numeric-sort %s > %s\n",
-                         mapTarget ? mapTarget :  "$@",
-                 mapFilename.c_str () );
+                 mapTarget ? backend->GetFullName ( *mapTarget ).c_str () :  "$@",
+                 backend->GetFullName ( mapFilename ).c_str () );
 
        fprintf ( fMakefile,
                  "endif\n" );
@@ -1497,28 +1561,20 @@ MingwModuleHandler::GenerateBuildNonSymbolStrippedCode ()
        fprintf ( fMakefile,
                  "ifeq ($(ROS_BUILDNOSTRIP),yes)\n" );
 
-       string filename = module.GetPath ();
-       string outputFilename = PassThruCacheDirectory (
-               filename,
-               backend->outputDirectory );
-       string nostripFilename = PassThruCacheDirectory (
-               GetBasename ( filename ) + ".nostrip" + GetExtension ( filename ),
-               backend->outputDirectory );
+       FileLocation nostripFilename ( OutputDirectory,
+                                      module.output->relative_path,
+                                      GetBasename ( module.output->name ) + ".nostrip" + GetExtension ( *module.output ) );
        CLEAN_FILE ( nostripFilename );
 
-       fprintf ( fMakefile,
-                 "\t$(ECHO_CP)\n" );
-       fprintf ( fMakefile,
-                         "\t${cp} %s %s 1>$(NUL)\n",
-                         outputFilename.c_str (),
-                 nostripFilename.c_str () );
+       OutputCopyCommand ( *module.output, nostripFilename );
 
        fprintf ( fMakefile,
                  "endif\n" );
 }
 
 void
-MergeStringVector ( const vector<string>& input,
+MergeStringVector ( const Backend* backend,
+                    const vector<FileLocation>& input,
                     vector<string>& output )
 {
        int wrap_at = 25;
@@ -1526,8 +1582,6 @@ MergeStringVector ( const vector<string>& input,
        int wrap_count = -1;
        for ( size_t i = 0; i < input.size (); i++ )
        {
-               if ( input[i].size () == 0 )
-                       continue;
                if ( wrap_count++ == wrap_at )
                {
                        output.push_back ( s );
@@ -1536,7 +1590,7 @@ MergeStringVector ( const vector<string>& input,
                }
                else if ( s.size () > 0)
                        s += " ";
-               s += input[i];
+               s += backend->GetFullName ( input[i] );
        }
        if ( s.length () > 0 )
                output.push_back ( s );
@@ -1544,12 +1598,15 @@ MergeStringVector ( const vector<string>& input,
 
 void
 MingwModuleHandler::GetObjectsVector ( const IfableData& data,
-                                       vector<string>& objectFiles ) const
+                                       vector<FileLocation>& objectFiles ) const
 {
        for ( size_t i = 0; i < data.compilationUnits.size (); i++ )
        {
                CompilationUnit& compilationUnit = *data.compilationUnits[i];
-               objectFiles.push_back ( GetObjectFilename ( compilationUnit.GetFilename ( backend->intermediateDirectory ), NULL ) );
+               const FileLocation& compilationName = compilationUnit.GetFilename ();
+               const FileLocation *object_file = GetObjectFilename ( &compilationName, module );
+               objectFiles.push_back ( *object_file );
+               delete object_file;
        }
 }
 
@@ -1558,11 +1615,12 @@ MingwModuleHandler::GenerateCleanObjectsAsYouGoCode () const
 {
        if ( backend->configuration.CleanAsYouGo )
        {
-               vector<string> objectFiles;
+               vector<FileLocation> objectFiles;
                GetObjectsVector ( module.non_if_data,
                                   objectFiles );
                vector<string> lines;
-               MergeStringVector ( objectFiles,
+               MergeStringVector ( backend,
+                                   objectFiles,
                                    lines );
                for ( size_t i = 0; i < lines.size (); i++ )
                {
@@ -1598,81 +1656,97 @@ MingwModuleHandler::GenerateRunStripCode () const
 void
 MingwModuleHandler::GenerateLinkerCommand (
        const string& dependencies,
-       const string& linker,
        const string& linkerParameters,
-       const string& objectsMacro,
-       const string& libsMacro,
        const string& pefixupParameters )
 {
-       string target ( GetTargetMacro ( module ) );
-       string target_folder ( GetDirectory ( GetTargetFilename ( module, NULL ) ) );
-       string definitionFilename = GetDefinitionFilename ();
+       const FileLocation *target_file = GetTargetFilename ( module, NULL );
+       const FileLocation *definitionFilename = GetDefinitionFilename ();
+       string linker = module.cplusplus ? "${gpp}" : "${gcc}";
+       string objectsMacro = GetObjectsMacro ( module );
+       string libsMacro = GetLibsMacro ();
+
+       string target_macro ( GetTargetMacro ( module ) );
+       string target_folder ( backend->GetFullPath ( *target_file ) );
 
        string linkerScriptArgument;
        if ( module.linkerScript != NULL )
-               linkerScriptArgument = ssprintf ( "-Wl,-T,%s", module.linkerScript->directory.c_str () );
+               linkerScriptArgument = ssprintf ( " -Wl,-T,%s", backend->GetFullName ( *module.linkerScript->file ).c_str () );
        else
                linkerScriptArgument = "";
 
        fprintf ( fMakefile,
                "%s: %s %s $(RSYM_TARGET) $(PEFIXUP_TARGET) | %s\n",
-               target.c_str (),
-               definitionFilename.c_str (),
+               target_macro.c_str (),
+               definitionFilename ? backend->GetFullName ( *definitionFilename ).c_str () : "",
                dependencies.c_str (),
                target_folder.c_str () );
        fprintf ( fMakefile, "\t$(ECHO_LD)\n" );
-       string targetName ( module.GetTargetName () );
+       string targetName ( module.output->name );
 
-       if ( module.IsDLL () )
+       if ( !module.IsDLL () )
        {
-               string temp_exp = ros_temp + module.name + ".temp.exp";
+               fprintf ( fMakefile,
+                         "\t%s %s%s -o %s %s %s %s\n",
+                         linker.c_str (),
+                         linkerParameters.c_str (),
+                         linkerScriptArgument.c_str (),
+                         target_macro.c_str (),
+                         objectsMacro.c_str (),
+                         libsMacro.c_str (),
+                         GetLinkerMacro ().c_str () );
+       }
+       else if ( module.HasImportLibrary () )
+       {
+               FileLocation temp_exp ( TemporaryDirectory,
+                                       "",
+                                       module.name + ".temp.exp" );
                CLEAN_FILE ( temp_exp );
 
                fprintf ( fMakefile,
-                         "\t${dlltool} --dllname %s --def %s --output-exp %s %s %s\n",
+                         "\t${dlltool} --dllname %s --def %s --output-exp %s%s%s\n",
                          targetName.c_str (),
-                         definitionFilename.c_str (),
-                         temp_exp.c_str (),
-                         module.mangledSymbols ? "" : "--kill-at",
-                         module.underscoreSymbols ? "--add-underscore" : "" );
+                         definitionFilename ? backend->GetFullName ( *definitionFilename ).c_str () : "",
+                         backend->GetFullName ( temp_exp ).c_str (),
+                         module.mangledSymbols ? "" : " --kill-at",
+                         module.underscoreSymbols ? " --add-underscore" : "" );
 
                fprintf ( fMakefile,
-                         "\t%s %s %s %s -o %s %s %s %s\n",
+                         "\t%s %s%s %s -o %s %s %s %s\n",
                          linker.c_str (),
                          linkerParameters.c_str (),
                          linkerScriptArgument.c_str (),
-                         temp_exp.c_str (),
-                         target.c_str (),
+                         backend->GetFullName ( temp_exp ).c_str (),
+                         target_macro.c_str (),
                          objectsMacro.c_str (),
                          libsMacro.c_str (),
                          GetLinkerMacro ().c_str () );
 
                fprintf ( fMakefile,
-                         "\t$(Q)$(PEFIXUP_TARGET) %s -exports %s\n",
-                         target.c_str (),
+                         "\t$(Q)$(PEFIXUP_TARGET) %s -exports%s\n",
+                         target_macro.c_str (),
                          pefixupParameters.c_str() );
 
                fprintf ( fMakefile,
                          "\t-@${rm} %s 2>$(NUL)\n",
-                         temp_exp.c_str () );
+                         backend->GetFullName ( temp_exp ).c_str () );
        }
        else
        {
+               /* XXX: need to workaround binutils bug, which exports
+                * all functions in a dll if no .def file or an empty
+                * one has been provided... */
+               /* See bug 1244 */
+               //printf ( "%s will have all its functions exported\n",
+               //         module.target->name.c_str () );
                fprintf ( fMakefile,
-                         "\t%s %s %s -o %s %s %s %s\n",
+                         "\t%s %s%s -o %s %s %s %s\n",
                          linker.c_str (),
                          linkerParameters.c_str (),
                          linkerScriptArgument.c_str (),
-                         target.c_str (),
+                         target_macro.c_str (),
                          objectsMacro.c_str (),
                          libsMacro.c_str (),
                          GetLinkerMacro ().c_str () );
-
-#if 0 // causes crashes sometimes
-               fprintf ( fMakefile,
-                         "\t${objcopy} -R .edata %s\n",
-                         target.c_str () );
-#endif
        }
 
        GenerateBuildMapCode ();
@@ -1680,42 +1754,51 @@ MingwModuleHandler::GenerateLinkerCommand (
        GenerateRunRsymCode ();
        GenerateRunStripCode ();
        GenerateCleanObjectsAsYouGoCode ();
+
+       if ( definitionFilename )
+               delete definitionFilename;
+       delete target_file;
 }
 
 void
 MingwModuleHandler::GeneratePhonyTarget() const
 {
        string targetMacro ( GetTargetMacro ( module ) );
+       const FileLocation *target_file = GetTargetFilename ( module, NULL );
+
        fprintf ( fMakefile,
                  ".PHONY: %s\n\n",
                  targetMacro.c_str ());
        fprintf ( fMakefile, "%s: | %s\n",
                  targetMacro.c_str (),
-                 GetDirectory ( GetTargetFilename ( module, NULL ) ).c_str () );
+                 backend->GetFullPath ( *target_file ).c_str () );
+
+       delete target_file;
 }
 
 void
-MingwModuleHandler::GenerateObjectFileTargets (
-       const IfableData& data,
-       const string& cc,
-       const string& cppc,
-       const string& cflagsMacro,
-       const string& nasmflagsMacro,
-       const string& windresflagsMacro,
-       const string& widlflagsMacro )
+MingwModuleHandler::GenerateObjectFileTargets ( const IfableData& data )
 {
        size_t i;
+       string moduleDependencies;
 
        const vector<CompilationUnit*>& compilationUnits = data.compilationUnits;
+       for ( i = 0; i < compilationUnits.size (); i++ )
+       {
+               CompilationUnit& compilationUnit = *compilationUnits[i];
+               const FileLocation& compilationName = compilationUnit.GetFilename ();
+               const FileLocation *objectFilename = GetObjectFilename ( &compilationName, module );
+               if ( GetExtension ( *objectFilename ) == ".h" )
+                       moduleDependencies += ssprintf ( " $(%s_HEADERS)", module.name.c_str () );
+               else if ( GetExtension ( *objectFilename ) == ".rc" )
+                       moduleDependencies += ssprintf ( " $(%s_RESOURCES)", module.name.c_str () );
+               delete objectFilename;
+       }
+
        for ( i = 0; i < compilationUnits.size (); i++ )
        {
                GenerateCommands ( *compilationUnits[i],
-                                  cc,
-                                  cppc,
-                                  cflagsMacro,
-                                  nasmflagsMacro,
-                                  windresflagsMacro,
-                                  widlflagsMacro );
+                                  moduleDependencies );
                fprintf ( fMakefile,
                          "\n" );
        }
@@ -1723,13 +1806,7 @@ MingwModuleHandler::GenerateObjectFileTargets (
        const vector<If*>& ifs = data.ifs;
        for ( i = 0; i < ifs.size(); i++ )
        {
-               GenerateObjectFileTargets ( ifs[i]->data,
-                                           cc,
-                                           cppc,
-                                           cflagsMacro,
-                                           nasmflagsMacro,
-                                           windresflagsMacro,
-                                           widlflagsMacro );
+               GenerateObjectFileTargets ( ifs[i]->data );
        }
 
        vector<CompilationUnit*> sourceCompilationUnits;
@@ -1737,89 +1814,75 @@ MingwModuleHandler::GenerateObjectFileTargets (
        for ( i = 0; i < sourceCompilationUnits.size (); i++ )
        {
                GenerateCommands ( *sourceCompilationUnits[i],
-                                  cc,
-                                  cppc,
-                                  cflagsMacro,
-                                  nasmflagsMacro,
-                                  windresflagsMacro,
-                                  widlflagsMacro );
+                                  moduleDependencies );
        }
        CleanupCompilationUnitVector ( sourceCompilationUnits );
 }
 
 void
-MingwModuleHandler::GenerateObjectFileTargets (
-       const string& cc,
-       const string& cppc,
-       const string& cflagsMacro,
-       const string& nasmflagsMacro,
-       const string& windresflagsMacro,
-       const string& widlflagsMacro )
+MingwModuleHandler::GenerateObjectFileTargets ()
 {
-       if ( module.pch && use_pch )
+       const FileLocation *pchFilename = GetPrecompiledHeaderFilename ();
+
+       if ( pchFilename )
        {
-               const string& baseHeaderFilename = module.pch->file.name;
-               const string& pchFilename = GetPrecompiledHeaderFilename ();
-               CLEAN_FILE(pchFilename);
-               string dependencies = baseHeaderFilename;
+               string cc = ( module.host == HostTrue ? "${host_gcc}" : "${gcc}" );
+               string cppc = ( module.host == HostTrue ? "${host_gpp}" : "${gpp}" );
+
+               const FileLocation& baseHeaderFile = *module.pch->file;
+               CLEAN_FILE ( *pchFilename );
+               string dependencies = backend->GetFullName ( baseHeaderFile );
                /* WIDL generated headers may be used */
-               vector<string> rpcDependencies;
+               vector<FileLocation> rpcDependencies;
                GetRpcHeaderDependencies ( rpcDependencies );
-               dependencies += " " + v2s ( rpcDependencies, 5 );
+               if ( rpcDependencies.size () > 0 )
+                       dependencies += " " + v2s ( backend, rpcDependencies, 5 );
                fprintf ( fMakefile,
-                         "%s: %s\n",
-                         pchFilename.c_str(),
-                         dependencies.c_str() );
+                         "%s: %s ${%s_precondition} | %s\n",
+                         backend->GetFullName ( *pchFilename ).c_str(),
+                         dependencies.c_str(),
+                         module.name.c_str (),
+                         backend->GetFullPath ( *pchFilename ).c_str() );
                fprintf ( fMakefile, "\t$(ECHO_PCH)\n" );
                fprintf ( fMakefile,
                          "\t%s -o %s %s -g %s\n\n",
                          module.cplusplus ? cppc.c_str() : cc.c_str(),
-                         pchFilename.c_str(),
+                         backend->GetFullName ( *pchFilename ).c_str(),
                          cflagsMacro.c_str(),
-                         baseHeaderFilename.c_str() );
+                         backend->GetFullName ( baseHeaderFile ).c_str() );
+               delete pchFilename;
        }
 
-       GenerateObjectFileTargets ( module.non_if_data,
-                                   cc,
-                                   cppc,
-                                   cflagsMacro,
-                                   nasmflagsMacro,
-                                   windresflagsMacro,
-                                   widlflagsMacro );
+       GenerateObjectFileTargets ( module.non_if_data );
        fprintf ( fMakefile, "\n" );
 }
 
-string
-MingwModuleHandler::GenerateArchiveTarget ( const string& ar,
-                                            const string& objs_macro ) const
+/* caller needs to delete the returned object */
+const FileLocation*
+MingwModuleHandler::GenerateArchiveTarget ()
 {
-       string archiveFilename ( GetModuleArchiveFilename () );
+       const FileLocation *archiveFilename = GetModuleArchiveFilename ();
+       const FileLocation *definitionFilename = GetDefinitionFilename ();
 
-       fprintf ( fMakefile,
-                 "%s: %s | %s\n",
-                 archiveFilename.c_str (),
-                 objs_macro.c_str (),
-                 GetDirectory(archiveFilename).c_str() );
+       arRule1.Execute ( fMakefile, backend, module, archiveFilename, clean_files );
 
-       if ( module.type == StaticLibrary && module.importLibrary )
+       if ( IsStaticLibrary ( module ) && definitionFilename )
        {
-               string archiveFilename ( GetModuleArchiveFilename () );
-               string definitionFilename ( GetDefinitionFilename () );
-
                fprintf ( fMakefile,
-                         "\t${dlltool} --dllname %s --def %s --output-lib $@ %s %s\n",
+                         "\t${dlltool} --dllname %s --def %s --output-lib $@%s%s\n",
                          module.importLibrary->dllname.c_str (),
-                         definitionFilename.c_str (),
-                         module.mangledSymbols ? "" : "--kill-at",
-                         module.underscoreSymbols ? "--add-underscore" : "" );
+                         backend->GetFullName ( *definitionFilename ).c_str (),
+                         module.mangledSymbols ? "" : " --kill-at",
+                         module.underscoreSymbols ? " --add-underscore" : "" );
        }
 
-       fprintf ( fMakefile, "\t$(ECHO_AR)\n" );
+       if ( definitionFilename )
+               delete definitionFilename;
 
-       fprintf ( fMakefile,
-                 "\t%s -rc $@ %s\n",
-                 ar.c_str (),
-                 objs_macro.c_str ());
+       if(module.type == HostStaticLibrary)
+               arHostRule2.Execute ( fMakefile, backend, module, archiveFilename, clean_files );
+       else
+               arRule2.Execute ( fMakefile, backend, module, archiveFilename, clean_files );
 
        GenerateCleanObjectsAsYouGoCode ();
 
@@ -1867,7 +1930,25 @@ MingwModuleHandler::GetModuleTargets ( const Module& module )
        if ( ReferenceObjects ( module ) )
                return GetObjectsMacro ( module );
        else
-               return GetTargetFilename ( module, NULL );
+       {
+               const FileLocation *target_file = GetTargetFilename ( module, NULL );
+               string target = backend->GetFullName ( *target_file ).c_str ();
+               delete target_file;
+               return target;
+       }
+}
+
+void
+MingwModuleHandler::GenerateSourceMacro ()
+{
+       sourcesMacro = ssprintf ( "%s_SOURCES", module.name.c_str ());
+
+       GenerateSourceMacros (
+               "=",
+               module.non_if_data );
+
+       // future references to the macro will be to get its values
+       sourcesMacro = ssprintf ("$(%s)", sourcesMacro.c_str ());
 }
 
 void
@@ -1877,8 +1958,7 @@ MingwModuleHandler::GenerateObjectMacro ()
 
        GenerateObjectMacros (
                "=",
-               module.non_if_data,
-               &module.linkerFlags );
+               module.non_if_data );
 
        // future references to the macro will be to get its values
        objectsMacro = ssprintf ("$(%s)", objectsMacro.c_str ());
@@ -1895,29 +1975,48 @@ MingwModuleHandler::GenerateTargetMacro ()
 
 void
 MingwModuleHandler::GetRpcHeaderDependencies (
-       vector<string>& dependencies ) const
+       vector<FileLocation>& dependencies ) const
 {
        for ( size_t i = 0; i < module.non_if_data.libraries.size (); i++ )
        {
                Library& library = *module.non_if_data.libraries[i];
                if ( library.importedModule->type == RpcServer ||
                     library.importedModule->type == RpcClient ||
+                    library.importedModule->type == RpcProxy ||
                     library.importedModule->type == IdlHeader )
                {
                        for ( size_t j = 0; j < library.importedModule->non_if_data.compilationUnits.size (); j++ )
                        {
                                CompilationUnit& compilationUnit = *library.importedModule->non_if_data.compilationUnits[j];
-                               FileLocation* sourceFileLocation = compilationUnit.GetFilename ( backend->intermediateDirectory );
-                               string extension = GetExtension ( sourceFileLocation->filename );
+                               const FileLocation& sourceFile = compilationUnit.GetFilename ();
+                               string extension = GetExtension ( sourceFile );
                                if ( extension == ".idl" || extension == ".IDL" )
                                {
-                                       string basename = GetBasename ( sourceFileLocation->filename );
+                                       string basename = GetBasename ( sourceFile.name );
                                        if ( library.importedModule->type == RpcServer )
-                                               dependencies.push_back ( GetRpcServerHeaderFilename ( basename ) );
+                                       {
+                                               const FileLocation *header = GetRpcServerHeaderFilename ( &sourceFile );
+                                               dependencies.push_back ( *header );
+                                               delete header;
+                                       }
                                        if ( library.importedModule->type == RpcClient )
-                                               dependencies.push_back ( GetRpcClientHeaderFilename ( basename ) );
+                                       {
+                                               const FileLocation *header = GetRpcClientHeaderFilename ( &sourceFile );
+                                               dependencies.push_back ( *header );
+                                               delete header;
+                                       }
+                                       if ( library.importedModule->type == RpcProxy )
+                                       {
+                                               const FileLocation *header = GetRpcProxyHeaderFilename ( &sourceFile );
+                                               dependencies.push_back ( *header );
+                                               delete header;
+                                       }
                                        if ( library.importedModule->type == IdlHeader )
-                                               dependencies.push_back ( GetIdlHeaderFilename ( basename ) );
+                                       {
+                                               const FileLocation *header = GetIdlHeaderFilename ( &sourceFile );
+                                               dependencies.push_back ( *header );
+                                               delete header;
+                                       }
                                }
                        }
                }
@@ -1927,6 +2026,8 @@ MingwModuleHandler::GetRpcHeaderDependencies (
 void
 MingwModuleHandler::GenerateOtherMacros ()
 {
+       set<const Define *> used_defs;
+
        cflagsMacro = ssprintf ("%s_CFLAGS", module.name.c_str ());
        nasmflagsMacro = ssprintf ("%s_NASMFLAGS", module.name.c_str ());
        windresflagsMacro = ssprintf ("%s_RCFLAGS", module.name.c_str ());
@@ -1938,19 +2039,29 @@ MingwModuleHandler::GenerateOtherMacros ()
        GenerateMacros (
                "=",
                module.non_if_data,
-               &module.linkerFlags );
+               &module.linkerFlags,
+               used_defs );
+
+       if ( module.host == HostFalse )
+       {
+               GenerateMacros (
+                       "+=",
+                       module.project.non_if_data,
+                       NULL,
+                       used_defs );
+       }
 
-       vector<string> s;
+       vector<FileLocation> s;
        if ( module.importLibrary )
        {
                const vector<CompilationUnit*>& compilationUnits = module.non_if_data.compilationUnits;
                for ( size_t i = 0; i < compilationUnits.size (); i++ )
                {
                        CompilationUnit& compilationUnit = *compilationUnits[i];
-                       FileLocation* sourceFileLocation = compilationUnit.GetFilename ( backend->intermediateDirectory );
-                       string extension = GetExtension ( sourceFileLocation->filename );
+                       const FileLocation& sourceFile = compilationUnit.GetFilename ();
+                       string extension = GetExtension ( sourceFile );
                        if ( extension == ".spec" || extension == ".SPEC" )
-                               GetSpecObjectDependencies ( s, sourceFileLocation->filename );
+                               GetSpecObjectDependencies ( s, &sourceFile );
                }
        }
        if ( s.size () > 0 )
@@ -1962,15 +2073,37 @@ MingwModuleHandler::GenerateOtherMacros ()
                for ( size_t i = 0; i < s.size(); i++ )
                        fprintf ( fMakefile,
                                  " %s",
-                                 s[i].c_str () );
+                                 backend->GetFullName ( s[i] ).c_str () );
                fprintf ( fMakefile, "\n" );
        }
 
-       string globalCflags = "-g";
+       string globalCflags = "";
+       if ( module.host == HostFalse )
+               globalCflags += " $(PROJECT_CFLAGS)";
+       else
+               globalCflags += " -Wall -Wpointer-arith -D__REACTOS__";
+       globalCflags += " -g";
        if ( backend->usePipe )
                globalCflags += " -pipe";
        if ( !module.allowWarnings )
                globalCflags += " -Werror";
+       if ( module.host == HostTrue )
+       {
+               if ( module.cplusplus )
+                       globalCflags += " $(HOST_CPPFLAGS)";
+               else
+                       globalCflags += " -Wno-strict-aliasing $(HOST_CFLAGS)";
+       }
+       else
+       {
+               if ( module.cplusplus )
+               {
+                       // HACK: use host headers when building C++
+                       globalCflags += " $(HOST_CPPFLAGS)";
+               }
+               else
+                       globalCflags += " -nostdinc";
+       }
 
        // Always force disabling of sibling calls optimisation for GCC
        // (TODO: Move to version-specific once this bug is fixed in GCC)
@@ -1978,24 +2111,35 @@ MingwModuleHandler::GenerateOtherMacros ()
 
        fprintf (
                fMakefile,
-               "%s += $(PROJECT_CFLAGS) %s\n",
+               "%s +=%s\n",
                cflagsMacro.c_str (),
                globalCflags.c_str () );
 
-       fprintf (
-               fMakefile,
-               "%s += $(PROJECT_RCFLAGS)\n",
-               windresflagsMacro.c_str () );
+       if ( module.host == HostFalse )
+       {
+               fprintf (
+                       fMakefile,
+                       "%s += $(PROJECT_RCFLAGS)\n",
+                       windresflagsMacro.c_str () );
 
-       fprintf (
-               fMakefile,
-               "%s += $(PROJECT_WIDLFLAGS)\n",
-               widlflagsMacro.c_str () );
+               fprintf (
+                       fMakefile,
+                       "%s += $(PROJECT_WIDLFLAGS) -I%s\n",
+                       widlflagsMacro.c_str (),
+                       module.output->relative_path.c_str () );
 
-       fprintf (
-               fMakefile,
-               "%s_LFLAGS += $(PROJECT_LFLAGS) -g\n",
-               module.name.c_str () );
+               fprintf (
+                       fMakefile,
+                       "%s_LFLAGS += $(PROJECT_LFLAGS) -g\n",
+                       module.name.c_str () );
+       }
+       else
+       {
+               fprintf (
+                       fMakefile,
+                       "%s_LFLAGS += $(HOST_LFLAGS)\n",
+                       module.name.c_str () );
+       }
 
        fprintf (
                fMakefile,
@@ -2030,7 +2174,7 @@ MingwModuleHandler::GenerateOtherMacros ()
                          linkerflags.c_str () );
        }
 
-       if ( module.type == StaticLibrary && module.isStartupLib )
+       if ( IsStaticLibrary ( module ) && module.isStartupLib )
        {
                fprintf ( fMakefile,
                          "%s += -Wno-main\n\n",
@@ -2048,20 +2192,9 @@ MingwModuleHandler::GenerateOtherMacros ()
 void
 MingwModuleHandler::GenerateRules ()
 {
-       string cc = ( module.host == HostTrue ? "${host_gcc}" : "${gcc}" );
-       string cppc = ( module.host == HostTrue ? "${host_gpp}" : "${gpp}" );
-       string ar = ( module.host == HostTrue ? "${host_ar}" : "${ar}" );
-
-       if ( module.name != "zlib" ) /* Avoid make warning */
-       {
-               string proxyMakefile = PassThruCacheDirectory (
-                       NormalizeFilename ( module.GetBasePath () + sSep + "makefile" ),
-                       backend->outputDirectory );
-               CLEAN_FILE ( proxyMakefile );
-       }
-
        string targetMacro = GetTargetMacro ( module );
-       CLEAN_FILE ( targetMacro );
+       //CLEAN_FILE ( targetMacro );
+       CLEAN_FILE ( FileLocation ( SourceDirectory, "", targetMacro ) );
 
        // generate phony target for module name
        fprintf ( fMakefile, ".PHONY: %s\n",
@@ -2081,17 +2214,11 @@ MingwModuleHandler::GenerateRules ()
 
        if ( !ReferenceObjects ( module ) )
        {
-               string ar_target ( GenerateArchiveTarget ( ar, objectsMacro ) );
-               if ( targetMacro != ar_target )
-                       CLEAN_FILE ( ar_target );
+               const FileLocation* ar_target = GenerateArchiveTarget ();
+               delete ar_target;
        }
 
-       GenerateObjectFileTargets ( cc,
-                                   cppc,
-                                   cflagsMacro,
-                                   nasmflagsMacro,
-                                   windresflagsMacro,
-                                   widlflagsMacro );
+       GenerateObjectFileTargets ();
 }
 
 void
@@ -2151,11 +2278,11 @@ MingwModuleHandler::GenerateInvocations () const
                                  invoke_targets[i].c_str () );
                fprintf ( fMakefile,
                          ": %s\n",
-                         NormalizeFilename ( invoke.invokeModule->GetPath () ).c_str () );
+                         NormalizeFilename ( backend->GetFullName ( *invoke.invokeModule->output ) ).c_str () );
                fprintf ( fMakefile, "\t$(ECHO_INVOKE)\n" );
                fprintf ( fMakefile,
                          "\t%s %s\n\n",
-                         NormalizeFilename ( invoke.invokeModule->GetPath () ).c_str (),
+                         NormalizeFilename ( backend->GetFullName ( *invoke.invokeModule->output ) ).c_str (),
                          invoke.GetParameters ().c_str () );
        }
 }
@@ -2171,18 +2298,35 @@ MingwModuleHandler::GetDefaultDependencies (
        string_list& dependencies ) const
 {
        /* Avoid circular dependency */
-       if ( module.type != BuildTool
-               && module.name != "zlib"
-               && module.name != "hostzlib" )
+       if ( module.host == HostTrue )
+               return;
 
-               dependencies.push_back ( "$(INIT)" );
+       if ( module.name != "psdk" )
+               dependencies.push_back ( "$(PSDK_TARGET) $(psdk_HEADERS)" );
+
+       /* Check if any dependent library relies on the generated headers */
+       for ( size_t i = 0; i < module.project.modules.size (); i++ )
+       {
+               const Module& m = *module.project.modules[i];
+               for ( size_t j = 0; j < m.non_if_data.compilationUnits.size (); j++ )
+               {
+                       CompilationUnit& compilationUnit = *m.non_if_data.compilationUnits[j];
+                       const FileLocation& sourceFile = compilationUnit.GetFilename ();
+                       string extension = GetExtension ( sourceFile );
+                       if (extension == ".mc" || extension == ".MC" )
+                       {
+                               string dependency = ssprintf ( "$(%s_MCHEADERS)", m.name.c_str () );
+                               dependencies.push_back ( dependency );
+                       }
+               }
+       }
 }
 
 void
 MingwModuleHandler::GeneratePreconditionDependencies ()
 {
        string preconditionDependenciesName = GetPreconditionDependenciesName ();
-       string_list sourceFilenames;
+       vector<FileLocation> sourceFilenames;
        GetSourceFilenamesWithoutGeneratedFiles ( sourceFilenames );
        string_list dependencies;
        GetDefaultDependencies ( dependencies );
@@ -2202,13 +2346,6 @@ MingwModuleHandler::GeneratePreconditionDependencies ()
                fprintf ( fMakefile, "\n\n" );
        }
 
-       for ( size_t i = 0; i < sourceFilenames.size(); i++ )
-       {
-               fprintf ( fMakefile,
-                         "%s: ${%s}\n",
-                         sourceFilenames[i].c_str(),
-                         preconditionDependenciesName.c_str ());
-       }
        fprintf ( fMakefile, "\n" );
 }
 
@@ -2218,24 +2355,26 @@ MingwModuleHandler::IsWineModule () const
        if ( module.importLibrary == NULL)
                return false;
 
-       size_t index = module.importLibrary->definition.rfind ( ".spec.def" );
+       size_t index = module.importLibrary->source->name.rfind ( ".spec.def" );
        return ( index != string::npos );
 }
 
-string
+/* caller needs to delete the returned object */
+const FileLocation*
 MingwModuleHandler::GetDefinitionFilename () const
 {
-       if ( module.importLibrary != NULL )
-       {
-               string defFilename = module.GetBasePath () + sSep + module.importLibrary->definition;
-               if ( IsWineModule () )
-                       return PassThruCacheDirectory ( NormalizeFilename ( defFilename ),
-                                                       backend->intermediateDirectory );
-               else
-                       return defFilename;
-       }
+       if ( module.importLibrary == NULL )
+               return NULL;
+
+       DirectoryLocation directory;
+       if ( IsWineModule () )
+               directory = IntermediateDirectory;
        else
-               return "tools" + sSep + "rbuild" + sSep + "empty.def";
+               directory = SourceDirectory;
+
+       return new FileLocation ( directory,
+                                 module.importLibrary->source->relative_path,
+                                 module.importLibrary->source->name );
 }
 
 void
@@ -2243,85 +2382,118 @@ MingwModuleHandler::GenerateImportLibraryTargetIfNeeded ()
 {
        if ( module.importLibrary != NULL )
        {
-               string library_target (
-                       GetImportLibraryFilename ( module, &clean_files ) );
-               string defFilename = GetDefinitionFilename ();
+               const FileLocation *library_target = GetImportLibraryFilename ( module, &clean_files );
+               const FileLocation *defFilename = GetDefinitionFilename ();
+               string empty = "tools" + sSep + "rbuild" + sSep + "empty.def";
 
-               string_list deps;
+               vector<FileLocation> deps;
                GetDefinitionDependencies ( deps );
 
                fprintf ( fMakefile, "# IMPORT LIBRARY RULE:\n" );
 
-               fprintf ( fMakefile, "%s: %s",
-                         library_target.c_str (),
-                         defFilename.c_str () );
+               fprintf ( fMakefile, "%s:",
+                         backend->GetFullName ( *library_target ).c_str () );
+
+               if ( defFilename )
+               {
+                       fprintf ( fMakefile, " %s",
+                                 backend->GetFullName ( *defFilename ).c_str () );
+               }
 
                size_t i, iend = deps.size();
                for ( i = 0; i < iend; i++ )
                        fprintf ( fMakefile, " %s",
-                                 deps[i].c_str () );
+                                 backend->GetFullName ( deps[i] ).c_str () );
 
                fprintf ( fMakefile, " | %s\n",
-                         GetDirectory ( GetImportLibraryFilename ( module, NULL ) ).c_str () );
+                         backend->GetFullPath ( *library_target ).c_str () );
 
                fprintf ( fMakefile, "\t$(ECHO_DLLTOOL)\n" );
 
                fprintf ( fMakefile,
-                         "\t${dlltool} --dllname %s --def %s --output-lib %s %s %s\n\n",
-                         module.GetTargetName ().c_str (),
-                         defFilename.c_str (),
-                         library_target.c_str (),
-                         module.mangledSymbols ? "" : "--kill-at",
-                         module.underscoreSymbols ? "--add-underscore" : "" );
+                         "\t${dlltool} --dllname %s --def %s --output-lib %s%s%s\n\n",
+                         module.output->name.c_str (),
+                         defFilename ? backend->GetFullName ( *defFilename ).c_str ()
+                                     : empty.c_str (),
+                         backend->GetFullName ( *library_target ).c_str (),
+                         module.mangledSymbols ? "" : " --kill-at",
+                         module.underscoreSymbols ? " --add-underscore" : "" );
+
+               if ( defFilename )
+                       delete defFilename;
+               delete library_target;
        }
 }
 
 void
 MingwModuleHandler::GetSpecObjectDependencies (
-       string_list& dependencies,
-       const string& filename ) const
+       vector<FileLocation>& dependencies,
+       const FileLocation *file ) const
+{
+       string basename = GetBasename ( file->name );
+
+       FileLocation defDependency ( IntermediateDirectory,
+                                    file->relative_path,
+                                    basename + ".spec.def" );
+       dependencies.push_back ( defDependency );
+
+       FileLocation stubsDependency ( IntermediateDirectory,
+                                      file->relative_path,
+                                    basename + ".stubs.c" );
+       dependencies.push_back ( stubsDependency );
+}
+
+void
+MingwModuleHandler::GetMcObjectDependencies (
+       vector<FileLocation>& dependencies,
+       const FileLocation *file ) const
 {
-       string basename = GetBasename ( filename );
-       string defDependency = PassThruCacheDirectory (
-               NormalizeFilename ( basename + ".spec.def" ),
-               backend->intermediateDirectory );
+       string basename = GetBasename ( file->name );
+
+       FileLocation defDependency ( IntermediateDirectory,
+                                    "include/reactos",
+                                    basename + ".h" );
        dependencies.push_back ( defDependency );
-       string stubsDependency = PassThruCacheDirectory (
-               NormalizeFilename ( basename + ".stubs.c" ),
-               backend->intermediateDirectory );
+
+       FileLocation stubsDependency ( IntermediateDirectory,
+                                      file->relative_path,
+                                    basename + ".rc" );
        dependencies.push_back ( stubsDependency );
 }
 
 void
 MingwModuleHandler::GetWidlObjectDependencies (
-       string_list& dependencies,
-       const string& filename ) const
+       vector<FileLocation>& dependencies,
+       const FileLocation *file ) const
 {
-       string basename = GetBasename ( filename );
-       string serverSourceDependency = PassThruCacheDirectory (
-               NormalizeFilename ( basename + "_s.c" ),
-               backend->intermediateDirectory );
+       string basename = GetBasename ( file->name );
+       const FileLocation *generatedHeaderFilename = GetRpcServerHeaderFilename ( file );
+
+       FileLocation serverSourceDependency ( IntermediateDirectory,
+                                             file->relative_path,
+                                             basename + "_s.c" );
        dependencies.push_back ( serverSourceDependency );
-       dependencies.push_back ( GetRpcServerHeaderFilename ( basename ) );
+       dependencies.push_back ( *generatedHeaderFilename );
+
+       delete generatedHeaderFilename;
 }
 
 void
 MingwModuleHandler::GetDefinitionDependencies (
-       string_list& dependencies ) const
+       vector<FileLocation>& dependencies ) const
 {
-       string dkNkmLibNoFixup = "dk/nkm/lib";
        const vector<CompilationUnit*>& compilationUnits = module.non_if_data.compilationUnits;
        for ( size_t i = 0; i < compilationUnits.size (); i++ )
        {
-               CompilationUnit& compilationUnit = *compilationUnits[i];
-               FileLocation* sourceFileLocation = compilationUnit.GetFilename ( backend->intermediateDirectory );
-               string extension = GetExtension ( sourceFileLocation->filename );
+               const CompilationUnit& compilationUnit = *compilationUnits[i];
+               const FileLocation& sourceFile = compilationUnit.GetFilename ();
+               string extension = GetExtension ( sourceFile );
                if ( extension == ".spec" || extension == ".SPEC" )
-                       GetSpecObjectDependencies ( dependencies, sourceFileLocation->filename );
+                       GetSpecObjectDependencies ( dependencies, &sourceFile );
                if ( extension == ".idl" || extension == ".IDL" )
                {
-                       if ( ( module.type == RpcServer ) || ( module.type == RpcClient ) )
-                               GetWidlObjectDependencies ( dependencies, sourceFileLocation->filename );
+                       if ( ( module.type == RpcServer ) || ( module.type == RpcClient ) || ( module.type == RpcProxy ) )
+                               GetWidlObjectDependencies ( dependencies, &sourceFile );
                }
        }
 }
@@ -2381,11 +2553,12 @@ MingwBuildToolModuleHandler::GenerateBuildToolModuleTarget ()
        else
                linker = "${host_gcc}";
 
+       const FileLocation *target_file = GetTargetFilename ( module, NULL );
        fprintf ( fMakefile, "%s: %s %s | %s\n",
                  targetMacro.c_str (),
                  objectsMacro.c_str (),
                  linkDepsMacro.c_str (),
-                 GetDirectory(GetTargetFilename(module,NULL)).c_str () );
+                 backend->GetFullPath ( *target_file ).c_str () );
        fprintf ( fMakefile, "\t$(ECHO_LD)\n" );
        fprintf ( fMakefile,
                  "\t%s %s -o $@ %s %s\n\n",
@@ -2393,6 +2566,8 @@ MingwBuildToolModuleHandler::GenerateBuildToolModuleTarget ()
                  GetLinkerMacro ().c_str (),
                  objectsMacro.c_str (),
                  libsMacro.c_str () );
+
+       delete target_file;
 }
 
 
@@ -2414,9 +2589,7 @@ MingwKernelModuleHandler::GenerateKernelModuleTarget ()
 {
        string targetMacro ( GetTargetMacro ( module ) );
        string workingDirectory = GetWorkingDirectory ( );
-       string objectsMacro = GetObjectsMacro ( module );
        string linkDepsMacro = GetLinkingDependenciesMacro ();
-       string libsMacro = GetLibsMacro ();
 
        GenerateImportLibraryTargetIfNeeded ();
 
@@ -2426,17 +2599,13 @@ MingwKernelModuleHandler::GenerateKernelModuleTarget ()
 
                string dependencies = linkDepsMacro + " " + objectsMacro;
 
-               string linkerParameters = ssprintf ( "-Wl,-T,%s%cntoskrnl.lnk -Wl,--subsystem,native -Wl,--entry,%s -Wl,--image-base,%s -Wl,--file-alignment,0x1000 -Wl,--section-alignment,0x1000 -nostartfiles -shared",
-                                                    module.GetBasePath ().c_str (),
-                                                    cSep,
-                                                    module.GetEntryPoint(true).c_str (),
+               string linkerParameters = ssprintf ( "-Wl,--subsystem,native -Wl,--entry,%s -Wl,--image-base,%s",
+                                                    module.GetEntryPoint(!(Environment::GetArch() == "arm")).c_str (),
                                                     module.baseaddress.c_str () );
+
                GenerateLinkerCommand ( dependencies,
-                                       "${gcc}",
-                                       linkerParameters,
-                                       objectsMacro,
-                                       libsMacro,
-                                       "-sections" );
+                                       linkerParameters + " $(NTOSKRNL_SHARED)",
+                                       " -sections" );
        }
        else
        {
@@ -2465,6 +2634,26 @@ MingwStaticLibraryModuleHandler::GenerateStaticLibraryModuleTarget ()
 }
 
 
+MingwHostStaticLibraryModuleHandler::MingwHostStaticLibraryModuleHandler (
+       const Module& module_ )
+
+       : MingwModuleHandler ( module_ )
+{
+}
+
+void
+MingwHostStaticLibraryModuleHandler::Process ()
+{
+       GenerateHostStaticLibraryModuleTarget ();
+}
+
+void
+MingwHostStaticLibraryModuleHandler::GenerateHostStaticLibraryModuleTarget ()
+{
+       GenerateRules ();
+}
+
+
 MingwObjectLibraryModuleHandler::MingwObjectLibraryModuleHandler (
        const Module& module_ )
 
@@ -2492,7 +2681,7 @@ MingwKernelModeDLLModuleHandler::MingwKernelModeDLLModuleHandler (
 {
 }
 
-MingwTypeLibModuleHandler::MingwTypeLibModuleHandler (
+MingwEmbeddedTypeLibModuleHandler::MingwEmbeddedTypeLibModuleHandler (
        const Module& module_ )
 
        : MingwModuleHandler ( module_ )
@@ -2500,7 +2689,7 @@ MingwTypeLibModuleHandler::MingwTypeLibModuleHandler (
 }
 
 void
-MingwTypeLibModuleHandler::Process ()
+MingwEmbeddedTypeLibModuleHandler::Process ()
 {
        GenerateRules ();
 }
@@ -2523,9 +2712,7 @@ MingwKernelModeDLLModuleHandler::GenerateKernelModeDLLModuleTarget ()
 {
        string targetMacro ( GetTargetMacro ( module ) );
        string workingDirectory = GetWorkingDirectory ( );
-       string objectsMacro = GetObjectsMacro ( module );
        string linkDepsMacro = GetLinkingDependenciesMacro ();
-       string libsMacro = GetLibsMacro ();
 
        GenerateImportLibraryTargetIfNeeded ();
 
@@ -2539,11 +2726,8 @@ MingwKernelModeDLLModuleHandler::GenerateKernelModeDLLModuleTarget ()
                                                     module.GetEntryPoint(true).c_str (),
                                                     module.baseaddress.c_str () );
                GenerateLinkerCommand ( dependencies,
-                                       "${gcc}",
                                        linkerParameters,
-                                       objectsMacro,
-                                       libsMacro,
-                                       "-sections" );
+                                       " -sections" );
        }
        else
        {
@@ -2577,9 +2761,7 @@ MingwKernelModeDriverModuleHandler::GenerateKernelModeDriverModuleTarget ()
 {
        string targetMacro ( GetTargetMacro (module) );
        string workingDirectory = GetWorkingDirectory ();
-       string objectsMacro = GetObjectsMacro ( module );
        string linkDepsMacro = GetLinkingDependenciesMacro ();
-       string libsMacro = GetLibsMacro ();
 
        GenerateImportLibraryTargetIfNeeded ();
 
@@ -2593,11 +2775,8 @@ MingwKernelModeDriverModuleHandler::GenerateKernelModeDriverModuleTarget ()
                                                     module.GetEntryPoint(true).c_str (),
                                                     module.baseaddress.c_str () );
                GenerateLinkerCommand ( dependencies,
-                                       "${gcc}",
                                        linkerParameters,
-                                       objectsMacro,
-                                       libsMacro,
-                                       "-sections" );
+                                       " -sections" );
        }
        else
        {
@@ -2630,9 +2809,7 @@ MingwNativeDLLModuleHandler::GenerateNativeDLLModuleTarget ()
 {
        string targetMacro ( GetTargetMacro (module) );
        string workingDirectory = GetWorkingDirectory ( );
-       string objectsMacro = GetObjectsMacro ( module );
        string linkDepsMacro = GetLinkingDependenciesMacro ();
-       string libsMacro = GetLibsMacro ();
 
        GenerateImportLibraryTargetIfNeeded ();
 
@@ -2646,10 +2823,7 @@ MingwNativeDLLModuleHandler::GenerateNativeDLLModuleTarget ()
                                                     module.GetEntryPoint(true).c_str (),
                                                     module.baseaddress.c_str () );
                GenerateLinkerCommand ( dependencies,
-                                       "${gcc}",
                                        linkerParameters,
-                                       objectsMacro,
-                                       libsMacro,
                                        "" );
        }
        else
@@ -2683,9 +2857,7 @@ MingwNativeCUIModuleHandler::GenerateNativeCUIModuleTarget ()
 {
        string targetMacro ( GetTargetMacro (module) );
        string workingDirectory = GetWorkingDirectory ( );
-       string objectsMacro = GetObjectsMacro ( module );
        string linkDepsMacro = GetLinkingDependenciesMacro ();
-       string libsMacro = GetLibsMacro ();
 
        GenerateImportLibraryTargetIfNeeded ();
 
@@ -2699,10 +2871,7 @@ MingwNativeCUIModuleHandler::GenerateNativeCUIModuleTarget ()
                                                     module.GetEntryPoint(true).c_str (),
                                                     module.baseaddress.c_str () );
                GenerateLinkerCommand ( dependencies,
-                                       "${gcc}",
                                        linkerParameters,
-                                       objectsMacro,
-                                       libsMacro,
                                        "" );
        }
        else
@@ -2726,13 +2895,52 @@ MingwWin32OCXModuleHandler::MingwWin32OCXModuleHandler (
 {
 }
 
+static bool
+LinksToCrt( Module &module )
+{
+       for ( size_t i = 0; i < module.non_if_data.libraries.size (); i++ )
+       {
+               Library& library = *module.non_if_data.libraries[i];
+               if ( library.name == "libcntpr" || library.name == "crt" )
+                       return true;
+       }
+       return false;
+}
+
 static void
 MingwAddImplicitLibraries( Module &module )
 {
        Library* pLibrary;
+       bool links_to_crt;
+
+       if ( module.type != Win32DLL
+         && module.type != Win32OCX
+         && module.type != Win32CUI
+         && module.type != Win32GUI
+         && module.type != Win32SCR )
+       {
+               // no implicit libraries
+               return;
+       }
+
+       links_to_crt = LinksToCrt ( module );
 
        if ( !module.isDefaultEntryPoint )
+       {
+               if ( module.GetEntryPoint(false) == "0" )
+               {
+                       if ( !links_to_crt )
+                       {
+                               pLibrary = new Library ( module, "mingw_common" );
+                               module.non_if_data.libraries.insert ( module.non_if_data.libraries.begin() , pLibrary );
+
+                               pLibrary = new Library ( module, "msvcrt" );
+                               module.non_if_data.libraries.push_back ( pLibrary );
+                               links_to_crt = true;
+                       }
+               }
                return;
+       }
 
        if ( module.IsDLL () )
        {
@@ -2748,7 +2956,7 @@ MingwAddImplicitLibraries( Module &module )
        pLibrary = new Library ( module, "mingw_common" );
        module.non_if_data.libraries.insert ( module.non_if_data.libraries.begin() + 1, pLibrary );
 
-       if ( module.name != "msvcrt" )
+       if ( !links_to_crt )
        {
                // always link in msvcrt to get the basic routines
                pLibrary = new Library ( module, "msvcrt" );
@@ -2774,9 +2982,7 @@ MingwWin32DLLModuleHandler::GenerateWin32DLLModuleTarget ()
 {
        string targetMacro ( GetTargetMacro (module) );
        string workingDirectory = GetWorkingDirectory ( );
-       string objectsMacro = GetObjectsMacro ( module );
        string linkDepsMacro = GetLinkingDependenciesMacro ();
-       string libsMacro = GetLibsMacro ();
 
        GenerateImportLibraryTargetIfNeeded ();
 
@@ -2786,20 +2992,11 @@ MingwWin32DLLModuleHandler::GenerateWin32DLLModuleTarget ()
 
                string dependencies = linkDepsMacro + " " + objectsMacro;
 
-               string linker;
-               if ( module.cplusplus )
-                       linker = "${gpp}";
-               else
-                       linker = "${gcc}";
-
                string linkerParameters = ssprintf ( "-Wl,--subsystem,console -Wl,--entry,%s -Wl,--image-base,%s -Wl,--file-alignment,0x1000 -Wl,--section-alignment,0x1000 -shared",
                                                     module.GetEntryPoint(true).c_str (),
                                                     module.baseaddress.c_str () );
                GenerateLinkerCommand ( dependencies,
-                                       linker,
                                        linkerParameters,
-                                       objectsMacro,
-                                       libsMacro,
                                        "" );
        }
        else
@@ -2827,9 +3024,7 @@ MingwWin32OCXModuleHandler::GenerateWin32OCXModuleTarget ()
 {
        string targetMacro ( GetTargetMacro (module) );
        string workingDirectory = GetWorkingDirectory ( );
-       string objectsMacro = GetObjectsMacro ( module );
        string linkDepsMacro = GetLinkingDependenciesMacro ();
-       string libsMacro = GetLibsMacro ();
 
        GenerateImportLibraryTargetIfNeeded ();
 
@@ -2839,20 +3034,11 @@ MingwWin32OCXModuleHandler::GenerateWin32OCXModuleTarget ()
 
                string dependencies = linkDepsMacro + " " + objectsMacro;
 
-               string linker;
-               if ( module.cplusplus )
-                       linker = "${gpp}";
-               else
-                       linker = "${gcc}";
-
                string linkerParameters = ssprintf ( "-Wl,--subsystem,console -Wl,--entry,%s -Wl,--image-base,%s -Wl,--file-alignment,0x1000 -Wl,--section-alignment,0x1000 -shared",
                                                     module.GetEntryPoint(true).c_str (),
                                                     module.baseaddress.c_str () );
                GenerateLinkerCommand ( dependencies,
-                                       linker,
                                        linkerParameters,
-                                       objectsMacro,
-                                       libsMacro,
                                        "" );
        }
        else
@@ -2887,9 +3073,7 @@ MingwWin32CUIModuleHandler::GenerateWin32CUIModuleTarget ()
 {
        string targetMacro ( GetTargetMacro (module) );
        string workingDirectory = GetWorkingDirectory ( );
-       string objectsMacro = GetObjectsMacro ( module );
        string linkDepsMacro = GetLinkingDependenciesMacro ();
-       string libsMacro = GetLibsMacro ();
 
        GenerateImportLibraryTargetIfNeeded ();
 
@@ -2899,20 +3083,11 @@ MingwWin32CUIModuleHandler::GenerateWin32CUIModuleTarget ()
 
                string dependencies = linkDepsMacro + " " + objectsMacro;
 
-               string linker;
-               if ( module.cplusplus )
-                       linker = "${gpp}";
-               else
-                       linker = "${gcc}";
-
                string linkerParameters = ssprintf ( "-Wl,--subsystem,console -Wl,--entry,%s -Wl,--image-base,%s -Wl,--file-alignment,0x1000 -Wl,--section-alignment,0x1000",
                                                     module.GetEntryPoint(true).c_str (),
                                                     module.baseaddress.c_str () );
                GenerateLinkerCommand ( dependencies,
-                                       linker,
                                        linkerParameters,
-                                       objectsMacro,
-                                       libsMacro,
                                        "" );
        }
        else
@@ -2947,9 +3122,7 @@ MingwWin32GUIModuleHandler::GenerateWin32GUIModuleTarget ()
 {
        string targetMacro ( GetTargetMacro (module) );
        string workingDirectory = GetWorkingDirectory ( );
-       string objectsMacro = GetObjectsMacro ( module );
        string linkDepsMacro = GetLinkingDependenciesMacro ();
-       string libsMacro = GetLibsMacro ();
 
        GenerateImportLibraryTargetIfNeeded ();
 
@@ -2959,20 +3132,11 @@ MingwWin32GUIModuleHandler::GenerateWin32GUIModuleTarget ()
 
                string dependencies = linkDepsMacro + " " + objectsMacro;
 
-               string linker;
-               if ( module.cplusplus )
-                       linker = "${gpp}";
-               else
-                       linker = "${gcc}";
-
                string linkerParameters = ssprintf ( "-Wl,--subsystem,windows -Wl,--entry,%s -Wl,--image-base,%s -Wl,--file-alignment,0x1000 -Wl,--section-alignment,0x1000",
                                                     module.GetEntryPoint(true).c_str (),
                                                     module.baseaddress.c_str () );
                GenerateLinkerCommand ( dependencies,
-                                       linker,
                                        linkerParameters,
-                                       objectsMacro,
-                                       libsMacro,
                                        "" );
        }
        else
@@ -2998,10 +3162,12 @@ MingwBootLoaderModuleHandler::Process ()
 void
 MingwBootLoaderModuleHandler::GenerateBootLoaderModuleTarget ()
 {
-       string targetName ( module.GetTargetName () );
+       string targetName ( module.output->name );
        string targetMacro ( GetTargetMacro (module) );
        string workingDirectory = GetWorkingDirectory ();
-       string junk_tmp = ros_temp + module.name + ".junk.tmp";
+       FileLocation junk_tmp ( TemporaryDirectory,
+                               "",
+                               module.name + ".junk.tmp" );
        CLEAN_FILE ( junk_tmp );
        string objectsMacro = GetObjectsMacro ( module );
        string linkDepsMacro = GetLinkingDependenciesMacro ();
@@ -3009,27 +3175,42 @@ MingwBootLoaderModuleHandler::GenerateBootLoaderModuleTarget ()
 
        GenerateRules ();
 
+       const FileLocation *target_file = GetTargetFilename ( module, NULL );
        fprintf ( fMakefile, "%s: %s %s | %s\n",
                  targetMacro.c_str (),
                  objectsMacro.c_str (),
                  linkDepsMacro.c_str (),
-                 GetDirectory(GetTargetFilename(module,NULL)).c_str () );
+                 backend->GetFullPath ( *target_file ).c_str () );
 
        fprintf ( fMakefile, "\t$(ECHO_LD)\n" );
 
-       fprintf ( fMakefile,
-                 "\t${ld} %s -N -Ttext=0x8000 -o %s %s %s\n",
-                 GetLinkerMacro ().c_str (),
-                 junk_tmp.c_str (),
-                 objectsMacro.c_str (),
-                 linkDepsMacro.c_str () );
+       if (Environment::GetArch() == "arm")
+       {
+               fprintf ( fMakefile,
+                        "\t${gcc} -Wl,--subsystem,native -Wl,--section-start,startup=0x8000 -o %s %s %s %s\n",
+                        backend->GetFullName ( junk_tmp ).c_str (),
+                        objectsMacro.c_str (),
+                        linkDepsMacro.c_str (),
+                        GetLinkerMacro ().c_str ());
+       }
+       else
+       {
+               fprintf ( fMakefile,
+                        "\t${gcc} -Wl,--subsystem,native -Wl,-Ttext,0x8000 -o %s %s %s %s\n",
+                        backend->GetFullName ( junk_tmp ).c_str (),
+                        objectsMacro.c_str (),
+                        linkDepsMacro.c_str (),
+                        GetLinkerMacro ().c_str ());
+       }
        fprintf ( fMakefile,
                  "\t${objcopy} -O binary %s $@\n",
-                 junk_tmp.c_str () );
-       GenerateBuildMapCode ( junk_tmp.c_str() );
+                 backend->GetFullName ( junk_tmp ).c_str () );
+       GenerateBuildMapCode ( &junk_tmp );
        fprintf ( fMakefile,
                  "\t-@${rm} %s 2>$(NUL)\n",
-                 junk_tmp.c_str () );
+                 backend->GetFullName ( junk_tmp ).c_str () );
+
+       delete target_file;
 }
 
 
@@ -3077,12 +3258,18 @@ MingwBootProgramModuleHandler::Process ()
 void
 MingwBootProgramModuleHandler::GenerateBootProgramModuleTarget ()
 {
-       string targetName ( module.GetTargetName () );
+       string targetName ( module.output->name );
        string targetMacro ( GetTargetMacro (module) );
        string workingDirectory = GetWorkingDirectory ();
-       string junk_tmp = ros_temp + module.name + ".junk.tmp";
-       string junk_elf = ros_temp + module.name + ".junk.elf";
-       string junk_cpy = ros_temp + module.name + ".junk.cpy";
+       FileLocation junk_tmp ( TemporaryDirectory,
+                               "",
+                               module.name + ".junk.tmp" );
+       FileLocation junk_elf ( TemporaryDirectory,
+                               "",
+                               module.name + ".junk.elf" );
+       FileLocation junk_cpy ( TemporaryDirectory,
+                               "",
+                               module.name + ".junk.elf" );
        CLEAN_FILE ( junk_tmp );
        CLEAN_FILE ( junk_elf );
        CLEAN_FILE ( junk_cpy );
@@ -3093,35 +3280,44 @@ MingwBootProgramModuleHandler::GenerateBootProgramModuleTarget ()
 
        GenerateRules ();
 
+       const FileLocation *target_file = GetTargetFilename ( module, NULL );
        fprintf ( fMakefile, "%s: %s %s %s | %s\n",
                  targetMacro.c_str (),
                  objectsMacro.c_str (),
                  linkDepsMacro.c_str (),
-                 payload->name.c_str (),
-                 GetDirectory(GetTargetFilename(module,NULL)).c_str () );
+                 payload->name.c_str (),
+                 backend->GetFullPath ( *target_file ).c_str () );
 
        fprintf ( fMakefile, "\t$(ECHO_BOOTPROG)\n" );
 
-       fprintf ( fMakefile, "\t$(BOOTPROG_PREPARE) $(OUTPUT)$(SEP)%s %s\n",
-                 NormalizeFilename( payload->GetPath() ).c_str (),
-               junk_cpy.c_str () );
+       fprintf ( fMakefile, "\t$(%s_PREPARE) $(OUTPUT)$(SEP)%s %s\n",
+               module.buildtype.c_str (),
+               NormalizeFilename( backend->GetFullName ( *payload->output ) ).c_str (),
+               backend->GetFullName ( junk_cpy ).c_str () );
 
-       fprintf ( fMakefile, "\t${objcopy} $(BOOTPROG_FLATFORMAT) %s %s\n",
-               junk_cpy.c_str (),
-               junk_tmp.c_str () );
+       fprintf ( fMakefile, "\t${objcopy} $(%s_FLATFORMAT) %s %s\n",
+               module.buildtype.c_str (),
+               backend->GetFullName ( junk_cpy ).c_str (),
+               backend->GetFullName ( junk_tmp ).c_str () );
 
-       fprintf ( fMakefile, "\t${ld} $(BOOTPROG_LINKFORMAT) %s %s -g -o %s\n",
+       fprintf ( fMakefile, "\t${ld} $(%s_LINKFORMAT) %s %s -g -o %s\n",
+               module.buildtype.c_str (),
                linkDepsMacro.c_str (),
-               junk_tmp.c_str (),
-               junk_elf.c_str () );
+               backend->GetFullName ( junk_tmp ).c_str (),
+               backend->GetFullName ( junk_elf ).c_str () );
 
-       fprintf ( fMakefile, "\t${objcopy} $(BOOTPROG_COPYFORMAT) %s %s\n",
-               junk_elf.c_str (),
-               module.GetPath().c_str () );
+       fprintf ( fMakefile, "\t${objcopy} $(%s_COPYFORMAT) %s $(INTERMEDIATE)$(SEP)%s\n",
+               module.buildtype.c_str (),
+               backend->GetFullName ( junk_elf ).c_str (),
+               backend->GetFullName ( *module.output ) .c_str () );
 
        fprintf ( fMakefile,
                  "\t-@${rm} %s %s %s 2>$(NUL)\n",
-                 junk_tmp.c_str (), junk_elf.c_str (), junk_cpy.c_str () );
+                 backend->GetFullName ( junk_tmp ).c_str (),
+                 backend->GetFullName ( junk_elf ).c_str (),
+                 backend->GetFullName ( junk_cpy ).c_str () );
+
+       delete target_file;
 }
 
 
@@ -3149,19 +3345,12 @@ MingwIsoModuleHandler::OutputBootstrapfileCopyCommands (
                        continue;
                if ( m.bootstrap != NULL )
                {
-                       string sourceFilename = PassThruCacheDirectory (
-                               NormalizeFilename ( m.GetPath () ),
-                               backend->outputDirectory );
-                       string targetFilenameNoFixup ( bootcdDirectory + sSep + m.bootstrap->base + sSep + m.bootstrap->nameoncd );
-                       string targetFilename = MingwModuleHandler::PassThruCacheDirectory (
-                               NormalizeFilename ( targetFilenameNoFixup ),
-                               backend->outputDirectory );
-                       fprintf ( fMakefile,
-                                 "\t$(ECHO_CP)\n" );
-                       fprintf ( fMakefile,
-                                 "\t${cp} %s %s 1>$(NUL)\n",
-                                 sourceFilename.c_str (),
-                                 targetFilename.c_str () );
+                       FileLocation targetFile ( OutputDirectory,
+                                                 m.bootstrap->base.length () > 0
+                                                          ? bootcdDirectory + sSep + m.bootstrap->base
+                                                          : bootcdDirectory,
+                                                 m.bootstrap->nameoncd );
+                       OutputCopyCommand ( *m.output, targetFile );
                }
        }
 }
@@ -3173,23 +3362,19 @@ MingwIsoModuleHandler::OutputCdfileCopyCommands (
        for ( size_t i = 0; i < module.project.cdfiles.size (); i++ )
        {
                const CDFile& cdfile = *module.project.cdfiles[i];
-               string targetFilenameNoFixup = bootcdDirectory + sSep + cdfile.base + sSep + cdfile.nameoncd;
-               string targetFilename = MingwModuleHandler::PassThruCacheDirectory (
-                       NormalizeFilename ( targetFilenameNoFixup ),
-                       backend->outputDirectory );
-               fprintf ( fMakefile,
-                         "\t$(ECHO_CP)\n" );
-               fprintf ( fMakefile,
-                         "\t${cp} %s %s 1>$(NUL)\n",
-                         cdfile.GetPath ().c_str (),
-                         targetFilename.c_str () );
+               FileLocation targetFile ( OutputDirectory,
+                                         cdfile.target->relative_path.length () > 0
+                                             ? bootcdDirectory + sSep + cdfile.target->relative_path
+                                             : bootcdDirectory,
+                                         cdfile.target->name );
+               OutputCopyCommand ( *cdfile.source, targetFile );
        }
 }
 
-string
-MingwIsoModuleHandler::GetBootstrapCdDirectories ( const string& bootcdDirectory )
+void
+MingwIsoModuleHandler::GetBootstrapCdDirectories ( vector<FileLocation>& out,
+                                                   const string& bootcdDirectory )
 {
-       string directories;
        for ( size_t i = 0; i < module.project.modules.size (); i++ )
        {
                const Module& m = *module.project.modules[i];
@@ -3197,45 +3382,43 @@ MingwIsoModuleHandler::GetBootstrapCdDirectories ( const string& bootcdDirectory
                        continue;
                if ( m.bootstrap != NULL )
                {
-                       string targetDirectory ( bootcdDirectory + sSep + m.bootstrap->base );
-                       if ( directories.size () > 0 )
-                               directories += " ";
-                       directories += PassThruCacheDirectory (
-                               NormalizeFilename ( targetDirectory ),
-                               backend->outputDirectory );
+                       FileLocation targetDirectory ( OutputDirectory,
+                                                      m.bootstrap->base.length () > 0
+                                                          ? bootcdDirectory + sSep + m.bootstrap->base
+                                                          : bootcdDirectory,
+                                                      "" );
+                       out.push_back ( targetDirectory );
                }
        }
-       return directories;
 }
 
-string
-MingwIsoModuleHandler::GetNonModuleCdDirectories ( const string& bootcdDirectory )
+void
+MingwIsoModuleHandler::GetNonModuleCdDirectories ( vector<FileLocation>& out,
+                                                   const string& bootcdDirectory )
 {
-       string directories;
        for ( size_t i = 0; i < module.project.cdfiles.size (); i++ )
        {
                const CDFile& cdfile = *module.project.cdfiles[i];
-               string targetDirectory ( bootcdDirectory + sSep + cdfile.base );
-               if ( directories.size () > 0 )
-                       directories += " ";
-               directories += PassThruCacheDirectory (
-                       NormalizeFilename ( targetDirectory ),
-                       backend->outputDirectory );
+               FileLocation targetDirectory ( OutputDirectory,
+                                              cdfile.target->relative_path.length () > 0
+                                                  ? bootcdDirectory + sSep + cdfile.target->relative_path
+                                                  : bootcdDirectory,
+                                              "" );
+               out.push_back( targetDirectory );
        }
-       return directories;
 }
 
-string
-MingwIsoModuleHandler::GetCdDirectories ( const string& bootcdDirectory )
+void
+MingwIsoModuleHandler::GetCdDirectories ( vector<FileLocation>& out,
+                                          const string& bootcdDirectory )
 {
-       string directories = GetBootstrapCdDirectories ( bootcdDirectory );
-       directories += " " + GetNonModuleCdDirectories ( bootcdDirectory );
-       return directories;
+       GetBootstrapCdDirectories ( out, bootcdDirectory );
+       GetNonModuleCdDirectories ( out, bootcdDirectory );
 }
 
 void
 MingwIsoModuleHandler::GetBootstrapCdFiles (
-       vector<string>& out ) const
+       vector<FileLocation>& out ) const
 {
        for ( size_t i = 0; i < module.project.modules.size (); i++ )
        {
@@ -3244,28 +3427,25 @@ MingwIsoModuleHandler::GetBootstrapCdFiles (
                        continue;
                if ( m.bootstrap != NULL )
                {
-                       string filename = PassThruCacheDirectory (
-                               NormalizeFilename ( m.GetPath () ),
-                               backend->outputDirectory );
-                       out.push_back ( filename );
+                       out.push_back ( *m.output );
                }
        }
 }
 
 void
 MingwIsoModuleHandler::GetNonModuleCdFiles (
-       vector<string>& out ) const
+       vector<FileLocation>& out ) const
 {
        for ( size_t i = 0; i < module.project.cdfiles.size (); i++ )
        {
                const CDFile& cdfile = *module.project.cdfiles[i];
-               out.push_back ( cdfile.GetPath () );
+               out.push_back ( *cdfile.source );
        }
 }
 
 void
 MingwIsoModuleHandler::GetCdFiles (
-       vector<string>& out ) const
+       vector<FileLocation>& out ) const
 {
        GetBootstrapCdFiles ( out );
        GetNonModuleCdFiles ( out );
@@ -3275,72 +3455,92 @@ void
 MingwIsoModuleHandler::GenerateIsoModuleTarget ()
 {
        string bootcdDirectory = "cd";
-       string bootcd = PassThruCacheDirectory (
-               NormalizeFilename ( bootcdDirectory + sSep ),
-               backend->outputDirectory );
+       FileLocation bootcd ( OutputDirectory,
+                             bootcdDirectory,
+                             "" );
+       FileLocation bootcdReactos ( OutputDirectory,
+                                    bootcdDirectory + sSep + Environment::GetCdOutputPath (),
+                                    "" );
+       vector<FileLocation> vSourceFiles, vCdFiles;
+       vector<FileLocation> vCdDirectories;
+
+       // unattend.inf
+       FileLocation srcunattend ( SourceDirectory,
+                                  "boot" + sSep + "bootdata" + sSep + "bootcdregtest",
+                                  "unattend.inf" );
+       FileLocation tarunattend ( bootcdReactos.directory,
+                                  bootcdReactos.relative_path,
+                                  "unattend.inf" );
+       if (module.type == IsoRegTest)
+               vSourceFiles.push_back ( srcunattend );
+
+       // bootsector
+       const Module* bootModule;
+       bootModule = module.project.LocateModule ( module.type == IsoRegTest
+                                                      ? "isobtrt"
+                                                      : "isoboot" );
+       const FileLocation *isoboot = bootModule->output;
+       vSourceFiles.push_back ( *isoboot );
+
+       // prepare reactos.dff and reactos.inf
+       FileLocation reactosDff ( SourceDirectory,
+                                 "boot" + sSep + "bootdata" + sSep + "packages",
+                                 "reactos.dff" );
+       FileLocation reactosInf ( bootcdReactos.directory,
+                                 bootcdReactos.relative_path,
+                                 "reactos.inf" );
+
+       vSourceFiles.push_back ( reactosDff );
 
-       string bootloader;
        string IsoName;
 
-       if (module.name == "bootcdregtest")
-       {
-               bootloader = "isobtrt.o";
+       if (module.type == IsoRegTest)
                IsoName = "ReactOS-RegTest.iso";
-       }
        else
-       {
-               bootloader = "isoboot.o";
                IsoName = "ReactOS.iso";
-       }
 
-       string isoboot = PassThruCacheDirectory (
-               NormalizeFilename ( "boot" + sSep + "freeldr" + sSep + "bootsect" + sSep + bootloader.c_str() ),
-               backend->outputDirectory );
-
-       string bootcdReactosNoFixup = bootcdDirectory + sSep + Environment::GetCdOutputPath ();
-       string bootcdReactos = PassThruCacheDirectory (
-               NormalizeFilename ( bootcdReactosNoFixup + sSep ),
-               backend->outputDirectory );
-       CLEAN_FILE ( bootcdReactos );
-       string reactosInf = PassThruCacheDirectory (
-               NormalizeFilename ( bootcdReactosNoFixup + sSep + "reactos.inf" ),
-               backend->outputDirectory );
-       string reactosDff = NormalizeFilename ( "boot" + sSep + "bootdata" + sSep + "packages" + sSep + "reactos.dff" );
-       string cdDirectories = GetCdDirectories ( bootcdDirectory );
-       vector<string> vCdFiles;
+
+       string sourceFiles = v2s ( backend, vSourceFiles, 5 );
+
+       // fill cdrom
+       GetCdDirectories ( vCdDirectories, bootcdDirectory );
        GetCdFiles ( vCdFiles );
-       string cdFiles = v2s ( vCdFiles, 5 );
+       string cdDirectories = "";//v2s ( vCdDirectories, 5 );
+       string cdFiles = v2s ( backend, vCdFiles, 5 );
 
        fprintf ( fMakefile, ".PHONY: %s\n\n",
                  module.name.c_str ());
        fprintf ( fMakefile,
-                 "%s: all %s %s %s %s $(CABMAN_TARGET) $(CDMAKE_TARGET)\n",
+                 "%s: all %s %s %s $(CABMAN_TARGET) $(CDMAKE_TARGET) %s\n",
                  module.name.c_str (),
-                 isoboot.c_str (),
-                 bootcdReactos.c_str (),
-                 cdDirectories.c_str (),
-                 cdFiles.c_str () );
-       fprintf ( fMakefile, "\t$(ECHO_CABMAN)\n" );
+                 backend->GetFullName ( *isoboot ).c_str (),
+                 sourceFiles.c_str (),
+                 cdFiles.c_str (),
+                 cdDirectories.c_str () );
        fprintf ( fMakefile,
                  "\t$(Q)$(CABMAN_TARGET) -C %s -L %s -I -P $(OUTPUT)\n",
-                 reactosDff.c_str (),
-                 bootcdReactos.c_str () );
+                 backend->GetFullName ( reactosDff ).c_str (),
+                 backend->GetFullPath ( bootcdReactos ).c_str () );
        fprintf ( fMakefile,
                  "\t$(Q)$(CABMAN_TARGET) -C %s -RC %s -L %s -N -P $(OUTPUT)\n",
-                 reactosDff.c_str (),
-                 reactosInf.c_str (),
-                 bootcdReactos.c_str ());
+                 backend->GetFullName ( reactosDff ).c_str (),
+                 backend->GetFullName ( reactosInf ).c_str (),
+                 backend->GetFullPath ( bootcdReactos ).c_str ());
        fprintf ( fMakefile,
                  "\t-@${rm} %s 2>$(NUL)\n",
-                 reactosInf.c_str () );
+                 backend->GetFullName ( reactosInf ).c_str () );
        OutputBootstrapfileCopyCommands ( bootcdDirectory );
        OutputCdfileCopyCommands ( bootcdDirectory );
+
+       if (module.type == IsoRegTest)
+               OutputCopyCommand ( srcunattend, tarunattend );
+
        fprintf ( fMakefile, "\t$(ECHO_CDMAKE)\n" );
        fprintf ( fMakefile,
                  "\t$(Q)$(CDMAKE_TARGET) -v -j -m -b %s %s REACTOS %s\n",
-                 isoboot.c_str (),
-                 bootcd.c_str (),
-                         IsoName.c_str() );
+                 backend->GetFullName ( *isoboot ).c_str (),
+                 backend->GetFullPath ( bootcd ).c_str (),
+                 IsoName.c_str() );
        fprintf ( fMakefile,
                  "\n" );
 }
@@ -3362,25 +3562,10 @@ MingwLiveIsoModuleHandler::Process ()
 void
 MingwLiveIsoModuleHandler::CreateDirectory ( const string& directory )
 {
-       string normalizedDirectory = MingwModuleHandler::PassThruCacheDirectory (
-               NormalizeFilename ( directory ) + sSep,
-               backend->outputDirectory );
-}
-
-void
-MingwLiveIsoModuleHandler::OutputCopyCommand ( const string& sourceFilename,
-                                               const string& targetFilename,
-                                               const string& targetDirectory )
-{
-       string normalizedTargetFilename = MingwModuleHandler::PassThruCacheDirectory (
-               NormalizeFilename ( targetDirectory + sSep + targetFilename ),
-               backend->outputDirectory );
-       fprintf ( fMakefile,
-                 "\t$(ECHO_CP)\n" );
-       fprintf ( fMakefile,
-                 "\t${cp} %s %s 1>$(NUL)\n",
-                 sourceFilename.c_str (),
-                 normalizedTargetFilename.c_str () );
+       FileLocation dir ( OutputDirectory,
+                          directory,
+                          "" );
+       MingwModuleHandler::PassThruCacheDirectory ( &dir );
 }
 
 void
@@ -3392,15 +3577,16 @@ MingwLiveIsoModuleHandler::OutputModuleCopyCommands ( string& livecdDirectory,
                const Module& m = *module.project.modules[i];
                if ( !m.enabled )
                        continue;
-               if ( m.installName.length () > 0 )
+               if ( m.install )
                {
                        const Module& aliasedModule = backend->GetAliasedModuleOrModule ( m  );
-                       string sourceFilename = MingwModuleHandler::PassThruCacheDirectory (
-                               NormalizeFilename ( aliasedModule.GetPath () ),
-                               backend->outputDirectory );
-                       OutputCopyCommand ( sourceFilename,
-                                           m.installName,
-                                           livecdDirectory + sSep + reactosDirectory + sSep + m.installBase );
+                       FileLocation destination ( OutputDirectory,
+                                                  m.install->relative_path.length () > 0
+                                                      ? livecdDirectory + sSep + reactosDirectory + sSep + m.install->relative_path
+                                                      : livecdDirectory + sSep + reactosDirectory,
+                                                  m.install->name );
+                       OutputCopyCommand ( *aliasedModule.output,
+                                           destination);
                }
        }
 }
@@ -3412,9 +3598,12 @@ MingwLiveIsoModuleHandler::OutputNonModuleCopyCommands ( string& livecdDirectory
        for ( size_t i = 0; i < module.project.installfiles.size (); i++ )
        {
                const InstallFile& installfile = *module.project.installfiles[i];
-               OutputCopyCommand ( installfile.GetPath (),
-                               installfile.newname,
-                               livecdDirectory + sSep + reactosDirectory + sSep + installfile.base );
+               FileLocation target ( OutputDirectory,
+                                     installfile.target->relative_path.length () > 0
+                                         ? livecdDirectory + sSep + reactosDirectory + sSep + installfile.target->relative_path
+                                         : livecdDirectory + sSep + reactosDirectory,
+                                     installfile.target->name );
+               OutputCopyCommand ( *installfile.source, target );
        }
 }
 
@@ -3428,36 +3617,40 @@ MingwLiveIsoModuleHandler::OutputProfilesDirectoryCommands ( string& livecdDirec
        CreateDirectory ( livecdDirectory + sSep + "Profiles" + sSep + "Default User" + sSep + "Desktop" );
        CreateDirectory ( livecdDirectory + sSep + "Profiles" + sSep + "Default User" + sSep + "My Documents" );
 
-       string livecdIni = "boot" + sSep + "bootdata" + sSep + "livecd.ini";
+       FileLocation livecdIni ( SourceDirectory,
+                                "boot" + sSep + "bootdata",
+                                "livecd.ini" );
+       FileLocation destination ( OutputDirectory,
+                                  livecdDirectory,
+                                  "freeldr.ini" );
        OutputCopyCommand ( livecdIni,
-                           "freeldr.ini",
-                           livecdDirectory );
+                           destination );
 }
 
 void
 MingwLiveIsoModuleHandler::OutputLoaderCommands ( string& livecdDirectory )
 {
-       string freeldr = PassThruCacheDirectory (
-               NormalizeFilename ( "boot" + sSep + "freeldr" + sSep + "freeldr" + sSep + "freeldr.sys" ),
-               backend->outputDirectory );
-       CreateDirectory ( livecdDirectory + sSep + "loader" );
+       FileLocation freeldr ( OutputDirectory,
+                              "boot" + sSep + "freeldr" + sSep + "freeldr",
+                              "freeldr.sys" );
+       FileLocation destination ( OutputDirectory,
+                                  livecdDirectory + sSep + "loader",
+                                  "setupldr.sys" );
        OutputCopyCommand ( freeldr,
-                          "setupldr.sys",
-                          livecdDirectory + sSep + "loader" );
+                           destination );
 }
 
 void
 MingwLiveIsoModuleHandler::OutputRegistryCommands ( string& livecdDirectory )
 {
-       string reactosSystem32ConfigDirectory = NormalizeFilename (
-               MingwModuleHandler::PassThruCacheDirectory (
-               livecdDirectory + sSep + "reactos" + sSep + "system32" + sSep + "config" + sSep,
-               backend->outputDirectory ) );
+       FileLocation reactosSystem32ConfigDirectory ( OutputDirectory,
+                                                     livecdDirectory + sSep + "reactos" + sSep + "system32" + sSep + "config",
+                                                     "" );
        fprintf ( fMakefile,
                  "\t$(ECHO_MKHIVE)\n" );
        fprintf ( fMakefile,
                  "\t$(MKHIVE_TARGET) boot%cbootdata %s boot%cbootdata%clivecd.inf boot%cbootdata%chiveinst.inf\n",
-                 cSep, reactosSystem32ConfigDirectory.c_str (),
+                 cSep, backend->GetFullPath ( reactosSystem32ConfigDirectory ).c_str (),
                  cSep, cSep, cSep, cSep );
 }
 
@@ -3465,33 +3658,25 @@ void
 MingwLiveIsoModuleHandler::GenerateLiveIsoModuleTarget ()
 {
        string livecdDirectory = module.name;
-       string livecd = PassThruCacheDirectory (
-               NormalizeFilename ( livecdDirectory + sSep ),
-               backend->outputDirectory );
+       FileLocation livecd ( OutputDirectory, livecdDirectory, "" );
 
-       string bootloader;
        string IsoName;
 
+       const Module* bootModule;
+       bootModule = module.project.LocateModule ( module.name == "livecdregtest"
+                                                      ? "isobtrt"
+                                                      : "isoboot" );
+       const FileLocation *isoboot = bootModule->output;
        if (module.name == "livecdregtest")
-       {
-               bootloader = "isobtrt.o";
                IsoName = "ReactOS-LiveCD-RegTest.iso";
-       }
        else
-       {
-               bootloader = "isoboot.o";
                IsoName = "ReactOS-LiveCD.iso";
-       }
-
-       string isoboot = PassThruCacheDirectory (
-               NormalizeFilename ( "boot" + sSep + "freeldr" + sSep + "bootsect" + sSep + bootloader.c_str() ),
-               backend->outputDirectory );
 
        string reactosDirectory = "reactos";
        string livecdReactosNoFixup = livecdDirectory + sSep + reactosDirectory;
-       string livecdReactos = NormalizeFilename ( PassThruCacheDirectory (
-               NormalizeFilename ( livecdReactosNoFixup + sSep ),
-               backend->outputDirectory ) );
+       FileLocation livecdReactos ( OutputDirectory,
+                                    livecdReactosNoFixup,
+                                    "" );
        CLEAN_FILE ( livecdReactos );
 
        fprintf ( fMakefile, ".PHONY: %s\n\n",
@@ -3499,8 +3684,8 @@ MingwLiveIsoModuleHandler::GenerateLiveIsoModuleTarget ()
        fprintf ( fMakefile,
                  "%s: all %s %s $(MKHIVE_TARGET) $(CDMAKE_TARGET)\n",
                  module.name.c_str (),
-                 isoboot.c_str (),
-                 livecdReactos.c_str () );
+                 backend->GetFullName ( *isoboot) .c_str (),
+                 backend->GetFullPath ( livecdReactos ).c_str () );
        OutputModuleCopyCommands ( livecdDirectory,
                                   reactosDirectory );
        OutputNonModuleCopyCommands ( livecdDirectory,
@@ -3511,9 +3696,9 @@ MingwLiveIsoModuleHandler::GenerateLiveIsoModuleTarget ()
        fprintf ( fMakefile, "\t$(ECHO_CDMAKE)\n" );
        fprintf ( fMakefile,
                  "\t$(Q)$(CDMAKE_TARGET) -v -m -j -b %s %s REACTOS %s\n",
-                 isoboot.c_str (),
-                 livecd.c_str (),
-                         IsoName.c_str() );
+                 backend->GetFullName( *isoboot ).c_str (),
+                 backend->GetFullPath ( livecd ).c_str (),
+                 IsoName.c_str() );
        fprintf ( fMakefile,
                  "\n" );
 }
@@ -3532,13 +3717,13 @@ MingwTestModuleHandler::Process ()
        GenerateTestModuleTarget ();
 }
 
+/* caller needs to delete the returned object */
 void
 MingwTestModuleHandler::GetModuleSpecificCompilationUnits ( vector<CompilationUnit*>& compilationUnits )
 {
-       string basePath = "$(INTERMEDIATE)" + sSep + module.GetBasePath ();
-       compilationUnits.push_back ( new CompilationUnit ( new File ( basePath + sSep + "_hooks.c", false, "", false ) ) );
-       compilationUnits.push_back ( new CompilationUnit ( new File ( basePath + sSep + "_stubs.S", false, "", false ) ) );
-       compilationUnits.push_back ( new CompilationUnit ( new File ( basePath + sSep + "_startup.c", false, "", false ) ) );
+       compilationUnits.push_back ( new CompilationUnit ( new File ( IntermediateDirectory, module.output->relative_path + sSep + "..", module.name + "_hooks.c", false, "", false ) ) );
+       compilationUnits.push_back ( new CompilationUnit ( new File ( IntermediateDirectory, module.output->relative_path + sSep + "..", module.name + "_stubs.S", false, "", false ) ) );
+       compilationUnits.push_back ( new CompilationUnit ( new File ( IntermediateDirectory, module.output->relative_path + sSep + "..", module.name + "_startup.c", false, "", false ) ) );
 }
 
 void
@@ -3546,9 +3731,7 @@ MingwTestModuleHandler::GenerateTestModuleTarget ()
 {
        string targetMacro ( GetTargetMacro ( module ) );
        string workingDirectory = GetWorkingDirectory ( );
-       string objectsMacro = GetObjectsMacro ( module );
        string linkDepsMacro = GetLinkingDependenciesMacro ();
-       string libsMacro = GetLibsMacro ();
 
        GenerateImportLibraryTargetIfNeeded ();
 
@@ -3558,20 +3741,11 @@ MingwTestModuleHandler::GenerateTestModuleTarget ()
 
                string dependencies = linkDepsMacro + " " + objectsMacro;
 
-               string linker;
-               if ( module.cplusplus )
-                       linker = "${gpp}";
-               else
-                       linker = "${gcc}";
-
                string linkerParameters = ssprintf ( "-Wl,--subsystem,console -Wl,--entry,%s -Wl,--image-base,%s -Wl,--file-alignment,0x1000 -Wl,--section-alignment,0x1000",
                                                     module.GetEntryPoint(true).c_str (),
                                                     module.baseaddress.c_str () );
                GenerateLinkerCommand ( dependencies,
-                                       linker,
                                        linkerParameters,
-                                       objectsMacro,
-                                       libsMacro,
                                        "" );
        }
        else
@@ -3609,6 +3783,20 @@ MingwRpcClientModuleHandler::Process ()
 }
 
 
+MingwRpcProxyModuleHandler::MingwRpcProxyModuleHandler (
+       const Module& module_ )
+
+       : MingwModuleHandler ( module_ )
+{
+}
+
+void
+MingwRpcProxyModuleHandler::Process ()
+{
+       GenerateRules ();
+}
+
+
 MingwAliasModuleHandler::MingwAliasModuleHandler (
        const Module& module_ )
 
@@ -3633,3 +3821,66 @@ MingwIdlHeaderModuleHandler::Process ()
 {
        GenerateRules ();
 }
+
+MingwCabinetModuleHandler::MingwCabinetModuleHandler (
+       const Module& module_ )
+
+       : MingwModuleHandler ( module_ )
+{
+}
+
+void
+MingwCabinetModuleHandler::Process ()
+{
+       string targetMacro ( GetTargetMacro (module) );
+
+       GenerateRules ();
+       
+       const FileLocation *target_file = GetTargetFilename ( module, NULL );
+       fprintf ( fMakefile, "%s: | %s\n",
+                 targetMacro.c_str (),
+                 backend->GetFullPath ( *target_file ).c_str () );
+
+       fprintf ( fMakefile, "\t$(ECHO_CABMAN)\n" );
+       fprintf ( fMakefile,
+                 "\t$(Q)$(CABMAN_TARGET) -M raw -S %s $(%s_SOURCES)\n",      // Escape the asterisk for Make
+                 targetMacro.c_str (),
+                         module.name.c_str());
+}
+
+MingwElfExecutableModuleHandler::MingwElfExecutableModuleHandler (
+       const Module& module_ )
+
+       : MingwModuleHandler ( module_ )
+{
+}
+
+void
+MingwElfExecutableModuleHandler::Process ()
+{
+       string targetName ( module.output->name );
+       string targetMacro ( GetTargetMacro (module) );
+       string workingDirectory = GetWorkingDirectory ();
+       string objectsMacro = GetObjectsMacro ( module );
+       string linkDepsMacro = GetLinkingDependenciesMacro ();
+       string libsMacro = GetLibsMacro ();
+
+       GenerateRules ();
+
+       const FileLocation *target_file = GetTargetFilename ( module, NULL );
+       fprintf ( fMakefile, "%s: %s %s | %s\n",
+                 targetMacro.c_str (),
+                 objectsMacro.c_str (),
+                 linkDepsMacro.c_str (),
+                 backend->GetFullPath ( *target_file ).c_str () );
+
+       fprintf ( fMakefile, "\t$(ECHO_BOOTPROG)\n" );
+
+       fprintf ( fMakefile, "\t${gcc} $(%s_LINKFORMAT) %s %s -g -o %s\n",
+                 module.buildtype.c_str(),
+                 objectsMacro.c_str(),
+                 libsMacro.c_str(),
+                 targetMacro.c_str () );
+
+       delete target_file;
+}