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