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
)
97 if ( node
.name
!= "module" )
98 throw Exception ( "internal tool error: Module created with non-<module> node" );
100 path
= FixSeparator ( modulePath
);
102 const XMLAttribute
* att
= moduleNode
.GetAttribute ( "name", true );
106 att
= moduleNode
.GetAttribute ( "type", true );
108 type
= GetModuleType ( node
.location
, *att
);
110 att
= moduleNode
.GetAttribute ( "extension", false );
112 extension
= att
->value
;
114 extension
= GetDefaultModuleExtension ();
116 att
= moduleNode
.GetAttribute ( "entrypoint", false );
118 entrypoint
= att
->value
;
120 entrypoint
= GetDefaultModuleEntrypoint ();
122 att
= moduleNode
.GetAttribute ( "baseaddress", false );
124 baseaddress
= att
->value
;
126 baseaddress
= GetDefaultModuleBaseaddress ();
128 att
= moduleNode
.GetAttribute ( "mangledsymbols", false );
130 mangledSymbols
= att
->value
!= "false";
132 mangledSymbols
= false;
138 for ( i
= 0; i
< invocations
.size(); i
++ )
139 delete invocations
[i
];
140 for ( i
= 0; i
< dependencies
.size(); i
++ )
141 delete dependencies
[i
];
142 for ( i
= 0; i
< compilerFlags
.size(); i
++ )
143 delete compilerFlags
[i
];
144 for ( i
= 0; i
< linkerFlags
.size(); i
++ )
145 delete linkerFlags
[i
];
154 for ( i
= 0; i
< node
.subElements
.size(); i
++ )
155 ProcessXMLSubElement ( *node
.subElements
[i
], path
);
156 for ( i
= 0; i
< invocations
.size(); i
++ )
157 invocations
[i
]->ProcessXML ();
158 for ( i
= 0; i
< dependencies
.size(); i
++ )
159 dependencies
[i
]->ProcessXML ();
160 for ( i
= 0; i
< compilerFlags
.size(); i
++ )
161 compilerFlags
[i
]->ProcessXML();
162 for ( i
= 0; i
< linkerFlags
.size(); i
++ )
163 linkerFlags
[i
]->ProcessXML();
164 non_if_data
.ProcessXML();
170 Module::ProcessXMLSubElement ( const XMLElement
& e
,
174 bool subs_invalid
= false;
175 string
subpath ( path
);
176 if ( e
.name
== "file" && e
.value
.size () > 0 )
179 const XMLAttribute
* att
= e
.GetAttribute ( "first", false );
182 if ( !stricmp ( att
->value
.c_str(), "true" ) )
184 else if ( stricmp ( att
->value
.c_str(), "false" ) )
185 throw InvalidBuildFileException (
187 "attribute 'first' of <file> element can only be 'true' or 'false'" );
191 // check for c++ file
192 string ext
= GetExtension ( e
.value
);
193 if ( !stricmp ( ext
.c_str(), ".cpp" ) )
195 else if ( !stricmp ( ext
.c_str(), ".cc" ) )
197 else if ( !stricmp ( ext
.c_str(), ".cxx" ) )
200 File
* pFile
= new File ( FixSeparator ( path
+ CSEP
+ e
.value
), first
);
202 pIf
->data
.files
.push_back ( pFile
);
204 non_if_data
.files
.push_back ( pFile
);
207 else if ( e
.name
== "library" && e
.value
.size () )
209 Library
* pLibrary
= new Library ( e
, *this, e
.value
);
211 pIf
->data
.libraries
.push_back ( pLibrary
);
213 non_if_data
.libraries
.push_back ( pLibrary
);
216 else if ( e
.name
== "directory" )
218 const XMLAttribute
* att
= e
.GetAttribute ( "name", true );
220 subpath
= FixSeparator ( path
+ CSEP
+ att
->value
);
222 else if ( e
.name
== "include" )
224 Include
* include
= new Include ( project
, this, e
);
226 pIf
->data
.includes
.push_back ( include
);
228 non_if_data
.includes
.push_back ( include
);
231 else if ( e
.name
== "define" )
233 Define
* pDefine
= new Define ( project
, this, e
);
235 pIf
->data
.defines
.push_back ( pDefine
);
237 non_if_data
.defines
.push_back ( pDefine
);
240 else if ( e
.name
== "invoke" )
243 throw InvalidBuildFileException (
245 "<invoke> is not a valid sub-element of <if>" );
246 invocations
.push_back ( new Invoke ( e
, *this ) );
247 subs_invalid
= false;
249 else if ( e
.name
== "dependency" )
252 throw InvalidBuildFileException (
254 "<dependency> is not a valid sub-element of <if>" );
255 dependencies
.push_back ( new Dependency ( e
, *this ) );
258 else if ( e
.name
== "importlibrary" )
261 throw InvalidBuildFileException (
263 "<importlibrary> is not a valid sub-element of <if>" );
265 throw InvalidBuildFileException (
267 "Only one <importlibrary> is valid per module" );
268 importLibrary
= new ImportLibrary ( e
, *this );
271 else if ( e
.name
== "if" )
274 pIf
= new If ( e
, project
, this );
276 pOldIf
->data
.ifs
.push_back ( pIf
);
278 non_if_data
.ifs
.push_back ( pIf
);
279 subs_invalid
= false;
281 else if ( e
.name
== "compilerflag" )
283 compilerFlags
.push_back ( new CompilerFlag ( project
, this, e
) );
286 else if ( e
.name
== "linkerflag" )
288 linkerFlags
.push_back ( new LinkerFlag ( project
, this, e
) );
291 else if ( e
.name
== "property" )
293 throw InvalidBuildFileException (
295 "<property> is not a valid sub-element of <module>" );
297 else if ( e
.name
== "bootstrap" )
299 bootstrap
= new Bootstrap ( project
, this, e
);
302 else if ( e
.name
== "pch" )
305 throw InvalidBuildFileException (
307 "<pch> is not a valid sub-element of <if>" );
309 throw InvalidBuildFileException (
311 "Only one <pch> is valid per module" );
313 e
, *this, FixSeparator ( path
+ CSEP
+ e
.value
) );
316 if ( subs_invalid
&& e
.subElements
.size() > 0 )
317 throw InvalidBuildFileException (
319 "<%s> cannot have sub-elements",
321 for ( size_t i
= 0; i
< e
.subElements
.size (); i
++ )
322 ProcessXMLSubElement ( *e
.subElements
[i
], subpath
, pIf
);
326 Module::GetModuleType ( const string
& location
, const XMLAttribute
& attribute
)
328 if ( attribute
.value
== "buildtool" )
330 if ( attribute
.value
== "staticlibrary" )
331 return StaticLibrary
;
332 if ( attribute
.value
== "objectlibrary" )
333 return ObjectLibrary
;
334 if ( attribute
.value
== "kernel" )
336 if ( attribute
.value
== "kernelmodedll" )
337 return KernelModeDLL
;
338 if ( attribute
.value
== "kernelmodedriver" )
339 return KernelModeDriver
;
340 if ( attribute
.value
== "nativedll" )
342 if ( attribute
.value
== "nativecui" )
344 if ( attribute
.value
== "win32dll" )
346 if ( attribute
.value
== "win32cui" )
348 if ( attribute
.value
== "win32gui" )
350 if ( attribute
.value
== "bootloader" )
352 if ( attribute
.value
== "bootsector" )
354 if ( attribute
.value
== "iso" )
356 throw InvalidAttributeValueException ( location
,
362 Module::GetDefaultModuleExtension () const
381 case KernelModeDriver
:
389 throw InvalidOperationException ( __FILE__
,
394 Module::GetDefaultModuleEntrypoint () const
399 return "_NtProcessStartup";
401 return "_DriverEntry@8";
403 return "_DllMainCRTStartup@12";
405 return "_NtProcessStartup@4";
407 return "_DllMain@12";
409 return "_mainCRTStartup";
411 return "_WinMainCRTStartup";
412 case KernelModeDriver
:
413 return "_DriverEntry@8";
422 throw InvalidOperationException ( __FILE__
,
427 Module::GetDefaultModuleBaseaddress () const
445 case KernelModeDriver
:
455 throw InvalidOperationException ( __FILE__
,
460 Module::HasImportLibrary () const
462 return importLibrary
!= NULL
;
466 Module::GetTargetName () const
468 return name
+ extension
;
472 Module::GetDependencyPath () const
474 if ( HasImportLibrary () )
476 return ssprintf ( "dk%snkm%slib%slib%s.a",
487 Module::GetBasePath () const
493 Module::GetPath () const
495 return path
+ CSEP
+ GetTargetName ();
499 Module::GetPathWithPrefix ( const string
& prefix
) const
501 return path
+ CSEP
+ prefix
+ GetTargetName ();
505 Module::GetTargets () const
507 if ( invocations
.size () > 0 )
509 string
targets ( "" );
510 for ( size_t i
= 0; i
< invocations
.size (); i
++ )
512 Invoke
& invoke
= *invocations
[i
];
513 if ( targets
.length () > 0 )
515 targets
+= invoke
.GetTargets ();
524 Module::GetInvocationTarget ( const int index
) const
526 return ssprintf ( "%s_invoke_%d",
532 Module::HasFileWithExtension (
533 const IfableData
& data
,
534 const std::string
& extension
) const
537 for ( i
= 0; i
< data
.files
.size (); i
++ )
539 File
& file
= *data
.files
[i
];
540 string file_ext
= GetExtension ( file
.name
);
541 if ( !stricmp ( file_ext
.c_str (), extension
.c_str () ) )
544 for ( i
= 0; i
< data
.ifs
.size (); i
++ )
546 if ( HasFileWithExtension ( data
.ifs
[i
]->data
, extension
) )
553 Module::InvokeModule () const
555 for ( size_t i
= 0; i
< invocations
.size (); i
++ )
557 Invoke
& invoke
= *invocations
[i
];
558 string command
= invoke
.invokeModule
->GetPath () + " " + invoke
.GetParameters ();
559 printf ( "Executing '%s'\n\n", command
.c_str () );
560 int exitcode
= system ( command
.c_str () );
562 throw InvocationFailedException ( command
,
568 File::File ( const string
& _name
, bool _first
)
569 : name(_name
), first(_first
)
579 Library::Library ( const XMLElement
& _node
,
580 const Module
& _module
,
581 const string
& _name
)
585 imported_module(_module
.project
.LocateModule(_name
))
587 if ( module
.name
== name
)
588 throw InvalidBuildFileException (
590 "module '%s' cannot link against itself",
592 if ( !imported_module
)
593 throw InvalidBuildFileException (
595 "module '%s' trying to import non-existant module '%s'",
601 Library::ProcessXML()
603 if ( !module
.project
.LocateModule ( name
) )
604 throw InvalidBuildFileException (
606 "module '%s' is trying to link against non-existant module '%s'",
612 Invoke::Invoke ( const XMLElement
& _node
,
613 const Module
& _module
)
622 const XMLAttribute
* att
= node
.GetAttribute ( "module", false );
624 invokeModule
= &module
;
627 invokeModule
= module
.project
.LocateModule ( att
->value
);
628 if ( invokeModule
== NULL
)
629 throw InvalidBuildFileException (
631 "module '%s' is trying to invoke non-existant module '%s'",
633 att
->value
.c_str() );
636 for ( size_t i
= 0; i
< node
.subElements
.size (); i
++ )
637 ProcessXMLSubElement ( *node
.subElements
[i
] );
641 Invoke::ProcessXMLSubElement ( const XMLElement
& e
)
643 bool subs_invalid
= false;
644 if ( e
.name
== "input" )
646 for ( size_t i
= 0; i
< e
.subElements
.size (); i
++ )
647 ProcessXMLSubElementInput ( *e
.subElements
[i
] );
649 else if ( e
.name
== "output" )
651 for ( size_t i
= 0; i
< e
.subElements
.size (); i
++ )
652 ProcessXMLSubElementOutput ( *e
.subElements
[i
] );
654 if ( subs_invalid
&& e
.subElements
.size() > 0 )
655 throw InvalidBuildFileException ( e
.location
,
656 "<%s> cannot have sub-elements",
661 Invoke::ProcessXMLSubElementInput ( const XMLElement
& e
)
663 bool subs_invalid
= false;
664 if ( e
.name
== "inputfile" && e
.value
.size () > 0 )
666 input
.push_back ( new InvokeFile ( e
, FixSeparator ( module
.path
+ CSEP
+ e
.value
) ) );
669 if ( subs_invalid
&& e
.subElements
.size() > 0 )
670 throw InvalidBuildFileException ( e
.location
,
671 "<%s> cannot have sub-elements",
676 Invoke::ProcessXMLSubElementOutput ( const XMLElement
& e
)
678 bool subs_invalid
= false;
679 if ( e
.name
== "outputfile" && e
.value
.size () > 0 )
681 output
.push_back ( new InvokeFile ( e
, FixSeparator ( module
.path
+ CSEP
+ e
.value
) ) );
684 if ( subs_invalid
&& e
.subElements
.size() > 0 )
685 throw InvalidBuildFileException ( e
.location
,
686 "<%s> cannot have sub-elements",
691 Invoke::GetTargets () const
693 string
targets ( "" );
694 for ( size_t i
= 0; i
< output
.size (); i
++ )
696 InvokeFile
& file
= *output
[i
];
697 if ( targets
.length () > 0 )
699 targets
+= NormalizeFilename ( file
.name
);
705 Invoke::GetParameters () const
707 string
parameters ( "" );
709 for ( i
= 0; i
< output
.size (); i
++ )
711 if ( parameters
.length () > 0)
713 InvokeFile
& invokeFile
= *output
[i
];
714 if ( invokeFile
.switches
.length () > 0 )
716 parameters
+= invokeFile
.switches
;
719 parameters
+= invokeFile
.name
;
722 for ( i
= 0; i
< input
.size (); i
++ )
724 if ( parameters
.length () > 0 )
726 InvokeFile
& invokeFile
= *input
[i
];
727 if ( invokeFile
.switches
.length () > 0 )
729 parameters
+= invokeFile
.switches
;
732 parameters
+= invokeFile
.name
;
739 InvokeFile::InvokeFile ( const XMLElement
& _node
,
740 const string
& _name
)
744 const XMLAttribute
* att
= _node
.GetAttribute ( "switches", false );
746 switches
= att
->value
;
752 InvokeFile::ProcessXML()
757 Dependency::Dependency ( const XMLElement
& _node
,
758 const Module
& _module
)
761 dependencyModule (NULL
)
766 Dependency::ProcessXML()
768 dependencyModule
= module
.project
.LocateModule ( node
.value
);
769 if ( dependencyModule
== NULL
)
770 throw InvalidBuildFileException ( node
.location
,
771 "module '%s' depend on non-existant module '%s'",
773 node
.value
.c_str() );
777 ImportLibrary::ImportLibrary ( const XMLElement
& _node
,
778 const Module
& _module
)
782 const XMLAttribute
* att
= _node
.GetAttribute ( "basename", false );
784 basename
= att
->value
;
786 basename
= module
.name
;
788 att
= _node
.GetAttribute ( "definition", true );
790 definition
= FixSeparator(att
->value
);
794 If::If ( const XMLElement
& node_
,
795 const Project
& project_
,
796 const Module
* module_
)
797 : node(node_
), project(project_
), module(module_
)
799 const XMLAttribute
* att
;
801 att
= node
.GetAttribute ( "property", true );
803 property
= att
->value
;
805 att
= node
.GetAttribute ( "value", true );
820 Property::Property ( const XMLElement
& node_
,
821 const Project
& project_
,
822 const Module
* module_
)
823 : node(node_
), project(project_
), module(module_
)
825 const XMLAttribute
* att
;
827 att
= node
.GetAttribute ( "name", true );
831 att
= node
.GetAttribute ( "value", true );
837 Property::ProcessXML()
843 const XMLElement
& node_
,
844 const Module
& module_
,
845 const string
& header_
)
846 : node(node_
), module(module_
), header(header_
)
851 PchFile::ProcessXML()