5 #include "../../rbuild.h"
7 #include "modulehandler.h"
13 map
<ModuleType
,MingwModuleHandler
*>*
14 MingwModuleHandler::handler_map
= NULL
;
16 MingwModuleHandler::ref
= 0;
19 MingwModuleHandler::fMakefile
= NULL
;
21 MingwModuleHandler::MingwModuleHandler ( ModuleType moduletype
)
24 handler_map
= new map
<ModuleType
,MingwModuleHandler
*>;
25 (*handler_map
)[moduletype
] = this;
28 MingwModuleHandler::~MingwModuleHandler()
38 MingwModuleHandler::SetMakefile ( FILE* f
)
43 /*static*/ MingwModuleHandler
*
44 MingwModuleHandler::LookupHandler ( const string
& location
,
45 ModuleType moduletype
)
48 throw Exception ( "internal tool error: no registered module handlers" );
49 MingwModuleHandler
* h
= (*handler_map
)[moduletype
];
52 throw UnknownModuleTypeException ( location
, moduletype
);
59 MingwModuleHandler::GetWorkingDirectory () const
65 MingwModuleHandler::GetExtension ( const string
& filename
) const
67 size_t index
= filename
.find_last_of ( '.' );
68 if (index
!= string::npos
)
69 return filename
.substr ( index
);
74 MingwModuleHandler::ReplaceExtension ( const string
& filename
,
75 const string
& newExtension
) const
77 size_t index
= filename
.find_last_of ( '.' );
78 if (index
!= string::npos
)
79 return filename
.substr ( 0, index
) + newExtension
;
84 MingwModuleHandler::GetModuleArchiveFilename ( const Module
& module
) const
86 return ReplaceExtension ( FixupTargetFilename ( module
.GetPath () ).c_str (),
91 MingwModuleHandler::GetImportLibraryDependencies ( const Module
& module
) const
93 if ( module
.libraries
.size () == 0 )
96 string
dependencies ( "" );
97 for ( size_t i
= 0; i
< module
.libraries
.size (); i
++ )
99 if ( dependencies
.size () > 0 )
101 const Module
* importedModule
= module
.project
.LocateModule ( module
.libraries
[i
]->name
);
102 assert ( importedModule
!= NULL
);
103 dependencies
+= FixupTargetFilename ( importedModule
->GetDependencyPath () ).c_str ();
109 MingwModuleHandler::GetModuleDependencies ( const Module
& module
) const
111 if ( module
.dependencies
.size () == 0 )
114 string
dependencies ( "" );
115 for ( size_t i
= 0; i
< module
.dependencies
.size (); i
++ )
117 if ( dependencies
.size () > 0 )
119 const Dependency
* dependency
= module
.dependencies
[i
];
120 const Module
* dependencyModule
= dependency
->dependencyModule
;
121 dependencies
+= dependencyModule
->GetTargets ();
127 MingwModuleHandler::GetAllDependencies ( const Module
& module
) const
129 string dependencies
= GetImportLibraryDependencies ( module
);
130 string s
= GetModuleDependencies ( module
);
140 MingwModuleHandler::GetSourceFilenames ( const Module
& module
) const
142 if ( module
.files
.size () == 0 )
145 string
sourceFilenames ( "" );
146 for ( size_t i
= 0; i
< module
.files
.size (); i
++ )
148 if ( sourceFilenames
.size () > 0 )
149 sourceFilenames
+= " ";
150 sourceFilenames
+= module
.files
[i
]->name
;
152 return sourceFilenames
;
156 MingwModuleHandler::GetObjectFilename ( const string
& sourceFilename
) const
158 return FixupTargetFilename ( ReplaceExtension ( sourceFilename
,
163 MingwModuleHandler::GetObjectFilenames ( const Module
& module
) const
165 if ( module
.files
.size () == 0 )
168 string
objectFilenames ( "" );
169 for ( size_t i
= 0; i
< module
.files
.size (); i
++ )
171 if ( objectFilenames
.size () > 0 )
172 objectFilenames
+= " ";
173 objectFilenames
+= GetObjectFilename ( module
.files
[i
]->name
);
175 return objectFilenames
;
179 MingwModuleHandler::GenerateGccDefineParametersFromVector ( const vector
<Define
*>& defines
) const
182 for (size_t i
= 0; i
< defines
.size (); i
++)
184 Define
& define
= *defines
[i
];
185 if (parameters
.length () > 0)
188 parameters
+= define
.name
;
189 if (define
.value
.length () > 0)
192 parameters
+= define
.value
;
199 MingwModuleHandler::GenerateGccDefineParameters ( const Module
& module
) const
201 string parameters
= GenerateGccDefineParametersFromVector ( module
.project
.defines
);
202 string s
= GenerateGccDefineParametersFromVector ( module
.defines
);
212 MingwModuleHandler::ConcatenatePaths ( const string
& path1
,
213 const string
& path2
) const
215 if ( ( path1
.length () == 0 ) || ( path1
== "." ) || ( path1
== "./" ) )
217 if ( path1
[path1
.length ()] == CSEP
)
218 return path1
+ path2
;
220 return path1
+ CSEP
+ path2
;
224 MingwModuleHandler::GenerateGccIncludeParametersFromVector ( const vector
<Include
*>& includes
) const
227 for ( size_t i
= 0; i
< includes
.size (); i
++ )
229 Include
& include
= *includes
[i
];
230 if (parameters
.length () > 0)
232 parameters
+= "-I" + include
.directory
;
238 MingwModuleHandler::GenerateGccModuleIncludeVariable ( const Module
& module
) const
241 string
name ( module
.name
+ "_CFLAGS" );
245 GenerateGccDefineParameters(module
).c_str(),
246 GenerateGccIncludeParameters(module
).c_str() );
251 MingwModuleHandler::GenerateGccIncludeParameters ( const Module
& module
) const
253 string parameters
= GenerateGccIncludeParametersFromVector ( module
.includes
);
254 string s
= GenerateGccIncludeParametersFromVector ( module
.project
.includes
);
255 if ( s
.length () > 0 )
264 MingwModuleHandler::GenerateMacros (
265 const Module
& module
,
267 const vector
<File
*>& files
,
268 const vector
<Include
*>* includes
,
269 const vector
<Define
*>& defines
,
270 const string
& cflags_macro
,
271 const string
& nasmflags_macro
,
272 const string
& objs_macro
) const
276 if ( (includes
&& includes
->size()) || defines
.size() )
281 cflags_macro
.c_str(),
284 for ( i
= 0; i
< includes
->size(); i
++ )
288 (*includes
)[i
]->directory
.c_str() );
289 for ( i
= 0; i
< module
.defines
.size(); i
++ )
291 Define
& d
= *module
.defines
[i
];
296 if ( d
.value
.size() )
302 fprintf ( fMakefile
, "\n" );
312 for ( i
= 0; i
< files
.size(); i
++ )
317 ( i
%10 == 9 ? "\\\n\t" : " " ),
318 GetObjectFilename(files
[i
]->name
).c_str() );
320 fprintf ( fMakefile
, "\n" );
325 MingwModuleHandler::GenerateMacros (
326 const Module
& module
,
327 const string
& cflags_macro
,
328 const string
& nasmflags_macro
,
329 const string
& objs_macro
) const
340 fprintf ( fMakefile
, "\n" );
342 for ( size_t i
= 0; i
< module
.ifs
.size(); i
++ )
344 If
& rIf
= *module
.ifs
[i
];
345 if ( rIf
.defines
.size() || rIf
.files
.size() )
349 "ifeq ($(%s),\"%s\")\n",
350 rIf
.property
.c_str(),
369 MingwModuleHandler::GenerateGccCommand ( const Module
& module
,
370 const string
& sourceFilename
,
372 const string
& cflagsMacro
) const
374 string objectFilename
= GetObjectFilename ( sourceFilename
);
375 return ssprintf ( "%s -c %s -o %s %s\n",
377 sourceFilename
.c_str (),
378 objectFilename
.c_str (),
379 cflagsMacro
.c_str () );
383 MingwModuleHandler::GenerateGccAssemblerCommand ( const Module
& module
,
384 const string
& sourceFilename
,
386 const string
& cflagsMacro
) const
388 string objectFilename
= GetObjectFilename ( sourceFilename
);
389 return ssprintf ( "%s -x assembler-with-cpp -c %s -o %s -D__ASM__ %s\n",
391 sourceFilename
.c_str (),
392 objectFilename
.c_str (),
393 cflagsMacro
.c_str () );
397 MingwModuleHandler::GenerateNasmCommand ( const Module
& module
,
398 const string
& sourceFilename
,
399 const string
& nasmflagsMacro
) const
401 string objectFilename
= GetObjectFilename ( sourceFilename
);
402 return ssprintf ( "%s -f win32 %s -o %s %s\n",
404 sourceFilename
.c_str (),
405 objectFilename
.c_str (),
406 nasmflagsMacro
.c_str () );
410 MingwModuleHandler::GenerateCommand ( const Module
& module
,
411 const string
& sourceFilename
,
413 const string
& cflagsMacro
,
414 const string
& nasmflagsMacro
) const
416 string extension
= GetExtension ( sourceFilename
);
417 if ( extension
== ".c" || extension
== ".C" )
418 return GenerateGccCommand ( module
,
422 else if ( extension
== ".s" || extension
== ".S" )
423 return GenerateGccAssemblerCommand ( module
,
427 else if ( extension
== ".asm" || extension
== ".ASM" )
428 return GenerateNasmCommand ( module
,
432 throw InvalidOperationException ( __FILE__
,
434 "Unsupported filename extension '%s' in file '%s'",
436 sourceFilename
.c_str () );
440 MingwModuleHandler::GenerateObjectFileTargets ( const Module
& module
,
441 const vector
<File
*>& files
,
443 const string
& cflagsMacro
,
444 const string
& nasmflagsMacro
) const
446 if ( files
.size () == 0 )
449 for ( size_t i
= 0; i
< files
.size (); i
++ )
451 string sourceFilename
= files
[i
]->name
;
452 string objectFilename
= GetObjectFilename ( sourceFilename
);
455 objectFilename
.c_str (),
456 sourceFilename
.c_str () );
459 GenerateCommand ( module
,
463 nasmflagsMacro
).c_str () );
466 fprintf ( fMakefile
, "\n" );
470 MingwModuleHandler::GenerateObjectFileTargets ( const Module
& module
,
472 const string
& cflagsMacro
,
473 const string
& nasmflagsMacro
) const
475 GenerateObjectFileTargets ( module
, module
.files
, cc
, cflagsMacro
, nasmflagsMacro
);
476 for ( size_t i
= 0; i
< module
.ifs
.size(); i
++ )
477 GenerateObjectFileTargets ( module
, module
.ifs
[i
]->files
, cc
, cflagsMacro
, nasmflagsMacro
);
481 MingwModuleHandler::GenerateArchiveTarget ( const Module
& module
,
483 const string
& objs_macro
) const
485 string archiveFilename
= GetModuleArchiveFilename ( module
);
486 string sourceFilenames
= GetSourceFilenames ( module
);
490 archiveFilename
.c_str (),
491 objs_macro
.c_str ());
494 "\t%s -rc %s %s\n\n",
496 archiveFilename
.c_str (),
497 objs_macro
.c_str ());
501 MingwModuleHandler::GenerateMacrosAndTargets (
502 const Module
& module
,
504 const string
& ar
) const
506 string cflagsMacro
= ssprintf("%s_CFLAGS",module
.name
.c_str());
507 string nasmflagsMacro
= ssprintf("%s_NASMFLAGS",module
.name
.c_str());
508 string objectsMacro
= ssprintf("%s_OBJS",module
.name
.c_str());
510 GenerateMacros ( module
, cflagsMacro
, nasmflagsMacro
, objectsMacro
);
512 // future references to the macros will be to get their values
513 cflagsMacro
= ssprintf("$(%s)",cflagsMacro
.c_str());
514 nasmflagsMacro
= ssprintf("$(%s)",nasmflagsMacro
.c_str());
515 objectsMacro
= ssprintf("$(%s)",objectsMacro
.c_str());
517 GenerateArchiveTarget ( module
, ar
, objectsMacro
);
518 GenerateObjectFileTargets ( module
, cc
, cflagsMacro
, nasmflagsMacro
);
522 MingwModuleHandler::GenerateMacrosAndTargetsHost ( const Module
& module
) const
524 GenerateMacrosAndTargets ( module
, "${host_gcc}", "${host_ar}" );
528 MingwModuleHandler::GenerateMacrosAndTargetsTarget ( const Module
& module
) const
530 GenerateMacrosAndTargets ( module
, "${gcc}", "${ar}" );
534 MingwModuleHandler::GetInvocationDependencies ( const Module
& module
) const
537 for ( size_t i
= 0; i
< module
.invocations
.size (); i
++ )
539 Invoke
& invoke
= *module
.invocations
[i
];
540 if (invoke
.invokeModule
== &module
)
541 /* Protect against circular dependencies */
543 if ( dependencies
.length () > 0 )
545 dependencies
+= invoke
.GetTargets ();
551 MingwModuleHandler::GetInvocationParameters ( const Invoke
& invoke
) const
553 string
parameters ( "" );
555 for (i
= 0; i
< invoke
.output
.size (); i
++)
557 if (parameters
.length () > 0)
559 InvokeFile
& invokeFile
= *invoke
.output
[i
];
560 if (invokeFile
.switches
.length () > 0)
562 parameters
+= invokeFile
.switches
;
565 parameters
+= invokeFile
.name
;
568 for (i
= 0; i
< invoke
.input
.size (); i
++)
570 if (parameters
.length () > 0)
572 InvokeFile
& invokeFile
= *invoke
.input
[i
];
573 if (invokeFile
.switches
.length () > 0)
575 parameters
+= invokeFile
.switches
;
578 parameters
+= invokeFile
.name
;
585 MingwModuleHandler::GenerateInvocations ( const Module
& module
) const
587 if ( module
.invocations
.size () == 0 )
590 for ( size_t i
= 0; i
< module
.invocations
.size (); i
++ )
592 const Invoke
& invoke
= *module
.invocations
[i
];
594 if ( invoke
.invokeModule
->type
!= BuildTool
)
595 throw InvalidBuildFileException ( module
.node
.location
,
596 "Only modules of type buildtool can be invoked." );
598 string invokeTarget
= module
.GetInvocationTarget ( i
);
601 invoke
.GetTargets ().c_str (),
602 invokeTarget
.c_str () );
605 invokeTarget
.c_str (),
606 FixupTargetFilename ( invoke
.invokeModule
->GetPath () ).c_str () );
609 FixupTargetFilename ( invoke
.invokeModule
->GetPath () ).c_str (),
610 GetInvocationParameters ( invoke
).c_str () );
613 invokeTarget
.c_str () );
618 MingwModuleHandler::GetPreconditionDependenciesName ( const Module
& module
) const
620 return ssprintf ( "%s_precondition",
621 module
.name
.c_str () );
625 MingwModuleHandler::GeneratePreconditionDependencies ( const Module
& module
) const
627 string preconditionDependenciesName
= GetPreconditionDependenciesName ( module
);
628 string sourceFilenames
= GetSourceFilenames ( module
);
629 string dependencies
= GetModuleDependencies ( module
);
630 string s
= GetInvocationDependencies ( module
);
631 if ( s
.length () > 0 )
633 if ( dependencies
.length () > 0 )
640 preconditionDependenciesName
.c_str () );
643 preconditionDependenciesName
.c_str (),
644 dependencies
.c_str () );
645 const char* p
= sourceFilenames
.c_str();
646 const char* end
= p
+ strlen(p
);
649 const char* p2
= &p
[512];
652 while ( p2
> p
&& !isspace(*p2
) )
656 p2
= strpbrk ( p
, " \t" );
664 preconditionDependenciesName
.c_str ());
666 p
+= strspn ( p
, " \t" );
668 fprintf ( fMakefile
, "\n" );
672 static MingwBuildToolModuleHandler buildtool_handler
;
674 MingwBuildToolModuleHandler::MingwBuildToolModuleHandler()
675 : MingwModuleHandler ( BuildTool
)
680 MingwBuildToolModuleHandler::Process ( const Module
& module
)
682 GeneratePreconditionDependencies ( module
);
683 GenerateBuildToolModuleTarget ( module
);
684 GenerateInvocations ( module
);
688 MingwBuildToolModuleHandler::GenerateBuildToolModuleTarget ( const Module
& module
)
690 string
target ( FixupTargetFilename ( module
.GetPath () ) );
691 string archiveFilename
= GetModuleArchiveFilename ( module
);
692 fprintf ( fMakefile
, "%s: %s\n",
694 archiveFilename
.c_str () );
696 "\t${host_gcc} -o %s %s\n\n",
698 archiveFilename
.c_str () );
699 GenerateMacrosAndTargetsHost ( module
);
702 static MingwKernelModuleHandler kernelmodule_handler
;
704 MingwKernelModuleHandler::MingwKernelModuleHandler ()
705 : MingwModuleHandler ( Kernel
)
710 MingwKernelModuleHandler::Process ( const Module
& module
)
712 GeneratePreconditionDependencies ( module
);
713 GenerateKernelModuleTarget ( module
);
714 GenerateInvocations ( module
);
718 MingwKernelModuleHandler::GenerateKernelModuleTarget ( const Module
& module
)
720 static string
ros_junk ( "$(ROS_TEMPORARY)" );
721 //static string ros_output ( "$(ROS_INTERMEDIATE)" );
722 string
target ( FixupTargetFilename(module
.GetPath()) );
723 string workingDirectory
= GetWorkingDirectory ( );
724 string archiveFilename
= GetModuleArchiveFilename ( module
);
725 string importLibraryDependencies
= GetImportLibraryDependencies ( module
);
726 string base_tmp
= ros_junk
+ module
.name
+ ".base.tmp";
727 string junk_tmp
= ros_junk
+ module
.name
+ ".junk.tmp";
728 string temp_exp
= ros_junk
+ module
.name
+ ".temp.exp";
729 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",
730 module
.GetBasePath ().c_str () );
731 fprintf ( fMakefile
, "%s: %s %s\n",
733 archiveFilename
.c_str (),
734 importLibraryDependencies
.c_str () );
736 "\t${gcc} %s -Wl,--base-file,%s -o %s %s %s\n",
740 archiveFilename
.c_str (),
741 importLibraryDependencies
.c_str () );
746 "\t${dlltool} --dllname %s --base-file %s --output-exp %s --kill-at\n",
754 "\t${gcc} %s -Wl,%s -o %s %s %s\n",
758 archiveFilename
.c_str (),
759 importLibraryDependencies
.c_str () );
764 GenerateMacrosAndTargetsTarget ( module
);
768 static MingwStaticLibraryModuleHandler staticlibrary_handler
;
770 MingwStaticLibraryModuleHandler::MingwStaticLibraryModuleHandler ()
771 : MingwModuleHandler ( StaticLibrary
)
776 MingwStaticLibraryModuleHandler::Process ( const Module
& module
)
778 GeneratePreconditionDependencies ( module
);
779 GenerateStaticLibraryModuleTarget ( module
);
780 GenerateInvocations ( module
);
784 MingwStaticLibraryModuleHandler::GenerateStaticLibraryModuleTarget ( const Module
& module
)
786 GenerateMacrosAndTargetsTarget ( module
);
790 static MingwKernelModeDLLModuleHandler kernelmodedll_handler
;
792 MingwKernelModeDLLModuleHandler::MingwKernelModeDLLModuleHandler ()
793 : MingwModuleHandler ( KernelModeDLL
)
798 MingwKernelModeDLLModuleHandler::Process ( const Module
& module
)
800 GeneratePreconditionDependencies ( module
);
801 GenerateKernelModeDLLModuleTarget ( module
);
802 GenerateInvocations ( module
);
806 MingwKernelModeDLLModuleHandler::GenerateKernelModeDLLModuleTarget ( const Module
& module
)
808 static string
ros_junk ( "$(ROS_TEMPORARY)" );
809 string
target ( FixupTargetFilename ( module
.GetPath () ) );
810 string workingDirectory
= GetWorkingDirectory ( );
811 string archiveFilename
= GetModuleArchiveFilename ( module
);
812 string importLibraryDependencies
= GetImportLibraryDependencies ( module
);
814 if (module
.importLibrary
!= NULL
)
816 fprintf ( fMakefile
, "%s:\n",
817 module
.GetDependencyPath ().c_str () );
820 "\t${dlltool} --dllname %s --def %s --output-lib %s --kill-at\n\n",
821 module
.GetTargetName ().c_str (),
822 FixupTargetFilename ( module
.GetBasePath () + SSEP
+ module
.importLibrary
->definition
).c_str (),
823 FixupTargetFilename ( module
.GetDependencyPath () ).c_str () );
826 if (module
.files
.size () > 0)
828 fprintf ( fMakefile
, "%s: %s %s\n",
830 archiveFilename
.c_str (),
831 importLibraryDependencies
.c_str () );
834 "\t${gcc} -Wl,--subsystem,native -Wl,--entry,_DriverEntry@8 -Wl,--image-base,0x10000 -Wl,--file-alignment,0x1000 -Wl,--section-alignment,0x1000 -nostartfiles -mdll -o %s %s %s\n\n",
836 archiveFilename
.c_str (),
837 importLibraryDependencies
.c_str () );
839 GenerateMacrosAndTargetsTarget ( module
);
843 fprintf ( fMakefile
, "%s:\n",
845 fprintf ( fMakefile
, ".PHONY: %s\n\n",
851 static MingwNativeDLLModuleHandler nativedll_handler
;
853 MingwNativeDLLModuleHandler::MingwNativeDLLModuleHandler ()
854 : MingwModuleHandler ( NativeDLL
)
859 MingwNativeDLLModuleHandler::Process ( const Module
& module
)
861 GeneratePreconditionDependencies ( module
);
862 GenerateNativeDLLModuleTarget ( module
);
863 GenerateInvocations ( module
);
867 MingwNativeDLLModuleHandler::GenerateNativeDLLModuleTarget ( const Module
& module
)
869 static string
ros_junk ( "$(ROS_TEMPORARY)" );
870 string
target ( FixupTargetFilename ( module
.GetPath () ) );
871 string workingDirectory
= GetWorkingDirectory ( );
872 string archiveFilename
= GetModuleArchiveFilename ( module
);
873 string importLibraryDependencies
= GetImportLibraryDependencies ( module
);
875 if (module
.importLibrary
!= NULL
)
877 fprintf ( fMakefile
, "%s:\n",
878 module
.GetDependencyPath ().c_str () );
881 "\t${dlltool} --dllname %s --def %s --output-lib %s --kill-at\n\n",
882 module
.GetTargetName ().c_str (),
883 FixupTargetFilename ( module
.GetBasePath () + SSEP
+ module
.importLibrary
->definition
).c_str (),
884 FixupTargetFilename ( module
.GetDependencyPath () ).c_str () );
887 if (module
.files
.size () > 0)
889 fprintf ( fMakefile
, "%s: %s %s\n",
891 archiveFilename
.c_str (),
892 importLibraryDependencies
.c_str () );
895 "\t${gcc} -Wl,--subsystem,native -Wl,--entry,_DllMainCRTStartup@12 -Wl,--image-base,0x10000 -Wl,--file-alignment,0x1000 -Wl,--section-alignment,0x1000 -nostartfiles -nostdlib -mdll -o %s %s %s\n\n",
897 archiveFilename
.c_str (),
898 importLibraryDependencies
.c_str () );
900 GenerateMacrosAndTargetsTarget ( module
);
904 fprintf ( fMakefile
, "%s:\n\n",
906 fprintf ( fMakefile
, ".PHONY: %s\n\n",