2 * Copyright (C) 2005 Casper S. Hornstrup
3 * 2006 Christoph von Wittich
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 #include "../../pch.h"
23 #include "modulehandler.h"
27 #define pclose _pclose
35 typedef set
<string
> set_string
;
38 MingwBackend::GetFullPath ( const FileLocation
& file
) const
40 MingwModuleHandler::PassThruCacheDirectory ( &file
);
43 switch ( file
.directory
)
48 case IntermediateDirectory
:
49 directory
= "$(INTERMEDIATE)";
52 directory
= "$(OUTPUT)";
54 case InstallDirectory
:
55 directory
= "$(INSTALL)";
57 case TemporaryDirectory
:
58 directory
= "$(TEMPORARY)";
61 throw InvalidOperationException ( __FILE__
,
63 "Invalid directory %d.",
67 if ( file
.relative_path
.length () > 0 )
69 if ( directory
.length () > 0 )
71 directory
+= file
.relative_path
;
77 MingwBackend::GetFullName ( const FileLocation
& file
) const
80 switch ( file
.directory
)
85 case IntermediateDirectory
:
86 directory
= "$(INTERMEDIATE)";
89 directory
= "$(OUTPUT)";
91 case InstallDirectory
:
92 directory
= "$(INSTALL)";
94 case TemporaryDirectory
:
95 directory
= "$(TEMPORARY)";
98 throw InvalidOperationException ( __FILE__
,
100 "Invalid directory %d.",
104 if ( file
.relative_path
.length () > 0 )
106 if ( directory
.length () > 0 )
108 directory
+= file
.relative_path
;
111 if ( directory
.length () > 0 )
114 return directory
+ file
.name
;
118 v2s ( const Backend
* backend
, const vector
<FileLocation
>& files
, int wrap_at
)
124 for ( size_t i
= 0; i
< files
.size(); i
++ )
126 const FileLocation
& file
= files
[i
];
127 if ( wrap_at
> 0 && wrap_count
++ == wrap_at
)
131 s
+= backend
->GetFullName ( file
);
138 v2s ( const string_list
& v
, int wrap_at
)
144 for ( size_t i
= 0; i
< v
.size(); i
++ )
148 if ( wrap_at
> 0 && wrap_count
++ == wrap_at
)
158 static class MingwFactory
: public Backend::Factory
161 MingwFactory() : Factory ( "mingw", "Minimalist GNU Win32" ) {}
162 Backend
* operator() ( Project
& project
,
163 Configuration
& configuration
)
165 return new MingwBackend ( project
,
171 MingwBackend::MingwBackend ( Project
& project
,
172 Configuration
& configuration
)
173 : Backend ( project
, configuration
),
174 manualBinutilsSetting( false ),
175 intermediateDirectory ( new Directory ( "" ) ),
176 outputDirectory ( new Directory ( "" ) ),
177 installDirectory ( new Directory ( "" ) )
182 MingwBackend::~MingwBackend()
184 delete intermediateDirectory
;
185 delete outputDirectory
;
186 delete installDirectory
;
190 MingwBackend::AddDirectoryTarget ( const string
& directory
,
191 Directory
* directoryTree
)
193 if ( directory
.length () > 0)
194 directoryTree
->Add ( directory
.c_str() );
195 return directoryTree
->name
;
199 MingwBackend::CanEnablePreCompiledHeaderSupportForModule ( const Module
& module
)
201 if ( !configuration
.CompilationUnitsEnabled
)
204 const vector
<CompilationUnit
*>& compilationUnits
= module
.non_if_data
.compilationUnits
;
206 for ( i
= 0; i
< compilationUnits
.size (); i
++ )
208 CompilationUnit
& compilationUnit
= *compilationUnits
[i
];
209 if ( compilationUnit
.GetFiles ().size () != 1 )
212 // intentionally make a copy so that we can append more work in
213 // the middle of processing without having to go recursive
214 vector
<If
*> v
= module
.non_if_data
.ifs
;
215 for ( i
= 0; i
< v
.size (); i
++ )
219 // check for sub-ifs to add to list
220 const vector
<If
*>& ifs
= rIf
.data
.ifs
;
221 for ( j
= 0; j
< ifs
.size (); j
++ )
222 v
.push_back ( ifs
[j
] );
223 const vector
<CompilationUnit
*>& compilationUnits
= rIf
.data
.compilationUnits
;
224 for ( j
= 0; j
< compilationUnits
.size (); j
++ )
226 CompilationUnit
& compilationUnit
= *compilationUnits
[j
];
227 if ( compilationUnit
.GetFiles ().size () != 1 )
235 MingwBackend::ProcessModules ()
237 printf ( "Processing modules..." );
239 vector
<MingwModuleHandler
*> v
;
242 for ( i
= 0; i
< ProjectNode
.modules
.size (); i
++ )
244 Module
& module
= *ProjectNode
.modules
[i
];
245 if ( !module
.enabled
)
247 MingwModuleHandler
* h
= MingwModuleHandler::InstanciateHandler (
250 h
->AddImplicitLibraries ( module
);
251 if ( use_pch
&& CanEnablePreCompiledHeaderSupportForModule ( module
) )
252 h
->EnablePreCompiledHeaderSupport ();
253 if ( module
.host
== HostDefault
)
255 module
.host
= h
->DefaultHost();
256 assert ( module
.host
!= HostDefault
);
261 size_t iend
= v
.size ();
263 for ( i
= 0; i
< iend
; i
++ )
264 v
[i
]->GenerateSourceMacro();
265 for ( i
= 0; i
< iend
; i
++ )
266 v
[i
]->GenerateObjectMacro();
267 fprintf ( fMakefile
, "\n" );
268 for ( i
= 0; i
< iend
; i
++ )
269 v
[i
]->GenerateTargetMacro();
270 fprintf ( fMakefile
, "\n" );
272 GenerateAllTarget ( v
);
273 GenerateInitTarget ();
274 GenerateRegTestsRunTarget ();
276 for ( i
= 0; i
< iend
; i
++ )
277 v
[i
]->GenerateOtherMacros();
279 for ( i
= 0; i
< iend
; i
++ )
281 MingwModuleHandler
& h
= *v
[i
];
282 h
.GeneratePreconditionDependencies ();
284 h
.GenerateInvocations ();
285 h
.GenerateCleanTarget ();
286 h
.GenerateInstallTarget ();
287 h
.GenerateDependsTarget ();
295 MingwBackend::Process ()
297 if ( configuration
.CheckDependenciesForModuleOnly
)
298 CheckAutomaticDependenciesForModuleOnly ();
304 MingwBackend::CheckAutomaticDependenciesForModuleOnly ()
306 if ( configuration
.AutomaticDependencies
)
308 Module
* module
= ProjectNode
.LocateModule ( configuration
.CheckDependenciesForModuleOnlyModule
);
309 if ( module
== NULL
)
311 printf ( "Module '%s' does not exist\n",
312 configuration
.CheckDependenciesForModuleOnlyModule
.c_str () );
316 printf ( "Checking automatic dependencies for module '%s'...",
317 module
->name
.c_str () );
318 AutomaticDependency
automaticDependency ( ProjectNode
);
319 automaticDependency
.CheckAutomaticDependenciesForModule ( *module
,
320 configuration
.Verbose
);
326 MingwBackend::ProcessNormal ()
330 DetectNetwideAssembler ();
331 DetectPipeSupport ();
335 GenerateGlobalVariables ();
336 GenerateXmlBuildFilesMacro ();
337 UnpackWineResources ();
339 GenerateInstallTarget ();
340 GenerateTestTarget ();
341 GenerateDirectoryTargets ();
342 GenerateDirectories ();
343 GenerateTestSupportCode ();
344 GenerateCompilationUnitSupportCode ();
346 GenerateProxyMakefiles ();
347 CheckAutomaticDependencies ();
352 MingwBackend::CreateMakefile ()
354 fMakefile
= fopen ( ProjectNode
.makefile
.c_str (), "w" );
356 throw AccessDeniedException ( ProjectNode
.makefile
);
357 MingwModuleHandler::SetBackend ( this );
358 MingwModuleHandler::SetMakefile ( fMakefile
);
362 MingwBackend::CloseMakefile () const
365 fclose ( fMakefile
);
369 MingwBackend::GenerateHeader () const
371 fprintf ( fMakefile
, "# THIS FILE IS AUTOMATICALLY GENERATED, EDIT '%s' INSTEAD\n\n",
372 ProjectNode
.GetProjectFilename ().c_str () );
376 MingwBackend::GenerateProjectCFlagsMacro ( const char* assignmentOperation
,
377 const IfableData
& data
) const
379 set
<string
> used_defs
;
381 if ( data
.includes
.size () > 0 )
384 "PROJECT_CFLAGS %s %s\n",
386 MingwModuleHandler::GenerateGccIncludeParametersFromVector ( data
.includes
).c_str ());
388 if ( data
.defines
.size () > 0 )
391 "PROJECT_CDEFINES %s %s\n",
393 MingwModuleHandler::GenerateGccDefineParametersFromVector ( data
.defines
, used_defs
).c_str ());
397 MingwBackend::GenerateGlobalCFlagsAndProperties (
398 const char* assignmentOperation
,
399 const IfableData
& data
) const
403 for ( i
= 0; i
< data
.properties
.size(); i
++ )
405 Property
& prop
= *data
.properties
[i
];
406 fprintf ( fMakefile
, "%s := %s\n",
408 prop
.value
.c_str() );
411 if ( data
.includes
.size() || data
.defines
.size() )
413 GenerateProjectCFlagsMacro ( assignmentOperation
,
417 for ( i
= 0; i
< data
.ifs
.size(); i
++ )
419 const If
& rIf
= *data
.ifs
[i
];
420 if ( rIf
.data
.defines
.size()
421 || rIf
.data
.includes
.size()
422 || rIf
.data
.ifs
.size() )
426 "ifeq (\"$(%s)\",\"%s\")\n",
427 rIf
.property
.c_str(),
429 GenerateGlobalCFlagsAndProperties (
440 MingwBackend::GenerateProjectGccOptionsMacro ( const char* assignmentOperation
,
441 IfableData
& data
) const
447 "PROJECT_GCCOPTIONS %s",
448 assignmentOperation
);
450 for ( i
= 0; i
< data
.compilerFlags
.size(); i
++ )
455 data
.compilerFlags
[i
]->flag
.c_str() );
458 fprintf ( fMakefile
, "\n" );
462 MingwBackend::GenerateProjectGccOptions (
463 const char* assignmentOperation
,
464 IfableData
& data
) const
468 if ( data
.compilerFlags
.size() )
470 GenerateProjectGccOptionsMacro ( assignmentOperation
,
474 for ( i
= 0; i
< data
.ifs
.size(); i
++ )
476 If
& rIf
= *data
.ifs
[i
];
477 if ( rIf
.data
.compilerFlags
.size()
478 || rIf
.data
.ifs
.size() )
482 "ifeq (\"$(%s)\",\"%s\")\n",
483 rIf
.property
.c_str(),
485 GenerateProjectGccOptions (
496 MingwBackend::GenerateProjectLFLAGS () const
499 for ( size_t i
= 0; i
< ProjectNode
.linkerFlags
.size (); i
++ )
501 LinkerFlag
& linkerFlag
= *ProjectNode
.linkerFlags
[i
];
502 if ( lflags
.length () > 0 )
504 lflags
+= linkerFlag
.flag
;
510 MingwBackend::GenerateGlobalVariables () const
514 compilerPrefix
.c_str () );
517 nasmCommand
.c_str () );
519 GenerateGlobalCFlagsAndProperties ( "=", ProjectNode
.non_if_data
);
520 GenerateProjectGccOptions ( "=", ProjectNode
.non_if_data
);
522 fprintf ( fMakefile
, "PROJECT_RCFLAGS := $(PROJECT_CFLAGS) $(PROJECT_CDEFINES)\n" );
523 fprintf ( fMakefile
, "PROJECT_WIDLFLAGS := $(PROJECT_CFLAGS) $(PROJECT_CDEFINES)\n" );
524 fprintf ( fMakefile
, "PROJECT_LFLAGS := %s\n",
525 GenerateProjectLFLAGS ().c_str () );
526 fprintf ( fMakefile
, "PROJECT_CFLAGS += -Wall\n" );
527 fprintf ( fMakefile
, "ifneq ($(OARCH),)\n" );
528 fprintf ( fMakefile
, "PROJECT_CFLAGS += -march=$(OARCH)\n" );
529 fprintf ( fMakefile
, "endif\n" );
530 fprintf ( fMakefile
, "PROJECT_CFLAGS += $(PROJECT_GCCOPTIONS)\n" );
531 fprintf ( fMakefile
, "\n" );
535 MingwBackend::IncludeInAllTarget ( const Module
& module
) const
537 if ( MingwModuleHandler::ReferenceObjects ( module
) )
539 if ( module
.type
== BootSector
)
541 if ( module
.type
== Iso
)
543 if ( module
.type
== LiveIso
)
545 if ( module
.type
== IsoRegTest
)
547 if ( module
.type
== LiveIsoRegTest
)
549 if ( module
.type
== Test
)
551 if ( module
.type
== Alias
)
557 MingwBackend::GenerateAllTarget ( const vector
<MingwModuleHandler
*>& handlers
) const
559 fprintf ( fMakefile
, "all:" );
561 size_t iend
= handlers
.size ();
562 for ( size_t i
= 0; i
< iend
; i
++ )
564 const Module
& module
= handlers
[i
]->module
;
565 if ( IncludeInAllTarget ( module
) )
567 if ( wrap_count
++ == 5 )
568 fprintf ( fMakefile
, " \\\n\t\t" ), wrap_count
= 0;
571 GetTargetMacro(module
).c_str () );
574 fprintf ( fMakefile
, "\n\t\n\n" );
578 MingwBackend::GetBuildToolDependencies () const
581 for ( size_t i
= 0; i
< ProjectNode
.modules
.size (); i
++ )
583 Module
& module
= *ProjectNode
.modules
[i
];
584 if ( !module
.enabled
)
586 if ( module
.type
== BuildTool
)
588 if ( dependencies
.length () > 0 )
590 dependencies
+= GetFullName ( *module
.dependency
);
597 MingwBackend::GenerateInitTarget () const
601 GetBuildToolDependencies ().c_str () );
602 fprintf ( fMakefile
, "\n" );
606 MingwBackend::GenerateRegTestsRunTarget () const
609 "REGTESTS_RUN_TARGET = regtests.dll\n" );
611 "$(REGTESTS_RUN_TARGET): $(REGTESTS_TARGET)\n" );
613 "\t$(cp) $(REGTESTS_TARGET) $(REGTESTS_RUN_TARGET)\n" );
614 fprintf ( fMakefile
, "\n" );
618 MingwBackend::GenerateXmlBuildFilesMacro() const
621 "XMLBUILDFILES = %s \\\n",
622 ProjectNode
.GetProjectFilename ().c_str () );
623 string xmlbuildFilenames
;
624 int numberOfExistingFiles
= 0;
626 time_t SystemTime
, lastWriteTime
;
628 for ( size_t i
= 0; i
< ProjectNode
.xmlbuildfiles
.size (); i
++ )
630 XMLInclude
& xmlbuildfile
= *ProjectNode
.xmlbuildfiles
[i
];
631 if ( !xmlbuildfile
.fileExists
)
633 numberOfExistingFiles
++;
634 if ( xmlbuildFilenames
.length () > 0 )
635 xmlbuildFilenames
+= " ";
637 FILE* f
= fopen ( xmlbuildfile
.topIncludeFilename
.c_str (), "rb" );
639 throw FileNotFoundException ( NormalizeFilename ( xmlbuildfile
.topIncludeFilename
) );
641 if ( fstat ( fileno ( f
), &statbuf
) != 0 )
644 throw AccessDeniedException ( NormalizeFilename ( xmlbuildfile
.topIncludeFilename
) );
647 lastWriteTime
= statbuf
.st_mtime
;
648 SystemTime
= time(NULL
);
650 if (SystemTime
!= -1)
652 if (difftime (lastWriteTime
, SystemTime
) > 0)
653 throw InvalidDateException ( NormalizeFilename ( xmlbuildfile
.topIncludeFilename
) );
658 xmlbuildFilenames
+= NormalizeFilename ( xmlbuildfile
.topIncludeFilename
);
659 if ( numberOfExistingFiles
% 5 == 4 || i
== ProjectNode
.xmlbuildfiles
.size () - 1 )
663 xmlbuildFilenames
.c_str ());
664 if ( i
== ProjectNode
.xmlbuildfiles
.size () - 1 )
666 fprintf ( fMakefile
, "\n" );
673 xmlbuildFilenames
.resize ( 0 );
675 numberOfExistingFiles
++;
677 fprintf ( fMakefile
, "\n" );
681 MingwBackend::GetBin2ResExecutable ()
683 return NormalizeFilename ( Environment::GetOutputPath () + sSep
+ "tools/bin2res/bin2res" + ExePostfix
);
687 MingwBackend::UnpackWineResources ()
689 printf ( "Unpacking WINE resources..." );
690 WineResource
wineResource ( ProjectNode
,
691 GetBin2ResExecutable () );
692 wineResource
.UnpackResources ( configuration
.Verbose
);
697 MingwBackend::GenerateTestSupportCode ()
699 printf ( "Generating test support code..." );
700 TestSupportCode
testSupportCode ( ProjectNode
);
701 testSupportCode
.GenerateTestSupportCode ( configuration
.Verbose
);
706 MingwBackend::GenerateCompilationUnitSupportCode ()
708 if ( configuration
.CompilationUnitsEnabled
)
710 printf ( "Generating compilation unit support code..." );
711 CompilationUnitSupportCode
compilationUnitSupportCode ( ProjectNode
);
712 compilationUnitSupportCode
.Generate ( configuration
.Verbose
);
718 MingwBackend::GenerateSysSetup ()
720 printf ( "Generating syssetup.inf..." );
721 SysSetupGenerator
sysSetupGenerator ( ProjectNode
);
722 sysSetupGenerator
.Generate ();
727 MingwBackend::GetProxyMakefileTree () const
729 if ( configuration
.GenerateProxyMakefilesInSourceTree
)
732 return Environment::GetOutputPath ();
736 MingwBackend::GenerateProxyMakefiles ()
738 printf ( "Generating proxy makefiles..." );
739 ProxyMakefile
proxyMakefile ( ProjectNode
);
740 proxyMakefile
.GenerateProxyMakefiles ( configuration
.Verbose
,
741 GetProxyMakefileTree () );
746 MingwBackend::CheckAutomaticDependencies ()
748 if ( configuration
.AutomaticDependencies
)
750 printf ( "Checking automatic dependencies..." );
751 AutomaticDependency
automaticDependency ( ProjectNode
);
752 automaticDependency
.CheckAutomaticDependencies ( configuration
.Verbose
);
758 MingwBackend::GenerateDirectories ()
760 printf ( "Creating directories..." );
761 intermediateDirectory
->GenerateTree ( IntermediateDirectory
, configuration
.Verbose
);
762 outputDirectory
->GenerateTree ( OutputDirectory
, configuration
.Verbose
);
763 if ( !configuration
.MakeHandlesInstallDirectories
)
764 installDirectory
->GenerateTree ( InstallDirectory
, configuration
.Verbose
);
769 MingwBackend::TryToDetectThisCompiler ( const string
& compiler
)
771 string command
= ssprintf (
773 FixSeparatorForSystemCommand(compiler
).c_str (),
776 int exitcode
= system ( command
.c_str () );
777 return (bool) (exitcode
== 0);
781 MingwBackend::DetectCompiler ()
783 printf ( "Detecting compiler..." );
785 bool detectedCompiler
= false;
786 const string
& ROS_PREFIXValue
= Environment::GetVariable ( "ROS_PREFIX" );
787 if ( ROS_PREFIXValue
.length () > 0 )
789 compilerPrefix
= ROS_PREFIXValue
;
790 compilerCommand
= compilerPrefix
+ "-gcc";
791 detectedCompiler
= TryToDetectThisCompiler ( compilerCommand
);
794 if ( !detectedCompiler
)
797 compilerCommand
= "gcc";
798 detectedCompiler
= TryToDetectThisCompiler ( compilerCommand
);
801 if ( !detectedCompiler
)
803 compilerPrefix
= "mingw32";
804 compilerCommand
= compilerPrefix
+ "-gcc";
805 detectedCompiler
= TryToDetectThisCompiler ( compilerCommand
);
808 if ( detectedCompiler
)
810 string compilerVersion
= GetCompilerVersion ( compilerCommand
);
811 if ( IsSupportedCompilerVersion ( compilerVersion
) )
812 printf ( "detected (%s %s)\n", compilerCommand
.c_str (), compilerVersion
.c_str() );
815 printf ( "detected (%s), but with unsupported version (%s)\n",
816 compilerCommand
.c_str (),
817 compilerVersion
.c_str () );
818 throw UnsupportedBuildToolException ( compilerCommand
, compilerVersion
);
822 printf ( "not detected\n" );
827 MingwBackend::TryToDetectThisNetwideAssembler ( const string
& assembler
)
829 string command
= ssprintf (
831 FixSeparatorForSystemCommand(assembler
).c_str (),
834 int exitcode
= system ( command
.c_str () );
835 return (bool) (exitcode
== 0);
839 MingwBackend::GetVersionString ( const string
& versionCommand
)
846 fp
= popen ( versionCommand
.c_str () , "r" );
849 ( feof ( fp
) == 0 &&
850 ( ( ch
= fgetc( fp
) ) != -1 ) );
853 buffer
[i
] = (char) ch
;
858 char separators
[] = " ";
860 char *prevtoken
= NULL
;
864 token
= strtok ( buffer
, separators
);
865 while ( token
!= NULL
)
868 version
= string( prevtoken
);
869 if ( (newline
= version
.find('\n')) != std::string::npos
)
870 version
.erase(newline
, 1);
871 if ( version
.find('.') != std::string::npos
)
873 token
= strtok ( NULL
, separators
);
879 MingwBackend::GetNetwideAssemblerVersion ( const string
& nasmCommand
)
881 string versionCommand
;
882 if ( nasmCommand
.find("yasm") != std::string::npos
)
884 versionCommand
= ssprintf ( "%s --version",
885 nasmCommand
.c_str (),
891 versionCommand
= ssprintf ( "%s -v",
892 nasmCommand
.c_str (),
896 return GetVersionString( versionCommand
);
900 MingwBackend::GetCompilerVersion ( const string
& compilerCommand
)
902 string versionCommand
= ssprintf ( "%s --version gcc",
903 compilerCommand
.c_str (),
906 return GetVersionString( versionCommand
);
910 MingwBackend::GetBinutilsVersion ( const string
& binutilsCommand
)
912 string versionCommand
= ssprintf ( "%s -v",
913 binutilsCommand
.c_str (),
916 return GetVersionString( versionCommand
);
920 MingwBackend::IsSupportedCompilerVersion ( const string
& compilerVersion
)
922 if ( strcmp ( compilerVersion
.c_str (), "3.4.2") < 0 )
929 MingwBackend::TryToDetectThisBinutils ( const string
& binutils
)
931 string command
= ssprintf (
933 FixSeparatorForSystemCommand(binutils
).c_str (),
936 int exitcode
= system ( command
.c_str () );
937 return (exitcode
== 0);
941 MingwBackend::GetBinutilsVersionDate ( const string
& binutilsCommand
)
947 string versionCommand
= ssprintf ( "%s -v",
948 binutilsCommand
.c_str (),
951 fp
= popen ( versionCommand
.c_str () , "r" );
954 ( feof ( fp
) == 0 &&
955 ( ( ch
= fgetc( fp
) ) != -1 ) );
958 buffer
[i
] = (char) ch
;
963 char separators
[] = " ";
965 char *prevtoken
= NULL
;
967 token
= strtok ( buffer
, separators
);
968 while ( token
!= NULL
)
971 token
= strtok ( NULL
, separators
);
973 string version
= string ( prevtoken
);
974 int lastDigit
= version
.find_last_not_of ( "\t\r\n" );
975 if ( lastDigit
!= -1 )
976 return string ( version
, 0, lastDigit
+1 );
982 MingwBackend::IsSupportedBinutilsVersion ( const string
& binutilsVersion
)
984 if ( manualBinutilsSetting
) return true;
987 if ( binutilsVersion
.find('.') != std::string::npos
)
989 /* TODO: blacklist versions on version number instead of date */
994 * - Binutils older than 2003/10/01 have broken windres which can't handle
995 * icons with alpha channel.
996 * - Binutils between 2004/09/02 and 2004/10/08 have broken handling of
997 * forward exports in dlltool.
999 if ( ( ( strcmp ( binutilsVersion
.c_str (), "20040902") >= 0 ) &&
1000 ( strcmp ( binutilsVersion
.c_str (), "20041008") <= 0 ) ) ||
1001 ( strcmp ( binutilsVersion
.c_str (), "20031001") < 0 ) )
1008 MingwBackend::DetectBinutils ()
1010 printf ( "Detecting binutils..." );
1012 bool detectedBinutils
= false;
1013 const string
& ROS_PREFIXValue
= Environment::GetVariable ( "ROS_PREFIX" );
1015 if ( ROS_PREFIXValue
.length () > 0 )
1017 binutilsPrefix
= ROS_PREFIXValue
;
1018 binutilsCommand
= binutilsPrefix
+ "-ld";
1019 manualBinutilsSetting
= true;
1020 detectedBinutils
= true;
1023 if ( !detectedBinutils
)
1025 binutilsPrefix
= "";
1026 binutilsCommand
= "ld";
1027 detectedBinutils
= TryToDetectThisBinutils ( binutilsCommand
);
1030 if ( !detectedBinutils
)
1032 binutilsPrefix
= "mingw32";
1033 binutilsCommand
= binutilsPrefix
+ "-ld";
1034 detectedBinutils
= TryToDetectThisBinutils ( binutilsCommand
);
1036 if ( detectedBinutils
)
1038 string binutilsVersion
= GetBinutilsVersionDate ( binutilsCommand
);
1039 if ( IsSupportedBinutilsVersion ( binutilsVersion
) )
1040 printf ( "detected (%s %s)\n", binutilsCommand
.c_str (), GetBinutilsVersion( binutilsCommand
).c_str() );
1043 printf ( "detected (%s), but with unsupported version (%s)\n",
1044 binutilsCommand
.c_str (),
1045 binutilsVersion
.c_str () );
1046 throw UnsupportedBuildToolException ( binutilsCommand
, binutilsVersion
);
1050 printf ( "not detected\n" );
1055 MingwBackend::DetectNetwideAssembler ()
1057 printf ( "Detecting netwide assembler..." );
1059 nasmCommand
= "nasm";
1060 bool detectedNasm
= TryToDetectThisNetwideAssembler ( nasmCommand
);
1062 if ( !detectedNasm
)
1064 nasmCommand
= "nasmw";
1065 detectedNasm
= TryToDetectThisNetwideAssembler ( nasmCommand
);
1068 if ( !detectedNasm
)
1070 nasmCommand
= "yasm";
1071 detectedNasm
= TryToDetectThisNetwideAssembler ( nasmCommand
);
1074 printf ( "detected (%s %s)\n", nasmCommand
.c_str (), GetNetwideAssemblerVersion( nasmCommand
).c_str() );
1076 printf ( "not detected\n" );
1080 MingwBackend::DetectPipeSupport ()
1082 printf ( "Detecting compiler -pipe support..." );
1084 string pipe_detection
= "tools" + sSep
+ "rbuild" + sSep
+ "backend" + sSep
+ "mingw" + sSep
+ "pipe_detection.c";
1085 string pipe_detectionObjectFilename
= ReplaceExtension ( pipe_detection
,
1087 string command
= ssprintf (
1088 "%s -pipe -c %s -o %s 1>%s 2>%s",
1089 FixSeparatorForSystemCommand(compilerCommand
).c_str (),
1090 pipe_detection
.c_str (),
1091 pipe_detectionObjectFilename
.c_str (),
1094 int exitcode
= system ( command
.c_str () );
1095 FILE* f
= fopen ( pipe_detectionObjectFilename
.c_str (), "rb" );
1098 usePipe
= (exitcode
== 0);
1100 unlink ( pipe_detectionObjectFilename
.c_str () );
1106 printf ( "detected\n" );
1108 printf ( "not detected\n" );
1112 MingwBackend::DetectPCHSupport ()
1114 printf ( "Detecting compiler pre-compiled header support..." );
1116 string path
= "tools" + sSep
+ "rbuild" + sSep
+ "backend" + sSep
+ "mingw" + sSep
+ "pch_detection.h";
1117 string cmd
= ssprintf (
1118 "%s -c %s 1>%s 2>%s",
1119 FixSeparatorForSystemCommand(compilerCommand
).c_str (),
1123 system ( cmd
.c_str () );
1126 FILE* f
= fopen ( path
.c_str (), "rb" );
1131 unlink ( path
.c_str () );
1137 printf ( "detected\n" );
1139 printf ( "not detected\n" );
1143 MingwBackend::GetNonModuleInstallTargetFiles (
1144 vector
<FileLocation
>& out
) const
1146 for ( size_t i
= 0; i
< ProjectNode
.installfiles
.size (); i
++ )
1148 const InstallFile
& installfile
= *ProjectNode
.installfiles
[i
];
1149 out
.push_back ( *installfile
.target
);
1154 MingwBackend::GetModuleInstallTargetFiles (
1155 vector
<FileLocation
>& out
) const
1157 for ( size_t i
= 0; i
< ProjectNode
.modules
.size (); i
++ )
1159 const Module
& module
= *ProjectNode
.modules
[i
];
1160 if ( !module
.enabled
)
1162 if ( module
.install
)
1163 out
.push_back ( *module
.install
);
1168 MingwBackend::GetInstallTargetFiles (
1169 vector
<FileLocation
>& out
) const
1171 GetNonModuleInstallTargetFiles ( out
);
1172 GetModuleInstallTargetFiles ( out
);
1176 MingwBackend::OutputInstallTarget ( const FileLocation
& source
,
1177 const FileLocation
& target
)
1179 fprintf ( fMakefile
,
1181 GetFullName ( target
).c_str (),
1182 GetFullName ( source
).c_str (),
1183 GetFullPath ( target
).c_str () );
1184 fprintf ( fMakefile
,
1186 fprintf ( fMakefile
,
1187 "\t${cp} %s %s 1>$(NUL)\n",
1188 GetFullName ( source
).c_str (),
1189 GetFullName ( target
).c_str () );
1193 MingwBackend::OutputNonModuleInstallTargets ()
1195 for ( size_t i
= 0; i
< ProjectNode
.installfiles
.size (); i
++ )
1197 const InstallFile
& installfile
= *ProjectNode
.installfiles
[i
];
1198 OutputInstallTarget ( *installfile
.source
, *installfile
.target
);
1203 MingwBackend::GetAliasedModuleOrModule ( const Module
& module
) const
1205 if ( module
.aliasedModuleName
.size () > 0 )
1207 const Module
* aliasedModule
= ProjectNode
.LocateModule ( module
.aliasedModuleName
);
1208 assert ( aliasedModule
);
1209 return *aliasedModule
;
1216 MingwBackend::OutputModuleInstallTargets ()
1218 for ( size_t i
= 0; i
< ProjectNode
.modules
.size (); i
++ )
1220 const Module
& module
= *ProjectNode
.modules
[i
];
1221 if ( !module
.enabled
)
1223 if ( module
.install
)
1225 const Module
& aliasedModule
= GetAliasedModuleOrModule ( module
);
1226 OutputInstallTarget ( *aliasedModule
.output
, *module
.install
);
1232 MingwBackend::GetRegistrySourceFiles ()
1234 return "boot" + sSep
+ "bootdata" + sSep
+ "hivecls.inf "
1235 "boot" + sSep
+ "bootdata" + sSep
+ "hivedef.inf "
1236 "boot" + sSep
+ "bootdata" + sSep
+ "hiveinst.inf "
1237 "boot" + sSep
+ "bootdata" + sSep
+ "hivesft.inf "
1238 "boot" + sSep
+ "bootdata" + sSep
+ "hivesys.inf";
1242 MingwBackend::GetRegistryTargetFiles ()
1244 string system32ConfigDirectory
= "system32" + sSep
+ "config";
1245 FileLocation
system32 ( InstallDirectory
, system32ConfigDirectory
, "" );
1247 vector
<FileLocation
> registry_files
;
1248 registry_files
.push_back ( FileLocation ( InstallDirectory
, system32ConfigDirectory
, "default" ) );
1249 registry_files
.push_back ( FileLocation ( InstallDirectory
, system32ConfigDirectory
, "sam" ) );
1250 registry_files
.push_back ( FileLocation ( InstallDirectory
, system32ConfigDirectory
, "security" ) );
1251 registry_files
.push_back ( FileLocation ( InstallDirectory
, system32ConfigDirectory
, "software" ) );
1252 registry_files
.push_back ( FileLocation ( InstallDirectory
, system32ConfigDirectory
, "system" ) );
1254 return v2s( this, registry_files
, 6 );
1258 MingwBackend::OutputRegistryInstallTarget ()
1260 FileLocation
system32 ( InstallDirectory
, "system32" + sSep
+ "config", "" );
1262 string registrySourceFiles
= GetRegistrySourceFiles ();
1263 string registryTargetFiles
= GetRegistryTargetFiles ();
1264 fprintf ( fMakefile
,
1265 "install_registry: %s\n",
1266 registryTargetFiles
.c_str () );
1267 fprintf ( fMakefile
,
1268 "%s: %s %s $(MKHIVE_TARGET)\n",
1269 registryTargetFiles
.c_str (),
1270 registrySourceFiles
.c_str (),
1271 GetFullPath ( system32
).c_str () );
1272 fprintf ( fMakefile
,
1273 "\t$(ECHO_MKHIVE)\n" );
1274 fprintf ( fMakefile
,
1275 "\t$(MKHIVE_TARGET) boot%cbootdata %s boot%cbootdata%chiveinst.inf\n",
1276 cSep
, GetFullPath ( system32
).c_str (),
1278 fprintf ( fMakefile
,
1283 MingwBackend::GenerateInstallTarget ()
1285 vector
<FileLocation
> vInstallTargetFiles
;
1286 GetInstallTargetFiles ( vInstallTargetFiles
);
1287 string installTargetFiles
= v2s ( this, vInstallTargetFiles
, 5 );
1288 string registryTargetFiles
= GetRegistryTargetFiles ();
1290 fprintf ( fMakefile
,
1292 installTargetFiles
.c_str (),
1293 registryTargetFiles
.c_str () );
1294 OutputNonModuleInstallTargets ();
1295 OutputModuleInstallTargets ();
1296 OutputRegistryInstallTarget ();
1297 fprintf ( fMakefile
,
1302 MingwBackend::GetModuleTestTargets (
1303 vector
<string
>& out
) const
1305 for ( size_t i
= 0; i
< ProjectNode
.modules
.size (); i
++ )
1307 const Module
& module
= *ProjectNode
.modules
[i
];
1308 if ( !module
.enabled
)
1310 if ( module
.type
== Test
)
1311 out
.push_back ( module
.name
);
1316 MingwBackend::GenerateTestTarget ()
1318 vector
<string
> vTestTargets
;
1319 GetModuleTestTargets ( vTestTargets
);
1320 string testTargets
= v2s ( vTestTargets
, 5 );
1322 fprintf ( fMakefile
,
1324 testTargets
.c_str () );
1325 fprintf ( fMakefile
,
1330 MingwBackend::GenerateDirectoryTargets ()
1332 intermediateDirectory
->CreateRule ( fMakefile
, "$(INTERMEDIATE)" );
1333 outputDirectory
->CreateRule ( fMakefile
, "$(OUTPUT)" );
1334 installDirectory
->CreateRule ( fMakefile
, "$(INSTALL)" );