Show execution time of tests
[reactos.git] / reactos / tools / rbuild / backend / mingw / mingw.cpp
index 3413557..aeeadd9 100644 (file)
@@ -41,18 +41,6 @@ v2s ( const string_list& v, int wrap_at )
 }
 
 
-/* static */ string
-Environment::GetVariable ( const string& name )
-{
-       char* value = getenv ( name.c_str () );
-       if ( value != NULL && strlen ( value ) > 0 )
-               return ssprintf ( "%s",
-                                 value );
-       else
-               return "";
-}
-
-
 Directory::Directory ( const string& name_ )
        : name(name_)
 {
@@ -121,8 +109,8 @@ Directory::CreateDirectory ( string path )
 
 string
 Directory::ReplaceVariable ( string name,
-                                string value,
-                                string path )
+                             string value,
+                             string path )
 {
        size_t i = path.find ( name );
        if ( i != string::npos )
@@ -131,51 +119,19 @@ Directory::ReplaceVariable ( string name,
                return path;
 }
 
-string
-Directory::GetEnvironmentVariablePathOrDefault ( const string& name,
-                                                    const string& defaultValue )
-{
-       const string& environmentVariableValue = Environment::GetVariable ( name );
-       if ( environmentVariableValue.length () > 0 )
-               return NormalizeFilename ( environmentVariableValue );
-       else
-               return defaultValue;
-}
-
-string
-Directory::GetIntermediatePath ()
-{
-       return GetEnvironmentVariablePathOrDefault ( "ROS_INTERMEDIATE",
-                                                    "obj-i386" );
-}
-
-string
-Directory::GetOutputPath ()
-{
-       return GetEnvironmentVariablePathOrDefault ( "ROS_OUTPUT",
-                                                    "output-i386" );
-}
-
-string
-Directory::GetInstallPath ()
-{
-       return GetEnvironmentVariablePathOrDefault ( "ROS_INSTALL",
-                                                    "reactos" );
-}
-
 void
 Directory::ResolveVariablesInPath ( char* buf,
-                                       string path )
+                                    string path )
 {
-       string s = ReplaceVariable ( "$(INTERMEDIATE)", GetIntermediatePath (), path );
-       s = ReplaceVariable ( "$(OUTPUT)", GetOutputPath (), s );
-       s = ReplaceVariable ( "$(INSTALL)", GetInstallPath (), s );
+       string s = ReplaceVariable ( "$(INTERMEDIATE)", Environment::GetIntermediatePath (), path );
+       s = ReplaceVariable ( "$(OUTPUT)", Environment::GetOutputPath (), s );
+       s = ReplaceVariable ( "$(INSTALL)", Environment::GetInstallPath (), s );
        strcpy ( buf, s.c_str () );
 }
 
 void
 Directory::GenerateTree ( const string& parent,
-                             bool verbose )
+                          bool verbose )
 {
        string path;
 
@@ -217,7 +173,7 @@ Directory::EscapeSpaces ( string path )
 
 void
 Directory::CreateRule ( FILE* f,
-                           const string& parent )
+                        const string& parent )
 {
        string path;
 
@@ -256,24 +212,22 @@ static class MingwFactory : public Backend::Factory
 public:
        MingwFactory() : Factory ( "mingw" ) {}
        Backend* operator() ( Project& project,
-                             bool verbose,
-                             bool cleanAsYouGo )
+                             Configuration& configuration )
        {
                return new MingwBackend ( project,
-                                         verbose,
-                                         cleanAsYouGo );
+                                         configuration );
        }
 } factory;
 
 
 MingwBackend::MingwBackend ( Project& project,
-                             bool verbose,
-                             bool cleanAsYouGo )
-       : Backend ( project, verbose, cleanAsYouGo ),
+                             Configuration& configuration )
+       : Backend ( project, configuration ),
          intermediateDirectory ( new Directory ("$(INTERMEDIATE)" ) ),
          outputDirectory ( new Directory ( "$(OUTPUT)" ) ),
          installDirectory ( new Directory ( "$(INSTALL)" ) )
 {
+       compilerPrefix = "";
 }
 
 MingwBackend::~MingwBackend()
