2 * Copyright (C) 2005 Casper S. Hornstrup
3 * Copyright (C) 2008 Hervé Poussineau
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28 Right ( const string
& s
, size_t n
)
32 return string ( &s
[s
.size()-n
] );
36 Replace ( const string
& s
, const string
& find
, const string
& with
)
39 const char* p
= s
.c_str();
42 const char* p2
= strstr ( p
, find
.c_str() );
46 ret
+= string ( p
, p2
-p
);
56 ChangeSeparator ( const string
& s
,
57 const char fromSeparator
,
58 const char toSeparator
)
61 char* p
= strchr ( &s2
[0], fromSeparator
);
65 p
= strchr ( p
, fromSeparator
);
71 FixSeparator ( const string
& s
)
73 return ChangeSeparator ( s
, cBadSep
, cSep
);
77 FixSeparatorForSystemCommand ( const string
& s
)
80 char* p
= strchr ( &s2
[0], DEF_CBAD_SEP
);
84 p
= strchr ( p
, DEF_CBAD_SEP
);
90 DosSeparator ( const string
& s
)
93 char* p
= strchr ( &s2
[0], '/' );
97 p
= strchr ( p
, '/' );
104 const string
& filename
,
105 const string
& newExtension
)
107 size_t index
= filename
.find_last_of ( '/' );
108 if ( index
== string::npos
)
110 size_t index2
= filename
.find_last_of ( '\\' );
111 if ( index2
!= string::npos
&& index2
> index
)
113 string tmp
= filename
.substr( index
/*, filename.size() - index*/ );
114 size_t ext_index
= tmp
.find_last_of( '.' );
115 if ( ext_index
!= string::npos
)
116 return filename
.substr ( 0, index
+ ext_index
) + newExtension
;
117 return filename
+ newExtension
;
122 const Project
& project
,
123 const string
& location
,
125 const string
& att_value
)
127 if ( !att_value
.size() )
128 throw XMLInvalidBuildFileException (
130 "<directory> tag has empty 'name' attribute" );
131 if ( strpbrk ( att_value
.c_str (), "/\\?*:<>|" ) )
132 throw XMLInvalidBuildFileException (
134 "<directory> tag has invalid characters in 'name' attribute" );
138 return FixSeparator(path
+ cSep
+ att_value
);
142 GetExtension ( const string
& filename
)
144 size_t index
= filename
.find_last_of ( '/' );
145 if (index
== string::npos
) index
= 0;
146 string tmp
= filename
.substr( index
, filename
.size() - index
);
147 size_t ext_index
= tmp
.find_last_of( '.' );
148 if (ext_index
!= string::npos
)
149 return filename
.substr ( index
+ ext_index
, filename
.size() );
154 GetExtension ( const FileLocation
& file
)
156 return GetExtension ( file
.name
);
160 NormalizeFilename ( const string
& filename
)
162 if ( filename
== "" )
165 string normalizedPath
= path
.Fixup ( filename
, true );
166 string relativeNormalizedPath
= path
.RelativeFromWorkingDirectory ( normalizedPath
);
167 return FixSeparator ( relativeNormalizedPath
);
171 GetBooleanValue ( const string
& value
)
180 ToLower ( string filename
)
182 for ( size_t i
= 1; i
< filename
.length (); i
++ )
183 filename
[i
] = tolower ( filename
[i
] );
187 IfableData::IfableData( )
192 void IfableData::ExtractModules( std::vector
<Module
*> &modules
)
195 for ( i
= 0; i
< this->modules
.size (); i
++ )
196 modules
.push_back(this->modules
[i
]);
199 IfableData::~IfableData()
202 for ( i
= 0; i
< includes
.size (); i
++ )
204 for ( i
= 0; i
< defines
.size (); i
++ )
206 for ( i
= 0; i
< libraries
.size (); i
++ )
208 for ( i
= 0; i
< properties
.size (); i
++ )
209 delete properties
[i
];
210 for ( i
= 0; i
< compilerFlags
.size (); i
++ )
211 delete compilerFlags
[i
];
212 for ( i
= 0; i
< modules
.size(); i
++ )
214 for ( i
= 0; i
< compilationUnits
.size (); i
++ )
215 delete compilationUnits
[i
];
218 void IfableData::ProcessXML ()
221 for ( i
= 0; i
< includes
.size (); i
++ )
222 includes
[i
]->ProcessXML ();
223 for ( i
= 0; i
< defines
.size (); i
++ )
224 defines
[i
]->ProcessXML ();
225 for ( i
= 0; i
< libraries
.size (); i
++ )
226 libraries
[i
]->ProcessXML ();
227 for ( i
= 0; i
< properties
.size(); i
++ )
228 properties
[i
]->ProcessXML ();
229 for ( i
= 0; i
< compilerFlags
.size(); i
++ )
230 compilerFlags
[i
]->ProcessXML ();
231 for ( i
= 0; i
< compilationUnits
.size (); i
++ )
232 compilationUnits
[i
]->ProcessXML ();
235 Module::Module ( const Project
& project
,
236 const XMLElement
& moduleNode
,
237 const string
& modulePath
)
240 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 (),
421 att
= moduleNode
.GetAttribute ( "output", false );
426 printf ( "%s: WARNING: 'installname' overrides 'output' also defined for this module.\n",
427 moduleNode
.location
.c_str() );
431 output
= new FileLocation ( GetTargetDirectoryTree (),
438 /* If no one has set the output file for this module set it automatically */
441 output
= new FileLocation ( GetTargetDirectoryTree (),
447 att
= moduleNode
.GetAttribute ( "allowwarnings", false );
450 att
= moduleNode
.GetAttribute ( "warnings", false );
453 printf ( "%s: WARNING: 'warnings' attribute of <module> is deprecated, use 'allowwarnings' instead\n",
454 moduleNode
.location
.c_str() );
458 allowWarnings
= att
->value
== "true";
460 allowWarnings
= false;
462 att
= moduleNode
.GetAttribute ( "aliasof", false );
463 if ( type
== Alias
&& att
!= NULL
)
464 aliasedModuleName
= att
->value
;
466 aliasedModuleName
= "";
468 if ( type
== BootProgram
)
470 att
= moduleNode
.GetAttribute ( "payload", true );
471 payload
= att
->value
;
474 if ( type
== BootProgram
|| type
== ElfExecutable
)
476 att
= moduleNode
.GetAttribute ( "buildtype", false );
479 buildtype
= att
->value
;
483 buildtype
= "BOOTPROG";
487 att
= moduleNode
.GetAttribute ( "description", false );
490 description
= project
.ResolveProperties(att
->value
);
495 att
= moduleNode
.GetAttribute ( "lcid", false );
496 if (type
== KeyboardLayout
&& att
!= NULL
)
501 att
= moduleNode
.GetAttribute ( "layoutid", false );
502 if (type
== KeyboardLayout
&& att
!= NULL
)
503 layoutId
= att
->value
;
507 att
= moduleNode
.GetAttribute ( "layoutnameresid", false );
508 if (type
== KeyboardLayout
&& att
!= NULL
)
509 layoutNameResId
= att
->value
;
511 layoutNameResId
= "";
513 SetImportLibrary ( NULL
);
519 for ( i
= 0; i
< invocations
.size(); i
++ )
520 delete invocations
[i
];
521 for ( i
= 0; i
< dependencies
.size(); i
++ )
522 delete dependencies
[i
];
523 for ( i
= 0; i
< compilerFlags
.size(); i
++ )
524 delete compilerFlags
[i
];
525 for ( i
= 0; i
< linkerFlags
.size(); i
++ )
526 delete linkerFlags
[i
];
527 for ( i
= 0; i
< stubbedComponents
.size(); i
++ )
528 delete stubbedComponents
[i
];
540 delete importLibrary
;
556 aliasedModuleName
= project
.ResolveProperties ( aliasedModuleName
);
557 if ( aliasedModuleName
== name
)
559 throw XMLInvalidBuildFileException (
561 "module '%s' cannot link against itself",
564 const Module
* m
= project
.LocateModule ( aliasedModuleName
);
567 throw XMLInvalidBuildFileException (
569 "module '%s' trying to alias non-existant module '%s'",
571 aliasedModuleName
.c_str() );
576 for ( i
= 0; i
< node
.subElements
.size(); i
++ )
578 ParseContext parseContext
;
579 ProcessXMLSubElement ( *node
.subElements
[i
], SourceDirectory
, output
->relative_path
, parseContext
);
581 for ( i
= 0; i
< invocations
.size(); i
++ )
582 invocations
[i
]->ProcessXML ();
583 for ( i
= 0; i
< dependencies
.size(); i
++ )
584 dependencies
[i
]->ProcessXML ();
585 for ( i
= 0; i
< compilerFlags
.size(); i
++ )
586 compilerFlags
[i
]->ProcessXML();
587 for ( i
= 0; i
< linkerFlags
.size(); i
++ )
588 linkerFlags
[i
]->ProcessXML();
589 for ( i
= 0; i
< stubbedComponents
.size(); i
++ )
590 stubbedComponents
[i
]->ProcessXML();
591 non_if_data
.ProcessXML();
593 linkerScript
->ProcessXML();
597 autoRegister
->ProcessXML();
601 Module::ProcessXMLSubElement ( const XMLElement
& e
,
602 DirectoryLocation directory
,
603 const string
& relative_path
,
604 ParseContext
& parseContext
)
606 CompilationUnit
* pOldCompilationUnit
= parseContext
.compilationUnit
;
607 bool subs_invalid
= false;
608 string
subpath ( relative_path
);
609 DirectoryLocation subdirectory
= SourceDirectory
;
610 if ( e
.name
== "file" && e
.value
.size () > 0 )
613 const XMLAttribute
* att
= e
.GetAttribute ( "first", false );
616 if ( !stricmp ( att
->value
.c_str(), "true" ) )
618 else if ( stricmp ( att
->value
.c_str(), "false" ) )
620 throw XMLInvalidBuildFileException (
622 "attribute 'first' of <file> element can only be 'true' or 'false'" );
625 string switches
= "";
626 att
= e
.GetAttribute ( "switches", false );
628 switches
= att
->value
;
631 // check for c++ file
632 string ext
= GetExtension ( e
.value
);
633 if ( !stricmp ( ext
.c_str(), ".cpp" ) )
635 else if ( !stricmp ( ext
.c_str(), ".cc" ) )
637 else if ( !stricmp ( ext
.c_str(), ".cxx" ) )
640 File
* pFile
= new File ( directory
,
646 if ( parseContext
.compilationUnit
)
647 parseContext
.compilationUnit
->AddFile ( pFile
);
650 CompilationUnit
* pCompilationUnit
= new CompilationUnit ( pFile
);
651 string ext
= ToLower ( GetExtension ( e
.value
) );
654 // put .idl files at the start of the module
655 non_if_data
.compilationUnits
.insert (
656 non_if_data
.compilationUnits
.begin(),
659 else if ( ext
== ".asm" || ext
== ".s" )
661 // put .asm files at the end of the module
662 non_if_data
.compilationUnits
.push_back ( pCompilationUnit
);
663 non_if_data
.asmFiles
++;
667 // put other files in the middle
668 non_if_data
.compilationUnits
.insert (
669 non_if_data
.compilationUnits
.end() - non_if_data
.asmFiles
,
673 non_if_data
.files
.push_back ( pFile
);
676 else if ( e
.name
== "library" && e
.value
.size () )
678 Library
* pLibrary
= new Library ( e
, *this, e
.value
);
679 non_if_data
.libraries
.push_back ( pLibrary
);
682 else if ( e
.name
== "directory" )
684 const XMLAttribute
* att
= e
.GetAttribute ( "name", true );
685 const XMLAttribute
* root
= e
.GetAttribute ( "root", false );
689 if ( root
->value
== "intermediate" )
690 subdirectory
= IntermediateDirectory
;
691 else if ( root
->value
== "output" )
692 subdirectory
= OutputDirectory
;
695 throw InvalidAttributeValueException (
701 subpath
= GetSubPath ( this->project
, e
.location
, relative_path
, att
->value
);
703 else if ( e
.name
== "include" )
705 Include
* include
= new Include ( project
, &e
, this );
706 non_if_data
.includes
.push_back ( include
);
709 else if ( e
.name
== "define" )
711 Define
* pDefine
= new Define ( project
, this, e
);
712 non_if_data
.defines
.push_back ( pDefine
);
715 else if ( e
.name
== "metadata" )
717 metadata
= new Metadata ( e
, *this );
718 subs_invalid
= false;
720 else if ( e
.name
== "invoke" )
722 invocations
.push_back ( new Invoke ( e
, *this ) );
723 subs_invalid
= false;
725 else if ( e
.name
== "dependency" )
727 dependencies
.push_back ( new Dependency ( e
, *this ) );
730 else if ( e
.name
== "bootsector" )
732 bootSector
= new Bootsector ( e
, this );
735 else if ( e
.name
== "importlibrary" )
739 throw XMLInvalidBuildFileException (
741 "Only one <importlibrary> is valid per module" );
743 SetImportLibrary ( new ImportLibrary ( project
, e
, this ) );
746 else if ( e
.name
== "if" || e
.name
== "ifnot" )
748 const XMLAttribute
* name
;
749 name
= e
.GetAttribute ( "property", true );
751 const Property
*property
= project
.LookupProperty( name
->value
);
754 // Property not found
755 throw InvalidOperationException ( __FILE__
,
757 "Test on unknown property '%s' at %s",
758 name
->value
.c_str (), e
.location
.c_str () );
761 const XMLAttribute
* value
;
762 value
= e
.GetAttribute ( "value", true );
765 bool negate
= ( e
.name
== "ifnot" );
766 bool equality
= ( property
->value
== value
->value
);
767 if ( equality
== negate
)
769 // Failed, skip this element
770 if ( project
.configuration
.Verbose
)
771 printf("Skipping 'If' at %s\n", e
.location
.c_str () );
774 subs_invalid
= false;
776 else if ( e
.name
== "compilerflag" )
778 CompilerFlag
* pCompilerFlag
= new CompilerFlag ( project
, this, e
);
779 non_if_data
.compilerFlags
.push_back ( pCompilerFlag
);
782 else if ( e
.name
== "linkerflag" )
784 linkerFlags
.push_back ( new LinkerFlag ( project
, this, e
) );
787 else if ( e
.name
== "linkerscript" )
791 throw XMLInvalidBuildFileException (
793 "Only one <linkerscript> is valid per module" );
795 size_t pos
= e
.value
.find_last_of ( "/\\" );
796 if ( pos
== string::npos
)
798 linkerScript
= new LinkerScript (
799 e
, *this, new FileLocation ( SourceDirectory
, relative_path
, e
.value
, &e
) );
803 string dir
= e
.value
.substr ( 0, pos
);
804 string name
= e
.value
.substr ( pos
+ 1);
805 linkerScript
= new LinkerScript (
806 e
, *this, new FileLocation ( SourceDirectory
, relative_path
+ sSep
+ dir
, name
, &e
) );
810 else if ( e
.name
== "component" )
812 stubbedComponents
.push_back ( new StubbedComponent ( this, e
) );
813 subs_invalid
= false;
815 else if ( e
.name
== "property" )
817 throw XMLInvalidBuildFileException (
819 "<property> is not a valid sub-element of <module>" );
821 else if ( e
.name
== "bootstrap" )
823 bootstrap
= new Bootstrap ( project
, this, e
);
826 else if ( e
.name
== "pch" )
830 throw XMLInvalidBuildFileException (
832 "Only one <pch> is valid per module" );
834 size_t pos
= e
.value
.find_last_of ( "/\\" );
835 if ( pos
== string::npos
)
838 e
, *this, new FileLocation ( SourceDirectory
, relative_path
, e
.value
, &e
) );
842 string dir
= e
.value
.substr ( 0, pos
);
843 string name
= e
.value
.substr ( pos
+ 1);
845 e
, *this, new FileLocation ( SourceDirectory
, relative_path
+ sSep
+ dir
, name
, &e
) );
849 else if ( e
.name
== "compilationunit" )
851 if ( project
.configuration
.CompilationUnitsEnabled
)
853 CompilationUnit
* pCompilationUnit
= new CompilationUnit ( &project
, this, &e
);
854 non_if_data
.compilationUnits
.push_back ( pCompilationUnit
);
855 parseContext
.compilationUnit
= pCompilationUnit
;
857 subs_invalid
= false;
859 else if ( e
.name
== "autoregister" )
861 if ( autoRegister
!= NULL
)
863 throw XMLInvalidBuildFileException (
865 "there can be only one <%s> element for a module",
868 autoRegister
= new AutoRegister ( project
, this, e
);
871 if ( subs_invalid
&& e
.subElements
.size() > 0 )
873 throw XMLInvalidBuildFileException (
875 "<%s> cannot have sub-elements",
878 for ( size_t i
= 0; i
< e
.subElements
.size (); i
++ )
879 ProcessXMLSubElement ( *e
.subElements
[i
], subdirectory
, subpath
, parseContext
);
880 parseContext
.compilationUnit
= pOldCompilationUnit
;
884 Module::GetModuleType ( const string
& location
, const XMLAttribute
& attribute
)
886 if ( attribute
.value
== "buildtool" )
888 if ( attribute
.value
== "staticlibrary" )
889 return StaticLibrary
;
890 if ( attribute
.value
== "hoststaticlibrary" )
891 return HostStaticLibrary
;
892 if ( attribute
.value
== "objectlibrary" )
893 return ObjectLibrary
;
894 if ( attribute
.value
== "kernel" )
896 if ( attribute
.value
== "kernelmodedll" )
897 return KernelModeDLL
;
898 if ( attribute
.value
== "kernelmodedriver" )
899 return KernelModeDriver
;
900 if ( attribute
.value
== "nativedll" )
902 if ( attribute
.value
== "nativecui" )
904 if ( attribute
.value
== "keyboardlayout" )
905 return KeyboardLayout
;
906 if ( attribute
.value
== "win32dll" )
908 if ( attribute
.value
== "win32ocx" )
910 if ( attribute
.value
== "win32cui" )
912 if ( attribute
.value
== "win32gui" )
914 if ( attribute
.value
== "win32scr" )
916 if ( attribute
.value
== "bootloader" )
918 if ( attribute
.value
== "bootsector" )
920 if ( attribute
.value
== "bootprogram" )
922 if ( attribute
.value
== "iso" )
924 if ( attribute
.value
== "liveiso" )
926 if ( attribute
.value
== "isoregtest" )
928 if ( attribute
.value
== "liveisoregtest" )
929 return LiveIsoRegTest
;
930 if ( attribute
.value
== "test" )
932 if ( attribute
.value
== "rpcserver" )
934 if ( attribute
.value
== "rpcclient" )
936 if ( attribute
.value
== "rpcproxy" )
938 if ( attribute
.value
== "alias" )
940 if ( attribute
.value
== "idlheader" )
942 if ( attribute
.value
== "embeddedtypelib" )
943 return EmbeddedTypeLib
;
944 if ( attribute
.value
== "elfexecutable" )
945 return ElfExecutable
;
946 if ( attribute
.value
== "cabinet" )
948 if ( attribute
.value
== "messageheader" )
949 return MessageHeader
;
950 throw InvalidAttributeValueException ( location
,
956 Module::GetTargetDirectoryTree () const
966 case KernelModeDriver
:
982 return OutputDirectory
;
983 case EmbeddedTypeLib
:
985 case HostStaticLibrary
:
993 return IntermediateDirectory
;
997 throw InvalidOperationException ( __FILE__
,
999 "Invalid module type %d.",
1004 Module::GetDefaultModuleExtension () const
1012 case HostStaticLibrary
:
1026 case KeyboardLayout
:
1031 case KernelModeDriver
:
1041 case LiveIsoRegTest
:
1054 case EmbeddedTypeLib
:
1059 throw InvalidOperationException ( __FILE__
,
1064 Module::GetDefaultModuleEntrypoint () const
1069 return "KiSystemStartup";
1070 case KeyboardLayout
:
1072 case KernelModeDriver
:
1073 if (Environment::GetArch() == "arm") return "DriverEntry";
1074 return "DriverEntry@8";
1076 if (Environment::GetArch() == "arm") return "DllMainCRTStartup";
1077 return "DllMainCRTStartup@12";
1079 if (Environment::GetArch() == "arm") return "NtProcessStartup";
1080 return "NtProcessStartup@4";
1083 if (Environment::GetArch() == "arm") return "DllMain";
1084 return "DllMain@12";
1088 return "wmainCRTStartup";
1090 return "mainCRTStartup";
1094 return "wWinMainCRTStartup";
1096 return "WinMainCRTStartup";
1099 case HostStaticLibrary
:
1106 case LiveIsoRegTest
:
1115 case EmbeddedTypeLib
:
1121 throw InvalidOperationException ( __FILE__
,
1126 Module::GetDefaultModuleBaseaddress () const
1131 return "0x80800000";
1134 return "0x10000000";
1139 return "0x00400000";
1142 return "0x00400000";
1143 case KeyboardLayout
:
1145 case KernelModeDriver
:
1146 return "0x00010000";
1151 case HostStaticLibrary
:
1158 case LiveIsoRegTest
:
1166 case EmbeddedTypeLib
:
1172 throw InvalidOperationException ( __FILE__
,
1177 Module::HasImportLibrary () const
1179 return importLibrary
!= NULL
&& type
!= StaticLibrary
&& type
!= HostStaticLibrary
;
1183 Module::IsDLL () const
1190 case KeyboardLayout
:
1193 case KernelModeDriver
:
1202 case HostStaticLibrary
:
1210 case LiveIsoRegTest
:
1217 case EmbeddedTypeLib
:
1224 throw InvalidOperationException ( __FILE__
,
1229 Module::GetPathWithPrefix ( const string
& prefix
) const
1231 return output
->relative_path
+ cSep
+ prefix
+ output
->name
;
1235 Module::GetPathToBaseDir () const
1237 string temp_path
= output
->relative_path
;
1238 string result
= "..\\";
1239 while(temp_path
.find ('\\') != string::npos
)
1241 temp_path
.erase (0, temp_path
.find('\\')+1);
1248 Module::GetInvocationTarget ( const int index
) const
1250 return ssprintf ( "%s_invoke_%d",
1256 Module::GetEntryPoint(bool leadingUnderscore
) const
1259 if (entrypoint
== "0" || entrypoint
== "0x0")
1261 if (leadingUnderscore
)
1264 result
+= entrypoint
;
1266 if (Environment::GetArch() == "amd64")
1268 size_t at_index
= result
.find_last_of( '@' );
1269 if ( at_index
!= result
.npos
)
1270 return result
.substr (0, at_index
);
1277 Module::HasFileWithExtension (
1278 const IfableData
& data
,
1279 const std::string
& extension
) const
1282 for ( i
= 0; i
< data
.compilationUnits
.size (); i
++ )
1284 CompilationUnit
* compilationUnit
= data
.compilationUnits
[i
];
1285 if ( compilationUnit
->HasFileWithExtension ( extension
) )
1292 Module::InvokeModule () const
1294 for ( size_t i
= 0; i
< invocations
.size (); i
++ )
1296 Invoke
& invoke
= *invocations
[i
];
1297 string command
= FixSeparatorForSystemCommand(invoke
.invokeModule
->output
->relative_path
+ "/" + invoke
.invokeModule
->output
->name
) + " " + invoke
.GetParameters ();
1298 printf ( "Executing '%s'\n\n", command
.c_str () );
1299 int exitcode
= system ( command
.c_str () );
1300 if ( exitcode
!= 0 )
1301 throw InvocationFailedException ( command
,
1308 Module::SetImportLibrary ( ImportLibrary
* importLibrary
)
1310 this->importLibrary
= importLibrary
;
1311 dependency
= new FileLocation ( HasImportLibrary () ? IntermediateDirectory
: output
->directory
,
1312 output
->relative_path
,
1313 HasImportLibrary () ? "lib" + name
+ ".a" : output
->name
);
1317 File::File ( DirectoryLocation directory
,
1318 const string
& relative_path
,
1321 const string
& _switches
,
1322 bool _isPreCompiledHeader
)
1323 : file ( directory
, relative_path
, name
),
1325 switches(_switches
),
1326 isPreCompiledHeader(_isPreCompiledHeader
)
1337 std::string
File::GetFullPath () const
1339 string
directory ( "" );
1340 switch ( file
.directory
)
1342 case SourceDirectory
:
1344 case IntermediateDirectory
:
1345 directory
= Environment::GetIntermediatePath () + sSep
;
1348 throw InvalidOperationException ( __FILE__
,
1350 "Invalid directory %d.",
1354 if ( file
.relative_path
.length () > 0 )
1355 directory
+= file
.relative_path
+ sSep
;
1358 return directory
+ file
.name
;
1362 Library::Library ( const XMLElement
& _node
,
1363 const Module
& _module
,
1364 const string
& _name
)
1368 importedModule(_module
.project
.LocateModule(_name
))
1370 if ( module
.name
== name
)
1372 throw XMLInvalidBuildFileException (
1374 "module '%s' cannot link against itself",
1377 if ( !importedModule
)
1379 throw XMLInvalidBuildFileException (
1381 "module '%s' trying to import non-existant module '%s'",
1382 module
.name
.c_str(),
1387 Library::Library ( const Module
& _module
,
1388 const string
& _name
)
1392 importedModule(_module
.project
.LocateModule(_name
))
1397 Library::ProcessXML()
1399 if ( node
&& !module
.project
.LocateModule ( name
) )
1401 throw XMLInvalidBuildFileException (
1403 "module '%s' is trying to link against non-existant module '%s'",
1404 module
.name
.c_str(),
1410 Invoke::Invoke ( const XMLElement
& _node
,
1411 const Module
& _module
)
1418 Invoke::ProcessXML()
1420 const XMLAttribute
* att
= node
.GetAttribute ( "module", false );
1422 invokeModule
= &module
;
1425 invokeModule
= module
.project
.LocateModule ( att
->value
);
1426 if ( invokeModule
== NULL
)
1428 throw XMLInvalidBuildFileException (
1430 "module '%s' is trying to invoke non-existant module '%s'",
1431 module
.name
.c_str(),
1432 att
->value
.c_str() );
1436 for ( size_t i
= 0; i
< node
.subElements
.size (); i
++ )
1437 ProcessXMLSubElement ( *node
.subElements
[i
] );
1441 Invoke::ProcessXMLSubElement ( const XMLElement
& e
)
1443 bool subs_invalid
= false;
1444 if ( e
.name
== "input" )
1446 for ( size_t i
= 0; i
< e
.subElements
.size (); i
++ )
1447 ProcessXMLSubElementInput ( *e
.subElements
[i
] );
1449 else if ( e
.name
== "output" )
1451 for ( size_t i
= 0; i
< e
.subElements
.size (); i
++ )
1452 ProcessXMLSubElementOutput ( *e
.subElements
[i
] );
1454 if ( subs_invalid
&& e
.subElements
.size() > 0 )
1456 throw XMLInvalidBuildFileException (
1458 "<%s> cannot have sub-elements",
1464 Invoke::ProcessXMLSubElementInput ( const XMLElement
& e
)
1466 bool subs_invalid
= false;
1467 if ( e
.name
== "inputfile" && e
.value
.size () > 0 )
1469 input
.push_back ( new InvokeFile (
1470 e
, FixSeparator ( module
.output
->relative_path
+ cSep
+ e
.value
) ) );
1471 subs_invalid
= true;
1473 if ( subs_invalid
&& e
.subElements
.size() > 0 )
1475 throw XMLInvalidBuildFileException (
1477 "<%s> cannot have sub-elements",
1483 Invoke::ProcessXMLSubElementOutput ( const XMLElement
& e
)
1485 bool subs_invalid
= false;
1486 if ( e
.name
== "outputfile" && e
.value
.size () > 0 )
1488 output
.push_back ( new InvokeFile (
1489 e
, FixSeparator ( module
.output
->relative_path
+ cSep
+ e
.value
) ) );
1490 subs_invalid
= true;
1492 if ( subs_invalid
&& e
.subElements
.size() > 0 )
1494 throw XMLInvalidBuildFileException (
1496 "<%s> cannot have sub-elements",
1502 Invoke::GetTargets ( string_list
& targets
) const
1504 for ( size_t i
= 0; i
< output
.size (); i
++ )
1506 InvokeFile
& file
= *output
[i
];
1507 targets
.push_back ( NormalizeFilename ( file
.name
) );
1512 Invoke::GetParameters () const
1514 string
parameters ( "" );
1516 for ( i
= 0; i
< output
.size (); i
++ )
1518 if ( parameters
.length () > 0)
1520 InvokeFile
& invokeFile
= *output
[i
];
1521 if ( invokeFile
.switches
.length () > 0 )
1523 parameters
+= invokeFile
.switches
+ " ";
1525 parameters
+= invokeFile
.name
;
1528 for ( i
= 0; i
< input
.size (); i
++ )
1530 if ( parameters
.length () > 0 )
1532 InvokeFile
& invokeFile
= *input
[i
];
1533 if ( invokeFile
.switches
.length () > 0 )
1535 parameters
+= invokeFile
.switches
;
1538 parameters
+= invokeFile
.name
;
1545 InvokeFile::InvokeFile ( const XMLElement
& _node
,
1546 const string
& _name
)
1550 const XMLAttribute
* att
= _node
.GetAttribute ( "switches", false );
1552 switches
= att
->value
;
1558 InvokeFile::ProcessXML()
1563 Dependency::Dependency ( const XMLElement
& _node
,
1564 const Module
& _module
)
1567 dependencyModule (NULL
)
1572 Dependency::ProcessXML()
1574 dependencyModule
= module
.project
.LocateModule ( node
.value
);
1575 if ( dependencyModule
== NULL
)
1577 throw XMLInvalidBuildFileException (
1579 "module '%s' depend on non-existant module '%s'",
1580 module
.name
.c_str(),
1581 node
.value
.c_str() );
1585 Bootsector::Bootsector ( const XMLElement
& _node
,
1586 const Module
* _module
)
1589 bootSectorModule (NULL
)
1591 if ( !IsSupportedModuleType ( module
->type
) )
1593 throw XMLInvalidBuildFileException (
1595 "<bootsector> is not applicable for this module type." );
1598 bootSectorModule
= module
->project
.LocateModule ( node
.value
);
1599 if ( bootSectorModule
== NULL
)
1601 throw XMLInvalidBuildFileException (
1603 "module '%s' depend on non-existant module '%s'",
1604 module
->name
.c_str(),
1605 node
.value
.c_str() );
1608 if (bootSectorModule
->type
!= BootSector
)
1610 throw XMLInvalidBuildFileException (
1612 "module '%s' is referencing non BootSector module '%s'",
1613 module
->name
.c_str(),
1614 node
.value
.c_str() );
1619 Bootsector::ProcessXML()
1624 Bootsector::IsSupportedModuleType ( ModuleType type
)
1628 type
== IsoRegTest
||
1629 type
== LiveIsoRegTest
)
1637 Metadata::Metadata ( const XMLElement
& _node
,
1638 const Module
& _module
)
1642 /* The module name */
1643 const XMLAttribute
* att
= _node
.GetAttribute ( "name", false );
1649 /* The module description */
1650 att
= _node
.GetAttribute ( "description", false );
1652 description
= att
->value
;
1656 /* The module version */
1657 att
= _node
.GetAttribute ( "version", false );
1659 version
= att
->value
;
1663 /* The module copyright */
1664 att
= _node
.GetAttribute ( "copyright", false );
1666 copyright
= att
->value
;
1670 att
= _node
.GetAttribute ( "url", false );
1676 /* When was this module updated */
1677 att
= _node
.GetAttribute ( "date", false );
1683 /* When was this module updated */
1684 att
= _node
.GetAttribute ( "owner", false );
1692 ImportLibrary::~ImportLibrary ()
1698 ImportLibrary::ImportLibrary ( const Project
& project
,
1699 const XMLElement
& node
,
1700 const Module
* module
)
1701 : XmlNode ( project
, node
),
1704 DirectoryLocation directory
= SourceDirectory
;
1705 const Module
* base
= module
;
1706 const XMLAttribute
* dllname
= node
.GetAttribute ( "dllname", false );
1707 const XMLAttribute
* definition
= node
.GetAttribute ( "definition", true );
1708 assert ( definition
);
1710 string relative_path
;
1711 const XMLAttribute
* att
= node
.GetAttribute ( "base", false );
1714 base
= project
.LocateModule ( att
->value
);
1716 throw XMLInvalidBuildFileException (
1718 "<importlibrary> attribute 'base' references non-existant module '%s'",
1719 att
->value
.c_str() );
1725 relative_path
= base
->output
->relative_path
;
1726 if ( node
.value
.length () > 0 && node
.value
!= "." )
1727 relative_path
+= sSep
+ node
.value
;
1730 relative_path
= node
.value
;
1732 att
= node
.GetAttribute ( "root", false );
1735 if ( att
->value
== "intermediate" )
1736 directory
= IntermediateDirectory
;
1738 throw InvalidAttributeValueException ( node
.location
,
1744 size_t index
= definition
->value
.rfind ( ".spec.def" );
1745 if ( index
!= string::npos
)
1746 directory
= IntermediateDirectory
;
1750 this->dllname
= dllname
->value
;
1751 else if ( module
->type
== StaticLibrary
|| module
->type
== HostStaticLibrary
)
1752 throw XMLInvalidBuildFileException (
1754 "<importlibrary> dllname attribute required." );
1756 size_t index
= definition
->value
.find_last_of ( "/\\" );
1757 if ( index
== string::npos
)
1759 source
= new FileLocation ( directory
,
1760 base
->output
->relative_path
,
1766 string dir
= definition
->value
.substr ( 0, index
);
1767 string name
= definition
->value
.substr ( index
+ 1);
1768 source
= new FileLocation ( directory
,
1769 NormalizeFilename ( base
->output
->relative_path
+ sSep
+ dir
),
1776 Property::Property ( const XMLElement
& node_
,
1777 const Project
& project_
,
1778 const Module
* module_
)
1779 : project(project_
), module(module_
)
1781 const XMLAttribute
* att
;
1783 att
= node_
.GetAttribute ( "name", true );
1785 name
= project
.ResolveProperties ( att
->value
);
1787 att
= node_
.GetAttribute ( "value", true );
1791 att
= node_
.GetAttribute ( "internal", false );
1794 const char* p
= att
->value
.c_str();
1795 if ( !stricmp ( p
, "true" ) || !stricmp ( p
, "yes" ) )
1797 else if ( !stricmp ( p
, "false" ) || !stricmp ( p
, "no" ) )
1801 throw InvalidAttributeValueException (
1811 Property::Property ( const Project
& project_
,
1812 const Module
* module_
,
1813 const std::string
& name_
,
1814 const std::string
& value_
)
1815 : project(project_
), module(module_
), name(name_
), value(value_
)
1820 Property::ProcessXML()
1826 const XMLElement
& node_
,
1827 const Module
& module_
,
1828 const FileLocation
*file_
)
1829 : node(node_
), module(module_
), file(file_
)
1839 PchFile::ProcessXML()