Christoph_vW <Christoph@ApiViewer.de>:
Binutils detection

Modified to support cross-compilation

Resolves #707
Modified: trunk/reactos/tools/rbuild/backend/mingw/mingw.cpp
Modified: trunk/reactos/tools/rbuild/backend/mingw/mingw.h
Modified: trunk/reactos/tools/rbuild/exception.cpp
Modified: trunk/reactos/tools/rbuild/exception.h

Modified: trunk/reactos/tools/rbuild/backend/mingw/mingw.cpp
--- trunk/reactos/tools/rbuild/backend/mingw/mingw.cpp	2005-09-08 16:18:51 UTC (rev 17743)
+++ trunk/reactos/tools/rbuild/backend/mingw/mingw.cpp	2005-09-08 16:41:07 UTC (rev 17744)
@@ -361,6 +361,7 @@
 MingwBackend::ProcessNormal ()
 {
 	DetectCompiler ();
+	DetectBinutils ();
 	DetectNetwideAssembler ();
 	DetectPipeSupport ();
 	DetectPCHSupport ();
@@ -813,7 +814,112 @@
 	return (exitcode == 0);
 }
 
+bool
+MingwBackend::TryToDetectThisBinutils ( const string& binutils )
+{
+	string command = ssprintf (
+		"%s -v 1>%s",
+		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 ); i++ )
+	{
+		buffer[i] = (char) ch;
+		ch = fgetc( fp );
+	}
+	buffer[i] = '\0';
+	pclose ( fp );
+	
+	char separators[] = " ";
+	char *token;
+	char *prevtoken;
+	
+	token = strtok ( buffer, separators );
+	while ( token != NULL )
+	{
+		prevtoken = token;
+		token = strtok ( NULL, separators );
+	}
+	string version = string ( prevtoken );
+	int firstSpace = version.find_last_not_of ( " \t" );
+	if ( firstSpace != -1 )
+		return string ( version, 0, firstSpace - 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 )
+	{
+		const 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 netwide assembler..." );

Modified: trunk/reactos/tools/rbuild/backend/mingw/mingw.h
--- trunk/reactos/tools/rbuild/backend/mingw/mingw.h	2005-09-08 16:18:51 UTC (rev 17743)
+++ trunk/reactos/tools/rbuild/backend/mingw/mingw.h	2005-09-08 16:41:07 UTC (rev 17744)
@@ -72,6 +72,8 @@
 	std::string compilerPrefix;
 	std::string compilerCommand;
 	std::string nasmCommand;
+	std::string binutilsPrefix;
+	std::string binutilsCommand;
 	bool usePipe;
 	Directory* intermediateDirectory;
 	Directory* outputDirectory;
@@ -108,6 +110,10 @@
 	bool TryToDetectThisCompiler ( const std::string& compiler );
 	void DetectCompiler ();
 	bool TryToDetectThisNetwideAssembler ( const std::string& assembler );
+	bool TryToDetectThisBinutils ( const std::string& binutils );
+	std::string GetBinutilsVersion ( const std::string& binutilsCommand );
+	bool IsSupportedBinutilsVersion ( const std::string& binutilsVersion );
+	void DetectBinutils ();
 	void DetectNetwideAssembler ();
 	void DetectPipeSupport ();
 	void DetectPCHSupport ();

Modified: trunk/reactos/tools/rbuild/exception.cpp
--- trunk/reactos/tools/rbuild/exception.cpp	2005-09-08 16:18:51 UTC (rev 17743)
+++ trunk/reactos/tools/rbuild/exception.cpp	2005-09-08 16:41:07 UTC (rev 17744)
@@ -187,3 +187,14 @@
 	Command = command;
 	ExitCode = exitcode;
 }
+
+
+UnsupportedBuildToolException::UnsupportedBuildToolException ( const std::string& buildTool,
+                                                               const std::string& version )
+	: Exception ( "Build tool '%s' with version '%s' is unsupported. Please upgrade your build tool.",
+	              buildTool.c_str (),
+	              version.c_str () )
+{
+	BuildTool = buildTool;
+	Version  = version;
+}

Modified: trunk/reactos/tools/rbuild/exception.h
--- trunk/reactos/tools/rbuild/exception.h	2005-09-08 16:18:51 UTC (rev 17743)
+++ trunk/reactos/tools/rbuild/exception.h	2005-09-08 16:41:07 UTC (rev 17744)
@@ -139,4 +139,14 @@
 	int ExitCode;
 };
 
+
+class UnsupportedBuildToolException : public Exception
+{
+public:
+	UnsupportedBuildToolException ( const std::string& buildtool,
+	                                const std::string& version );
+	std::string BuildTool;
+	std::string Version;
+};
+
 #endif /* __EXCEPTION_H */