@@ -285,9 +239,10 @@ MingwBackend::~MingwBackend()
 
 string
 MingwBackend::AddDirectoryTarget ( const string& directory,
-                                      Directory* directoryTree )
+                                   Directory* directoryTree )
 {
-       directoryTree->Add ( directory.c_str() );
+       if ( directory.length () > 0)
+               directoryTree->Add ( directory.c_str() );
        return directoryTree->name;
 }
 
@@ -301,6 +256,8 @@ MingwBackend::ProcessModules ()
        for ( i = 0; i < ProjectNode.modules.size (); i++ )
        {
                Module& module = *ProjectNode.modules[i];
+               if ( !module.enabled )
+                       continue;
                MingwModuleHandler* h = MingwModuleHandler::InstanciateHandler (
                        module,
                        this );
@@ -323,6 +280,7 @@ MingwBackend::ProcessModules ()
 
        GenerateAllTarget ( v );
        GenerateInitTarget ();
+       GenerateRegTestsRunTarget ();
 
        for ( i = 0; i < iend; i++ )
                v[i]->GenerateOtherMacros();
@@ -335,16 +293,49 @@ MingwBackend::ProcessModules ()
                h.GenerateInvocations ();
                h.GenerateCleanTarget ();
                h.GenerateInstallTarget ();
+               h.GenerateDependsTarget ();
                delete v[i];
        }
 
        printf ( "done\n" );
 }
-       
+
 void
 MingwBackend::Process ()
+{
+       if ( configuration.CheckDependenciesForModuleOnly )
+               CheckAutomaticDependenciesForModuleOnly ();
+       else
+               ProcessNormal ();
+}
+
+void
+MingwBackend::CheckAutomaticDependenciesForModuleOnly ()
+{
+       if ( configuration.AutomaticDependencies )
+       {
+               Module* module = ProjectNode.LocateModule ( configuration.CheckDependenciesForModuleOnlyModule );
+               if ( module == NULL )
+               {
+                       printf ( "Module '%s' does not exist\n",
+                               configuration.CheckDependenciesForModuleOnlyModule.c_str () );
+                       return;
+               }
+               
+               printf ( "Checking automatic dependencies for module '%s'...",
+                        module->name.c_str () );
+               AutomaticDependency automaticDependency ( ProjectNode );
+               automaticDependency.CheckAutomaticDependencies ( *module,
+                                                                configuration.Verbose );
+               printf ( "done\n" );
+       }
+}
+
+void
+MingwBackend::ProcessNormal ()
 {
        DetectCompiler ();
+       DetectNetwideAssembler ();
        DetectPipeSupport ();
        DetectPCHSupport ();
        CreateMakefile ();
@@ -353,8 +344,12 @@ MingwBackend::Process ()
        GenerateXmlBuildFilesMacro ();
        ProcessModules ();
        GenerateInstallTarget ();
+       GenerateTestTarget ();
        GenerateDirectoryTargets ();
        GenerateDirectories ();
+       UnpackWineResources ();
+       GenerateTestSupportCode ();
+       GenerateProxyMakefiles ();
        CheckAutomaticDependencies ();
        CloseMakefile ();
 }
@@ -383,46 +378,27 @@ MingwBackend::GenerateHeader () const
        fprintf ( fMakefile, "# THIS FILE IS AUTOMATICALLY GENERATED, EDIT 'ReactOS.xml' INSTEAD\n\n" );
 }
 
+string
+MingwBackend::GenerateIncludesAndDefines ( IfableData& data ) const
+{
+       string includeParameters = MingwModuleHandler::GenerateGccIncludeParametersFromVector ( data.includes );
+       string defineParameters = MingwModuleHandler::GenerateGccDefineParametersFromVector ( data.defines );
+       return includeParameters + " " + defineParameters;
+}
+
 void
 MingwBackend::GenerateProjectCFlagsMacro ( const char* assignmentOperation,
                                            IfableData& data ) const
 {
-       size_t i;
-
        fprintf (
                fMakefile,
                "PROJECT_CFLAGS %s",
                assignmentOperation );
        
-       for ( i = 0; i < data.compilerFlags.size(); i++ )
-       {
-               fprintf (
-                       fMakefile,
-                       " %s",
-                       data.compilerFlags[i]->flag.c_str() );
-       }
-
-       for ( i = 0; i < data.includes.size(); i++ )
-       {
-               fprintf (
-                       fMakefile,
-                       " -I%s",
-                       data.includes[i]->directory.c_str() );
-       }
+       fprintf ( fMakefile,
+                 " %s",
+                 GenerateIncludesAndDefines ( data ).c_str() );
 
-       for ( i = 0; i < data.defines.size(); i++ )
-       {
-               Define& d = *data.defines[i];
-               fprintf (
-                       fMakefile,
-                       " -D%s",
-                       d.name.c_str() );
-               if ( d.value.size() )
-                       fprintf (
-                               fMakefile,
-                               "=%s",
-                               d.value.c_str() );
-       }
        fprintf ( fMakefile, "\n" );
 }
 
