10 FixSeparator ( const string
& s
)
13 char* p
= strchr ( &s2
[0], CBAD_SEP
);
17 p
= strchr ( p
, CBAD_SEP
);
24 const string
& location
,
26 const string
& att_value
)
28 if ( !att_value
.size() )
29 throw InvalidBuildFileException (
31 "<directory> tag has empty 'name' attribute" );
32 if ( strpbrk ( att_value
.c_str (), "/\\?*:<>|" ) )
33 throw InvalidBuildFileException (
35 "<directory> tag has invalid characters in 'name' attribute" );
38 return FixSeparator(path
+ CSEP
+ att_value
);
42 GetExtension ( const string
& filename
)
44 size_t index
= filename
.find_last_of ( '/' );
45 if (index
== string::npos
) index
= 0;
46 string tmp
= filename
.substr( index
, filename
.size() - index
);
47 size_t ext_index
= tmp
.find_last_of( '.' );
48 if (ext_index
!= string::npos
)
49 return filename
.substr ( index
+ ext_index
, filename
.size() );
54 GetDirectory ( const string
& filename
)
56 size_t index
= filename
.find_last_of ( CSEP
);
57 if ( index
== string::npos
)
60 return filename
.substr ( 0, index
);
64 NormalizeFilename ( const string
& filename
)
67 string normalizedPath
= path
.Fixup ( filename
, true );
68 string relativeNormalizedPath
= path
.RelativeFromWorkingDirectory ( normalizedPath
);
69 return FixSeparator ( relativeNormalizedPath
);
72 IfableData::~IfableData()
75 for ( i
= 0; i
< files
.size(); i
++ )
77 for ( i
= 0; i
< includes
.size(); i
++ )
79 for ( i
= 0; i
< defines
.size(); i
++ )
81 for ( i
= 0; i
< libraries
.size(); i
++ )
83 for ( i
= 0; i
< properties
.size(); i
++ )
85 for ( i
= 0; i
< ifs
.size(); i
++ )
89 void IfableData::ProcessXML ()
92 for ( i
= 0; i
< files
.size (); i
++ )
93 files
[i
]->ProcessXML ();
94 for ( i
= 0; i
< includes
.size (); i
++ )
95 includes
[i
]->ProcessXML ();
96 for ( i
= 0; i
< defines
.size (); i
++ )
97 defines
[i
]->ProcessXML ();
98 for ( i
= 0; i
< libraries
.size (); i
++ )
99 libraries
[i
]->ProcessXML ();
100 for ( i
= 0; i
< properties
.size(); i
++ )
101 properties
[i
]->ProcessXML ();
102 for ( i
= 0; i
< ifs
.size (); i
++ )
103 ifs
[i
]->ProcessXML ();
106 Module::Module ( const Project
& project
,
107 const XMLElement
& moduleNode
,
108 const string
& modulePath
)
111 importLibrary (NULL
),
117 if ( node
.name
!= "module" )
118 throw Exception ( "internal tool error: Module created with non-<module> node" );
120 path
= FixSeparator ( modulePath
);
122 const XMLAttribute
* att
= moduleNode
.GetAttribute ( "name", true );
126 att
= moduleNode
.GetAttribute ( "type", true );
128 type
= GetModuleType ( node
.location
, *att
);
130 att
= moduleNode
.GetAttribute ( "extension", false );
132 extension
= att
->value
;
134 extension
= GetDefaultModuleExtension ();
136 att
= moduleNode
.GetAttribute ( "entrypoint", false );
138 entrypoint
= att
->value
;
140 entrypoint
= GetDefaultModuleEntrypoint ();
142 att
= moduleNode
.GetAttribute ( "baseaddress", false );
144 baseaddress
= att
->value
;
146 baseaddress
= GetDefaultModuleBaseaddress ();
148 att
= moduleNode
.GetAttribute ( "mangledsymbols", false );
151 const char* p
= att
->value
.c_str();
152 if ( !stricmp ( p
, "true" ) || !stricmp ( p
, "yes" ) )
153 mangledSymbols
= true;
154 else if ( !stricmp ( p
, "false" ) || !stricmp ( p
, "no" ) )
155 mangledSymbols
= false;
158 throw InvalidAttributeValueException (
165 mangledSymbols
= false;
167 att
= moduleNode
.GetAttribute ( "host", false );
170 const char* p
= att
->value
.c_str();
171 if ( !stricmp ( p
, "true" ) || !stricmp ( p
, "yes" ) )
173 else if ( !stricmp ( p
, "false" ) || !stricmp ( p
, "no" ) )
177 throw InvalidAttributeValueException (
184 att
= moduleNode
.GetAttribute ( "prefix", false );
192 for ( i
= 0; i
< invocations
.size(); i
++ )
193 delete invocations
[i
];
194 for ( i
= 0; i
< dependencies
.size(); i
++ )
195 delete dependencies
[i
];
196 for ( i
= 0; i
< compilerFlags
.size(); i
++ )
197 delete compilerFlags
[i
];
198 for ( i
= 0; i
< linkerFlags
.size(); i
++ )
199 delete linkerFlags
[i
];
208 for ( i
= 0; i
< node
.subElements
.size(); i
++ )
209 ProcessXMLSubElement ( *node
.subElements
[i
], path
);
210 for ( i
= 0; i
< invocations
.size(); i
++ )
211 invocations
[i
]->ProcessXML ();
212 for ( i
= 0; i
< dependencies
.size(); i
++ )
213 dependencies
[i
]->ProcessXML ();
214 for ( i
= 0; i
< compilerFlags
.size(); i
++ )
215 compilerFlags
[i
]->ProcessXML();
216 for ( i
= 0; i
< linkerFlags
.size(); i
++ )
217 linkerFlags
[i
]->ProcessXML();
218 non_if_data
.ProcessXML();
224 Module::ProcessXMLSubElement ( const XMLElement
& e
,
228 bool subs_invalid
= false;
229 string
subpath ( path
);
230 if ( e
.name
== "file" && e
.value
.size () > 0 )
233 const XMLAttribute
* att
= e
.GetAttribute ( "first", false );
236 if ( !stricmp ( att
->value
.c_str(), "true" ) )
238 else if ( stricmp ( att
->value
.c_str(), "false" ) )
239 throw InvalidBuildFileException (
241 "attribute 'first' of <file> element can only be 'true' or 'false'" );
245 // check for c++ file
246 string ext
= GetExtension ( e
.value
);
247 if ( !stricmp ( ext
.c_str(), ".cpp" ) )
249 else if ( !stricmp ( ext
.c_str(), ".cc" ) )
251 else if ( !stricmp ( ext
.c_str(), ".cxx" ) )
254 File
* pFile
= new File ( FixSeparator ( path
+ CSEP
+ e
.value
), first
);
256 pIf
->data
.files
.push_back ( pFile
);
258 non_if_data
.files
.push_back ( pFile
);
261 else if ( e
.name
== "library" && e
.value
.size () )
263 Library
* pLibrary
= new Library ( e
, *this, e
.value
);
265 pIf
->data
.libraries
.push_back ( pLibrary
);
267 non_if_data
.libraries
.push_back ( pLibrary
);
270 else if ( e
.name
== "directory" )
272 const XMLAttribute
* att
= e
.GetAttribute ( "name", true );
274 subpath
= GetSubPath ( e
.location
, path
, att
->value
);
276 else if ( e
.name
== "include" )
278 Include
* include
= new Include ( project
, this, e
);
280 pIf
->data
.includes
.push_back ( include
);
282 non_if_data
.includes
.push_back ( include
);
285 else if ( e
.name
== "define" )
287 Define
* pDefine
= new Define ( project
, this, e
);
289 pIf
->data
.defines
.push_back ( pDefine
);
291 non_if_data
.defines
.push_back ( pDefine
);
294 else if ( e
.name
== "invoke" )
297 throw InvalidBuildFileException (
299 "<invoke> is not a valid sub-element of <if>" );
300 invocations
.push_back ( new Invoke ( e
, *this ) );
301 subs_invalid
= false;
303 else if ( e
.name
== "dependency" )
306 throw InvalidBuildFileException (
308 "<dependency> is not a valid sub-element of <if>" );
309 dependencies
.push_back ( new Dependency ( e
, *this ) );
312 else if ( e
.name
== "importlibrary" )
315 throw InvalidBuildFileException (
317 "<importlibrary> is not a valid sub-element of <if>" );
319 throw InvalidBuildFileException (
321 "Only one <importlibrary> is valid per module" );
322 importLibrary
= new ImportLibrary ( e
, *this );
325 else if ( e
.name
== "if" )
328 pIf
= new If ( e
, project
, this );
330 pOldIf
->data
.ifs
.push_back ( pIf
);
332 non_if_data
.ifs
.push_back ( pIf
);
333 subs_invalid
= false;
335 else if ( e
.name
== "compilerflag" )
337 compilerFlags
.push_back ( new CompilerFlag ( project
, this, e
) );
340 else if ( e
.name
== "linkerflag" )
342 linkerFlags
.push_back ( new LinkerFlag ( project
, this, e
) );
345 else if ( e
.name
== "property" )
347 throw InvalidBuildFileException (
349 "<property> is not a valid sub-element of <module>" );
351 else if ( e
.name
== "bootstrap" )
353 bootstrap
= new Bootstrap ( project
, this, e
);
356 else if ( e
.name
== "pch" )
359 throw InvalidBuildFileException (
361 "<pch> is not a valid sub-element of <if>" );
363 throw InvalidBuildFileException (
365 "Only one <pch> is valid per module" );
367 e
, *this, FixSeparator ( path
+ CSEP
+ e
.value
) );
370 if ( subs_invalid
&& e
.subElements
.size() > 0 )
371 throw InvalidBuildFileException (
373 "<%s> cannot have sub-elements",
375 for ( size_t i
= 0; i
< e
.subElements
.size (); i
++ )
376 ProcessXMLSubElement ( *e
.subElements
[i
], subpath
, pIf
);
380 Module::GetModuleType ( const string
& location
, const XMLAttribute
& attribute
)
382 if ( attribute
.value
== "buildtool" )
384 if ( attribute
.value
== "staticlibrary" )
385 return StaticLibrary
;
386 if ( attribute
.value
== "objectlibrary" )
387 return ObjectLibrary
;
388 if ( attribute
.value
== "kernel" )
390 if ( attribute
.value
== "kernelmodedll" )
391 return KernelModeDLL
;
392 if ( attribute
.value
== "kernelmodedriver" )
393 return KernelModeDriver
;
394 if ( attribute
.value
== "nativedll" )
396 if ( attribute
.value
== "nativecui" )
398 if ( attribute
.value
== "win32dll" )
400 if ( attribute
.value
== "win32cui" )
402 if ( attribute
.value
== "win32gui" )
404 if ( attribute
.value
== "bootloader" )
406 if ( attribute
.value
== "bootsector" )
408 if ( attribute
.value
== "iso" )
410 throw InvalidAttributeValueException ( location
,
416 Module::GetDefaultModuleExtension () const
435 case KernelModeDriver
:
443 throw InvalidOperationException ( __FILE__
,
448 Module::GetDefaultModuleEntrypoint () const
453 return "_NtProcessStartup";
455 return "_DriverEntry@8";
457 return "_DllMainCRTStartup@12";
459 return "_NtProcessStartup@4";
461 return "_DllMain@12";
463 return "_mainCRTStartup";
465 return "_WinMainCRTStartup";
466 case KernelModeDriver
:
467 return "_DriverEntry@8";
476 throw InvalidOperationException ( __FILE__
,
481 Module::GetDefaultModuleBaseaddress () const
499 case KernelModeDriver
:
509 throw InvalidOperationException ( __FILE__
,
514 Module::HasImportLibrary () const
516 return importLibrary
!= NULL
;
520 Module::GetTargetName () const
522 return name
+ extension
;
526 Module::GetDependencyPath () const
528 if ( HasImportLibrary () )
530 return ssprintf ( "dk%cnkm%clib%clib%s.a",
541 Module::GetBasePath () const
547 Module::GetPath () const
549 return path
+ CSEP
+ GetTargetName ();
553 Module::GetPathWithPrefix ( const string
& prefix
) const
555 return path
+ CSEP
+ prefix
+ GetTargetName ();
559 Module::GetTargets () const
561 if ( invocations
.size () > 0 )
563 string
targets ( "" );
564 for ( size_t i
= 0; i
< invocations
.size (); i
++ )
566 Invoke
& invoke
= *invocations
[i
];
567 if ( targets
.length () > 0 )
569 targets
+= invoke
.GetTargets ();
578 Module::GetInvocationTarget ( const int index
) const
580 return ssprintf ( "%s_invoke_%d",
586 Module::HasFileWithExtension (
587 const IfableData
& data
,
588 const std::string
& extension
) const
591 for ( i
= 0; i
< data
.files
.size (); i
++ )
593 File
& file
= *data
.files
[i
];
594 string file_ext
= GetExtension ( file
.name
);
595 if ( !stricmp ( file_ext
.c_str (), extension
.c_str () ) )
598 for ( i
= 0; i
< data
.ifs
.size (); i
++ )
600 if ( HasFileWithExtension ( data
.ifs
[i
]->data
, extension
) )
607 Module::InvokeModule () const
609 for ( size_t i
= 0; i
< invocations
.size (); i
++ )
611 Invoke
& invoke
= *invocations
[i
];
612 string command
= invoke
.invokeModule
->GetPath () + " " + invoke
.GetParameters ();
613 printf ( "Executing '%s'\n\n", command
.c_str () );
614 int exitcode
= system ( command
.c_str () );
616 throw InvocationFailedException ( command
,
622 File::File ( const string
& _name
, bool _first
)
623 : name(_name
), first(_first
)
633 Library::Library ( const XMLElement
& _node
,
634 const Module
& _module
,
635 const string
& _name
)
639 imported_module(_module
.project
.LocateModule(_name
))
641 if ( module
.name
== name
)
642 throw InvalidBuildFileException (
644 "module '%s' cannot link against itself",
646 if ( !imported_module
)
647 throw InvalidBuildFileException (
649 "module '%s' trying to import non-existant module '%s'",
655 Library::ProcessXML()
657 if ( !module
.project
.LocateModule ( name
) )
658 throw InvalidBuildFileException (
660 "module '%s' is trying to link against non-existant module '%s'",
666 Invoke::Invoke ( const XMLElement
& _node
,
667 const Module
& _module
)
676 const XMLAttribute
* att
= node
.GetAttribute ( "module", false );
678 invokeModule
= &module
;
681 invokeModule
= module
.project
.LocateModule ( att
->value
);
682 if ( invokeModule
== NULL
)
683 throw InvalidBuildFileException (
685 "module '%s' is trying to invoke non-existant module '%s'",
687 att
->value
.c_str() );
690 for ( size_t i
= 0; i
< node
.subElements
.size (); i
++ )
691 ProcessXMLSubElement ( *node
.subElements
[i
] );
695 Invoke::ProcessXMLSubElement ( const XMLElement
& e
)
697 bool subs_invalid
= false;
698 if ( e
.name
== "input" )
700 for ( size_t i
= 0; i
< e
.subElements
.size (); i
++ )
701 ProcessXMLSubElementInput ( *e
.subElements
[i
] );
703 else if ( e
.name
== "output" )
705 for ( size_t i
= 0; i
< e
.subElements
.size (); i
++ )
706 ProcessXMLSubElementOutput ( *e
.subElements
[i
] );
708 if ( subs_invalid
&& e
.subElements
.size() > 0 )
709 throw InvalidBuildFileException ( e
.location
,
710 "<%s> cannot have sub-elements",
715 Invoke::ProcessXMLSubElementInput ( const XMLElement
& e
)
717 bool subs_invalid
= false;
718 if ( e
.name
== "inputfile" && e
.value
.size () > 0 )
720 input
.push_back ( new InvokeFile ( e
, FixSeparator ( module
.path
+ CSEP
+ e
.value
) ) );
723 if ( subs_invalid
&& e
.subElements
.size() > 0 )
724 throw InvalidBuildFileException ( e
.location
,
725 "<%s> cannot have sub-elements",
730 Invoke::ProcessXMLSubElementOutput ( const XMLElement
& e
)
732 bool subs_invalid
= false;
733 if ( e
.name
== "outputfile" && e
.value
.size () > 0 )
735 output
.push_back ( new InvokeFile ( e
, FixSeparator ( module
.path
+ CSEP
+ e
.value
) ) );
738 if ( subs_invalid
&& e
.subElements
.size() > 0 )
739 throw InvalidBuildFileException ( e
.location
,
740 "<%s> cannot have sub-elements",
745 Invoke::GetTargets () const
747 string
targets ( "" );
748 for ( size_t i
= 0; i
< output
.size (); i
++ )
750 InvokeFile
& file
= *output
[i
];
751 if ( targets
.length () > 0 )
753 targets
+= NormalizeFilename ( file
.name
);
759 Invoke::GetParameters () const
761 string
parameters ( "" );
763 for ( i
= 0; i
< output
.size (); i
++ )
765 if ( parameters
.length () > 0)
767 InvokeFile
& invokeFile
= *output
[i
];
768 if ( invokeFile
.switches
.length () > 0 )
770 parameters
+= invokeFile
.switches
;
773 parameters
+= invokeFile
.name
;
776 for ( i
= 0; i
< input
.size (); i
++ )
778 if ( parameters
.length () > 0 )
780 InvokeFile
& invokeFile
= *input
[i
];
781 if ( invokeFile
.switches
.length () > 0 )
783 parameters
+= invokeFile
.switches
;
786 parameters
+= invokeFile
.name
;
793 InvokeFile::InvokeFile ( const XMLElement
& _node
,
794 const string
& _name
)
798 const XMLAttribute
* att
= _node
.GetAttribute ( "switches", false );
800 switches
= att
->value
;
806 InvokeFile::ProcessXML()
811 Dependency::Dependency ( const XMLElement
& _node
,
812 const Module
& _module
)
815 dependencyModule (NULL
)
820 Dependency::ProcessXML()
822 dependencyModule
= module
.project
.LocateModule ( node
.value
);
823 if ( dependencyModule
== NULL
)
824 throw InvalidBuildFileException ( node
.location
,
825 "module '%s' depend on non-existant module '%s'",
827 node
.value
.c_str() );
831 ImportLibrary::ImportLibrary ( const XMLElement
& _node
,
832 const Module
& _module
)
836 const XMLAttribute
* att
= _node
.GetAttribute ( "basename", false );
838 basename
= att
->value
;
840 basename
= module
.name
;
842 att
= _node
.GetAttribute ( "definition", true );
844 definition
= FixSeparator(att
->value
);
848 If::If ( const XMLElement
& node_
,
849 const Project
& project_
,
850 const Module
* module_
)
851 : node(node_
), project(project_
), module(module_
)
853 const XMLAttribute
* att
;
855 att
= node
.GetAttribute ( "property", true );
857 property
= att
->value
;
859 att
= node
.GetAttribute ( "value", true );
874 Property::Property ( const XMLElement
& node_
,
875 const Project
& project_
,
876 const Module
* module_
)
877 : node(node_
), project(project_
), module(module_
)
879 const XMLAttribute
* att
;
881 att
= node
.GetAttribute ( "name", true );
885 att
= node
.GetAttribute ( "value", true );
891 Property::ProcessXML()
897 const XMLElement
& node_
,
898 const Module
& module_
,
899 const string
& header_
)
900 : node(node_
), module(module_
), header(header_
)
905 PchFile::ProcessXML()