Support modules with no base install directory
[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 bool verbose,
216 bool cleanAsYouGo )
217 {
218 return new MingwBackend ( project,
219 verbose,
220 cleanAsYouGo );
221 }
222 } factory;
223
224
225 MingwBackend::MingwBackend ( Project& project,
226 bool verbose,
227 bool cleanAsYouGo )
228 : Backend ( project, verbose, cleanAsYouGo ),
229 intermediateDirectory ( new Directory ("$(INTERMEDIATE)" ) ),
230 outputDirectory ( new Directory ( "$(OUTPUT)" ) ),
231 installDirectory ( new Directory ( "$(INSTALL)" ) )
232 {
233 }
234
235 MingwBackend::~MingwBackend()
236 {
237 delete intermediateDirectory;
238 delete outputDirectory;
239 delete installDirectory;
240 }
241
242 string
243 MingwBackend::AddDirectoryTarget ( const string& directory,
244 Directory* directoryTree )
245 {
246 if ( directory.length () > 0)
247 directoryTree->Add ( directory.c_str() );
248 return directoryTree->name;
249 }
250
251 void
252 MingwBackend::ProcessModules ()
253 {
254 printf ( "Processing modules..." );
255
256 vector<MingwModuleHandler*> v;
257 size_t i;
258 for ( i = 0; i < ProjectNode.modules.size (); i++ )
259 {
260 Module& module = *ProjectNode.modules[i];
261 MingwModuleHandler* h = MingwModuleHandler::InstanciateHandler (
262 module,
263 this );
264 if ( module.host == HostDefault )
265 {
266 module.host = h->DefaultHost();
267 assert ( module.host != HostDefault );
268 }
269 v.push_back ( h );
270 }
271
272 size_t iend = v.size ();
273
274 for ( i = 0; i < iend; i++ )
275 v[i]->GenerateObjectMacro();
276 fprintf ( fMakefile, "\n" );
277 for ( i = 0; i < iend; i++ )
278 v[i]->GenerateTargetMacro();
279 fprintf ( fMakefile, "\n" );
280
281 GenerateAllTarget ( v );
282 GenerateInitTarget ();
283
284 for ( i = 0; i < iend; i++ )
285 v[i]->GenerateOtherMacros();
286
287 for ( i = 0; i < iend; i++ )
288 {
289 MingwModuleHandler& h = *v[i];
290 h.GeneratePreconditionDependencies ();
291 h.Process ();
292 h.GenerateInvocations ();
293 h.GenerateCleanTarget ();
294 h.GenerateInstallTarget ();
295 delete v[i];
296 }
297
298 printf ( "done\n" );
299 }
300
301 void
302 MingwBackend::Process ()
303 {
304 DetectCompiler ();
305 DetectPipeSupport ();
306 DetectPCHSupport ();
307 CreateMakefile ();
308 GenerateHeader ();
309 GenerateGlobalVariables ();
310 GenerateXmlBuildFilesMacro ();
311 ProcessModules ();
312 GenerateInstallTarget ();
313 GenerateDirectoryTargets ();
314 GenerateDirectories ();
315 UnpackWineResources ();
316 GenerateTestSupportCode ();
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::GenerateXmlBuildFilesMacro() const
562 {
563 fprintf ( fMakefile,
564 "XMLBUILDFILES = %s \\\n",
565 ProjectNode.GetProjectFilename ().c_str () );
566 string xmlbuildFilenames;
567 int numberOfExistingFiles = 0;
568 for ( size_t i = 0; i < ProjectNode.xmlbuildfiles.size (); i++ )
569 {
570 XMLInclude& xmlbuildfile = *ProjectNode.xmlbuildfiles[i];
571 if ( !xmlbuildfile.fileExists )
572 continue;
573 numberOfExistingFiles++;
574 if ( xmlbuildFilenames.length () > 0 )
575 xmlbuildFilenames += " ";
576 xmlbuildFilenames += NormalizeFilename ( xmlbuildfile.topIncludeFilename );
577 if ( numberOfExistingFiles % 5 == 4 || i == ProjectNode.xmlbuildfiles.size () - 1 )
578 {
579 fprintf ( fMakefile,
580 "\t%s",
581 xmlbuildFilenames.c_str ());
582 if ( i == ProjectNode.xmlbuildfiles.size () - 1 )
583 {
584 fprintf ( fMakefile, "\n" );
585 }
586 else
587 {
588 fprintf ( fMakefile,
589 " \\\n",
590 xmlbuildFilenames.c_str () );
591 }
592 xmlbuildFilenames.resize ( 0 );
593 }
594 numberOfExistingFiles++;
595 }
596 fprintf ( fMakefile, "\n" );
597 }
598
599 string
600 MingwBackend::GetBin2ResExecutable ()
601 {
602 return NormalizeFilename ( Environment::GetOutputPath () + SSEP + "tools/bin2res/bin2res" + EXEPOSTFIX );
603 }
604
605 void
606 MingwBackend::UnpackWineResources ()
607 {
608 printf ( "Unpacking WINE resources..." );
609 WineResource wineResource ( ProjectNode,
610 GetBin2ResExecutable () );
611 wineResource.UnpackResources ( verbose );
612 printf ( "done\n" );
613 }
614
615 void
616 MingwBackend::GenerateTestSupportCode ()
617 {
618 printf ( "Generating test support code..." );
619 TestSupportCode testSupportCode ( ProjectNode );
620 testSupportCode.GenerateTestSupportCode ( verbose );
621 printf ( "done\n" );
622 }
623
624 void
625 MingwBackend::CheckAutomaticDependencies ()
626 {
627 printf ( "Checking automatic dependencies..." );
628 AutomaticDependency automaticDependency ( ProjectNode );
629 automaticDependency.Process ();
630 automaticDependency.CheckAutomaticDependencies ( verbose );
631 printf ( "done\n" );
632 }
633
634 bool
635 MingwBackend::IncludeDirectoryTarget ( const string& directory ) const
636 {
637 if ( directory == "$(INTERMEDIATE)" SSEP "tools")
638 return false;
639 else
640 return true;
641 }
642
643 void
644 MingwBackend::GenerateDirectories ()
645 {
646 printf ( "Creating directories..." );
647 intermediateDirectory->GenerateTree ( "", verbose );
648 outputDirectory->GenerateTree ( "", verbose );
649 installDirectory->GenerateTree ( "", verbose );
650 printf ( "done\n" );
651 }
652
653 bool
654 MingwBackend::TryToDetectThisCompiler ( const string& compiler )
655 {
656 string command = ssprintf (
657 "%s -v 2>%s",
658 compiler.c_str (),
659 NUL );
660 int exitcode = system ( command.c_str () );
661 return (exitcode == 0);
662 }
663
664 void
665 MingwBackend::DetectCompiler ()
666 {
667 printf ( "Detecting compiler..." );
668
669 bool detectedCompiler = false;
670 const string& ROS_PREFIXValue = Environment::GetVariable ( "ROS_PREFIX" );
671 if ( ROS_PREFIXValue.length () > 0 )
672 {
673 compilerCommand = ROS_PREFIXValue + "-gcc";
674 detectedCompiler = TryToDetectThisCompiler ( compilerCommand );
675 }
676 #if defined(WIN32)
677 if ( !detectedCompiler )
678 {
679 compilerCommand = "gcc";
680 detectedCompiler = TryToDetectThisCompiler ( compilerCommand );
681 }
682 #endif
683 if ( !detectedCompiler )
684 {
685 compilerCommand = "mingw32-gcc";
686 detectedCompiler = TryToDetectThisCompiler ( compilerCommand );
687 }
688 if ( detectedCompiler )
689 printf ( "detected (%s)\n", compilerCommand.c_str () );
690 else
691 printf ( "not detected\n" );
692 }
693
694 void
695 MingwBackend::DetectPipeSupport ()
696 {
697 printf ( "Detecting compiler -pipe support..." );
698
699 string pipe_detection = "tools" SSEP "rbuild" SSEP "backend" SSEP "mingw" SSEP "pipe_detection.c";
700 string pipe_detectionObjectFilename = ReplaceExtension ( pipe_detection,
701 ".o" );
702 string command = ssprintf (
703 "%s -pipe -c %s -o %s 2>%s",
704 compilerCommand.c_str (),
705 pipe_detection.c_str (),
706 pipe_detectionObjectFilename.c_str (),
707 NUL );
708 int exitcode = system ( command.c_str () );
709 FILE* f = fopen ( pipe_detectionObjectFilename.c_str (), "rb" );
710 if ( f )
711 {
712 usePipe = (exitcode == 0);
713 fclose ( f );
714 unlink ( pipe_detectionObjectFilename.c_str () );
715 }
716 else
717 usePipe = false;
718
719 if ( usePipe )
720 printf ( "detected\n" );
721 else
722 printf ( "not detected\n" );
723 }
724
725 void
726 MingwBackend::DetectPCHSupport ()
727 {
728 printf ( "Detecting compiler pre-compiled header support..." );
729
730 string path = "tools" SSEP "rbuild" SSEP "backend" SSEP "mingw" SSEP "pch_detection.h";
731 string cmd = ssprintf (
732 "%s -c %s 2>%s",
733 compilerCommand.c_str (),
734 path.c_str (),
735 NUL );
736 system ( cmd.c_str () );
737 path += ".gch";
738
739 FILE* f = fopen ( path.c_str (), "rb" );
740 if ( f )
741 {
742 use_pch = true;
743 fclose ( f );
744 unlink ( path.c_str () );
745 }
746 else
747 use_pch = false;
748
749 if ( use_pch )
750 printf ( "detected\n" );
751 else
752 printf ( "not detected\n" );
753 }
754
755 void
756 MingwBackend::GetNonModuleInstallTargetFiles (
757 vector<string>& out ) const
758 {
759 for ( size_t i = 0; i < ProjectNode.installfiles.size (); i++ )
760 {
761 const InstallFile& installfile = *ProjectNode.installfiles[i];
762 string targetFilenameNoFixup = installfile.base + SSEP + installfile.newname;
763 string targetFilename = MingwModuleHandler::PassThruCacheDirectory (
764 NormalizeFilename ( targetFilenameNoFixup ),
765 installDirectory );
766 out.push_back ( targetFilename );
767 }
768 }
769
770 void
771 MingwBackend::GetModuleInstallTargetFiles (
772 vector<string>& out ) const
773 {
774 for ( size_t i = 0; i < ProjectNode.modules.size (); i++ )
775 {
776 const Module& module = *ProjectNode.modules[i];
777 if ( module.installName.length () > 0 )
778 {
779 string targetFilenameNoFixup;
780 if ( module.installBase.length () > 0 )
781 targetFilenameNoFixup = module.installBase + SSEP + module.installName;
782 else
783 targetFilenameNoFixup = module.installName;
784 string targetFilename = MingwModuleHandler::PassThruCacheDirectory (
785 NormalizeFilename ( targetFilenameNoFixup ),
786 installDirectory );
787 out.push_back ( targetFilename );
788 }
789 }
790 }
791
792 void
793 MingwBackend::GetInstallTargetFiles (
794 vector<string>& out ) const
795 {
796 GetNonModuleInstallTargetFiles ( out );
797 GetModuleInstallTargetFiles ( out );
798 }
799
800 void
801 MingwBackend::OutputInstallTarget ( const string& sourceFilename,
802 const string& targetFilename,
803 const string& targetDirectory )
804 {
805 string fullTargetFilename;
806 if ( targetDirectory.length () > 0)
807 fullTargetFilename = targetDirectory + SSEP + targetFilename;
808 else
809 fullTargetFilename = targetFilename;
810 string normalizedTargetFilename = MingwModuleHandler::PassThruCacheDirectory (
811 NormalizeFilename ( fullTargetFilename ),
812 installDirectory );
813 string normalizedTargetDirectory = MingwModuleHandler::PassThruCacheDirectory (
814 NormalizeFilename ( targetDirectory ),
815 installDirectory );
816 fprintf ( fMakefile,
817 "%s: %s | %s\n",
818 normalizedTargetFilename.c_str (),
819 sourceFilename.c_str (),
820 normalizedTargetDirectory.c_str () );
821 fprintf ( fMakefile,
822 "\t$(ECHO_CP)\n" );
823 fprintf ( fMakefile,
824 "\t${cp} %s %s 1>$(NUL)\n",
825 sourceFilename.c_str (),
826 normalizedTargetFilename.c_str () );
827 }
828
829 void
830 MingwBackend::OutputNonModuleInstallTargets ()
831 {
832 for ( size_t i = 0; i < ProjectNode.installfiles.size (); i++ )
833 {
834 const InstallFile& installfile = *ProjectNode.installfiles[i];
835 OutputInstallTarget ( installfile.GetPath (),
836 installfile.newname,
837 installfile.base );
838 }
839 }
840
841 void
842 MingwBackend::OutputModuleInstallTargets ()
843 {
844 for ( size_t i = 0; i < ProjectNode.modules.size (); i++ )
845 {
846 const Module& module = *ProjectNode.modules[i];
847 if ( module.installName.length () > 0 )
848 {
849 string sourceFilename = MingwModuleHandler::PassThruCacheDirectory (
850 NormalizeFilename ( module.GetPath () ),
851 outputDirectory );
852 OutputInstallTarget ( sourceFilename,
853 module.installName,
854 module.installBase );
855 }
856 }
857 }
858
859 string
860 MingwBackend::GetRegistrySourceFiles ()
861 {
862 return "bootdata" SSEP "hivecls.inf "
863 "bootdata" SSEP "hivedef.inf "
864 "bootdata" SSEP "hiveinst.inf "
865 "bootdata" SSEP "hivesft.inf "
866 "bootdata" SSEP "hivesys.inf";
867 }
868
869 string
870 MingwBackend::GetRegistryTargetFiles ()
871 {
872 string system32ConfigDirectory = NormalizeFilename (
873 MingwModuleHandler::PassThruCacheDirectory (
874 "system32" SSEP "config" SSEP,
875 installDirectory ) );
876 return system32ConfigDirectory + SSEP "default " +
877 system32ConfigDirectory + SSEP "sam " +
878 system32ConfigDirectory + SSEP "security " +
879 system32ConfigDirectory + SSEP "software " +
880 system32ConfigDirectory + SSEP "system";
881 }
882
883 void
884 MingwBackend::OutputRegistryInstallTarget ()
885 {
886 string system32ConfigDirectory = NormalizeFilename (
887 MingwModuleHandler::PassThruCacheDirectory (
888 "system32" SSEP "config" SSEP,
889 installDirectory ) );
890
891 string registrySourceFiles = GetRegistrySourceFiles ();
892 string registryTargetFiles = GetRegistryTargetFiles ();
893 fprintf ( fMakefile,
894 "install_registry: %s\n",
895 registryTargetFiles.c_str () );
896 fprintf ( fMakefile,
897 "%s: %s %s $(MKHIVE_TARGET)\n",
898 registryTargetFiles.c_str (),
899 registrySourceFiles.c_str (),
900 system32ConfigDirectory.c_str () );
901 fprintf ( fMakefile,
902 "\t$(ECHO_MKHIVE)\n" );
903 fprintf ( fMakefile,
904 "\t$(MKHIVE_TARGET) bootdata %s bootdata" SSEP "hiveinst.inf\n",
905 system32ConfigDirectory.c_str () );
906 fprintf ( fMakefile,
907 "\n" );
908 }
909
910 void
911 MingwBackend::GenerateInstallTarget ()
912 {
913 vector<string> vInstallTargetFiles;
914 GetInstallTargetFiles ( vInstallTargetFiles );
915 string installTargetFiles = v2s ( vInstallTargetFiles, 5 );
916
917 fprintf ( fMakefile,
918 "install: %s install_registry\n",
919 installTargetFiles.c_str () );
920 OutputNonModuleInstallTargets ();
921 OutputModuleInstallTargets ();
922 OutputRegistryInstallTarget ();
923 fprintf ( fMakefile,
924 "\n" );
925 }
926
927 void
928 MingwBackend::GenerateDirectoryTargets ()
929 {
930 intermediateDirectory->CreateRule ( fMakefile, "" );
931 outputDirectory->CreateRule ( fMakefile, "" );
932 installDirectory->CreateRule ( fMakefile, "" );
933 }