b9195b5487e95dace6094403142d4663bdd9276a
[reactos.git] / reactos / tools / rbuild / backend / mingw / modulehandler.cpp
1
2 #include "../../pch.h"
3 #include <assert.h>
4
5 #include "../../rbuild.h"
6 #include "mingw.h"
7 #include "modulehandler.h"
8
9 using std::string;
10 using std::vector;
11 using std::map;
12
13 map<ModuleType,MingwModuleHandler*>*
14 MingwModuleHandler::handler_map = NULL;
15 int
16 MingwModuleHandler::ref = 0;
17
18 FILE*
19 MingwModuleHandler::fMakefile = NULL;
20
21 MingwModuleHandler::MingwModuleHandler ( ModuleType moduletype )
22 {
23 if ( !ref++ )
24 handler_map = new map<ModuleType,MingwModuleHandler*>;
25 (*handler_map)[moduletype] = this;
26 }
27
28 MingwModuleHandler::~MingwModuleHandler()
29 {
30 if ( !--ref )
31 {
32 delete handler_map;
33 handler_map = NULL;
34 }
35 }
36
37 void
38 MingwModuleHandler::SetMakefile ( FILE* f )
39 {
40 fMakefile = f;
41 }
42
43 MingwModuleHandler*
44 MingwModuleHandler::LookupHandler ( const string& location,
45 ModuleType moduletype )
46 {
47 if ( !handler_map )
48 throw Exception ( "internal tool error: no registered module handlers" );
49 MingwModuleHandler* h = (*handler_map)[moduletype];
50 if ( !h )
51 {
52 throw UnknownModuleTypeException ( location, moduletype );
53 return NULL;
54 }
55 return h;
56 }
57
58 string
59 MingwModuleHandler::GetWorkingDirectory () const
60 {
61 return ".";
62 }
63
64 string
65 MingwModuleHandler::GetExtension ( const string& filename ) const
66 {
67 size_t index = filename.find_last_of ( '.' );
68 if (index != string::npos)
69 return filename.substr ( index );
70 return "";
71 }
72
73 string
74 MingwModuleHandler::ReplaceExtension ( const string& filename,
75 const string& newExtension ) const
76 {
77 size_t index = filename.find_last_of ( '.' );
78 if (index != string::npos)
79 return filename.substr ( 0, index ) + newExtension;
80 return filename;
81 }
82
83 string
84 MingwModuleHandler::GetModuleArchiveFilename ( const Module& module ) const
85 {
86 return ReplaceExtension ( FixupTargetFilename ( module.GetPath () ),
87 ".a" );
88 }
89
90 string
91 MingwModuleHandler::GetImportLibraryDependencies ( const Module& module ) const
92 {
93 if ( module.libraries.size () == 0 )
94 return "";
95
96 string dependencies ( "" );
97 for ( size_t i = 0; i < module.libraries.size (); i++ )
98 {
99 if ( dependencies.size () > 0 )
100 dependencies += " ";
101 const Module* importedModule = module.project.LocateModule ( module.libraries[i]->name );
102 assert ( importedModule != NULL );
103 dependencies += FixupTargetFilename ( importedModule->GetDependencyPath () ).c_str ();
104 }
105 return dependencies;
106 }
107
108 string
109 MingwModuleHandler::GetModuleDependencies ( const Module& module ) const
110 {
111 if ( module.dependencies.size () == 0 )
112 return "";
113
114 string dependencies ( "" );
115 for ( size_t i = 0; i < module.dependencies.size (); i++ )
116 {
117 if ( dependencies.size () > 0 )
118 dependencies += " ";
119 const Dependency* dependency = module.dependencies[i];
120 const Module* dependencyModule = dependency->dependencyModule;
121 dependencies += dependencyModule->GetTargets ();
122 }
123 return dependencies;
124 }
125
126 string
127 MingwModuleHandler::GetAllDependencies ( const Module& module ) const
128 {
129 string dependencies = GetImportLibraryDependencies ( module );
130 string s = GetModuleDependencies ( module );
131 if (s.length () > 0)
132 {
133 dependencies += " ";
134 dependencies += s;
135 }
136 return dependencies;
137 }
138
139 string
140 MingwModuleHandler::GetSourceFilenames ( const Module& module ) const
141 {
142 size_t i;
143
144 string sourceFilenames ( "" );
145 for ( i = 0; i < module.files.size (); i++ )
146 sourceFilenames += " " + module.files[i]->name;
147 vector<If*> ifs = module.ifs;
148 for ( i = 0; i < ifs.size(); i++ )
149 {
150 size_t j;
151 If& rIf = *ifs[i];
152 for ( j = 0; j < rIf.ifs.size(); j++ )
153 ifs.push_back ( rIf.ifs[j] );
154 for ( j = 0; j < rIf.files.size(); j++ )
155 sourceFilenames += " " + rIf.files[j]->name;
156 }
157 return sourceFilenames;
158 }
159
160 string
161 MingwModuleHandler::GetObjectFilename ( const string& sourceFilename ) const
162 {
163 string newExtension;
164 string extension = GetExtension ( sourceFilename );
165 if ( extension == ".rc" || extension == ".RC" )
166 newExtension = ".coff";
167 else
168 newExtension = ".o";
169 return FixupTargetFilename ( ReplaceExtension ( sourceFilename,
170 newExtension ) );
171 }
172
173 string
174 MingwModuleHandler::GetObjectFilenames ( const Module& module ) const
175 {
176 if ( module.files.size () == 0 )
177 return "";
178
179 string objectFilenames ( "" );
180 for ( size_t i = 0; i < module.files.size (); i++ )
181 {
182 if ( objectFilenames.size () > 0 )
183 objectFilenames += " ";
184 objectFilenames += GetObjectFilename ( module.files[i]->name );
185 }
186 return objectFilenames;
187 }
188
189 string
190 MingwModuleHandler::GenerateGccDefineParametersFromVector ( const vector<Define*>& defines ) const
191 {
192 string parameters;
193 for (size_t i = 0; i < defines.size (); i++)
194 {
195 Define& define = *defines[i];
196 if (parameters.length () > 0)
197 parameters += " ";
198 parameters += "-D";
199 parameters += define.name;
200 if (define.value.length () > 0)
201 {
202 parameters += "=";
203 parameters += define.value;
204 }
205 }
206 return parameters;
207 }
208
209 string
210 MingwModuleHandler::GenerateGccDefineParameters ( const Module& module ) const
211 {
212 string parameters = GenerateGccDefineParametersFromVector ( module.project.defines );
213 string s = GenerateGccDefineParametersFromVector ( module.defines );
214 if (s.length () > 0)
215 {
216 parameters += " ";
217 parameters += s;
218 }
219 return parameters;
220 }
221
222 string
223 MingwModuleHandler::ConcatenatePaths ( const string& path1,
224 const string& path2 ) const
225 {
226 if ( ( path1.length () == 0 ) || ( path1 == "." ) || ( path1 == "./" ) )
227 return path2;
228 if ( path1[path1.length ()] == CSEP )
229 return path1 + path2;
230 else
231 return path1 + CSEP + path2;
232 }
233
234 string
235 MingwModuleHandler::GenerateGccIncludeParametersFromVector ( const vector<Include*>& includes ) const
236 {
237 string parameters;
238 for ( size_t i = 0; i < includes.size (); i++ )
239 {
240 Include& include = *includes[i];
241 if (parameters.length () > 0)
242 parameters += " ";
243 parameters += "-I" + include.directory;
244 }
245 return parameters;
246 }
247
248 string
249 MingwModuleHandler::GenerateGccIncludeParameters ( const Module& module ) const
250 {
251 string parameters = GenerateGccIncludeParametersFromVector ( module.includes );
252 string s = GenerateGccIncludeParametersFromVector ( module.project.includes );
253 if ( s.length () > 0 )
254 {
255 parameters += " ";
256 parameters += s;
257 }
258 return parameters;
259 }
260
261
262 string
263 MingwModuleHandler::GenerateLinkerParametersFromVector ( const vector<LinkerFlag*>& linkerFlags ) const
264 {
265 string parameters;
266 for ( size_t i = 0; i < linkerFlags.size (); i++ )
267 {
268 LinkerFlag& linkerFlag = *linkerFlags[i];
269 if ( parameters.length () > 0 )
270 parameters += " ";
271 parameters += linkerFlag.flag;
272 }
273 return parameters;
274 }
275
276 string
277 MingwModuleHandler::GenerateLinkerParameters ( const Module& module ) const
278 {
279 return GenerateLinkerParametersFromVector ( module.linkerFlags );
280 }
281
282 void
283 MingwModuleHandler::GenerateMacro ( const char* assignmentOperation,
284 const string& macro,
285 const vector<Include*>& includes,
286 const vector<Define*>& defines ) const
287 {
288 size_t i;
289
290 fprintf (
291 fMakefile,
292 "%s %s",
293 macro.c_str(),
294 assignmentOperation );
295 for ( i = 0; i < includes.size(); i++ )
296 {
297 fprintf (
298 fMakefile,
299 " -I%s",
300 includes[i]->directory.c_str() );
301 }
302 for ( i = 0; i < defines.size(); i++ )
303 {
304 Define& d = *defines[i];
305 fprintf (
306 fMakefile,
307 " -D%s",
308 d.name.c_str() );
309 if ( d.value.size() )
310 fprintf (
311 fMakefile,
312 "=%s",
313 d.value.c_str() );
314 }
315 fprintf ( fMakefile, "\n" );
316 }
317
318 void
319 MingwModuleHandler::GenerateMacros (
320 const char* assignmentOperation,
321 const vector<File*>& files,
322 const vector<Include*>& includes,
323 const vector<Define*>& defines,
324 const vector<LinkerFlag*>* linkerFlags,
325 const vector<If*>& ifs,
326 const string& cflags_macro,
327 const string& nasmflags_macro,
328 const string& windresflags_macro,
329 const string& linkerflags_macro,
330 const string& objs_macro) const
331 {
332 size_t i;
333
334 if ( includes.size() || defines.size() )
335 {
336 GenerateMacro ( assignmentOperation,
337 cflags_macro,
338 includes,
339 defines );
340 GenerateMacro ( assignmentOperation,
341 windresflags_macro,
342 includes,
343 defines );
344 }
345
346 if ( linkerFlags != NULL )
347 {
348 string linkerParameters = GenerateLinkerParametersFromVector ( *linkerFlags );
349 if ( linkerParameters.size () > 0 )
350 {
351 fprintf (
352 fMakefile,
353 "%s %s %s\n",
354 linkerflags_macro.c_str (),
355 assignmentOperation,
356 linkerParameters.c_str() );
357 }
358 }
359
360 if ( files.size() )
361 {
362 fprintf (
363 fMakefile,
364 "%s %s",
365 objs_macro.c_str(),
366 assignmentOperation );
367 for ( i = 0; i < files.size(); i++ )
368 {
369 fprintf (
370 fMakefile,
371 "%s%s",
372 ( i%10 == 9 ? "\\\n\t" : " " ),
373 GetObjectFilename(files[i]->name).c_str() );
374 }
375 fprintf ( fMakefile, "\n" );
376 }
377
378 for ( i = 0; i < ifs.size(); i++ )
379 {
380 If& rIf = *ifs[i];
381 if ( rIf.defines.size() || rIf.includes.size() || rIf.files.size() || rIf.ifs.size() )
382 {
383 fprintf (
384 fMakefile,
385 "ifeq (\"$(%s)\",\"%s\")\n",
386 rIf.property.c_str(),
387 rIf.value.c_str() );
388 GenerateMacros (
389 "+=",
390 rIf.files,
391 rIf.includes,
392 rIf.defines,
393 NULL,
394 rIf.ifs,
395 cflags_macro,
396 nasmflags_macro,
397 windresflags_macro,
398 linkerflags_macro,
399 objs_macro );
400 fprintf (
401 fMakefile,
402 "endif\n\n" );
403 }
404 }
405 }
406
407 void
408 MingwModuleHandler::GenerateMacros (
409 const Module& module,
410 const string& cflags_macro,
411 const string& nasmflags_macro,
412 const string& windresflags_macro,
413 const string& linkerflags_macro,
414 const string& objs_macro) const
415 {
416 GenerateMacros (
417 "=",
418 module.files,
419 module.includes,
420 module.defines,
421 &module.linkerFlags,
422 module.ifs,
423 cflags_macro,
424 nasmflags_macro,
425 windresflags_macro,
426 linkerflags_macro,
427 objs_macro );
428 fprintf ( fMakefile, "\n" );
429
430 fprintf (
431 fMakefile,
432 "%s += $(PROJECT_CFLAGS)\n\n",
433 cflags_macro.c_str () );
434
435 fprintf (
436 fMakefile,
437 "%s += $(PROJECT_RCFLAGS)\n\n",
438 windresflags_macro.c_str () );
439
440 fprintf (
441 fMakefile,
442 "%s_LFLAGS += $(PROJECT_LFLAGS)\n\n",
443 module.name.c_str () );
444 }
445
446 string
447 MingwModuleHandler::GenerateGccCommand ( const Module& module,
448 const string& sourceFilename,
449 const string& cc,
450 const string& cflagsMacro ) const
451 {
452 string objectFilename = GetObjectFilename ( sourceFilename );
453 return ssprintf ( "%s -c %s -o %s %s\n",
454 cc.c_str (),
455 sourceFilename.c_str (),
456 objectFilename.c_str (),
457 cflagsMacro.c_str () );
458 }
459
460 string
461 MingwModuleHandler::GenerateGccAssemblerCommand ( const Module& module,
462 const string& sourceFilename,
463 const string& cc,
464 const string& cflagsMacro ) const
465 {
466 string objectFilename = GetObjectFilename ( sourceFilename );
467 return ssprintf ( "%s -x assembler-with-cpp -c %s -o %s -D__ASM__ %s\n",
468 cc.c_str (),
469 sourceFilename.c_str (),
470 objectFilename.c_str (),
471 cflagsMacro.c_str () );
472 }
473
474 string
475 MingwModuleHandler::GenerateNasmCommand ( const Module& module,
476 const string& sourceFilename,
477 const string& nasmflagsMacro ) const
478 {
479 string objectFilename = GetObjectFilename ( sourceFilename );
480 return ssprintf ( "%s -f win32 %s -o %s %s\n",
481 "nasm",
482 sourceFilename.c_str (),
483 objectFilename.c_str (),
484 nasmflagsMacro.c_str () );
485 }
486
487 string
488 MingwModuleHandler::GenerateWindresCommand ( const Module& module,
489 const string& sourceFilename,
490 const string& windresflagsMacro ) const
491 {
492 string objectFilename = GetObjectFilename ( sourceFilename );
493 return ssprintf ( "%s %s -o %s ${%s}\n",
494 "${windres}",
495 sourceFilename.c_str (),
496 objectFilename.c_str (),
497 windresflagsMacro.c_str () );
498 }
499
500 string
501 MingwModuleHandler::GenerateCommand ( const Module& module,
502 const string& sourceFilename,
503 const string& cc,
504 const string& cflagsMacro,
505 const string& nasmflagsMacro,
506 const string& windresflagsMacro ) const
507 {
508 string extension = GetExtension ( sourceFilename );
509 if ( extension == ".c" || extension == ".C" )
510 return GenerateGccCommand ( module,
511 sourceFilename,
512 cc,
513 cflagsMacro );
514 else if ( extension == ".s" || extension == ".S" )
515 return GenerateGccAssemblerCommand ( module,
516 sourceFilename,
517 cc,
518 cflagsMacro );
519 else if ( extension == ".asm" || extension == ".ASM" )
520 return GenerateNasmCommand ( module,
521 sourceFilename,
522 nasmflagsMacro );
523 else if ( extension == ".rc" || extension == ".RC" )
524 return GenerateWindresCommand ( module,
525 sourceFilename,
526 windresflagsMacro );
527
528 throw InvalidOperationException ( __FILE__,
529 __LINE__,
530 "Unsupported filename extension '%s' in file '%s'",
531 extension.c_str (),
532 sourceFilename.c_str () );
533 }
534
535 string
536 MingwModuleHandler::GenerateLinkerCommand ( const Module& module,
537 const string& linker,
538 const string& linkerParameters,
539 const string& objectFilenames ) const
540 {
541 string target ( FixupTargetFilename ( module.GetPath () ) );
542 string importLibraryDependencies = GetImportLibraryDependencies ( module );
543 return ssprintf ( "%s %s -o %s %s %s %s\n",
544 linker.c_str (),
545 linkerParameters.c_str (),
546 target.c_str (),
547 objectFilenames.c_str (),
548 importLibraryDependencies.c_str (),
549 GetLinkerMacro ( module ).c_str () );
550 }
551
552 void
553 MingwModuleHandler::GenerateObjectFileTargets ( const Module& module,
554 const vector<File*>& files,
555 const vector<If*>& ifs,
556 const string& cc,
557 const string& cflagsMacro,
558 const string& nasmflagsMacro,
559 const string& windresflagsMacro ) const
560 {
561 size_t i;
562
563 for ( i = 0; i < files.size (); i++ )
564 {
565 string sourceFilename = files[i]->name;
566 string objectFilename = GetObjectFilename ( sourceFilename );
567 fprintf ( fMakefile,
568 "%s: %s\n",
569 objectFilename.c_str (),
570 sourceFilename.c_str () );
571 fprintf ( fMakefile,
572 "\t%s\n",
573 GenerateCommand ( module,
574 sourceFilename,
575 cc,
576 cflagsMacro,
577 nasmflagsMacro,
578 windresflagsMacro ).c_str () );
579 }
580
581 for ( i = 0; i < ifs.size(); i++ )
582 GenerateObjectFileTargets ( module,
583 ifs[i]->files,
584 ifs[i]->ifs,
585 cc,
586 cflagsMacro,
587 nasmflagsMacro,
588 windresflagsMacro );
589 }
590
591 void
592 MingwModuleHandler::GenerateObjectFileTargets ( const Module& module,
593 const string& cc,
594 const string& cflagsMacro,
595 const string& nasmflagsMacro,
596 const string& windresflagsMacro ) const
597 {
598 GenerateObjectFileTargets ( module,
599 module.files,
600 module.ifs,
601 cc,
602 cflagsMacro,
603 nasmflagsMacro,
604 windresflagsMacro );
605 fprintf ( fMakefile, "\n" );
606 }
607
608 void
609 MingwModuleHandler::GetCleanTargets ( vector<string>& out,
610 const vector<File*>& files,
611 const vector<If*>& ifs ) const
612 {
613 size_t i;
614
615 for ( i = 0; i < files.size(); i++ )
616 out.push_back ( GetObjectFilename(files[i]->name) );
617
618 for ( i = 0; i < ifs.size(); i++ )
619 GetCleanTargets ( out, ifs[i]->files, ifs[i]->ifs );
620 }
621
622 string
623 MingwModuleHandler::GenerateArchiveTarget ( const Module& module,
624 const string& ar,
625 const string& objs_macro ) const
626 {
627 string archiveFilename = GetModuleArchiveFilename ( module );
628
629 fprintf ( fMakefile,
630 "%s: %s\n",
631 archiveFilename.c_str (),
632 objs_macro.c_str ());
633
634 fprintf ( fMakefile,
635 "\t%s -rc %s %s\n\n",
636 ar.c_str (),
637 archiveFilename.c_str (),
638 objs_macro.c_str ());
639
640 return archiveFilename;
641 }
642
643 string
644 MingwModuleHandler::GetObjectsMacro ( const Module& module ) const
645 {
646 return ssprintf ( "$(%s_OBJS)",
647 module.name.c_str () );
648 }
649
650 string
651 MingwModuleHandler::GetLinkerMacro ( const Module& module ) const
652 {
653 return ssprintf ( "$(%s_LFLAGS)",
654 module.name.c_str () );
655 }
656
657 void
658 MingwModuleHandler::GenerateMacrosAndTargets (
659 const Module& module,
660 const string& cc,
661 const string& ar ) const
662 {
663 string cflagsMacro = ssprintf ("%s_CFLAGS", module.name.c_str ());
664 string nasmflagsMacro = ssprintf ("%s_NASMFLAGS", module.name.c_str ());
665 string windresflagsMacro = ssprintf ("%s_RCFLAGS", module.name.c_str ());
666 string linkerFlagsMacro = ssprintf ("%s_LFLAGS", module.name.c_str ());
667 string objectsMacro = ssprintf ("%s_OBJS", module.name.c_str ());
668
669 GenerateMacros ( module,
670 cflagsMacro,
671 nasmflagsMacro,
672 windresflagsMacro,
673 linkerFlagsMacro,
674 objectsMacro );
675
676 // generate phony target for module name
677 fprintf ( fMakefile, ".PHONY: %s\n",
678 module.name.c_str() );
679 fprintf ( fMakefile, "%s: %s\n\n",
680 module.name.c_str(),
681 module.GetPath().c_str() );
682
683 // future references to the macros will be to get their values
684 cflagsMacro = ssprintf ("$(%s)", cflagsMacro.c_str ());
685 nasmflagsMacro = ssprintf ("$(%s)", nasmflagsMacro.c_str ());
686 objectsMacro = ssprintf ("$(%s)", objectsMacro.c_str ());
687
688 string ar_target = GenerateArchiveTarget ( module, ar, objectsMacro );
689 GenerateObjectFileTargets ( module,
690 cc,
691 cflagsMacro,
692 nasmflagsMacro,
693 windresflagsMacro );
694
695 vector<string> clean_files;
696 clean_files.push_back ( FixupTargetFilename(module.GetPath()) );
697 clean_files.push_back ( ar_target );
698 GetCleanTargets ( clean_files, module.files, module.ifs );
699
700 fprintf ( fMakefile, "clean::\n\t-@$(rm)" );
701 for ( size_t i = 0; i < clean_files.size(); i++ )
702 {
703 if ( 9==(i%10) )
704 fprintf ( fMakefile, " 2>NUL\n\t-@$(rm)" );
705 fprintf ( fMakefile, " %s", clean_files[i].c_str() );
706 }
707 fprintf ( fMakefile, " 2>NUL\n\n" );
708 }
709
710 void
711 MingwModuleHandler::GenerateMacrosAndTargetsHost ( const Module& module ) const
712 {
713 GenerateMacrosAndTargets ( module, "${host_gcc}", "${host_ar}" );
714 }
715
716 void
717 MingwModuleHandler::GenerateMacrosAndTargetsTarget ( const Module& module ) const
718 {
719 GenerateMacrosAndTargets ( module, "${gcc}", "${ar}" );
720 }
721
722 string
723 MingwModuleHandler::GetInvocationDependencies ( const Module& module ) const
724 {
725 string dependencies;
726 for ( size_t i = 0; i < module.invocations.size (); i++ )
727 {
728 Invoke& invoke = *module.invocations[i];
729 if (invoke.invokeModule == &module)
730 /* Protect against circular dependencies */
731 continue;
732 if ( dependencies.length () > 0 )
733 dependencies += " ";
734 dependencies += invoke.GetTargets ();
735 }
736 return dependencies;
737 }
738
739 string
740 MingwModuleHandler::GetInvocationParameters ( const Invoke& invoke ) const
741 {
742 string parameters ( "" );
743 size_t i;
744 for (i = 0; i < invoke.output.size (); i++)
745 {
746 if (parameters.length () > 0)
747 parameters += " ";
748 InvokeFile& invokeFile = *invoke.output[i];
749 if (invokeFile.switches.length () > 0)
750 {
751 parameters += invokeFile.switches;
752 parameters += " ";
753 }
754 parameters += invokeFile.name;
755 }
756
757 for (i = 0; i < invoke.input.size (); i++)
758 {
759 if (parameters.length () > 0)
760 parameters += " ";
761 InvokeFile& invokeFile = *invoke.input[i];
762 if (invokeFile.switches.length () > 0)
763 {
764 parameters += invokeFile.switches;
765 parameters += " ";
766 }
767 parameters += invokeFile.name;
768 }
769
770 return parameters;
771 }
772
773 void
774 MingwModuleHandler::GenerateInvocations ( const Module& module ) const
775 {
776 if ( module.invocations.size () == 0 )
777 return;
778
779 for ( size_t i = 0; i < module.invocations.size (); i++ )
780 {
781 const Invoke& invoke = *module.invocations[i];
782
783 if ( invoke.invokeModule->type != BuildTool )
784 throw InvalidBuildFileException ( module.node.location,
785 "Only modules of type buildtool can be invoked." );
786
787 string invokeTarget = module.GetInvocationTarget ( i );
788 fprintf ( fMakefile,
789 "%s: %s\n\n",
790 invoke.GetTargets ().c_str (),
791 invokeTarget.c_str () );
792 fprintf ( fMakefile,
793 "%s: %s\n",
794 invokeTarget.c_str (),
795 FixupTargetFilename ( invoke.invokeModule->GetPath () ).c_str () );
796 fprintf ( fMakefile,
797 "\t%s %s\n\n",
798 FixupTargetFilename ( invoke.invokeModule->GetPath () ).c_str (),
799 GetInvocationParameters ( invoke ).c_str () );
800 fprintf ( fMakefile,
801 ".PNONY: %s\n\n",
802 invokeTarget.c_str () );
803 }
804 }
805
806 string
807 MingwModuleHandler::GetPreconditionDependenciesName ( const Module& module ) const
808 {
809 return ssprintf ( "%s_precondition",
810 module.name.c_str () );
811 }
812
813 void
814 MingwModuleHandler::GeneratePreconditionDependencies ( const Module& module ) const
815 {
816 string preconditionDependenciesName = GetPreconditionDependenciesName ( module );
817 string sourceFilenames = GetSourceFilenames ( module );
818 string dependencies = GetModuleDependencies ( module );
819 string s = GetInvocationDependencies ( module );
820 if ( s.length () > 0 )
821 {
822 if ( dependencies.length () > 0 )
823 dependencies += " ";
824 dependencies += s;
825 }
826
827 fprintf ( fMakefile,
828 ".PHONY: %s\n\n",
829 preconditionDependenciesName.c_str () );
830 fprintf ( fMakefile,
831 "%s: %s\n\n",
832 preconditionDependenciesName.c_str (),
833 dependencies.c_str () );
834 const char* p = sourceFilenames.c_str();
835 const char* end = p + strlen(p);
836 while ( p < end )
837 {
838 const char* p2 = &p[512];
839 if ( p2 > end )
840 p2 = end;
841 while ( p2 > p && !isspace(*p2) )
842 --p2;
843 if ( p == p2 )
844 {
845 p2 = strpbrk ( p, " \t" );
846 if ( !p2 )
847 p2 = end;
848 }
849 fprintf ( fMakefile,
850 "%.*s: %s\n",
851 p2-p,
852 p,
853 preconditionDependenciesName.c_str ());
854 p = p2;
855 p += strspn ( p, " \t" );
856 }
857 fprintf ( fMakefile, "\n" );
858 }
859
860
861 static MingwBuildToolModuleHandler buildtool_handler;
862
863 MingwBuildToolModuleHandler::MingwBuildToolModuleHandler()
864 : MingwModuleHandler ( BuildTool )
865 {
866 }
867
868 void
869 MingwBuildToolModuleHandler::Process ( const Module& module )
870 {
871 GeneratePreconditionDependencies ( module );
872 GenerateBuildToolModuleTarget ( module );
873 GenerateInvocations ( module );
874 }
875
876 void
877 MingwBuildToolModuleHandler::GenerateBuildToolModuleTarget ( const Module& module )
878 {
879 string target ( FixupTargetFilename ( module.GetPath () ) );
880 string archiveFilename = GetModuleArchiveFilename ( module );
881
882 GenerateMacrosAndTargetsHost ( module );
883
884 fprintf ( fMakefile, "%s: %s\n",
885 target.c_str (),
886 archiveFilename.c_str () );
887 fprintf ( fMakefile,
888 "\t${host_gcc} %s -o %s %s\n\n",
889 GetLinkerMacro ( module ).c_str (),
890 target.c_str (),
891 archiveFilename.c_str () );
892 }
893
894 static MingwKernelModuleHandler kernelmodule_handler;
895
896 MingwKernelModuleHandler::MingwKernelModuleHandler ()
897 : MingwModuleHandler ( Kernel )
898 {
899 }
900
901 void
902 MingwKernelModuleHandler::Process ( const Module& module )
903 {
904 GeneratePreconditionDependencies ( module );
905 GenerateKernelModuleTarget ( module );
906 GenerateInvocations ( module );
907 }
908
909 void
910 MingwKernelModuleHandler::GenerateKernelModuleTarget ( const Module& module )
911 {
912 static string ros_junk ( "$(ROS_TEMPORARY)" );
913 string target ( FixupTargetFilename (module.GetPath ()) );
914 string workingDirectory = GetWorkingDirectory ();
915 string objectsMacro = GetObjectsMacro ( module );
916 string importLibraryDependencies = GetImportLibraryDependencies ( module );
917 string base_tmp = ros_junk + module.name + ".base.tmp";
918 string junk_tmp = ros_junk + module.name + ".junk.tmp";
919 string temp_exp = ros_junk + module.name + ".temp.exp";
920 string gccOptions = ssprintf ("-Wl,-T,%s" SSEP "ntoskrnl.lnk -Wl,--subsystem,native -Wl,--entry,_NtProcessStartup -Wl,--image-base,0xC0000000 -Wl,--file-alignment,0x1000 -Wl,--section-alignment,0x1000 -nostartfiles -mdll",
921 module.GetBasePath ().c_str () );
922
923 GenerateMacrosAndTargetsTarget ( module );
924
925 fprintf ( fMakefile, "%s: %s %s\n",
926 target.c_str (),
927 objectsMacro.c_str (),
928 importLibraryDependencies.c_str () );
929 fprintf ( fMakefile,
930 "\t${gcc} %s %s -Wl,--base-file,%s -o %s %s %s\n",
931 GetLinkerMacro ( module ).c_str (),
932 gccOptions.c_str (),
933 base_tmp.c_str (),
934 junk_tmp.c_str (),
935 objectsMacro.c_str (),
936 importLibraryDependencies.c_str () );
937 fprintf ( fMakefile,
938 "\t${rm} %s\n",
939 junk_tmp.c_str () );
940 fprintf ( fMakefile,
941 "\t${dlltool} --dllname %s --base-file %s --def ntoskrnl/ntoskrnl.def --output-exp %s --kill-at\n",
942 target.c_str (),
943 base_tmp.c_str (),
944 temp_exp.c_str () );
945 fprintf ( fMakefile,
946 "\t${rm} %s\n",
947 base_tmp.c_str () );
948 fprintf ( fMakefile,
949 "\t${gcc} %s %s -Wl,%s -o %s %s %s\n",
950 GetLinkerMacro ( module ).c_str (),
951 gccOptions.c_str (),
952 temp_exp.c_str (),
953 target.c_str (),
954 objectsMacro.c_str (),
955 importLibraryDependencies.c_str () );
956 fprintf ( fMakefile,
957 "\t${rm} %s\n\n",
958 temp_exp.c_str () );
959 }
960
961
962 static MingwStaticLibraryModuleHandler staticlibrary_handler;
963
964 MingwStaticLibraryModuleHandler::MingwStaticLibraryModuleHandler ()
965 : MingwModuleHandler ( StaticLibrary )
966 {
967 }
968
969 void
970 MingwStaticLibraryModuleHandler::Process ( const Module& module )
971 {
972 GeneratePreconditionDependencies ( module );
973 GenerateStaticLibraryModuleTarget ( module );
974 GenerateInvocations ( module );
975 }
976
977 void
978 MingwStaticLibraryModuleHandler::GenerateStaticLibraryModuleTarget ( const Module& module )
979 {
980 GenerateMacrosAndTargetsTarget ( module );
981 }
982
983
984 static MingwKernelModeDLLModuleHandler kernelmodedll_handler;
985
986 MingwKernelModeDLLModuleHandler::MingwKernelModeDLLModuleHandler ()
987 : MingwModuleHandler ( KernelModeDLL )
988 {
989 }
990
991 void
992 MingwKernelModeDLLModuleHandler::Process ( const Module& module )
993 {
994 GeneratePreconditionDependencies ( module );
995 GenerateKernelModeDLLModuleTarget ( module );
996 GenerateInvocations ( module );
997 }
998
999 void
1000 MingwKernelModeDLLModuleHandler::GenerateKernelModeDLLModuleTarget ( const Module& module )
1001 {
1002 static string ros_junk ( "$(ROS_TEMPORARY)" );
1003 string target ( FixupTargetFilename ( module.GetPath () ) );
1004 string workingDirectory = GetWorkingDirectory ( );
1005 string archiveFilename = GetModuleArchiveFilename ( module );
1006 string importLibraryDependencies = GetImportLibraryDependencies ( module );
1007
1008 if (module.importLibrary != NULL)
1009 {
1010 fprintf ( fMakefile, "%s:\n",
1011 module.GetDependencyPath ().c_str () );
1012
1013 fprintf ( fMakefile,
1014 "\t${dlltool} --dllname %s --def %s --output-lib %s --kill-at\n\n",
1015 module.GetTargetName ().c_str (),
1016 FixupTargetFilename ( module.GetBasePath () + SSEP + module.importLibrary->definition ).c_str (),
1017 FixupTargetFilename ( module.GetDependencyPath () ).c_str () );
1018 }
1019
1020 if (module.files.size () > 0)
1021 {
1022 GenerateMacrosAndTargetsTarget ( module );
1023
1024 fprintf ( fMakefile, "%s: %s %s\n",
1025 target.c_str (),
1026 archiveFilename.c_str (),
1027 importLibraryDependencies.c_str () );
1028
1029 string linkerParameters ( "-Wl,--subsystem,native -Wl,--entry,_DriverEntry@8 -Wl,--image-base,0x10000 -Wl,--file-alignment,0x1000 -Wl,--section-alignment,0x1000 -nostartfiles -mdll" );
1030 string linkerCommand = GenerateLinkerCommand ( module,
1031 "${gcc}",
1032 linkerParameters,
1033 archiveFilename );
1034 fprintf ( fMakefile,
1035 "\t%s\n\n",
1036 linkerCommand.c_str () );
1037 }
1038 else
1039 {
1040 fprintf ( fMakefile, "%s:\n",
1041 target.c_str ());
1042 fprintf ( fMakefile, ".PHONY: %s\n\n",
1043 target.c_str ());
1044 }
1045 }
1046
1047
1048 static MingwNativeDLLModuleHandler nativedll_handler;
1049
1050 MingwNativeDLLModuleHandler::MingwNativeDLLModuleHandler ()
1051 : MingwModuleHandler ( NativeDLL )
1052 {
1053 }
1054
1055 void
1056 MingwNativeDLLModuleHandler::Process ( const Module& module )
1057 {
1058 GeneratePreconditionDependencies ( module );
1059 GenerateNativeDLLModuleTarget ( module );
1060 GenerateInvocations ( module );
1061 }
1062
1063 void
1064 MingwNativeDLLModuleHandler::GenerateNativeDLLModuleTarget ( const Module& module )
1065 {
1066 static string ros_junk ( "$(ROS_TEMPORARY)" );
1067 string target ( FixupTargetFilename ( module.GetPath () ) );
1068 string workingDirectory = GetWorkingDirectory ( );
1069 string archiveFilename = GetModuleArchiveFilename ( module );
1070 string importLibraryDependencies = GetImportLibraryDependencies ( module );
1071
1072 if (module.importLibrary != NULL)
1073 {
1074 fprintf ( fMakefile, "%s:\n",
1075 module.GetDependencyPath ().c_str () );
1076
1077 fprintf ( fMakefile,
1078 "\t${dlltool} --dllname %s --def %s --output-lib %s --kill-at\n\n",
1079 module.GetTargetName ().c_str (),
1080 FixupTargetFilename ( module.GetBasePath () + SSEP + module.importLibrary->definition ).c_str (),
1081 FixupTargetFilename ( module.GetDependencyPath () ).c_str () );
1082 }
1083
1084 if (module.files.size () > 0)
1085 {
1086 GenerateMacrosAndTargetsTarget ( module );
1087
1088 fprintf ( fMakefile, "%s: %s %s\n",
1089 target.c_str (),
1090 archiveFilename.c_str (),
1091 importLibraryDependencies.c_str () );
1092
1093 string linkerParameters ( "-Wl,--subsystem,native -Wl,--entry,_DllMainCRTStartup@12 -Wl,--image-base,0x10000 -Wl,--file-alignment,0x1000 -Wl,--section-alignment,0x1000 -nostartfiles -nostdlib -mdll" );
1094 string linkerCommand = GenerateLinkerCommand ( module,
1095 "${gcc}",
1096 linkerParameters,
1097 archiveFilename );
1098 fprintf ( fMakefile,
1099 "\t%s\n\n",
1100 linkerCommand.c_str () );
1101 }
1102 else
1103 {
1104 fprintf ( fMakefile, "%s:\n\n",
1105 target.c_str ());
1106 fprintf ( fMakefile, ".PHONY: %s\n\n",
1107 target.c_str ());
1108 }
1109 }
1110
1111
1112 static MingwWin32DLLModuleHandler win32dll_handler;
1113
1114 MingwWin32DLLModuleHandler::MingwWin32DLLModuleHandler ()
1115 : MingwModuleHandler ( Win32DLL )
1116 {
1117 }
1118
1119 void
1120 MingwWin32DLLModuleHandler::Process ( const Module& module )
1121 {
1122 GeneratePreconditionDependencies ( module );
1123 GenerateWin32DLLModuleTarget ( module );
1124 GenerateInvocations ( module );
1125 }
1126
1127 void
1128 MingwWin32DLLModuleHandler::GenerateWin32DLLModuleTarget ( const Module& module )
1129 {
1130 static string ros_junk ( "$(ROS_TEMPORARY)" );
1131 string target ( FixupTargetFilename ( module.GetPath () ) );
1132 string workingDirectory = GetWorkingDirectory ( );
1133 string archiveFilename = GetModuleArchiveFilename ( module );
1134 string importLibraryDependencies = GetImportLibraryDependencies ( module );
1135
1136 if (module.importLibrary != NULL)
1137 {
1138 fprintf ( fMakefile, "%s:\n",
1139 module.GetDependencyPath ().c_str () );
1140
1141 fprintf ( fMakefile,
1142 "\t${dlltool} --dllname %s --def %s --output-lib %s --kill-at\n\n",
1143 module.GetTargetName ().c_str (),
1144 FixupTargetFilename ( module.GetBasePath () + SSEP + module.importLibrary->definition ).c_str (),
1145 FixupTargetFilename ( module.GetDependencyPath () ).c_str () );
1146 }
1147
1148 if (module.files.size () > 0)
1149 {
1150 GenerateMacrosAndTargetsTarget ( module );
1151
1152 fprintf ( fMakefile, "%s: %s %s\n",
1153 target.c_str (),
1154 archiveFilename.c_str (),
1155 importLibraryDependencies.c_str () );
1156
1157 string linkerParameters ( "-Wl,--subsystem,console -Wl,--entry,_DllMain@12 -Wl,--image-base,0x10000 -Wl,--file-alignment,0x1000 -Wl,--section-alignment,0x1000 -mdll" );
1158 string linkerCommand = GenerateLinkerCommand ( module,
1159 "${gcc}",
1160 linkerParameters,
1161 archiveFilename );
1162 fprintf ( fMakefile,
1163 "\t%s\n\n",
1164 linkerCommand.c_str () );
1165 }
1166 else
1167 {
1168 fprintf ( fMakefile, "%s:\n\n",
1169 target.c_str ());
1170 fprintf ( fMakefile, ".PHONY: %s\n\n",
1171 target.c_str ());
1172 }
1173 }
1174
1175
1176 static MingwWin32GUIModuleHandler win32gui_handler;
1177
1178 MingwWin32GUIModuleHandler::MingwWin32GUIModuleHandler ()
1179 : MingwModuleHandler ( Win32GUI )
1180 {
1181 }
1182
1183 void
1184 MingwWin32GUIModuleHandler::Process ( const Module& module )
1185 {
1186 GeneratePreconditionDependencies ( module );
1187 GenerateWin32GUIModuleTarget ( module );
1188 GenerateInvocations ( module );
1189 }
1190
1191 void
1192 MingwWin32GUIModuleHandler::GenerateWin32GUIModuleTarget ( const Module& module )
1193 {
1194 static string ros_junk ( "$(ROS_TEMPORARY)" );
1195 string target ( FixupTargetFilename ( module.GetPath () ) );
1196 string workingDirectory = GetWorkingDirectory ( );
1197 string objectFilenames = GetObjectFilenames ( module );
1198 string importLibraryDependencies = GetImportLibraryDependencies ( module );
1199
1200 if (module.files.size () > 0)
1201 {
1202 GenerateMacrosAndTargetsTarget ( module );
1203
1204 fprintf ( fMakefile, "%s: %s %s\n",
1205 target.c_str (),
1206 objectFilenames.c_str (),
1207 importLibraryDependencies.c_str () );
1208
1209 string linkerParameters ( "-Wl,--subsystem,windows -Wl,--entry,_WinMainCRTStartup -Wl,--image-base,0x00400000 -Wl,--file-alignment,0x1000 -Wl,--section-alignment,0x1000" );
1210 string linkerCommand = GenerateLinkerCommand ( module,
1211 "${gcc}",
1212 linkerParameters,
1213 objectFilenames );
1214 fprintf ( fMakefile,
1215 "\t%s\n\n",
1216 linkerCommand.c_str () );
1217 }
1218 else
1219 {
1220 fprintf ( fMakefile, "%s:\n\n",
1221 target.c_str ());
1222 fprintf ( fMakefile, ".PHONY: %s\n\n",
1223 target.c_str ());
1224 }
1225 }