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 void IfableData::ExtractModules( std::vector
<Module
*> &modules
)
189 for ( i
= 0; i
< this->modules
.size (); i
++ )
190 modules
.push_back(this->modules
[i
]);
193 IfableData::~IfableData()
196 for ( i
= 0; i
< includes
.size (); i
++ )
198 for ( i
= 0; i
< defines
.size (); i
++ )
200 for ( i
= 0; i
< libraries
.size (); i
++ )
202 for ( i
= 0; i
< properties
.size (); i
++ )
203 delete properties
[i
];
204 for ( i
= 0; i
< compilerFlags
.size (); i
++ )
205 delete compilerFlags
[i
];
206 for ( i
= 0; i
< modules
.size(); i
++ )
208 for ( i
= 0; i
< ifs
.size (); i
++ )
210 for ( i
= 0; i
< compilationUnits
.size (); i
++ )
211 delete compilationUnits
[i
];
214 void IfableData::ProcessXML ()
217 for ( i
= 0; i
< includes
.size (); i
++ )
218 includes
[i
]->ProcessXML ();
219 for ( i
= 0; i
< defines
.size (); i
++ )
220 defines
[i
]->ProcessXML ();
221 for ( i
= 0; i
< libraries
.size (); i
++ )
222 libraries
[i
]->ProcessXML ();
223 for ( i
= 0; i
< properties
.size(); i
++ )
224 properties
[i
]->ProcessXML ();
225 for ( i
= 0; i
< compilerFlags
.size(); i
++ )
226 compilerFlags
[i
]->ProcessXML ();
227 for ( i
= 0; i
< ifs
.size (); i
++ )
228 ifs
[i
]->ProcessXML ();
229 for ( i
= 0; i
< compilationUnits
.size (); i
++ )
230 compilationUnits
[i
]->ProcessXML ();
233 Module::Module ( const Project
& project
,
234 const XMLElement
& moduleNode
,
235 const string
& modulePath
)
238 importLibrary (NULL
),
247 if ( node
.name
!= "module" )
248 throw InvalidOperationException ( __FILE__
,
250 "Module created with non-<module> node" );
252 xmlbuildFile
= Path::RelativeFromWorkingDirectory ( moduleNode
.xmlFile
->filename () );
254 const XMLAttribute
* att
= moduleNode
.GetAttribute ( "name", true );
260 att
= moduleNode
.GetAttribute ( "if", false );
262 enabled
= GetBooleanValue ( project
.ResolveProperties ( att
->value
) );
264 att
= moduleNode
.GetAttribute ( "ifnot", false );
266 enabled
= !GetBooleanValue ( project
.ResolveProperties ( att
->value
) );
268 if ( !enabled
&& project
.configuration
.Verbose
)
269 printf("Module '%s' has been disabled.\n", name
.c_str () );
271 att
= moduleNode
.GetAttribute ( "type", true );
273 type
= GetModuleType ( node
.location
, *att
);
275 att
= moduleNode
.GetAttribute ( "extension", false );
277 extension
= att
->value
;
279 extension
= GetDefaultModuleExtension ();
281 output
= new FileLocation ( GetTargetDirectoryTree (),
285 att
= moduleNode
.GetAttribute ( "unicode", false );
288 const char* p
= att
->value
.c_str();
289 if ( !stricmp ( p
, "true" ) || !stricmp ( p
, "yes" ) )
291 else if ( !stricmp ( p
, "false" ) || !stricmp ( p
, "no" ) )
295 throw InvalidAttributeValueException (
306 // Always define UNICODE and _UNICODE
307 Define
* pDefine
= new Define ( project
, this, "UNICODE" );
308 non_if_data
.defines
.push_back ( pDefine
);
310 pDefine
= new Define ( project
, this, "_UNICODE" );
311 non_if_data
.defines
.push_back ( pDefine
);
314 att
= moduleNode
.GetAttribute ( "entrypoint", false );
317 if ( att
->value
== "" )
319 throw InvalidAttributeValueException (
325 entrypoint
= att
->value
;
326 isDefaultEntryPoint
= false;
330 entrypoint
= GetDefaultModuleEntrypoint ();
331 isDefaultEntryPoint
= true;
334 att
= moduleNode
.GetAttribute ( "baseaddress", false );
336 baseaddress
= att
->value
;
338 baseaddress
= GetDefaultModuleBaseaddress ();
340 att
= moduleNode
.GetAttribute ( "mangledsymbols", false );
343 const char* p
= att
->value
.c_str();
344 if ( !stricmp ( p
, "true" ) || !stricmp ( p
, "yes" ) )
345 mangledSymbols
= true;
346 else if ( !stricmp ( p
, "false" ) || !stricmp ( p
, "no" ) )
347 mangledSymbols
= false;
350 throw InvalidAttributeValueException (
357 mangledSymbols
= false;
359 att
= moduleNode
.GetAttribute ( "underscoresymbols", false );
361 underscoreSymbols
= att
->value
== "true";
363 underscoreSymbols
= false;
365 att
= moduleNode
.GetAttribute ( "host", false );
368 const char* p
= att
->value
.c_str();
369 if ( !stricmp ( p
, "true" ) || !stricmp ( p
, "yes" ) )
371 else if ( !stricmp ( p
, "false" ) || !stricmp ( p
, "no" ) )
375 throw InvalidAttributeValueException (
382 att
= moduleNode
.GetAttribute ( "isstartuplib", false );
385 const char* p
= att
->value
.c_str();
386 if ( !stricmp ( p
, "true" ) || !stricmp ( p
, "yes" ) )
388 else if ( !stricmp ( p
, "false" ) || !stricmp ( p
, "no" ) )
389 isStartupLib
= false;
392 throw InvalidAttributeValueException (
399 isStartupLib
= false;
401 att
= moduleNode
.GetAttribute ( "prefix", false );
405 att
= moduleNode
.GetAttribute ( "installname", false );
408 const XMLAttribute
* installbase
= moduleNode
.GetAttribute ( "installbase", false );
409 install
= new FileLocation ( InstallDirectory
,
410 installbase
? installbase
->value
: "",
416 att
= moduleNode
.GetAttribute ( "usewrc", false );
418 useWRC
= att
->value
== "true";
422 att
= moduleNode
.GetAttribute ( "allowwarnings", false );
425 att
= moduleNode
.GetAttribute ( "warnings", false );
428 printf ( "%s: WARNING: 'warnings' attribute of <module> is deprecated, use 'allowwarnings' instead\n",
429 moduleNode
.location
.c_str() );
433 allowWarnings
= att
->value
== "true";
435 allowWarnings
= false;
437 att
= moduleNode
.GetAttribute ( "aliasof", false );
438 if ( type
== Alias
&& att
!= NULL
)
439 aliasedModuleName
= att
->value
;
441 aliasedModuleName
= "";
443 if ( type
== BootProgram
)
445 att
= moduleNode
.GetAttribute ( "payload", true );
446 payload
= att
->value
;
449 if ( type
== BootProgram
|| type
== ElfExecutable
)
451 att
= moduleNode
.GetAttribute ( "buildtype", false );
454 buildtype
= att
->value
;
458 buildtype
= "BOOTPROG";
462 SetImportLibrary ( NULL
);
468 for ( i
= 0; i
< invocations
.size(); i
++ )
469 delete invocations
[i
];
470 for ( i
= 0; i
< dependencies
.size(); i
++ )
471 delete dependencies
[i
];
472 for ( i
= 0; i
< compilerFlags
.size(); i
++ )
473 delete compilerFlags
[i
];
474 for ( i
= 0; i
< linkerFlags
.size(); i
++ )
475 delete linkerFlags
[i
];
476 for ( i
= 0; i
< stubbedComponents
.size(); i
++ )
477 delete stubbedComponents
[i
];
489 aliasedModuleName
= project
.ResolveProperties ( aliasedModuleName
);
490 if ( aliasedModuleName
== name
)
492 throw XMLInvalidBuildFileException (
494 "module '%s' cannot link against itself",
497 const Module
* m
= project
.LocateModule ( aliasedModuleName
);
500 throw XMLInvalidBuildFileException (
502 "module '%s' trying to alias non-existant module '%s'",
504 aliasedModuleName
.c_str() );
509 for ( i
= 0; i
< node
.subElements
.size(); i
++ )
511 ParseContext parseContext
;
512 ProcessXMLSubElement ( *node
.subElements
[i
], SourceDirectory
, output
->relative_path
, parseContext
);
514 for ( i
= 0; i
< invocations
.size(); i
++ )
515 invocations
[i
]->ProcessXML ();
516 for ( i
= 0; i
< dependencies
.size(); i
++ )
517 dependencies
[i
]->ProcessXML ();
518 for ( i
= 0; i
< compilerFlags
.size(); i
++ )
519 compilerFlags
[i
]->ProcessXML();
520 for ( i
= 0; i
< linkerFlags
.size(); i
++ )
521 linkerFlags
[i
]->ProcessXML();
522 for ( i
= 0; i
< stubbedComponents
.size(); i
++ )
523 stubbedComponents
[i
]->ProcessXML();
524 non_if_data
.ProcessXML();
526 linkerScript
->ProcessXML();
530 autoRegister
->ProcessXML();
534 Module::ProcessXMLSubElement ( const XMLElement
& e
,
535 DirectoryLocation directory
,
536 const string
& relative_path
,
537 ParseContext
& parseContext
)
539 If
* pOldIf
= parseContext
.ifData
;
540 CompilationUnit
* pOldCompilationUnit
= parseContext
.compilationUnit
;
541 bool subs_invalid
= false;
542 string
subpath ( relative_path
);
543 DirectoryLocation subdirectory
= SourceDirectory
;
544 if ( e
.name
== "file" && e
.value
.size () > 0 )
547 const XMLAttribute
* att
= e
.GetAttribute ( "first", false );
550 if ( !stricmp ( att
->value
.c_str(), "true" ) )
552 else if ( stricmp ( att
->value
.c_str(), "false" ) )
554 throw XMLInvalidBuildFileException (
556 "attribute 'first' of <file> element can only be 'true' or 'false'" );
559 string switches
= "";
560 att
= e
.GetAttribute ( "switches", false );
562 switches
= att
->value
;
565 // check for c++ file
566 string ext
= GetExtension ( e
.value
);
567 if ( !stricmp ( ext
.c_str(), ".cpp" ) )
569 else if ( !stricmp ( ext
.c_str(), ".cc" ) )
571 else if ( !stricmp ( ext
.c_str(), ".cxx" ) )
574 File
* pFile
= new File ( directory
,
580 if ( parseContext
.compilationUnit
)
581 parseContext
.compilationUnit
->files
.push_back ( pFile
);
584 CompilationUnit
* pCompilationUnit
= new CompilationUnit ( pFile
);
585 if ( parseContext
.ifData
)
586 parseContext
.ifData
->data
.compilationUnits
.push_back ( pCompilationUnit
);
589 string ext
= GetExtension ( e
.value
);
590 if ( !stricmp ( ext
.c_str(), ".idl" ) )
591 non_if_data
.compilationUnits
.insert ( non_if_data
.compilationUnits
.begin(), pCompilationUnit
);
593 non_if_data
.compilationUnits
.push_back ( pCompilationUnit
);
596 if ( parseContext
.ifData
)
597 parseContext
.ifData
->data
.files
.push_back ( pFile
);
599 non_if_data
.files
.push_back ( pFile
);
602 else if ( e
.name
== "library" && e
.value
.size () )
604 Library
* pLibrary
= new Library ( e
, *this, e
.value
);
605 if ( parseContext
.ifData
)
606 parseContext
.ifData
->data
.libraries
.push_back ( pLibrary
);
608 non_if_data
.libraries
.push_back ( pLibrary
);
611 else if ( e
.name
== "directory" )
613 const XMLAttribute
* att
= e
.GetAttribute ( "name", true );
614 const XMLAttribute
* root
= e
.GetAttribute ( "root", false );
618 if ( root
->value
== "intermediate" )
619 subdirectory
= IntermediateDirectory
;
620 else if ( root
->value
== "output" )
621 subdirectory
= OutputDirectory
;
624 throw InvalidAttributeValueException (
630 subpath
= GetSubPath ( this->project
, e
.location
, relative_path
, att
->value
);
632 else if ( e
.name
== "include" )
634 Include
* include
= new Include ( project
, &e
, this );
635 if ( parseContext
.ifData
)
636 parseContext
.ifData
->data
.includes
.push_back ( include
);
638 non_if_data
.includes
.push_back ( include
);
641 else if ( e
.name
== "define" )
643 Define
* pDefine
= new Define ( project
, this, e
);
644 if ( parseContext
.ifData
)
645 parseContext
.ifData
->data
.defines
.push_back ( pDefine
);
647 non_if_data
.defines
.push_back ( pDefine
);
650 else if ( e
.name
== "metadata" )
652 if ( parseContext
.ifData
)
654 throw XMLInvalidBuildFileException (
656 "<metadata> is not a valid sub-element of <if>" );
658 metadata
= new Metadata ( e
, *this );
659 subs_invalid
= false;
661 else if ( e
.name
== "invoke" )
663 if ( parseContext
.ifData
)
665 throw XMLInvalidBuildFileException (
667 "<invoke> is not a valid sub-element of <if>" );
669 invocations
.push_back ( new Invoke ( e
, *this ) );
670 subs_invalid
= false;
672 else if ( e
.name
== "dependency" )
674 if ( parseContext
.ifData
)
676 throw XMLInvalidBuildFileException (
678 "<dependency> is not a valid sub-element of <if>" );
680 dependencies
.push_back ( new Dependency ( e
, *this ) );
683 else if ( e
.name
== "importlibrary" )
685 if ( parseContext
.ifData
)
687 throw XMLInvalidBuildFileException (
689 "<importlibrary> is not a valid sub-element of <if>" );
693 throw XMLInvalidBuildFileException (
695 "Only one <importlibrary> is valid per module" );
697 SetImportLibrary ( new ImportLibrary ( project
, e
, *this ) );
700 else if ( e
.name
== "if" )
702 parseContext
.ifData
= new If ( e
, project
, this );
704 pOldIf
->data
.ifs
.push_back ( parseContext
.ifData
);
706 non_if_data
.ifs
.push_back ( parseContext
.ifData
);
707 subs_invalid
= false;
709 else if ( e
.name
== "ifnot" )
711 parseContext
.ifData
= new If ( e
, project
, this, true );
713 pOldIf
->data
.ifs
.push_back ( parseContext
.ifData
);
715 non_if_data
.ifs
.push_back ( parseContext
.ifData
);
716 subs_invalid
= false;
718 else if ( e
.name
== "compilerflag" )
720 CompilerFlag
* pCompilerFlag
= new CompilerFlag ( project
, this, e
);
721 if ( parseContext
.ifData
)
722 parseContext
.ifData
->data
.compilerFlags
.push_back ( pCompilerFlag
);
724 non_if_data
.compilerFlags
.push_back ( pCompilerFlag
);
727 else if ( e
.name
== "linkerflag" )
729 linkerFlags
.push_back ( new LinkerFlag ( project
, this, e
) );
732 else if ( e
.name
== "linkerscript" )
736 throw XMLInvalidBuildFileException (
738 "Only one <linkerscript> is valid per module" );
740 linkerScript
= new LinkerScript ( project
, this, e
);
743 else if ( e
.name
== "component" )
745 stubbedComponents
.push_back ( new StubbedComponent ( this, e
) );
746 subs_invalid
= false;
748 else if ( e
.name
== "property" )
750 throw XMLInvalidBuildFileException (
752 "<property> is not a valid sub-element of <module>" );
754 else if ( e
.name
== "bootstrap" )
756 bootstrap
= new Bootstrap ( project
, this, e
);
759 else if ( e
.name
== "pch" )
761 if ( parseContext
.ifData
)
763 throw XMLInvalidBuildFileException (
765 "<pch> is not a valid sub-element of <if>" );
769 throw XMLInvalidBuildFileException (
771 "Only one <pch> is valid per module" );
773 size_t pos
= e
.value
.find_last_of ( "/\\" );
774 if ( pos
== string::npos
)
777 e
, *this, FileLocation ( SourceDirectory
, relative_path
, e
.value
) );
781 string dir
= e
.value
.substr ( 0, pos
);
782 string name
= e
.value
.substr ( pos
+ 1);
784 e
, *this, FileLocation ( SourceDirectory
, relative_path
+ sSep
+ dir
, name
) );
788 else if ( e
.name
== "compilationunit" )
790 if ( project
.configuration
.CompilationUnitsEnabled
)
792 CompilationUnit
* pCompilationUnit
= new CompilationUnit ( &project
, this, &e
);
793 if ( parseContext
.ifData
)
794 parseContext
.ifData
->data
.compilationUnits
.push_back ( pCompilationUnit
);
796 non_if_data
.compilationUnits
.push_back ( pCompilationUnit
);
797 parseContext
.compilationUnit
= pCompilationUnit
;
799 subs_invalid
= false;
801 else if ( e
.name
== "autoregister" )
803 if ( autoRegister
!= NULL
)
805 throw XMLInvalidBuildFileException (
807 "there can be only one <%s> element for a module",
810 autoRegister
= new AutoRegister ( project
, this, e
);
813 if ( subs_invalid
&& e
.subElements
.size() > 0 )
815 throw XMLInvalidBuildFileException (
817 "<%s> cannot have sub-elements",
820 for ( size_t i
= 0; i
< e
.subElements
.size (); i
++ )
821 ProcessXMLSubElement ( *e
.subElements
[i
], subdirectory
, subpath
, parseContext
);
822 parseContext
.ifData
= pOldIf
;
823 parseContext
.compilationUnit
= pOldCompilationUnit
;
827 Module::GetModuleType ( const string
& location
, const XMLAttribute
& attribute
)
829 if ( attribute
.value
== "buildtool" )
831 if ( attribute
.value
== "staticlibrary" )
832 return StaticLibrary
;
833 if ( attribute
.value
== "objectlibrary" )
834 return ObjectLibrary
;
835 if ( attribute
.value
== "kernel" )
837 if ( attribute
.value
== "kernelmodedll" )
838 return KernelModeDLL
;
839 if ( attribute
.value
== "kernelmodedriver" )
840 return KernelModeDriver
;
841 if ( attribute
.value
== "nativedll" )
843 if ( attribute
.value
== "nativecui" )
845 if ( attribute
.value
== "win32dll" )
847 if ( attribute
.value
== "win32ocx" )
849 if ( attribute
.value
== "win32cui" )
851 if ( attribute
.value
== "win32gui" )
853 if ( attribute
.value
== "win32scr" )
855 if ( attribute
.value
== "bootloader" )
857 if ( attribute
.value
== "bootsector" )
859 if ( attribute
.value
== "bootprogram" )
861 if ( attribute
.value
== "iso" )
863 if ( attribute
.value
== "liveiso" )
865 if ( attribute
.value
== "isoregtest" )
867 if ( attribute
.value
== "liveisoregtest" )
868 return LiveIsoRegTest
;
869 if ( attribute
.value
== "test" )
871 if ( attribute
.value
== "rpcserver" )
873 if ( attribute
.value
== "rpcclient" )
875 if ( attribute
.value
== "alias" )
877 if ( attribute
.value
== "idlheader" )
879 if ( attribute
.value
== "embeddedtypelib" )
880 return EmbeddedTypeLib
;
881 if ( attribute
.value
== "elfexecutable" )
882 return ElfExecutable
;
883 throw InvalidAttributeValueException ( location
,
889 Module::GetTargetDirectoryTree () const
898 case KernelModeDriver
:
912 case EmbeddedTypeLib
:
914 return OutputDirectory
;
921 return IntermediateDirectory
;
923 throw InvalidOperationException ( __FILE__
,
925 "Invalid module type %d.",
930 Module::GetDefaultModuleExtension () const
955 case KernelModeDriver
:
975 case EmbeddedTypeLib
:
978 throw InvalidOperationException ( __FILE__
,
983 Module::GetDefaultModuleEntrypoint () const
988 return "NtProcessStartup";
990 case KernelModeDriver
:
991 return "DriverEntry@8";
993 return "DllMainCRTStartup@12";
995 return "NtProcessStartup@4";
1002 return "wmainCRTStartup";
1004 return "mainCRTStartup";
1008 return "wWinMainCRTStartup";
1010 return "WinMainCRTStartup";
1019 case LiveIsoRegTest
:
1026 case EmbeddedTypeLib
:
1029 throw InvalidOperationException ( __FILE__
,
1034 Module::GetDefaultModuleBaseaddress () const
1039 return "0x80800000";
1042 return "0x10000000";
1047 return "0x00400000";
1050 return "0x00400000";
1052 case KernelModeDriver
:
1053 return "0x00010000";
1064 case LiveIsoRegTest
:
1070 case EmbeddedTypeLib
:
1073 throw InvalidOperationException ( __FILE__
,
1078 Module::HasImportLibrary () const
1080 return importLibrary
!= NULL
&& type
!= StaticLibrary
;
1084 Module::IsDLL () const
1093 case KernelModeDriver
:
1109 case LiveIsoRegTest
:
1114 case EmbeddedTypeLib
:
1118 throw InvalidOperationException ( __FILE__
,
1123 Module::GetPathWithPrefix ( const string
& prefix
) const
1125 return output
->relative_path
+ cSep
+ prefix
+ output
->name
;
1129 Module::GetPathToBaseDir () const
1131 string temp_path
= output
->relative_path
;
1132 string result
= "..\\";
1133 while(temp_path
.find ('\\') != string::npos
)
1135 temp_path
.erase (0, temp_path
.find('\\')+1);
1142 Module::GetInvocationTarget ( const int index
) const
1144 return ssprintf ( "%s_invoke_%d",
1150 Module::GetEntryPoint(bool leadingUnderscore
) const
1153 if (entrypoint
== "0" || entrypoint
== "0x0")
1155 if (leadingUnderscore
)
1158 result
+= entrypoint
;
1163 Module::HasFileWithExtension (
1164 const IfableData
& data
,
1165 const std::string
& extension
) const
1168 for ( i
= 0; i
< data
.compilationUnits
.size (); i
++ )
1170 CompilationUnit
* compilationUnit
= data
.compilationUnits
[i
];
1171 if ( compilationUnit
->HasFileWithExtension ( extension
) )
1174 for ( i
= 0; i
< data
.ifs
.size (); i
++ )
1176 if ( HasFileWithExtension ( data
.ifs
[i
]->data
, extension
) )
1183 Module::InvokeModule () const
1185 for ( size_t i
= 0; i
< invocations
.size (); i
++ )
1187 Invoke
& invoke
= *invocations
[i
];
1188 string command
= FixSeparatorForSystemCommand(invoke
.invokeModule
->output
->relative_path
+ "/" + invoke
.invokeModule
->output
->name
) + " " + invoke
.GetParameters ();
1189 printf ( "Executing '%s'\n\n", command
.c_str () );
1190 int exitcode
= system ( command
.c_str () );
1191 if ( exitcode
!= 0 )
1192 throw InvocationFailedException ( command
,
1199 Module::SetImportLibrary ( ImportLibrary
* importLibrary
)
1201 this->importLibrary
= importLibrary
;
1202 dependency
= new FileLocation ( IntermediateDirectory
,
1203 output
->relative_path
,
1204 HasImportLibrary () ? "lib" + name
+ ".a" : output
->name
);
1208 File::File ( DirectoryLocation directory
,
1209 const string
& relative_path
,
1212 const string
& _switches
,
1213 bool _isPreCompiledHeader
)
1214 : file ( directory
, relative_path
, name
),
1216 switches(_switches
),
1217 isPreCompiledHeader(_isPreCompiledHeader
)
1228 std::string
File::GetFullPath () const
1230 string
directory ( "" );
1231 switch ( file
.directory
)
1233 case SourceDirectory
:
1235 case IntermediateDirectory
:
1236 directory
= Environment::GetIntermediatePath () + sSep
;
1239 throw InvalidOperationException ( __FILE__
,
1241 "Invalid directory %d.",
1245 if ( file
.relative_path
.length () > 0 )
1246 directory
+= file
.relative_path
+ sSep
;
1249 return directory
+ file
.name
;
1253 Library::Library ( const XMLElement
& _node
,
1254 const Module
& _module
,
1255 const string
& _name
)
1259 importedModule(_module
.project
.LocateModule(_name
))
1261 if ( module
.name
== name
)
1263 throw XMLInvalidBuildFileException (
1265 "module '%s' cannot link against itself",
1268 if ( !importedModule
)
1270 throw XMLInvalidBuildFileException (
1272 "module '%s' trying to import non-existant module '%s'",
1273 module
.name
.c_str(),
1278 Library::Library ( const Module
& _module
,
1279 const string
& _name
)
1283 importedModule(_module
.project
.LocateModule(_name
))
1288 Library::ProcessXML()
1290 if ( node
&& !module
.project
.LocateModule ( name
) )
1292 throw XMLInvalidBuildFileException (
1294 "module '%s' is trying to link against non-existant module '%s'",
1295 module
.name
.c_str(),
1301 Invoke::Invoke ( const XMLElement
& _node
,
1302 const Module
& _module
)
1309 Invoke::ProcessXML()
1311 const XMLAttribute
* att
= node
.GetAttribute ( "module", false );
1313 invokeModule
= &module
;
1316 invokeModule
= module
.project
.LocateModule ( att
->value
);
1317 if ( invokeModule
== NULL
)
1319 throw XMLInvalidBuildFileException (
1321 "module '%s' is trying to invoke non-existant module '%s'",
1322 module
.name
.c_str(),
1323 att
->value
.c_str() );
1327 for ( size_t i
= 0; i
< node
.subElements
.size (); i
++ )
1328 ProcessXMLSubElement ( *node
.subElements
[i
] );
1332 Invoke::ProcessXMLSubElement ( const XMLElement
& e
)
1334 bool subs_invalid
= false;
1335 if ( e
.name
== "input" )
1337 for ( size_t i
= 0; i
< e
.subElements
.size (); i
++ )
1338 ProcessXMLSubElementInput ( *e
.subElements
[i
] );
1340 else if ( e
.name
== "output" )
1342 for ( size_t i
= 0; i
< e
.subElements
.size (); i
++ )
1343 ProcessXMLSubElementOutput ( *e
.subElements
[i
] );
1345 if ( subs_invalid
&& e
.subElements
.size() > 0 )
1347 throw XMLInvalidBuildFileException (
1349 "<%s> cannot have sub-elements",
1355 Invoke::ProcessXMLSubElementInput ( const XMLElement
& e
)
1357 bool subs_invalid
= false;
1358 if ( e
.name
== "inputfile" && e
.value
.size () > 0 )
1360 input
.push_back ( new InvokeFile (
1361 e
, FixSeparator ( module
.output
->relative_path
+ cSep
+ e
.value
) ) );
1362 subs_invalid
= true;
1364 if ( subs_invalid
&& e
.subElements
.size() > 0 )
1366 throw XMLInvalidBuildFileException (
1368 "<%s> cannot have sub-elements",
1374 Invoke::ProcessXMLSubElementOutput ( const XMLElement
& e
)
1376 bool subs_invalid
= false;
1377 if ( e
.name
== "outputfile" && e
.value
.size () > 0 )
1379 output
.push_back ( new InvokeFile (
1380 e
, FixSeparator ( module
.output
->relative_path
+ cSep
+ e
.value
) ) );
1381 subs_invalid
= true;
1383 if ( subs_invalid
&& e
.subElements
.size() > 0 )
1385 throw XMLInvalidBuildFileException (
1387 "<%s> cannot have sub-elements",
1393 Invoke::GetTargets ( string_list
& targets
) const
1395 for ( size_t i
= 0; i
< output
.size (); i
++ )
1397 InvokeFile
& file
= *output
[i
];
1398 targets
.push_back ( NormalizeFilename ( file
.name
) );
1403 Invoke::GetParameters () const
1405 string
parameters ( "" );
1407 for ( i
= 0; i
< output
.size (); i
++ )
1409 if ( parameters
.length () > 0)
1411 InvokeFile
& invokeFile
= *output
[i
];
1412 if ( invokeFile
.switches
.length () > 0 )
1414 parameters
+= invokeFile
.switches
+ " ";
1416 parameters
+= invokeFile
.name
;
1419 for ( i
= 0; i
< input
.size (); i
++ )
1421 if ( parameters
.length () > 0 )
1423 InvokeFile
& invokeFile
= *input
[i
];
1424 if ( invokeFile
.switches
.length () > 0 )
1426 parameters
+= invokeFile
.switches
;
1429 parameters
+= invokeFile
.name
;
1436 InvokeFile::InvokeFile ( const XMLElement
& _node
,
1437 const string
& _name
)
1441 const XMLAttribute
* att
= _node
.GetAttribute ( "switches", false );
1443 switches
= att
->value
;
1449 InvokeFile::ProcessXML()
1454 Dependency::Dependency ( const XMLElement
& _node
,
1455 const Module
& _module
)
1458 dependencyModule (NULL
)
1463 Dependency::ProcessXML()
1465 dependencyModule
= module
.project
.LocateModule ( node
.value
);
1466 if ( dependencyModule
== NULL
)
1468 throw XMLInvalidBuildFileException (
1470 "module '%s' depend on non-existant module '%s'",
1471 module
.name
.c_str(),
1472 node
.value
.c_str() );
1477 Metadata::Metadata ( const XMLElement
& _node
,
1478 const Module
& _module
)
1482 /* The module name */
1483 const XMLAttribute
* att
= _node
.GetAttribute ( "name", false );
1489 /* The module description */
1490 att
= _node
.GetAttribute ( "description", false );
1492 description
= att
->value
;
1496 /* The module version */
1497 att
= _node
.GetAttribute ( "version", false );
1499 version
= att
->value
;
1503 /* The module copyright */
1504 att
= _node
.GetAttribute ( "copyright", false );
1506 copyright
= att
->value
;
1510 att
= _node
.GetAttribute ( "url", false );
1516 /* When was this module updated */
1517 att
= _node
.GetAttribute ( "date", false );
1523 /* When was this module updated */
1524 att
= _node
.GetAttribute ( "owner", false );
1532 ImportLibrary::ImportLibrary ( const Project
& project
,
1533 const XMLElement
& node
,
1534 const Module
& module
)
1535 : XmlNode ( project
, node
),
1538 const XMLAttribute
* dllname
= node
.GetAttribute ( "dllname", false );
1539 const XMLAttribute
* definition
= node
.GetAttribute ( "definition", true );
1540 assert ( definition
);
1543 this->dllname
= dllname
->value
;
1544 else if ( module
.type
== StaticLibrary
)
1545 throw XMLInvalidBuildFileException (
1547 "<importlibrary> dllname attribute required." );
1549 DirectoryLocation directory
= SourceDirectory
;
1550 size_t index
= definition
->value
.rfind ( ".spec.def" );
1551 if ( index
!= string::npos
)
1552 directory
= IntermediateDirectory
;
1554 index
= definition
->value
.find_last_of ( "/\\" );
1555 if ( index
== string::npos
)
1557 source
= new FileLocation ( directory
,
1558 module
.output
->relative_path
,
1559 definition
->value
);
1563 string dir
= definition
->value
.substr ( 0, index
);
1564 string name
= definition
->value
.substr ( index
+ 1);
1565 source
= new FileLocation ( directory
,
1566 NormalizeFilename ( module
.output
->relative_path
+ sSep
+ dir
),
1572 If::If ( const XMLElement
& node_
,
1573 const Project
& project_
,
1574 const Module
* module_
,
1575 const bool negated_
)
1576 : node(node_
), project(project_
), module(module_
), negated(negated_
)
1578 const XMLAttribute
* att
;
1580 att
= node
.GetAttribute ( "property", true );
1582 property
= att
->value
;
1584 att
= node
.GetAttribute ( "value", true );
1600 Property::Property ( const XMLElement
& node_
,
1601 const Project
& project_
,
1602 const Module
* module_
)
1603 : project(project_
), module(module_
)
1605 const XMLAttribute
* att
;
1607 att
= node_
.GetAttribute ( "name", true );
1609 name
= project
.ResolveProperties ( att
->value
);
1611 att
= node_
.GetAttribute ( "value", true );
1616 Property::Property ( const Project
& project_
,
1617 const Module
* module_
,
1618 const std::string
& name_
,
1619 const std::string
& value_
)
1620 : project(project_
), module(module_
), name(name_
), value(value_
)
1625 Property::ProcessXML()
1631 const XMLElement
& node_
,
1632 const Module
& module_
,
1633 const FileLocation
& file_
)
1634 : node(node_
), module(module_
), file(file_
)
1639 PchFile::ProcessXML()