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
),
255 if ( node
.name
!= "module" )
256 throw InvalidOperationException ( __FILE__
,
258 "Module created with non-<module> node" );
260 xmlbuildFile
= FixSeparator ( Path::RelativeFromWorkingDirectory ( moduleNode
.xmlFile
->filename () ) );
262 const XMLAttribute
* att
= moduleNode
.GetAttribute ( "name", true );
268 att
= moduleNode
.GetAttribute ( "if", false );
270 enabled
= GetBooleanValue ( project
.ResolveProperties ( att
->value
) );
272 att
= moduleNode
.GetAttribute ( "ifnot", false );
274 enabled
= !GetBooleanValue ( project
.ResolveProperties ( att
->value
) );
276 if ( !enabled
&& project
.configuration
.Verbose
)
277 printf("Module '%s' has been disabled.\n", name
.c_str () );
279 att
= moduleNode
.GetAttribute ( "type", true );
281 type
= GetModuleType ( node
.location
, *att
);
283 att
= moduleNode
.GetAttribute ( "extension", false );
285 extension
= att
->value
;
287 extension
= GetDefaultModuleExtension ();
289 att
= moduleNode
.GetAttribute ( "unicode", false );
292 const char* p
= att
->value
.c_str();
293 if ( !stricmp ( p
, "true" ) || !stricmp ( p
, "yes" ) )
295 else if ( !stricmp ( p
, "false" ) || !stricmp ( p
, "no" ) )
299 throw InvalidAttributeValueException (
310 // Always define UNICODE and _UNICODE
311 Define
* pDefine
= new Define ( project
, this, "UNICODE" );
312 non_if_data
.defines
.push_back ( pDefine
);
314 pDefine
= new Define ( project
, this, "_UNICODE" );
315 non_if_data
.defines
.push_back ( pDefine
);
318 att
= moduleNode
.GetAttribute ( "entrypoint", false );
321 if ( att
->value
== "" )
323 throw InvalidAttributeValueException (
329 entrypoint
= att
->value
;
330 isDefaultEntryPoint
= false;
334 entrypoint
= GetDefaultModuleEntrypoint ();
335 isDefaultEntryPoint
= true;
338 att
= moduleNode
.GetAttribute ( "baseaddress", false );
340 baseaddress
= att
->value
;
342 baseaddress
= GetDefaultModuleBaseaddress ();
344 att
= moduleNode
.GetAttribute ( "mangledsymbols", false );
347 const char* p
= att
->value
.c_str();
348 if ( !stricmp ( p
, "true" ) || !stricmp ( p
, "yes" ) )
349 mangledSymbols
= true;
350 else if ( !stricmp ( p
, "false" ) || !stricmp ( p
, "no" ) )
351 mangledSymbols
= false;
354 throw InvalidAttributeValueException (
361 mangledSymbols
= false;
363 att
= moduleNode
.GetAttribute ( "underscoresymbols", false );
365 underscoreSymbols
= att
->value
== "true";
367 underscoreSymbols
= false;
369 att
= moduleNode
.GetAttribute ( "host", false );
372 const char* p
= att
->value
.c_str();
373 if ( !stricmp ( p
, "true" ) || !stricmp ( p
, "yes" ) )
375 else if ( !stricmp ( p
, "false" ) || !stricmp ( p
, "no" ) )
379 throw InvalidAttributeValueException (
386 att
= moduleNode
.GetAttribute ( "isstartuplib", false );
389 const char* p
= att
->value
.c_str();
390 if ( !stricmp ( p
, "true" ) || !stricmp ( p
, "yes" ) )
392 else if ( !stricmp ( p
, "false" ) || !stricmp ( p
, "no" ) )
393 isStartupLib
= false;
396 throw InvalidAttributeValueException (
403 isStartupLib
= false;
405 att
= moduleNode
.GetAttribute ( "prefix", false );
409 att
= moduleNode
.GetAttribute ( "installname", false );
412 const XMLAttribute
* installbase
= moduleNode
.GetAttribute ( "installbase", false );
413 install
= new FileLocation ( InstallDirectory
,
414 installbase
? installbase
->value
: "",
418 output
= new FileLocation ( GetTargetDirectoryTree (),
424 att
= moduleNode
.GetAttribute ( "output", false );
429 printf ( "%s: WARNING: 'installname' overrides 'output' also defined for this module.\n",
430 moduleNode
.location
.c_str() );
434 output
= new FileLocation ( GetTargetDirectoryTree (),
441 /* If no one has set the output file for this module set it automatically */
444 output
= new FileLocation ( GetTargetDirectoryTree (),
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
;
477 if ( type
== BootProgram
|| type
== ElfExecutable
)
479 att
= moduleNode
.GetAttribute ( "buildtype", false );
482 buildtype
= att
->value
;
486 buildtype
= "BOOTPROG";
490 att
= moduleNode
.GetAttribute ( "description", false );
493 description
= project
.ResolveProperties(att
->value
);
498 att
= moduleNode
.GetAttribute ( "lcid", false );
499 if (type
== KeyboardLayout
&& att
!= NULL
)
504 att
= moduleNode
.GetAttribute ( "layoutid", false );
505 if (type
== KeyboardLayout
&& att
!= NULL
)
506 layoutId
= att
->value
;
510 att
= moduleNode
.GetAttribute ( "layoutnameresid", false );
511 if (type
== KeyboardLayout
&& att
!= NULL
)
512 layoutNameResId
= att
->value
;
514 layoutNameResId
= "";
516 SetImportLibrary ( NULL
);
522 for ( i
= 0; i
< invocations
.size(); i
++ )
523 delete invocations
[i
];
524 for ( i
= 0; i
< dependencies
.size(); i
++ )
525 delete dependencies
[i
];
526 for ( i
= 0; i
< compilerFlags
.size(); i
++ )
527 delete compilerFlags
[i
];
528 for ( i
= 0; i
< linkerFlags
.size(); i
++ )
529 delete linkerFlags
[i
];
530 for ( i
= 0; i
< stubbedComponents
.size(); i
++ )
531 delete stubbedComponents
[i
];
543 delete importLibrary
;
559 aliasedModuleName
= project
.ResolveProperties ( aliasedModuleName
);
560 if ( aliasedModuleName
== name
)
562 throw XMLInvalidBuildFileException (
564 "module '%s' cannot link against itself",
567 const Module
* m
= project
.LocateModule ( aliasedModuleName
);
570 throw XMLInvalidBuildFileException (
572 "module '%s' trying to alias non-existant module '%s'",
574 aliasedModuleName
.c_str() );
579 for ( i
= 0; i
< node
.subElements
.size(); i
++ )
581 ParseContext parseContext
;
582 ProcessXMLSubElement ( *node
.subElements
[i
], SourceDirectory
, output
->relative_path
, parseContext
);
584 for ( i
= 0; i
< invocations
.size(); i
++ )
585 invocations
[i
]->ProcessXML ();
586 for ( i
= 0; i
< dependencies
.size(); i
++ )
587 dependencies
[i
]->ProcessXML ();
588 for ( i
= 0; i
< compilerFlags
.size(); i
++ )
589 compilerFlags
[i
]->ProcessXML();
590 for ( i
= 0; i
< linkerFlags
.size(); i
++ )
591 linkerFlags
[i
]->ProcessXML();
592 for ( i
= 0; i
< stubbedComponents
.size(); i
++ )
593 stubbedComponents
[i
]->ProcessXML();
594 non_if_data
.ProcessXML();
596 linkerScript
->ProcessXML();
600 autoRegister
->ProcessXML();
604 Module::ProcessXMLSubElement ( const XMLElement
& e
,
605 DirectoryLocation directory
,
606 const string
& relative_path
,
607 ParseContext
& parseContext
)
609 If
* pOldIf
= parseContext
.ifData
;
610 CompilationUnit
* pOldCompilationUnit
= parseContext
.compilationUnit
;
611 bool subs_invalid
= false;
612 string
subpath ( relative_path
);
613 DirectoryLocation subdirectory
= SourceDirectory
;
614 if ( e
.name
== "file" && e
.value
.size () > 0 )
617 const XMLAttribute
* att
= e
.GetAttribute ( "first", false );
620 if ( !stricmp ( att
->value
.c_str(), "true" ) )
622 else if ( stricmp ( att
->value
.c_str(), "false" ) )
624 throw XMLInvalidBuildFileException (
626 "attribute 'first' of <file> element can only be 'true' or 'false'" );
629 string switches
= "";
630 att
= e
.GetAttribute ( "switches", false );
632 switches
= att
->value
;
635 // check for c++ file
636 string ext
= GetExtension ( e
.value
);
637 if ( !stricmp ( ext
.c_str(), ".cpp" ) )
639 else if ( !stricmp ( ext
.c_str(), ".cc" ) )
641 else if ( !stricmp ( ext
.c_str(), ".cxx" ) )
644 File
* pFile
= new File ( directory
,
650 if ( parseContext
.compilationUnit
)
651 parseContext
.compilationUnit
->AddFile ( pFile
);
654 CompilationUnit
* pCompilationUnit
= new CompilationUnit ( pFile
);
655 if ( parseContext
.ifData
)
656 parseContext
.ifData
->data
.compilationUnits
.push_back ( pCompilationUnit
);
659 string ext
= ToLower ( GetExtension ( e
.value
) );
662 // put .idl files at the start of the module
663 non_if_data
.compilationUnits
.insert (
664 non_if_data
.compilationUnits
.begin(),
667 else if ( ext
== ".asm" || ext
== ".s" )
669 // put .asm files at the end of the module
670 non_if_data
.compilationUnits
.push_back ( pCompilationUnit
);
671 non_if_data
.asmFiles
++;
675 // put other files in the middle
676 non_if_data
.compilationUnits
.insert (
677 non_if_data
.compilationUnits
.end() - non_if_data
.asmFiles
,
682 if ( parseContext
.ifData
)
683 parseContext
.ifData
->data
.files
.push_back ( pFile
);
685 non_if_data
.files
.push_back ( pFile
);
688 else if ( e
.name
== "library" && e
.value
.size () )
690 Library
* pLibrary
= new Library ( e
, *this, e
.value
);
691 if ( parseContext
.ifData
)
692 parseContext
.ifData
->data
.libraries
.push_back ( pLibrary
);
694 non_if_data
.libraries
.push_back ( pLibrary
);
697 else if ( e
.name
== "directory" )
699 const XMLAttribute
* att
= e
.GetAttribute ( "name", true );
700 const XMLAttribute
* root
= e
.GetAttribute ( "root", false );
704 if ( root
->value
== "intermediate" )
705 subdirectory
= IntermediateDirectory
;
706 else if ( root
->value
== "output" )
707 subdirectory
= OutputDirectory
;
710 throw InvalidAttributeValueException (
716 subpath
= GetSubPath ( this->project
, e
.location
, relative_path
, att
->value
);
718 else if ( e
.name
== "include" )
720 Include
* include
= new Include ( project
, &e
, this );
721 if ( parseContext
.ifData
)
722 parseContext
.ifData
->data
.includes
.push_back ( include
);
724 non_if_data
.includes
.push_back ( include
);
727 else if ( e
.name
== "define" )
729 Define
* pDefine
= new Define ( project
, this, e
);
730 if ( parseContext
.ifData
)
731 parseContext
.ifData
->data
.defines
.push_back ( pDefine
);
733 non_if_data
.defines
.push_back ( pDefine
);
736 else if ( e
.name
== "metadata" )
738 if ( parseContext
.ifData
)
740 throw XMLInvalidBuildFileException (
742 "<metadata> is not a valid sub-element of <if>" );
744 metadata
= new Metadata ( e
, *this );
745 subs_invalid
= false;
747 else if ( e
.name
== "invoke" )
749 if ( parseContext
.ifData
)
751 throw XMLInvalidBuildFileException (
753 "<invoke> is not a valid sub-element of <if>" );
755 invocations
.push_back ( new Invoke ( e
, *this ) );
756 subs_invalid
= false;
758 else if ( e
.name
== "dependency" )
760 if ( parseContext
.ifData
)
762 throw XMLInvalidBuildFileException (
764 "<dependency> is not a valid sub-element of <if>" );
766 dependencies
.push_back ( new Dependency ( e
, *this ) );
769 else if ( e
.name
== "bootsector" )
771 if ( parseContext
.ifData
)
773 throw XMLInvalidBuildFileException (
775 "<bootsector> is not a valid sub-element of <if>" );
777 bootSector
= new Bootsector ( e
, this );
780 else if ( e
.name
== "importlibrary" )
782 if ( parseContext
.ifData
)
784 throw XMLInvalidBuildFileException (
786 "<importlibrary> is not a valid sub-element of <if>" );
790 throw XMLInvalidBuildFileException (
792 "Only one <importlibrary> is valid per module" );
794 SetImportLibrary ( new ImportLibrary ( project
, e
, this ) );
797 else if ( e
.name
== "if" )
799 parseContext
.ifData
= new If ( e
, project
, this );
801 pOldIf
->data
.ifs
.push_back ( parseContext
.ifData
);
803 non_if_data
.ifs
.push_back ( parseContext
.ifData
);
804 subs_invalid
= false;
806 else if ( e
.name
== "ifnot" )
808 parseContext
.ifData
= new If ( e
, project
, this, true );
810 pOldIf
->data
.ifs
.push_back ( parseContext
.ifData
);
812 non_if_data
.ifs
.push_back ( parseContext
.ifData
);
813 subs_invalid
= false;
815 else if ( e
.name
== "compilerflag" )
817 CompilerFlag
* pCompilerFlag
= new CompilerFlag ( project
, this, e
);
818 if ( parseContext
.ifData
)
819 parseContext
.ifData
->data
.compilerFlags
.push_back ( pCompilerFlag
);
821 non_if_data
.compilerFlags
.push_back ( pCompilerFlag
);
824 else if ( e
.name
== "linkerflag" )
826 linkerFlags
.push_back ( new LinkerFlag ( project
, this, e
) );
829 else if ( e
.name
== "linkerscript" )
831 if ( parseContext
.ifData
)
833 throw XMLInvalidBuildFileException (
835 "<linkerscript> is not a valid sub-element of <if>" );
839 throw XMLInvalidBuildFileException (
841 "Only one <linkerscript> is valid per module" );
843 size_t pos
= e
.value
.find_last_of ( "/\\" );
844 if ( pos
== string::npos
)
846 linkerScript
= new LinkerScript (
847 e
, *this, new FileLocation ( SourceDirectory
, relative_path
, e
.value
, &e
) );
851 string dir
= e
.value
.substr ( 0, pos
);
852 string name
= e
.value
.substr ( pos
+ 1);
853 linkerScript
= new LinkerScript (
854 e
, *this, new FileLocation ( SourceDirectory
, relative_path
+ sSep
+ dir
, name
, &e
) );
858 else if ( e
.name
== "component" )
860 stubbedComponents
.push_back ( new StubbedComponent ( this, e
) );
861 subs_invalid
= false;
863 else if ( e
.name
== "property" )
865 throw XMLInvalidBuildFileException (
867 "<property> is not a valid sub-element of <module>" );
869 else if ( e
.name
== "bootstrap" )
871 bootstrap
= new Bootstrap ( project
, this, e
);
874 else if ( e
.name
== "pch" )
876 if ( parseContext
.ifData
)
878 throw XMLInvalidBuildFileException (
880 "<pch> is not a valid sub-element of <if>" );
884 throw XMLInvalidBuildFileException (
886 "Only one <pch> is valid per module" );
888 size_t pos
= e
.value
.find_last_of ( "/\\" );
889 if ( pos
== string::npos
)
892 e
, *this, new FileLocation ( SourceDirectory
, relative_path
, e
.value
, &e
) );
896 string dir
= e
.value
.substr ( 0, pos
);
897 string name
= e
.value
.substr ( pos
+ 1);
899 e
, *this, new FileLocation ( SourceDirectory
, relative_path
+ sSep
+ dir
, name
, &e
) );
903 else if ( e
.name
== "compilationunit" )
905 if ( project
.configuration
.CompilationUnitsEnabled
)
907 CompilationUnit
* pCompilationUnit
= new CompilationUnit ( &project
, this, &e
);
908 if ( parseContext
.ifData
)
909 parseContext
.ifData
->data
.compilationUnits
.push_back ( pCompilationUnit
);
911 non_if_data
.compilationUnits
.push_back ( pCompilationUnit
);
912 parseContext
.compilationUnit
= pCompilationUnit
;
914 subs_invalid
= false;
916 else if ( e
.name
== "autoregister" )
918 if ( autoRegister
!= NULL
)
920 throw XMLInvalidBuildFileException (
922 "there can be only one <%s> element for a module",
925 autoRegister
= new AutoRegister ( project
, this, e
);
928 if ( subs_invalid
&& e
.subElements
.size() > 0 )
930 throw XMLInvalidBuildFileException (
932 "<%s> cannot have sub-elements",
935 for ( size_t i
= 0; i
< e
.subElements
.size (); i
++ )
936 ProcessXMLSubElement ( *e
.subElements
[i
], subdirectory
, subpath
, parseContext
);
937 parseContext
.ifData
= pOldIf
;
938 parseContext
.compilationUnit
= pOldCompilationUnit
;
942 Module::GetModuleType ( const string
& location
, const XMLAttribute
& attribute
)
944 if ( attribute
.value
== "buildtool" )
946 if ( attribute
.value
== "staticlibrary" )
947 return StaticLibrary
;
948 if ( attribute
.value
== "hoststaticlibrary" )
949 return HostStaticLibrary
;
950 if ( attribute
.value
== "objectlibrary" )
951 return ObjectLibrary
;
952 if ( attribute
.value
== "kernel" )
954 if ( attribute
.value
== "kernelmodedll" )
955 return KernelModeDLL
;
956 if ( attribute
.value
== "kernelmodedriver" )
957 return KernelModeDriver
;
958 if ( attribute
.value
== "nativedll" )
960 if ( attribute
.value
== "nativecui" )
962 if ( attribute
.value
== "keyboardlayout" )
963 return KeyboardLayout
;
964 if ( attribute
.value
== "win32dll" )
966 if ( attribute
.value
== "win32ocx" )
968 if ( attribute
.value
== "win32cui" )
970 if ( attribute
.value
== "win32gui" )
972 if ( attribute
.value
== "win32scr" )
974 if ( attribute
.value
== "bootloader" )
976 if ( attribute
.value
== "bootsector" )
978 if ( attribute
.value
== "bootprogram" )
980 if ( attribute
.value
== "iso" )
982 if ( attribute
.value
== "liveiso" )
984 if ( attribute
.value
== "isoregtest" )
986 if ( attribute
.value
== "liveisoregtest" )
987 return LiveIsoRegTest
;
988 if ( attribute
.value
== "test" )
990 if ( attribute
.value
== "rpcserver" )
992 if ( attribute
.value
== "rpcclient" )
994 if ( attribute
.value
== "rpcproxy" )
996 if ( attribute
.value
== "alias" )
998 if ( attribute
.value
== "idlheader" )
1000 if ( attribute
.value
== "embeddedtypelib" )
1001 return EmbeddedTypeLib
;
1002 if ( attribute
.value
== "elfexecutable" )
1003 return ElfExecutable
;
1004 if ( attribute
.value
== "cabinet" )
1006 if ( attribute
.value
== "messageheader" )
1007 return MessageHeader
;
1008 throw InvalidAttributeValueException ( location
,
1014 Module::GetTargetDirectoryTree () const
1020 case KeyboardLayout
:
1024 case KernelModeDriver
:
1037 case LiveIsoRegTest
:
1040 return OutputDirectory
;
1041 case EmbeddedTypeLib
:
1043 case HostStaticLibrary
:
1051 return IntermediateDirectory
;
1055 throw InvalidOperationException ( __FILE__
,
1057 "Invalid module type %d.",
1062 Module::GetDefaultModuleExtension () const
1070 case HostStaticLibrary
:
1084 case KeyboardLayout
:
1089 case KernelModeDriver
:
1099 case LiveIsoRegTest
:
1112 case EmbeddedTypeLib
:
1117 throw InvalidOperationException ( __FILE__
,
1122 Module::GetDefaultModuleEntrypoint () const
1127 return "KiSystemStartup";
1128 case KeyboardLayout
:
1130 case KernelModeDriver
:
1131 return "DriverEntry@8";
1133 return "DllMainCRTStartup@12";
1135 return "NtProcessStartup@4";
1138 return "DllMain@12";
1142 return "wmainCRTStartup";
1144 return "mainCRTStartup";
1148 return "wWinMainCRTStartup";
1150 return "WinMainCRTStartup";
1153 case HostStaticLibrary
:
1160 case LiveIsoRegTest
:
1169 case EmbeddedTypeLib
:
1175 throw InvalidOperationException ( __FILE__
,
1180 Module::GetDefaultModuleBaseaddress () const
1185 return "0x80800000";
1188 return "0x10000000";
1193 return "0x00400000";
1196 return "0x00400000";
1197 case KeyboardLayout
:
1199 case KernelModeDriver
:
1200 return "0x00010000";
1205 case HostStaticLibrary
:
1212 case LiveIsoRegTest
:
1220 case EmbeddedTypeLib
:
1226 throw InvalidOperationException ( __FILE__
,
1231 Module::HasImportLibrary () const
1233 return importLibrary
!= NULL
&& type
!= StaticLibrary
&& type
!= HostStaticLibrary
;
1237 Module::IsDLL () const
1244 case KeyboardLayout
:
1247 case KernelModeDriver
:
1256 case HostStaticLibrary
:
1264 case LiveIsoRegTest
:
1271 case EmbeddedTypeLib
:
1278 throw InvalidOperationException ( __FILE__
,
1283 Module::GetPathWithPrefix ( const string
& prefix
) const
1285 return output
->relative_path
+ cSep
+ prefix
+ output
->name
;
1289 Module::GetPathToBaseDir () const
1291 string temp_path
= output
->relative_path
;
1292 string result
= "..\\";
1293 while(temp_path
.find ('\\') != string::npos
)
1295 temp_path
.erase (0, temp_path
.find('\\')+1);
1302 Module::GetInvocationTarget ( const int index
) const
1304 return ssprintf ( "%s_invoke_%d",
1310 Module::GetEntryPoint(bool leadingUnderscore
) const
1313 if (entrypoint
== "0" || entrypoint
== "0x0")
1315 if (leadingUnderscore
)
1318 result
+= entrypoint
;
1320 if (Environment::GetArch() == "amd64")
1322 size_t at_index
= result
.find_last_of( '@' );
1323 if ( at_index
!= result
.npos
)
1324 return result
.substr (0, at_index
);
1331 Module::HasFileWithExtension (
1332 const IfableData
& data
,
1333 const std::string
& extension
) const
1336 for ( i
= 0; i
< data
.compilationUnits
.size (); i
++ )
1338 CompilationUnit
* compilationUnit
= data
.compilationUnits
[i
];
1339 if ( compilationUnit
->HasFileWithExtension ( extension
) )
1342 for ( i
= 0; i
< data
.ifs
.size (); i
++ )
1344 if ( HasFileWithExtension ( data
.ifs
[i
]->data
, extension
) )
1351 Module::InvokeModule () const
1353 for ( size_t i
= 0; i
< invocations
.size (); i
++ )
1355 Invoke
& invoke
= *invocations
[i
];
1356 string command
= FixSeparatorForSystemCommand(invoke
.invokeModule
->output
->relative_path
+ "/" + invoke
.invokeModule
->output
->name
) + " " + invoke
.GetParameters ();
1357 printf ( "Executing '%s'\n\n", command
.c_str () );
1358 int exitcode
= system ( command
.c_str () );
1359 if ( exitcode
!= 0 )
1360 throw InvocationFailedException ( command
,
1367 Module::SetImportLibrary ( ImportLibrary
* importLibrary
)
1369 this->importLibrary
= importLibrary
;
1370 dependency
= new FileLocation ( HasImportLibrary () ? IntermediateDirectory
: output
->directory
,
1371 output
->relative_path
,
1372 HasImportLibrary () ? "lib" + name
+ ".a" : output
->name
);
1376 File::File ( DirectoryLocation directory
,
1377 const string
& relative_path
,
1380 const string
& _switches
,
1381 bool _isPreCompiledHeader
)
1382 : file ( directory
, relative_path
, name
),
1384 switches(_switches
),
1385 isPreCompiledHeader(_isPreCompiledHeader
)
1396 std::string
File::GetFullPath () const
1398 string
directory ( "" );
1399 switch ( file
.directory
)
1401 case SourceDirectory
:
1403 case IntermediateDirectory
:
1404 directory
= Environment::GetIntermediatePath () + sSep
;
1407 throw InvalidOperationException ( __FILE__
,
1409 "Invalid directory %d.",
1413 if ( file
.relative_path
.length () > 0 )
1414 directory
+= file
.relative_path
+ sSep
;
1417 return directory
+ file
.name
;
1421 Library::Library ( const XMLElement
& _node
,
1422 const Module
& _module
,
1423 const string
& _name
)
1427 importedModule(_module
.project
.LocateModule(_name
))
1429 if ( module
.name
== name
)
1431 throw XMLInvalidBuildFileException (
1433 "module '%s' cannot link against itself",
1436 if ( !importedModule
)
1438 throw XMLInvalidBuildFileException (
1440 "module '%s' trying to import non-existant module '%s'",
1441 module
.name
.c_str(),
1446 Library::Library ( const Module
& _module
,
1447 const string
& _name
)
1451 importedModule(_module
.project
.LocateModule(_name
))
1456 Library::ProcessXML()
1458 if ( node
&& !module
.project
.LocateModule ( name
) )
1460 throw XMLInvalidBuildFileException (
1462 "module '%s' is trying to link against non-existant module '%s'",
1463 module
.name
.c_str(),
1469 Invoke::Invoke ( const XMLElement
& _node
,
1470 const Module
& _module
)
1477 Invoke::ProcessXML()
1479 const XMLAttribute
* att
= node
.GetAttribute ( "module", false );
1481 invokeModule
= &module
;
1484 invokeModule
= module
.project
.LocateModule ( att
->value
);
1485 if ( invokeModule
== NULL
)
1487 throw XMLInvalidBuildFileException (
1489 "module '%s' is trying to invoke non-existant module '%s'",
1490 module
.name
.c_str(),
1491 att
->value
.c_str() );
1495 for ( size_t i
= 0; i
< node
.subElements
.size (); i
++ )
1496 ProcessXMLSubElement ( *node
.subElements
[i
] );
1500 Invoke::ProcessXMLSubElement ( const XMLElement
& e
)
1502 bool subs_invalid
= false;
1503 if ( e
.name
== "input" )
1505 for ( size_t i
= 0; i
< e
.subElements
.size (); i
++ )
1506 ProcessXMLSubElementInput ( *e
.subElements
[i
] );
1508 else if ( e
.name
== "output" )
1510 for ( size_t i
= 0; i
< e
.subElements
.size (); i
++ )
1511 ProcessXMLSubElementOutput ( *e
.subElements
[i
] );
1513 if ( subs_invalid
&& e
.subElements
.size() > 0 )
1515 throw XMLInvalidBuildFileException (
1517 "<%s> cannot have sub-elements",
1523 Invoke::ProcessXMLSubElementInput ( const XMLElement
& e
)
1525 bool subs_invalid
= false;
1526 if ( e
.name
== "inputfile" && e
.value
.size () > 0 )
1528 input
.push_back ( new InvokeFile (
1529 e
, FixSeparator ( module
.output
->relative_path
+ cSep
+ e
.value
) ) );
1530 subs_invalid
= true;
1532 if ( subs_invalid
&& e
.subElements
.size() > 0 )
1534 throw XMLInvalidBuildFileException (
1536 "<%s> cannot have sub-elements",
1542 Invoke::ProcessXMLSubElementOutput ( const XMLElement
& e
)
1544 bool subs_invalid
= false;
1545 if ( e
.name
== "outputfile" && e
.value
.size () > 0 )
1547 output
.push_back ( new InvokeFile (
1548 e
, FixSeparator ( module
.output
->relative_path
+ cSep
+ e
.value
) ) );
1549 subs_invalid
= true;
1551 if ( subs_invalid
&& e
.subElements
.size() > 0 )
1553 throw XMLInvalidBuildFileException (
1555 "<%s> cannot have sub-elements",
1561 Invoke::GetTargets ( string_list
& targets
) const
1563 for ( size_t i
= 0; i
< output
.size (); i
++ )
1565 InvokeFile
& file
= *output
[i
];
1566 targets
.push_back ( NormalizeFilename ( file
.name
) );
1571 Invoke::GetParameters () const
1573 string
parameters ( "" );
1575 for ( i
= 0; i
< output
.size (); i
++ )
1577 if ( parameters
.length () > 0)
1579 InvokeFile
& invokeFile
= *output
[i
];
1580 if ( invokeFile
.switches
.length () > 0 )
1582 parameters
+= invokeFile
.switches
+ " ";
1584 parameters
+= invokeFile
.name
;
1587 for ( i
= 0; i
< input
.size (); i
++ )
1589 if ( parameters
.length () > 0 )
1591 InvokeFile
& invokeFile
= *input
[i
];
1592 if ( invokeFile
.switches
.length () > 0 )
1594 parameters
+= invokeFile
.switches
;
1597 parameters
+= invokeFile
.name
;
1604 InvokeFile::InvokeFile ( const XMLElement
& _node
,
1605 const string
& _name
)
1609 const XMLAttribute
* att
= _node
.GetAttribute ( "switches", false );
1611 switches
= att
->value
;
1617 InvokeFile::ProcessXML()
1622 Dependency::Dependency ( const XMLElement
& _node
,
1623 const Module
& _module
)
1626 dependencyModule (NULL
)
1631 Dependency::ProcessXML()
1633 dependencyModule
= module
.project
.LocateModule ( node
.value
);
1634 if ( dependencyModule
== NULL
)
1636 throw XMLInvalidBuildFileException (
1638 "module '%s' depend on non-existant module '%s'",
1639 module
.name
.c_str(),
1640 node
.value
.c_str() );
1644 Bootsector::Bootsector ( const XMLElement
& _node
,
1645 const Module
* _module
)
1648 bootSectorModule (NULL
)
1650 if ( !IsSupportedModuleType ( module
->type
) )
1652 throw XMLInvalidBuildFileException (
1654 "<bootsector> is not applicable for this module type." );
1657 bootSectorModule
= module
->project
.LocateModule ( node
.value
);
1658 if ( bootSectorModule
== NULL
)
1660 throw XMLInvalidBuildFileException (
1662 "module '%s' depend on non-existant module '%s'",
1663 module
->name
.c_str(),
1664 node
.value
.c_str() );
1667 if (bootSectorModule
->type
!= BootSector
)
1669 throw XMLInvalidBuildFileException (
1671 "module '%s' is referencing non BootSector module '%s'",
1672 module
->name
.c_str(),
1673 node
.value
.c_str() );
1678 Bootsector::ProcessXML()
1683 Bootsector::IsSupportedModuleType ( ModuleType type
)
1687 type
== IsoRegTest
||
1688 type
== LiveIsoRegTest
)
1696 Metadata::Metadata ( const XMLElement
& _node
,
1697 const Module
& _module
)
1701 /* The module name */
1702 const XMLAttribute
* att
= _node
.GetAttribute ( "name", false );
1708 /* The module description */
1709 att
= _node
.GetAttribute ( "description", false );
1711 description
= att
->value
;
1715 /* The module version */
1716 att
= _node
.GetAttribute ( "version", false );
1718 version
= att
->value
;
1722 /* The module copyright */
1723 att
= _node
.GetAttribute ( "copyright", false );
1725 copyright
= att
->value
;
1729 att
= _node
.GetAttribute ( "url", false );
1735 /* When was this module updated */
1736 att
= _node
.GetAttribute ( "date", false );
1742 /* When was this module updated */
1743 att
= _node
.GetAttribute ( "owner", false );
1751 ImportLibrary::~ImportLibrary ()
1757 ImportLibrary::ImportLibrary ( const Project
& project
,
1758 const XMLElement
& node
,
1759 const Module
* module
)
1760 : XmlNode ( project
, node
),
1763 DirectoryLocation directory
= SourceDirectory
;
1764 const Module
* base
= module
;
1765 const XMLAttribute
* dllname
= node
.GetAttribute ( "dllname", false );
1766 const XMLAttribute
* definition
= node
.GetAttribute ( "definition", true );
1767 assert ( definition
);
1769 string relative_path
;
1770 const XMLAttribute
* att
= node
.GetAttribute ( "base", false );
1773 base
= project
.LocateModule ( att
->value
);
1775 throw XMLInvalidBuildFileException (
1777 "<importlibrary> attribute 'base' references non-existant module '%s'",
1778 att
->value
.c_str() );
1784 relative_path
= base
->output
->relative_path
;
1785 if ( node
.value
.length () > 0 && node
.value
!= "." )
1786 relative_path
+= sSep
+ node
.value
;
1789 relative_path
= node
.value
;
1791 att
= node
.GetAttribute ( "root", false );
1794 if ( att
->value
== "intermediate" )
1795 directory
= IntermediateDirectory
;
1797 throw InvalidAttributeValueException ( node
.location
,
1803 size_t index
= definition
->value
.rfind ( ".spec.def" );
1804 if ( index
!= string::npos
)
1805 directory
= IntermediateDirectory
;
1809 this->dllname
= dllname
->value
;
1810 else if ( module
->type
== StaticLibrary
|| module
->type
== HostStaticLibrary
)
1811 throw XMLInvalidBuildFileException (
1813 "<importlibrary> dllname attribute required." );
1815 size_t index
= definition
->value
.find_last_of ( "/\\" );
1816 if ( index
== string::npos
)
1818 source
= new FileLocation ( directory
,
1819 base
->output
->relative_path
,
1825 string dir
= definition
->value
.substr ( 0, index
);
1826 string name
= definition
->value
.substr ( index
+ 1);
1827 source
= new FileLocation ( directory
,
1828 NormalizeFilename ( base
->output
->relative_path
+ sSep
+ dir
),
1835 If::If ( const XMLElement
& node_
,
1836 const Project
& project_
,
1837 const Module
* module_
,
1838 const bool negated_
)
1839 : node(node_
), project(project_
), module(module_
), negated(negated_
)
1841 const XMLAttribute
* att
;
1843 att
= node
.GetAttribute ( "property", true );
1845 property
= att
->value
;
1847 att
= node
.GetAttribute ( "value", true );
1863 Property::Property ( const XMLElement
& node_
,
1864 const Project
& project_
,
1865 const Module
* module_
)
1866 : project(project_
), module(module_
)
1868 const XMLAttribute
* att
;
1870 att
= node_
.GetAttribute ( "name", true );
1872 name
= project
.ResolveProperties ( att
->value
);
1874 att
= node_
.GetAttribute ( "value", true );
1878 att
= node_
.GetAttribute ( "internal", false );
1881 const char* p
= att
->value
.c_str();
1882 if ( !stricmp ( p
, "true" ) || !stricmp ( p
, "yes" ) )
1884 else if ( !stricmp ( p
, "false" ) || !stricmp ( p
, "no" ) )
1888 throw InvalidAttributeValueException (
1898 Property::Property ( const Project
& project_
,
1899 const Module
* module_
,
1900 const std::string
& name_
,
1901 const std::string
& value_
)
1902 : project(project_
), module(module_
), name(name_
), value(value_
)
1907 Property::ProcessXML()
1913 const XMLElement
& node_
,
1914 const Module
& module_
,
1915 const FileLocation
*file_
)
1916 : node(node_
), module(module_
), file(file_
)
1926 PchFile::ProcessXML()