Copy rpoolmgr.h from trunk
[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 }
231
232 MingwBackend::~MingwBackend()
233 {
234 delete intermediateDirectory;
235 delete outputDirectory;
236 delete installDirectory;
237 }
238
239 string
240 MingwBackend::AddDirectoryTarget ( const string& directory,
241 Directory* directoryTree )
242 {
243 if ( directory.length () > 0)
244 directoryTree->Add ( directory.c_str() );
245 return directoryTree->name;
246 }
247
248 void
249 MingwBackend::ProcessModules ()
250 {
251 printf ( "Processing modules..." );
252
253 vector<MingwModuleHandler*> v;
254 size_t i;
255 for ( i = 0; i < ProjectNode.modules.size (); i++ )
256 {
257 Module& module = *ProjectNode.modules[i];
258 MingwModuleHandler* h = MingwModuleHandler::InstanciateHandler (
259 module,
260 this );
261 if ( module.host == HostDefault )
262 {
263 module.host = h->DefaultHost();
264 assert ( module.host != HostDefault );
265 }
266 v.push_back ( h );
267 }
268
269 size_t iend = v.size ();
270
271 for ( i = 0; i < iend; i++ )
272 v[i]->GenerateObjectMacro();
273 fprintf ( fMakefile, "\n" );
274 for ( i = 0; i < iend; i++ )
275 v[i]->GenerateTargetMacro();
276 fprintf ( fMakefile, "\n" );
277
278 GenerateAllTarget ( v );
279 GenerateInitTarget ();
280 GenerateRegTestsRunTarget ();
281
282 for ( i = 0; i < iend; i++ )
283 v[i]->GenerateOtherMacros();
284
285 for ( i = 0; i < iend; i++ )
286 {
287 MingwModuleHandler& h = *v[i];
288 h.GeneratePreconditionDependencies ();
289 h.Process ();
290 h.GenerateInvocations ();
291 h.GenerateCleanTarget ();
292 h.GenerateInstallTarget ();
293 delete v[i];
294 }
295
296 printf ( "done\n" );
297 }
298
299 void
300 MingwBackend::Process ()
301 {
302 DetectCompiler ();
303 DetectPipeSupport ();
304 DetectPCHSupport ();
305 CreateMakefile ();
306 GenerateHeader ();
307 GenerateGlobalVariables ();
308 GenerateXmlBuildFilesMacro ();
309 ProcessModules ();
310 GenerateInstallTarget ();
311 GenerateTestTarget ();
312 GenerateDirectoryTargets ();
313 GenerateDirectories ();
314 UnpackWineResources ();
315 GenerateTestSupportCode ();
316 GenerateProxyMakefiles ();
317 CheckAutomaticDependencies ();
318 CloseMakefile ();
319 }
320
321 void
322 MingwBackend::CreateMakefile ()
323 {
324 fMakefile = fopen ( ProjectNode.makefile.c_str (), "w" );
325 if ( !fMakefile )
326 throw AccessDeniedException ( ProjectNode.makefile );
327 MingwModuleHandler::SetBackend ( this );
328 MingwModuleHandler::SetMakefile ( fMakefile );
329 MingwModuleHandler::SetUsePch ( use_pch );
330 }
331
332 void
333 MingwBackend::CloseMakefile () const
334 {
335 if (fMakefile)
336 fclose ( fMakefile );
337 }
338
339 void
340 MingwBackend::GenerateHeader () const
341 {
342 fprintf ( fMakefile, "# THIS FILE IS AUTOMATICALLY GENERATED, EDIT 'ReactOS.xml' INSTEAD\n\n" );
343 }
344
345 string
346 MingwBackend::GenerateIncludesAndDefines ( IfableData& data ) const
347 {
348 string includeParameters = MingwModuleHandler::GenerateGccIncludeParametersFromVector ( data.includes );
349 string defineParameters = MingwModuleHandler::GenerateGccDefineParametersFromVector ( data.defines );
350 return includeParameters + " " + defineParameters;
351 }
352
353 void
354 MingwBackend::GenerateProjectCFlagsMacro ( const char* assignmentOperation,
355 IfableData& data ) const
356 {
357 fprintf (
358 fMakefile,
359 "PROJECT_CFLAGS %s",
360 assignmentOperation );
361
362 fprintf ( fMakefile,
363 " %s",
364 GenerateIncludesAndDefines ( data ).c_str() );
365
366 fprintf ( fMakefile, "\n" );
367 }
368
369 void
370 MingwBackend::GenerateGlobalCFlagsAndProperties (
371 const char* assignmentOperation,
372 IfableData& data ) const
373 {
374 size_t i;
375
376 for ( i = 0; i < data.properties.size(); i++ )
377 {
378 Property& prop = *data.properties[i];
379 fprintf ( fMakefile, "%s := %s\n",
380 prop.name.c_str(),
381 prop.value.c_str() );
382 }
383
384 if ( data.includes.size() || data.defines.size() )
385 {
386 GenerateProjectCFlagsMacro ( assignmentOperation,
387 data );
388 }
389
390 for ( i = 0; i < data.ifs.size(); i++ )
391 {
392 If& rIf = *data.ifs[i];
393 if ( rIf.data.defines.size()
394 || rIf.data.includes.size()
395 || rIf.data.ifs.size() )
396 {
397 fprintf (
398 fMakefile,
399 "ifeq (\"$(%s)\",\"%s\")\n",
400 rIf.property.c_str(),
401 rIf.value.c_str() );
402 GenerateGlobalCFlagsAndProperties (
403 "+=",
404 rIf.data );
405 fprintf (
406 fMakefile,
407 "endif\n\n" );
408 }
409 }
410 }
411
412 void
413 MingwBackend::GenerateProjectGccOptionsMacro ( const char* assignmentOperation,
414 IfableData& data ) const
415 {
416 size_t i;
417
418 fprintf (
419 fMakefile,
420 "PROJECT_GCCOPTIONS %s",
421 assignmentOperation );
422
423 for ( i = 0; i < data.compilerFlags.size(); i++ )
424 {
425 fprintf (
426 fMakefile,
427 " %s",
428 data.compilerFlags[i]->flag.c_str() );
429 }
430
431 fprintf ( fMakefile, "\n" );
432 }
433
434 void
435 MingwBackend::GenerateProjectGccOptions (
436 const char* assignmentOperation,
437 IfableData& data ) const
438 {
439 size_t i;
440
441 if ( data.compilerFlags.size() )
442 {
443 GenerateProjectGccOptionsMacro ( assignmentOperation,
444 data );
445 }
446
447 for ( i = 0; i < data.ifs.size(); i++ )
448 {
449 If& rIf = *data.ifs[i];
450 if ( rIf.data.compilerFlags.size()
451 || rIf.data.ifs.size() )
452 {
453 fprintf (
454 fMakefile,
455 "ifeq (\"$(%s)\",\"%s\")\n",
456 rIf.property.c_str(),
457 rIf.value.c_str() );
458 GenerateProjectGccOptions (
459 "+=",
460 rIf.data );
461 fprintf (
462 fMakefile,
463 "endif\n\n" );
464 }
465 }
466 }
467
468 string
469 MingwBackend::GenerateProjectLFLAGS () const
470 {
471 string lflags;
472 for ( size_t i = 0; i < ProjectNode.linkerFlags.size (); i++ )
473 {
474 LinkerFlag& linkerFlag = *ProjectNode.linkerFlags[i];
475 if ( lflags.length () > 0 )
476 lflags += " ";
477 lflags += linkerFlag.flag;
478 }
479 return lflags;
480 }
481
482 void
483 MingwBackend::GenerateGlobalVariables () const
484 {
485 GenerateGlobalCFlagsAndProperties ( "=", ProjectNode.non_if_data );
486 GenerateProjectGccOptions ( "=", ProjectNode.non_if_data );
487
488 fprintf ( fMakefile, "PROJECT_RCFLAGS := $(PROJECT_CFLAGS)\n" );
489 fprintf ( fMakefile, "PROJECT_WIDLFLAGS := $(PROJECT_CFLAGS)\n" );
490 fprintf ( fMakefile, "PROJECT_LFLAGS := %s\n",
491 GenerateProjectLFLAGS ().c_str () );
492 fprintf ( fMakefile, "PROJECT_CFLAGS += $(PROJECT_GCCOPTIONS)\n" );
493 fprintf ( fMakefile, "PROJECT_CFLAGS += -Wall\n" );
494 fprintf ( fMakefile, "\n" );
495 }
496
497 bool
498 MingwBackend::IncludeInAllTarget ( const Module& module ) const
499 {
500 if ( MingwModuleHandler::ReferenceObjects ( module ) )
501 return false;
502 if ( module.type == BootSector )
503 return false;
504 if ( module.type == Iso )
505 return false;
506 if ( module.type == LiveIso )
507 return false;
508 if ( module.type == Test )
509 return false;
510 return true;
511 }
512
513 void
514 MingwBackend::GenerateAllTarget ( const vector<MingwModuleHandler*>& handlers ) const
515 {
516 fprintf ( fMakefile, "all:" );
517 int wrap_count = 0;
518 size_t iend = handlers.size ();
519 for ( size_t i = 0; i < iend; i++ )
520 {
521 const Module& module = handlers[i]->module;
522 if ( IncludeInAllTarget ( module ) )
523 {
524 if ( wrap_count++ == 5 )
525 fprintf ( fMakefile, " \\\n\t\t" ), wrap_count = 0;
526 fprintf ( fMakefile,
527 " %s",
528 GetTargetMacro(module).c_str () );
529 }
530 }
531 fprintf ( fMakefile, "\n\t\n\n" );
532 }
533
534 string
535 MingwBackend::GetBuildToolDependencies () const
536 {
537 string dependencies;
538 for ( size_t i = 0; i < ProjectNode.modules.size (); i++ )
539 {
540 Module& module = *ProjectNode.modules[i];
541 if ( module.type == BuildTool )
542 {
543 if ( dependencies.length () > 0 )
544 dependencies += " ";
545 dependencies += module.GetDependencyPath ();
546 }
547 }
548 return dependencies;
549 }
550
551 void
552 MingwBackend::GenerateInitTarget () const
553 {
554 fprintf ( fMakefile,
555 "INIT = %s\n",
556 GetBuildToolDependencies ().c_str () );
557 fprintf ( fMakefile, "\n" );
558 }
559
560 void
561 MingwBackend::GenerateRegTestsRunTarget () const
562 {
563 fprintf ( fMakefile,
564 "REGTESTS_RUN_TARGET = regtests.dll\n" );
565 fprintf ( fMakefile,
566 "$(REGTESTS_RUN_TARGET):\n" );
567 fprintf ( fMakefile,
568 "\t$(cp) $(REGTESTS_TARGET) $(REGTESTS_RUN_TARGET)\n" );
569 fprintf ( fMakefile, "\n" );
570 }
571
572 void
573 MingwBackend::GenerateXmlBuildFilesMacro() const
574 {
575 fprintf ( fMakefile,
576 "XMLBUILDFILES = %s \\\n",
577 ProjectNode.GetProjectFilename ().c_str () );
578 string xmlbuildFilenames;
579 int numberOfExistingFiles = 0;
580 for ( size_t i = 0; i < ProjectNode.xmlbuildfiles.size (); i++ )
581 {
582 XMLInclude& xmlbuildfile = *ProjectNode.xmlbuildfiles[i];
583 if ( !xmlbuildfile.fileExists )
584 continue;
585 numberOfExistingFiles++;
586 if ( xmlbuildFilenames.length () > 0 )
587 xmlbuildFilenames += " ";
588 xmlbuildFilenames += NormalizeFilename ( xmlbuildfile.topIncludeFilename );
589 if ( numberOfExistingFiles % 5 == 4 || i == ProjectNode.xmlbuildfiles.size () - 1 )
590 {
591 fprintf ( fMakefile,
592 "\t%s",
593 xmlbuildFilenames.c_str ());
594 if ( i == ProjectNode.xmlbuildfiles.size () - 1 )
595 {
596 fprintf ( fMakefile, "\n" );
597 }
598 else
599 {
600 fprintf ( fMakefile,
601 " \\\n",
602 xmlbuildFilenames.c_str () );
603 }
604 xmlbuildFilenames.resize ( 0 );
605 }
606 numberOfExistingFiles++;
607 }
608 fprintf ( fMakefile, "\n" );
609 }
610
611 string
612 MingwBackend::GetBin2ResExecutable ()
613 {
614 return NormalizeFilename ( Environment::GetOutputPath () + SSEP + "tools/bin2res/bin2res" + EXEPOSTFIX );
615 }
616
617 void
618 MingwBackend::UnpackWineResources ()
619 {
620 printf ( "Unpacking WINE resources..." );
621 WineResource wineResource ( ProjectNode,
622 GetBin2ResExecutable () );
623 wineResource.UnpackResources ( configuration.Verbose );
624 printf ( "done\n" );
625 }
626
627 void
628 MingwBackend::GenerateTestSupportCode ()
629 {
630 printf ( "Generating test support code..." );
631 TestSupportCode testSupportCode ( ProjectNode );
632 testSupportCode.GenerateTestSupportCode ( configuration.Verbose );
633 printf ( "done\n" );
634 }
635
636 void
637 MingwBackend::GenerateProxyMakefiles ()
638 {
639 printf ( "Generating proxy makefiles..." );
640 ProxyMakefile proxyMakefile ( ProjectNode );
641 proxyMakefile.GenerateProxyMakefiles ( configuration.Verbose );
642 printf ( "done\n" );
643 }
644
645 void
646 MingwBackend::CheckAutomaticDependencies ()
647 {
648 if ( configuration.AutomaticDependencies )
649 {
650 printf ( "Checking automatic dependencies..." );
651 AutomaticDependency automaticDependency ( ProjectNode );
652 automaticDependency.Process ();
653 automaticDependency.CheckAutomaticDependencies ( configuration.Verbose );
654 printf ( "done\n" );
655 }
656 }
657
658 bool
659 MingwBackend::IncludeDirectoryTarget ( const string& directory ) const
660 {
661 if ( directory == "$(INTERMEDIATE)" SSEP "tools")
662 return false;
663 else
664 return true;
665 }
666
667 void
668 MingwBackend::GenerateDirectories ()
669 {
670 printf ( "Creating directories..." );
671 intermediateDirectory->GenerateTree ( "", configuration.Verbose );
672 outputDirectory->GenerateTree ( "", configuration.Verbose );
673 installDirectory->GenerateTree ( "", configuration.Verbose );
674 printf ( "done\n" );
675 }
676
677 bool
678 MingwBackend::TryToDetectThisCompiler ( const string& compiler )
679 {
680 string command = ssprintf (
681 "%s -v 2>%s",
682 compiler.c_str (),
683 NUL );
684 int exitcode = system ( command.c_str () );
685 return (exitcode == 0);
686 }
687
688 void
689 MingwBackend::DetectCompiler ()
690 {
691 printf ( "Detecting compiler..." );
692
693 bool detectedCompiler = false;
694 const string& ROS_PREFIXValue = Environment::GetVariable ( "ROS_PREFIX" );
695 if ( ROS_PREFIXValue.length () > 0 )
696 {
697 compilerCommand = ROS_PREFIXValue + "-gcc";
698 detectedCompiler = TryToDetectThisCompiler ( compilerCommand );
699 }
700 #if defined(WIN32)
701 if ( !detectedCompiler )
702 {
703 compilerCommand = "gcc";
704 detectedCompiler = TryToDetectThisCompiler ( compilerCommand );
705 }
706 #endif
707 if ( !detectedCompiler )
708 {
709 compilerCommand = "mingw32-gcc";
710 detectedCompiler = TryToDetectThisCompiler ( compilerCommand );
711 }
712 if ( detectedCompiler )
713 printf ( "detected (%s)\n", compilerCommand.c_str () );
714 else
715 printf ( "not detected\n" );
716 }
717
718 void
719 MingwBackend::DetectPipeSupport ()
720 {
721 printf ( "Detecting compiler -pipe support..." );
722
723 string pipe_detection = "tools" SSEP "rbuild" SSEP "backend" SSEP "mingw" SSEP "pipe_detection.c";
724 string pipe_detectionObjectFilename = ReplaceExtension ( pipe_detection,
725 ".o" );
726 string command = ssprintf (
727 "%s -pipe -c %s -o %s 2>%s",
728 compilerCommand.c_str (),
729 pipe_detection.c_str (),
730 pipe_detectionObjectFilename.c_str (),
731 NUL );
732 int exitcode = system ( command.c_str () );
733 FILE* f = fopen ( pipe_detectionObjectFilename.c_str (), "rb" );
734 if ( f )
735 {
736 usePipe = (exitcode == 0);
737 fclose ( f );
738 unlink ( pipe_detectionObjectFilename.c_str () );
739 }
740 else
741 usePipe = false;
742
743 if ( usePipe )
744 printf ( "detected\n" );
745 else
746 printf ( "not detected\n" );
747 }
748
749 void
750 MingwBackend::DetectPCHSupport ()
751 {
752 printf ( "Detecting compiler pre-compiled header support..." );
753
754 string path = "tools" SSEP "rbuild" SSEP "backend" SSEP "mingw" SSEP "pch_detection.h";
755 string cmd = ssprintf (
756 "%s -c %s 2>%s",
757 compilerCommand.c_str (),
758 path.c_str (),
759 NUL );
760 system ( cmd.c_str () );
761 path += ".gch";
762
763 FILE* f = fopen ( path.c_str (), "rb" );
764 if ( f )
765 {
766 use_pch = true;
767 fclose ( f );
768 unlink ( path.c_str () );
769 }
770 else
771 use_pch = false;
772
773 if ( use_pch )
774 printf ( "detected\n" );
775 else
776 printf ( "not detected\n" );
777 }
778
779 void
780 MingwBackend::GetNonModuleInstallTargetFiles (
781 vector<string>& out ) const
782 {
783 for ( size_t i = 0; i < ProjectNode.installfiles.size (); i++ )
784 {
785 const InstallFile& installfile = *ProjectNode.installfiles[i];
786 string targetFilenameNoFixup = installfile.base + SSEP + installfile.newname;
787 string targetFilename = MingwModuleHandler::PassThruCacheDirectory (
788 NormalizeFilename ( targetFilenameNoFixup ),
789 installDirectory );
790 out.push_back ( targetFilename );
791 }
792 }
793
794 void
795 MingwBackend::GetModuleInstallTargetFiles (
796 vector<string>& out ) const
797 {
798 for ( size_t i = 0; i < ProjectNode.modules.size (); i++ )
799 {
800 const Module& module = *ProjectNode.modules[i];
801 if ( module.installName.length () > 0 )
802 {
803 string targetFilenameNoFixup;
804 if ( module.installBase.length () > 0 )
805 targetFilenameNoFixup = module.installBase + SSEP + module.installName;
806 else
807 targetFilenameNoFixup = module.installName;
808 string targetFilename = MingwModuleHandler::PassThruCacheDirectory (
809 NormalizeFilename ( targetFilenameNoFixup ),
810 installDirectory );
811 out.push_back ( targetFilename );
812 }
813 }
814 }
815
816 void
817 MingwBackend::GetInstallTargetFiles (
818 vector<string>& out ) const
819 {
820 GetNonModuleInstallTargetFiles ( out );
821 GetModuleInstallTargetFiles ( out );
822 }
823
824 void
825 MingwBackend::OutputInstallTarget ( const string& sourceFilename,
826 const string& targetFilename,
827 const string& targetDirectory )
828 {
829 string fullTargetFilename;
830 if ( targetDirectory.length () > 0)
831 fullTargetFilename = targetDirectory + SSEP + targetFilename;
832 else
833 fullTargetFilename = targetFilename;
834 string normalizedTargetFilename = MingwModuleHandler::PassThruCacheDirectory (
835 NormalizeFilename ( fullTargetFilename ),
836 installDirectory );
837 string normalizedTargetDirectory = MingwModuleHandler::PassThruCacheDirectory (
838 NormalizeFilename ( targetDirectory ),
839 installDirectory );
840 fprintf ( fMakefile,
841 "%s: %s | %s\n",
842 normalizedTargetFilename.c_str (),
843 sourceFilename.c_str (),
844 normalizedTargetDirectory.c_str () );
845 fprintf ( fMakefile,
846 "\t$(ECHO_CP)\n" );
847 fprintf ( fMakefile,
848 "\t${cp} %s %s 1>$(NUL)\n",
849 sourceFilename.c_str (),
850 normalizedTargetFilename.c_str () );
851 }
852
853 void
854 MingwBackend::OutputNonModuleInstallTargets ()
855 {
856 for ( size_t i = 0; i < ProjectNode.installfiles.size (); i++ )
857 {
858 const InstallFile& installfile = *ProjectNode.installfiles[i];
859 OutputInstallTarget ( installfile.GetPath (),
860 installfile.newname,
861 installfile.base );
862 }
863 }
864
865 void
866 MingwBackend::OutputModuleInstallTargets ()
867 {
868 for ( size_t i = 0; i < ProjectNode.modules.size (); i++ )
869 {
870 const Module& module = *ProjectNode.modules[i];
871 if ( module.installName.length () > 0 )
872 {
873 string sourceFilename = MingwModuleHandler::PassThruCacheDirectory (
874 NormalizeFilename ( module.GetPath () ),
875 outputDirectory );
876 OutputInstallTarget ( sourceFilename,
877 module.installName,
878 module.installBase );
879 }
880 }
881 }
882
883 string
884 MingwBackend::GetRegistrySourceFiles ()
885 {
886 return "bootdata" SSEP "hivecls.inf "
887 "bootdata" SSEP "hivedef.inf "
888 "bootdata" SSEP "hiveinst.inf "
889 "bootdata" SSEP "hivesft.inf "
890 "bootdata" SSEP "hivesys.inf";
891 }
892
893 string
894 MingwBackend::GetRegistryTargetFiles ()
895 {
896 string system32ConfigDirectory = NormalizeFilename (
897 MingwModuleHandler::PassThruCacheDirectory (
898 "system32" SSEP "config" SSEP,
899 installDirectory ) );
900 return system32ConfigDirectory + SSEP "default " +
901 system32ConfigDirectory + SSEP "sam " +
902 system32ConfigDirectory + SSEP "security " +
903 system32ConfigDirectory + SSEP "software " +
904 system32ConfigDirectory + SSEP "system";
905 }
906
907 void
908 MingwBackend::OutputRegistryInstallTarget ()
909 {
910 string system32ConfigDirectory = NormalizeFilename (
911 MingwModuleHandler::PassThruCacheDirectory (
912 "system32" SSEP "config" SSEP,
913 installDirectory ) );
914
915 string registrySourceFiles = GetRegistrySourceFiles ();
916 string registryTargetFiles = GetRegistryTargetFiles ();
917 fprintf ( fMakefile,
918 "install_registry: %s\n",
919 registryTargetFiles.c_str () );
920 fprintf ( fMakefile,
921 "%s: %s %s $(MKHIVE_TARGET)\n",
922 registryTargetFiles.c_str (),
923 registrySourceFiles.c_str (),
924 system32ConfigDirectory.c_str () );
925 fprintf ( fMakefile,
926 "\t$(ECHO_MKHIVE)\n" );
927 fprintf ( fMakefile,
928 "\t$(MKHIVE_TARGET) bootdata %s bootdata" SSEP "hiveinst.inf\n",
929 system32ConfigDirectory.c_str () );
930 fprintf ( fMakefile,
931 "\n" );
932 }
933
934 void
935 MingwBackend::GenerateInstallTarget ()
936 {
937 vector<string> vInstallTargetFiles;
938 GetInstallTargetFiles ( vInstallTargetFiles );
939 string installTargetFiles = v2s ( vInstallTargetFiles, 5 );
940 string registryTargetFiles = GetRegistryTargetFiles ();
941
942 fprintf ( fMakefile,
943 "install: %s %s\n",
944 installTargetFiles.c_str (),
945 registryTargetFiles.c_str () );
946 OutputNonModuleInstallTargets ();
947 OutputModuleInstallTargets ();
948 OutputRegistryInstallTarget ();
949 fprintf ( fMakefile,
950 "\n" );
951 }
952
953 void
954 MingwBackend::GetModuleTestTargets (
955 vector<string>& out ) const
956 {
957 for ( size_t i = 0; i < ProjectNode.modules.size (); i++ )
958 {
959 const Module& module = *ProjectNode.modules[i];
960 if ( module.type == Test )
961 out.push_back ( module.name );
962 }
963 }
964
965 void
966 MingwBackend::GenerateTestTarget ()
967 {
968 vector<string> vTestTargets;
969 GetModuleTestTargets ( vTestTargets );
970 string testTargets = v2s ( vTestTargets, 5 );
971
972 fprintf ( fMakefile,
973 "test: %s\n",
974 testTargets.c_str () );
975 fprintf ( fMakefile,
976 "\n" );
977 }
978
979 void
980 MingwBackend::GenerateDirectoryTargets ()
981 {
982 intermediateDirectory->CreateRule ( fMakefile, "" );
983 outputDirectory->CreateRule ( fMakefile, "" );
984 installDirectory->CreateRule ( fMakefile, "" );
985 }