* Implement <autoregister>
[reactos.git] / reactos / tools / rbuild / backend / mingw / mingw.cpp
index 55a2537..7b4ceb3 100644 (file)
 
 #include "mingw.h"
 #include <assert.h>
+#include "modulehandler.h"
+
 #ifdef _MSC_VER
 #define popen _popen
 #define pclose _pclose
-#else
-#include <dirent.h>
 #endif//_MSC_VER
-#include "modulehandler.h"
-
-#ifdef WIN32
-#define MKDIR(s) mkdir(s)
-#else
-#define MKDIR(s) mkdir(s, 0755)
-#endif
 
 using std::string;
 using std::vector;
@@ -62,180 +55,6 @@ v2s ( const string_list& v, int wrap_at )
 }
 
 
-Directory::Directory ( const string& name_ )
-       : name(name_)
-{
-}
-
-void
-Directory::Add ( const char* subdir )
-{
-       size_t i;
-       string s1 = string ( subdir );
-       if ( ( i = s1.find ( '$' ) ) != string::npos )
-       {
-               throw InvalidOperationException ( __FILE__,
-                                                 __LINE__,
-                                                 "No environment variables can be used here. Path was %s",
-                                                 subdir );
-       }
-
-       const char* p = strpbrk ( subdir, "/\\" );
-       if ( !p )
-               p = subdir + strlen(subdir);
-       string s ( subdir, p-subdir );
-       if ( subdirs.find(s) == subdirs.end() )
-               subdirs[s] = new Directory(s);
-       if ( *p && *++p )
-               subdirs[s]->Add ( p );
-}
-
-bool
-Directory::mkdir_p ( const char* path )
-{
-#ifndef _MSC_VER
-       DIR *directory;
-       directory = opendir ( path );
-       if ( directory != NULL )
-       {
-               closedir ( directory );
-               return false;
-       }
-#endif//_MSC_VER
-
-       if ( MKDIR ( path ) != 0 )
-       {
-#ifdef _MSC_VER
-               if ( errno == EEXIST )
-                       return false;
-#endif//_MSC_VER
-               throw AccessDeniedException ( string ( path ) );
-       }
-       return true;
-}
-
-bool
-Directory::CreateDirectory ( string path )
-{
-       size_t index = 0;
-       size_t nextIndex;
-       if ( isalpha ( path[0] ) && path[1] == ':' && path[2] == CSEP )
-       {
-               nextIndex = path.find ( CSEP, 3);
-       }
-       else
-               nextIndex = path.find ( CSEP );
-
-       bool directoryWasCreated = false;
-       while ( nextIndex != string::npos )
-       {
-               nextIndex = path.find ( CSEP, index + 1 );
-               directoryWasCreated = mkdir_p ( path.substr ( 0, nextIndex ).c_str () );
-               index = nextIndex;
-       }
-       return directoryWasCreated;
-}
-
-string
-Directory::ReplaceVariable ( string name,
-                             string value,
-                             string path )
-{
-       size_t i = path.find ( name );
-       if ( i != string::npos )
-               return path.replace ( i, name.length (), value );
-       else
-               return path;
-}
-
-void
-Directory::ResolveVariablesInPath ( char* buf,
-                                    string path )
-{
-       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 )
-{
-       string path;
-
-       if ( parent.size () > 0 )
-       {
-               char buf[256];
-               
-               path = parent + SSEP + name;
-               ResolveVariablesInPath ( buf, path );
-               if ( CreateDirectory ( buf ) && verbose )
-                       printf ( "Created %s\n", buf );
-       }
-       else
-               path = name;
-
-       for ( directory_map::iterator i = subdirs.begin ();
-               i != subdirs.end ();
-               ++i )
-       {
-               i->second->GenerateTree ( path, verbose );
-       }
-}
-
-string
-Directory::EscapeSpaces ( string path )
-{
-       string newpath;
-       char* p = &path[0];
-       while ( *p != 0 )
-       {
-               if ( *p == ' ' )
-                       newpath = newpath + "\\ ";
-               else
-                       newpath = newpath + *p;
-               *p++;
-       }
-       return newpath;
-}
-
-void
-Directory::CreateRule ( FILE* f,
-                        const string& parent )
-{
-       string path;
-
-       if ( parent.size() > 0 )
-       {
-               string escapedParent = EscapeSpaces ( parent );
-               fprintf ( f,
-                       "%s%c%s: | %s\n",
-                       escapedParent.c_str (),
-                       CSEP,
-                       EscapeSpaces ( name ).c_str (),
-                       escapedParent.c_str () );
-
-               fprintf ( f,
-                       "\t$(ECHO_MKDIR)\n" );
-
-               fprintf ( f,
-                       "\t${mkdir} $@\n" );
-
-               path = parent + SSEP + name;
-       }
-       else
-               path = name;
-
-       for ( directory_map::iterator i = subdirs.begin();
-               i != subdirs.end();
-               ++i )
-       {
-               i->second->CreateRule ( f, path );
-       }
-}
-
-
 static class MingwFactory : public Backend::Factory
 {
 public:
@@ -275,6 +94,42 @@ MingwBackend::AddDirectoryTarget ( const string& directory,
        return directoryTree->name;
 }
 
+bool
+MingwBackend::CanEnablePreCompiledHeaderSupportForModule ( const Module& module )
+{
+       if ( !configuration.CompilationUnitsEnabled )
+               return true;
+
+       const vector<CompilationUnit*>& compilationUnits = module.non_if_data.compilationUnits;
+       size_t i;
+       for ( i = 0; i < compilationUnits.size (); i++ )
+       {
+               CompilationUnit& compilationUnit = *compilationUnits[i];
+               if ( compilationUnit.files.size () != 1 )
+                       return false;
+       }
+       // intentionally make a copy so that we can append more work in
+       // the middle of processing without having to go recursive
+       vector<If*> v = module.non_if_data.ifs;
+       for ( i = 0; i < v.size (); i++ )
+       {
+               size_t j;
+               If& rIf = *v[i];
+               // check for sub-ifs to add to list
+               const vector<If*>& ifs = rIf.data.ifs;
+               for ( j = 0; j < ifs.size (); j++ )
+                       v.push_back ( ifs[j] );
+               const vector<CompilationUnit*>& compilationUnits = rIf.data.compilationUnits;
+               for ( j = 0; j < compilationUnits.size (); j++ )
+               {
+                       CompilationUnit& compilationUnit = *compilationUnits[j];
+                       if ( compilationUnit.files.size () != 1 )
+                               return false;
+               }
+       }
+       return true;
+}
+
 void
 MingwBackend::ProcessModules ()
 {
@@ -290,6 +145,8 @@ MingwBackend::ProcessModules ()
                MingwModuleHandler* h = MingwModuleHandler::InstanciateHandler (
                        module,
                        this );
+               if ( use_pch && CanEnablePreCompiledHeaderSupportForModule ( module ) )
+                       h->EnablePreCompiledHeaderSupport ();
                if ( module.host == HostDefault )
                {
                        module.host = h->DefaultHost();
@@ -379,6 +236,8 @@ MingwBackend::ProcessNormal ()
        GenerateDirectories ();
        UnpackWineResources ();
        GenerateTestSupportCode ();
+       GenerateCompilationUnitSupportCode ();
+       GenerateSysSetup ();
        GenerateProxyMakefiles ();
        CheckAutomaticDependencies ();
        CloseMakefile ();
@@ -392,7 +251,6 @@ MingwBackend::CreateMakefile ()
                throw AccessDeniedException ( ProjectNode.makefile );
        MingwModuleHandler::SetBackend ( this );
        MingwModuleHandler::SetMakefile ( fMakefile );
-       MingwModuleHandler::SetUsePch ( use_pch );
 }
 
 void
@@ -687,7 +545,7 @@ MingwBackend::GenerateXmlBuildFilesMacro() const
 string
 MingwBackend::GetBin2ResExecutable ()
 {
-       return NormalizeFilename ( Environment::GetOutputPath () + SSEP + "tools/bin2res/bin2res" + EXEPOSTFIX );
+       return NormalizeFilename ( Environment::GetOutputPath () + sSep + "tools/bin2res/bin2res" + ExePostfix );
 }
 
 void
@@ -709,6 +567,27 @@ MingwBackend::GenerateTestSupportCode ()
        printf ( "done\n" );
 }
 
+void
+MingwBackend::GenerateCompilationUnitSupportCode ()
+{
+       if ( configuration.CompilationUnitsEnabled )
+       {
+               printf ( "Generating compilation unit support code..." );
+               CompilationUnitSupportCode compilationUnitSupportCode ( ProjectNode );
+               compilationUnitSupportCode.Generate ( configuration.Verbose );
+               printf ( "done\n" );
+       }
+}
+
+void
+MingwBackend::GenerateSysSetup ()
+{
+       printf ( "Generating syssetup.inf..." );
+       SysSetupGenerator sysSetupGenerator ( ProjectNode );
+       sysSetupGenerator.Generate ();
+       printf ( "done\n" );
+}
+
 string
 MingwBackend::GetProxyMakefileTree () const
 {
@@ -743,7 +622,7 @@ MingwBackend::CheckAutomaticDependencies ()
 bool
 MingwBackend::IncludeDirectoryTarget ( const string& directory ) const
 {
-       if ( directory == "$(INTERMEDIATE)" SSEP "tools")
+       if ( directory == "$(INTERMEDIATE)" + sSep + "tools")
                return false;
        else
                return true;
@@ -765,7 +644,7 @@ MingwBackend::TryToDetectThisCompiler ( const string& compiler )
 {
        string command = ssprintf (
                "%s -v 1>%s 2>%s",
-               compiler.c_str (),
+               FixSeparatorForSystemCommand(compiler).c_str (),
                NUL,
                NUL );
        int exitcode = system ( command.c_str () );
@@ -810,7 +689,7 @@ MingwBackend::TryToDetectThisNetwideAssembler ( const string& assembler )
 {
        string command = ssprintf (
                "%s -h 1>%s 2>%s",
-               assembler.c_str (),
+               FixSeparatorForSystemCommand(assembler).c_str (),
                NUL,
                NUL );
        int exitcode = system ( command.c_str () );
@@ -822,7 +701,7 @@ MingwBackend::TryToDetectThisBinutils ( const string& binutils )
 {
        string command = ssprintf (
                "%s -v 1>%s",
-               binutils.c_str (),
+               FixSeparatorForSystemCommand(binutils).c_str (),
                NUL,
                NUL );
        int exitcode = system ( command.c_str () );
@@ -955,12 +834,12 @@ MingwBackend::DetectPipeSupport ()
 {
        printf ( "Detecting compiler -pipe support..." );
 
-       string pipe_detection = "tools" SSEP "rbuild" SSEP "backend" SSEP "mingw" SSEP "pipe_detection.c";
+       string pipe_detection = "tools" + sSep + "rbuild" + sSep + "backend" + sSep + "mingw" + sSep + "pipe_detection.c";
        string pipe_detectionObjectFilename = ReplaceExtension ( pipe_detection,
                                                                 ".o" );
        string command = ssprintf (
                "%s -pipe -c %s -o %s 1>%s 2>%s",
-               compilerCommand.c_str (),
+               FixSeparatorForSystemCommand(compilerCommand).c_str (),
                pipe_detection.c_str (),
                pipe_detectionObjectFilename.c_str (),
                NUL,
@@ -987,10 +866,10 @@ MingwBackend::DetectPCHSupport ()
 {
        printf ( "Detecting compiler pre-compiled header support..." );
 
-       string path = "tools" SSEP "rbuild" SSEP "backend" SSEP "mingw" SSEP "pch_detection.h";
+       string path = "tools" + sSep + "rbuild" + sSep + "backend" + sSep + "mingw" + sSep + "pch_detection.h";
        string cmd = ssprintf (
                "%s -c %s 1>%s 2>%s",
-               compilerCommand.c_str (),
+               FixSeparatorForSystemCommand(compilerCommand).c_str (),
                path.c_str (),
                NUL,
                NUL );
@@ -1020,7 +899,7 @@ MingwBackend::GetNonModuleInstallTargetFiles (
        for ( size_t i = 0; i < ProjectNode.installfiles.size (); i++ )
        {
                const InstallFile& installfile = *ProjectNode.installfiles[i];
-               string targetFilenameNoFixup = installfile.base + SSEP + installfile.newname;
+               string targetFilenameNoFixup = installfile.base + sSep + installfile.newname;
                string targetFilename = MingwModuleHandler::PassThruCacheDirectory (
                        NormalizeFilename ( targetFilenameNoFixup ),
                        installDirectory );
@@ -1041,7 +920,7 @@ MingwBackend::GetModuleInstallTargetFiles (
                {
                        string targetFilenameNoFixup;
                        if ( module.installBase.length () > 0 )
-                               targetFilenameNoFixup = module.installBase + SSEP + module.installName;
+                               targetFilenameNoFixup = module.installBase + sSep + module.installName;
                        else
                                targetFilenameNoFixup = module.installName;
                        string targetFilename = MingwModuleHandler::PassThruCacheDirectory (
@@ -1067,7 +946,7 @@ MingwBackend::OutputInstallTarget ( const string& sourceFilename,
 {
        string fullTargetFilename;
        if ( targetDirectory.length () > 0)
-               fullTargetFilename = targetDirectory + SSEP + targetFilename;
+               fullTargetFilename = targetDirectory + sSep + targetFilename;
        else
                fullTargetFilename = targetFilename;
        string normalizedTargetFilename = MingwModuleHandler::PassThruCacheDirectory (
@@ -1138,11 +1017,11 @@ MingwBackend::OutputModuleInstallTargets ()
 string
 MingwBackend::GetRegistrySourceFiles ()
 {
-       return "bootdata" SSEP "hivecls.inf "
-               "bootdata" SSEP "hivedef.inf "
-               "bootdata" SSEP "hiveinst.inf "
-               "bootdata" SSEP "hivesft.inf "
-               "bootdata" SSEP "hivesys.inf";
+       return "bootdata" + sSep + "hivecls.inf "
+               "bootdata" + sSep + "hivedef.inf "
+               "bootdata" + sSep + "hiveinst.inf "
+               "bootdata" + sSep + "hivesft.inf "
+               "bootdata" + sSep + "hivesys.inf";
 }
 
 string
@@ -1150,13 +1029,13 @@ MingwBackend::GetRegistryTargetFiles ()
 {
        string system32ConfigDirectory = NormalizeFilename (
                MingwModuleHandler::PassThruCacheDirectory (
-               "system32" SSEP "config" SSEP,
+               "system32" + sSep + "config" + sSep,
                installDirectory ) );
-       return system32ConfigDirectory + SSEP "default " +
-               system32ConfigDirectory + SSEP "sam " +
-               system32ConfigDirectory + SSEP "security " +
-               system32ConfigDirectory + SSEP "software " +
-               system32ConfigDirectory + SSEP "system";
+       return system32ConfigDirectory + sSep + "default " +
+               system32ConfigDirectory + sSep + "sam " +
+                system32ConfigDirectory + sSep + "security " +
+               system32ConfigDirectory + sSep + "software " +
+               system32ConfigDirectory + sSep + "system";
 }
 
 void
@@ -1164,7 +1043,7 @@ MingwBackend::OutputRegistryInstallTarget ()
 {
        string system32ConfigDirectory = NormalizeFilename (
                MingwModuleHandler::PassThruCacheDirectory (
-               "system32" SSEP "config" SSEP,
+               "system32" + sSep + "config" + sSep,
                installDirectory ) );
 
        string registrySourceFiles = GetRegistrySourceFiles ();
@@ -1180,8 +1059,9 @@ MingwBackend::OutputRegistryInstallTarget ()
        fprintf ( fMakefile,
                  "\t$(ECHO_MKHIVE)\n" );
        fprintf ( fMakefile,
-                 "\t$(MKHIVE_TARGET) bootdata %s bootdata" SSEP "hiveinst.inf\n",
-                 system32ConfigDirectory.c_str () );
+                 "\t$(MKHIVE_TARGET) bootdata %s bootdata%chiveinst.inf\n",
+                 system32ConfigDirectory.c_str (),
+                  cSep );
        fprintf ( fMakefile,
                  "\n" );
 }