10 FixSeparator ( const string
& s
)
13 char* p
= strchr ( &s2
[0], CBAD_SEP
);
17 p
= strchr ( p
, CBAD_SEP
);
23 GetExtension ( const string
& filename
)
25 size_t index
= filename
.find_last_of ( '/' );
26 if (index
== string::npos
) index
= 0;
27 string tmp
= filename
.substr( index
, filename
.size() - index
);
28 size_t ext_index
= tmp
.find_last_of( '.' );
29 if (ext_index
!= string::npos
)
30 return filename
.substr ( index
+ ext_index
, filename
.size() );
35 GetDirectory ( const string
& filename
)
37 size_t index
= filename
.find_last_of ( CSEP
);
38 if ( index
== string::npos
)
41 return filename
.substr ( 0, index
);
45 NormalizeFilename ( const string
& filename
)
48 string normalizedPath
= path
.Fixup ( filename
, true );
49 string relativeNormalizedPath
= path
.RelativeFromWorkingDirectory ( normalizedPath
);
50 return FixSeparator ( relativeNormalizedPath
);
53 Module::Module ( const Project
& project
,
54 const XMLElement
& moduleNode
,
55 const string
& modulePath
)
61 if ( node
.name
!= "module" )
62 throw Exception ( "internal tool error: Module created with non-<module> node" );
64 path
= FixSeparator ( modulePath
);
66 const XMLAttribute
* att
= moduleNode
.GetAttribute ( "name", true );
70 att
= moduleNode
.GetAttribute ( "type", true );
72 type
= GetModuleType ( node
.location
, *att
);
74 att
= moduleNode
.GetAttribute ( "extension", false );
76 extension
= att
->value
;
78 extension
= GetDefaultModuleExtension ();
80 att
= moduleNode
.GetAttribute ( "entrypoint", false );
82 entrypoint
= att
->value
;
84 entrypoint
= GetDefaultModuleEntrypoint ();
86 att
= moduleNode
.GetAttribute ( "baseaddress", false );
88 baseaddress
= att
->value
;
90 baseaddress
= GetDefaultModuleBaseaddress ();
92 att
= moduleNode
.GetAttribute ( "mangledsymbols", false );
94 mangledSymbols
= att
->value
!= "false";
96 mangledSymbols
= false;
102 for ( i
= 0; i
< files
.size(); i
++ )
104 for ( i
= 0; i
< libraries
.size(); i
++ )
106 for ( i
= 0; i
< includes
.size(); i
++ )
108 for ( i
= 0; i
< defines
.size(); i
++ )
110 for ( i
= 0; i
< invocations
.size(); i
++ )
111 delete invocations
[i
];
112 for ( i
= 0; i
< dependencies
.size(); i
++ )
113 delete dependencies
[i
];
114 for ( i
= 0; i
< ifs
.size(); i
++ )
116 for ( i
= 0; i
< compilerFlags
.size(); i
++ )
117 delete compilerFlags
[i
];
118 for ( i
= 0; i
< linkerFlags
.size(); i
++ )
119 delete linkerFlags
[i
];
126 for ( i
= 0; i
< node
.subElements
.size(); i
++ )
127 ProcessXMLSubElement ( *node
.subElements
[i
], path
);
128 for ( i
= 0; i
< files
.size (); i
++ )
129 files
[i
]->ProcessXML ();
130 for ( i
= 0; i
< libraries
.size(); i
++ )
131 libraries
[i
]->ProcessXML ();
132 for ( i
= 0; i
< includes
.size(); i
++ )
133 includes
[i
]->ProcessXML ();
134 for ( i
= 0; i
< defines
.size(); i
++ )
135 defines
[i
]->ProcessXML ();
136 for ( i
= 0; i
< invocations
.size(); i
++ )
137 invocations
[i
]->ProcessXML ();
138 for ( i
= 0; i
< dependencies
.size(); i
++ )
139 dependencies
[i
]->ProcessXML ();
140 for ( i
= 0; i
< ifs
.size(); i
++ )
141 ifs
[i
]->ProcessXML();
142 for ( i
= 0; i
< compilerFlags
.size(); i
++ )
143 compilerFlags
[i
]->ProcessXML();
144 for ( i
= 0; i
< linkerFlags
.size(); i
++ )
145 linkerFlags
[i
]->ProcessXML();
149 Module::ProcessXMLSubElement ( const XMLElement
& e
,
153 bool subs_invalid
= false;
154 string
subpath ( path
);
155 if ( e
.name
== "file" && e
.value
.size () > 0 )
158 const XMLAttribute
* att
= e
.GetAttribute ( "first", false );
161 if ( !stricmp ( att
->value
.c_str(), "true" ) )
163 else if ( stricmp ( att
->value
.c_str(), "false" ) )
164 throw InvalidBuildFileException (
166 "attribute 'first' of <file> element can only be 'true' or 'false'" );
168 File
* pFile
= new File ( FixSeparator ( path
+ CSEP
+ e
.value
), first
);
170 pIf
->files
.push_back ( pFile
);
172 files
.push_back ( pFile
);
175 else if ( e
.name
== "library" && e
.value
.size () )
178 throw InvalidBuildFileException (
180 "<library> is not a valid sub-element of <if>" );*/
181 libraries
.push_back ( new Library ( e
, *this, e
.value
) );
184 else if ( e
.name
== "directory" )
186 const XMLAttribute
* att
= e
.GetAttribute ( "name", true );
188 subpath
= FixSeparator ( path
+ CSEP
+ att
->value
);
190 else if ( e
.name
== "include" )
192 Include
* include
= new Include ( project
, this, e
);
194 pIf
->includes
.push_back ( include
);
196 includes
.push_back ( include
);
199 else if ( e
.name
== "define" )
201 Define
* pDefine
= new Define ( project
, this, e
);
203 pIf
->defines
.push_back ( pDefine
);
205 defines
.push_back ( pDefine
);
208 else if ( e
.name
== "invoke" )
211 throw InvalidBuildFileException (
213 "<invoke> is not a valid sub-element of <if>" );
214 invocations
.push_back ( new Invoke ( e
, *this ) );
215 subs_invalid
= false;
217 else if ( e
.name
== "dependency" )
220 throw InvalidBuildFileException (
222 "<dependency> is not a valid sub-element of <if>" );
223 dependencies
.push_back ( new Dependency ( e
, *this ) );
226 else if ( e
.name
== "importlibrary" )
229 throw InvalidBuildFileException (
231 "<importlibrary> is not a valid sub-element of <if>" );
233 throw InvalidBuildFileException (
235 "Only one <importlibrary> is valid per module" );
236 importLibrary
= new ImportLibrary ( e
, *this );
239 else if ( e
.name
== "if" )
242 pIf
= new If ( e
, project
, this );
244 pOldIf
->ifs
.push_back ( pIf
);
246 ifs
.push_back ( pIf
);
247 subs_invalid
= false;
249 else if ( e
.name
== "compilerflag" )
251 compilerFlags
.push_back ( new CompilerFlag ( project
, this, e
) );
254 else if ( e
.name
== "linkerflag" )
256 linkerFlags
.push_back ( new LinkerFlag ( project
, this, e
) );
259 else if ( e
.name
== "property" )
261 throw InvalidBuildFileException (
263 "<property> is not a valid sub-element of <module>" );
265 else if ( e
.name
== "bootstrap" )
267 bootstrap
= new Bootstrap ( project
, this, e
);
270 if ( subs_invalid
&& e
.subElements
.size() > 0 )
271 throw InvalidBuildFileException (
273 "<%s> cannot have sub-elements",
275 for ( size_t i
= 0; i
< e
.subElements
.size (); i
++ )
276 ProcessXMLSubElement ( *e
.subElements
[i
], subpath
, pIf
);
280 Module::GetModuleType ( const string
& location
, const XMLAttribute
& attribute
)
282 if ( attribute
.value
== "buildtool" )
284 if ( attribute
.value
== "staticlibrary" )
285 return StaticLibrary
;
286 if ( attribute
.value
== "objectlibrary" )
287 return ObjectLibrary
;
288 if ( attribute
.value
== "kernel" )
290 if ( attribute
.value
== "kernelmodedll" )
291 return KernelModeDLL
;
292 if ( attribute
.value
== "kernelmodedriver" )
293 return KernelModeDriver
;
294 if ( attribute
.value
== "nativedll" )
296 if ( attribute
.value
== "nativecui" )
298 if ( attribute
.value
== "win32dll" )
300 if ( attribute
.value
== "win32cui" )
302 if ( attribute
.value
== "win32gui" )
304 if ( attribute
.value
== "bootloader" )
306 if ( attribute
.value
== "bootsector" )
308 if ( attribute
.value
== "iso" )
310 throw InvalidAttributeValueException ( location
,
316 Module::GetDefaultModuleExtension () const
335 case KernelModeDriver
:
343 throw InvalidOperationException ( __FILE__
,
348 Module::GetDefaultModuleEntrypoint () const
353 return "_NtProcessStartup";
355 return "_DriverEntry@8";
357 return "_DllMainCRTStartup@12";
359 return "_NtProcessStartup@4";
361 return "_DllMain@12";
363 return "_mainCRTStartup";
365 return "_WinMainCRTStartup";
366 case KernelModeDriver
:
367 return "_DriverEntry@8";
376 throw InvalidOperationException ( __FILE__
,
381 Module::GetDefaultModuleBaseaddress () const
399 case KernelModeDriver
:
409 throw InvalidOperationException ( __FILE__
,
414 Module::HasImportLibrary () const
416 return importLibrary
!= NULL
;
420 Module::GetTargetName () const
422 return name
+ extension
;
426 Module::GetDependencyPath () const
428 if ( HasImportLibrary () )
430 return ssprintf ( "dk%snkm%slib%slib%s.a",
441 Module::GetBasePath () const
447 Module::GetPath () const
449 return path
+ CSEP
+ GetTargetName ();
453 Module::GetPathWithPrefix ( const string
& prefix
) const
455 return path
+ CSEP
+ prefix
+ GetTargetName ();
459 Module::GetTargets () const
461 if ( invocations
.size () > 0 )
463 string
targets ( "" );
464 for ( size_t i
= 0; i
< invocations
.size (); i
++ )
466 Invoke
& invoke
= *invocations
[i
];
467 if ( targets
.length () > 0 )
469 targets
+= invoke
.GetTargets ();
478 Module::GetInvocationTarget ( const int index
) const
480 return ssprintf ( "%s_invoke_%d",
486 Module::HasFileWithExtensions ( const std::string
& extension1
,
487 const std::string
& extension2
) const
489 for ( size_t i
= 0; i
< files
.size (); i
++ )
491 File
& file
= *files
[i
];
492 string extension
= GetExtension ( file
.name
);
493 if ( extension
== extension1
|| extension
== extension2
)
500 Module::InvokeModule () const
502 for ( size_t i
= 0; i
< invocations
.size (); i
++ )
504 Invoke
& invoke
= *invocations
[i
];
505 string command
= invoke
.invokeModule
->GetPath () + " " + invoke
.GetParameters ();
506 printf ( "Executing '%s'\n\n", command
.c_str () );
507 int exitcode
= system ( command
.c_str () );
509 throw InvocationFailedException ( command
,
515 File::File ( const string
& _name
, bool _first
)
516 : name(_name
), first(_first
)
526 Library::Library ( const XMLElement
& _node
,
527 const Module
& _module
,
528 const string
& _name
)
532 imported_module(_module
.project
.LocateModule(_name
))
534 if ( module
.name
== name
)
535 throw InvalidBuildFileException (
537 "module '%s' cannot link against itself",
539 if ( !imported_module
)
540 throw InvalidBuildFileException (
542 "module '%s' trying to import non-existant module '%s'",
548 Library::ProcessXML()
550 if ( !module
.project
.LocateModule ( name
) )
551 throw InvalidBuildFileException (
553 "module '%s' is trying to link against non-existant module '%s'",
559 Invoke::Invoke ( const XMLElement
& _node
,
560 const Module
& _module
)
569 const XMLAttribute
* att
= node
.GetAttribute ( "module", false );
571 invokeModule
= &module
;
574 invokeModule
= module
.project
.LocateModule ( att
->value
);
575 if ( invokeModule
== NULL
)
576 throw InvalidBuildFileException (
578 "module '%s' is trying to invoke non-existant module '%s'",
580 att
->value
.c_str() );
583 for ( size_t i
= 0; i
< node
.subElements
.size (); i
++ )
584 ProcessXMLSubElement ( *node
.subElements
[i
] );
588 Invoke::ProcessXMLSubElement ( const XMLElement
& e
)
590 bool subs_invalid
= false;
591 if ( e
.name
== "input" )
593 for ( size_t i
= 0; i
< e
.subElements
.size (); i
++ )
594 ProcessXMLSubElementInput ( *e
.subElements
[i
] );
596 else if ( e
.name
== "output" )
598 for ( size_t i
= 0; i
< e
.subElements
.size (); i
++ )
599 ProcessXMLSubElementOutput ( *e
.subElements
[i
] );
601 if ( subs_invalid
&& e
.subElements
.size() > 0 )
602 throw InvalidBuildFileException ( e
.location
,
603 "<%s> cannot have sub-elements",
608 Invoke::ProcessXMLSubElementInput ( const XMLElement
& e
)
610 bool subs_invalid
= false;
611 if ( e
.name
== "inputfile" && e
.value
.size () > 0 )
613 input
.push_back ( new InvokeFile ( e
, FixSeparator ( module
.path
+ CSEP
+ e
.value
) ) );
616 if ( subs_invalid
&& e
.subElements
.size() > 0 )
617 throw InvalidBuildFileException ( e
.location
,
618 "<%s> cannot have sub-elements",
623 Invoke::ProcessXMLSubElementOutput ( const XMLElement
& e
)
625 bool subs_invalid
= false;
626 if ( e
.name
== "outputfile" && e
.value
.size () > 0 )
628 output
.push_back ( new InvokeFile ( e
, FixSeparator ( module
.path
+ CSEP
+ e
.value
) ) );
631 if ( subs_invalid
&& e
.subElements
.size() > 0 )
632 throw InvalidBuildFileException ( e
.location
,
633 "<%s> cannot have sub-elements",
638 Invoke::GetTargets () const
640 string
targets ( "" );
641 for ( size_t i
= 0; i
< output
.size (); i
++ )
643 InvokeFile
& file
= *output
[i
];
644 if ( targets
.length () > 0 )
646 targets
+= NormalizeFilename ( file
.name
);
652 Invoke::GetParameters () const
654 string
parameters ( "" );
656 for ( i
= 0; i
< output
.size (); i
++ )
658 if ( parameters
.length () > 0)
660 InvokeFile
& invokeFile
= *output
[i
];
661 if ( invokeFile
.switches
.length () > 0 )
663 parameters
+= invokeFile
.switches
;
666 parameters
+= invokeFile
.name
;
669 for ( i
= 0; i
< input
.size (); i
++ )
671 if ( parameters
.length () > 0 )
673 InvokeFile
& invokeFile
= *input
[i
];
674 if ( invokeFile
.switches
.length () > 0 )
676 parameters
+= invokeFile
.switches
;
679 parameters
+= invokeFile
.name
;
686 InvokeFile::InvokeFile ( const XMLElement
& _node
,
687 const string
& _name
)
691 const XMLAttribute
* att
= _node
.GetAttribute ( "switches", false );
693 switches
= att
->value
;
699 InvokeFile::ProcessXML()
704 Dependency::Dependency ( const XMLElement
& _node
,
705 const Module
& _module
)
708 dependencyModule (NULL
)
713 Dependency::ProcessXML()
715 dependencyModule
= module
.project
.LocateModule ( node
.value
);
716 if ( dependencyModule
== NULL
)
717 throw InvalidBuildFileException ( node
.location
,
718 "module '%s' depend on non-existant module '%s'",
720 node
.value
.c_str() );
724 ImportLibrary::ImportLibrary ( const XMLElement
& _node
,
725 const Module
& _module
)
729 const XMLAttribute
* att
= _node
.GetAttribute ( "basename", false );
731 basename
= att
->value
;
733 basename
= module
.name
;
735 att
= _node
.GetAttribute ( "definition", true );
737 definition
= FixSeparator(att
->value
);
741 If::If ( const XMLElement
& node_
,
742 const Project
& project_
,
743 const Module
* module_
)
744 : node(node_
), project(project_
), module(module_
)
746 const XMLAttribute
* att
;
748 att
= node
.GetAttribute ( "property", true );
750 property
= att
->value
;
752 att
= node
.GetAttribute ( "value", true );
760 for ( i
= 0; i
< files
.size(); i
++ )
762 for ( i
= 0; i
< includes
.size(); i
++ )
764 for ( i
= 0; i
< defines
.size(); i
++ )
766 for ( i
= 0; i
< ifs
.size(); i
++ )
776 Property::Property ( const XMLElement
& node_
,
777 const Project
& project_
,
778 const Module
* module_
)
779 : node(node_
), project(project_
), module(module_
)
781 const XMLAttribute
* att
;
783 att
= node
.GetAttribute ( "name", true );
787 att
= node
.GetAttribute ( "value", true );
793 Property::ProcessXML()