@@ -441,7 +417,7 @@ MingwBackend::GenerateGlobalCFlagsAndProperties (
                        prop.value.c_str() );
        }
 
-       if ( data.includes.size() || data.defines.size() || data.compilerFlags.size() )
+       if ( data.includes.size() || data.defines.size() )
        {
                GenerateProjectCFlagsMacro ( assignmentOperation,
                                             data );
@@ -452,7 +428,6 @@ MingwBackend::GenerateGlobalCFlagsAndProperties (
                If& rIf = *data.ifs[i];
                if ( rIf.data.defines.size()
                        || rIf.data.includes.size()
-                       || rIf.data.compilerFlags.size()
                        || rIf.data.ifs.size() )
                {
                        fprintf (
@@ -470,6 +445,62 @@ MingwBackend::GenerateGlobalCFlagsAndProperties (
        }
 }
 
+void
+MingwBackend::GenerateProjectGccOptionsMacro ( const char* assignmentOperation,
+                                               IfableData& data ) const
+{
+       size_t i;
+
+       fprintf (
+               fMakefile,
+               "PROJECT_GCCOPTIONS %s",
+               assignmentOperation );
+       
+       for ( i = 0; i < data.compilerFlags.size(); i++ )
+       {
+               fprintf (
+                       fMakefile,
+                       " %s",
+                       data.compilerFlags[i]->flag.c_str() );
+       }
+
+       fprintf ( fMakefile, "\n" );
+}
+
+void
+MingwBackend::GenerateProjectGccOptions (
+       const char* assignmentOperation,
+       IfableData& data ) const
+{
+       size_t i;
+
+       if ( data.compilerFlags.size() )
+       {
+               GenerateProjectGccOptionsMacro ( assignmentOperation,
+                                                data );
+       }
+
+       for ( i = 0; i < data.ifs.size(); i++ )
+       {
+               If& rIf = *data.ifs[i];
+               if ( rIf.data.compilerFlags.size()
+                    || rIf.data.ifs.size() )
+               {
+                       fprintf (
+                               fMakefile,
+                               "ifeq (\"$(%s)\",\"%s\")\n",
+                               rIf.property.c_str(),
+                               rIf.value.c_str() );
+                       GenerateProjectGccOptions (
+                               "+=",
+                               rIf.data );
+                       fprintf (
+                               fMakefile,
+                               "endif\n\n" );
+               }
+       }
+}
+
 string
 MingwBackend::GenerateProjectLFLAGS () const
 {
@@ -487,15 +518,22 @@ MingwBackend::GenerateProjectLFLAGS () const
 void
 MingwBackend::GenerateGlobalVariables () const
 {
-       GenerateGlobalCFlagsAndProperties (
-               "=",
-               ProjectNode.non_if_data );
+       fprintf ( fMakefile,
+                 "PREFIX := %s\n",
+                 compilerPrefix.c_str () );
+       fprintf ( fMakefile,
+                 "nasm := %s\n",
+                 nasmCommand.c_str () );
+
+       GenerateGlobalCFlagsAndProperties ( "=", ProjectNode.non_if_data );
+       GenerateProjectGccOptions ( "=", ProjectNode.non_if_data );
 
        fprintf ( fMakefile, "PROJECT_RCFLAGS := $(PROJECT_CFLAGS)\n" );
        fprintf ( fMakefile, "PROJECT_WIDLFLAGS := $(PROJECT_CFLAGS)\n" );
        fprintf ( fMakefile, "PROJECT_LFLAGS := %s\n",
                  GenerateProjectLFLAGS ().c_str () );
        fprintf ( fMakefile, "PROJECT_CFLAGS += -Wall\n" );
+       fprintf ( fMakefile, "PROJECT_CFLAGS += $(PROJECT_GCCOPTIONS)\n" );
        fprintf ( fMakefile, "\n" );
 }
 
@@ -543,6 +581,8 @@ MingwBackend::GetBuildToolDependencies () const
        for ( size_t i = 0; i < ProjectNode.modules.size (); i++ )
        {
                Module& module = *ProjectNode.modules[i];
+               if ( !module.enabled )
+                       continue;
                if ( module.type == BuildTool )
                {
                        if ( dependencies.length () > 0 )
@@ -562,6 +602,18 @@ MingwBackend::GenerateInitTarget () const
        fprintf ( fMakefile, "\n" );
 }
 
+void
+MingwBackend::GenerateRegTestsRunTarget () const
+{
+       fprintf ( fMakefile,
+                 "REGTESTS_RUN_TARGET = regtests.dll\n" );
+       fprintf ( fMakefile,
+                 "$(REGTESTS_RUN_TARGET): $(REGTESTS_TARGET)\n" );
+       fprintf ( fMakefile,
+                 "\t$(cp) $(REGTESTS_TARGET) $(REGTESTS_RUN_TARGET)\n" );
+       fprintf ( fMakefile, "\n" );
+}
+
 void
 MingwBackend::GenerateXmlBuildFilesMacro() const
 {
@@ -591,8 +643,7 @@ MingwBackend::GenerateXmlBuildFilesMacro() const
                        else
                        {
                                fprintf ( fMakefile,
-                                         " \\\n",
-                                         xmlbuildFilenames.c_str () );
+                                         " \\\n" );
                        }
                        xmlbuildFilenames.resize ( 0 );
                }
@@ -601,16 +652,62 @@ MingwBackend::GenerateXmlBuildFilesMacro() const
        fprintf ( fMakefile, "\n" );
 }
 
+string
+MingwBackend::GetBin2ResExecutable ()
+{
+       return NormalizeFilename ( Environment::GetOutputPath () + SSEP + "tools/bin2res/bin2res" + EXEPOSTFIX );
+}
+
 void
-MingwBackend::CheckAutomaticDependencies ()
+MingwBackend::UnpackWineResources ()
+{
+       printf ( "Unpacking WINE resources..." );
+       WineResource wineResource ( ProjectNode,
+                                   GetBin2ResExecutable () );
+       wineResource.UnpackResources ( configuration.Verbose );
+       printf ( "done\n" );
+}
+
+void
+MingwBackend::GenerateTestSupportCode ()
 {
-       printf ( "Checking automatic dependencies..." );
-       AutomaticDependency automaticDependency ( ProjectNode );
-       automaticDependency.Process ();
-       automaticDependency.CheckAutomaticDependencies ( verbose );
+       printf ( "Generating test support code..." );
+       TestSupportCode testSupportCode ( ProjectNode );
+       testSupportCode.GenerateTestSupportCode ( configuration.Verbose );
        printf ( "done\n" );
 }
 
+string
+MingwBackend::GetProxyMakefileTree () const
+{
+       if ( configuration.GenerateProxyMakefilesInSourceTree )
+               return "";
+       else
+               return Environment::GetOutputPath ();
+}
+
+void
+MingwBackend::GenerateProxyMakefiles ()
+{
+       printf ( "Generating proxy makefiles..." );
+       ProxyMakefile proxyMakefile ( ProjectNode );
+       proxyMakefile.GenerateProxyMakefiles ( configuration.Verbose,
+                                              GetProxyMakefileTree () );
+       printf ( "done\n" );
+}
+
+void
+MingwBackend::CheckAutomaticDependencies ()
+{
+       if ( configuration.AutomaticDependencies )
+       {
+               printf ( "Checking automatic dependencies..." );
+               AutomaticDependency automaticDependency ( ProjectNode );
+               automaticDependency.CheckAutomaticDependencies ( configuration.Verbose );
+               printf ( "done\n" );
+       }
+}
+
 bool
 MingwBackend::IncludeDirectoryTarget ( const string& directory ) const
 {
@@ -624,9 +721,10 @@ void
 MingwBackend::GenerateDirectories ()
 {
        printf ( "Creating directories..." );
-       intermediateDirectory->GenerateTree ( "", verbose );
-       outputDirectory->GenerateTree ( "", verbose );
-       installDirectory->GenerateTree ( "", verbose );
+       intermediateDirectory->GenerateTree ( "", configuration.Verbose );
+       outputDirectory->GenerateTree ( "", configuration.Verbose );
+       if ( !configuration.MakeHandlesInstallDirectories )
+               installDirectory->GenerateTree ( "", configuration.Verbose );
        printf ( "done\n" );
 }
 
@@ -634,8 +732,9 @@ bool
 MingwBackend::TryToDetectThisCompiler ( const string& compiler )
 {
        string command = ssprintf (
-               "%s -v 2>%s",
+               "%s -v 1>%s 2>%s",
                compiler.c_str (),
+               NUL,
                NUL );
        int exitcode = system ( command.c_str () );
        return (exitcode == 0);
@@ -650,19 +749,22 @@ MingwBackend::DetectCompiler ()
        const string& ROS_PREFIXValue = Environment::GetVariable ( "ROS_PREFIX" );
        if ( ROS_PREFIXValue.length () > 0 )
        {
-               compilerCommand = ROS_PREFIXValue + "-gcc";
+               compilerPrefix = ROS_PREFIXValue;
+               compilerCommand = compilerPrefix + "-gcc";
                detectedCompiler = TryToDetectThisCompiler ( compilerCommand );
        }
 #if defined(WIN32)
        if ( !detectedCompiler )
        {
+               compilerPrefix = "";
                compilerCommand = "gcc";
                detectedCompiler = TryToDetectThisCompiler ( compilerCommand );
        }
 #endif
        if ( !detectedCompiler )
        {
-               compilerCommand = "mingw32-gcc";
+               compilerPrefix = "mingw32";
+               compilerCommand = compilerPrefix + "-gcc";
                detectedCompiler = TryToDetectThisCompiler ( compilerCommand );
        }
        if ( detectedCompiler )
@@ -671,6 +773,38 @@ MingwBackend::DetectCompiler ()
                printf ( "not detected\n" );
 }
 
+bool
+MingwBackend::TryToDetectThisNetwideAssembler ( const string& assembler )
+{
+       string command = ssprintf (
+               "%s -h 1>%s 2>%s",
+               assembler.c_str (),
+               NUL,
+               NUL );
+       int exitcode = system ( command.c_str () );
+       return (exitcode == 0);
+}
+
+void
+MingwBackend::DetectNetwideAssembler ()
+{
+       printf ( "Detecting netwide assembler..." );
+
+       nasmCommand = "nasm";
+       bool detectedNasm = TryToDetectThisNetwideAssembler ( nasmCommand );
+#if defined(WIN32)
+       if ( !detectedNasm )
+       {
+               nasmCommand = "nasmw";
+               detectedNasm = TryToDetectThisNetwideAssembler ( nasmCommand );
+       }
+#endif
+       if ( detectedNasm )
+               printf ( "detected (%s)\n", nasmCommand.c_str () );
+       else
+               printf ( "not detected\n" );
+}
+
 void
 MingwBackend::DetectPipeSupport ()
 {
@@ -680,10 +814,11 @@ MingwBackend::DetectPipeSupport ()
        string pipe_detectionObjectFilename = ReplaceExtension ( pipe_detection,
                                                                 ".o" );
        string command = ssprintf (
-               "%s -pipe -c %s -o %s 2>%s",
+               "%s -pipe -c %s -o %s 1>%s 2>%s",
                compilerCommand.c_str (),
                pipe_detection.c_str (),
                pipe_detectionObjectFilename.c_str (),
+               NUL,
                NUL );
        int exitcode = system ( command.c_str () );
        FILE* f = fopen ( pipe_detectionObjectFilename.c_str (), "rb" );
@@ -709,9 +844,10 @@ MingwBackend::DetectPCHSupport ()
 
        string path = "tools" SSEP "rbuild" SSEP "backend" SSEP "mingw" SSEP "pch_detection.h";
        string cmd = ssprintf (
-               "%s -c %s 2>%s",
+               "%s -c %s 1>%s 2>%s",
                compilerCommand.c_str (),
                path.c_str (),
+               NUL,
                NUL );
        system ( cmd.c_str () );
        path += ".gch";
@@ -754,9 +890,15 @@ MingwBackend::GetModuleInstallTargetFiles (
        for ( size_t i = 0; i < ProjectNode.modules.size (); i++ )
        {
                const Module& module = *ProjectNode.modules[i];
+               if ( !module.enabled )
+                       continue;
                if ( module.installName.length () > 0 )
                {
-                       string targetFilenameNoFixup = module.installBase + SSEP + module.installName;
+                       string targetFilenameNoFixup;
+                       if ( module.installBase.length () > 0 )
+                               targetFilenameNoFixup = module.installBase + SSEP + module.installName;
+                       else
+                               targetFilenameNoFixup = module.installName;
                        string targetFilename = MingwModuleHandler::PassThruCacheDirectory (
                                NormalizeFilename ( targetFilenameNoFixup ),
                                installDirectory );
@@ -775,11 +917,16 @@ MingwBackend::GetInstallTargetFiles (
 
 void
 MingwBackend::OutputInstallTarget ( const string& sourceFilename,
-                                       const string& targetFilename,
-                                       const string& targetDirectory )
+                                   const string& targetFilename,
+                                   const string& targetDirectory )
 {
+       string fullTargetFilename;
+       if ( targetDirectory.length () > 0)
+               fullTargetFilename = targetDirectory + SSEP + targetFilename;
+       else
+               fullTargetFilename = targetFilename;
        string normalizedTargetFilename = MingwModuleHandler::PassThruCacheDirectory (
-               NormalizeFilename ( targetDirectory + SSEP + targetFilename ),
+               NormalizeFilename ( fullTargetFilename ),
                installDirectory );
        string normalizedTargetDirectory = MingwModuleHandler::PassThruCacheDirectory (
                NormalizeFilename ( targetDirectory ),
@@ -804,8 +951,8 @@ MingwBackend::OutputNonModuleInstallTargets ()
        {
                const InstallFile& installfile = *ProjectNode.installfiles[i];
                OutputInstallTarget ( installfile.GetPath (),
-                                 installfile.newname,
-                                 installfile.base );
+                                     installfile.newname,
+                                     installfile.base );
        }
 }
 
@@ -815,14 +962,16 @@ MingwBackend::OutputModuleInstallTargets ()
        for ( size_t i = 0; i < ProjectNode.modules.size (); i++ )
        {
                const Module& module = *ProjectNode.modules[i];
+               if ( !module.enabled )
+                       continue;
                if ( module.installName.length () > 0 )
                {
                        string sourceFilename = MingwModuleHandler::PassThruCacheDirectory (
                                NormalizeFilename ( module.GetPath () ),
                                outputDirectory );
                        OutputInstallTarget ( sourceFilename,
-                                         module.installName,
-                                         module.installBase );
+                                             module.installName,
+                                             module.installBase );
                }
        }
 }
@@ -884,10 +1033,12 @@ MingwBackend::GenerateInstallTarget ()
        vector<string> vInstallTargetFiles;
        GetInstallTargetFiles ( vInstallTargetFiles );
        string installTargetFiles = v2s ( vInstallTargetFiles, 5 );
+       string registryTargetFiles = GetRegistryTargetFiles ();
 
        fprintf ( fMakefile,
-                 "install: %s install_registry\n",
-                 installTargetFiles.c_str () );
+                 "install: %s %s\n",
+                 installTargetFiles.c_str (),
+                 registryTargetFiles.c_str () );
        OutputNonModuleInstallTargets ();
        OutputModuleInstallTargets ();
        OutputRegistryInstallTarget ();
@@ -895,6 +1046,34 @@ MingwBackend::GenerateInstallTarget ()
                  "\n" );
 }
 
+void
+MingwBackend::GetModuleTestTargets (
+       vector<string>& out ) const
+{
+       for ( size_t i = 0; i < ProjectNode.modules.size (); i++ )
+       {
+               const Module& module = *ProjectNode.modules[i];
+               if ( !module.enabled )
+                       continue;
+               if ( module.type == Test )
+                       out.push_back ( module.name );
+       }
+}
+
+void
+MingwBackend::GenerateTestTarget ()
+{
+       vector<string> vTestTargets;
+       GetModuleTestTargets ( vTestTargets );
+       string testTargets = v2s ( vTestTargets, 5 );
+
+       fprintf ( fMakefile,
+                 "test: %s\n",
+                 testTargets.c_str () );
+       fprintf ( fMakefile,
+                 "\n" );
+}
+
 void
 MingwBackend::GenerateDirectoryTargets ()
 {