-mi switch for rbuild to not have rbuild create install directories.
[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 += -Wall\n" );
493 fprintf ( fMakefile, "PROJECT_CFLAGS += $(PROJECT_GCCOPTIONS)\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 if ( !configuration.MakeHandlesInstallDirectories )
674 installDirectory->GenerateTree ( "", configuration.Verbose );
675 printf ( "done\n" );
676 }
677
678 bool
679 MingwBackend::TryToDetectThisCompiler ( const string& compiler )
680 {
681 string command = ssprintf (
682 "%s -v 2>%s",
683 compiler.c_str (),
684 NUL );
685 int exitcode = system ( command.c_str () );
686 return (exitcode == 0);
687 }
688
689 void
690 MingwBackend::DetectCompiler ()
691 {
692 printf ( "Detecting compiler..." );
693
694 bool detectedCompiler = false;
695 const string& ROS_PREFIXValue = Environment::GetVariable ( "ROS_PREFIX" );
696 if ( ROS_PREFIXValue.length () > 0 )
697 {
698 compilerCommand = ROS_PREFIXValue + "-gcc";
699 detectedCompiler = TryToDetectThisCompiler ( compilerCommand );
700 }
701 #if defined(WIN32)
702 if ( !detectedCompiler )
703 {
704 compilerCommand = "gcc";
705 detectedCompiler = TryToDetectThisCompiler ( compilerCommand );
706 }
707 #endif
708 if ( !detectedCompiler )
709 {
710 compilerCommand = "mingw32-gcc";
711 detectedCompiler = TryToDetectThisCompiler ( compilerCommand );
712 }
713 if ( detectedCompiler )
714 printf ( "detected (%s)\n", compilerCommand.c_str () );
715 else
716 printf ( "not detected\n" );
717 }
718
719 void
720 MingwBackend::DetectPipeSupport ()
721 {
722 printf ( "Detecting compiler -pipe support..." );
723
724 string pipe_detection = "tools" SSEP "rbuild" SSEP "backend" SSEP "mingw" SSEP "pipe_detection.c";
725 string pipe_detectionObjectFilename = ReplaceExtension ( pipe_detection,
726 ".o" );
727 string command = ssprintf (
728 "%s -pipe -c %s -o %s 2>%s",
729 compilerCommand.c_str (),
730 pipe_detection.c_str (),
731 pipe_detectionObjectFilename.c_str (),
732 NUL );
733 int exitcode = system ( command.c_str () );
734 FILE* f = fopen ( pipe_detectionObjectFilename.c_str (), "rb" );
735 if ( f )
736 {
737 usePipe = (exitcode == 0);
738 fclose ( f );
739 unlink ( pipe_detectionObjectFilename.c_str () );
740 }
741 else
742 usePipe = false;
743
744 if ( usePipe )
745 printf ( "detected\n" );
746 else
747 printf ( "not detected\n" );
748 }
749
750 void
751 MingwBackend::DetectPCHSupport ()
752 {
753 printf ( "Detecting compiler pre-compiled header support..." );
754
755 string path = "tools" SSEP "rbuild" SSEP "backend" SSEP "mingw" SSEP "pch_detection.h";
756 string cmd = ssprintf (
757 "%s -c %s 2>%s",
758 compilerCommand.c_str (),
759 path.c_str (),
760 NUL );
761 system ( cmd.c_str () );
762 path += ".gch";
763
764 FILE* f = fopen ( path.c_str (), "rb" );
765 if ( f )
766 {
767 use_pch = true;
768 fclose ( f );
769 unlink ( path.c_str () );
770 }
771 else
772 use_pch = false;
773
774 if ( use_pch )
775 printf ( "detected\n" );
776 else
777 printf ( "not detected\n" );
778 }
779
780 void
781 MingwBackend::GetNonModuleInstallTargetFiles (
782 vector<string>& out ) const
783 {
784 for ( size_t i = 0; i < ProjectNode.installfiles.size (); i++ )
785 {
786 const InstallFile& installfile = *ProjectNode.installfiles[i];
787 string targetFilenameNoFixup = installfile.base + SSEP + installfile.newname;
788 string targetFilename = MingwModuleHandler::PassThruCacheDirectory (
789 NormalizeFilename ( targetFilenameNoFixup ),
790 installDirectory );
791 out.push_back ( targetFilename );
792 }
793 }
794
795 void
796 MingwBackend::GetModuleInstallTargetFiles (
797 vector<string>& out ) const
798 {
799 for ( size_t i = 0; i < ProjectNode.modules.size (); i++ )
800 {
801 const Module& module = *ProjectNode.modules[i];
802 if ( module.installName.length () > 0 )
803 {
804 string targetFilenameNoFixup;
805 if ( module.installBase.length () > 0 )
806 targetFilenameNoFixup = module.installBase + SSEP + module.installName;
807 else
808 targetFilenameNoFixup = module.installName;
809 string targetFilename = MingwModuleHandler::PassThruCacheDirectory (
810 NormalizeFilename ( targetFilenameNoFixup ),
811 installDirectory );
812 out.push_back ( targetFilename );
813 }
814 }
815 }
816
817 void
818 MingwBackend::GetInstallTargetFiles (
819 vector<string>& out ) const
820 {
821 GetNonModuleInstallTargetFiles ( out );
822 GetModuleInstallTargetFiles ( out );
823 }
824
825 void
826 MingwBackend::OutputInstallTarget ( const string& sourceFilename,
827 const string& targetFilename,
828 const string& targetDirectory )
829 {
830 string fullTargetFilename;
831 if ( targetDirectory.length () > 0)
832 fullTargetFilename = targetDirectory + SSEP + targetFilename;
833 else
834 fullTargetFilename = targetFilename;
835 string normalizedTargetFilename = MingwModuleHandler::PassThruCacheDirectory (
836 NormalizeFilename ( fullTargetFilename ),
837 installDirectory );
838 string normalizedTargetDirectory = MingwModuleHandler::PassThruCacheDirectory (
839 NormalizeFilename ( targetDirectory ),
840 installDirectory );
841 fprintf ( fMakefile,
842 "%s: %s | %s\n",
843 normalizedTargetFilename.c_str (),
844 sourceFilename.c_str (),
845 normalizedTargetDirectory.c_str () );
846 fprintf ( fMakefile,
847 "\t$(ECHO_CP)\n" );
848 fprintf ( fMakefile,
849 "\t${cp} %s %s 1>$(NUL)\n",
850 sourceFilename.c_str (),
851 normalizedTargetFilename.c_str () );
852 }
853
854 void
855 MingwBackend::OutputNonModuleInstallTargets ()
856 {
857 for ( size_t i = 0; i < ProjectNode.installfiles.size (); i++ )
858 {
859 const InstallFile& installfile = *ProjectNode.installfiles[i];
860 OutputInstallTarget ( installfile.GetPath (),
861 installfile.newname,
862 installfile.base );
863 }
864 }
865
866 void
867 MingwBackend::OutputModuleInstallTargets ()
868 {
869 for ( size_t i = 0; i < ProjectNode.modules.size (); i++ )
870 {
871 const Module& module = *ProjectNode.modules[i];
872 if ( module.installName.length () > 0 )
873 {
874 string sourceFilename = MingwModuleHandler::PassThruCacheDirectory (
875 NormalizeFilename ( module.GetPath () ),
876 outputDirectory );
877 OutputInstallTarget ( sourceFilename,
878 module.installName,
879 module.installBase );
880 }
881 }
882 }
883
884 string
885 MingwBackend::GetRegistrySourceFiles ()
886 {
887 return "bootdata" SSEP "hivecls.inf "
888 "bootdata" SSEP "hivedef.inf "
889 "bootdata" SSEP "hiveinst.inf "
890 "bootdata" SSEP "hivesft.inf "
891 "bootdata" SSEP "hivesys.inf";
892 }
893
894 string
895 MingwBackend::GetRegistryTargetFiles ()
896 {
897 string system32ConfigDirectory = NormalizeFilename (
898 MingwModuleHandler::PassThruCacheDirectory (
899 "system32" SSEP "config" SSEP,
900 installDirectory ) );
901 return system32ConfigDirectory + SSEP "default " +
902 system32ConfigDirectory + SSEP "sam " +
903 system32ConfigDirectory + SSEP "security " +
904 system32ConfigDirectory + SSEP "software " +
905 system32ConfigDirectory + SSEP "system";
906 }
907
908 void
909 MingwBackend::OutputRegistryInstallTarget ()
910 {
911 string system32ConfigDirectory = NormalizeFilename (
912 MingwModuleHandler::PassThruCacheDirectory (
913 "system32" SSEP "config" SSEP,
914 installDirectory ) );
915
916 string registrySourceFiles = GetRegistrySourceFiles ();
917 string registryTargetFiles = GetRegistryTargetFiles ();
918 fprintf ( fMakefile,
919 "install_registry: %s\n",
920 registryTargetFiles.c_str () );
921 fprintf ( fMakefile,
922 "%s: %s %s $(MKHIVE_TARGET)\n",
923 registryTargetFiles.c_str (),
924 registrySourceFiles.c_str (),
925 system32ConfigDirectory.c_str () );
926 fprintf ( fMakefile,
927 "\t$(ECHO_MKHIVE)\n" );
928 fprintf ( fMakefile,
929 "\t$(MKHIVE_TARGET) bootdata %s bootdata" SSEP "hiveinst.inf\n",
930 system32ConfigDirectory.c_str () );
931 fprintf ( fMakefile,
932 "\n" );
933 }
934
935 void
936 MingwBackend::GenerateInstallTarget ()
937 {
938 vector<string> vInstallTargetFiles;
939 GetInstallTargetFiles ( vInstallTargetFiles );
940 string installTargetFiles = v2s ( vInstallTargetFiles, 5 );
941 string registryTargetFiles = GetRegistryTargetFiles ();
942
943 fprintf ( fMakefile,
944 "install: %s %s\n",
945 installTargetFiles.c_str (),
946 registryTargetFiles.c_str () );
947 OutputNonModuleInstallTargets ();
948 OutputModuleInstallTargets ();
949 OutputRegistryInstallTarget ();
950 fprintf ( fMakefile,
951 "\n" );
952 }
953
954 void
955 MingwBackend::GetModuleTestTargets (
956 vector<string>& out ) const
957 {
958 for ( size_t i = 0; i < ProjectNode.modules.size (); i++ )
959 {
960 const Module& module = *ProjectNode.modules[i];
961 if ( module.type == Test )
962 out.push_back ( module.name );
963 }
964 }
965
966 void
967 MingwBackend::GenerateTestTarget ()
968 {
969 vector<string> vTestTargets;
970 GetModuleTestTargets ( vTestTargets );
971 string testTargets = v2s ( vTestTargets, 5 );
972
973 fprintf ( fMakefile,
974 "test: %s\n",
975 testTargets.c_str () );
976 fprintf ( fMakefile,
977 "\n" );
978 }
979
980 void
981 MingwBackend::GenerateDirectoryTargets ()
982 {
983 intermediateDirectory->CreateRule ( fMakefile, "" );
984 outputDirectory->CreateRule ( fMakefile, "" );
985 installDirectory->CreateRule ( fMakefile, "" );
986 }