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 IfableData::~IfableData()
56 for ( i
= 0; i
< files
.size(); i
++ )
58 for ( i
= 0; i
< includes
.size(); i
++ )
60 for ( i
= 0; i
< defines
.size(); i
++ )
62 for ( i
= 0; i
< libraries
.size(); i
++ )
64 for ( i
= 0; i
< properties
.size(); i
++ )
66 for ( i
= 0; i
< ifs
.size(); i
++ )
70 void IfableData::ProcessXML ()
73 for ( i
= 0; i
< files
.size (); i
++ )
74 files
[i
]->ProcessXML ();
75 for ( i
= 0; i
< includes
.size (); i
++ )
76 includes
[i
]->ProcessXML ();
77 for ( i
= 0; i
< defines
.size (); i
++ )
78 defines
[i
]->ProcessXML ();
79 for ( i
= 0; i
< libraries
.size (); i
++ )
80 libraries
[i
]->ProcessXML ();
81 for ( i
= 0; i
< properties
.size(); i
++ )
82 properties
[i
]->ProcessXML ();
83 for ( i
= 0; i
< ifs
.size (); i
++ )
84 ifs
[i
]->ProcessXML ();
87 Module::Module ( const Project
& project
,
88 const XMLElement
& moduleNode
,
89 const string
& modulePath
)
95 if ( node
.name
!= "module" )
96 throw Exception ( "internal tool error: Module created with non-<module> node" );
98 path
= FixSeparator ( modulePath
);
100 const XMLAttribute
* att
= moduleNode
.GetAttribute ( "name", true );
104 att
= moduleNode
.GetAttribute ( "type", true );
106 type
= GetModuleType ( node
.location
, *att
);
108 att
= moduleNode
.GetAttribute ( "extension", false );
110 extension
= att
->value
;
112 extension
= GetDefaultModuleExtension ();
114 att
= moduleNode
.GetAttribute ( "entrypoint", false );
116 entrypoint
= att
->value
;
118 entrypoint
= GetDefaultModuleEntrypoint ();
120 att
= moduleNode
.GetAttribute ( "baseaddress", false );
122 baseaddress
= att
->value
;
124 baseaddress
= GetDefaultModuleBaseaddress ();
126 att
= moduleNode
.GetAttribute ( "mangledsymbols", false );
128 mangledSymbols
= att
->value
!= "false";
130 mangledSymbols
= false;
136 for ( i
= 0; i
< invocations
.size(); i
++ )
137 delete invocations
[i
];
138 for ( i
= 0; i
< dependencies
.size(); i
++ )
139 delete dependencies
[i
];
140 for ( i
= 0; i
< compilerFlags
.size(); i
++ )
141 delete compilerFlags
[i
];
142 for ( i
= 0; i
< linkerFlags
.size(); i
++ )
143 delete linkerFlags
[i
];
150 for ( i
= 0; i
< node
.subElements
.size(); i
++ )
151 ProcessXMLSubElement ( *node
.subElements
[i
], path
);
152 for ( i
= 0; i
< invocations
.size(); i
++ )
153 invocations
[i
]->ProcessXML ();
154 for ( i
= 0; i
< dependencies
.size(); i
++ )
155 dependencies
[i
]->ProcessXML ();
156 for ( i
= 0; i
< compilerFlags
.size(); i
++ )
157 compilerFlags
[i
]->ProcessXML();
158 for ( i
= 0; i
< linkerFlags
.size(); i
++ )
159 linkerFlags
[i
]->ProcessXML();
160 non_if_data
.ProcessXML();
164 Module::ProcessXMLSubElement ( const XMLElement
& e
,
168 bool subs_invalid
= false;
169 string
subpath ( path
);
170 if ( e
.name
== "file" && e
.value
.size () > 0 )
173 const XMLAttribute
* att
= e
.GetAttribute ( "first", false );
176 if ( !stricmp ( att
->value
.c_str(), "true" ) )
178 else if ( stricmp ( att
->value
.c_str(), "false" ) )
179 throw InvalidBuildFileException (
181 "attribute 'first' of <file> element can only be 'true' or 'false'" );
183 File
* pFile
= new File ( FixSeparator ( path
+ CSEP
+ e
.value
), first
);
185 pIf
->data
.files
.push_back ( pFile
);
187 non_if_data
.files
.push_back ( pFile
);
190 else if ( e
.name
== "library" && e
.value
.size () )
192 Library
* pLibrary
= new Library ( e
, *this, e
.value
);
194 pIf
->data
.libraries
.push_back ( pLibrary
);
196 non_if_data
.libraries
.push_back ( pLibrary
);
199 else if ( e
.name
== "directory" )
201 const XMLAttribute
* att
= e
.GetAttribute ( "name", true );
203 subpath
= FixSeparator ( path
+ CSEP
+ att
->value
);
205 else if ( e
.name
== "include" )
207 Include
* include
= new Include ( project
, this, e
);
209 pIf
->data
.includes
.push_back ( include
);
211 non_if_data
.includes
.push_back ( include
);
214 else if ( e
.name
== "define" )
216 Define
* pDefine
= new Define ( project
, this, e
);
218 pIf
->data
.defines
.push_back ( pDefine
);
220 non_if_data
.defines
.push_back ( pDefine
);
223 else if ( e
.name
== "invoke" )
226 throw InvalidBuildFileException (
228 "<invoke> is not a valid sub-element of <if>" );
229 invocations
.push_back ( new Invoke ( e
, *this ) );
230 subs_invalid
= false;
232 else if ( e
.name
== "dependency" )
235 throw InvalidBuildFileException (
237 "<dependency> is not a valid sub-element of <if>" );
238 dependencies
.push_back ( new Dependency ( e
, *this ) );
241 else if ( e
.name
== "importlibrary" )
244 throw InvalidBuildFileException (
246 "<importlibrary> is not a valid sub-element of <if>" );
248 throw InvalidBuildFileException (
250 "Only one <importlibrary> is valid per module" );
251 importLibrary
= new ImportLibrary ( e
, *this );
254 else if ( e
.name
== "if" )
257 pIf
= new If ( e
, project
, this );
259 pOldIf
->data
.ifs
.push_back ( pIf
);
261 non_if_data
.ifs
.push_back ( pIf
);
262 subs_invalid
= false;
264 else if ( e
.name
== "compilerflag" )
266 compilerFlags
.push_back ( new CompilerFlag ( project
, this, e
) );
269 else if ( e
.name
== "linkerflag" )
271 linkerFlags
.push_back ( new LinkerFlag ( project
, this, e
) );
274 else if ( e
.name
== "property" )
276 throw InvalidBuildFileException (
278 "<property> is not a valid sub-element of <module>" );
280 else if ( e
.name
== "bootstrap" )
282 bootstrap
= new Bootstrap ( project
, this, e
);
285 if ( subs_invalid
&& e
.subElements
.size() > 0 )
286 throw InvalidBuildFileException (
288 "<%s> cannot have sub-elements",
290 for ( size_t i
= 0; i
< e
.subElements
.size (); i
++ )
291 ProcessXMLSubElement ( *e
.subElements
[i
], subpath
, pIf
);
295 Module::GetModuleType ( const string
& location
, const XMLAttribute
& attribute
)
297 if ( attribute
.value
== "buildtool" )
299 if ( attribute
.value
== "staticlibrary" )
300 return StaticLibrary
;
301 if ( attribute
.value
== "objectlibrary" )
302 return ObjectLibrary
;
303 if ( attribute
.value
== "kernel" )
305 if ( attribute
.value
== "kernelmodedll" )
306 return KernelModeDLL
;
307 if ( attribute
.value
== "kernelmodedriver" )
308 return KernelModeDriver
;
309 if ( attribute
.value
== "nativedll" )
311 if ( attribute
.value
== "nativecui" )
313 if ( attribute
.value
== "win32dll" )
315 if ( attribute
.value
== "win32cui" )
317 if ( attribute
.value
== "win32gui" )
319 if ( attribute
.value
== "bootloader" )
321 if ( attribute
.value
== "bootsector" )
323 if ( attribute
.value
== "iso" )
325 throw InvalidAttributeValueException ( location
,
331 Module::GetDefaultModuleExtension () const
350 case KernelModeDriver
:
358 throw InvalidOperationException ( __FILE__
,
363 Module::GetDefaultModuleEntrypoint () const
368 return "_NtProcessStartup";
370 return "_DriverEntry@8";
372 return "_DllMainCRTStartup@12";
374 return "_NtProcessStartup@4";
376 return "_DllMain@12";
378 return "_mainCRTStartup";
380 return "_WinMainCRTStartup";
381 case KernelModeDriver
:
382 return "_DriverEntry@8";
391 throw InvalidOperationException ( __FILE__
,
396 Module::GetDefaultModuleBaseaddress () const
414 case KernelModeDriver
:
424 throw InvalidOperationException ( __FILE__
,
429 Module::HasImportLibrary () const
431 return importLibrary
!= NULL
;
435 Module::GetTargetName () const
437 return name
+ extension
;
441 Module::GetDependencyPath () const
443 if ( HasImportLibrary () )
445 return ssprintf ( "dk%snkm%slib%slib%s.a",
456 Module::GetBasePath () const
462 Module::GetPath () const
464 return path
+ CSEP
+ GetTargetName ();
468 Module::GetPathWithPrefix ( const string
& prefix
) const
470 return path
+ CSEP
+ prefix
+ GetTargetName ();
474 Module::GetTargets () const
476 if ( invocations
.size () > 0 )
478 string
targets ( "" );
479 for ( size_t i
= 0; i
< invocations
.size (); i
++ )
481 Invoke
& invoke
= *invocations
[i
];
482 if ( targets
.length () > 0 )
484 targets
+= invoke
.GetTargets ();
493 Module::GetInvocationTarget ( const int index
) const
495 return ssprintf ( "%s_invoke_%d",
501 Module::HasFileWithExtension (
502 const IfableData
& data
,
503 const std::string
& extension
) const
506 for ( i
= 0; i
< data
.files
.size (); i
++ )
508 File
& file
= *data
.files
[i
];
509 string file_ext
= GetExtension ( file
.name
);
510 if ( !stricmp ( file_ext
.c_str (), extension
.c_str () ) )
513 for ( i
= 0; i
< data
.ifs
.size (); i
++ )
515 if ( HasFileWithExtension ( data
.ifs
[i
]->data
, extension
) )
522 Module::InvokeModule () const
524 for ( size_t i
= 0; i
< invocations
.size (); i
++ )
526 Invoke
& invoke
= *invocations
[i
];
527 string command
= invoke
.invokeModule
->GetPath () + " " + invoke
.GetParameters ();
528 printf ( "Executing '%s'\n\n", command
.c_str () );
529 int exitcode
= system ( command
.c_str () );
531 throw InvocationFailedException ( command
,
537 File::File ( const string
& _name
, bool _first
)
538 : name(_name
), first(_first
)
548 Library::Library ( const XMLElement
& _node
,
549 const Module
& _module
,
550 const string
& _name
)
554 imported_module(_module
.project
.LocateModule(_name
))
556 if ( module
.name
== name
)
557 throw InvalidBuildFileException (
559 "module '%s' cannot link against itself",
561 if ( !imported_module
)
562 throw InvalidBuildFileException (
564 "module '%s' trying to import non-existant module '%s'",
570 Library::ProcessXML()
572 if ( !module
.project
.LocateModule ( name
) )
573 throw InvalidBuildFileException (
575 "module '%s' is trying to link against non-existant module '%s'",
581 Invoke::Invoke ( const XMLElement
& _node
,
582 const Module
& _module
)
591 const XMLAttribute
* att
= node
.GetAttribute ( "module", false );
593 invokeModule
= &module
;
596 invokeModule
= module
.project
.LocateModule ( att
->value
);
597 if ( invokeModule
== NULL
)
598 throw InvalidBuildFileException (
600 "module '%s' is trying to invoke non-existant module '%s'",
602 att
->value
.c_str() );
605 for ( size_t i
= 0; i
< node
.subElements
.size (); i
++ )
606 ProcessXMLSubElement ( *node
.subElements
[i
] );
610 Invoke::ProcessXMLSubElement ( const XMLElement
& e
)
612 bool subs_invalid
= false;
613 if ( e
.name
== "input" )
615 for ( size_t i
= 0; i
< e
.subElements
.size (); i
++ )
616 ProcessXMLSubElementInput ( *e
.subElements
[i
] );
618 else if ( e
.name
== "output" )
620 for ( size_t i
= 0; i
< e
.subElements
.size (); i
++ )
621 ProcessXMLSubElementOutput ( *e
.subElements
[i
] );
623 if ( subs_invalid
&& e
.subElements
.size() > 0 )
624 throw InvalidBuildFileException ( e
.location
,
625 "<%s> cannot have sub-elements",
630 Invoke::ProcessXMLSubElementInput ( const XMLElement
& e
)
632 bool subs_invalid
= false;
633 if ( e
.name
== "inputfile" && e
.value
.size () > 0 )
635 input
.push_back ( new InvokeFile ( e
, FixSeparator ( module
.path
+ CSEP
+ e
.value
) ) );
638 if ( subs_invalid
&& e
.subElements
.size() > 0 )
639 throw InvalidBuildFileException ( e
.location
,
640 "<%s> cannot have sub-elements",
645 Invoke::ProcessXMLSubElementOutput ( const XMLElement
& e
)
647 bool subs_invalid
= false;
648 if ( e
.name
== "outputfile" && e
.value
.size () > 0 )
650 output
.push_back ( new InvokeFile ( e
, FixSeparator ( module
.path
+ CSEP
+ e
.value
) ) );
653 if ( subs_invalid
&& e
.subElements
.size() > 0 )
654 throw InvalidBuildFileException ( e
.location
,
655 "<%s> cannot have sub-elements",
660 Invoke::GetTargets () const
662 string
targets ( "" );
663 for ( size_t i
= 0; i
< output
.size (); i
++ )
665 InvokeFile
& file
= *output
[i
];
666 if ( targets
.length () > 0 )
668 targets
+= NormalizeFilename ( file
.name
);
674 Invoke::GetParameters () const
676 string
parameters ( "" );
678 for ( i
= 0; i
< output
.size (); i
++ )
680 if ( parameters
.length () > 0)
682 InvokeFile
& invokeFile
= *output
[i
];
683 if ( invokeFile
.switches
.length () > 0 )
685 parameters
+= invokeFile
.switches
;
688 parameters
+= invokeFile
.name
;
691 for ( i
= 0; i
< input
.size (); i
++ )
693 if ( parameters
.length () > 0 )
695 InvokeFile
& invokeFile
= *input
[i
];
696 if ( invokeFile
.switches
.length () > 0 )
698 parameters
+= invokeFile
.switches
;
701 parameters
+= invokeFile
.name
;
708 InvokeFile::InvokeFile ( const XMLElement
& _node
,
709 const string
& _name
)
713 const XMLAttribute
* att
= _node
.GetAttribute ( "switches", false );
715 switches
= att
->value
;
721 InvokeFile::ProcessXML()
726 Dependency::Dependency ( const XMLElement
& _node
,
727 const Module
& _module
)
730 dependencyModule (NULL
)
735 Dependency::ProcessXML()
737 dependencyModule
= module
.project
.LocateModule ( node
.value
);
738 if ( dependencyModule
== NULL
)
739 throw InvalidBuildFileException ( node
.location
,
740 "module '%s' depend on non-existant module '%s'",
742 node
.value
.c_str() );
746 ImportLibrary::ImportLibrary ( const XMLElement
& _node
,
747 const Module
& _module
)
751 const XMLAttribute
* att
= _node
.GetAttribute ( "basename", false );
753 basename
= att
->value
;
755 basename
= module
.name
;
757 att
= _node
.GetAttribute ( "definition", true );
759 definition
= FixSeparator(att
->value
);
763 If::If ( const XMLElement
& node_
,
764 const Project
& project_
,
765 const Module
* module_
)
766 : node(node_
), project(project_
), module(module_
)
768 const XMLAttribute
* att
;
770 att
= node
.GetAttribute ( "property", true );
772 property
= att
->value
;
774 att
= node
.GetAttribute ( "value", true );
789 Property::Property ( const XMLElement
& node_
,
790 const Project
& project_
,
791 const Module
* module_
)
792 : node(node_
), project(project_
), module(module_
)
794 const XMLAttribute
* att
;
796 att
= node
.GetAttribute ( "name", true );
800 att
= node
.GetAttribute ( "value", true );
806 Property::ProcessXML()