Clean intermediate files.
[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 void
536 MingwModuleHandler::GenerateLinkerCommand ( const Module& module,
537 const string& linker,
538 const string& linkerParameters,
539 const string& objectFilenames ) const
540 {
541 string targetName ( module.GetTargetName () );
542 string target ( FixupTargetFilename ( module.GetPath () ) );
543 string importLibraryDependencies = GetImportLibraryDependencies ( module );
544 if ( module.importLibrary != NULL )
545 {
546 static string ros_junk ( "$(ROS_TEMPORARY)" );
547 string base_tmp = ros_junk + module.name + ".base.tmp";
548 string junk_tmp = ros_junk + module.name + ".junk.tmp";
549 string temp_exp = ros_junk + module.name + ".temp.exp";
550
551 fprintf ( fMakefile,
552 "\t%s %s -Wl,--base-file,%s -o %s %s %s %s\n",
553 linker.c_str (),
554 linkerParameters.c_str (),
555 base_tmp.c_str (),
556 junk_tmp.c_str (),
557 objectFilenames.c_str (),
558 importLibraryDependencies.c_str (),
559 GetLinkerMacro ( module ).c_str () );
560
561 fprintf ( fMakefile,
562 "\t${rm} %s\n",
563 junk_tmp.c_str () );
564
565 fprintf ( fMakefile,
566 "\t${dlltool} --dllname %s --base-file %s --def %s --output-exp %s --kill-at\n",
567 targetName.c_str (),
568 base_tmp.c_str (),
569 FixupTargetFilename ( module.GetBasePath () + SSEP + module.importLibrary->definition ).c_str (),
570 temp_exp.c_str () );
571
572 fprintf ( fMakefile,
573 "\t${rm} %s\n",
574 base_tmp.c_str () );
575
576 fprintf ( fMakefile,
577 "\t%s %s %s -o %s %s %s %s\n\n",
578 linker.c_str (),
579 linkerParameters.c_str (),
580 temp_exp.c_str (),
581 target.c_str (),
582 objectFilenames.c_str (),
583 importLibraryDependencies.c_str (),
584 GetLinkerMacro ( module ).c_str () );
585
586 fprintf ( fMakefile,
587 "\t${rm} %s\n\n",
588 temp_exp.c_str () );
589 }
590 else
591 {
592 fprintf ( fMakefile,
593 "\t%s %s -o %s %s %s %s\n\n",
594 linker.c_str (),
595 linkerParameters.c_str (),
596 target.c_str (),
597 objectFilenames.c_str (),
598 importLibraryDependencies.c_str (),
599 GetLinkerMacro ( module ).c_str () );
600 }
601 }
602
603 void
604 MingwModuleHandler::GenerateObjectFileTargets ( const Module& module,
605 const vector<File*>& files,
606 const vector<If*>& ifs,
607 const string& cc,
608 const string& cflagsMacro,
609 const string& nasmflagsMacro,
610 const string& windresflagsMacro ) const
611 {
612 size_t i;
613
614 for ( i = 0; i < files.size (); i++ )
615 {
616 string sourceFilename = files[i]->name;
617 string objectFilename = GetObjectFilename ( sourceFilename );
618 fprintf ( fMakefile,
619 "%s: %s\n",
620 objectFilename.c_str (),
621 sourceFilename.c_str () );
622 fprintf ( fMakefile,
623 "\t%s\n",
624 GenerateCommand ( module,
625 sourceFilename,
626 cc,
627 cflagsMacro,
628 nasmflagsMacro,
629 windresflagsMacro ).c_str () );
630 }
631
632 for ( i = 0; i < ifs.size(); i++ )
633 GenerateObjectFileTargets ( module,
634 ifs[i]->files,
635 ifs[i]->ifs,
636 cc,
637 cflagsMacro,
638 nasmflagsMacro,
639 windresflagsMacro );
640 }
641
642 void
643 MingwModuleHandler::GenerateObjectFileTargets ( const Module& module,
644 const string& cc,
645 const string& cflagsMacro,
646 const string& nasmflagsMacro,
647 const string& windresflagsMacro ) const
648 {
649 GenerateObjectFileTargets ( module,
650 module.files,
651 module.ifs,
652 cc,
653 cflagsMacro,
654 nasmflagsMacro,
655 windresflagsMacro );
656 fprintf ( fMakefile, "\n" );
657 }
658
659 void
660 MingwModuleHandler::GetCleanTargets ( vector<string>& out,
661 const vector<File*>& files,
662 const vector<If*>& ifs ) const
663 {
664 size_t i;
665
666 for ( i = 0; i < files.size(); i++ )
667 out.push_back ( GetObjectFilename(files[i]->name) );
668
669 for ( i = 0; i < ifs.size(); i++ )
670 GetCleanTargets ( out, ifs[i]->files, ifs[i]->ifs );
671 }
672
673 string
674 MingwModuleHandler::GenerateArchiveTarget ( const Module& module,
675 const string& ar,
676 const string& objs_macro ) const
677 {
678 string archiveFilename = GetModuleArchiveFilename ( module );
679
680 fprintf ( fMakefile,
681 "%s: %s\n",
682 archiveFilename.c_str (),
683 objs_macro.c_str ());
684
685 fprintf ( fMakefile,
686 "\t%s -rc %s %s\n\n",
687 ar.c_str (),
688 archiveFilename.c_str (),
689 objs_macro.c_str ());
690
691 return archiveFilename;
692 }
693
694 string
695 MingwModuleHandler::GetCFlagsMacro ( const Module& module ) const
696 {
697 return ssprintf ( "$(%s_CFLAGS)",
698 module.name.c_str () );
699 }
700
701 string
702 MingwModuleHandler::GetObjectsMacro ( const Module& module ) const
703 {
704 return ssprintf ( "$(%s_OBJS)",
705 module.name.c_str () );
706 }
707
708 string
709 MingwModuleHandler::GetLinkerMacro ( const Module& module ) const
710 {
711 return ssprintf ( "$(%s_LFLAGS)",
712 module.name.c_str () );
713 }
714
715 void
716 MingwModuleHandler::GenerateMacrosAndTargets (
717 const Module& module,
718 const string& cc,
719 const string& ar,
720 const string* cflags ) const
721 {
722 string cflagsMacro = ssprintf ("%s_CFLAGS", module.name.c_str ());
723 string nasmflagsMacro = ssprintf ("%s_NASMFLAGS", module.name.c_str ());
724 string windresflagsMacro = ssprintf ("%s_RCFLAGS", module.name.c_str ());
725 string linkerFlagsMacro = ssprintf ("%s_LFLAGS", module.name.c_str ());
726 string objectsMacro = ssprintf ("%s_OBJS", module.name.c_str ());
727
728 GenerateMacros ( module,
729 cflagsMacro,
730 nasmflagsMacro,
731 windresflagsMacro,
732 linkerFlagsMacro,
733 objectsMacro );
734
735 if ( cflags != NULL )
736 {
737 fprintf ( fMakefile,
738 "%s += %s\n\n",
739 cflagsMacro.c_str (),
740 cflags->c_str () );
741 }
742
743 // generate phony target for module name
744 fprintf ( fMakefile, ".PHONY: %s\n",
745 module.name.c_str () );
746 fprintf ( fMakefile, "%s: %s\n\n",
747 module.name.c_str (),
748 module.GetPath ().c_str () );
749
750 // future references to the macros will be to get their values
751 cflagsMacro = ssprintf ("$(%s)", cflagsMacro.c_str ());
752 nasmflagsMacro = ssprintf ("$(%s)", nasmflagsMacro.c_str ());
753 objectsMacro = ssprintf ("$(%s)", objectsMacro.c_str ());
754
755 string ar_target = GenerateArchiveTarget ( module, ar, objectsMacro );
756 GenerateObjectFileTargets ( module,
757 cc,
758 cflagsMacro,
759 nasmflagsMacro,
760 windresflagsMacro );
761
762 vector<string> clean_files;
763 clean_files.push_back ( FixupTargetFilename(module.GetPath()) );
764 clean_files.push_back ( ar_target );
765 GetCleanTargets ( clean_files, module.files, module.ifs );
766
767 fprintf ( fMakefile, "clean::\n\t-@$(rm)" );
768 for ( size_t i = 0; i < clean_files.size(); i++ )
769 {
770 if ( 9==(i%10) )
771 fprintf ( fMakefile, " 2>NUL\n\t-@$(rm)" );
772 fprintf ( fMakefile, " %s", clean_files[i].c_str() );
773 }
774 fprintf ( fMakefile, " 2>NUL\n\n" );
775 }
776
777 void
778 MingwModuleHandler::GenerateMacrosAndTargetsHost ( const Module& module ) const
779 {
780 GenerateMacrosAndTargets ( module, "${host_gcc}", "${host_ar}", NULL );
781 }
782
783 void
784 MingwModuleHandler::GenerateMacrosAndTargetsTarget ( const Module& module ) const
785 {
786 GenerateMacrosAndTargetsTarget ( module,
787 NULL );
788 }
789
790 void
791 MingwModuleHandler::GenerateMacrosAndTargetsTarget ( const Module& module,
792 const string* clags ) const
793 {
794 GenerateMacrosAndTargets ( module, "${gcc}", "${ar}", clags );
795 }
796
797 string
798 MingwModuleHandler::GetInvocationDependencies ( const Module& module ) const
799 {
800 string dependencies;
801 for ( size_t i = 0; i < module.invocations.size (); i++ )
802 {
803 Invoke& invoke = *module.invocations[i];
804 if (invoke.invokeModule == &module)
805 /* Protect against circular dependencies */
806 continue;
807 if ( dependencies.length () > 0 )
808 dependencies += " ";
809 dependencies += invoke.GetTargets ();
810 }
811 return dependencies;
812 }
813
814 string
815 MingwModuleHandler::GetInvocationParameters ( const Invoke& invoke ) const
816 {
817 string parameters ( "" );
818 size_t i;
819 for (i = 0; i < invoke.output.size (); i++)
820 {
821 if (parameters.length () > 0)
822 parameters += " ";
823 InvokeFile& invokeFile = *invoke.output[i];
824 if (invokeFile.switches.length () > 0)
825 {
826 parameters += invokeFile.switches;
827 parameters += " ";
828 }
829 parameters += invokeFile.name;
830 }
831
832 for (i = 0; i < invoke.input.size (); i++)
833 {
834 if (parameters.length () > 0)
835 parameters += " ";
836 InvokeFile& invokeFile = *invoke.input[i];
837 if (invokeFile.switches.length () > 0)
838 {
839 parameters += invokeFile.switches;
840 parameters += " ";
841 }
842 parameters += invokeFile.name;
843 }
844
845 return parameters;
846 }
847
848 void
849 MingwModuleHandler::GenerateInvocations ( const Module& module ) const
850 {
851 if ( module.invocations.size () == 0 )
852 return;
853
854 for ( size_t i = 0; i < module.invocations.size (); i++ )
855 {
856 const Invoke& invoke = *module.invocations[i];
857
858 if ( invoke.invokeModule->type != BuildTool )
859 throw InvalidBuildFileException ( module.node.location,
860 "Only modules of type buildtool can be invoked." );
861
862 string invokeTarget = module.GetInvocationTarget ( i );
863 fprintf ( fMakefile,
864 "%s: %s\n\n",
865 invoke.GetTargets ().c_str (),
866 invokeTarget.c_str () );
867 fprintf ( fMakefile,
868 "%s: %s\n",
869 invokeTarget.c_str (),
870 FixupTargetFilename ( invoke.invokeModule->GetPath () ).c_str () );
871 fprintf ( fMakefile,
872 "\t%s %s\n\n",
873 FixupTargetFilename ( invoke.invokeModule->GetPath () ).c_str (),
874 GetInvocationParameters ( invoke ).c_str () );
875 fprintf ( fMakefile,
876 ".PNONY: %s\n\n",
877 invokeTarget.c_str () );
878 }
879 }
880
881 string
882 MingwModuleHandler::GetPreconditionDependenciesName ( const Module& module ) const
883 {
884 return ssprintf ( "%s_precondition",
885 module.name.c_str () );
886 }
887
888 void
889 MingwModuleHandler::GeneratePreconditionDependencies ( const Module& module ) const
890 {
891 string preconditionDependenciesName = GetPreconditionDependenciesName ( module );
892 string sourceFilenames = GetSourceFilenames ( module );
893 string dependencies = GetModuleDependencies ( module );
894 string s = GetInvocationDependencies ( module );
895 if ( s.length () > 0 )
896 {
897 if ( dependencies.length () > 0 )
898 dependencies += " ";
899 dependencies += s;
900 }
901
902 fprintf ( fMakefile,
903 ".PHONY: %s\n\n",
904 preconditionDependenciesName.c_str () );
905 fprintf ( fMakefile,
906 "%s: %s\n\n",
907 preconditionDependenciesName.c_str (),
908 dependencies.c_str () );
909 const char* p = sourceFilenames.c_str();
910 const char* end = p + strlen(p);
911 while ( p < end )
912 {
913 const char* p2 = &p[512];
914 if ( p2 > end )
915 p2 = end;
916 while ( p2 > p && !isspace(*p2) )
917 --p2;
918 if ( p == p2 )
919 {
920 p2 = strpbrk ( p, " \t" );
921 if ( !p2 )
922 p2 = end;
923 }
924 fprintf ( fMakefile,
925 "%.*s: %s\n",
926 p2-p,
927 p,
928 preconditionDependenciesName.c_str ());
929 p = p2;
930 p += strspn ( p, " \t" );
931 }
932 fprintf ( fMakefile, "\n" );
933 }
934
935 void
936 MingwModuleHandler::GenerateImportLibraryTargetIfNeeded ( const Module& module ) const
937 {
938 if ( module.importLibrary != NULL )
939 {
940 fprintf ( fMakefile, "%s:\n",
941 module.GetDependencyPath ().c_str () );
942
943 fprintf ( fMakefile,
944 "\t${dlltool} --dllname %s --def %s --output-lib %s --kill-at\n\n",
945 module.GetTargetName ().c_str (),
946 FixupTargetFilename ( module.GetBasePath () + SSEP + module.importLibrary->definition ).c_str (),
947 FixupTargetFilename ( module.GetDependencyPath () ).c_str () );
948 }
949 }
950
951
952 static MingwBuildToolModuleHandler buildtool_handler;
953
954 MingwBuildToolModuleHandler::MingwBuildToolModuleHandler()
955 : MingwModuleHandler ( BuildTool )
956 {
957 }
958
959 void
960 MingwBuildToolModuleHandler::Process ( const Module& module )
961 {
962 GeneratePreconditionDependencies ( module );
963 GenerateBuildToolModuleTarget ( module );
964 GenerateInvocations ( module );
965 }
966
967 void
968 MingwBuildToolModuleHandler::GenerateBuildToolModuleTarget ( const Module& module )
969 {
970 string target ( FixupTargetFilename ( module.GetPath () ) );
971 string archiveFilename = GetModuleArchiveFilename ( module );
972
973 GenerateMacrosAndTargetsHost ( module );
974
975 fprintf ( fMakefile, "%s: %s\n",
976 target.c_str (),
977 archiveFilename.c_str () );
978 fprintf ( fMakefile,
979 "\t${host_gcc} %s -o %s %s\n\n",
980 GetLinkerMacro ( module ).c_str (),
981 target.c_str (),
982 archiveFilename.c_str () );
983 }
984
985 static MingwKernelModuleHandler kernelmodule_handler;
986
987 MingwKernelModuleHandler::MingwKernelModuleHandler ()
988 : MingwModuleHandler ( Kernel )
989 {
990 }
991
992 void
993 MingwKernelModuleHandler::Process ( const Module& module )
994 {
995 GeneratePreconditionDependencies ( module );
996 GenerateKernelModuleTarget ( module );
997 GenerateInvocations ( module );
998 }
999
1000 void
1001 MingwKernelModuleHandler::GenerateKernelModuleTarget ( const Module& module )
1002 {
1003 static string ros_junk ( "$(ROS_TEMPORARY)" );
1004 string targetName ( module.GetTargetName () );
1005 string target ( FixupTargetFilename (module.GetPath ()) );
1006 string workingDirectory = GetWorkingDirectory ();
1007 string objectsMacro = GetObjectsMacro ( module );
1008 string importLibraryDependencies = GetImportLibraryDependencies ( module );
1009 string base_tmp = ros_junk + module.name + ".base.tmp";
1010 string junk_tmp = ros_junk + module.name + ".junk.tmp";
1011 string temp_exp = ros_junk + module.name + ".temp.exp";
1012 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",
1013 module.GetBasePath ().c_str () );
1014
1015 GenerateMacrosAndTargetsTarget ( module );
1016
1017 GenerateImportLibraryTargetIfNeeded ( module );
1018
1019 fprintf ( fMakefile, "%s: %s %s\n",
1020 target.c_str (),
1021 objectsMacro.c_str (),
1022 importLibraryDependencies.c_str () );
1023 fprintf ( fMakefile,
1024 "\t${gcc} %s %s -Wl,--base-file,%s -o %s %s %s\n",
1025 GetLinkerMacro ( module ).c_str (),
1026 gccOptions.c_str (),
1027 base_tmp.c_str (),
1028 junk_tmp.c_str (),
1029 objectsMacro.c_str (),
1030 importLibraryDependencies.c_str () );
1031 fprintf ( fMakefile,
1032 "\t${rm} %s\n",
1033 junk_tmp.c_str () );
1034 fprintf ( fMakefile,
1035 "\t${dlltool} --dllname %s --base-file %s --def ntoskrnl/ntoskrnl.def --output-exp %s --kill-at\n",
1036 targetName.c_str (),
1037 base_tmp.c_str (),
1038 temp_exp.c_str () );
1039 fprintf ( fMakefile,
1040 "\t${rm} %s\n",
1041 base_tmp.c_str () );
1042 fprintf ( fMakefile,
1043 "\t${gcc} %s %s -Wl,%s -o %s %s %s\n",
1044 GetLinkerMacro ( module ).c_str (),
1045 gccOptions.c_str (),
1046 temp_exp.c_str (),
1047 target.c_str (),
1048 objectsMacro.c_str (),
1049 importLibraryDependencies.c_str () );
1050 fprintf ( fMakefile,
1051 "\t${rm} %s\n\n",
1052 temp_exp.c_str () );
1053 }
1054
1055
1056 static MingwStaticLibraryModuleHandler staticlibrary_handler;
1057
1058 MingwStaticLibraryModuleHandler::MingwStaticLibraryModuleHandler ()
1059 : MingwModuleHandler ( StaticLibrary )
1060 {
1061 }
1062
1063 void
1064 MingwStaticLibraryModuleHandler::Process ( const Module& module )
1065 {
1066 GeneratePreconditionDependencies ( module );
1067 GenerateStaticLibraryModuleTarget ( module );
1068 GenerateInvocations ( module );
1069 }
1070
1071 void
1072 MingwStaticLibraryModuleHandler::GenerateStaticLibraryModuleTarget ( const Module& module )
1073 {
1074 GenerateMacrosAndTargetsTarget ( module );
1075 }
1076
1077
1078 static MingwKernelModeDLLModuleHandler kernelmodedll_handler;
1079
1080 MingwKernelModeDLLModuleHandler::MingwKernelModeDLLModuleHandler ()
1081 : MingwModuleHandler ( KernelModeDLL )
1082 {
1083 }
1084
1085 void
1086 MingwKernelModeDLLModuleHandler::Process ( const Module& module )
1087 {
1088 GeneratePreconditionDependencies ( module );
1089 GenerateKernelModeDLLModuleTarget ( module );
1090 GenerateInvocations ( module );
1091 }
1092
1093 void
1094 MingwKernelModeDLLModuleHandler::GenerateKernelModeDLLModuleTarget ( const Module& module )
1095 {
1096 static string ros_junk ( "$(ROS_TEMPORARY)" );
1097 string target ( FixupTargetFilename ( module.GetPath () ) );
1098 string workingDirectory = GetWorkingDirectory ( );
1099 string archiveFilename = GetModuleArchiveFilename ( module );
1100 string importLibraryDependencies = GetImportLibraryDependencies ( module );
1101
1102 GenerateImportLibraryTargetIfNeeded ( module );
1103
1104 if ( module.files.size () > 0 )
1105 {
1106 GenerateMacrosAndTargetsTarget ( module );
1107
1108 fprintf ( fMakefile, "%s: %s %s\n",
1109 target.c_str (),
1110 archiveFilename.c_str (),
1111 importLibraryDependencies.c_str () );
1112
1113 string linkerParameters ( "-Wl,--subsystem,native -Wl,--entry,_DriverEntry@8 -Wl,--image-base,0x10000 -Wl,--file-alignment,0x1000 -Wl,--section-alignment,0x1000 -nostartfiles -mdll" );
1114 GenerateLinkerCommand ( module,
1115 "${gcc}",
1116 linkerParameters,
1117 archiveFilename );
1118 }
1119 else
1120 {
1121 fprintf ( fMakefile, "%s:\n",
1122 target.c_str ());
1123 fprintf ( fMakefile, ".PHONY: %s\n\n",
1124 target.c_str ());
1125 }
1126 }
1127
1128
1129 static MingwKernelModeDriverModuleHandler kernelmodedriver_handler;
1130
1131 MingwKernelModeDriverModuleHandler::MingwKernelModeDriverModuleHandler ()
1132 : MingwModuleHandler ( KernelModeDriver )
1133 {
1134 }
1135
1136 void
1137 MingwKernelModeDriverModuleHandler::Process ( const Module& module )
1138 {
1139 GeneratePreconditionDependencies ( module );
1140 GenerateKernelModeDriverModuleTarget ( module );
1141 GenerateInvocations ( module );
1142 }
1143
1144 void
1145 MingwKernelModeDriverModuleHandler::GenerateKernelModeDriverModuleTarget ( const Module& module )
1146 {
1147 static string ros_junk ( "$(ROS_TEMPORARY)" );
1148 string target ( FixupTargetFilename ( module.GetPath () ) );
1149 string workingDirectory = GetWorkingDirectory ( );
1150 string archiveFilename = GetModuleArchiveFilename ( module );
1151 string importLibraryDependencies = GetImportLibraryDependencies ( module );
1152
1153 GenerateImportLibraryTargetIfNeeded ( module );
1154
1155 if ( module.files.size () > 0 )
1156 {
1157 string* cflags = new string ( "-D__NTDRIVER__" );
1158 GenerateMacrosAndTargetsTarget ( module,
1159 cflags );
1160 delete cflags;
1161
1162 fprintf ( fMakefile, "%s: %s %s\n",
1163 target.c_str (),
1164 archiveFilename.c_str (),
1165 importLibraryDependencies.c_str () );
1166
1167 string linkerParameters ( "-Wl,--subsystem,native -Wl,--entry,_DriverEntry@8 -Wl,--image-base,0x10000 -Wl,--file-alignment,0x1000 -Wl,--section-alignment,0x1000 -nostartfiles -mdll" );
1168 GenerateLinkerCommand ( module,
1169 "${gcc}",
1170 linkerParameters,
1171 archiveFilename );
1172 }
1173 else
1174 {
1175 fprintf ( fMakefile, "%s:\n",
1176 target.c_str ());
1177 fprintf ( fMakefile, ".PHONY: %s\n\n",
1178 target.c_str ());
1179 }
1180 }
1181
1182
1183 static MingwNativeDLLModuleHandler nativedll_handler;
1184
1185 MingwNativeDLLModuleHandler::MingwNativeDLLModuleHandler ()
1186 : MingwModuleHandler ( NativeDLL )
1187 {
1188 }
1189
1190 void
1191 MingwNativeDLLModuleHandler::Process ( const Module& module )
1192 {
1193 GeneratePreconditionDependencies ( module );
1194 GenerateNativeDLLModuleTarget ( module );
1195 GenerateInvocations ( module );
1196 }
1197
1198 void
1199 MingwNativeDLLModuleHandler::GenerateNativeDLLModuleTarget ( const Module& module )
1200 {
1201 static string ros_junk ( "$(ROS_TEMPORARY)" );
1202 string target ( FixupTargetFilename ( module.GetPath () ) );
1203 string workingDirectory = GetWorkingDirectory ( );
1204 string objectFilenames = GetObjectFilenames ( module );
1205 string archiveFilename = GetModuleArchiveFilename ( module );
1206 string importLibraryDependencies = GetImportLibraryDependencies ( module );
1207
1208 GenerateImportLibraryTargetIfNeeded ( module );
1209
1210 if ( module.files.size () > 0 )
1211 {
1212 GenerateMacrosAndTargetsTarget ( module );
1213
1214 fprintf ( fMakefile, "%s: %s %s\n",
1215 target.c_str (),
1216 archiveFilename.c_str (),
1217 importLibraryDependencies.c_str () );
1218
1219 string linkerParameters ( "-Wl,--subsystem,native -Wl,--entry,_DllMainCRTStartup@12 -Wl,--image-base,0x10000 -Wl,--file-alignment,0x1000 -Wl,--section-alignment,0x1000 -nostartfiles -nostdlib -mdll" );
1220 GenerateLinkerCommand ( module,
1221 "${gcc}",
1222 linkerParameters,
1223 objectFilenames );
1224 }
1225 else
1226 {
1227 fprintf ( fMakefile, "%s:\n\n",
1228 target.c_str ());
1229 fprintf ( fMakefile, ".PHONY: %s\n\n",
1230 target.c_str ());
1231 }
1232 }
1233
1234
1235 static MingwWin32DLLModuleHandler win32dll_handler;
1236
1237 MingwWin32DLLModuleHandler::MingwWin32DLLModuleHandler ()
1238 : MingwModuleHandler ( Win32DLL )
1239 {
1240 }
1241
1242 void
1243 MingwWin32DLLModuleHandler::Process ( const Module& module )
1244 {
1245 GeneratePreconditionDependencies ( module );
1246 GenerateWin32DLLModuleTarget ( module );
1247 GenerateInvocations ( module );
1248 }
1249
1250 void
1251 MingwWin32DLLModuleHandler::GenerateWin32DLLModuleTarget ( const Module& module )
1252 {
1253 static string ros_junk ( "$(ROS_TEMPORARY)" );
1254 string target ( FixupTargetFilename ( module.GetPath () ) );
1255 string workingDirectory = GetWorkingDirectory ( );
1256 string archiveFilename = GetModuleArchiveFilename ( module );
1257 string importLibraryDependencies = GetImportLibraryDependencies ( module );
1258
1259 GenerateImportLibraryTargetIfNeeded ( module );
1260
1261 if ( module.files.size () > 0 )
1262 {
1263 GenerateMacrosAndTargetsTarget ( module );
1264
1265 fprintf ( fMakefile, "%s: %s %s\n",
1266 target.c_str (),
1267 archiveFilename.c_str (),
1268 importLibraryDependencies.c_str () );
1269
1270 string linkerParameters ( "-Wl,--subsystem,console -Wl,--entry,_DllMain@12 -Wl,--image-base,0x10000 -Wl,--file-alignment,0x1000 -Wl,--section-alignment,0x1000 -mdll" );
1271 GenerateLinkerCommand ( module,
1272 "${gcc}",
1273 linkerParameters,
1274 archiveFilename );
1275 }
1276 else
1277 {
1278 fprintf ( fMakefile, "%s:\n\n",
1279 target.c_str ());
1280 fprintf ( fMakefile, ".PHONY: %s\n\n",
1281 target.c_str ());
1282 }
1283 }
1284
1285
1286 static MingwWin32GUIModuleHandler win32gui_handler;
1287
1288 MingwWin32GUIModuleHandler::MingwWin32GUIModuleHandler ()
1289 : MingwModuleHandler ( Win32GUI )
1290 {
1291 }
1292
1293 void
1294 MingwWin32GUIModuleHandler::Process ( const Module& module )
1295 {
1296 GeneratePreconditionDependencies ( module );
1297 GenerateWin32GUIModuleTarget ( module );
1298 GenerateInvocations ( module );
1299 }
1300
1301 void
1302 MingwWin32GUIModuleHandler::GenerateWin32GUIModuleTarget ( const Module& module )
1303 {
1304 static string ros_junk ( "$(ROS_TEMPORARY)" );
1305 string target ( FixupTargetFilename ( module.GetPath () ) );
1306 string workingDirectory = GetWorkingDirectory ( );
1307 string objectFilenames = GetObjectFilenames ( module );
1308 string importLibraryDependencies = GetImportLibraryDependencies ( module );
1309
1310 GenerateImportLibraryTargetIfNeeded ( module );
1311
1312 if ( module.files.size () > 0 )
1313 {
1314 GenerateMacrosAndTargetsTarget ( module );
1315
1316 fprintf ( fMakefile, "%s: %s %s\n",
1317 target.c_str (),
1318 objectFilenames.c_str (),
1319 importLibraryDependencies.c_str () );
1320
1321 string linkerParameters ( "-Wl,--subsystem,windows -Wl,--entry,_WinMainCRTStartup -Wl,--image-base,0x00400000 -Wl,--file-alignment,0x1000 -Wl,--section-alignment,0x1000" );
1322 GenerateLinkerCommand ( module,
1323 "${gcc}",
1324 linkerParameters,
1325 objectFilenames );
1326 }
1327 else
1328 {
1329 fprintf ( fMakefile, "%s:\n\n",
1330 target.c_str ());
1331 fprintf ( fMakefile, ".PHONY: %s\n\n",
1332 target.c_str ());
1333 }
1334 }