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 along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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::map
<std::string
, Module
*> &modules
)
195 for ( i
= 0; i
< this->modules
.size (); i
++ )
196 modules
.insert(std::make_pair(this->modules
[i
]->name
, 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 ( std::map
<std::string
, Property
*>::const_iterator p
= properties
.begin(); p
!= properties
.end(); ++ p
)
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 ( std::map
<std::string
, Property
*>::const_iterator p
= properties
.begin(); p
!= properties
.end(); ++ p
)
228 p
->second
->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 bool Module::GetBooleanAttribute ( const XMLElement
& moduleNode
, const char * name
, bool default_value
)
237 const XMLAttribute
* att
= moduleNode
.GetAttribute ( name
, false );
240 const char* p
= att
->value
.c_str();
241 if ( !stricmp ( p
, "true" ) || !stricmp ( p
, "yes" ) )
243 else if ( !stricmp ( p
, "false" ) || !stricmp ( p
, "no" ) )
247 throw InvalidAttributeValueException (
254 return default_value
;
257 Module::Module ( const Project
& project
,
258 const XMLElement
& moduleNode
,
259 const string
& modulePath
)
262 importLibrary (NULL
),
263 delayImportLibrary (NULL
),
274 if ( node
.name
!= "module" )
275 throw InvalidOperationException ( __FILE__
,
277 "Module created with non-<module> node" );
279 xmlbuildFile
= FixSeparator ( Path::RelativeFromWorkingDirectory ( moduleNode
.xmlFile
->filename () ) );
281 const XMLAttribute
* att
= moduleNode
.GetAttribute ( "name", true );
287 att
= moduleNode
.GetAttribute ( "if", false );
289 enabled
= GetBooleanValue ( project
.ResolveProperties ( att
->value
) );
291 att
= moduleNode
.GetAttribute ( "ifnot", false );
293 enabled
= !GetBooleanValue ( project
.ResolveProperties ( att
->value
) );
295 if ( !enabled
&& project
.configuration
.Verbose
)
296 printf("Module '%s' has been disabled.\n", name
.c_str () );
298 att
= moduleNode
.GetAttribute ( "type", true );
300 type
= GetModuleType ( node
.location
, *att
);
302 att
= moduleNode
.GetAttribute ( "extension", false );
304 extension
= att
->value
;
306 extension
= GetDefaultModuleExtension ();
308 isUnicode
= GetBooleanAttribute ( moduleNode
, "unicode" );
312 // Always define UNICODE and _UNICODE
313 Define
* pDefine
= new Define ( project
, this, "UNICODE" );
314 non_if_data
.defines
.push_back ( pDefine
);
316 pDefine
= new Define ( project
, this, "_UNICODE" );
317 non_if_data
.defines
.push_back ( pDefine
);
320 att
= moduleNode
.GetAttribute ( "entrypoint", false );
323 if ( att
->value
== "" )
325 throw InvalidAttributeValueException (
331 entrypoint
= att
->value
;
332 isDefaultEntryPoint
= false;
336 entrypoint
= GetDefaultModuleEntrypoint ();
337 isDefaultEntryPoint
= true;
340 att
= moduleNode
.GetAttribute ( "baseaddress", false );
342 baseaddress
= att
->value
;
344 baseaddress
= GetDefaultModuleBaseaddress ();
346 isStartupLib
= GetBooleanAttribute ( moduleNode
, "isstartuplib" );
347 isCRT
= GetBooleanAttribute ( moduleNode
, "iscrt", GetDefaultModuleIsCRT () );
349 att
= moduleNode
.GetAttribute ( "crt", false );
354 if ( stricmp ( CRT
.c_str (), "auto" ) == 0 )
355 CRT
= GetDefaultModuleCRT ();
358 CRT
= GetDefaultModuleCRT ();
360 const char * crtAttr
= CRT
.c_str ();
361 if ( crtAttr
== NULL
|| stricmp ( crtAttr
, "none" ) == 0 )
363 else if ( stricmp ( crtAttr
, "libc" ) == 0 )
365 else if ( stricmp ( crtAttr
, "msvcrt" ) == 0 )
367 else if ( stricmp ( crtAttr
, "libcntpr" ) == 0 )
369 else if ( stricmp ( crtAttr
, "ntdll" ) == 0 )
371 else if ( stricmp ( crtAttr
, "static" ) == 0 )
373 else if ( stricmp ( crtAttr
, "dll" ) == 0 )
377 throw InvalidAttributeValueException (
380 std::string ( crtAttr
) );
383 if ( isCRT
&& dynamicCRT
)
385 throw XMLInvalidBuildFileException (
387 "C runtime module '%s' cannot be compiled for a dynamically-linked C runtime",
391 att
= moduleNode
.GetAttribute ( "prefix", false );
395 att
= moduleNode
.GetAttribute ( "installname", false );
398 const XMLAttribute
* installbase
= moduleNode
.GetAttribute ( "installbase", false );
399 install
= new FileLocation ( InstallDirectory
,
400 installbase
? installbase
->value
: "",
404 output
= new FileLocation ( GetTargetDirectoryTree (),
410 att
= moduleNode
.GetAttribute ( "output", false );
415 printf ( "%s: WARNING: 'installname' overrides 'output' also defined for this module.\n",
416 moduleNode
.location
.c_str() );
420 output
= new FileLocation ( GetTargetDirectoryTree (),
427 /* If no one has set the output file for this module set it automatically */
430 output
= new FileLocation ( GetTargetDirectoryTree (),
436 att
= moduleNode
.GetAttribute ( "allowwarnings", false );
439 att
= moduleNode
.GetAttribute ( "warnings", false );
442 printf ( "%s: WARNING: 'warnings' attribute of <module> is deprecated, use 'allowwarnings' instead\n",
443 moduleNode
.location
.c_str() );
447 allowWarnings
= att
->value
== "true";
448 else if ( project
.allowWarningsSet
)
449 allowWarnings
= project
.allowWarnings
;
451 allowWarnings
= false;
453 att
= moduleNode
.GetAttribute ( "aliasof", false );
454 if ( type
== Alias
&& att
!= NULL
)
455 aliasedModuleName
= att
->value
;
457 aliasedModuleName
= "";
459 if ( type
== BootProgram
)
461 att
= moduleNode
.GetAttribute ( "payload", true );
462 payload
= att
->value
;
465 if ( type
== BootProgram
|| type
== ElfExecutable
)
467 att
= moduleNode
.GetAttribute ( "buildtype", false );
470 buildtype
= att
->value
;
474 buildtype
= "BOOTPROG";
478 att
= moduleNode
.GetAttribute ( "description", false );
481 description
= project
.ResolveProperties(att
->value
);
486 att
= moduleNode
.GetAttribute ( "lcid", false );
487 if (type
== KeyboardLayout
&& att
!= NULL
)
492 att
= moduleNode
.GetAttribute ( "layoutid", false );
493 if (type
== KeyboardLayout
&& att
!= NULL
)
494 layoutId
= att
->value
;
498 att
= moduleNode
.GetAttribute ( "layoutnameresid", false );
499 if (type
== KeyboardLayout
&& att
!= NULL
)
500 layoutNameResId
= att
->value
;
502 layoutNameResId
= "";
504 SetImportLibrary ( NULL
);
510 for ( i
= 0; i
< invocations
.size(); i
++ )
511 delete invocations
[i
];
512 for ( i
= 0; i
< dependencies
.size(); i
++ )
513 delete dependencies
[i
];
514 for ( i
= 0; i
< compilerFlags
.size(); i
++ )
515 delete compilerFlags
[i
];
516 for ( i
= 0; i
< linkerFlags
.size(); i
++ )
517 delete linkerFlags
[i
];
518 for ( i
= 0; i
< stubbedComponents
.size(); i
++ )
519 delete stubbedComponents
[i
];
520 for ( i
= 0; i
< cdfiles
.size (); i
++ )
533 delete importLibrary
;
549 aliasedModuleName
= project
.ResolveProperties ( aliasedModuleName
);
550 if ( aliasedModuleName
== name
)
552 throw XMLInvalidBuildFileException (
554 "module '%s' cannot link against itself",
557 const Module
* m
= project
.LocateModule ( aliasedModuleName
);
560 throw XMLInvalidBuildFileException (
562 "module '%s' trying to alias non-existant module '%s'",
564 aliasedModuleName
.c_str() );
569 for ( i
= 0; i
< node
.subElements
.size(); i
++ )
571 ParseContext parseContext
;
572 ProcessXMLSubElement ( *node
.subElements
[i
], SourceDirectory
, output
->relative_path
, parseContext
);
574 for ( i
= 0; i
< invocations
.size(); i
++ )
575 invocations
[i
]->ProcessXML ();
576 for ( i
= 0; i
< dependencies
.size(); i
++ )
577 dependencies
[i
]->ProcessXML ();
578 for ( i
= 0; i
< compilerFlags
.size(); i
++ )
579 compilerFlags
[i
]->ProcessXML();
580 for ( i
= 0; i
< linkerFlags
.size(); i
++ )
581 linkerFlags
[i
]->ProcessXML();
582 for ( i
= 0; i
< stubbedComponents
.size(); i
++ )
583 stubbedComponents
[i
]->ProcessXML();
584 non_if_data
.ProcessXML();
586 linkerScript
->ProcessXML();
590 autoRegister
->ProcessXML();
594 Module::ProcessXMLSubElement ( const XMLElement
& e
,
595 DirectoryLocation directory
,
596 const string
& relative_path
,
597 ParseContext
& parseContext
)
599 const XMLAttribute
* att
;
601 att
= e
.GetAttribute ( "compilerset", false );
605 CompilerSet compilerSet
;
607 if ( att
->value
== "msc" )
608 compilerSet
= MicrosoftC
;
609 else if ( att
->value
== "gcc" )
610 compilerSet
= GnuGcc
;
612 throw InvalidAttributeValueException (
617 if ( compilerSet
!= project
.configuration
.Compiler
)
621 att
= e
.GetAttribute ( "linkerset", false );
627 if ( att
->value
== "mslink" )
628 linkerSet
= MicrosoftLink
;
629 else if ( att
->value
== "ld" )
632 throw InvalidAttributeValueException (
637 if ( linkerSet
!= project
.configuration
.Linker
)
641 CompilationUnit
* pOldCompilationUnit
= parseContext
.compilationUnit
;
642 bool subs_invalid
= false;
643 string
subpath ( relative_path
);
644 DirectoryLocation subdirectory
= SourceDirectory
;
645 if ( e
.name
== "file" && e
.value
.size () > 0 )
648 const XMLAttribute
* att
= e
.GetAttribute ( "first", false );
651 if ( !stricmp ( att
->value
.c_str(), "true" ) )
653 else if ( stricmp ( att
->value
.c_str(), "false" ) )
655 throw XMLInvalidBuildFileException (
657 "attribute 'first' of <file> element can only be 'true' or 'false'" );
660 string switches
= "";
661 att
= e
.GetAttribute ( "switches", false );
663 switches
= att
->value
;
666 // check for c++ file
667 string ext
= GetExtension ( e
.value
);
668 if ( !stricmp ( ext
.c_str(), ".cpp" ) )
670 else if ( !stricmp ( ext
.c_str(), ".cc" ) )
672 else if ( !stricmp ( ext
.c_str(), ".cxx" ) )
675 File
* pFile
= new File ( directory
,
681 if ( parseContext
.compilationUnit
)
682 parseContext
.compilationUnit
->AddFile ( pFile
);
685 CompilationUnit
* pCompilationUnit
= new CompilationUnit ( pFile
);
686 string ext
= ToLower ( GetExtension ( e
.value
) );
689 // put .idl files at the start of the module
690 non_if_data
.compilationUnits
.insert (
691 non_if_data
.compilationUnits
.begin(),
694 else if ( ext
== ".asm" || ext
== ".s" )
696 // put .asm files at the end of the module
697 non_if_data
.compilationUnits
.push_back ( pCompilationUnit
);
698 non_if_data
.asmFiles
++;
702 // put other files in the middle
703 non_if_data
.compilationUnits
.insert (
704 non_if_data
.compilationUnits
.end() - non_if_data
.asmFiles
,
708 non_if_data
.files
.push_back ( pFile
);
711 else if ( e
.name
== "library" && e
.value
.size () )
713 const XMLAttribute
* att
= e
.GetAttribute ( "delayimport", false );
714 Library
* pLibrary
= new Library ( e
, *this, e
.value
);
715 if ( att
&& !stricmp ( att
->value
.c_str(), "true" ) )
716 pLibrary
->delayimp
= true;
717 non_if_data
.libraries
.push_back ( pLibrary
);
720 else if ( e
.name
== "directory" )
722 const XMLAttribute
* att
= e
.GetAttribute ( "name", true );
723 const XMLAttribute
* root
= e
.GetAttribute ( "root", false );
727 if ( root
->value
== "intermediate" )
728 subdirectory
= IntermediateDirectory
;
729 else if ( root
->value
== "output" )
730 subdirectory
= OutputDirectory
;
733 throw InvalidAttributeValueException (
739 subpath
= GetSubPath ( this->project
, e
.location
, relative_path
, att
->value
);
741 else if ( e
.name
== "include" )
743 Include
* include
= new Include ( project
, &e
, this );
744 non_if_data
.includes
.push_back ( include
);
747 else if ( e
.name
== "define" || e
.name
== "redefine" )
749 Define
* pDefine
= new Define ( project
, this, e
);
750 non_if_data
.defines
.push_back ( pDefine
);
753 else if ( e
.name
== "metadata" )
755 metadata
= new Metadata ( e
, *this );
756 subs_invalid
= false;
758 else if ( e
.name
== "invoke" )
760 invocations
.push_back ( new Invoke ( e
, *this ) );
761 subs_invalid
= false;
763 else if ( e
.name
== "dependency" )
765 dependencies
.push_back ( new Dependency ( e
, *this ) );
768 else if ( e
.name
== "bootsector" )
770 bootSector
= new Bootsector ( e
, this );
773 else if ( e
.name
== "importlibrary" )
777 throw XMLInvalidBuildFileException (
779 "Only one <importlibrary> is valid per module" );
781 SetImportLibrary ( new ImportLibrary ( project
, e
, this, false ) );
782 SetDelayImportLibrary ( new ImportLibrary ( project
, e
, this, true ) );
785 else if ( e
.name
== "if" || e
.name
== "ifnot" )
787 const XMLAttribute
* name
;
788 name
= e
.GetAttribute ( "property", true );
790 const Property
*property
= project
.LookupProperty( name
->value
);
791 const string
*PropertyValue
;
792 const string EmptyString
;
796 PropertyValue
= &property
->value
;
800 // Property does not exist, treat it as being empty
801 PropertyValue
= &EmptyString
;
804 const XMLAttribute
* value
;
805 value
= e
.GetAttribute ( "value", true );
808 bool negate
= ( e
.name
== "ifnot" );
809 bool equality
= ( *PropertyValue
== value
->value
);
810 if ( equality
== negate
)
812 // Failed, skip this element
813 if ( project
.configuration
.Verbose
)
814 printf("Skipping 'If' at %s\n", e
.location
.c_str () );
817 subs_invalid
= false;
819 else if ( e
.name
== "compilerflag" )
821 CompilerFlag
* pCompilerFlag
= new CompilerFlag ( project
, this, e
);
822 non_if_data
.compilerFlags
.push_back ( pCompilerFlag
);
825 else if ( e
.name
== "linkerflag" )
827 linkerFlags
.push_back ( new LinkerFlag ( project
, this, e
) );
830 else if ( e
.name
== "linkerscript" )
834 throw XMLInvalidBuildFileException (
836 "Only one <linkerscript> is valid per module" );
838 size_t pos
= e
.value
.find_last_of ( "/\\" );
839 if ( pos
== string::npos
)
841 linkerScript
= new LinkerScript (
842 e
, *this, new FileLocation ( SourceDirectory
, relative_path
, e
.value
, &e
) );
846 string dir
= e
.value
.substr ( 0, pos
);
847 string name
= e
.value
.substr ( pos
+ 1);
848 linkerScript
= new LinkerScript (
849 e
, *this, new FileLocation ( SourceDirectory
, relative_path
+ sSep
+ dir
, name
, &e
) );
853 else if ( e
.name
== "component" )
855 stubbedComponents
.push_back ( new StubbedComponent ( this, e
) );
856 subs_invalid
= false;
858 else if ( e
.name
== "property" )
860 throw XMLInvalidBuildFileException (
862 "<property> is not a valid sub-element of <module>" );
864 else if ( e
.name
== "bootstrap" )
866 bootstrap
= new Bootstrap ( project
, this, e
);
869 else if ( e
.name
== "pch" )
873 throw XMLInvalidBuildFileException (
875 "Only one <pch> is valid per module" );
877 size_t pos
= e
.value
.find_last_of ( "/\\" );
878 if ( pos
== string::npos
)
881 e
, *this, new FileLocation ( SourceDirectory
, relative_path
, e
.value
, &e
) );
885 string dir
= e
.value
.substr ( 0, pos
);
886 string name
= e
.value
.substr ( pos
+ 1);
888 e
, *this, new FileLocation ( SourceDirectory
, relative_path
+ sSep
+ dir
, name
, &e
) );
892 else if ( e
.name
== "compilationunit" )
894 if ( project
.configuration
.CompilationUnitsEnabled
)
896 CompilationUnit
* pCompilationUnit
= new CompilationUnit ( &project
, this, &e
);
897 non_if_data
.compilationUnits
.push_back ( pCompilationUnit
);
898 parseContext
.compilationUnit
= pCompilationUnit
;
900 subs_invalid
= false;
902 else if ( e
.name
== "autoregister" )
904 if ( autoRegister
!= NULL
)
906 throw XMLInvalidBuildFileException (
908 "there can be only one <%s> element for a module",
911 autoRegister
= new AutoRegister ( project
, this, e
);
914 else if ( e
.name
== "cdfile" )
916 CDFile
* cdfile
= new CDFile ( project
, e
, subpath
);
917 cdfiles
.push_back ( cdfile
);
920 if ( subs_invalid
&& e
.subElements
.size() > 0 )
922 throw XMLInvalidBuildFileException (
924 "<%s> cannot have sub-elements",
927 for ( size_t i
= 0; i
< cdfiles
.size (); i
++ )
928 cdfiles
[i
]->ProcessXML ();
929 for ( size_t i
= 0; i
< e
.subElements
.size (); i
++ )
930 ProcessXMLSubElement ( *e
.subElements
[i
], subdirectory
, subpath
, parseContext
);
931 parseContext
.compilationUnit
= pOldCompilationUnit
;
935 Module::GetModuleType ( const string
& location
, const XMLAttribute
& attribute
)
937 if ( attribute
.value
== "buildtool" )
939 if ( attribute
.value
== "staticlibrary" )
940 return StaticLibrary
;
941 if ( attribute
.value
== "hoststaticlibrary" )
942 return HostStaticLibrary
;
943 if ( attribute
.value
== "objectlibrary" )
944 return ObjectLibrary
;
945 if ( attribute
.value
== "kernel" )
947 if ( attribute
.value
== "kernelmodedll" )
948 return KernelModeDLL
;
949 if ( attribute
.value
== "kernelmodedriver" )
950 return KernelModeDriver
;
951 if ( attribute
.value
== "nativedll" )
953 if ( attribute
.value
== "nativecui" )
955 if ( attribute
.value
== "keyboardlayout" )
956 return KeyboardLayout
;
957 if ( attribute
.value
== "win32dll" )
959 if ( attribute
.value
== "win32ocx" )
961 if ( attribute
.value
== "win32cui" )
963 if ( attribute
.value
== "win32gui" )
965 if ( attribute
.value
== "win32scr" )
967 if ( attribute
.value
== "bootloader" )
969 if ( attribute
.value
== "bootsector" )
971 if ( attribute
.value
== "bootprogram" )
973 if ( attribute
.value
== "iso" )
975 if ( attribute
.value
== "liveiso" )
977 if ( attribute
.value
== "test" )
979 if ( attribute
.value
== "rpcserver" )
981 if ( attribute
.value
== "rpcclient" )
983 if ( attribute
.value
== "rpcproxy" )
985 if ( attribute
.value
== "alias" )
987 if ( attribute
.value
== "idlheader" )
989 if ( attribute
.value
== "idlinterface" )
991 if ( attribute
.value
== "embeddedtypelib" )
992 return EmbeddedTypeLib
;
993 if ( attribute
.value
== "elfexecutable" )
994 return ElfExecutable
;
995 if ( attribute
.value
== "cabinet" )
997 if ( attribute
.value
== "messageheader" )
998 return MessageHeader
;
999 throw InvalidAttributeValueException ( location
,
1005 Module::GetTargetDirectoryTree () const
1011 case KeyboardLayout
:
1015 case KernelModeDriver
:
1029 return OutputDirectory
;
1030 case EmbeddedTypeLib
:
1032 case HostStaticLibrary
:
1041 return IntermediateDirectory
;
1045 throw InvalidOperationException ( __FILE__
,
1047 "Invalid module type %d.",
1052 Module::GetDefaultModuleExtension () const
1060 case HostStaticLibrary
:
1074 case KeyboardLayout
:
1079 case KernelModeDriver
:
1101 case EmbeddedTypeLib
:
1106 throw InvalidOperationException ( __FILE__
,
1111 Module::GetDefaultModuleEntrypoint () const
1116 if (Environment::GetArch() == "arm") return "KiSystemStartup";
1117 return "KiSystemStartup@4";
1118 case KeyboardLayout
:
1120 case KernelModeDriver
:
1121 if (Environment::GetArch() == "arm") return "DriverEntry";
1122 return "DriverEntry@8";
1124 if (Environment::GetArch() == "arm") return "DllMainCRTStartup";
1125 return "DllMainCRTStartup@12";
1127 if (Environment::GetArch() == "arm") return "NtProcessStartup";
1128 return "NtProcessStartup@4";
1131 if (Environment::GetArch() == "arm") return "DllMain";
1132 return "DllMain@12";
1135 return "mainCRTStartup";
1138 return "WinMainCRTStartup";
1141 case HostStaticLibrary
:
1156 case EmbeddedTypeLib
:
1162 throw InvalidOperationException ( __FILE__
,
1167 Module::GetDefaultModuleBaseaddress () const
1172 return "0x80800000";
1175 return "0x10000000";
1180 return "0x00400000";
1183 return "0x00400000";
1184 case KeyboardLayout
:
1186 case KernelModeDriver
:
1187 return "0x00010000";
1192 case HostStaticLibrary
:
1206 case EmbeddedTypeLib
:
1212 throw InvalidOperationException ( __FILE__
,
1217 Module::GetDefaultModuleCRT () const
1237 return "msvcrt"; // BUGBUG: not sure about this
1238 case KeyboardLayout
:
1241 case KernelModeDriver
:
1248 case HostStaticLibrary
:
1261 case EmbeddedTypeLib
:
1266 throw InvalidOperationException ( __FILE__
,
1271 Module::GetDefaultModuleIsCRT () const
1273 return type
== Kernel
;
1277 Module::HasImportLibrary () const
1279 return importLibrary
!= NULL
&& type
!= StaticLibrary
&& type
!= HostStaticLibrary
;
1283 Module::IsDLL () const
1290 case KeyboardLayout
:
1293 case KernelModeDriver
:
1302 case HostStaticLibrary
:
1316 case EmbeddedTypeLib
:
1323 throw InvalidOperationException ( __FILE__
,
1328 Module::GetPathWithPrefix ( const string
& prefix
) const
1330 return output
->relative_path
+ cSep
+ prefix
+ output
->name
;
1334 Module::GetPathToBaseDir () const
1336 string temp_path
= output
->relative_path
;
1337 string result
= "..\\";
1338 while(temp_path
.find ('\\') != string::npos
)
1340 temp_path
.erase (0, temp_path
.find('\\')+1);
1347 Module::GetInvocationTarget ( const int index
) const
1349 return ssprintf ( "%s_invoke_%d",
1355 Module::GetEntryPoint() const
1358 if (entrypoint
== "0" || entrypoint
== "0x0")
1361 if (Environment::GetArch() != "arm")
1364 result
+= entrypoint
;
1366 if (Environment::GetArch() == "amd64")
1368 size_t at_index
= result
.find_last_of( '@' );
1369 if ( at_index
!= result
.npos
)
1370 return result
.substr (0, at_index
);
1377 Module::HasFileWithExtension (
1378 const IfableData
& data
,
1379 const std::string
& extension
) const
1382 for ( i
= 0; i
< data
.compilationUnits
.size (); i
++ )
1384 CompilationUnit
* compilationUnit
= data
.compilationUnits
[i
];
1385 if ( compilationUnit
->HasFileWithExtension ( extension
) )
1392 Module::InvokeModule () const
1394 for ( size_t i
= 0; i
< invocations
.size (); i
++ )
1396 Invoke
& invoke
= *invocations
[i
];
1397 string command
= FixSeparatorForSystemCommand(invoke
.invokeModule
->output
->relative_path
+ "/" + invoke
.invokeModule
->output
->name
) + " " + invoke
.GetParameters ();
1398 printf ( "Executing '%s'\n\n", command
.c_str () );
1399 int exitcode
= system ( command
.c_str () );
1400 if ( exitcode
!= 0 )
1401 throw InvocationFailedException ( command
,
1408 Module::SetImportLibrary ( ImportLibrary
* importLibrary
)
1410 this->importLibrary
= importLibrary
;
1411 dependency
= new FileLocation ( HasImportLibrary () ? IntermediateDirectory
: output
->directory
,
1412 output
->relative_path
,
1413 HasImportLibrary () ? "lib" + name
+ ".a" : output
->name
);
1417 Module::SetDelayImportLibrary ( ImportLibrary
* importLibrary
)
1419 this->delayImportLibrary
= importLibrary
;
1423 Module::GetDllName () const
1425 if ( importLibrary
&& !importLibrary
->dllname
.empty() )
1426 return importLibrary
->dllname
;
1428 return output
->name
;
1430 throw new InvalidOperationException ( __FILE__
, __LINE__
, "Module %s has no dllname." );
1434 Module::IsSpecDefinitionFile () const
1439 std::string ext
= GetExtension ( *importLibrary
->source
);
1441 if ( ext
== ".spec" )
1444 if ( ext
== ".pspec" )
1451 File::File ( DirectoryLocation directory
,
1452 const string
& relative_path
,
1455 const string
& _switches
,
1456 bool _isPreCompiledHeader
)
1457 : file ( directory
, relative_path
, name
),
1459 switches(_switches
),
1460 isPreCompiledHeader(_isPreCompiledHeader
)
1471 std::string
File::GetFullPath () const
1473 string
directory ( "" );
1474 switch ( file
.directory
)
1476 case SourceDirectory
:
1478 case IntermediateDirectory
:
1479 directory
= Environment::GetIntermediatePath () + sSep
;
1482 throw InvalidOperationException ( __FILE__
,
1484 "Invalid directory %d.",
1488 if ( file
.relative_path
.length () > 0 )
1489 directory
+= file
.relative_path
+ sSep
;
1492 return directory
+ file
.name
;
1496 Library::Library ( const XMLElement
& _node
,
1497 const Module
& _module
,
1498 const string
& _name
)
1502 importedModule(_module
.project
.LocateModule(_name
)),
1505 if ( module
.name
== name
)
1507 throw XMLInvalidBuildFileException (
1509 "module '%s' cannot link against itself",
1512 if ( !importedModule
)
1514 throw XMLInvalidBuildFileException (
1516 "module '%s' trying to import non-existant module '%s'",
1517 module
.name
.c_str(),
1522 Library::Library ( const Module
& _module
,
1523 const string
& _name
)
1527 importedModule(_module
.project
.LocateModule(_name
)),
1530 if ( !importedModule
)
1532 throw XMLInvalidBuildFileException (
1534 "module '%s' trying to import non-existant module '%s'",
1535 module
.name
.c_str(),
1541 Library::ProcessXML()
1543 if ( node
&& !module
.project
.LocateModule ( name
) )
1545 throw XMLInvalidBuildFileException (
1547 "module '%s' is trying to link against non-existant module '%s'",
1548 module
.name
.c_str(),
1554 Invoke::Invoke ( const XMLElement
& _node
,
1555 const Module
& _module
)
1562 Invoke::ProcessXML()
1564 const XMLAttribute
* att
= node
.GetAttribute ( "module", false );
1566 invokeModule
= &module
;
1569 invokeModule
= module
.project
.LocateModule ( att
->value
);
1570 if ( invokeModule
== NULL
)
1572 throw XMLInvalidBuildFileException (
1574 "module '%s' is trying to invoke non-existant module '%s'",
1575 module
.name
.c_str(),
1576 att
->value
.c_str() );
1580 for ( size_t i
= 0; i
< node
.subElements
.size (); i
++ )
1581 ProcessXMLSubElement ( *node
.subElements
[i
] );
1585 Invoke::ProcessXMLSubElement ( const XMLElement
& e
)
1587 bool subs_invalid
= false;
1588 if ( e
.name
== "input" )
1590 for ( size_t i
= 0; i
< e
.subElements
.size (); i
++ )
1591 ProcessXMLSubElementInput ( *e
.subElements
[i
] );
1593 else if ( e
.name
== "output" )
1595 for ( size_t i
= 0; i
< e
.subElements
.size (); i
++ )
1596 ProcessXMLSubElementOutput ( *e
.subElements
[i
] );
1598 if ( subs_invalid
&& e
.subElements
.size() > 0 )
1600 throw XMLInvalidBuildFileException (
1602 "<%s> cannot have sub-elements",
1608 Invoke::ProcessXMLSubElementInput ( const XMLElement
& e
)
1610 bool subs_invalid
= false;
1611 if ( e
.name
== "inputfile" && e
.value
.size () > 0 )
1613 input
.push_back ( new InvokeFile (
1614 e
, FixSeparator ( module
.output
->relative_path
+ cSep
+ e
.value
) ) );
1615 subs_invalid
= true;
1617 if ( subs_invalid
&& e
.subElements
.size() > 0 )
1619 throw XMLInvalidBuildFileException (
1621 "<%s> cannot have sub-elements",
1627 Invoke::ProcessXMLSubElementOutput ( const XMLElement
& e
)
1629 bool subs_invalid
= false;
1630 if ( e
.name
== "outputfile" && e
.value
.size () > 0 )
1632 output
.push_back ( new InvokeFile (
1633 e
, FixSeparator ( module
.output
->relative_path
+ cSep
+ e
.value
) ) );
1634 subs_invalid
= true;
1636 if ( subs_invalid
&& e
.subElements
.size() > 0 )
1638 throw XMLInvalidBuildFileException (
1640 "<%s> cannot have sub-elements",
1646 Invoke::GetTargets ( string_list
& targets
) const
1648 for ( size_t i
= 0; i
< output
.size (); i
++ )
1650 InvokeFile
& file
= *output
[i
];
1651 targets
.push_back ( NormalizeFilename ( file
.name
) );
1656 Invoke::GetParameters () const
1658 string
parameters ( "" );
1660 for ( i
= 0; i
< output
.size (); i
++ )
1662 if ( parameters
.length () > 0)
1664 InvokeFile
& invokeFile
= *output
[i
];
1665 if ( invokeFile
.switches
.length () > 0 )
1667 parameters
+= invokeFile
.switches
+ " ";
1669 parameters
+= invokeFile
.name
;
1672 for ( i
= 0; i
< input
.size (); i
++ )
1674 if ( parameters
.length () > 0 )
1676 InvokeFile
& invokeFile
= *input
[i
];
1677 if ( invokeFile
.switches
.length () > 0 )
1679 parameters
+= invokeFile
.switches
;
1682 parameters
+= invokeFile
.name
;
1689 InvokeFile::InvokeFile ( const XMLElement
& _node
,
1690 const string
& _name
)
1694 const XMLAttribute
* att
= _node
.GetAttribute ( "switches", false );
1696 switches
= att
->value
;
1702 InvokeFile::ProcessXML()
1707 Dependency::Dependency ( const XMLElement
& _node
,
1708 const Module
& _module
)
1711 dependencyModule (NULL
)
1716 Dependency::ProcessXML()
1718 dependencyModule
= module
.project
.LocateModule ( node
.value
);
1719 if ( dependencyModule
== NULL
)
1721 throw XMLInvalidBuildFileException (
1723 "module '%s' depend on non-existant module '%s'",
1724 module
.name
.c_str(),
1725 node
.value
.c_str() );
1729 Bootsector::Bootsector ( const XMLElement
& _node
,
1730 const Module
* _module
)
1733 bootSectorModule (NULL
)
1735 if ( !IsSupportedModuleType ( module
->type
) )
1737 throw XMLInvalidBuildFileException (
1739 "<bootsector> is not applicable for this module type." );
1742 bootSectorModule
= module
->project
.LocateModule ( node
.value
);
1743 if ( bootSectorModule
== NULL
)
1745 throw XMLInvalidBuildFileException (
1747 "module '%s' depend on non-existant module '%s'",
1748 module
->name
.c_str(),
1749 node
.value
.c_str() );
1752 if (bootSectorModule
->type
!= BootSector
)
1754 throw XMLInvalidBuildFileException (
1756 "module '%s' is referencing non BootSector module '%s'",
1757 module
->name
.c_str(),
1758 node
.value
.c_str() );
1763 Bootsector::ProcessXML()
1768 Bootsector::IsSupportedModuleType ( ModuleType type
)
1779 Metadata::Metadata ( const XMLElement
& _node
,
1780 const Module
& _module
)
1784 /* The module name */
1785 const XMLAttribute
* att
= _node
.GetAttribute ( "name", false );
1791 /* The module description */
1792 att
= _node
.GetAttribute ( "description", false );
1794 description
= att
->value
;
1798 /* The module version */
1799 att
= _node
.GetAttribute ( "version", false );
1801 version
= att
->value
;
1805 /* The module copyright */
1806 att
= _node
.GetAttribute ( "copyright", false );
1808 copyright
= att
->value
;
1812 att
= _node
.GetAttribute ( "url", false );
1818 /* When was this module updated */
1819 att
= _node
.GetAttribute ( "date", false );
1825 /* When was this module updated */
1826 att
= _node
.GetAttribute ( "owner", false );
1834 ImportLibrary::~ImportLibrary ()
1841 ImportLibrary::ImportLibrary ( const Project
& project
,
1842 const XMLElement
& node
,
1843 const Module
* module
,
1845 : XmlNode ( project
, node
),
1848 DirectoryLocation directory
= SourceDirectory
;
1849 const Module
* base
= module
;
1850 const XMLAttribute
* dllname
= node
.GetAttribute ( "dllname", false );
1851 const XMLAttribute
* definition
= node
.GetAttribute ( "definition", true );
1852 assert ( definition
);
1854 string relative_path
;
1855 const XMLAttribute
* att
= node
.GetAttribute ( "base", false );
1858 base
= project
.LocateModule ( att
->value
);
1860 throw XMLInvalidBuildFileException (
1862 "<importlibrary> attribute 'base' references non-existant module '%s'",
1863 att
->value
.c_str() );
1869 relative_path
= base
->output
->relative_path
;
1870 if ( node
.value
.length () > 0 && node
.value
!= "." )
1871 relative_path
+= sSep
+ node
.value
;
1874 relative_path
= node
.value
;
1876 att
= node
.GetAttribute ( "root", false );
1879 if ( att
->value
== "intermediate" )
1880 directory
= IntermediateDirectory
;
1882 throw InvalidAttributeValueException ( node
.location
,
1888 this->dllname
= dllname
->value
;
1890 size_t index
= definition
->value
.find_last_of ( "/\\" );
1891 if ( index
== string::npos
)
1893 source
= new FileLocation ( directory
,
1894 base
->output
->relative_path
,
1900 string dir
= definition
->value
.substr ( 0, index
);
1901 string name
= definition
->value
.substr ( index
+ 1);
1902 source
= new FileLocation ( directory
,
1903 NormalizeFilename ( base
->output
->relative_path
+ sSep
+ dir
),
1908 target
= new FileLocation ( IntermediateDirectory
,
1909 base
->output
->relative_path
,
1910 "lib" + module
->name
+ (delayimp
? ".delayimp.a" : ".a" ));
1915 Property::Property ( const XMLElement
& node_
,
1916 const Project
& project_
,
1917 const Module
* module_
)
1918 : project(project_
), module(module_
)
1920 const XMLAttribute
* att
;
1922 att
= node_
.GetAttribute ( "name", true );
1924 name
= project
.ResolveProperties ( att
->value
);
1926 att
= node_
.GetAttribute ( "value", true );
1930 att
= node_
.GetAttribute ( "internal", false );
1933 const char* p
= att
->value
.c_str();
1934 if ( !stricmp ( p
, "true" ) || !stricmp ( p
, "yes" ) )
1936 else if ( !stricmp ( p
, "false" ) || !stricmp ( p
, "no" ) )
1940 throw InvalidAttributeValueException (
1950 Property::Property ( const Project
& project_
,
1951 const Module
* module_
,
1952 const std::string
& name_
,
1953 const std::string
& value_
)
1954 : project(project_
), module(module_
), name(name_
), value(value_
)
1959 Property::ProcessXML()
1965 const XMLElement
& node_
,
1966 const Module
& module_
,
1967 const FileLocation
*file_
)
1968 : node(node_
), module(module_
), file(file_
)
1978 PchFile::ProcessXML()