2 * Copyright (C) 2005 Casper S. Hornstrup
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 Right ( const string
& s
, size_t n
)
31 return string ( &s
[s
.size()-n
] );
35 Replace ( const string
& s
, const string
& find
, const string
& with
)
38 const char* p
= s
.c_str();
41 const char* p2
= strstr ( p
, find
.c_str() );
45 ret
+= string ( p
, p2
-p
);
55 ChangeSeparator ( const string
& s
,
56 const char fromSeparator
,
57 const char toSeparator
)
60 char* p
= strchr ( &s2
[0], fromSeparator
);
64 p
= strchr ( p
, fromSeparator
);
70 FixSeparator ( const string
& s
)
72 return ChangeSeparator ( s
, cBadSep
, cSep
);
76 FixSeparatorForSystemCommand ( const string
& s
)
79 char* p
= strchr ( &s2
[0], DEF_CBAD_SEP
);
83 p
= strchr ( p
, DEF_CBAD_SEP
);
89 DosSeparator ( const string
& s
)
92 char* p
= strchr ( &s2
[0], '/' );
96 p
= strchr ( p
, '/' );
103 const string
& filename
,
104 const string
& newExtension
)
106 size_t index
= filename
.find_last_of ( '/' );
107 if ( index
== string::npos
)
109 size_t index2
= filename
.find_last_of ( '\\' );
110 if ( index2
!= string::npos
&& index2
> index
)
112 string tmp
= filename
.substr( index
/*, filename.size() - index*/ );
113 size_t ext_index
= tmp
.find_last_of( '.' );
114 if ( ext_index
!= string::npos
)
115 return filename
.substr ( 0, index
+ ext_index
) + newExtension
;
116 return filename
+ newExtension
;
121 const Project
& project
,
122 const string
& location
,
124 const string
& att_value
)
126 if ( !att_value
.size() )
127 throw XMLInvalidBuildFileException (
129 "<directory> tag has empty 'name' attribute" );
130 if ( strpbrk ( att_value
.c_str (), "/\\?*:<>|" ) )
131 throw XMLInvalidBuildFileException (
133 "<directory> tag has invalid characters in 'name' attribute" );
137 return FixSeparator(path
+ cSep
+ att_value
);
141 GetExtension ( const string
& filename
)
143 size_t index
= filename
.find_last_of ( '/' );
144 if (index
== string::npos
) index
= 0;
145 string tmp
= filename
.substr( index
, filename
.size() - index
);
146 size_t ext_index
= tmp
.find_last_of( '.' );
147 if (ext_index
!= string::npos
)
148 return filename
.substr ( index
+ ext_index
, filename
.size() );
153 GetDirectory ( const string
& filename
)
155 size_t index
= filename
.find_last_of ( cSep
);
156 if ( index
== string::npos
)
159 return filename
.substr ( 0, index
);
163 GetFilename ( const string
& filename
)
165 size_t index
= filename
.find_last_of ( cSep
);
166 if ( index
== string::npos
)
169 return filename
.substr ( index
+ 1, filename
.length () - index
);
173 NormalizeFilename ( const string
& filename
)
175 if ( filename
== "" )
178 string normalizedPath
= path
.Fixup ( filename
, true );
179 string relativeNormalizedPath
= path
.RelativeFromWorkingDirectory ( normalizedPath
);
180 return FixSeparator ( relativeNormalizedPath
);
184 GetBooleanValue ( const string
& value
)
193 ToLower ( string filename
)
195 for ( size_t i
= 1; i
< filename
.length (); i
++ )
196 filename
[i
] = tolower ( filename
[i
] );
200 void IfableData::ExtractModules( std::vector
<Module
*> &modules
)
203 for ( i
= 0; i
< this->modules
.size (); i
++ )
204 modules
.push_back(this->modules
[i
]);
207 IfableData::~IfableData()
210 for ( i
= 0; i
< includes
.size (); i
++ )
212 for ( i
= 0; i
< defines
.size (); i
++ )
214 for ( i
= 0; i
< libraries
.size (); i
++ )
216 for ( i
= 0; i
< properties
.size (); i
++ )
217 delete properties
[i
];
218 for ( i
= 0; i
< compilerFlags
.size (); i
++ )
219 delete compilerFlags
[i
];
220 for ( i
= 0; i
< modules
.size(); i
++ )
222 for ( i
= 0; i
< ifs
.size (); i
++ )
224 for ( i
= 0; i
< compilationUnits
.size (); i
++ )
225 delete compilationUnits
[i
];
228 void IfableData::ProcessXML ()
231 for ( i
= 0; i
< includes
.size (); i
++ )
232 includes
[i
]->ProcessXML ();
233 for ( i
= 0; i
< defines
.size (); i
++ )
234 defines
[i
]->ProcessXML ();
235 for ( i
= 0; i
< libraries
.size (); i
++ )
236 libraries
[i
]->ProcessXML ();
237 for ( i
= 0; i
< properties
.size(); i
++ )
238 properties
[i
]->ProcessXML ();
239 for ( i
= 0; i
< compilerFlags
.size(); i
++ )
240 compilerFlags
[i
]->ProcessXML ();
241 for ( i
= 0; i
< ifs
.size (); i
++ )
242 ifs
[i
]->ProcessXML ();
243 for ( i
= 0; i
< compilationUnits
.size (); i
++ )
244 compilationUnits
[i
]->ProcessXML ();
247 Module::Module ( const Project
& project
,
248 const XMLElement
& moduleNode
,
249 const string
& modulePath
)
252 importLibrary (NULL
),
260 if ( node
.name
!= "module" )
261 throw InvalidOperationException ( __FILE__
,
263 "Module created with non-<module> node" );
265 xmlbuildFile
= Path::RelativeFromWorkingDirectory ( moduleNode
.xmlFile
->filename () );
267 path
= FixSeparator ( modulePath
);
271 const XMLAttribute
* att
= moduleNode
.GetAttribute ( "if", false );
273 enabled
= GetBooleanValue ( project
.ResolveProperties ( att
->value
) );
275 att
= moduleNode
.GetAttribute ( "ifnot", false );
277 enabled
= !GetBooleanValue ( project
.ResolveProperties ( att
->value
) );
279 att
= moduleNode
.GetAttribute ( "name", true );
283 att
= moduleNode
.GetAttribute ( "type", true );
285 type
= GetModuleType ( node
.location
, *att
);
287 att
= moduleNode
.GetAttribute ( "extension", false );
289 extension
= att
->value
;
291 extension
= GetDefaultModuleExtension ();
293 att
= moduleNode
.GetAttribute ( "unicode", false );
296 const char* p
= att
->value
.c_str();
297 if ( !stricmp ( p
, "true" ) || !stricmp ( p
, "yes" ) )
299 else if ( !stricmp ( p
, "false" ) || !stricmp ( p
, "no" ) )
303 throw InvalidAttributeValueException (
312 att
= moduleNode
.GetAttribute ( "stdlib", false );
315 const char* p
= att
->value
.c_str();
316 if ( !stricmp ( p
, "host" ) )
317 useHostStdlib
= true;
318 else if ( !stricmp ( p
, "default" ) )
319 useHostStdlib
= false;
322 throw InvalidAttributeValueException (
329 useHostStdlib
= false;
333 // Always define UNICODE and _UNICODE
334 Define
* pDefine
= new Define ( project
, this, "UNICODE" );
335 non_if_data
.defines
.push_back ( pDefine
);
337 pDefine
= new Define ( project
, this, "_UNICODE" );
338 non_if_data
.defines
.push_back ( pDefine
);
341 att
= moduleNode
.GetAttribute ( "entrypoint", false );
344 if ( att
->value
== "" )
346 throw InvalidAttributeValueException (
352 entrypoint
= att
->value
;
353 isDefaultEntryPoint
= false;
357 entrypoint
= GetDefaultModuleEntrypoint ();
358 isDefaultEntryPoint
= true;
361 att
= moduleNode
.GetAttribute ( "baseaddress", false );
363 baseaddress
= att
->value
;
365 baseaddress
= GetDefaultModuleBaseaddress ();
367 att
= moduleNode
.GetAttribute ( "mangledsymbols", false );
370 const char* p
= att
->value
.c_str();
371 if ( !stricmp ( p
, "true" ) || !stricmp ( p
, "yes" ) )
372 mangledSymbols
= true;
373 else if ( !stricmp ( p
, "false" ) || !stricmp ( p
, "no" ) )
374 mangledSymbols
= false;
377 throw InvalidAttributeValueException (
384 mangledSymbols
= false;
386 att
= moduleNode
.GetAttribute ( "underscoresymbols", false );
388 underscoreSymbols
= att
->value
== "true";
390 underscoreSymbols
= false;
392 att
= moduleNode
.GetAttribute ( "host", false );
395 const char* p
= att
->value
.c_str();
396 if ( !stricmp ( p
, "true" ) || !stricmp ( p
, "yes" ) )
398 else if ( !stricmp ( p
, "false" ) || !stricmp ( p
, "no" ) )
402 throw InvalidAttributeValueException (
409 att
= moduleNode
.GetAttribute ( "isstartuplib", false );
412 const char* p
= att
->value
.c_str();
413 if ( !stricmp ( p
, "true" ) || !stricmp ( p
, "yes" ) )
415 else if ( !stricmp ( p
, "false" ) || !stricmp ( p
, "no" ) )
416 isStartupLib
= false;
419 throw InvalidAttributeValueException (
426 isStartupLib
= false;
428 att
= moduleNode
.GetAttribute ( "prefix", false );
432 att
= moduleNode
.GetAttribute ( "installbase", false );
434 installBase
= att
->value
;
438 att
= moduleNode
.GetAttribute ( "installname", false );
440 installName
= att
->value
;
444 att
= moduleNode
.GetAttribute ( "usewrc", false );
446 useWRC
= att
->value
== "true";
450 att
= moduleNode
.GetAttribute ( "allowwarnings", false );
453 att
= moduleNode
.GetAttribute ( "warnings", false );
456 printf ( "%s: WARNING: 'warnings' attribute of <module> is deprecated, use 'allowwarnings' instead\n",
457 moduleNode
.location
.c_str() );
461 allowWarnings
= att
->value
== "true";
463 allowWarnings
= false;
465 att
= moduleNode
.GetAttribute ( "aliasof", false );
466 if ( type
== Alias
&& att
!= NULL
)
467 aliasedModuleName
= att
->value
;
469 aliasedModuleName
= "";
471 if ( type
== BootProgram
)
473 att
= moduleNode
.GetAttribute ( "payload", true );
474 payload
= att
->value
;
481 for ( i
= 0; i
< invocations
.size(); i
++ )
482 delete invocations
[i
];
483 for ( i
= 0; i
< dependencies
.size(); i
++ )
484 delete dependencies
[i
];
485 for ( i
= 0; i
< compilerFlags
.size(); i
++ )
486 delete compilerFlags
[i
];
487 for ( i
= 0; i
< linkerFlags
.size(); i
++ )
488 delete linkerFlags
[i
];
489 for ( i
= 0; i
< stubbedComponents
.size(); i
++ )
490 delete stubbedComponents
[i
];
502 if ( aliasedModuleName
== name
)
504 throw XMLInvalidBuildFileException (
506 "module '%s' cannot link against itself",
509 const Module
* m
= project
.LocateModule ( aliasedModuleName
);
512 throw XMLInvalidBuildFileException (
514 "module '%s' trying to alias non-existant module '%s'",
516 aliasedModuleName
.c_str() );
521 for ( i
= 0; i
< node
.subElements
.size(); i
++ )
523 ParseContext parseContext
;
524 ProcessXMLSubElement ( *node
.subElements
[i
], path
, "", parseContext
);
526 for ( i
= 0; i
< invocations
.size(); i
++ )
527 invocations
[i
]->ProcessXML ();
528 for ( i
= 0; i
< dependencies
.size(); i
++ )
529 dependencies
[i
]->ProcessXML ();
530 for ( i
= 0; i
< compilerFlags
.size(); i
++ )
531 compilerFlags
[i
]->ProcessXML();
532 for ( i
= 0; i
< linkerFlags
.size(); i
++ )
533 linkerFlags
[i
]->ProcessXML();
534 for ( i
= 0; i
< stubbedComponents
.size(); i
++ )
535 stubbedComponents
[i
]->ProcessXML();
536 non_if_data
.ProcessXML();
538 linkerScript
->ProcessXML();
542 autoRegister
->ProcessXML();
546 Module::ProcessXMLSubElement ( const XMLElement
& e
,
548 const string
& path_prefix
,
549 ParseContext
& parseContext
)
551 If
* pOldIf
= parseContext
.ifData
;
552 CompilationUnit
* pOldCompilationUnit
= parseContext
.compilationUnit
;
553 bool subs_invalid
= false;
554 string
subpath ( path
);
555 string
subpath_prefix ( "" );
556 if ( e
.name
== "file" && e
.value
.size () > 0 )
559 const XMLAttribute
* att
= e
.GetAttribute ( "first", false );
562 if ( !stricmp ( att
->value
.c_str(), "true" ) )
564 else if ( stricmp ( att
->value
.c_str(), "false" ) )
566 throw XMLInvalidBuildFileException (
568 "attribute 'first' of <file> element can only be 'true' or 'false'" );
571 string switches
= "";
572 att
= e
.GetAttribute ( "switches", false );
574 switches
= att
->value
;
577 // check for c++ file
578 string ext
= GetExtension ( e
.value
);
579 if ( !stricmp ( ext
.c_str(), ".cpp" ) )
581 else if ( !stricmp ( ext
.c_str(), ".cc" ) )
583 else if ( !stricmp ( ext
.c_str(), ".cxx" ) )
586 File
* pFile
= new File ( FixSeparator ( path
+ cSep
+ e
.value
),
591 if ( parseContext
.compilationUnit
)
592 parseContext
.compilationUnit
->files
.push_back ( pFile
);
595 CompilationUnit
* pCompilationUnit
= new CompilationUnit ( pFile
);
596 if ( parseContext
.ifData
)
597 parseContext
.ifData
->data
.compilationUnits
.push_back ( pCompilationUnit
);
600 string ext
= GetExtension ( e
.value
);
601 if ( !stricmp ( ext
.c_str(), ".idl" ) )
602 non_if_data
.compilationUnits
.insert ( non_if_data
.compilationUnits
.begin(), pCompilationUnit
);
604 non_if_data
.compilationUnits
.push_back ( pCompilationUnit
);
607 if ( parseContext
.ifData
)
608 parseContext
.ifData
->data
.files
.push_back ( pFile
);
610 non_if_data
.files
.push_back ( pFile
);
613 else if ( e
.name
== "library" && e
.value
.size () )
615 Library
* pLibrary
= new Library ( e
, *this, e
.value
);
616 if ( parseContext
.ifData
)
617 parseContext
.ifData
->data
.libraries
.push_back ( pLibrary
);
619 non_if_data
.libraries
.push_back ( pLibrary
);
622 else if ( e
.name
== "directory" )
624 const XMLAttribute
* att
= e
.GetAttribute ( "name", true );
625 const XMLAttribute
* root
= e
.GetAttribute ( "root", false );
629 if ( root
->value
== "intermediate" )
630 subpath_prefix
= "$(INTERMEDIATE)";
631 else if ( root
->value
== "output" )
632 subpath_prefix
= "$(OUTPUT)";
635 throw InvalidAttributeValueException (
641 subpath
= GetSubPath ( this->project
, e
.location
, path
, att
->value
);
643 else if ( e
.name
== "include" )
645 Include
* include
= new Include ( project
, this, &e
);
646 if ( parseContext
.ifData
)
647 parseContext
.ifData
->data
.includes
.push_back ( include
);
649 non_if_data
.includes
.push_back ( include
);
652 else if ( e
.name
== "define" )
654 Define
* pDefine
= new Define ( project
, this, e
);
655 if ( parseContext
.ifData
)
656 parseContext
.ifData
->data
.defines
.push_back ( pDefine
);
658 non_if_data
.defines
.push_back ( pDefine
);
661 else if ( e
.name
== "invoke" )
663 if ( parseContext
.ifData
)
665 throw XMLInvalidBuildFileException (
667 "<invoke> is not a valid sub-element of <if>" );
669 invocations
.push_back ( new Invoke ( e
, *this ) );
670 subs_invalid
= false;
672 else if ( e
.name
== "dependency" )
674 if ( parseContext
.ifData
)
676 throw XMLInvalidBuildFileException (
678 "<dependency> is not a valid sub-element of <if>" );
680 dependencies
.push_back ( new Dependency ( e
, *this ) );
683 else if ( e
.name
== "importlibrary" )
685 if ( parseContext
.ifData
)
687 throw XMLInvalidBuildFileException (
689 "<importlibrary> is not a valid sub-element of <if>" );
693 throw XMLInvalidBuildFileException (
695 "Only one <importlibrary> is valid per module" );
697 importLibrary
= new ImportLibrary ( e
, *this );
700 else if ( e
.name
== "if" )
702 parseContext
.ifData
= new If ( e
, project
, this );
704 pOldIf
->data
.ifs
.push_back ( parseContext
.ifData
);
706 non_if_data
.ifs
.push_back ( parseContext
.ifData
);
707 subs_invalid
= false;
709 else if ( e
.name
== "ifnot" )
711 parseContext
.ifData
= new If ( e
, project
, this, true );
713 pOldIf
->data
.ifs
.push_back ( parseContext
.ifData
);
715 non_if_data
.ifs
.push_back ( parseContext
.ifData
);
716 subs_invalid
= false;
718 else if ( e
.name
== "compilerflag" )
720 CompilerFlag
* pCompilerFlag
= new CompilerFlag ( project
, this, e
);
721 if ( parseContext
.ifData
)
722 parseContext
.ifData
->data
.compilerFlags
.push_back ( pCompilerFlag
);
724 non_if_data
.compilerFlags
.push_back ( pCompilerFlag
);
727 else if ( e
.name
== "linkerflag" )
729 linkerFlags
.push_back ( new LinkerFlag ( project
, this, e
) );
732 else if ( e
.name
== "linkerscript" )
736 throw XMLInvalidBuildFileException (
738 "Only one <linkerscript> is valid per module" );
740 linkerScript
= new LinkerScript ( project
, this, e
);
743 else if ( e
.name
== "component" )
745 stubbedComponents
.push_back ( new StubbedComponent ( this, e
) );
746 subs_invalid
= false;
748 else if ( e
.name
== "property" )
750 throw XMLInvalidBuildFileException (
752 "<property> is not a valid sub-element of <module>" );
754 else if ( e
.name
== "bootstrap" )
756 bootstrap
= new Bootstrap ( project
, this, e
);
759 else if ( e
.name
== "pch" )
761 if ( parseContext
.ifData
)
763 throw XMLInvalidBuildFileException (
765 "<pch> is not a valid sub-element of <if>" );
769 throw XMLInvalidBuildFileException (
771 "Only one <pch> is valid per module" );
774 e
, *this, File ( FixSeparator ( path
+ cSep
+ e
.value
), false, "", true ) );
777 else if ( e
.name
== "compilationunit" )
779 if ( project
.configuration
.CompilationUnitsEnabled
)
781 CompilationUnit
* pCompilationUnit
= new CompilationUnit ( &project
, this, &e
);
782 if ( parseContext
.ifData
)
783 parseContext
.ifData
->data
.compilationUnits
.push_back ( pCompilationUnit
);
785 non_if_data
.compilationUnits
.push_back ( pCompilationUnit
);
786 parseContext
.compilationUnit
= pCompilationUnit
;
788 subs_invalid
= false;
790 else if ( e
.name
== "autoregister" )
792 if ( autoRegister
!= NULL
)
794 throw XMLInvalidBuildFileException (
796 "there can be only one <%s> element for a module",
799 autoRegister
= new AutoRegister ( project
, this, e
);
802 if ( subs_invalid
&& e
.subElements
.size() > 0 )
804 throw XMLInvalidBuildFileException (
806 "<%s> cannot have sub-elements",
809 for ( size_t i
= 0; i
< e
.subElements
.size (); i
++ )
810 ProcessXMLSubElement ( *e
.subElements
[i
], subpath
, subpath_prefix
, parseContext
);
811 parseContext
.ifData
= pOldIf
;
812 parseContext
.compilationUnit
= pOldCompilationUnit
;
816 Module::GetModuleType ( const string
& location
, const XMLAttribute
& attribute
)
818 if ( attribute
.value
== "buildtool" )
820 if ( attribute
.value
== "staticlibrary" )
821 return StaticLibrary
;
822 if ( attribute
.value
== "objectlibrary" )
823 return ObjectLibrary
;
824 if ( attribute
.value
== "kernel" )
826 if ( attribute
.value
== "kernelmodedll" )
827 return KernelModeDLL
;
828 if ( attribute
.value
== "kernelmodedriver" )
829 return KernelModeDriver
;
830 if ( attribute
.value
== "nativedll" )
832 if ( attribute
.value
== "nativecui" )
834 if ( attribute
.value
== "win32dll" )
836 if ( attribute
.value
== "win32ocx" )
838 if ( attribute
.value
== "win32cui" )
840 if ( attribute
.value
== "win32gui" )
842 if ( attribute
.value
== "win32scr" )
844 if ( attribute
.value
== "bootloader" )
846 if ( attribute
.value
== "bootsector" )
848 if ( attribute
.value
== "bootprogram" )
850 if ( attribute
.value
== "iso" )
852 if ( attribute
.value
== "liveiso" )
854 if ( attribute
.value
== "isoregtest" )
856 if ( attribute
.value
== "liveisoregtest" )
857 return LiveIsoRegTest
;
858 if ( attribute
.value
== "test" )
860 if ( attribute
.value
== "rpcserver" )
862 if ( attribute
.value
== "rpcclient" )
864 if ( attribute
.value
== "alias" )
866 if ( attribute
.value
== "idlheader" )
868 if ( attribute
.value
== "embeddedtypelib" )
869 return EmbeddedTypeLib
;
870 throw InvalidAttributeValueException ( location
,
876 Module::GetDefaultModuleExtension () const
900 case KernelModeDriver
:
920 case EmbeddedTypeLib
:
923 throw InvalidOperationException ( __FILE__
,
928 Module::GetDefaultModuleEntrypoint () const
933 return "NtProcessStartup";
935 case KernelModeDriver
:
936 return "DriverEntry@8";
938 return "DllMainCRTStartup@12";
940 return "NtProcessStartup@4";
947 return "wmainCRTStartup";
949 return "mainCRTStartup";
953 return "wWinMainCRTStartup";
955 return "WinMainCRTStartup";
970 case EmbeddedTypeLib
:
973 throw InvalidOperationException ( __FILE__
,
978 Module::GetDefaultModuleBaseaddress () const
996 case KernelModeDriver
:
1006 case LiveIsoRegTest
:
1012 case EmbeddedTypeLib
:
1015 throw InvalidOperationException ( __FILE__
,
1020 Module::HasImportLibrary () const
1022 return importLibrary
!= NULL
&& type
!= StaticLibrary
;
1026 Module::IsDLL () const
1035 case KernelModeDriver
:
1051 case LiveIsoRegTest
:
1056 case EmbeddedTypeLib
:
1059 throw InvalidOperationException ( __FILE__
,
1064 Module::GenerateInOutputTree () const
1073 case KernelModeDriver
:
1086 case LiveIsoRegTest
:
1087 case EmbeddedTypeLib
:
1097 throw InvalidOperationException ( __FILE__
,
1102 Module::GetTargetName () const
1104 return name
+ extension
;
1108 Module::GetDependencyPath () const
1110 if ( HasImportLibrary () )
1111 return ReplaceExtension ( GetPathWithPrefix ( "lib" ), ".a" );
1117 Module::GetBasePath () const
1123 Module::GetPath () const
1125 if ( path
.length() > 0 )
1126 return path
+ cSep
+ GetTargetName ();
1128 return GetTargetName ();
1132 Module::GetPathWithPrefix ( const string
& prefix
) const
1134 return path
+ cSep
+ prefix
+ GetTargetName ();
1138 Module::GetPathToBaseDir () const
1140 string temp_path
= path
;
1141 string result
= "..\\";
1142 while(temp_path
.find ('\\') != string::npos
)
1144 temp_path
.erase (0, temp_path
.find('\\')+1);
1151 Module::GetInvocationTarget ( const int index
) const
1153 return ssprintf ( "%s_invoke_%d",
1159 Module::GetEntryPoint(bool leadingUnderscore
) const
1162 if (entrypoint
== "0" || entrypoint
== "0x0")
1164 if (leadingUnderscore
)
1167 result
+= entrypoint
;
1172 Module::HasFileWithExtension (
1173 const IfableData
& data
,
1174 const std::string
& extension
) const
1177 for ( i
= 0; i
< data
.compilationUnits
.size (); i
++ )
1179 CompilationUnit
* compilationUnit
= data
.compilationUnits
[i
];
1180 if ( compilationUnit
->HasFileWithExtension ( extension
) )
1183 for ( i
= 0; i
< data
.ifs
.size (); i
++ )
1185 if ( HasFileWithExtension ( data
.ifs
[i
]->data
, extension
) )
1192 Module::InvokeModule () const
1194 for ( size_t i
= 0; i
< invocations
.size (); i
++ )
1196 Invoke
& invoke
= *invocations
[i
];
1197 string command
= FixSeparatorForSystemCommand(invoke
.invokeModule
->GetPath ()) + " " + invoke
.GetParameters ();
1198 printf ( "Executing '%s'\n\n", command
.c_str () );
1199 int exitcode
= system ( command
.c_str () );
1200 if ( exitcode
!= 0 )
1201 throw InvocationFailedException ( command
,
1207 File::File ( const string
& _name
,
1209 std::string _switches
,
1210 bool _isPreCompiledHeader
)
1214 switches(_switches
),
1215 isPreCompiledHeader(_isPreCompiledHeader
)
1220 File::File ( const string
& _name
,
1221 const string
& _path_prefix
,
1223 std::string _switches
,
1224 bool _isPreCompiledHeader
)
1226 path_prefix(_path_prefix
),
1228 switches(_switches
),
1229 isPreCompiledHeader(_isPreCompiledHeader
)
1239 std::string
File::GetFullPath () const
1241 if ( path_prefix
.length () > 0 )
1242 return path_prefix
+ sSep
+ name
;
1248 Library::Library ( const XMLElement
& _node
,
1249 const Module
& _module
,
1250 const string
& _name
)
1254 importedModule(_module
.project
.LocateModule(_name
))
1256 if ( module
.name
== name
)
1258 throw XMLInvalidBuildFileException (
1260 "module '%s' cannot link against itself",
1263 if ( !importedModule
)
1265 throw XMLInvalidBuildFileException (
1267 "module '%s' trying to import non-existant module '%s'",
1268 module
.name
.c_str(),
1273 Library::Library ( const Module
& _module
,
1274 const string
& _name
)
1278 importedModule(_module
.project
.LocateModule(_name
))
1283 Library::ProcessXML()
1285 if ( node
&& !module
.project
.LocateModule ( name
) )
1287 throw XMLInvalidBuildFileException (
1289 "module '%s' is trying to link against non-existant module '%s'",
1290 module
.name
.c_str(),
1296 Invoke::Invoke ( const XMLElement
& _node
,
1297 const Module
& _module
)
1304 Invoke::ProcessXML()
1306 const XMLAttribute
* att
= node
.GetAttribute ( "module", false );
1308 invokeModule
= &module
;
1311 invokeModule
= module
.project
.LocateModule ( att
->value
);
1312 if ( invokeModule
== NULL
)
1314 throw XMLInvalidBuildFileException (
1316 "module '%s' is trying to invoke non-existant module '%s'",
1317 module
.name
.c_str(),
1318 att
->value
.c_str() );
1322 for ( size_t i
= 0; i
< node
.subElements
.size (); i
++ )
1323 ProcessXMLSubElement ( *node
.subElements
[i
] );
1327 Invoke::ProcessXMLSubElement ( const XMLElement
& e
)
1329 bool subs_invalid
= false;
1330 if ( e
.name
== "input" )
1332 for ( size_t i
= 0; i
< e
.subElements
.size (); i
++ )
1333 ProcessXMLSubElementInput ( *e
.subElements
[i
] );
1335 else if ( e
.name
== "output" )
1337 for ( size_t i
= 0; i
< e
.subElements
.size (); i
++ )
1338 ProcessXMLSubElementOutput ( *e
.subElements
[i
] );
1340 if ( subs_invalid
&& e
.subElements
.size() > 0 )
1342 throw XMLInvalidBuildFileException (
1344 "<%s> cannot have sub-elements",
1350 Invoke::ProcessXMLSubElementInput ( const XMLElement
& e
)
1352 bool subs_invalid
= false;
1353 if ( e
.name
== "inputfile" && e
.value
.size () > 0 )
1355 input
.push_back ( new InvokeFile (
1356 e
, FixSeparator ( module
.path
+ cSep
+ e
.value
) ) );
1357 subs_invalid
= true;
1359 if ( subs_invalid
&& e
.subElements
.size() > 0 )
1361 throw XMLInvalidBuildFileException (
1363 "<%s> cannot have sub-elements",
1369 Invoke::ProcessXMLSubElementOutput ( const XMLElement
& e
)
1371 bool subs_invalid
= false;
1372 if ( e
.name
== "outputfile" && e
.value
.size () > 0 )
1374 output
.push_back ( new InvokeFile (
1375 e
, FixSeparator ( module
.path
+ cSep
+ e
.value
) ) );
1376 subs_invalid
= true;
1378 if ( subs_invalid
&& e
.subElements
.size() > 0 )
1380 throw XMLInvalidBuildFileException (
1382 "<%s> cannot have sub-elements",
1388 Invoke::GetTargets ( string_list
& targets
) const
1390 for ( size_t i
= 0; i
< output
.size (); i
++ )
1392 InvokeFile
& file
= *output
[i
];
1393 targets
.push_back ( NormalizeFilename ( file
.name
) );
1398 Invoke::GetParameters () const
1400 string
parameters ( "" );
1402 for ( i
= 0; i
< output
.size (); i
++ )
1404 if ( parameters
.length () > 0)
1406 InvokeFile
& invokeFile
= *output
[i
];
1407 if ( invokeFile
.switches
.length () > 0 )
1409 parameters
+= invokeFile
.switches
+ " ";
1411 parameters
+= invokeFile
.name
;
1414 for ( i
= 0; i
< input
.size (); i
++ )
1416 if ( parameters
.length () > 0 )
1418 InvokeFile
& invokeFile
= *input
[i
];
1419 if ( invokeFile
.switches
.length () > 0 )
1421 parameters
+= invokeFile
.switches
;
1424 parameters
+= invokeFile
.name
;
1431 InvokeFile::InvokeFile ( const XMLElement
& _node
,
1432 const string
& _name
)
1436 const XMLAttribute
* att
= _node
.GetAttribute ( "switches", false );
1438 switches
= att
->value
;
1444 InvokeFile::ProcessXML()
1449 Dependency::Dependency ( const XMLElement
& _node
,
1450 const Module
& _module
)
1453 dependencyModule (NULL
)
1458 Dependency::ProcessXML()
1460 dependencyModule
= module
.project
.LocateModule ( node
.value
);
1461 if ( dependencyModule
== NULL
)
1463 throw XMLInvalidBuildFileException (
1465 "module '%s' depend on non-existant module '%s'",
1466 module
.name
.c_str(),
1467 node
.value
.c_str() );
1472 ImportLibrary::ImportLibrary ( const XMLElement
& _node
,
1473 const Module
& _module
)
1477 const XMLAttribute
* att
= _node
.GetAttribute ( "basename", false );
1479 basename
= att
->value
;
1481 basename
= module
.name
;
1483 att
= _node
.GetAttribute ( "dllname", false );
1485 dllname
= att
->value
;
1488 if ( _module
.type
== StaticLibrary
)
1490 throw XMLInvalidBuildFileException (
1492 "<importlibrary> dllname attribute required." );
1498 att
= _node
.GetAttribute ( "definition", true );
1500 definition
= FixSeparator(att
->value
);
1504 If::If ( const XMLElement
& node_
,
1505 const Project
& project_
,
1506 const Module
* module_
,
1507 const bool negated_
)
1508 : node(node_
), project(project_
), module(module_
), negated(negated_
)
1510 const XMLAttribute
* att
;
1512 att
= node
.GetAttribute ( "property", true );
1514 property
= att
->value
;
1516 att
= node
.GetAttribute ( "value", true );
1532 Property::Property ( const XMLElement
& node_
,
1533 const Project
& project_
,
1534 const Module
* module_
)
1535 : project(project_
), module(module_
)
1537 const XMLAttribute
* att
;
1539 att
= node_
.GetAttribute ( "name", true );
1543 att
= node_
.GetAttribute ( "value", true );
1548 Property::Property ( const Project
& project_
,
1549 const Module
* module_
,
1550 const std::string
& name_
,
1551 const std::string
& value_
)
1552 : project(project_
), module(module_
), name(name_
), value(value_
)
1557 Property::ProcessXML()
1563 const XMLElement
& node_
,
1564 const Module
& module_
,
1566 : node(node_
), module(module_
), file(file_
)
1571 PchFile::ProcessXML()
1576 AutoRegister::AutoRegister ( const Project
& project_
,
1577 const Module
* module_
,
1578 const XMLElement
& node_
)
1579 : project(project_
),
1586 AutoRegister::~AutoRegister ()
1591 AutoRegister::IsSupportedModuleType ( ModuleType type
)
1605 case KernelModeDriver
:
1615 case LiveIsoRegTest
:
1621 case EmbeddedTypeLib
:
1624 throw InvalidOperationException ( __FILE__
,
1629 AutoRegister::GetAutoRegisterType( string type
)
1631 if ( type
== "DllRegisterServer" )
1632 return DllRegisterServer
;
1633 if ( type
== "DllInstall" )
1635 if ( type
== "Both" )
1637 throw XMLInvalidBuildFileException (
1639 "<autoregister> type attribute must be DllRegisterServer, DllInstall or Both." );
1643 AutoRegister::Initialize ()
1645 if ( !IsSupportedModuleType ( module
->type
) )
1647 throw XMLInvalidBuildFileException (
1649 "<autoregister> is not applicable for this module type." );
1652 const XMLAttribute
* att
= node
.GetAttribute ( "infsection", true );
1653 infSection
= att
->value
;
1655 att
= node
.GetAttribute ( "type", true );
1656 type
= GetAutoRegisterType ( att
->value
);
1660 AutoRegister::ProcessXML()