10 FixSeparator ( const string
& s
)
13 char* p
= strchr ( &s2
[0], CBAD_SEP
);
17 p
= strchr ( p
, CBAD_SEP
);
24 const string
& filename
,
25 const string
& newExtension
)
27 size_t index
= filename
.find_last_of ( '/' );
28 if ( index
== string::npos
)
30 size_t index2
= filename
.find_last_of ( '\\' );
31 if ( index2
!= string::npos
&& index2
> index
)
33 string tmp
= filename
.substr( index
/*, filename.size() - index*/ );
34 size_t ext_index
= tmp
.find_last_of( '.' );
35 if ( ext_index
!= string::npos
)
36 return filename
.substr ( 0, index
+ ext_index
) + newExtension
;
37 return filename
+ newExtension
;
42 const string
& location
,
44 const string
& att_value
)
46 if ( !att_value
.size() )
47 throw InvalidBuildFileException (
49 "<directory> tag has empty 'name' attribute" );
50 if ( strpbrk ( att_value
.c_str (), "/\\?*:<>|" ) )
51 throw InvalidBuildFileException (
53 "<directory> tag has invalid characters in 'name' attribute" );
56 return FixSeparator(path
+ CSEP
+ att_value
);
60 GetExtension ( const string
& filename
)
62 size_t index
= filename
.find_last_of ( '/' );
63 if (index
== string::npos
) index
= 0;
64 string tmp
= filename
.substr( index
, filename
.size() - index
);
65 size_t ext_index
= tmp
.find_last_of( '.' );
66 if (ext_index
!= string::npos
)
67 return filename
.substr ( index
+ ext_index
, filename
.size() );
72 GetDirectory ( const string
& filename
)
74 size_t index
= filename
.find_last_of ( CSEP
);
75 if ( index
== string::npos
)
78 return filename
.substr ( 0, index
);
82 GetFilename ( const string
& filename
)
84 size_t index
= filename
.find_last_of ( CSEP
);
85 if ( index
== string::npos
)
88 return filename
.substr ( index
+ 1, filename
.length () - index
);
92 NormalizeFilename ( const string
& filename
)
97 string normalizedPath
= path
.Fixup ( filename
, true );
98 string relativeNormalizedPath
= path
.RelativeFromWorkingDirectory ( normalizedPath
);
99 return FixSeparator ( relativeNormalizedPath
);
102 IfableData::~IfableData()
105 for ( i
= 0; i
< files
.size(); i
++ )
107 for ( i
= 0; i
< includes
.size(); i
++ )
109 for ( i
= 0; i
< defines
.size(); i
++ )
111 for ( i
= 0; i
< libraries
.size(); i
++ )
113 for ( i
= 0; i
< properties
.size(); i
++ )
114 delete properties
[i
];
115 for ( i
= 0; i
< compilerFlags
.size(); i
++ )
116 delete compilerFlags
[i
];
117 for ( i
= 0; i
< ifs
.size(); i
++ )
121 void IfableData::ProcessXML ()
124 for ( i
= 0; i
< files
.size (); i
++ )
125 files
[i
]->ProcessXML ();
126 for ( i
= 0; i
< includes
.size (); i
++ )
127 includes
[i
]->ProcessXML ();
128 for ( i
= 0; i
< defines
.size (); i
++ )
129 defines
[i
]->ProcessXML ();
130 for ( i
= 0; i
< libraries
.size (); i
++ )
131 libraries
[i
]->ProcessXML ();
132 for ( i
= 0; i
< properties
.size(); i
++ )
133 properties
[i
]->ProcessXML ();
134 for ( i
= 0; i
< compilerFlags
.size(); i
++ )
135 compilerFlags
[i
]->ProcessXML ();
136 for ( i
= 0; i
< ifs
.size (); i
++ )
137 ifs
[i
]->ProcessXML ();
140 Module::Module ( const Project
& project
,
141 const XMLElement
& moduleNode
,
142 const string
& modulePath
)
145 importLibrary (NULL
),
151 if ( node
.name
!= "module" )
152 throw InvalidOperationException ( __FILE__
,
154 "Module created with non-<module> node" );
156 xmlbuildFile
= Path::RelativeFromWorkingDirectory ( moduleNode
.xmlFile
->filename() );
158 path
= FixSeparator ( modulePath
);
160 const XMLAttribute
* att
= moduleNode
.GetAttribute ( "name", true );
164 att
= moduleNode
.GetAttribute ( "type", true );
166 type
= GetModuleType ( node
.location
, *att
);
168 att
= moduleNode
.GetAttribute ( "extension", false );
170 extension
= att
->value
;
172 extension
= GetDefaultModuleExtension ();
174 att
= moduleNode
.GetAttribute ( "entrypoint", false );
176 entrypoint
= att
->value
;
178 entrypoint
= GetDefaultModuleEntrypoint ();
180 att
= moduleNode
.GetAttribute ( "baseaddress", false );
182 baseaddress
= att
->value
;
184 baseaddress
= GetDefaultModuleBaseaddress ();
186 att
= moduleNode
.GetAttribute ( "mangledsymbols", false );
189 const char* p
= att
->value
.c_str();
190 if ( !stricmp ( p
, "true" ) || !stricmp ( p
, "yes" ) )
191 mangledSymbols
= true;
192 else if ( !stricmp ( p
, "false" ) || !stricmp ( p
, "no" ) )
193 mangledSymbols
= false;
196 throw InvalidAttributeValueException (
203 mangledSymbols
= false;
205 att
= moduleNode
.GetAttribute ( "host", false );
208 const char* p
= att
->value
.c_str();
209 if ( !stricmp ( p
, "true" ) || !stricmp ( p
, "yes" ) )
211 else if ( !stricmp ( p
, "false" ) || !stricmp ( p
, "no" ) )
215 throw InvalidAttributeValueException (
222 att
= moduleNode
.GetAttribute ( "prefix", false );
226 att
= moduleNode
.GetAttribute ( "installbase", false );
228 installBase
= att
->value
;
232 att
= moduleNode
.GetAttribute ( "installname", false );
234 installName
= att
->value
;
238 att
= moduleNode
.GetAttribute ( "usewrc", false );
240 useWRC
= att
->value
== "true";
244 att
= moduleNode
.GetAttribute ( "warnings", false );
246 enableWarnings
= att
->value
== "true";
248 enableWarnings
= false;
254 for ( i
= 0; i
< invocations
.size(); i
++ )
255 delete invocations
[i
];
256 for ( i
= 0; i
< dependencies
.size(); i
++ )
257 delete dependencies
[i
];
258 for ( i
= 0; i
< compilerFlags
.size(); i
++ )
259 delete compilerFlags
[i
];
260 for ( i
= 0; i
< linkerFlags
.size(); i
++ )
261 delete linkerFlags
[i
];
262 for ( i
= 0; i
< stubbedComponents
.size(); i
++ )
263 delete stubbedComponents
[i
];
272 for ( i
= 0; i
< node
.subElements
.size(); i
++ )
273 ProcessXMLSubElement ( *node
.subElements
[i
], path
);
274 for ( i
= 0; i
< invocations
.size(); i
++ )
275 invocations
[i
]->ProcessXML ();
276 for ( i
= 0; i
< dependencies
.size(); i
++ )
277 dependencies
[i
]->ProcessXML ();
278 for ( i
= 0; i
< compilerFlags
.size(); i
++ )
279 compilerFlags
[i
]->ProcessXML();
280 for ( i
= 0; i
< linkerFlags
.size(); i
++ )
281 linkerFlags
[i
]->ProcessXML();
282 for ( i
= 0; i
< stubbedComponents
.size(); i
++ )
283 stubbedComponents
[i
]->ProcessXML();
284 non_if_data
.ProcessXML();
290 Module::ProcessXMLSubElement ( const XMLElement
& e
,
294 bool subs_invalid
= false;
295 string
subpath ( path
);
296 if ( e
.name
== "file" && e
.value
.size () > 0 )
299 const XMLAttribute
* att
= e
.GetAttribute ( "first", false );
302 if ( !stricmp ( att
->value
.c_str(), "true" ) )
304 else if ( stricmp ( att
->value
.c_str(), "false" ) )
305 throw InvalidBuildFileException (
307 "attribute 'first' of <file> element can only be 'true' or 'false'" );
309 string switches
= "";
310 att
= e
.GetAttribute ( "switches", false );
312 switches
= att
->value
;
315 // check for c++ file
316 string ext
= GetExtension ( e
.value
);
317 if ( !stricmp ( ext
.c_str(), ".cpp" ) )
319 else if ( !stricmp ( ext
.c_str(), ".cc" ) )
321 else if ( !stricmp ( ext
.c_str(), ".cxx" ) )
324 File
* pFile
= new File ( FixSeparator ( path
+ CSEP
+ e
.value
),
329 pIf
->data
.files
.push_back ( pFile
);
331 non_if_data
.files
.push_back ( pFile
);
334 else if ( e
.name
== "library" && e
.value
.size () )
336 Library
* pLibrary
= new Library ( e
, *this, e
.value
);
338 pIf
->data
.libraries
.push_back ( pLibrary
);
340 non_if_data
.libraries
.push_back ( pLibrary
);
343 else if ( e
.name
== "directory" )
345 const XMLAttribute
* att
= e
.GetAttribute ( "name", true );
347 subpath
= GetSubPath ( e
.location
, path
, att
->value
);
349 else if ( e
.name
== "include" )
351 Include
* include
= new Include ( project
, this, e
);
353 pIf
->data
.includes
.push_back ( include
);
355 non_if_data
.includes
.push_back ( include
);
358 else if ( e
.name
== "define" )
360 Define
* pDefine
= new Define ( project
, this, e
);
362 pIf
->data
.defines
.push_back ( pDefine
);
364 non_if_data
.defines
.push_back ( pDefine
);
367 else if ( e
.name
== "invoke" )
370 throw InvalidBuildFileException (
372 "<invoke> is not a valid sub-element of <if>" );
373 invocations
.push_back ( new Invoke ( e
, *this ) );
374 subs_invalid
= false;
376 else if ( e
.name
== "dependency" )
379 throw InvalidBuildFileException (
381 "<dependency> is not a valid sub-element of <if>" );
382 dependencies
.push_back ( new Dependency ( e
, *this ) );
385 else if ( e
.name
== "importlibrary" )
388 throw InvalidBuildFileException (
390 "<importlibrary> is not a valid sub-element of <if>" );
392 throw InvalidBuildFileException (
394 "Only one <importlibrary> is valid per module" );
395 importLibrary
= new ImportLibrary ( e
, *this );
398 else if ( e
.name
== "if" )
401 pIf
= new If ( e
, project
, this );
403 pOldIf
->data
.ifs
.push_back ( pIf
);
405 non_if_data
.ifs
.push_back ( pIf
);
406 subs_invalid
= false;
408 else if ( e
.name
== "compilerflag" )
410 CompilerFlag
* pCompilerFlag
= new CompilerFlag ( project
, this, e
);
412 pIf
->data
.compilerFlags
.push_back ( pCompilerFlag
);
414 non_if_data
.compilerFlags
.push_back ( pCompilerFlag
);
417 else if ( e
.name
== "linkerflag" )
419 linkerFlags
.push_back ( new LinkerFlag ( project
, this, e
) );
422 else if ( e
.name
== "component" )
424 stubbedComponents
.push_back ( new StubbedComponent ( this, e
) );
425 subs_invalid
= false;
427 else if ( e
.name
== "property" )
429 throw InvalidBuildFileException (
431 "<property> is not a valid sub-element of <module>" );
433 else if ( e
.name
== "bootstrap" )
435 bootstrap
= new Bootstrap ( project
, this, e
);
438 else if ( e
.name
== "pch" )
441 throw InvalidBuildFileException (
443 "<pch> is not a valid sub-element of <if>" );
445 throw InvalidBuildFileException (
447 "Only one <pch> is valid per module" );
449 e
, *this, File ( FixSeparator ( path
+ CSEP
+ e
.value
), false, "", true ) );
452 if ( subs_invalid
&& e
.subElements
.size() > 0 )
453 throw InvalidBuildFileException (
455 "<%s> cannot have sub-elements",
457 for ( size_t i
= 0; i
< e
.subElements
.size (); i
++ )
458 ProcessXMLSubElement ( *e
.subElements
[i
], subpath
, pIf
);
462 Module::GetModuleType ( const string
& location
, const XMLAttribute
& attribute
)
464 if ( attribute
.value
== "buildtool" )
466 if ( attribute
.value
== "staticlibrary" )
467 return StaticLibrary
;
468 if ( attribute
.value
== "objectlibrary" )
469 return ObjectLibrary
;
470 if ( attribute
.value
== "kernel" )
472 if ( attribute
.value
== "kernelmodedll" )
473 return KernelModeDLL
;
474 if ( attribute
.value
== "kernelmodedriver" )
475 return KernelModeDriver
;
476 if ( attribute
.value
== "nativedll" )
478 if ( attribute
.value
== "nativecui" )
480 if ( attribute
.value
== "win32dll" )
482 if ( attribute
.value
== "win32cui" )
484 if ( attribute
.value
== "win32gui" )
486 if ( attribute
.value
== "bootloader" )
488 if ( attribute
.value
== "bootsector" )
490 if ( attribute
.value
== "iso" )
492 if ( attribute
.value
== "liveiso" )
494 if ( attribute
.value
== "test" )
496 if ( attribute
.value
== "rpcserver" )
498 if ( attribute
.value
== "rpcclient" )
500 throw InvalidAttributeValueException ( location
,
506 Module::GetDefaultModuleExtension () const
525 case KernelModeDriver
:
540 throw InvalidOperationException ( __FILE__
,
545 Module::GetDefaultModuleEntrypoint () const
550 return "_NtProcessStartup";
552 return "_DriverEntry@8";
554 return "_DllMainCRTStartup@12";
556 return "_NtProcessStartup@4";
558 return "_DllMain@12";
561 return "_mainCRTStartup";
563 return "_WinMainCRTStartup";
564 case KernelModeDriver
:
565 return "_DriverEntry@8";
577 throw InvalidOperationException ( __FILE__
,
582 Module::GetDefaultModuleBaseaddress () const
598 case KernelModeDriver
:
611 throw InvalidOperationException ( __FILE__
,
616 Module::HasImportLibrary () const
618 return importLibrary
!= NULL
;
622 Module::IsDLL () const
630 case KernelModeDriver
:
647 throw InvalidOperationException ( __FILE__
,
652 Module::GetTargetName () const
654 return name
+ extension
;
658 Module::GetDependencyPath () const
660 if ( HasImportLibrary () )
661 return ReplaceExtension ( GetPathWithPrefix ( "lib" ), ".a" );
667 Module::GetBasePath () const
673 Module::GetPath () const
675 if ( path
.length() > 0 )
676 return path
+ CSEP
+ GetTargetName ();
678 return GetTargetName ();
682 Module::GetPathWithPrefix ( const string
& prefix
) const
684 return path
+ CSEP
+ prefix
+ GetTargetName ();
688 Module::GetInvocationTarget ( const int index
) const
690 return ssprintf ( "%s_invoke_%d",
696 Module::HasFileWithExtension (
697 const IfableData
& data
,
698 const std::string
& extension
) const
701 for ( i
= 0; i
< data
.files
.size (); i
++ )
703 File
& file
= *data
.files
[i
];
704 string file_ext
= GetExtension ( file
.name
);
705 if ( !stricmp ( file_ext
.c_str (), extension
.c_str () ) )
708 for ( i
= 0; i
< data
.ifs
.size (); i
++ )
710 if ( HasFileWithExtension ( data
.ifs
[i
]->data
, extension
) )
717 Module::InvokeModule () const
719 for ( size_t i
= 0; i
< invocations
.size (); i
++ )
721 Invoke
& invoke
= *invocations
[i
];
722 string command
= invoke
.invokeModule
->GetPath () + " " + invoke
.GetParameters ();
723 printf ( "Executing '%s'\n\n", command
.c_str () );
724 int exitcode
= system ( command
.c_str () );
726 throw InvocationFailedException ( command
,
732 File::File ( const string
& _name
, bool _first
,
733 std::string _switches
,
734 bool _isPreCompiledHeader
)
738 isPreCompiledHeader(_isPreCompiledHeader
)
748 File::IsGeneratedFile () const
750 string extension
= GetExtension ( name
);
751 return ( extension
== ".spec" || extension
== ".SPEC" );
755 Library::Library ( const XMLElement
& _node
,
756 const Module
& _module
,
757 const string
& _name
)
761 imported_module(_module
.project
.LocateModule(_name
))
763 if ( module
.name
== name
)
764 throw InvalidBuildFileException (
766 "module '%s' cannot link against itself",
768 if ( !imported_module
)
769 throw InvalidBuildFileException (
771 "module '%s' trying to import non-existant module '%s'",
777 Library::ProcessXML()
779 if ( !module
.project
.LocateModule ( name
) )
780 throw InvalidBuildFileException (
782 "module '%s' is trying to link against non-existant module '%s'",
788 Invoke::Invoke ( const XMLElement
& _node
,
789 const Module
& _module
)
798 const XMLAttribute
* att
= node
.GetAttribute ( "module", false );
800 invokeModule
= &module
;
803 invokeModule
= module
.project
.LocateModule ( att
->value
);
804 if ( invokeModule
== NULL
)
805 throw InvalidBuildFileException (
807 "module '%s' is trying to invoke non-existant module '%s'",
809 att
->value
.c_str() );
812 for ( size_t i
= 0; i
< node
.subElements
.size (); i
++ )
813 ProcessXMLSubElement ( *node
.subElements
[i
] );
817 Invoke::ProcessXMLSubElement ( const XMLElement
& e
)
819 bool subs_invalid
= false;
820 if ( e
.name
== "input" )
822 for ( size_t i
= 0; i
< e
.subElements
.size (); i
++ )
823 ProcessXMLSubElementInput ( *e
.subElements
[i
] );
825 else if ( e
.name
== "output" )
827 for ( size_t i
= 0; i
< e
.subElements
.size (); i
++ )
828 ProcessXMLSubElementOutput ( *e
.subElements
[i
] );
830 if ( subs_invalid
&& e
.subElements
.size() > 0 )
831 throw InvalidBuildFileException ( e
.location
,
832 "<%s> cannot have sub-elements",
837 Invoke::ProcessXMLSubElementInput ( const XMLElement
& e
)
839 bool subs_invalid
= false;
840 if ( e
.name
== "inputfile" && e
.value
.size () > 0 )
842 input
.push_back ( new InvokeFile ( e
, FixSeparator ( module
.path
+ CSEP
+ e
.value
) ) );
845 if ( subs_invalid
&& e
.subElements
.size() > 0 )
846 throw InvalidBuildFileException ( e
.location
,
847 "<%s> cannot have sub-elements",
852 Invoke::ProcessXMLSubElementOutput ( const XMLElement
& e
)
854 bool subs_invalid
= false;
855 if ( e
.name
== "outputfile" && e
.value
.size () > 0 )
857 output
.push_back ( new InvokeFile ( e
, FixSeparator ( module
.path
+ CSEP
+ e
.value
) ) );
860 if ( subs_invalid
&& e
.subElements
.size() > 0 )
861 throw InvalidBuildFileException (
863 "<%s> cannot have sub-elements",
868 Invoke::GetTargets ( string_list
& targets
) const
870 for ( size_t i
= 0; i
< output
.size (); i
++ )
872 InvokeFile
& file
= *output
[i
];
873 targets
.push_back ( NormalizeFilename ( file
.name
) );
878 Invoke::GetParameters () const
880 string
parameters ( "" );
882 for ( i
= 0; i
< output
.size (); i
++ )
884 if ( parameters
.length () > 0)
886 InvokeFile
& invokeFile
= *output
[i
];
887 if ( invokeFile
.switches
.length () > 0 )
889 parameters
+= invokeFile
.switches
+ " ";
891 parameters
+= invokeFile
.name
;
894 for ( i
= 0; i
< input
.size (); i
++ )
896 if ( parameters
.length () > 0 )
898 InvokeFile
& invokeFile
= *input
[i
];
899 if ( invokeFile
.switches
.length () > 0 )
901 parameters
+= invokeFile
.switches
;
904 parameters
+= invokeFile
.name
;
911 InvokeFile::InvokeFile ( const XMLElement
& _node
,
912 const string
& _name
)
916 const XMLAttribute
* att
= _node
.GetAttribute ( "switches", false );
918 switches
= att
->value
;
924 InvokeFile::ProcessXML()
929 Dependency::Dependency ( const XMLElement
& _node
,
930 const Module
& _module
)
933 dependencyModule (NULL
)
938 Dependency::ProcessXML()
940 dependencyModule
= module
.project
.LocateModule ( node
.value
);
941 if ( dependencyModule
== NULL
)
942 throw InvalidBuildFileException ( node
.location
,
943 "module '%s' depend on non-existant module '%s'",
945 node
.value
.c_str() );
949 ImportLibrary::ImportLibrary ( const XMLElement
& _node
,
950 const Module
& _module
)
954 const XMLAttribute
* att
= _node
.GetAttribute ( "basename", false );
956 basename
= att
->value
;
958 basename
= module
.name
;
960 att
= _node
.GetAttribute ( "definition", true );
962 definition
= FixSeparator(att
->value
);
966 If::If ( const XMLElement
& node_
,
967 const Project
& project_
,
968 const Module
* module_
)
969 : node(node_
), project(project_
), module(module_
)
971 const XMLAttribute
* att
;
973 att
= node
.GetAttribute ( "property", true );
975 property
= att
->value
;
977 att
= node
.GetAttribute ( "value", true );
992 Property::Property ( const XMLElement
& node_
,
993 const Project
& project_
,
994 const Module
* module_
)
995 : node(node_
), project(project_
), module(module_
)
997 const XMLAttribute
* att
;
999 att
= node
.GetAttribute ( "name", true );
1003 att
= node
.GetAttribute ( "value", true );
1009 Property::ProcessXML()
1015 const XMLElement
& node_
,
1016 const Module
& module_
,
1018 : node(node_
), module(module_
), file(file_
)
1023 PchFile::ProcessXML()