Clean object files for static libraries
[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 /* static */ string
45 Environment::GetVariable ( const string& name )
46 {
47 char* value = getenv ( name.c_str () );
48 if ( value != NULL && strlen ( value ) > 0 )
49 return ssprintf ( "%s",
50 value );
51 else
52 return "";
53 }
54
55
56 Directory::Directory ( const string& name_ )
57 : name(name_)
58 {
59 }
60
61 void
62 Directory::Add ( const char* subdir )
63 {
64 size_t i;
65 string s1 = string ( subdir );
66 if ( ( i = s1.find ( '$' ) ) != string::npos )
67 {
68 throw InvalidOperationException ( __FILE__,
69 __LINE__,
70 "No environment variables can be used here. Path was %s",
71 subdir );
72 }
73
74 const char* p = strpbrk ( subdir, "/\\" );
75 if ( !p )
76 p = subdir + strlen(subdir);
77 string s ( subdir, p-subdir );
78 if ( subdirs.find(s) == subdirs.end() )
79 subdirs[s] = new Directory(s);
80 if ( *p && *++p )
81 subdirs[s]->Add ( p );
82 }
83
84 bool
85 Directory::mkdir_p ( const char* path )
86 {
87 DIR *directory;
88 directory = opendir ( path );
89 if ( directory != NULL )
90 {
91 closedir ( directory );
92 return false;
93 }
94
95 if ( MKDIR ( path ) != 0 )
96 throw AccessDeniedException ( string ( path ) );
97 return true;
98 }
99
100 bool
101 Directory::CreateDirectory ( string path )
102 {
103 size_t index = 0;
104 size_t nextIndex;
105 if ( isalpha ( path[0] ) && path[1] == ':' && path[2] == CSEP )
106 {
107 nextIndex = path.find ( CSEP, 3);
108 }
109 else
110 nextIndex = path.find ( CSEP );
111
112 bool directoryWasCreated = false;
113 while ( nextIndex != string::npos )
114 {
115 nextIndex = path.find ( CSEP, index + 1 );
116 directoryWasCreated = mkdir_p ( path.substr ( 0, nextIndex ).c_str () );
117 index = nextIndex;
118 }
119 return directoryWasCreated;
120 }
121
122 string
123 Directory::ReplaceVariable ( string name,
124 string value,
125 string path )
126 {
127 size_t i = path.find ( name );
128 if ( i != string::npos )
129 return path.replace ( i, name.length (), value );
130 else
131 return path;
132 }
133
134 string
135 Directory::GetEnvironmentVariablePathOrDefault ( const string& name,
136 const string& defaultValue )
137 {
138 const string& environmentVariableValue = Environment::GetVariable ( name );
139 if ( environmentVariableValue.length () > 0 )
140 return NormalizeFilename ( environmentVariableValue );
141 else
142 return defaultValue;
143 }
144
145 string
146 Directory::GetIntermediatePath ()
147 {
148 return GetEnvironmentVariablePathOrDefault ( "ROS_INTERMEDIATE",
149 "obj-i386" );
150 }
151
152 string
153 Directory::GetOutputPath ()
154 {
155 return GetEnvironmentVariablePathOrDefault ( "ROS_OUTPUT",
156 "output-i386" );
157 }
158
159 string
160 Directory::GetInstallPath ()
161 {
162 return GetEnvironmentVariablePathOrDefault ( "ROS_INSTALL",
163 "reactos" );
164 }
165
166 void
167 Directory::ResolveVariablesInPath ( char* buf,
168 string path )
169 {
170 string s = ReplaceVariable ( "$(INTERMEDIATE)", GetIntermediatePath (), path );
171 s = ReplaceVariable ( "$(OUTPUT)", GetOutputPath (), s );
172 s = ReplaceVariable ( "$(INSTALL)", GetInstallPath (), s );
173 strcpy ( buf, s.c_str () );
174 }
175
176 void
177 Directory::GenerateTree ( const string& parent,
178 bool verbose )
179 {
180 string path;
181
182 if ( parent.size() )
183 {
184 char buf[256];
185
186 path = parent + SSEP + name;
187 ResolveVariablesInPath ( buf, path );
188 if ( CreateDirectory ( buf ) && verbose )
189 printf ( "Created %s\n", buf );
190 }
191 else
192 path = name;
193
194 for ( directory_map::iterator i = subdirs.begin();
195 i != subdirs.end();
196 ++i )
197 {
198 i->second->GenerateTree ( path, verbose );
199 }
200 }
201
202
203 static class MingwFactory : public Backend::Factory
204 {
205 public:
206 MingwFactory() : Factory ( "mingw" ) {}
207 Backend* operator() ( Project& project,
208 bool verbose,
209 bool cleanAsYouGo )
210 {
211 return new MingwBackend ( project,
212 verbose,
213 cleanAsYouGo );
214 }
215 } factory;
216
217
218 MingwBackend::MingwBackend ( Project& project,
219 bool verbose,
220 bool cleanAsYouGo )
221 : Backend ( project, verbose, cleanAsYouGo ),
222 intermediateDirectory ( new Directory ("$(INTERMEDIATE)" ) ),
223 outputDirectory ( new Directory ( "$(OUTPUT)" ) ),
224 installDirectory ( new Directory ( "$(INSTALL)" ) )
225 {
226 }
227
228 MingwBackend::~MingwBackend()
229 {
230 delete intermediateDirectory;
231 delete outputDirectory;
232 delete installDirectory;
233 }
234
235 string
236 MingwBackend::AddDirectoryTarget ( const string& directory,
237 Directory* directoryTree )
238 {
239 directoryTree->Add ( directory.c_str() );
240 return directoryTree->name;
241 }
242
243 void
244 MingwBackend::ProcessModules ()
245 {
246 printf ( "Processing modules..." );
247
248 vector<MingwModuleHandler*> v;
249 size_t i;
250 for ( i = 0; i < ProjectNode.modules.size (); i++ )
251 {
252 Module& module = *ProjectNode.modules[i];
253 MingwModuleHandler* h = MingwModuleHandler::InstanciateHandler (
254 module,
255 this );
256 if ( module.host == HostDefault )
257 {
258 module.host = h->DefaultHost();
259 assert ( module.host != HostDefault );
260 }
261 v.push_back ( h );
262 }
263
264 size_t iend = v.size ();
265
266 for ( i = 0; i < iend; i++ )
267 v[i]->GenerateObjectMacro();
268 fprintf ( fMakefile, "\n" );
269 for ( i = 0; i < iend; i++ )
270 v[i]->GenerateTargetMacro();
271 fprintf ( fMakefile, "\n" );
272
273 GenerateAllTarget ( v );
274 GenerateInitTarget ();
275
276 for ( i = 0; i < iend; i++ )
277 v[i]->GenerateOtherMacros();
278
279 for ( i = 0; i < iend; i++ )
280 {
281 MingwModuleHandler& h = *v[i];
282 h.GeneratePreconditionDependencies ();
283 h.Process ();
284 h.GenerateInvocations ();
285 h.GenerateCleanTarget ();
286 delete v[i];
287 }
288
289 printf ( "done\n" );
290 }
291
292 void
293 MingwBackend::Process ()
294 {
295 DetectCompiler ();
296 DetectPipeSupport ();
297 DetectPCHSupport ();
298 CreateMakefile ();
299 GenerateHeader ();
300 GenerateGlobalVariables ();
301 GenerateXmlBuildFilesMacro ();
302 ProcessModules ();
303 GenerateInstallTarget ();
304 GenerateDirectories ();
305 CheckAutomaticDependencies ();
306 CloseMakefile ();
307 }
308
309 void
310 MingwBackend::CreateMakefile ()
311 {
312 fMakefile = fopen ( ProjectNode.makefile.c_str (), "w" );
313 if ( !fMakefile )
314 throw AccessDeniedException ( ProjectNode.makefile );
315 MingwModuleHandler::SetBackend ( this );
316 MingwModuleHandler::SetMakefile ( fMakefile );
317 MingwModuleHandler::SetUsePch ( use_pch );
318 }
319
320 void
321 MingwBackend::CloseMakefile () const
322 {
323 if (fMakefile)
324 fclose ( fMakefile );
325 }
326
327 void
328 MingwBackend::GenerateHeader () const
329 {
330 fprintf ( fMakefile, "# THIS FILE IS AUTOMATICALLY GENERATED, EDIT 'ReactOS.xml' INSTEAD\n\n" );
331 }
332
333 void
334 MingwBackend::GenerateProjectCFlagsMacro ( const char* assignmentOperation,
335 IfableData& data ) const
336 {
337 size_t i;
338
339 fprintf (
340 fMakefile,
341 "PROJECT_CFLAGS %s",
342 assignmentOperation );
343 for ( i = 0; i < data.includes.size(); i++ )
344 {
345 fprintf (
346 fMakefile,
347 " -I%s",
348 data.includes[i]->directory.c_str() );
349 }
350
351 for ( i = 0; i < data.defines.size(); i++ )
352 {
353 Define& d = *data.defines[i];
354 fprintf (
355 fMakefile,
356 " -D%s",
357 d.name.c_str() );
358 if ( d.value.size() )
359 fprintf (
360 fMakefile,
361 "=%s",
362 d.value.c_str() );
363 }
364 fprintf ( fMakefile, "\n" );
365 }
366
367 void
368 MingwBackend::GenerateGlobalCFlagsAndProperties (
369 const char* assignmentOperation,
370 IfableData& data ) const
371 {
372 size_t i;
373
374 for ( i = 0; i < data.properties.size(); i++ )
375 {
376 Property& prop = *data.properties[i];
377 fprintf ( fMakefile, "%s := %s\n",
378 prop.name.c_str(),
379 prop.value.c_str() );
380 }
381
382 if ( data.includes.size() || data.defines.size() )
383 {
384 GenerateProjectCFlagsMacro ( assignmentOperation,
385 data );
386 }
387
388 for ( i = 0; i < data.ifs.size(); i++ )
389 {
390 If& rIf = *data.ifs[i];
391 if ( rIf.data.defines.size()
392 || rIf.data.includes.size()
393 || rIf.data.ifs.size() )
394 {
395 fprintf (
396 fMakefile,
397 "ifeq (\"$(%s)\",\"%s\")\n",
398 rIf.property.c_str(),
399 rIf.value.c_str() );
400 GenerateGlobalCFlagsAndProperties (
401 "+=",
402 rIf.data );
403 fprintf (
404 fMakefile,
405 "endif\n\n" );
406 }
407 }
408 }
409
410 string
411 MingwBackend::GenerateProjectLFLAGS () const
412 {
413 string lflags;
414 for ( size_t i = 0; i < ProjectNode.linkerFlags.size (); i++ )
415 {
416 LinkerFlag& linkerFlag = *ProjectNode.linkerFlags[i];
417 if ( lflags.length () > 0 )
418 lflags += " ";
419 lflags += linkerFlag.flag;
420 }
421 return lflags;
422 }
423
424 void
425 MingwBackend::GenerateGlobalVariables () const
426 {
427 GenerateGlobalCFlagsAndProperties (
428 "=",
429 ProjectNode.non_if_data );
430
431 fprintf ( fMakefile, "PROJECT_RCFLAGS := $(PROJECT_CFLAGS)\n" );
432 fprintf ( fMakefile, "PROJECT_WIDLFLAGS := $(PROJECT_CFLAGS)\n" );
433 fprintf ( fMakefile, "PROJECT_LFLAGS := %s\n",
434 GenerateProjectLFLAGS ().c_str () );
435 fprintf ( fMakefile, "PROJECT_CFLAGS += -Wall\n" );
436 fprintf ( fMakefile, "\n" );
437 }
438
439 bool
440 MingwBackend::IncludeInAllTarget ( const Module& module ) const
441 {
442 if ( MingwModuleHandler::ReferenceObjects ( module ) )
443 return false;
444 if ( module.type == BootSector )
445 return false;
446 if ( module.type == Iso )
447 return false;
448 if ( module.type == LiveIso )
449 return false;
450 if ( module.type == Test )
451 return false;
452 return true;
453 }
454
455 void
456 MingwBackend::GenerateAllTarget ( const vector<MingwModuleHandler*>& handlers ) const
457 {
458 fprintf ( fMakefile, "all:" );
459 int wrap_count = 0;
460 size_t iend = handlers.size ();
461 for ( size_t i = 0; i < iend; i++ )
462 {
463 const Module& module = handlers[i]->module;
464 if ( IncludeInAllTarget ( module ) )
465 {
466 if ( wrap_count++ == 5 )
467 fprintf ( fMakefile, " \\\n\t\t" ), wrap_count = 0;
468 fprintf ( fMakefile,
469 " %s",
470 GetTargetMacro(module).c_str () );
471 }
472 }
473 fprintf ( fMakefile, "\n\t\n\n" );
474 }
475
476 string
477 MingwBackend::GetBuildToolDependencies () const
478 {
479 string dependencies;
480 for ( size_t i = 0; i < ProjectNode.modules.size (); i++ )
481 {
482 Module& module = *ProjectNode.modules[i];
483 if ( module.type == BuildTool )
484 {
485 if ( dependencies.length () > 0 )
486 dependencies += " ";
487 dependencies += module.GetDependencyPath ();
488 }
489 }
490 return dependencies;
491 }
492
493 void
494 MingwBackend::GenerateInitTarget () const
495 {
496 fprintf ( fMakefile,
497 "INIT = %s\n",
498 GetBuildToolDependencies ().c_str () );
499 fprintf ( fMakefile, "\n" );
500 }
501
502 void
503 MingwBackend::GenerateXmlBuildFilesMacro() const
504 {
505 fprintf ( fMakefile,
506 "XMLBUILDFILES = %s \\\n",
507 ProjectNode.GetProjectFilename ().c_str () );
508 string xmlbuildFilenames;
509 int numberOfExistingFiles = 0;
510 for ( size_t i = 0; i < ProjectNode.xmlbuildfiles.size (); i++ )
511 {
512 XMLInclude& xmlbuildfile = *ProjectNode.xmlbuildfiles[i];
513 if ( !xmlbuildfile.fileExists )
514 continue;
515 numberOfExistingFiles++;
516 if ( xmlbuildFilenames.length () > 0 )
517 xmlbuildFilenames += " ";
518 xmlbuildFilenames += NormalizeFilename ( xmlbuildfile.topIncludeFilename );
519 if ( numberOfExistingFiles % 5 == 4 || i == ProjectNode.xmlbuildfiles.size () - 1 )
520 {
521 fprintf ( fMakefile,
522 "\t%s",
523 xmlbuildFilenames.c_str ());
524 if ( i == ProjectNode.xmlbuildfiles.size () - 1 )
525 {
526 fprintf ( fMakefile, "\n" );
527 }
528 else
529 {
530 fprintf ( fMakefile,
531 " \\\n",
532 xmlbuildFilenames.c_str () );
533 }
534 xmlbuildFilenames.resize ( 0 );
535 }
536 numberOfExistingFiles++;
537 }
538 fprintf ( fMakefile, "\n" );
539 }
540
541 void
542 MingwBackend::CheckAutomaticDependencies ()
543 {
544 printf ( "Checking automatic dependencies..." );
545 AutomaticDependency automaticDependency ( ProjectNode );
546 automaticDependency.Process ();
547 automaticDependency.CheckAutomaticDependencies ( verbose );
548 printf ( "done\n" );
549 }
550
551 bool
552 MingwBackend::IncludeDirectoryTarget ( const string& directory ) const
553 {
554 if ( directory == "$(INTERMEDIATE)" SSEP "tools")
555 return false;
556 else
557 return true;
558 }
559
560 void
561 MingwBackend::GenerateDirectories ()
562 {
563 printf ( "Creating directories..." );
564 intermediateDirectory->GenerateTree ( "", verbose );
565 outputDirectory->GenerateTree ( "", verbose );
566 installDirectory->GenerateTree ( "", verbose );
567 printf ( "done\n" );
568 }
569
570 bool
571 MingwBackend::TryToDetectThisCompiler ( const string& compiler )
572 {
573 string command = ssprintf (
574 "%s -v 2>%s",
575 compiler.c_str (),
576 NUL );
577 int exitcode = system ( command.c_str () );
578 return (exitcode == 0);
579 }
580
581 void
582 MingwBackend::DetectCompiler ()
583 {
584 printf ( "Detecting compiler..." );
585
586 bool detectedCompiler = false;
587 const string& ROS_PREFIXValue = Environment::GetVariable ( "ROS_PREFIX" );
588 if ( ROS_PREFIXValue.length () > 0 )
589 {
590 compilerCommand = ROS_PREFIXValue + "-gcc";
591 detectedCompiler = TryToDetectThisCompiler ( compilerCommand );
592 }
593 if ( !detectedCompiler )
594 {
595 compilerCommand = "gcc";
596 detectedCompiler = TryToDetectThisCompiler ( compilerCommand );
597 }
598 if ( !detectedCompiler )
599 {
600 compilerCommand = "mingw32-gcc";
601 detectedCompiler = TryToDetectThisCompiler ( compilerCommand );
602 }
603 if ( detectedCompiler )
604 printf ( "detected (%s)\n", compilerCommand.c_str () );
605 else
606 printf ( "not detected\n" );
607 }
608
609 void
610 MingwBackend::DetectPipeSupport ()
611 {
612 printf ( "Detecting compiler -pipe support..." );
613
614 string pipe_detection = "tools" SSEP "rbuild" SSEP "backend" SSEP "mingw" SSEP "pipe_detection.c";
615 string pipe_detectionObjectFilename = ReplaceExtension ( pipe_detection,
616 ".o" );
617 string command = ssprintf (
618 "%s -pipe -c %s -o %s 2>%s",
619 compilerCommand.c_str (),
620 pipe_detection.c_str (),
621 pipe_detectionObjectFilename.c_str (),
622 NUL );
623 int exitcode = system ( command.c_str () );
624 FILE* f = fopen ( pipe_detectionObjectFilename.c_str (), "rb" );
625 if ( f )
626 {
627 usePipe = (exitcode == 0);
628 fclose ( f );
629 unlink ( pipe_detectionObjectFilename.c_str () );
630 }
631 else
632 usePipe = false;
633
634 if ( usePipe )
635 printf ( "detected\n" );
636 else
637 printf ( "not detected\n" );
638 }
639
640 void
641 MingwBackend::DetectPCHSupport ()
642 {
643 printf ( "Detecting compiler pre-compiled header support..." );
644
645 string path = "tools" SSEP "rbuild" SSEP "backend" SSEP "mingw" SSEP "pch_detection.h";
646 string cmd = ssprintf (
647 "%s -c %s 2>%s",
648 compilerCommand.c_str (),
649 path.c_str (),
650 NUL );
651 system ( cmd.c_str () );
652 path += ".gch";
653
654 FILE* f = fopen ( path.c_str (), "rb" );
655 if ( f )
656 {
657 use_pch = true;
658 fclose ( f );
659 unlink ( path.c_str () );
660 }
661 else
662 use_pch = false;
663
664 if ( use_pch )
665 printf ( "detected\n" );
666 else
667 printf ( "not detected\n" );
668 }
669
670 void
671 MingwBackend::GetNonModuleInstallTargetFiles (
672 vector<string>& out ) const
673 {
674 for ( size_t i = 0; i < ProjectNode.installfiles.size (); i++ )
675 {
676 const InstallFile& installfile = *ProjectNode.installfiles[i];
677 string targetFilenameNoFixup = installfile.base + SSEP + installfile.newname;
678 string targetFilename = MingwModuleHandler::PassThruCacheDirectory (
679 NormalizeFilename ( targetFilenameNoFixup ),
680 installDirectory );
681 out.push_back ( targetFilename );
682 }
683 }
684
685 void
686 MingwBackend::GetModuleInstallTargetFiles (
687 vector<string>& out ) const
688 {
689 for ( size_t i = 0; i < ProjectNode.modules.size (); i++ )
690 {
691 const Module& module = *ProjectNode.modules[i];
692 if ( module.installName.length () > 0 )
693 {
694 string targetFilenameNoFixup = module.installBase + SSEP + module.installName;
695 string targetFilename = MingwModuleHandler::PassThruCacheDirectory (
696 NormalizeFilename ( targetFilenameNoFixup ),
697 installDirectory );
698 out.push_back ( targetFilename );
699 }
700 }
701 }
702
703 void
704 MingwBackend::GetInstallTargetFiles (
705 vector<string>& out ) const
706 {
707 GetNonModuleInstallTargetFiles ( out );
708 GetModuleInstallTargetFiles ( out );
709 }
710
711 void
712 MingwBackend::OutputInstallTarget ( const string& sourceFilename,
713 const string& targetFilename,
714 const string& targetDirectory )
715 {
716 string normalizedTargetFilename = MingwModuleHandler::PassThruCacheDirectory (
717 NormalizeFilename ( targetDirectory + SSEP + targetFilename ),
718 installDirectory );
719 string normalizedTargetDirectory = MingwModuleHandler::PassThruCacheDirectory (
720 NormalizeFilename ( targetDirectory ),
721 installDirectory );
722 fprintf ( fMakefile,
723 "%s: %s %s\n",
724 normalizedTargetFilename.c_str (),
725 sourceFilename.c_str (),
726 normalizedTargetDirectory.c_str () );
727 fprintf ( fMakefile,
728 "\t$(ECHO_CP)\n" );
729 fprintf ( fMakefile,
730 "\t${cp} %s %s 1>$(NUL)\n",
731 sourceFilename.c_str (),
732 normalizedTargetFilename.c_str () );
733 }
734
735 void
736 MingwBackend::OutputNonModuleInstallTargets ()
737 {
738 for ( size_t i = 0; i < ProjectNode.installfiles.size (); i++ )
739 {
740 const InstallFile& installfile = *ProjectNode.installfiles[i];
741 OutputInstallTarget ( installfile.GetPath (),
742 installfile.newname,
743 installfile.base );
744 }
745 }
746
747 void
748 MingwBackend::OutputModuleInstallTargets ()
749 {
750 for ( size_t i = 0; i < ProjectNode.modules.size (); i++ )
751 {
752 const Module& module = *ProjectNode.modules[i];
753 if ( module.installName.length () > 0 )
754 {
755 string sourceFilename = MingwModuleHandler::PassThruCacheDirectory (
756 NormalizeFilename ( module.GetPath () ),
757 outputDirectory );
758 OutputInstallTarget ( sourceFilename,
759 module.installName,
760 module.installBase );
761 }
762 }
763 }
764
765 string
766 MingwBackend::GetRegistrySourceFiles ()
767 {
768 return "bootdata" SSEP "hivecls.inf "
769 "bootdata" SSEP "hivedef.inf "
770 "bootdata" SSEP "hiveinst.inf "
771 "bootdata" SSEP "hivesft.inf "
772 "bootdata" SSEP "hivesys.inf";
773 }
774
775 string
776 MingwBackend::GetRegistryTargetFiles ()
777 {
778 string system32ConfigDirectory = NormalizeFilename (
779 MingwModuleHandler::PassThruCacheDirectory (
780 "system32" SSEP "config" SSEP,
781 installDirectory ) );
782 return system32ConfigDirectory + SSEP "default " +
783 system32ConfigDirectory + SSEP "sam " +
784 system32ConfigDirectory + SSEP "security " +
785 system32ConfigDirectory + SSEP "software " +
786 system32ConfigDirectory + SSEP "system";
787 }
788
789 void
790 MingwBackend::OutputRegistryInstallTarget ()
791 {
792 string system32ConfigDirectory = NormalizeFilename (
793 MingwModuleHandler::PassThruCacheDirectory (
794 "system32" SSEP "config" SSEP,
795 installDirectory ) );
796
797 string registrySourceFiles = GetRegistrySourceFiles ();
798 string registryTargetFiles = GetRegistryTargetFiles ();
799 fprintf ( fMakefile,
800 "install_registry: %s\n",
801 registryTargetFiles.c_str () );
802 fprintf ( fMakefile,
803 "%s: %s %s $(MKHIVE_TARGET)\n",
804 registryTargetFiles.c_str (),
805 registrySourceFiles.c_str (),
806 system32ConfigDirectory.c_str () );
807 fprintf ( fMakefile,
808 "\t$(ECHO_MKHIVE)\n" );
809 fprintf ( fMakefile,
810 "\t$(MKHIVE_TARGET) bootdata %s bootdata" SSEP "hiveinst.inf\n",
811 system32ConfigDirectory.c_str () );
812 fprintf ( fMakefile,
813 "\n" );
814 }
815
816 void
817 MingwBackend::GenerateInstallTarget ()
818 {
819 vector<string> vInstallTargetFiles;
820 GetInstallTargetFiles ( vInstallTargetFiles );
821 string installTargetFiles = v2s ( vInstallTargetFiles, 5 );
822
823 fprintf ( fMakefile,
824 "install: %s install_registry\n",
825 installTargetFiles.c_str () );
826 OutputNonModuleInstallTargets ();
827 OutputModuleInstallTargets ();
828 OutputRegistryInstallTarget ();
829 fprintf ( fMakefile,
830 "\n" );
831 }