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