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 GetExtension ( const FileLocation
& file
)
155 return GetExtension ( file
.name
);
159 NormalizeFilename ( const string
& filename
)
161 if ( filename
== "" )
164 string normalizedPath
= path
.Fixup ( filename
, true );
165 string relativeNormalizedPath
= path
.RelativeFromWorkingDirectory ( normalizedPath
);
166 return FixSeparator ( relativeNormalizedPath
);
170 GetBooleanValue ( const string
& value
)
179 ToLower ( string filename
)
181 for ( size_t i
= 1; i
< filename
.length (); i
++ )
182 filename
[i
] = tolower ( filename
[i
] );
186 IfableData::IfableData( )
191 void IfableData::ExtractModules( std::vector
<Module
*> &modules
)
194 for ( i
= 0; i
< this->modules
.size (); i
++ )
195 modules
.push_back(this->modules
[i
]);
198 IfableData::~IfableData()
201 for ( i
= 0; i
< includes
.size (); i
++ )
203 for ( i
= 0; i
< defines
.size (); i
++ )
205 for ( i
= 0; i
< libraries
.size (); i
++ )
207 for ( i
= 0; i
< properties
.size (); i
++ )
208 delete properties
[i
];
209 for ( i
= 0; i
< compilerFlags
.size (); i
++ )
210 delete compilerFlags
[i
];
211 for ( i
= 0; i
< modules
.size(); i
++ )
213 for ( i
= 0; i
< ifs
.size (); i
++ )
215 for ( i
= 0; i
< compilationUnits
.size (); i
++ )
216 delete compilationUnits
[i
];
219 void IfableData::ProcessXML ()
222 for ( i
= 0; i
< includes
.size (); i
++ )
223 includes
[i
]->ProcessXML ();
224 for ( i
= 0; i
< defines
.size (); i
++ )
225 defines
[i
]->ProcessXML ();
226 for ( i
= 0; i
< libraries
.size (); i
++ )
227 libraries
[i
]->ProcessXML ();
228 for ( i
= 0; i
< properties
.size(); i
++ )
229 properties
[i
]->ProcessXML ();
230 for ( i
= 0; i
< compilerFlags
.size(); i
++ )
231 compilerFlags
[i
]->ProcessXML ();
232 for ( i
= 0; i
< ifs
.size (); i
++ )
233 ifs
[i
]->ProcessXML ();
234 for ( i
= 0; i
< compilationUnits
.size (); i
++ )
235 compilationUnits
[i
]->ProcessXML ();
238 Module::Module ( const Project
& project
,
239 const XMLElement
& moduleNode
,
240 const string
& modulePath
)
243 importLibrary (NULL
),
252 if ( node
.name
!= "module" )
253 throw InvalidOperationException ( __FILE__
,
255 "Module created with non-<module> node" );
257 xmlbuildFile
= FixSeparator ( Path::RelativeFromWorkingDirectory ( moduleNode
.xmlFile
->filename () ) );
259 const XMLAttribute
* att
= moduleNode
.GetAttribute ( "name", true );
265 att
= moduleNode
.GetAttribute ( "if", false );
267 enabled
= GetBooleanValue ( project
.ResolveProperties ( att
->value
) );
269 att
= moduleNode
.GetAttribute ( "ifnot", false );
271 enabled
= !GetBooleanValue ( project
.ResolveProperties ( att
->value
) );
273 if ( !enabled
&& project
.configuration
.Verbose
)
274 printf("Module '%s' has been disabled.\n", name
.c_str () );
276 att
= moduleNode
.GetAttribute ( "type", true );
278 type
= GetModuleType ( node
.location
, *att
);
280 att
= moduleNode
.GetAttribute ( "extension", false );
282 extension
= att
->value
;
284 extension
= GetDefaultModuleExtension ();
286 att
= moduleNode
.GetAttribute ( "unicode", false );
289 const char* p
= att
->value
.c_str();
290 if ( !stricmp ( p
, "true" ) || !stricmp ( p
, "yes" ) )
292 else if ( !stricmp ( p
, "false" ) || !stricmp ( p
, "no" ) )
296 throw InvalidAttributeValueException (
307 // Always define UNICODE and _UNICODE
308 Define
* pDefine
= new Define ( project
, this, "UNICODE" );
309 non_if_data
.defines
.push_back ( pDefine
);
311 pDefine
= new Define ( project
, this, "_UNICODE" );
312 non_if_data
.defines
.push_back ( pDefine
);
315 att
= moduleNode
.GetAttribute ( "entrypoint", false );
318 if ( att
->value
== "" )
320 throw InvalidAttributeValueException (
326 entrypoint
= att
->value
;
327 isDefaultEntryPoint
= false;
331 entrypoint
= GetDefaultModuleEntrypoint ();
332 isDefaultEntryPoint
= true;
335 att
= moduleNode
.GetAttribute ( "baseaddress", false );
337 baseaddress
= att
->value
;
339 baseaddress
= GetDefaultModuleBaseaddress ();
341 att
= moduleNode
.GetAttribute ( "mangledsymbols", false );
344 const char* p
= att
->value
.c_str();
345 if ( !stricmp ( p
, "true" ) || !stricmp ( p
, "yes" ) )
346 mangledSymbols
= true;
347 else if ( !stricmp ( p
, "false" ) || !stricmp ( p
, "no" ) )
348 mangledSymbols
= false;
351 throw InvalidAttributeValueException (
358 mangledSymbols
= false;
360 att
= moduleNode
.GetAttribute ( "underscoresymbols", false );
362 underscoreSymbols
= att
->value
== "true";
364 underscoreSymbols
= false;
366 att
= moduleNode
.GetAttribute ( "host", false );
369 const char* p
= att
->value
.c_str();
370 if ( !stricmp ( p
, "true" ) || !stricmp ( p
, "yes" ) )
372 else if ( !stricmp ( p
, "false" ) || !stricmp ( p
, "no" ) )
376 throw InvalidAttributeValueException (
383 att
= moduleNode
.GetAttribute ( "isstartuplib", false );
386 const char* p
= att
->value
.c_str();
387 if ( !stricmp ( p
, "true" ) || !stricmp ( p
, "yes" ) )
389 else if ( !stricmp ( p
, "false" ) || !stricmp ( p
, "no" ) )
390 isStartupLib
= false;
393 throw InvalidAttributeValueException (
400 isStartupLib
= false;
402 att
= moduleNode
.GetAttribute ( "prefix", false );
406 att
= moduleNode
.GetAttribute ( "installname", false );
409 const XMLAttribute
* installbase
= moduleNode
.GetAttribute ( "installbase", false );
410 install
= new FileLocation ( InstallDirectory
,
411 installbase
? installbase
->value
: "",
415 output
= new FileLocation ( GetTargetDirectoryTree (),
423 output
= new FileLocation ( GetTargetDirectoryTree (),
429 att
= moduleNode
.GetAttribute ( "allowwarnings", false );
432 att
= moduleNode
.GetAttribute ( "warnings", false );
435 printf ( "%s: WARNING: 'warnings' attribute of <module> is deprecated, use 'allowwarnings' instead\n",
436 moduleNode
.location
.c_str() );
440 allowWarnings
= att
->value
== "true";
442 allowWarnings
= false;
444 att
= moduleNode
.GetAttribute ( "aliasof", false );
445 if ( type
== Alias
&& att
!= NULL
)
446 aliasedModuleName
= att
->value
;
448 aliasedModuleName
= "";
450 if ( type
== BootProgram
)
452 att
= moduleNode
.GetAttribute ( "payload", true );
453 payload
= att
->value
;
456 if ( type
== BootProgram
|| type
== ElfExecutable
)
458 att
= moduleNode
.GetAttribute ( "buildtype", false );
461 buildtype
= att
->value
;
465 buildtype
= "BOOTPROG";
469 att
= moduleNode
.GetAttribute ( "description", false );
472 description
= project
.ResolveProperties(att
->value
);
477 att
= moduleNode
.GetAttribute ( "lcid", false );
478 if (type
== KeyboardLayout
&& att
!= NULL
)
483 SetImportLibrary ( NULL
);
489 for ( i
= 0; i
< invocations
.size(); i
++ )
490 delete invocations
[i
];
491 for ( i
= 0; i
< dependencies
.size(); i
++ )
492 delete dependencies
[i
];
493 for ( i
= 0; i
< compilerFlags
.size(); i
++ )
494 delete compilerFlags
[i
];
495 for ( i
= 0; i
< linkerFlags
.size(); i
++ )
496 delete linkerFlags
[i
];
497 for ( i
= 0; i
< stubbedComponents
.size(); i
++ )
498 delete stubbedComponents
[i
];
510 delete importLibrary
;
524 aliasedModuleName
= project
.ResolveProperties ( aliasedModuleName
);
525 if ( aliasedModuleName
== name
)
527 throw XMLInvalidBuildFileException (
529 "module '%s' cannot link against itself",
532 const Module
* m
= project
.LocateModule ( aliasedModuleName
);
535 throw XMLInvalidBuildFileException (
537 "module '%s' trying to alias non-existant module '%s'",
539 aliasedModuleName
.c_str() );
544 for ( i
= 0; i
< node
.subElements
.size(); i
++ )
546 ParseContext parseContext
;
547 ProcessXMLSubElement ( *node
.subElements
[i
], SourceDirectory
, output
->relative_path
, parseContext
);
549 for ( i
= 0; i
< invocations
.size(); i
++ )
550 invocations
[i
]->ProcessXML ();
551 for ( i
= 0; i
< dependencies
.size(); i
++ )
552 dependencies
[i
]->ProcessXML ();
553 for ( i
= 0; i
< compilerFlags
.size(); i
++ )
554 compilerFlags
[i
]->ProcessXML();
555 for ( i
= 0; i
< linkerFlags
.size(); i
++ )
556 linkerFlags
[i
]->ProcessXML();
557 for ( i
= 0; i
< stubbedComponents
.size(); i
++ )
558 stubbedComponents
[i
]->ProcessXML();
559 non_if_data
.ProcessXML();
561 linkerScript
->ProcessXML();
565 autoRegister
->ProcessXML();
569 Module::ProcessXMLSubElement ( const XMLElement
& e
,
570 DirectoryLocation directory
,
571 const string
& relative_path
,
572 ParseContext
& parseContext
)
574 If
* pOldIf
= parseContext
.ifData
;
575 CompilationUnit
* pOldCompilationUnit
= parseContext
.compilationUnit
;
576 bool subs_invalid
= false;
577 string
subpath ( relative_path
);
578 DirectoryLocation subdirectory
= SourceDirectory
;
579 if ( e
.name
== "file" && e
.value
.size () > 0 )
582 const XMLAttribute
* att
= e
.GetAttribute ( "first", false );
585 if ( !stricmp ( att
->value
.c_str(), "true" ) )
587 else if ( stricmp ( att
->value
.c_str(), "false" ) )
589 throw XMLInvalidBuildFileException (
591 "attribute 'first' of <file> element can only be 'true' or 'false'" );
594 string switches
= "";
595 att
= e
.GetAttribute ( "switches", false );
597 switches
= att
->value
;
600 // check for c++ file
601 string ext
= GetExtension ( e
.value
);
602 if ( !stricmp ( ext
.c_str(), ".cpp" ) )
604 else if ( !stricmp ( ext
.c_str(), ".cc" ) )
606 else if ( !stricmp ( ext
.c_str(), ".cxx" ) )
609 File
* pFile
= new File ( directory
,
615 if ( parseContext
.compilationUnit
)
616 parseContext
.compilationUnit
->AddFile ( pFile
);
619 CompilationUnit
* pCompilationUnit
= new CompilationUnit ( pFile
);
620 if ( parseContext
.ifData
)
621 parseContext
.ifData
->data
.compilationUnits
.push_back ( pCompilationUnit
);
624 string ext
= ToLower ( GetExtension ( e
.value
) );
627 // put .idl files at the start of the module
628 non_if_data
.compilationUnits
.insert (
629 non_if_data
.compilationUnits
.begin(),
632 else if ( ext
== ".asm" || ext
== ".s" )
634 // put .asm files at the end of the module
635 non_if_data
.compilationUnits
.push_back ( pCompilationUnit
);
636 non_if_data
.asmFiles
++;
640 // put other files in the middle
641 non_if_data
.compilationUnits
.insert (
642 non_if_data
.compilationUnits
.end() - non_if_data
.asmFiles
,
647 if ( parseContext
.ifData
)
648 parseContext
.ifData
->data
.files
.push_back ( pFile
);
650 non_if_data
.files
.push_back ( pFile
);
653 else if ( e
.name
== "library" && e
.value
.size () )
655 Library
* pLibrary
= new Library ( e
, *this, e
.value
);
656 if ( parseContext
.ifData
)
657 parseContext
.ifData
->data
.libraries
.push_back ( pLibrary
);
659 non_if_data
.libraries
.push_back ( pLibrary
);
662 else if ( e
.name
== "directory" )
664 const XMLAttribute
* att
= e
.GetAttribute ( "name", true );
665 const XMLAttribute
* root
= e
.GetAttribute ( "root", false );
669 if ( root
->value
== "intermediate" )
670 subdirectory
= IntermediateDirectory
;
671 else if ( root
->value
== "output" )
672 subdirectory
= OutputDirectory
;
675 throw InvalidAttributeValueException (
681 subpath
= GetSubPath ( this->project
, e
.location
, relative_path
, att
->value
);
683 else if ( e
.name
== "include" )
685 Include
* include
= new Include ( project
, &e
, this );
686 if ( parseContext
.ifData
)
687 parseContext
.ifData
->data
.includes
.push_back ( include
);
689 non_if_data
.includes
.push_back ( include
);
692 else if ( e
.name
== "define" )
694 Define
* pDefine
= new Define ( project
, this, e
);
695 if ( parseContext
.ifData
)
696 parseContext
.ifData
->data
.defines
.push_back ( pDefine
);
698 non_if_data
.defines
.push_back ( pDefine
);
701 else if ( e
.name
== "metadata" )
703 if ( parseContext
.ifData
)
705 throw XMLInvalidBuildFileException (
707 "<metadata> is not a valid sub-element of <if>" );
709 metadata
= new Metadata ( e
, *this );
710 subs_invalid
= false;
712 else if ( e
.name
== "invoke" )
714 if ( parseContext
.ifData
)
716 throw XMLInvalidBuildFileException (
718 "<invoke> is not a valid sub-element of <if>" );
720 invocations
.push_back ( new Invoke ( e
, *this ) );
721 subs_invalid
= false;
723 else if ( e
.name
== "dependency" )
725 if ( parseContext
.ifData
)
727 throw XMLInvalidBuildFileException (
729 "<dependency> is not a valid sub-element of <if>" );
731 dependencies
.push_back ( new Dependency ( e
, *this ) );
734 else if ( e
.name
== "importlibrary" )
736 if ( parseContext
.ifData
)
738 throw XMLInvalidBuildFileException (
740 "<importlibrary> is not a valid sub-element of <if>" );
744 throw XMLInvalidBuildFileException (
746 "Only one <importlibrary> is valid per module" );
748 SetImportLibrary ( new ImportLibrary ( project
, e
, *this ) );
751 else if ( e
.name
== "if" )
753 parseContext
.ifData
= new If ( e
, project
, this );
755 pOldIf
->data
.ifs
.push_back ( parseContext
.ifData
);
757 non_if_data
.ifs
.push_back ( parseContext
.ifData
);
758 subs_invalid
= false;
760 else if ( e
.name
== "ifnot" )
762 parseContext
.ifData
= new If ( e
, project
, this, true );
764 pOldIf
->data
.ifs
.push_back ( parseContext
.ifData
);
766 non_if_data
.ifs
.push_back ( parseContext
.ifData
);
767 subs_invalid
= false;
769 else if ( e
.name
== "compilerflag" )
771 CompilerFlag
* pCompilerFlag
= new CompilerFlag ( project
, this, e
);
772 if ( parseContext
.ifData
)
773 parseContext
.ifData
->data
.compilerFlags
.push_back ( pCompilerFlag
);
775 non_if_data
.compilerFlags
.push_back ( pCompilerFlag
);
778 else if ( e
.name
== "linkerflag" )
780 linkerFlags
.push_back ( new LinkerFlag ( project
, this, e
) );
783 else if ( e
.name
== "linkerscript" )
785 if ( parseContext
.ifData
)
787 throw XMLInvalidBuildFileException (
789 "<linkerscript> is not a valid sub-element of <if>" );
793 throw XMLInvalidBuildFileException (
795 "Only one <linkerscript> is valid per module" );
797 size_t pos
= e
.value
.find_last_of ( "/\\" );
798 if ( pos
== string::npos
)
800 linkerScript
= new LinkerScript (
801 e
, *this, new FileLocation ( SourceDirectory
, relative_path
, e
.value
, &e
) );
805 string dir
= e
.value
.substr ( 0, pos
);
806 string name
= e
.value
.substr ( pos
+ 1);
807 linkerScript
= new LinkerScript (
808 e
, *this, new FileLocation ( SourceDirectory
, relative_path
+ sSep
+ dir
, name
, &e
) );
812 else if ( e
.name
== "component" )
814 stubbedComponents
.push_back ( new StubbedComponent ( this, e
) );
815 subs_invalid
= false;
817 else if ( e
.name
== "property" )
819 throw XMLInvalidBuildFileException (
821 "<property> is not a valid sub-element of <module>" );
823 else if ( e
.name
== "bootstrap" )
825 bootstrap
= new Bootstrap ( project
, this, e
);
828 else if ( e
.name
== "pch" )
830 if ( parseContext
.ifData
)
832 throw XMLInvalidBuildFileException (
834 "<pch> is not a valid sub-element of <if>" );
838 throw XMLInvalidBuildFileException (
840 "Only one <pch> is valid per module" );
842 size_t pos
= e
.value
.find_last_of ( "/\\" );
843 if ( pos
== string::npos
)
846 e
, *this, new FileLocation ( SourceDirectory
, relative_path
, e
.value
, &e
) );
850 string dir
= e
.value
.substr ( 0, pos
);
851 string name
= e
.value
.substr ( pos
+ 1);
853 e
, *this, new FileLocation ( SourceDirectory
, relative_path
+ sSep
+ dir
, name
, &e
) );
857 else if ( e
.name
== "compilationunit" )
859 if ( project
.configuration
.CompilationUnitsEnabled
)
861 CompilationUnit
* pCompilationUnit
= new CompilationUnit ( &project
, this, &e
);
862 if ( parseContext
.ifData
)
863 parseContext
.ifData
->data
.compilationUnits
.push_back ( pCompilationUnit
);
865 non_if_data
.compilationUnits
.push_back ( pCompilationUnit
);
866 parseContext
.compilationUnit
= pCompilationUnit
;
868 subs_invalid
= false;
870 else if ( e
.name
== "autoregister" )
872 if ( autoRegister
!= NULL
)
874 throw XMLInvalidBuildFileException (
876 "there can be only one <%s> element for a module",
879 autoRegister
= new AutoRegister ( project
, this, e
);
882 if ( subs_invalid
&& e
.subElements
.size() > 0 )
884 throw XMLInvalidBuildFileException (
886 "<%s> cannot have sub-elements",
889 for ( size_t i
= 0; i
< e
.subElements
.size (); i
++ )
890 ProcessXMLSubElement ( *e
.subElements
[i
], subdirectory
, subpath
, parseContext
);
891 parseContext
.ifData
= pOldIf
;
892 parseContext
.compilationUnit
= pOldCompilationUnit
;
896 Module::GetModuleType ( const string
& location
, const XMLAttribute
& attribute
)
898 if ( attribute
.value
== "buildtool" )
900 if ( attribute
.value
== "staticlibrary" )
901 return StaticLibrary
;
902 if ( attribute
.value
== "hoststaticlibrary" )
903 return HostStaticLibrary
;
904 if ( attribute
.value
== "objectlibrary" )
905 return ObjectLibrary
;
906 if ( attribute
.value
== "kernel" )
908 if ( attribute
.value
== "kernelmodedll" )
909 return KernelModeDLL
;
910 if ( attribute
.value
== "kernelmodedriver" )
911 return KernelModeDriver
;
912 if ( attribute
.value
== "nativedll" )
914 if ( attribute
.value
== "nativecui" )
916 if ( attribute
.value
== "keyboardlayout" )
917 return KeyboardLayout
;
918 if ( attribute
.value
== "win32dll" )
920 if ( attribute
.value
== "win32ocx" )
922 if ( attribute
.value
== "win32cui" )
924 if ( attribute
.value
== "win32gui" )
926 if ( attribute
.value
== "win32scr" )
928 if ( attribute
.value
== "bootloader" )
930 if ( attribute
.value
== "bootsector" )
932 if ( attribute
.value
== "bootprogram" )
934 if ( attribute
.value
== "iso" )
936 if ( attribute
.value
== "liveiso" )
938 if ( attribute
.value
== "isoregtest" )
940 if ( attribute
.value
== "liveisoregtest" )
941 return LiveIsoRegTest
;
942 if ( attribute
.value
== "test" )
944 if ( attribute
.value
== "rpcserver" )
946 if ( attribute
.value
== "rpcclient" )
948 if ( attribute
.value
== "rpcproxy" )
950 if ( attribute
.value
== "alias" )
952 if ( attribute
.value
== "idlheader" )
954 if ( attribute
.value
== "embeddedtypelib" )
955 return EmbeddedTypeLib
;
956 if ( attribute
.value
== "elfexecutable" )
957 return ElfExecutable
;
958 if ( attribute
.value
== "cabinet" )
960 throw InvalidAttributeValueException ( location
,
966 Module::GetTargetDirectoryTree () const
976 case KernelModeDriver
:
992 return OutputDirectory
;
993 case EmbeddedTypeLib
:
995 case HostStaticLibrary
:
1002 return IntermediateDirectory
;
1006 throw InvalidOperationException ( __FILE__
,
1008 "Invalid module type %d.",
1013 Module::GetDefaultModuleExtension () const
1021 case HostStaticLibrary
:
1035 case KeyboardLayout
:
1040 case KernelModeDriver
:
1050 case LiveIsoRegTest
:
1062 case EmbeddedTypeLib
:
1067 throw InvalidOperationException ( __FILE__
,
1072 Module::GetDefaultModuleEntrypoint () const
1077 return "KiSystemStartup";
1078 case KeyboardLayout
:
1080 case KernelModeDriver
:
1081 return "DriverEntry@8";
1083 return "DllMainCRTStartup@12";
1085 return "NtProcessStartup@4";
1088 return "DllMain@12";
1092 return "wmainCRTStartup";
1094 return "mainCRTStartup";
1098 return "wWinMainCRTStartup";
1100 return "WinMainCRTStartup";
1103 case HostStaticLibrary
:
1110 case LiveIsoRegTest
:
1118 case EmbeddedTypeLib
:
1124 throw InvalidOperationException ( __FILE__
,
1129 Module::GetDefaultModuleBaseaddress () const
1134 return "0x80800000";
1137 return "0x10000000";
1142 return "0x00400000";
1145 return "0x00400000";
1146 case KeyboardLayout
:
1148 case KernelModeDriver
:
1149 return "0x00010000";
1154 case HostStaticLibrary
:
1161 case LiveIsoRegTest
:
1168 case EmbeddedTypeLib
:
1174 throw InvalidOperationException ( __FILE__
,
1179 Module::HasImportLibrary () const
1181 return importLibrary
!= NULL
&& type
!= StaticLibrary
&& type
!= HostStaticLibrary
;
1185 Module::IsDLL () const
1192 case KeyboardLayout
:
1195 case KernelModeDriver
:
1204 case HostStaticLibrary
:
1212 case LiveIsoRegTest
:
1218 case EmbeddedTypeLib
:
1225 throw InvalidOperationException ( __FILE__
,
1230 Module::GetPathWithPrefix ( const string
& prefix
) const
1232 return output
->relative_path
+ cSep
+ prefix
+ output
->name
;
1236 Module::GetPathToBaseDir () const
1238 string temp_path
= output
->relative_path
;
1239 string result
= "..\\";
1240 while(temp_path
.find ('\\') != string::npos
)
1242 temp_path
.erase (0, temp_path
.find('\\')+1);
1249 Module::GetInvocationTarget ( const int index
) const
1251 return ssprintf ( "%s_invoke_%d",
1257 Module::GetEntryPoint(bool leadingUnderscore
) const
1260 if (entrypoint
== "0" || entrypoint
== "0x0")
1262 if (leadingUnderscore
)
1265 result
+= entrypoint
;
1270 Module::HasFileWithExtension (
1271 const IfableData
& data
,
1272 const std::string
& extension
) const
1275 for ( i
= 0; i
< data
.compilationUnits
.size (); i
++ )
1277 CompilationUnit
* compilationUnit
= data
.compilationUnits
[i
];
1278 if ( compilationUnit
->HasFileWithExtension ( extension
) )
1281 for ( i
= 0; i
< data
.ifs
.size (); i
++ )
1283 if ( HasFileWithExtension ( data
.ifs
[i
]->data
, extension
) )
1290 Module::InvokeModule () const
1292 for ( size_t i
= 0; i
< invocations
.size (); i
++ )
1294 Invoke
& invoke
= *invocations
[i
];
1295 string command
= FixSeparatorForSystemCommand(invoke
.invokeModule
->output
->relative_path
+ "/" + invoke
.invokeModule
->output
->name
) + " " + invoke
.GetParameters ();
1296 printf ( "Executing '%s'\n\n", command
.c_str () );
1297 int exitcode
= system ( command
.c_str () );
1298 if ( exitcode
!= 0 )
1299 throw InvocationFailedException ( command
,
1306 Module::SetImportLibrary ( ImportLibrary
* importLibrary
)
1308 this->importLibrary
= importLibrary
;
1309 dependency
= new FileLocation ( HasImportLibrary () ? IntermediateDirectory
: output
->directory
,
1310 output
->relative_path
,
1311 HasImportLibrary () ? "lib" + name
+ ".a" : output
->name
);
1315 File::File ( DirectoryLocation directory
,
1316 const string
& relative_path
,
1319 const string
& _switches
,
1320 bool _isPreCompiledHeader
)
1321 : file ( directory
, relative_path
, name
),
1323 switches(_switches
),
1324 isPreCompiledHeader(_isPreCompiledHeader
)
1335 std::string
File::GetFullPath () const
1337 string
directory ( "" );
1338 switch ( file
.directory
)
1340 case SourceDirectory
:
1342 case IntermediateDirectory
:
1343 directory
= Environment::GetIntermediatePath () + sSep
;
1346 throw InvalidOperationException ( __FILE__
,
1348 "Invalid directory %d.",
1352 if ( file
.relative_path
.length () > 0 )
1353 directory
+= file
.relative_path
+ sSep
;
1356 return directory
+ file
.name
;
1360 Library::Library ( const XMLElement
& _node
,
1361 const Module
& _module
,
1362 const string
& _name
)
1366 importedModule(_module
.project
.LocateModule(_name
))
1368 if ( module
.name
== name
)
1370 throw XMLInvalidBuildFileException (
1372 "module '%s' cannot link against itself",
1375 if ( !importedModule
)
1377 throw XMLInvalidBuildFileException (
1379 "module '%s' trying to import non-existant module '%s'",
1380 module
.name
.c_str(),
1385 Library::Library ( const Module
& _module
,
1386 const string
& _name
)
1390 importedModule(_module
.project
.LocateModule(_name
))
1395 Library::ProcessXML()
1397 if ( node
&& !module
.project
.LocateModule ( name
) )
1399 throw XMLInvalidBuildFileException (
1401 "module '%s' is trying to link against non-existant module '%s'",
1402 module
.name
.c_str(),
1408 Invoke::Invoke ( const XMLElement
& _node
,
1409 const Module
& _module
)
1416 Invoke::ProcessXML()
1418 const XMLAttribute
* att
= node
.GetAttribute ( "module", false );
1420 invokeModule
= &module
;
1423 invokeModule
= module
.project
.LocateModule ( att
->value
);
1424 if ( invokeModule
== NULL
)
1426 throw XMLInvalidBuildFileException (
1428 "module '%s' is trying to invoke non-existant module '%s'",
1429 module
.name
.c_str(),
1430 att
->value
.c_str() );
1434 for ( size_t i
= 0; i
< node
.subElements
.size (); i
++ )
1435 ProcessXMLSubElement ( *node
.subElements
[i
] );
1439 Invoke::ProcessXMLSubElement ( const XMLElement
& e
)
1441 bool subs_invalid
= false;
1442 if ( e
.name
== "input" )
1444 for ( size_t i
= 0; i
< e
.subElements
.size (); i
++ )
1445 ProcessXMLSubElementInput ( *e
.subElements
[i
] );
1447 else if ( e
.name
== "output" )
1449 for ( size_t i
= 0; i
< e
.subElements
.size (); i
++ )
1450 ProcessXMLSubElementOutput ( *e
.subElements
[i
] );
1452 if ( subs_invalid
&& e
.subElements
.size() > 0 )
1454 throw XMLInvalidBuildFileException (
1456 "<%s> cannot have sub-elements",
1462 Invoke::ProcessXMLSubElementInput ( const XMLElement
& e
)
1464 bool subs_invalid
= false;
1465 if ( e
.name
== "inputfile" && e
.value
.size () > 0 )
1467 input
.push_back ( new InvokeFile (
1468 e
, FixSeparator ( module
.output
->relative_path
+ cSep
+ e
.value
) ) );
1469 subs_invalid
= true;
1471 if ( subs_invalid
&& e
.subElements
.size() > 0 )
1473 throw XMLInvalidBuildFileException (
1475 "<%s> cannot have sub-elements",
1481 Invoke::ProcessXMLSubElementOutput ( const XMLElement
& e
)
1483 bool subs_invalid
= false;
1484 if ( e
.name
== "outputfile" && e
.value
.size () > 0 )
1486 output
.push_back ( new InvokeFile (
1487 e
, FixSeparator ( module
.output
->relative_path
+ cSep
+ e
.value
) ) );
1488 subs_invalid
= true;
1490 if ( subs_invalid
&& e
.subElements
.size() > 0 )
1492 throw XMLInvalidBuildFileException (
1494 "<%s> cannot have sub-elements",
1500 Invoke::GetTargets ( string_list
& targets
) const
1502 for ( size_t i
= 0; i
< output
.size (); i
++ )
1504 InvokeFile
& file
= *output
[i
];
1505 targets
.push_back ( NormalizeFilename ( file
.name
) );
1510 Invoke::GetParameters () const
1512 string
parameters ( "" );
1514 for ( i
= 0; i
< output
.size (); i
++ )
1516 if ( parameters
.length () > 0)
1518 InvokeFile
& invokeFile
= *output
[i
];
1519 if ( invokeFile
.switches
.length () > 0 )
1521 parameters
+= invokeFile
.switches
+ " ";
1523 parameters
+= invokeFile
.name
;
1526 for ( i
= 0; i
< input
.size (); i
++ )
1528 if ( parameters
.length () > 0 )
1530 InvokeFile
& invokeFile
= *input
[i
];
1531 if ( invokeFile
.switches
.length () > 0 )
1533 parameters
+= invokeFile
.switches
;
1536 parameters
+= invokeFile
.name
;
1543 InvokeFile::InvokeFile ( const XMLElement
& _node
,
1544 const string
& _name
)
1548 const XMLAttribute
* att
= _node
.GetAttribute ( "switches", false );
1550 switches
= att
->value
;
1556 InvokeFile::ProcessXML()
1561 Dependency::Dependency ( const XMLElement
& _node
,
1562 const Module
& _module
)
1565 dependencyModule (NULL
)
1570 Dependency::ProcessXML()
1572 dependencyModule
= module
.project
.LocateModule ( node
.value
);
1573 if ( dependencyModule
== NULL
)
1575 throw XMLInvalidBuildFileException (
1577 "module '%s' depend on non-existant module '%s'",
1578 module
.name
.c_str(),
1579 node
.value
.c_str() );
1584 Metadata::Metadata ( const XMLElement
& _node
,
1585 const Module
& _module
)
1589 /* The module name */
1590 const XMLAttribute
* att
= _node
.GetAttribute ( "name", false );
1596 /* The module description */
1597 att
= _node
.GetAttribute ( "description", false );
1599 description
= att
->value
;
1603 /* The module version */
1604 att
= _node
.GetAttribute ( "version", false );
1606 version
= att
->value
;
1610 /* The module copyright */
1611 att
= _node
.GetAttribute ( "copyright", false );
1613 copyright
= att
->value
;
1617 att
= _node
.GetAttribute ( "url", false );
1623 /* When was this module updated */
1624 att
= _node
.GetAttribute ( "date", false );
1630 /* When was this module updated */
1631 att
= _node
.GetAttribute ( "owner", false );
1639 ImportLibrary::~ImportLibrary ()
1645 ImportLibrary::ImportLibrary ( const Project
& project
,
1646 const XMLElement
& node
,
1647 const Module
& module
)
1648 : XmlNode ( project
, node
),
1651 const XMLAttribute
* dllname
= node
.GetAttribute ( "dllname", false );
1652 const XMLAttribute
* definition
= node
.GetAttribute ( "definition", true );
1653 assert ( definition
);
1656 this->dllname
= dllname
->value
;
1657 else if ( module
.type
== StaticLibrary
|| module
.type
== HostStaticLibrary
)
1658 throw XMLInvalidBuildFileException (
1660 "<importlibrary> dllname attribute required." );
1662 DirectoryLocation directory
= SourceDirectory
;
1663 size_t index
= definition
->value
.rfind ( ".spec.def" );
1664 if ( index
!= string::npos
)
1665 directory
= IntermediateDirectory
;
1667 index
= definition
->value
.find_last_of ( "/\\" );
1668 if ( index
== string::npos
)
1670 source
= new FileLocation ( directory
,
1671 module
.output
->relative_path
,
1677 string dir
= definition
->value
.substr ( 0, index
);
1678 string name
= definition
->value
.substr ( index
+ 1);
1679 source
= new FileLocation ( directory
,
1680 NormalizeFilename ( module
.output
->relative_path
+ sSep
+ dir
),
1687 If::If ( const XMLElement
& node_
,
1688 const Project
& project_
,
1689 const Module
* module_
,
1690 const bool negated_
)
1691 : node(node_
), project(project_
), module(module_
), negated(negated_
)
1693 const XMLAttribute
* att
;
1695 att
= node
.GetAttribute ( "property", true );
1697 property
= att
->value
;
1699 att
= node
.GetAttribute ( "value", true );
1715 Property::Property ( const XMLElement
& node_
,
1716 const Project
& project_
,
1717 const Module
* module_
)
1718 : project(project_
), module(module_
)
1720 const XMLAttribute
* att
;
1722 att
= node_
.GetAttribute ( "name", true );
1724 name
= project
.ResolveProperties ( att
->value
);
1726 att
= node_
.GetAttribute ( "value", true );
1730 att
= node_
.GetAttribute ( "internal", false );
1733 const char* p
= att
->value
.c_str();
1734 if ( !stricmp ( p
, "true" ) || !stricmp ( p
, "yes" ) )
1736 else if ( !stricmp ( p
, "false" ) || !stricmp ( p
, "no" ) )
1740 throw InvalidAttributeValueException (
1750 Property::Property ( const Project
& project_
,
1751 const Module
* module_
,
1752 const std::string
& name_
,
1753 const std::string
& value_
)
1754 : project(project_
), module(module_
), name(name_
), value(value_
)
1759 Property::ProcessXML()
1765 const XMLElement
& node_
,
1766 const Module
& module_
,
1767 const FileLocation
*file_
)
1768 : node(node_
), module(module_
), file(file_
)
1778 PchFile::ProcessXML()