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
)
60 if ( node
.name
!= "module" )
61 throw Exception ( "internal tool error: Module created with non-<module> node" );
63 path
= FixSeparator ( modulePath
);
65 const XMLAttribute
* att
= moduleNode
.GetAttribute ( "name", true );
69 att
= moduleNode
.GetAttribute ( "type", true );
71 type
= GetModuleType ( node
.location
, *att
);
73 att
= moduleNode
.GetAttribute ( "extension", false );
75 extension
= att
->value
;
77 extension
= GetDefaultModuleExtension ();
79 att
= moduleNode
.GetAttribute ( "entrypoint", false );
81 entrypoint
= att
->value
;
83 entrypoint
= GetDefaultModuleEntrypoint ();
85 att
= moduleNode
.GetAttribute ( "mangledsymbols", false );
87 mangledSymbols
= att
->value
!= "false";
89 mangledSymbols
= false;
95 for ( i
= 0; i
< files
.size(); i
++ )
97 for ( i
= 0; i
< libraries
.size(); i
++ )
99 for ( i
= 0; i
< includes
.size(); i
++ )
101 for ( i
= 0; i
< defines
.size(); i
++ )
103 for ( i
= 0; i
< invocations
.size(); i
++ )
104 delete invocations
[i
];
105 for ( i
= 0; i
< dependencies
.size(); i
++ )
106 delete dependencies
[i
];
107 for ( i
= 0; i
< ifs
.size(); i
++ )
109 for ( i
= 0; i
< compilerFlags
.size(); i
++ )
110 delete compilerFlags
[i
];
111 for ( i
= 0; i
< linkerFlags
.size(); i
++ )
112 delete linkerFlags
[i
];
119 for ( i
= 0; i
< node
.subElements
.size(); i
++ )
120 ProcessXMLSubElement ( *node
.subElements
[i
], path
);
121 for ( i
= 0; i
< files
.size (); i
++ )
122 files
[i
]->ProcessXML ();
123 for ( i
= 0; i
< libraries
.size(); i
++ )
124 libraries
[i
]->ProcessXML ();
125 for ( i
= 0; i
< includes
.size(); i
++ )
126 includes
[i
]->ProcessXML ();
127 for ( i
= 0; i
< defines
.size(); i
++ )
128 defines
[i
]->ProcessXML ();
129 for ( i
= 0; i
< invocations
.size(); i
++ )
130 invocations
[i
]->ProcessXML ();
131 for ( i
= 0; i
< dependencies
.size(); i
++ )
132 dependencies
[i
]->ProcessXML ();
133 for ( i
= 0; i
< ifs
.size(); i
++ )
134 ifs
[i
]->ProcessXML();
135 for ( i
= 0; i
< compilerFlags
.size(); i
++ )
136 compilerFlags
[i
]->ProcessXML();
137 for ( i
= 0; i
< linkerFlags
.size(); i
++ )
138 linkerFlags
[i
]->ProcessXML();
142 Module::ProcessXMLSubElement ( const XMLElement
& e
,
146 bool subs_invalid
= false;
147 string
subpath ( path
);
148 if ( e
.name
== "file" && e
.value
.size () > 0 )
151 const XMLAttribute
* att
= e
.GetAttribute ( "first", false );
154 if ( !stricmp ( att
->value
.c_str(), "true" ) )
156 else if ( stricmp ( att
->value
.c_str(), "false" ) )
157 throw InvalidBuildFileException (
159 "attribute 'first' of <file> element can only be 'true' or 'false'" );
161 File
* pFile
= new File ( FixSeparator ( path
+ CSEP
+ e
.value
), first
);
163 pIf
->files
.push_back ( pFile
);
165 files
.push_back ( pFile
);
168 else if ( e
.name
== "library" && e
.value
.size () )
171 throw InvalidBuildFileException (
173 "<library> is not a valid sub-element of <if>" );
174 libraries
.push_back ( new Library ( e
, *this, e
.value
) );
177 else if ( e
.name
== "directory" )
179 const XMLAttribute
* att
= e
.GetAttribute ( "name", true );
181 subpath
= FixSeparator ( path
+ CSEP
+ att
->value
);
183 else if ( e
.name
== "include" )
185 Include
* include
= new Include ( project
, this, e
);
187 pIf
->includes
.push_back ( include
);
189 includes
.push_back ( include
);
192 else if ( e
.name
== "define" )
194 Define
* pDefine
= new Define ( project
, this, e
);
196 pIf
->defines
.push_back ( pDefine
);
198 defines
.push_back ( pDefine
);
201 else if ( e
.name
== "invoke" )
204 throw InvalidBuildFileException (
206 "<invoke> is not a valid sub-element of <if>" );
207 invocations
.push_back ( new Invoke ( e
, *this ) );
208 subs_invalid
= false;
210 else if ( e
.name
== "dependency" )
213 throw InvalidBuildFileException (
215 "<dependency> is not a valid sub-element of <if>" );
216 dependencies
.push_back ( new Dependency ( e
, *this ) );
219 else if ( e
.name
== "importlibrary" )
222 throw InvalidBuildFileException (
224 "<importlibrary> is not a valid sub-element of <if>" );
226 throw InvalidBuildFileException (
228 "Only one <importlibrary> is valid per module" );
229 importLibrary
= new ImportLibrary ( e
, *this );
232 else if ( e
.name
== "if" )
235 pIf
= new If ( e
, project
, this );
237 pOldIf
->ifs
.push_back ( pIf
);
239 ifs
.push_back ( pIf
);
240 subs_invalid
= false;
242 else if ( e
.name
== "compilerflag" )
244 compilerFlags
.push_back ( new CompilerFlag ( project
, this, e
) );
247 else if ( e
.name
== "linkerflag" )
249 linkerFlags
.push_back ( new LinkerFlag ( project
, this, e
) );
252 else if ( e
.name
== "property" )
254 throw InvalidBuildFileException (
256 "<property> is not a valid sub-element of <module>" );
258 if ( subs_invalid
&& e
.subElements
.size() > 0 )
259 throw InvalidBuildFileException (
261 "<%s> cannot have sub-elements",
263 for ( size_t i
= 0; i
< e
.subElements
.size (); i
++ )
264 ProcessXMLSubElement ( *e
.subElements
[i
], subpath
, pIf
);
268 Module::GetModuleType ( const string
& location
, const XMLAttribute
& attribute
)
270 if ( attribute
.value
== "buildtool" )
272 if ( attribute
.value
== "staticlibrary" )
273 return StaticLibrary
;
274 if ( attribute
.value
== "objectlibrary" )
275 return ObjectLibrary
;
276 if ( attribute
.value
== "kernel" )
278 if ( attribute
.value
== "kernelmodedll" )
279 return KernelModeDLL
;
280 if ( attribute
.value
== "kernelmodedriver" )
281 return KernelModeDriver
;
282 if ( attribute
.value
== "nativedll" )
284 if ( attribute
.value
== "nativecui" )
286 if ( attribute
.value
== "win32dll" )
288 if ( attribute
.value
== "win32cui" )
290 if ( attribute
.value
== "win32gui" )
292 if ( attribute
.value
== "bootloader" )
294 if ( attribute
.value
== "bootsector" )
296 if ( attribute
.value
== "iso" )
298 throw InvalidAttributeValueException ( location
,
304 Module::GetDefaultModuleExtension () const
323 case KernelModeDriver
:
331 throw InvalidOperationException ( __FILE__
,
336 Module::GetDefaultModuleEntrypoint () const
341 return "_NtProcessStartup";
343 return "_DriverEntry@8";
345 return "_DllMainCRTStartup@12";
347 return "_NtProcessStartup@4";
349 return "_DllMain@12";
351 return "_mainCRTStartup";
353 return "_WinMainCRTStartup";
354 case KernelModeDriver
:
355 return "_DriverEntry@8";
364 throw InvalidOperationException ( __FILE__
,
369 Module::HasImportLibrary () const
371 return importLibrary
!= NULL
;
375 Module::GetTargetName () const
377 return name
+ extension
;
381 Module::GetDependencyPath () const
383 if ( HasImportLibrary () )
385 return ssprintf ( "dk%snkm%slib%slib%s.a",
396 Module::GetBasePath () const
402 Module::GetPath () const
404 return path
+ CSEP
+ GetTargetName ();
408 Module::GetPathWithPrefix ( const string
& prefix
) const
410 return path
+ CSEP
+ prefix
+ GetTargetName ();
414 Module::GetTargets () const
416 if ( invocations
.size () > 0 )
418 string
targets ( "" );
419 for ( size_t i
= 0; i
< invocations
.size (); i
++ )
421 Invoke
& invoke
= *invocations
[i
];
422 if ( targets
.length () > 0 )
424 targets
+= invoke
.GetTargets ();
433 Module::GetInvocationTarget ( const int index
) const
435 return ssprintf ( "%s_invoke_%d",
441 Module::HasFileWithExtensions ( const std::string
& extension1
,
442 const std::string
& extension2
) const
444 for ( size_t i
= 0; i
< files
.size (); i
++ )
446 File
& file
= *files
[i
];
447 string extension
= GetExtension ( file
.name
);
448 if ( extension
== extension1
|| extension
== extension2
)
455 Module::InvokeModule () const
457 for ( size_t i
= 0; i
< invocations
.size (); i
++ )
459 Invoke
& invoke
= *invocations
[i
];
460 string command
= invoke
.invokeModule
->GetPath () + " " + invoke
.GetParameters ();
461 printf ( "Executing '%s'\n\n", command
.c_str () );
462 int exitcode
= system ( command
.c_str () );
464 throw InvocationFailedException ( command
,
470 File::File ( const string
& _name
, bool _first
)
471 : name(_name
), first(_first
)
481 Library::Library ( const XMLElement
& _node
,
482 const Module
& _module
,
483 const string
& _name
)
488 if ( module
.name
== name
)
489 throw InvalidBuildFileException (
491 "module '%s' cannot link against itself",
496 Library::ProcessXML()
498 if ( !module
.project
.LocateModule ( name
) )
499 throw InvalidBuildFileException (
501 "module '%s' is trying to link against non-existant module '%s'",
507 Invoke::Invoke ( const XMLElement
& _node
,
508 const Module
& _module
)
517 const XMLAttribute
* att
= node
.GetAttribute ( "module", false );
519 invokeModule
= &module
;
522 invokeModule
= module
.project
.LocateModule ( att
->value
);
523 if ( invokeModule
== NULL
)
524 throw InvalidBuildFileException (
526 "module '%s' is trying to invoke non-existant module '%s'",
528 att
->value
.c_str() );
531 for ( size_t i
= 0; i
< node
.subElements
.size (); i
++ )
532 ProcessXMLSubElement ( *node
.subElements
[i
] );
536 Invoke::ProcessXMLSubElement ( const XMLElement
& e
)
538 bool subs_invalid
= false;
539 if ( e
.name
== "input" )
541 for ( size_t i
= 0; i
< e
.subElements
.size (); i
++ )
542 ProcessXMLSubElementInput ( *e
.subElements
[i
] );
544 else if ( e
.name
== "output" )
546 for ( size_t i
= 0; i
< e
.subElements
.size (); i
++ )
547 ProcessXMLSubElementOutput ( *e
.subElements
[i
] );
549 if ( subs_invalid
&& e
.subElements
.size() > 0 )
550 throw InvalidBuildFileException ( e
.location
,
551 "<%s> cannot have sub-elements",
556 Invoke::ProcessXMLSubElementInput ( const XMLElement
& e
)
558 bool subs_invalid
= false;
559 if ( e
.name
== "inputfile" && e
.value
.size () > 0 )
561 input
.push_back ( new InvokeFile ( e
, FixSeparator ( module
.path
+ CSEP
+ e
.value
) ) );
564 if ( subs_invalid
&& e
.subElements
.size() > 0 )
565 throw InvalidBuildFileException ( e
.location
,
566 "<%s> cannot have sub-elements",
571 Invoke::ProcessXMLSubElementOutput ( const XMLElement
& e
)
573 bool subs_invalid
= false;
574 if ( e
.name
== "outputfile" && e
.value
.size () > 0 )
576 output
.push_back ( new InvokeFile ( e
, FixSeparator ( module
.path
+ CSEP
+ e
.value
) ) );
579 if ( subs_invalid
&& e
.subElements
.size() > 0 )
580 throw InvalidBuildFileException ( e
.location
,
581 "<%s> cannot have sub-elements",
586 Invoke::GetTargets () const
588 string
targets ( "" );
589 for ( size_t i
= 0; i
< output
.size (); i
++ )
591 InvokeFile
& file
= *output
[i
];
592 if ( targets
.length () > 0 )
594 targets
+= NormalizeFilename ( file
.name
);
600 Invoke::GetParameters () const
602 string
parameters ( "" );
604 for ( i
= 0; i
< output
.size (); i
++ )
606 if ( parameters
.length () > 0)
608 InvokeFile
& invokeFile
= *output
[i
];
609 if ( invokeFile
.switches
.length () > 0 )
611 parameters
+= invokeFile
.switches
;
614 parameters
+= invokeFile
.name
;
617 for ( i
= 0; i
< input
.size (); i
++ )
619 if ( parameters
.length () > 0 )
621 InvokeFile
& invokeFile
= *input
[i
];
622 if ( invokeFile
.switches
.length () > 0 )
624 parameters
+= invokeFile
.switches
;
627 parameters
+= invokeFile
.name
;
634 InvokeFile::InvokeFile ( const XMLElement
& _node
,
635 const string
& _name
)
639 const XMLAttribute
* att
= _node
.GetAttribute ( "switches", false );
641 switches
= att
->value
;
647 InvokeFile::ProcessXML()
652 Dependency::Dependency ( const XMLElement
& _node
,
653 const Module
& _module
)
656 dependencyModule (NULL
)
661 Dependency::ProcessXML()
663 dependencyModule
= module
.project
.LocateModule ( node
.value
);
664 if ( dependencyModule
== NULL
)
665 throw InvalidBuildFileException ( node
.location
,
666 "module '%s' depend on non-existant module '%s'",
668 node
.value
.c_str() );
672 ImportLibrary::ImportLibrary ( const XMLElement
& _node
,
673 const Module
& _module
)
677 const XMLAttribute
* att
= _node
.GetAttribute ( "basename", false );
679 basename
= att
->value
;
681 basename
= module
.name
;
683 att
= _node
.GetAttribute ( "definition", true );
685 definition
= FixSeparator(att
->value
);
689 If::If ( const XMLElement
& node_
,
690 const Project
& project_
,
691 const Module
* module_
)
692 : node(node_
), project(project_
), module(module_
)
694 const XMLAttribute
* att
;
696 att
= node
.GetAttribute ( "property", true );
698 property
= att
->value
;
700 att
= node
.GetAttribute ( "value", true );
708 for ( i
= 0; i
< files
.size(); i
++ )
710 for ( i
= 0; i
< includes
.size(); i
++ )
712 for ( i
= 0; i
< defines
.size(); i
++ )
714 for ( i
= 0; i
< ifs
.size(); i
++ )
724 Property::Property ( const XMLElement
& node_
,
725 const Project
& project_
,
726 const Module
* module_
)
727 : node(node_
), project(project_
), module(module_
)
729 const XMLAttribute
* att
;
731 att
= node
.GetAttribute ( "name", true );
735 att
= node
.GetAttribute ( "value", true );
741 Property::ProcessXML()