Autodetect nasm
[reactos.git] / reactos / tools / rbuild / backend / mingw / mingw.cpp
1
2 #include "../../pch.h"
3
4 #include "mingw.h"
5 #include <assert.h>
6 #include <dirent.h>
7 #include "modulehandler.h"
8
9 #ifdef WIN32
10 #define MKDIR(s) mkdir(s)
11 #else
12 #define MKDIR(s) mkdir(s, 0755)
13 #endif
14
15 using std::string;
16 using std::vector;
17 using std::set;
18 using std::map;
19
20 typedef set<string> set_string;
21
22
23 string
24 v2s ( const string_list& v, int wrap_at )
25 {
26 if ( !v.size() )
27 return "";
28 string s;
29 int wrap_count = 0;
30 for ( size_t i = 0; i < v.size(); i++ )
31 {
32 if ( !v[i].size() )
33 continue;
34 if ( wrap_at > 0 && wrap_count++ == wrap_at )
35 s += " \\\n\t\t";
36 else if ( s.size() )
37 s += " ";
38 s += v[i];
39 }
40 return s;
41 }
42
43
44 Directory::Directory ( const string& name_ )
45 : name(name_)
46 {
47 }
48
49 void
50 Directory::Add ( const char* subdir )
51 {
52 size_t i;
53 string s1 = string ( subdir );
54 if ( ( i = s1.find ( '$' ) ) != string::npos )
55 {
56 throw InvalidOperationException ( __FILE__,
57 __LINE__,
58 "No environment variables can be used here. Path was %s",
59 subdir );
60 }
61
62 const char* p = strpbrk ( subdir, "/\\" );
63 if ( !p )
64 p = subdir + strlen(subdir);
65 string s ( subdir, p-subdir );
66 if ( subdirs.find(s) == subdirs.end() )
67 subdirs[s] = new Directory(s);
68 if ( *p && *++p )
69 subdirs[s]->Add ( p );
70 }
71
72 bool
73 Directory::mkdir_p ( const char* path )
74 {
75 DIR *directory;
76 directory = opendir ( path );
77 if ( directory != NULL )
78 {
79 closedir ( directory );
80 return false;
81 }
82
83 if ( MKDIR ( path ) != 0 )
84 throw AccessDeniedException ( string ( path ) );
85 return true;
86 }
87
88 bool
89 Directory::CreateDirectory ( string path )
90 {
91 size_t index = 0;
92 size_t nextIndex;
93 if ( isalpha ( path[0] ) && path[1] == ':' && path[2] == CSEP )
94 {
95 nextIndex = path.find ( CSEP, 3);
96 }
97 else
98 nextIndex = path.find ( CSEP );
99
100 bool directoryWasCreated = false;
101 while ( nextIndex != string::npos )
102 {
103 nextIndex = path.find ( CSEP, index + 1 );
104 directoryWasCreated = mkdir_p ( path.substr ( 0, nextIndex ).c_str () );
105 index = nextIndex;
106 }
107 return directoryWasCreated;
108 }
109
110 string
111 Directory::ReplaceVariable ( string name,
112 string value,
113 string path )
114 {
115 size_t i = path.find ( name );
116 if ( i != string::npos )
117 return path.replace ( i, name.length (), value );
118 else
119 return path;
120 }
121
122 void
123 Directory::ResolveVariablesInPath ( char* buf,
124 string path )
125 {
126 string s = ReplaceVariable ( "$(INTERMEDIATE)", Environment::GetIntermediatePath (), path );
127 s = ReplaceVariable ( "$(OUTPUT)", Environment::GetOutputPath (), s );
128 s = ReplaceVariable ( "$(INSTALL)", Environment::GetInstallPath (), s );
129 strcpy ( buf, s.c_str () );
130 }
131
132 void
133 Directory::GenerateTree ( const string& parent,
134 bool verbose )
135 {
136 string path;
137
138 if ( parent.size () > 0 )
139 {
140 char buf[256];
141
142 path = parent + SSEP + name;
143 ResolveVariablesInPath ( buf, path );
144 if ( CreateDirectory ( buf ) && verbose )
145 printf ( "Created %s\n", buf );
146 }
147 else
148 path = name;
149
150 for ( directory_map::iterator i = subdirs.begin ();
151 i != subdirs.end ();
152 ++i )
153 {
154 i->second->GenerateTree ( path, verbose );
155 }
156 }
157
158 string
159 Directory::EscapeSpaces ( string path )
160 {
161 string newpath;
162 char* p = &path[0];
163 while ( *p != 0 )
164 {
165 if ( *p == ' ' )
166 newpath = newpath + "\\ ";
167 else
168 newpath = newpath + *p;
169 *p++;
170 }
171 return newpath;
172 }
173
174 void
175 Directory::CreateRule ( FILE* f,
176 const string& parent )
177 {
178 string path;
179
180 if ( parent.size() > 0 )
181 {
182 string escapedParent = EscapeSpaces ( parent );
183 fprintf ( f,
184 "%s%c%s: | %s\n",
185 escapedParent.c_str (),
186 CSEP,
187 EscapeSpaces ( name ).c_str (),
188 escapedParent.c_str () );
189
190 fprintf ( f,
191 "\t$(ECHO_MKDIR)\n" );
192
193 fprintf ( f,
194 "\t${mkdir} $@\n" );
195
196 path = parent + SSEP + name;
197 }
198 else
199 path = name;
200
201 for ( directory_map::iterator i = subdirs.begin();
202 i != subdirs.end();
203 ++i )
204 {
205 i->second->CreateRule ( f, path );
206 }
207 }
208
209
210 static class MingwFactory : public Backend::Factory
211 {
212 public:
213 MingwFactory() : Factory ( "mingw" ) {}
214 Backend* operator() ( Project& project,
215 Configuration& configuration )
216 {
217 return new MingwBackend ( project,
218 configuration );
219 }
220 } factory;
221
222
223 MingwBackend::MingwBackend ( Project& project,
224 Configuration& configuration )
225 : Backend ( project, configuration ),
226 intermediateDirectory ( new Directory ("$(INTERMEDIATE)" ) ),
227 outputDirectory ( new Directory ( "$(OUTPUT)" ) ),
228 installDirectory ( new Directory ( "$(INSTALL)" ) )
229 {
230 compilerPrefix = "";
231 }
232
233 MingwBackend::~MingwBackend()
234 {
235 delete intermediateDirectory;
236 delete outputDirectory;
237 delete installDirectory;
238 }
239
240 string
241 MingwBackend::AddDirectoryTarget ( const string& directory,
242 Directory* directoryTree )
243 {
244 if ( directory.length () > 0)
245 directoryTree->Add ( directory.c_str() );
246 return directoryTree->name;
247 }
248
249 void
250 MingwBackend::ProcessModules ()
251 {
252 printf ( "Processing modules..." );
253
254 vector<MingwModuleHandler*> v;
255 size_t i;
256 for ( i = 0; i < ProjectNode.modules.size (); i++ )
257 {
258 Module& module = *ProjectNode.modules[i];
259 MingwModuleHandler* h = MingwModuleHandler::InstanciateHandler (
260 module,
261 this );
262 if ( module.host == HostDefault )
263 {
264 module.host = h->DefaultHost();
265 assert ( module.host != HostDefault );
266 }
267 v.push_back ( h );
268 }
269
270 size_t iend = v.size ();
271
272 for ( i = 0; i < iend; i++ )
273 v[i]->GenerateObjectMacro();
274 fprintf ( fMakefile, "\n" );
275 for ( i = 0; i < iend; i++ )
276 v[i]->GenerateTargetMacro();
277 fprintf ( fMakefile, "\n" );
278
279 GenerateAllTarget ( v );
280 GenerateInitTarget ();
281 GenerateRegTestsRunTarget ();
282
283 for ( i = 0; i < iend; i++ )
284 v[i]->GenerateOtherMacros();
285
286 for ( i = 0; i < iend; i++ )
287 {
288 MingwModuleHandler& h = *v[i];
289 h.GeneratePreconditionDependencies ();
290 h.Process ();
291 h.GenerateInvocations ();
292 h.GenerateCleanTarget ();
293 h.GenerateInstallTarget ();
294 delete v[i];
295 }
296
297 printf ( "done\n" );
298 }
299
300 void
301 MingwBackend::Process ()
302 {
303 DetectCompiler ();
304 DetectNetwideAssembler ();
305 DetectPipeSupport ();
306 DetectPCHSupport ();
307 CreateMakefile ();
308 GenerateHeader ();
309 GenerateGlobalVariables ();
310 GenerateXmlBuildFilesMacro ();
311 ProcessModules ();
312 GenerateInstallTarget ();
313 GenerateTestTarget ();
314 GenerateDirectoryTargets ();
315 GenerateDirectories ();
316 UnpackWineResources ();
317 GenerateTestSupportCode ();
318 GenerateProxyMakefiles ();
319 CheckAutomaticDependencies ();
320 CloseMakefile ();
321 }
322
323 void
324 MingwBackend::CreateMakefile ()
325 {
326 fMakefile = fopen ( ProjectNode.makefile.c_str (), "w" );
327 if ( !fMakefile )
328 throw AccessDeniedException ( ProjectNode.makefile );
329 MingwModuleHandler::SetBackend ( this );
330 MingwModuleHandler::SetMakefile ( fMakefile );
331 MingwModuleHandler::SetUsePch ( use_pch );
332 }
333
334 void
335 MingwBackend::CloseMakefile () const
336 {
337 if (fMakefile)
338 fclose ( fMakefile );
339 }
340
341 void
342 MingwBackend::GenerateHeader () const
343 {
344 fprintf ( fMakefile, "# THIS FILE IS AUTOMATICALLY GENERATED, EDIT 'ReactOS.xml' INSTEAD\n\n" );
345 }
346
347 string
348 MingwBackend::GenerateIncludesAndDefines ( IfableData& data ) const
349 {
350 string includeParameters = MingwModuleHandler::GenerateGccIncludeParametersFromVector ( data.includes );
351 string defineParameters = MingwModuleHandler::GenerateGccDefineParametersFromVector ( data.defines );
352 return includeParameters + " " + defineParameters;
353 }
354
355 void
356 MingwBackend::GenerateProjectCFlagsMacro ( const char* assignmentOperation,
357 IfableData& data ) const
358 {
359 fprintf (
360 fMakefile,
361 "PROJECT_CFLAGS %s",
362 assignmentOperation );
363
364 fprintf ( fMakefile,
365 " %s",
366 GenerateIncludesAndDefines ( data ).c_str() );
367
368 fprintf ( fMakefile, "\n" );
369 }
370
371 void
372 MingwBackend::GenerateGlobalCFlagsAndProperties (
373 const char* assignmentOperation,
374 IfableData& data ) const
375 {
376 size_t i;
377
378 for ( i = 0; i < data.properties.size(); i++ )
379 {
380 Property& prop = *data.properties[i];
381 fprintf ( fMakefile, "%s := %s\n",
382 prop.name.c_str(),
383 prop.value.c_str() );
384 }
385
386 if ( data.includes.size() || data.defines.size() )
387 {
388 GenerateProjectCFlagsMacro ( assignmentOperation,
389 data );
390 }
391
392 for ( i = 0; i < data.ifs.size(); i++ )
393 {
394 If& rIf = *data.ifs[i];
395 if ( rIf.data.defines.size()
396 || rIf.data.includes.size()
397 || rIf.data.ifs.size() )
398 {
399 fprintf (
400 fMakefile,
401 "ifeq (\"$(%s)\",\"%s\")\n",
402 rIf.property.c_str(),
403 rIf.value.c_str() );
404 GenerateGlobalCFlagsAndProperties (
405 "+=",
406 rIf.data );
407 fprintf (
408 fMakefile,
409 "endif\n\n" );
410 }
411 }
412 }
413
414 void
415 MingwBackend::GenerateProjectGccOptionsMacro ( const char* assignmentOperation,
416 IfableData& data ) const
417 {
418 size_t i;
419
420 fprintf (
421 fMakefile,
422 "PROJECT_GCCOPTIONS %s",
423 assignmentOperation );
424
425 for ( i = 0; i < data.compilerFlags.size(); i++ )
426 {
427 fprintf (
428 fMakefile,
429 " %s",
430 data.compilerFlags[i]->flag.c_str() );
431 }
432
433 fprintf ( fMakefile, "\n" );
434 }
435
436 void
437 MingwBackend::GenerateProjectGccOptions (
438 const char* assignmentOperation,
439 IfableData& data ) const
440 {
441 size_t i;
442
443 if ( data.compilerFlags.size() )
444 {
445 GenerateProjectGccOptionsMacro ( assignmentOperation,
446 data );
447 }
448
449 for ( i = 0; i < data.ifs.size(); i++ )
450 {
451 If& rIf = *data.ifs[i];
452 if ( rIf.data.compilerFlags.size()
453 || rIf.data.ifs.size() )
454 {
455 fprintf (
456 fMakefile,
457 "ifeq (\"$(%s)\",\"%s\")\n",
458 rIf.property.c_str(),
459 rIf.value.c_str() );
460 GenerateProjectGccOptions (
461 "+=",
462 rIf.data );
463 fprintf (
464 fMakefile,
465 "endif\n\n" );
466 }
467 }
468 }
469
470 string
471 MingwBackend::GenerateProjectLFLAGS () const
472 {
473 string lflags;
474 for ( size_t i = 0; i < ProjectNode.linkerFlags.size (); i++ )
475 {
476 LinkerFlag& linkerFlag = *ProjectNode.linkerFlags[i];
477 if ( lflags.length () > 0 )
478 lflags += " ";
479 lflags += linkerFlag.flag;
480 }
481 return lflags;
482 }
483
484 void
485 MingwBackend::GenerateGlobalVariables () const
486 {
487 fprintf ( fMakefile,
488 "PREFIX := %s\n",
489 compilerPrefix.c_str () );
490 fprintf ( fMakefile,
491 "nasm := %s\n",
492 nasmCommand.c_str () );
493
494 GenerateGlobalCFlagsAndProperties ( "=", ProjectNode.non_if_data );
495 GenerateProjectGccOptions ( "=", ProjectNode.non_if_data );
496
497 fprintf ( fMakefile, "PROJECT_RCFLAGS := $(PROJECT_CFLAGS)\n" );
498 fprintf ( fMakefile, "PROJECT_WIDLFLAGS := $(PROJECT_CFLAGS)\n" );
499 fprintf ( fMakefile, "PROJECT_LFLAGS := %s\n",
500 GenerateProjectLFLAGS ().c_str () );
501 fprintf ( fMakefile, "PROJECT_CFLAGS += -Wall\n" );
502 fprintf ( fMakefile, "PROJECT_CFLAGS += $(PROJECT_GCCOPTIONS)\n" );
503 fprintf ( fMakefile, "\n" );
504 }
505
506 bool
507 MingwBackend::IncludeInAllTarget ( const Module& module ) const
508 {
509 if ( MingwModuleHandler::ReferenceObjects ( module ) )
510 return false;
511 if ( module.type == BootSector )
512 return false;
513 if ( module.type == Iso )
514 return false;
515 if ( module.type == LiveIso )
516 return false;
517 if ( module.type == Test )
518 return false;
519 return true;
520 }
521
522 void
523 MingwBackend::GenerateAllTarget ( const vector<MingwModuleHandler*>& handlers ) const
524 {
525 fprintf ( fMakefile, "all:" );
526 int wrap_count = 0;
527 size_t iend = handlers.size ();
528 for ( size_t i = 0; i < iend; i++ )
529 {
530 const Module& module = handlers[i]->module;
531 if ( IncludeInAllTarget ( module ) )
532 {
533 if ( wrap_count++ == 5 )
534 fprintf ( fMakefile, " \\\n\t\t" ), wrap_count = 0;
535 fprintf ( fMakefile,
536 " %s",
537 GetTargetMacro(module).c_str () );
538 }
539 }
540 fprintf ( fMakefile, "\n\t\n\n" );
541 }
542
543 string
544 MingwBackend::GetBuildToolDependencies () const
545 {
546 string dependencies;
547 for ( size_t i = 0; i < ProjectNode.modules.size (); i++ )
548 {
549 Module& module = *ProjectNode.modules[i];
550 if ( module.type == BuildTool )
551 {
552 if ( dependencies.length () > 0 )
553 dependencies += " ";
554 dependencies += module.GetDependencyPath ();
555 }
556 }
557 return dependencies;
558 }
559
560 void
561 MingwBackend::GenerateInitTarget () const
562 {
563 fprintf ( fMakefile,
564 "INIT = %s\n",
565 GetBuildToolDependencies ().c_str () );
566 fprintf ( fMakefile, "\n" );
567 }
568
569 void
570 MingwBackend::GenerateRegTestsRunTarget () const
571 {
572 fprintf ( fMakefile,
573 "REGTESTS_RUN_TARGET = regtests.dll\n" );
574 fprintf ( fMakefile,
575 "$(REGTESTS_RUN_TARGET):\n" );
576 fprintf ( fMakefile,
577 "\t$(cp) $(REGTESTS_TARGET) $(REGTESTS_RUN_TARGET)\n" );
578 fprintf ( fMakefile, "\n" );
579 }
580
581 void
582 MingwBackend::GenerateXmlBuildFilesMacro() const
583 {
584 fprintf ( fMakefile,
585 "XMLBUILDFILES = %s \\\n",
586 ProjectNode.GetProjectFilename ().c_str () );
587 string xmlbuildFilenames;
588 int numberOfExistingFiles = 0;
589 for ( size_t i = 0; i < ProjectNode.xmlbuildfiles.size (); i++ )
590 {
591 XMLInclude& xmlbuildfile = *ProjectNode.xmlbuildfiles[i];
592 if ( !xmlbuildfile.fileExists )
593 continue;
594 numberOfExistingFiles++;
595 if ( xmlbuildFilenames.length () > 0 )
596 xmlbuildFilenames += " ";
597 xmlbuildFilenames += NormalizeFilename ( xmlbuildfile.topIncludeFilename );
598 if ( numberOfExistingFiles % 5 == 4 || i == ProjectNode.xmlbuildfiles.size () - 1 )
599 {
600 fprintf ( fMakefile,
601 "\t%s",
602 xmlbuildFilenames.c_str ());
603 if ( i == ProjectNode.xmlbuildfiles.size () - 1 )
604 {
605 fprintf ( fMakefile, "\n" );
606 }
607 else
608 {
609 fprintf ( fMakefile,
610 " \\\n" );
611 }
612 xmlbuildFilenames.resize ( 0 );
613 }
614 numberOfExistingFiles++;
615 }
616 fprintf ( fMakefile, "\n" );
617 }
618
619 string
620 MingwBackend::GetBin2ResExecutable ()
621 {
622 return NormalizeFilename ( Environment::GetOutputPath () + SSEP + "tools/bin2res/bin2res" + EXEPOSTFIX );
623 }
624
625 void
626 MingwBackend::UnpackWineResources ()
627 {
628 printf ( "Unpacking WINE resources..." );
629 WineResource wineResource ( ProjectNode,
630 GetBin2ResExecutable () );
631 wineResource.UnpackResources ( configuration.Verbose );
632 printf ( "done\n" );
633 }
634
635 void
636 MingwBackend::GenerateTestSupportCode ()
637 {
638 printf ( "Generating test support code..." );
639 TestSupportCode testSupportCode ( ProjectNode );
640 testSupportCode.GenerateTestSupportCode ( configuration.Verbose );
641 printf ( "done\n" );
642 }
643
644 void
645 MingwBackend::GenerateProxyMakefiles ()
646 {
647 printf ( "Generating proxy makefiles..." );
648 ProxyMakefile proxyMakefile ( ProjectNode );
649 proxyMakefile.GenerateProxyMakefiles ( configuration.Verbose );
650 printf ( "done\n" );
651 }
652
653 void
654 MingwBackend::CheckAutomaticDependencies ()
655 {
656 if ( configuration.AutomaticDependencies )
657 {
658 printf ( "Checking automatic dependencies..." );
659 AutomaticDependency automaticDependency ( ProjectNode );
660 automaticDependency.Process ();
661 automaticDependency.CheckAutomaticDependencies ( configuration.Verbose );
662 printf ( "done\n" );
663 }
664 }
665
666 bool
667 MingwBackend::IncludeDirectoryTarget ( const string& directory ) const
668 {
669 if ( directory == "$(INTERMEDIATE)" SSEP "tools")
670 return false;
671 else
672 return true;
673 }
674
675 void
676 MingwBackend::GenerateDirectories ()
677 {
678 printf ( "Creating directories..." );
679 intermediateDirectory->GenerateTree ( "", configuration.Verbose );
680 outputDirectory->GenerateTree ( "", configuration.Verbose );
681 if ( !configuration.MakeHandlesInstallDirectories )
682 installDirectory->GenerateTree ( "", configuration.Verbose );
683 printf ( "done\n" );
684 }
685
686 bool
687 MingwBackend::TryToDetectThisCompiler ( const string& compiler )
688 {
689 string command = ssprintf (
690 "%s -v 1>%s 2>%s",
691 compiler.c_str (),
692 NUL,
693 NUL );
694 int exitcode = system ( command.c_str () );
695 return (exitcode == 0);
696 }
697
698 void
699 MingwBackend::DetectCompiler ()
700 {
701 printf ( "Detecting compiler..." );
702
703 bool detectedCompiler = false;
704 const string& ROS_PREFIXValue = Environment::GetVariable ( "ROS_PREFIX" );
705 if ( ROS_PREFIXValue.length () > 0 )
706 {
707 compilerPrefix = ROS_PREFIXValue;
708 compilerCommand = compilerPrefix + "-gcc";
709 detectedCompiler = TryToDetectThisCompiler ( compilerCommand );
710 }
711 #if defined(WIN32)
712 if ( !detectedCompiler )
713 {
714 compilerPrefix = "";
715 compilerCommand = "gcc";
716 detectedCompiler = TryToDetectThisCompiler ( compilerCommand );
717 }
718 #endif
719 if ( !detectedCompiler )
720 {
721 compilerPrefix = "mingw32";
722 compilerCommand = compilerPrefix + "-gcc";
723 detectedCompiler = TryToDetectThisCompiler ( compilerCommand );
724 }
725 if ( detectedCompiler )
726 printf ( "detected (%s)\n", compilerCommand.c_str () );
727 else
728 printf ( "not detected\n" );
729 }
730
731 bool
732 MingwBackend::TryToDetectThisNetwideAssembler ( const string& assembler )
733 {
734 string command = ssprintf (
735 "%s -h 1>%s 2>%s",
736 assembler.c_str (),
737 NUL,
738 NUL );
739 int exitcode = system ( command.c_str () );
740 return (exitcode == 0);
741 }
742
743 void
744 MingwBackend::DetectNetwideAssembler ()
745 {
746 printf ( "Detecting netwide assembler..." );
747
748 nasmCommand = "nasm";
749 bool detectedNasm = TryToDetectThisNetwideAssembler ( nasmCommand );
750 #if defined(WIN32)
751 if ( !detectedNasm )
752 {
753 nasmCommand = "nasmw";
754 detectedNasm = TryToDetectThisNetwideAssembler ( nasmCommand );
755 }
756 #endif
757 if ( detectedNasm )
758 printf ( "detected (%s)\n", nasmCommand.c_str () );
759 else
760 printf ( "not detected\n" );
761 }
762
763 void
764 MingwBackend::DetectPipeSupport ()
765 {
766 printf ( "Detecting compiler -pipe support..." );
767
768 string pipe_detection = "tools" SSEP "rbuild" SSEP "backend" SSEP "mingw" SSEP "pipe_detection.c";
769 string pipe_detectionObjectFilename = ReplaceExtension ( pipe_detection,
770 ".o" );
771 string command = ssprintf (
772 "%s -pipe -c %s -o %s 1>%s 2>%s",
773 compilerCommand.c_str (),
774 pipe_detection.c_str (),
775 pipe_detectionObjectFilename.c_str (),
776 NUL,
777 NUL );
778 int exitcode = system ( command.c_str () );
779 FILE* f = fopen ( pipe_detectionObjectFilename.c_str (), "rb" );
780 if ( f )
781 {
782 usePipe = (exitcode == 0);
783 fclose ( f );
784 unlink ( pipe_detectionObjectFilename.c_str () );
785 }
786 else
787 usePipe = false;
788
789 if ( usePipe )
790 printf ( "detected\n" );
791 else
792 printf ( "not detected\n" );
793 }
794
795 void
796 MingwBackend::DetectPCHSupport ()
797 {
798 printf ( "Detecting compiler pre-compiled header support..." );
799
800 string path = "tools" SSEP "rbuild" SSEP "backend" SSEP "mingw" SSEP "pch_detection.h";
801 string cmd = ssprintf (
802 "%s -c %s 1>%s 2>%s",
803 compilerCommand.c_str (),
804 path.c_str (),
805 NUL,
806 NUL );
807 system ( cmd.c_str () );
808 path += ".gch";
809
810 FILE* f = fopen ( path.c_str (), "rb" );
811 if ( f )
812 {
813 use_pch = true;
814 fclose ( f );
815 unlink ( path.c_str () );
816 }
817 else
818 use_pch = false;
819
820 if ( use_pch )
821 printf ( "detected\n" );
822 else
823 printf ( "not detected\n" );
824 }
825
826 void
827 MingwBackend::GetNonModuleInstallTargetFiles (
828 vector<string>& out ) const
829 {
830 for ( size_t i = 0; i < ProjectNode.installfiles.size (); i++ )
831 {
832 const InstallFile& installfile = *ProjectNode.installfiles[i];
833 string targetFilenameNoFixup = installfile.base + SSEP + installfile.newname;
834 string targetFilename = MingwModuleHandler::PassThruCacheDirectory (
835 NormalizeFilename ( targetFilenameNoFixup ),
836 installDirectory );
837 out.push_back ( targetFilename );
838 }
839 }
840
841 void
842 MingwBackend::GetModuleInstallTargetFiles (
843 vector<string>& out ) const
844 {
845 for ( size_t i = 0; i < ProjectNode.modules.size (); i++ )
846 {
847 const Module& module = *ProjectNode.modules[i];
848 if ( module.installName.length () > 0 )
849 {
850 string targetFilenameNoFixup;
851 if ( module.installBase.length () > 0 )
852 targetFilenameNoFixup = module.installBase + SSEP + module.installName;
853 else
854 targetFilenameNoFixup = module.installName;
855 string targetFilename = MingwModuleHandler::PassThruCacheDirectory (
856 NormalizeFilename ( targetFilenameNoFixup ),
857 installDirectory );
858 out.push_back ( targetFilename );
859 }
860 }
861 }
862
863 void
864 MingwBackend::GetInstallTargetFiles (
865 vector<string>& out ) const
866 {
867 GetNonModuleInstallTargetFiles ( out );
868 GetModuleInstallTargetFiles ( out );
869 }
870
871 void
872 MingwBackend::OutputInstallTarget ( const string& sourceFilename,
873 const string& targetFilename,
874 const string& targetDirectory )
875 {
876 string fullTargetFilename;
877 if ( targetDirectory.length () > 0)
878 fullTargetFilename = targetDirectory + SSEP + targetFilename;
879 else
880 fullTargetFilename = targetFilename;
881 string normalizedTargetFilename = MingwModuleHandler::PassThruCacheDirectory (
882 NormalizeFilename ( fullTargetFilename ),
883 installDirectory );
884 string normalizedTargetDirectory = MingwModuleHandler::PassThruCacheDirectory (
885 NormalizeFilename ( targetDirectory ),
886 installDirectory );
887 fprintf ( fMakefile,
888 "%s: %s | %s\n",
889 normalizedTargetFilename.c_str (),
890 sourceFilename.c_str (),
891 normalizedTargetDirectory.c_str () );
892 fprintf ( fMakefile,
893 "\t$(ECHO_CP)\n" );
894 fprintf ( fMakefile,
895 "\t${cp} %s %s 1>$(NUL)\n",
896 sourceFilename.c_str (),
897 normalizedTargetFilename.c_str () );
898 }
899
900 void
901 MingwBackend::OutputNonModuleInstallTargets ()
902 {
903 for ( size_t i = 0; i < ProjectNode.installfiles.size (); i++ )
904 {
905 const InstallFile& installfile = *ProjectNode.installfiles[i];
906 OutputInstallTarget ( installfile.GetPath (),
907 installfile.newname,
908 installfile.base );
909 }
910 }
911
912 void
913 MingwBackend::OutputModuleInstallTargets ()
914 {
915 for ( size_t i = 0; i < ProjectNode.modules.size (); i++ )
916 {
917 const Module& module = *ProjectNode.modules[i];
918 if ( module.installName.length () > 0 )
919 {
920 string sourceFilename = MingwModuleHandler::PassThruCacheDirectory (
921 NormalizeFilename ( module.GetPath () ),
922 outputDirectory );
923 OutputInstallTarget ( sourceFilename,
924 module.installName,
925 module.installBase );
926 }
927 }
928 }
929
930 string
931 MingwBackend::GetRegistrySourceFiles ()
932 {
933 return "bootdata" SSEP "hivecls.inf "
934 "bootdata" SSEP "hivedef.inf "
935 "bootdata" SSEP "hiveinst.inf "
936 "bootdata" SSEP "hivesft.inf "
937 "bootdata" SSEP "hivesys.inf";
938 }
939
940 string
941 MingwBackend::GetRegistryTargetFiles ()
942 {
943 string system32ConfigDirectory = NormalizeFilename (
944 MingwModuleHandler::PassThruCacheDirectory (
945 "system32" SSEP "config" SSEP,
946 installDirectory ) );
947 return system32ConfigDirectory + SSEP "default " +
948 system32ConfigDirectory + SSEP "sam " +
949 system32ConfigDirectory + SSEP "security " +
950 system32ConfigDirectory + SSEP "software " +
951 system32ConfigDirectory + SSEP "system";
952 }
953
954 void
955 MingwBackend::OutputRegistryInstallTarget ()
956 {
957 string system32ConfigDirectory = NormalizeFilename (
958 MingwModuleHandler::PassThruCacheDirectory (
959 "system32" SSEP "config" SSEP,
960 installDirectory ) );
961
962 string registrySourceFiles = GetRegistrySourceFiles ();
963 string registryTargetFiles = GetRegistryTargetFiles ();
964 fprintf ( fMakefile,
965 "install_registry: %s\n",
966 registryTargetFiles.c_str () );
967 fprintf ( fMakefile,
968 "%s: %s %s $(MKHIVE_TARGET)\n",
969 registryTargetFiles.c_str (),
970 registrySourceFiles.c_str (),
971 system32ConfigDirectory.c_str () );
972 fprintf ( fMakefile,
973 "\t$(ECHO_MKHIVE)\n" );
974 fprintf ( fMakefile,
975 "\t$(MKHIVE_TARGET) bootdata %s bootdata" SSEP "hiveinst.inf\n",
976 system32ConfigDirectory.c_str () );
977 fprintf ( fMakefile,
978 "\n" );
979 }
980
981 void
982 MingwBackend::GenerateInstallTarget ()
983 {
984 vector<string> vInstallTargetFiles;
985 GetInstallTargetFiles ( vInstallTargetFiles );
986 string installTargetFiles = v2s ( vInstallTargetFiles, 5 );
987 string registryTargetFiles = GetRegistryTargetFiles ();
988
989 fprintf ( fMakefile,
990 "install: %s %s\n",
991 installTargetFiles.c_str (),
992 registryTargetFiles.c_str () );
993 OutputNonModuleInstallTargets ();
994 OutputModuleInstallTargets ();
995 OutputRegistryInstallTarget ();
996 fprintf ( fMakefile,
997 "\n" );
998 }
999
1000 void
1001 MingwBackend::GetModuleTestTargets (
1002 vector<string>& out ) const
1003 {
1004 for ( size_t i = 0; i < ProjectNode.modules.size (); i++ )
1005 {
1006 const Module& module = *ProjectNode.modules[i];
1007 if ( module.type == Test )
1008 out.push_back ( module.name );
1009 }
1010 }
1011
1012 void
1013 MingwBackend::GenerateTestTarget ()
1014 {
1015 vector<string> vTestTargets;
1016 GetModuleTestTargets ( vTestTargets );
1017 string testTargets = v2s ( vTestTargets, 5 );
1018
1019 fprintf ( fMakefile,
1020 "test: %s\n",
1021 testTargets.c_str () );
1022 fprintf ( fMakefile,
1023 "\n" );
1024 }
1025
1026 void
1027 MingwBackend::GenerateDirectoryTargets ()
1028 {
1029 intermediateDirectory->CreateRule ( fMakefile, "" );
1030 outputDirectory->CreateRule ( fMakefile, "" );
1031 installDirectory->CreateRule ( fMakefile, "" );
1032 }