#include "mingw.h"
#include <assert.h>
-#include <dirent.h>
#include "modulehandler.h"
-#ifdef WIN32
-#define MKDIR(s) mkdir(s)
-#else
-#define MKDIR(s) mkdir(s, 0755)
-#endif
+#ifdef _MSC_VER
+#define popen _popen
+#define pclose _pclose
+#endif//_MSC_VER
using std::string;
using std::vector;
}
-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 )
-{
- DIR *directory;
- directory = opendir ( path );
- if ( directory != NULL )
- {
- closedir ( directory );
- return false;
- }
-
- if ( MKDIR ( path ) != 0 )
- 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:
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 ()
{
MingwModuleHandler* h = MingwModuleHandler::InstanciateHandler (
module,
this );
+ if ( use_pch && CanEnablePreCompiledHeaderSupportForModule ( module ) )
+ h->EnablePreCompiledHeaderSupport ();
if ( module.host == HostDefault )
{
module.host = h->DefaultHost();
MingwBackend::ProcessNormal ()
{
DetectCompiler ();
+ DetectBinutils ();
DetectNetwideAssembler ();
DetectPipeSupport ();
DetectPCHSupport ();
GenerateDirectories ();
UnpackWineResources ();
GenerateTestSupportCode ();
+ GenerateCompilationUnitSupportCode ();
+ GenerateSysSetup ();
GenerateProxyMakefiles ();
CheckAutomaticDependencies ();
CloseMakefile ();
throw AccessDeniedException ( ProjectNode.makefile );
MingwModuleHandler::SetBackend ( this );
MingwModuleHandler::SetMakefile ( fMakefile );
- MingwModuleHandler::SetUsePch ( use_pch );
}
void
string
MingwBackend::GetBin2ResExecutable ()
{
- return NormalizeFilename ( Environment::GetOutputPath () + SSEP + "tools/bin2res/bin2res" + EXEPOSTFIX );
+ return NormalizeFilename ( Environment::GetOutputPath () + sSep + "tools/bin2res/bin2res" + ExePostfix );
}
void
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
{
bool
MingwBackend::IncludeDirectoryTarget ( const string& directory ) const
{
- if ( directory == "$(INTERMEDIATE)" SSEP "tools")
+ if ( directory == "$(INTERMEDIATE)" + sSep + "tools")
return false;
else
return true;
{
string command = ssprintf (
"%s -v 1>%s 2>%s",
- compiler.c_str (),
+ FixSeparatorForSystemCommand(compiler).c_str (),
NUL,
NUL );
int exitcode = system ( command.c_str () );
{
string command = ssprintf (
"%s -h 1>%s 2>%s",
- assembler.c_str (),
+ FixSeparatorForSystemCommand(assembler).c_str (),
NUL,
NUL );
int exitcode = system ( command.c_str () );
return (exitcode == 0);
}
+bool
+MingwBackend::TryToDetectThisBinutils ( const string& binutils )
+{
+ string command = ssprintf (
+ "%s -v 1>%s",
+ FixSeparatorForSystemCommand(binutils).c_str (),
+ NUL,
+ NUL );
+ int exitcode = system ( command.c_str () );
+ return (exitcode == 0);
+}
+
+string
+MingwBackend::GetBinutilsVersion ( const string& binutilsCommand )
+{
+ FILE *fp;
+ int ch, i;
+ char buffer[81];
+
+ string versionCommand = ssprintf ( "%s -v",
+ binutilsCommand.c_str (),
+ NUL,
+ NUL );
+ fp = popen ( versionCommand.c_str () , "r" );
+ for( i = 0;
+ ( i < 80 ) &&
+ ( feof ( fp ) == 0 &&
+ ( ( ch = fgetc( fp ) ) != -1 ) );
+ i++ )
+ {
+ buffer[i] = (char) ch;
+ }
+ buffer[i] = '\0';
+ pclose ( fp );
+
+ char separators[] = " ";
+ char *token;
+ char *prevtoken = NULL;
+
+ token = strtok ( buffer, separators );
+ while ( token != NULL )
+ {
+ prevtoken = token;
+ token = strtok ( NULL, separators );
+ }
+ string version = string ( prevtoken );
+ int lastDigit = version.find_last_not_of ( "\t\r\n" );
+ if ( lastDigit != -1 )
+ return string ( version, 0, lastDigit+1 );
+ else
+ return version;
+}
+
+bool
+MingwBackend::IsSupportedBinutilsVersion ( const string& binutilsVersion )
+{
+ if ( ( ( strcmp ( binutilsVersion.c_str (), "20040902") >= 0 ) &&
+ ( strcmp ( binutilsVersion.c_str (), "20041008") <= 0 ) ) ||
+ ( strcmp ( binutilsVersion.c_str (), "20031001") < 0 ) )
+ return false;
+ else
+ return true;
+}
+
+void
+MingwBackend::DetectBinutils ()
+{
+ printf ( "Detecting binutils..." );
+
+ bool detectedBinutils = false;
+ const string& ROS_PREFIXValue = Environment::GetVariable ( "ROS_PREFIX" );
+ if ( ROS_PREFIXValue.length () > 0 )
+ {
+ binutilsPrefix = ROS_PREFIXValue;
+ binutilsCommand = binutilsPrefix + "-ld";
+ detectedBinutils = TryToDetectThisBinutils ( binutilsCommand );
+ }
+#if defined(WIN32)
+ if ( !detectedBinutils )
+ {
+ binutilsPrefix = "";
+ binutilsCommand = "ld";
+ detectedBinutils = TryToDetectThisBinutils ( binutilsCommand );
+ }
+#endif
+ if ( !detectedBinutils )
+ {
+ binutilsPrefix = "mingw32";
+ binutilsCommand = binutilsPrefix + "-ld";
+ detectedBinutils = TryToDetectThisBinutils ( binutilsCommand );
+ }
+ if ( detectedBinutils )
+ {
+ string binutilsVersion = GetBinutilsVersion ( binutilsCommand );
+ if ( IsSupportedBinutilsVersion ( binutilsVersion ) )
+ printf ( "detected (%s)\n", binutilsCommand.c_str () );
+ else
+ {
+ printf ( "detected (%s), but with unsupported version (%s)\n",
+ binutilsCommand.c_str (),
+ binutilsVersion.c_str () );
+ throw UnsupportedBuildToolException ( binutilsCommand, binutilsVersion );
+ }
+ }
+ else
+ printf ( "not detected\n" );
+}
+
void
MingwBackend::DetectNetwideAssembler ()
{
{
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,
{
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 );
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 );
{
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 (
{
string fullTargetFilename;
if ( targetDirectory.length () > 0)
- fullTargetFilename = targetDirectory + SSEP + targetFilename;
+ fullTargetFilename = targetDirectory + sSep + targetFilename;
else
fullTargetFilename = targetFilename;
string normalizedTargetFilename = MingwModuleHandler::PassThruCacheDirectory (
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
{
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
{
string system32ConfigDirectory = NormalizeFilename (
MingwModuleHandler::PassThruCacheDirectory (
- "system32" SSEP "config" SSEP,
+ "system32" + sSep + "config" + sSep,
installDirectory ) );
string registrySourceFiles = GetRegistrySourceFiles ();
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" );
}