- Stop adding those damn @ decorations to ARM builds.
[reactos.git] / reactos / tools / rbuild / module.cpp
1 /*
2 * Copyright (C) 2005 Casper S. Hornstrup
3 *
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.
8 *
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.
13 *
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.
17 */
18 #include "pch.h"
19 #include <assert.h>
20
21 #include "rbuild.h"
22
23 using std::string;
24 using std::vector;
25
26 string
27 Right ( const string& s, size_t n )
28 {
29 if ( n > s.size() )
30 return s;
31 return string ( &s[s.size()-n] );
32 }
33
34 string
35 Replace ( const string& s, const string& find, const string& with )
36 {
37 string ret;
38 const char* p = s.c_str();
39 while ( p )
40 {
41 const char* p2 = strstr ( p, find.c_str() );
42 if ( !p2 )
43 break;
44 if ( p2 > p )
45 ret += string ( p, p2-p );
46 ret += with;
47 p = p2 + find.size();
48 }
49 if ( *p )
50 ret += p;
51 return ret;
52 }
53
54 string
55 ChangeSeparator ( const string& s,
56 const char fromSeparator,
57 const char toSeparator )
58 {
59 string s2(s);
60 char* p = strchr ( &s2[0], fromSeparator );
61 while ( p )
62 {
63 *p++ = toSeparator;
64 p = strchr ( p, fromSeparator );
65 }
66 return s2;
67 }
68
69 string
70 FixSeparator ( const string& s )
71 {
72 return ChangeSeparator ( s, cBadSep, cSep );
73 }
74
75 string
76 FixSeparatorForSystemCommand ( const string& s )
77 {
78 string s2(s);
79 char* p = strchr ( &s2[0], DEF_CBAD_SEP );
80 while ( p )
81 {
82 *p++ = DEF_CSEP;
83 p = strchr ( p, DEF_CBAD_SEP );
84 }
85 return s2;
86 }
87
88 string
89 DosSeparator ( const string& s )
90 {
91 string s2(s);
92 char* p = strchr ( &s2[0], '/' );
93 while ( p )
94 {
95 *p++ = '\\';
96 p = strchr ( p, '/' );
97 }
98 return s2;
99 }
100
101 string
102 ReplaceExtension (
103 const string& filename,
104 const string& newExtension )
105 {
106 size_t index = filename.find_last_of ( '/' );
107 if ( index == string::npos )
108 index = 0;
109 size_t index2 = filename.find_last_of ( '\\' );
110 if ( index2 != string::npos && index2 > index )
111 index = index2;
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;
117 }
118
119 string
120 GetSubPath (
121 const Project& project,
122 const string& location,
123 const string& path,
124 const string& att_value )
125 {
126 if ( !att_value.size() )
127 throw XMLInvalidBuildFileException (
128 location,
129 "<directory> tag has empty 'name' attribute" );
130 if ( strpbrk ( att_value.c_str (), "/\\?*:<>|" ) )
131 throw XMLInvalidBuildFileException (
132 location,
133 "<directory> tag has invalid characters in 'name' attribute" );
134 if ( !path.size() )
135 return att_value;
136
137 return FixSeparator(path + cSep + att_value);
138 }
139
140 static string
141 GetExtension ( const string& filename )
142 {
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() );
149 return "";
150 }
151
152 string
153 GetExtension ( const FileLocation& file )
154 {
155 return GetExtension ( file.name );
156 }
157
158 string
159 NormalizeFilename ( const string& filename )
160 {
161 if ( filename == "" )
162 return "";
163 Path path;
164 string normalizedPath = path.Fixup ( filename, true );
165 string relativeNormalizedPath = path.RelativeFromWorkingDirectory ( normalizedPath );
166 return FixSeparator ( relativeNormalizedPath );
167 }
168
169 bool
170 GetBooleanValue ( const string& value )
171 {
172 if ( value == "1" )
173 return true;
174 else
175 return false;
176 }
177
178 string
179 ToLower ( string filename )
180 {
181 for ( size_t i = 1; i < filename.length (); i++ )
182 filename[i] = tolower ( filename[i] );
183 return filename;
184 }
185
186 IfableData::IfableData( )
187 : asmFiles ( 0 )
188 {
189 }
190
191 void IfableData::ExtractModules( std::vector<Module*> &modules )
192 {
193 size_t i;
194 for ( i = 0; i < this->modules.size (); i++ )
195 modules.push_back(this->modules[i]);
196 }
197
198 IfableData::~IfableData()
199 {
200 size_t i;
201 for ( i = 0; i < includes.size (); i++ )
202 delete includes[i];
203 for ( i = 0; i < defines.size (); i++ )
204 delete defines[i];
205 for ( i = 0; i < libraries.size (); i++ )
206 delete libraries[i];
207 for ( i = 0; i < properties.size (); i++ )
208 delete properties[i];
209 for ( i = 0; i < compilerFlags.size (); i++ )
210 delete compilerFlags[i];
211 for ( i = 0; i < modules.size(); i++ )
212 delete modules[i];
213 for ( i = 0; i < ifs.size (); i++ )
214 delete ifs[i];
215 for ( i = 0; i < compilationUnits.size (); i++ )
216 delete compilationUnits[i];
217 }
218
219 void IfableData::ProcessXML ()
220 {
221 size_t i;
222 for ( i = 0; i < includes.size (); i++ )
223 includes[i]->ProcessXML ();
224 for ( i = 0; i < defines.size (); i++ )
225 defines[i]->ProcessXML ();
226 for ( i = 0; i < libraries.size (); i++ )
227 libraries[i]->ProcessXML ();
228 for ( i = 0; i < properties.size(); i++ )
229 properties[i]->ProcessXML ();
230 for ( i = 0; i < compilerFlags.size(); i++ )
231 compilerFlags[i]->ProcessXML ();
232 for ( i = 0; i < ifs.size (); i++ )
233 ifs[i]->ProcessXML ();
234 for ( i = 0; i < compilationUnits.size (); i++ )
235 compilationUnits[i]->ProcessXML ();
236 }
237
238 Module::Module ( const Project& project,
239 const XMLElement& moduleNode,
240 const string& modulePath )
241 : project (project),
242 node (moduleNode),
243 importLibrary (NULL),
244 metadata (NULL),
245 bootSector (NULL),
246 bootstrap (NULL),
247 autoRegister(NULL),
248 linkerScript (NULL),
249 pch (NULL),
250 cplusplus (false),
251 host (HostDefault),
252 output (NULL),
253 install (NULL)
254 {
255 if ( node.name != "module" )
256 throw InvalidOperationException ( __FILE__,
257 __LINE__,
258 "Module created with non-<module> node" );
259
260 xmlbuildFile = FixSeparator ( Path::RelativeFromWorkingDirectory ( moduleNode.xmlFile->filename () ) );
261
262 const XMLAttribute* att = moduleNode.GetAttribute ( "name", true );
263 assert(att);
264 name = att->value;
265
266 enabled = true;
267
268 att = moduleNode.GetAttribute ( "if", false );
269 if ( att != NULL )
270 enabled = GetBooleanValue ( project.ResolveProperties ( att->value ) );
271
272 att = moduleNode.GetAttribute ( "ifnot", false );
273 if ( att != NULL )
274 enabled = !GetBooleanValue ( project.ResolveProperties ( att->value ) );
275
276 if ( !enabled && project.configuration.Verbose )
277 printf("Module '%s' has been disabled.\n", name.c_str () );
278
279 att = moduleNode.GetAttribute ( "type", true );
280 assert(att);
281 type = GetModuleType ( node.location, *att );
282
283 att = moduleNode.GetAttribute ( "extension", false );
284 if ( att != NULL )
285 extension = att->value;
286 else
287 extension = GetDefaultModuleExtension ();
288
289 att = moduleNode.GetAttribute ( "unicode", false );
290 if ( att != NULL )
291 {
292 const char* p = att->value.c_str();
293 if ( !stricmp ( p, "true" ) || !stricmp ( p, "yes" ) )
294 isUnicode = true;
295 else if ( !stricmp ( p, "false" ) || !stricmp ( p, "no" ) )
296 isUnicode = false;
297 else
298 {
299 throw InvalidAttributeValueException (
300 moduleNode.location,
301 "unicode",
302 att->value );
303 }
304 }
305 else
306 isUnicode = false;
307
308 if (isUnicode)
309 {
310 // Always define UNICODE and _UNICODE
311 Define* pDefine = new Define ( project, this, "UNICODE" );
312 non_if_data.defines.push_back ( pDefine );
313
314 pDefine = new Define ( project, this, "_UNICODE" );
315 non_if_data.defines.push_back ( pDefine );
316 }
317
318 att = moduleNode.GetAttribute ( "entrypoint", false );
319 if ( att != NULL )
320 {
321 if ( att->value == "" )
322 {
323 throw InvalidAttributeValueException (
324 moduleNode.location,
325 "entrypoint",
326 att->value );
327 }
328
329 entrypoint = att->value;
330 isDefaultEntryPoint = false;
331 }
332 else
333 {
334 entrypoint = GetDefaultModuleEntrypoint ();
335 isDefaultEntryPoint = true;
336 }
337
338 att = moduleNode.GetAttribute ( "baseaddress", false );
339 if ( att != NULL )
340 baseaddress = att->value;
341 else
342 baseaddress = GetDefaultModuleBaseaddress ();
343
344 att = moduleNode.GetAttribute ( "mangledsymbols", false );
345 if ( att != NULL )
346 {
347 const char* p = att->value.c_str();
348 if ( !stricmp ( p, "true" ) || !stricmp ( p, "yes" ) )
349 mangledSymbols = true;
350 else if ( !stricmp ( p, "false" ) || !stricmp ( p, "no" ) )
351 mangledSymbols = false;
352 else
353 {
354 throw InvalidAttributeValueException (
355 moduleNode.location,
356 "mangledsymbols",
357 att->value );
358 }
359 }
360 else
361 mangledSymbols = false;
362
363 att = moduleNode.GetAttribute ( "underscoresymbols", false );
364 if ( att != NULL )
365 underscoreSymbols = att->value == "true";
366 else
367 underscoreSymbols = false;
368
369 att = moduleNode.GetAttribute ( "host", false );
370 if ( att != NULL )
371 {
372 const char* p = att->value.c_str();
373 if ( !stricmp ( p, "true" ) || !stricmp ( p, "yes" ) )
374 host = HostTrue;
375 else if ( !stricmp ( p, "false" ) || !stricmp ( p, "no" ) )
376 host = HostFalse;
377 else
378 {
379 throw InvalidAttributeValueException (
380 moduleNode.location,
381 "host",
382 att->value );
383 }
384 }
385
386 att = moduleNode.GetAttribute ( "isstartuplib", false );
387 if ( att != NULL )
388 {
389 const char* p = att->value.c_str();
390 if ( !stricmp ( p, "true" ) || !stricmp ( p, "yes" ) )
391 isStartupLib = true;
392 else if ( !stricmp ( p, "false" ) || !stricmp ( p, "no" ) )
393 isStartupLib = false;
394 else
395 {
396 throw InvalidAttributeValueException (
397 moduleNode.location,
398 "host",
399 att->value );
400 }
401 }
402 else
403 isStartupLib = false;
404
405 att = moduleNode.GetAttribute ( "prefix", false );
406 if ( att != NULL )
407 prefix = att->value;
408
409 att = moduleNode.GetAttribute ( "installname", false );
410 if ( att != NULL )
411 {
412 const XMLAttribute* installbase = moduleNode.GetAttribute ( "installbase", false );
413 install = new FileLocation ( InstallDirectory,
414 installbase ? installbase->value : "",
415 att->value,
416 &moduleNode );
417
418 output = new FileLocation ( GetTargetDirectoryTree (),
419 modulePath,
420 att->value,
421 &moduleNode );
422 }
423
424 att = moduleNode.GetAttribute ( "output", false );
425 if ( att != NULL )
426 {
427 if (output != NULL)
428 {
429 printf ( "%s: WARNING: 'installname' overrides 'output' also defined for this module.\n",
430 moduleNode.location.c_str() );
431 }
432 else
433 {
434 output = new FileLocation ( GetTargetDirectoryTree (),
435 modulePath,
436 att->value,
437 &moduleNode );
438 }
439 }
440
441 /* If no one has set the output file for this module set it automatically */
442 if (output == NULL)
443 {
444 output = new FileLocation ( GetTargetDirectoryTree (),
445 modulePath,
446 name + extension,
447 &moduleNode );
448 }
449
450 att = moduleNode.GetAttribute ( "allowwarnings", false );
451 if ( att == NULL )
452 {
453 att = moduleNode.GetAttribute ( "warnings", false );
454 if ( att != NULL )
455 {
456 printf ( "%s: WARNING: 'warnings' attribute of <module> is deprecated, use 'allowwarnings' instead\n",
457 moduleNode.location.c_str() );
458 }
459 }
460 if ( att != NULL )
461 allowWarnings = att->value == "true";
462 else
463 allowWarnings = false;
464
465 att = moduleNode.GetAttribute ( "aliasof", false );
466 if ( type == Alias && att != NULL )
467 aliasedModuleName = att->value;
468 else
469 aliasedModuleName = "";
470
471 if ( type == BootProgram )
472 {
473 att = moduleNode.GetAttribute ( "payload", true );
474 payload = att->value;
475 }
476
477 if ( type == BootProgram || type == ElfExecutable )
478 {
479 att = moduleNode.GetAttribute ( "buildtype", false );
480 if ( att != NULL )
481 {
482 buildtype = att->value;
483 }
484 else
485 {
486 buildtype = "BOOTPROG";
487 }
488 }
489
490 att = moduleNode.GetAttribute ( "description", false );
491 if (att != NULL )
492 {
493 description = project.ResolveProperties(att->value);
494 }
495 else
496 description = "";
497
498 att = moduleNode.GetAttribute ( "lcid", false );
499 if (type == KeyboardLayout && att != NULL )
500 lcid = att->value;
501 else
502 lcid = "";
503
504 att = moduleNode.GetAttribute ( "layoutid", false );
505 if (type == KeyboardLayout && att != NULL )
506 layoutId = att->value;
507 else
508 layoutId = "";
509
510 att = moduleNode.GetAttribute ( "layoutnameresid", false );
511 if (type == KeyboardLayout && att != NULL )
512 layoutNameResId = att->value;
513 else
514 layoutNameResId = "";
515
516 SetImportLibrary ( NULL );
517 }
518
519 Module::~Module ()
520 {
521 size_t i;
522 for ( i = 0; i < invocations.size(); i++ )
523 delete invocations[i];
524 for ( i = 0; i < dependencies.size(); i++ )
525 delete dependencies[i];
526 for ( i = 0; i < compilerFlags.size(); i++ )
527 delete compilerFlags[i];
528 for ( i = 0; i < linkerFlags.size(); i++ )
529 delete linkerFlags[i];
530 for ( i = 0; i < stubbedComponents.size(); i++ )
531 delete stubbedComponents[i];
532 if ( linkerScript )
533 delete linkerScript;
534 if ( pch )
535 delete pch;
536 if ( install )
537 delete install;
538 if ( metadata )
539 delete metadata;
540 if ( bootstrap )
541 delete bootstrap;
542 if ( importLibrary )
543 delete importLibrary;
544 if ( bootSector )
545 delete bootSector;
546 if ( dependency )
547 delete dependency;
548 if ( autoRegister )
549 delete autoRegister;
550 if ( output )
551 delete output;
552 }
553
554 void
555 Module::ProcessXML()
556 {
557 if ( type == Alias )
558 {
559 aliasedModuleName = project.ResolveProperties ( aliasedModuleName );
560 if ( aliasedModuleName == name )
561 {
562 throw XMLInvalidBuildFileException (
563 node.location,
564 "module '%s' cannot link against itself",
565 name.c_str() );
566 }
567 const Module* m = project.LocateModule ( aliasedModuleName );
568 if ( !m && enabled )
569 {
570 throw XMLInvalidBuildFileException (
571 node.location,
572 "module '%s' trying to alias non-existant module '%s'",
573 name.c_str(),
574 aliasedModuleName.c_str() );
575 }
576 }
577
578 size_t i;
579 for ( i = 0; i < node.subElements.size(); i++ )
580 {
581 ParseContext parseContext;
582 ProcessXMLSubElement ( *node.subElements[i], SourceDirectory, output->relative_path, parseContext );
583 }
584 for ( i = 0; i < invocations.size(); i++ )
585 invocations[i]->ProcessXML ();
586 for ( i = 0; i < dependencies.size(); i++ )
587 dependencies[i]->ProcessXML ();
588 for ( i = 0; i < compilerFlags.size(); i++ )
589 compilerFlags[i]->ProcessXML();
590 for ( i = 0; i < linkerFlags.size(); i++ )
591 linkerFlags[i]->ProcessXML();
592 for ( i = 0; i < stubbedComponents.size(); i++ )
593 stubbedComponents[i]->ProcessXML();
594 non_if_data.ProcessXML();
595 if ( linkerScript )
596 linkerScript->ProcessXML();
597 if ( pch )
598 pch->ProcessXML();
599 if ( autoRegister )
600 autoRegister->ProcessXML();
601 }
602
603 void
604 Module::ProcessXMLSubElement ( const XMLElement& e,
605 DirectoryLocation directory,
606 const string& relative_path,
607 ParseContext& parseContext )
608 {
609 If* pOldIf = parseContext.ifData;
610 CompilationUnit* pOldCompilationUnit = parseContext.compilationUnit;
611 bool subs_invalid = false;
612 string subpath ( relative_path );
613 DirectoryLocation subdirectory = SourceDirectory;
614 if ( e.name == "file" && e.value.size () > 0 )
615 {
616 bool first = false;
617 const XMLAttribute* att = e.GetAttribute ( "first", false );
618 if ( att != NULL )
619 {
620 if ( !stricmp ( att->value.c_str(), "true" ) )
621 first = true;
622 else if ( stricmp ( att->value.c_str(), "false" ) )
623 {
624 throw XMLInvalidBuildFileException (
625 e.location,
626 "attribute 'first' of <file> element can only be 'true' or 'false'" );
627 }
628 }
629 string switches = "";
630 att = e.GetAttribute ( "switches", false );
631 if ( att != NULL )
632 switches = att->value;
633 if ( !cplusplus )
634 {
635 // check for c++ file
636 string ext = GetExtension ( e.value );
637 if ( !stricmp ( ext.c_str(), ".cpp" ) )
638 cplusplus = true;
639 else if ( !stricmp ( ext.c_str(), ".cc" ) )
640 cplusplus = true;
641 else if ( !stricmp ( ext.c_str(), ".cxx" ) )
642 cplusplus = true;
643 }
644 File* pFile = new File ( directory,
645 relative_path,
646 e.value,
647 first,
648 switches,
649 false );
650 if ( parseContext.compilationUnit )
651 parseContext.compilationUnit->AddFile ( pFile );
652 else
653 {
654 CompilationUnit* pCompilationUnit = new CompilationUnit ( pFile );
655 if ( parseContext.ifData )
656 parseContext.ifData->data.compilationUnits.push_back ( pCompilationUnit );
657 else
658 {
659 string ext = ToLower ( GetExtension ( e.value ) );
660 if ( ext == ".idl" )
661 {
662 // put .idl files at the start of the module
663 non_if_data.compilationUnits.insert (
664 non_if_data.compilationUnits.begin(),
665 pCompilationUnit );
666 }
667 else if ( ext == ".asm" || ext == ".s" )
668 {
669 // put .asm files at the end of the module
670 non_if_data.compilationUnits.push_back ( pCompilationUnit );
671 non_if_data.asmFiles++;
672 }
673 else
674 {
675 // put other files in the middle
676 non_if_data.compilationUnits.insert (
677 non_if_data.compilationUnits.end() - non_if_data.asmFiles,
678 pCompilationUnit );
679 }
680 }
681 }
682 if ( parseContext.ifData )
683 parseContext.ifData->data.files.push_back ( pFile );
684 else
685 non_if_data.files.push_back ( pFile );
686 subs_invalid = true;
687 }
688 else if ( e.name == "library" && e.value.size () )
689 {
690 Library* pLibrary = new Library ( e, *this, e.value );
691 if ( parseContext.ifData )
692 parseContext.ifData->data.libraries.push_back ( pLibrary );
693 else
694 non_if_data.libraries.push_back ( pLibrary );
695 subs_invalid = true;
696 }
697 else if ( e.name == "directory" )
698 {
699 const XMLAttribute* att = e.GetAttribute ( "name", true );
700 const XMLAttribute* root = e.GetAttribute ( "root", false );
701 assert(att);
702 if ( root )
703 {
704 if ( root->value == "intermediate" )
705 subdirectory = IntermediateDirectory;
706 else if ( root->value == "output" )
707 subdirectory = OutputDirectory;
708 else
709 {
710 throw InvalidAttributeValueException (
711 e.location,
712 "root",
713 root->value );
714 }
715 }
716 subpath = GetSubPath ( this->project, e.location, relative_path, att->value );
717 }
718 else if ( e.name == "include" )
719 {
720 Include* include = new Include ( project, &e, this );
721 if ( parseContext.ifData )
722 parseContext.ifData->data.includes.push_back ( include );
723 else
724 non_if_data.includes.push_back ( include );
725 subs_invalid = true;
726 }
727 else if ( e.name == "define" )
728 {
729 Define* pDefine = new Define ( project, this, e );
730 if ( parseContext.ifData )
731 parseContext.ifData->data.defines.push_back ( pDefine );
732 else
733 non_if_data.defines.push_back ( pDefine );
734 subs_invalid = true;
735 }
736 else if ( e.name == "metadata" )
737 {
738 if ( parseContext.ifData )
739 {
740 throw XMLInvalidBuildFileException (
741 e.location,
742 "<metadata> is not a valid sub-element of <if>" );
743 }
744 metadata = new Metadata ( e, *this );
745 subs_invalid = false;
746 }
747 else if ( e.name == "invoke" )
748 {
749 if ( parseContext.ifData )
750 {
751 throw XMLInvalidBuildFileException (
752 e.location,
753 "<invoke> is not a valid sub-element of <if>" );
754 }
755 invocations.push_back ( new Invoke ( e, *this ) );
756 subs_invalid = false;
757 }
758 else if ( e.name == "dependency" )
759 {
760 if ( parseContext.ifData )
761 {
762 throw XMLInvalidBuildFileException (
763 e.location,
764 "<dependency> is not a valid sub-element of <if>" );
765 }
766 dependencies.push_back ( new Dependency ( e, *this ) );
767 subs_invalid = true;
768 }
769 else if ( e.name == "bootsector" )
770 {
771 if ( parseContext.ifData )
772 {
773 throw XMLInvalidBuildFileException (
774 e.location,
775 "<bootsector> is not a valid sub-element of <if>" );
776 }
777 bootSector = new Bootsector ( e, this );
778 subs_invalid = true;
779 }
780 else if ( e.name == "importlibrary" )
781 {
782 if ( parseContext.ifData )
783 {
784 throw XMLInvalidBuildFileException (
785 e.location,
786 "<importlibrary> is not a valid sub-element of <if>" );
787 }
788 if ( importLibrary )
789 {
790 throw XMLInvalidBuildFileException (
791 e.location,
792 "Only one <importlibrary> is valid per module" );
793 }
794 SetImportLibrary ( new ImportLibrary ( project, e, this ) );
795 subs_invalid = true;
796 }
797 else if ( e.name == "if" )
798 {
799 parseContext.ifData = new If ( e, project, this );
800 if ( pOldIf )
801 pOldIf->data.ifs.push_back ( parseContext.ifData );
802 else
803 non_if_data.ifs.push_back ( parseContext.ifData );
804 subs_invalid = false;
805 }
806 else if ( e.name == "ifnot" )
807 {
808 parseContext.ifData = new If ( e, project, this, true );
809 if ( pOldIf )
810 pOldIf->data.ifs.push_back ( parseContext.ifData );
811 else
812 non_if_data.ifs.push_back ( parseContext.ifData );
813 subs_invalid = false;
814 }
815 else if ( e.name == "compilerflag" )
816 {
817 CompilerFlag* pCompilerFlag = new CompilerFlag ( project, this, e );
818 if ( parseContext.ifData )
819 parseContext.ifData->data.compilerFlags.push_back ( pCompilerFlag );
820 else
821 non_if_data.compilerFlags.push_back ( pCompilerFlag );
822 subs_invalid = true;
823 }
824 else if ( e.name == "linkerflag" )
825 {
826 linkerFlags.push_back ( new LinkerFlag ( project, this, e ) );
827 subs_invalid = true;
828 }
829 else if ( e.name == "linkerscript" )
830 {
831 if ( parseContext.ifData )
832 {
833 throw XMLInvalidBuildFileException (
834 e.location,
835 "<linkerscript> is not a valid sub-element of <if>" );
836 }
837 if ( linkerScript )
838 {
839 throw XMLInvalidBuildFileException (
840 e.location,
841 "Only one <linkerscript> is valid per module" );
842 }
843 size_t pos = e.value.find_last_of ( "/\\" );
844 if ( pos == string::npos )
845 {
846 linkerScript = new LinkerScript (
847 e, *this, new FileLocation ( SourceDirectory, relative_path, e.value, &e ) );
848 }
849 else
850 {
851 string dir = e.value.substr ( 0, pos );
852 string name = e.value.substr ( pos + 1);
853 linkerScript = new LinkerScript (
854 e, *this, new FileLocation ( SourceDirectory, relative_path + sSep + dir, name, &e ) );
855 }
856 subs_invalid = true;
857 }
858 else if ( e.name == "component" )
859 {
860 stubbedComponents.push_back ( new StubbedComponent ( this, e ) );
861 subs_invalid = false;
862 }
863 else if ( e.name == "property" )
864 {
865 throw XMLInvalidBuildFileException (
866 e.location,
867 "<property> is not a valid sub-element of <module>" );
868 }
869 else if ( e.name == "bootstrap" )
870 {
871 bootstrap = new Bootstrap ( project, this, e );
872 subs_invalid = true;
873 }
874 else if ( e.name == "pch" )
875 {
876 if ( parseContext.ifData )
877 {
878 throw XMLInvalidBuildFileException (
879 e.location,
880 "<pch> is not a valid sub-element of <if>" );
881 }
882 if ( pch )
883 {
884 throw XMLInvalidBuildFileException (
885 e.location,
886 "Only one <pch> is valid per module" );
887 }
888 size_t pos = e.value.find_last_of ( "/\\" );
889 if ( pos == string::npos )
890 {
891 pch = new PchFile (
892 e, *this, new FileLocation ( SourceDirectory, relative_path, e.value, &e ) );
893 }
894 else
895 {
896 string dir = e.value.substr ( 0, pos );
897 string name = e.value.substr ( pos + 1);
898 pch = new PchFile (
899 e, *this, new FileLocation ( SourceDirectory, relative_path + sSep + dir, name, &e ) );
900 }
901 subs_invalid = true;
902 }
903 else if ( e.name == "compilationunit" )
904 {
905 if ( project.configuration.CompilationUnitsEnabled )
906 {
907 CompilationUnit* pCompilationUnit = new CompilationUnit ( &project, this, &e );
908 if ( parseContext.ifData )
909 parseContext.ifData->data.compilationUnits.push_back ( pCompilationUnit );
910 else
911 non_if_data.compilationUnits.push_back ( pCompilationUnit );
912 parseContext.compilationUnit = pCompilationUnit;
913 }
914 subs_invalid = false;
915 }
916 else if ( e.name == "autoregister" )
917 {
918 if ( autoRegister != NULL)
919 {
920 throw XMLInvalidBuildFileException (
921 e.location,
922 "there can be only one <%s> element for a module",
923 e.name.c_str() );
924 }
925 autoRegister = new AutoRegister ( project, this, e );
926 subs_invalid = true;
927 }
928 if ( subs_invalid && e.subElements.size() > 0 )
929 {
930 throw XMLInvalidBuildFileException (
931 e.location,
932 "<%s> cannot have sub-elements",
933 e.name.c_str() );
934 }
935 for ( size_t i = 0; i < e.subElements.size (); i++ )
936 ProcessXMLSubElement ( *e.subElements[i], subdirectory, subpath, parseContext );
937 parseContext.ifData = pOldIf;
938 parseContext.compilationUnit = pOldCompilationUnit;
939 }
940
941 ModuleType
942 Module::GetModuleType ( const string& location, const XMLAttribute& attribute )
943 {
944 if ( attribute.value == "buildtool" )
945 return BuildTool;
946 if ( attribute.value == "staticlibrary" )
947 return StaticLibrary;
948 if ( attribute.value == "hoststaticlibrary" )
949 return HostStaticLibrary;
950 if ( attribute.value == "objectlibrary" )
951 return ObjectLibrary;
952 if ( attribute.value == "kernel" )
953 return Kernel;
954 if ( attribute.value == "kernelmodedll" )
955 return KernelModeDLL;
956 if ( attribute.value == "kernelmodedriver" )
957 return KernelModeDriver;
958 if ( attribute.value == "nativedll" )
959 return NativeDLL;
960 if ( attribute.value == "nativecui" )
961 return NativeCUI;
962 if ( attribute.value == "keyboardlayout" )
963 return KeyboardLayout;
964 if ( attribute.value == "win32dll" )
965 return Win32DLL;
966 if ( attribute.value == "win32ocx" )
967 return Win32OCX;
968 if ( attribute.value == "win32cui" )
969 return Win32CUI;
970 if ( attribute.value == "win32gui" )
971 return Win32GUI;
972 if ( attribute.value == "win32scr" )
973 return Win32SCR;
974 if ( attribute.value == "bootloader" )
975 return BootLoader;
976 if ( attribute.value == "bootsector" )
977 return BootSector;
978 if ( attribute.value == "bootprogram" )
979 return BootProgram;
980 if ( attribute.value == "iso" )
981 return Iso;
982 if ( attribute.value == "liveiso" )
983 return LiveIso;
984 if ( attribute.value == "isoregtest" )
985 return IsoRegTest;
986 if ( attribute.value == "liveisoregtest" )
987 return LiveIsoRegTest;
988 if ( attribute.value == "test" )
989 return Test;
990 if ( attribute.value == "rpcserver" )
991 return RpcServer;
992 if ( attribute.value == "rpcclient" )
993 return RpcClient;
994 if ( attribute.value == "rpcproxy" )
995 return RpcProxy;
996 if ( attribute.value == "alias" )
997 return Alias;
998 if ( attribute.value == "idlheader" )
999 return IdlHeader;
1000 if ( attribute.value == "embeddedtypelib" )
1001 return EmbeddedTypeLib;
1002 if ( attribute.value == "elfexecutable" )
1003 return ElfExecutable;
1004 if ( attribute.value == "cabinet" )
1005 return Cabinet;
1006 if ( attribute.value == "messageheader" )
1007 return MessageHeader;
1008 throw InvalidAttributeValueException ( location,
1009 attribute.name,
1010 attribute.value );
1011 }
1012
1013 DirectoryLocation
1014 Module::GetTargetDirectoryTree () const
1015 {
1016 switch ( type )
1017 {
1018 case Kernel:
1019 case KernelModeDLL:
1020 case KeyboardLayout:
1021 case NativeDLL:
1022 case Win32DLL:
1023 case Win32OCX:
1024 case KernelModeDriver:
1025 case NativeCUI:
1026 case Win32CUI:
1027 case Test:
1028 case Win32SCR:
1029 case Win32GUI:
1030 case BuildTool:
1031 case BootLoader:
1032 case BootSector:
1033 case BootProgram:
1034 case Iso:
1035 case LiveIso:
1036 case IsoRegTest:
1037 case LiveIsoRegTest:
1038 case ElfExecutable:
1039 case Cabinet:
1040 return OutputDirectory;
1041 case EmbeddedTypeLib:
1042 case StaticLibrary:
1043 case HostStaticLibrary:
1044 case ObjectLibrary:
1045 case RpcServer:
1046 case RpcClient:
1047 case RpcProxy:
1048 case Alias:
1049 case IdlHeader:
1050 case MessageHeader:
1051 return IntermediateDirectory;
1052 case TypeDontCare:
1053 break;
1054 }
1055 throw InvalidOperationException ( __FILE__,
1056 __LINE__,
1057 "Invalid module type %d.",
1058 type );
1059 }
1060
1061 string
1062 Module::GetDefaultModuleExtension () const
1063 {
1064 switch (type)
1065 {
1066 case BuildTool:
1067 return ExePostfix;
1068 case BootProgram:
1069 case StaticLibrary:
1070 case HostStaticLibrary:
1071 return ".a";
1072 case ObjectLibrary:
1073 return ".o";
1074 case Kernel:
1075 case NativeCUI:
1076 case Win32CUI:
1077 case Win32GUI:
1078 return ".exe";
1079 case Win32SCR:
1080 return ".scr";
1081
1082 case KernelModeDLL:
1083 case NativeDLL:
1084 case KeyboardLayout:
1085 case Win32DLL:
1086 return ".dll";
1087 case Win32OCX:
1088 return ".ocx";
1089 case KernelModeDriver:
1090 case BootLoader:
1091 return ".sys";
1092 case Cabinet:
1093 return ".cab";
1094 case BootSector:
1095 return ".o";
1096 case Iso:
1097 case LiveIso:
1098 case IsoRegTest:
1099 case LiveIsoRegTest:
1100 return ".iso";
1101 case Test:
1102 return ".exe";
1103 case RpcServer:
1104 case RpcClient:
1105 case RpcProxy:
1106 return ".o";
1107 case Alias:
1108 case ElfExecutable:
1109 case IdlHeader:
1110 case MessageHeader:
1111 return "";
1112 case EmbeddedTypeLib:
1113 return ".tlb";
1114 case TypeDontCare:
1115 break;
1116 }
1117 throw InvalidOperationException ( __FILE__,
1118 __LINE__ );
1119 }
1120
1121 string
1122 Module::GetDefaultModuleEntrypoint () const
1123 {
1124 switch ( type )
1125 {
1126 case Kernel:
1127 return "KiSystemStartup";
1128 case KeyboardLayout:
1129 case KernelModeDLL:
1130 case KernelModeDriver:
1131 if (Environment::GetArch() == "arm") return "DriverEntry";
1132 return "DriverEntry@8";
1133 case NativeDLL:
1134 if (Environment::GetArch() == "arm") return "DllMainCRTStartup";
1135 return "DllMainCRTStartup@12";
1136 case NativeCUI:
1137 if (Environment::GetArch() == "arm") return "NtProcessStartup";
1138 return "NtProcessStartup@4";
1139 case Win32DLL:
1140 case Win32OCX:
1141 if (Environment::GetArch() == "arm") return "DllMain";
1142 return "DllMain@12";
1143 case Win32CUI:
1144 case Test:
1145 if ( isUnicode )
1146 return "wmainCRTStartup";
1147 else
1148 return "mainCRTStartup";
1149 case Win32SCR:
1150 case Win32GUI:
1151 if ( isUnicode )
1152 return "wWinMainCRTStartup";
1153 else
1154 return "WinMainCRTStartup";
1155 case BuildTool:
1156 case StaticLibrary:
1157 case HostStaticLibrary:
1158 case ObjectLibrary:
1159 case BootLoader:
1160 case BootSector:
1161 case Iso:
1162 case LiveIso:
1163 case IsoRegTest:
1164 case LiveIsoRegTest:
1165 case RpcServer:
1166 case RpcClient:
1167 case RpcProxy:
1168 case Alias:
1169 case BootProgram:
1170 case IdlHeader:
1171 case MessageHeader:
1172 case ElfExecutable:
1173 case EmbeddedTypeLib:
1174 case Cabinet:
1175 return "";
1176 case TypeDontCare:
1177 break;
1178 }
1179 throw InvalidOperationException ( __FILE__,
1180 __LINE__ );
1181 }
1182
1183 string
1184 Module::GetDefaultModuleBaseaddress () const
1185 {
1186 switch ( type )
1187 {
1188 case Kernel:
1189 return "0x80800000";
1190 case Win32DLL:
1191 case Win32OCX:
1192 return "0x10000000";
1193 case NativeDLL:
1194 case NativeCUI:
1195 case Win32CUI:
1196 case Test:
1197 return "0x00400000";
1198 case Win32SCR:
1199 case Win32GUI:
1200 return "0x00400000";
1201 case KeyboardLayout:
1202 case KernelModeDLL:
1203 case KernelModeDriver:
1204 return "0x00010000";
1205 case ElfExecutable:
1206 return "0xe00000";
1207 case BuildTool:
1208 case StaticLibrary:
1209 case HostStaticLibrary:
1210 case ObjectLibrary:
1211 case BootLoader:
1212 case BootSector:
1213 case Iso:
1214 case LiveIso:
1215 case IsoRegTest:
1216 case LiveIsoRegTest:
1217 case RpcServer:
1218 case RpcClient:
1219 case RpcProxy:
1220 case Alias:
1221 case BootProgram:
1222 case IdlHeader:
1223 case MessageHeader:
1224 case EmbeddedTypeLib:
1225 case Cabinet:
1226 return "";
1227 case TypeDontCare:
1228 break;
1229 }
1230 throw InvalidOperationException ( __FILE__,
1231 __LINE__ );
1232 }
1233
1234 bool
1235 Module::HasImportLibrary () const
1236 {
1237 return importLibrary != NULL && type != StaticLibrary && type != HostStaticLibrary;
1238 }
1239
1240 bool
1241 Module::IsDLL () const
1242 {
1243 switch ( type )
1244 {
1245 case Kernel:
1246 case KernelModeDLL:
1247 case NativeDLL:
1248 case KeyboardLayout:
1249 case Win32DLL:
1250 case Win32OCX:
1251 case KernelModeDriver:
1252 return true;
1253 case NativeCUI:
1254 case Win32CUI:
1255 case Test:
1256 case Win32SCR:
1257 case Win32GUI:
1258 case BuildTool:
1259 case StaticLibrary:
1260 case HostStaticLibrary:
1261 case ObjectLibrary:
1262 case BootLoader:
1263 case BootSector:
1264 case BootProgram:
1265 case Iso:
1266 case LiveIso:
1267 case IsoRegTest:
1268 case LiveIsoRegTest:
1269 case RpcServer:
1270 case RpcClient:
1271 case RpcProxy:
1272 case Alias:
1273 case IdlHeader:
1274 case MessageHeader:
1275 case EmbeddedTypeLib:
1276 case ElfExecutable:
1277 case Cabinet:
1278 return false;
1279 case TypeDontCare:
1280 break;
1281 }
1282 throw InvalidOperationException ( __FILE__,
1283 __LINE__ );
1284 }
1285
1286 string
1287 Module::GetPathWithPrefix ( const string& prefix ) const
1288 {
1289 return output->relative_path + cSep + prefix + output->name;
1290 }
1291
1292 string
1293 Module::GetPathToBaseDir () const
1294 {
1295 string temp_path = output->relative_path;
1296 string result = "..\\";
1297 while(temp_path.find ('\\') != string::npos)
1298 {
1299 temp_path.erase (0, temp_path.find('\\')+1);
1300 result += "..\\";
1301 }
1302 return result;
1303 }
1304
1305 string
1306 Module::GetInvocationTarget ( const int index ) const
1307 {
1308 return ssprintf ( "%s_invoke_%d",
1309 name.c_str (),
1310 index );
1311 }
1312
1313 string
1314 Module::GetEntryPoint(bool leadingUnderscore) const
1315 {
1316 string result = "";
1317 if (entrypoint == "0" || entrypoint == "0x0")
1318 return "0";
1319 if (leadingUnderscore)
1320 result = "_";
1321
1322 result += entrypoint;
1323 return result;
1324 }
1325
1326 bool
1327 Module::HasFileWithExtension (
1328 const IfableData& data,
1329 const std::string& extension ) const
1330 {
1331 size_t i;
1332 for ( i = 0; i < data.compilationUnits.size (); i++ )
1333 {
1334 CompilationUnit* compilationUnit = data.compilationUnits[i];
1335 if ( compilationUnit->HasFileWithExtension ( extension ) )
1336 return true;
1337 }
1338 for ( i = 0; i < data.ifs.size (); i++ )
1339 {
1340 if ( HasFileWithExtension ( data.ifs[i]->data, extension ) )
1341 return true;
1342 }
1343 return false;
1344 }
1345
1346 void
1347 Module::InvokeModule () const
1348 {
1349 for ( size_t i = 0; i < invocations.size (); i++ )
1350 {
1351 Invoke& invoke = *invocations[i];
1352 string command = FixSeparatorForSystemCommand(invoke.invokeModule->output->relative_path + "/" + invoke.invokeModule->output->name ) + " " + invoke.GetParameters ();
1353 printf ( "Executing '%s'\n\n", command.c_str () );
1354 int exitcode = system ( command.c_str () );
1355 if ( exitcode != 0 )
1356 throw InvocationFailedException ( command,
1357 exitcode );
1358 }
1359 }
1360
1361
1362 void
1363 Module::SetImportLibrary ( ImportLibrary* importLibrary )
1364 {
1365 this->importLibrary = importLibrary;
1366 dependency = new FileLocation ( HasImportLibrary () ? IntermediateDirectory : output->directory,
1367 output->relative_path,
1368 HasImportLibrary () ? "lib" + name + ".a" : output->name );
1369 }
1370
1371
1372 File::File ( DirectoryLocation directory,
1373 const string& relative_path,
1374 const string& name,
1375 bool _first,
1376 const string& _switches,
1377 bool _isPreCompiledHeader )
1378 : file ( directory, relative_path, name ),
1379 first(_first),
1380 switches(_switches),
1381 isPreCompiledHeader(_isPreCompiledHeader)
1382 {
1383 }
1384
1385
1386 void
1387 File::ProcessXML()
1388 {
1389 }
1390
1391
1392 std::string File::GetFullPath () const
1393 {
1394 string directory ( "" );
1395 switch ( file.directory )
1396 {
1397 case SourceDirectory:
1398 break;
1399 case IntermediateDirectory:
1400 directory = Environment::GetIntermediatePath () + sSep;
1401 break;
1402 default:
1403 throw InvalidOperationException ( __FILE__,
1404 __LINE__,
1405 "Invalid directory %d.",
1406 file.directory );
1407 }
1408
1409 if ( file.relative_path.length () > 0 )
1410 directory += file.relative_path + sSep;
1411
1412
1413 return directory + file.name;
1414 }
1415
1416
1417 Library::Library ( const XMLElement& _node,
1418 const Module& _module,
1419 const string& _name )
1420 : node(&_node),
1421 module(_module),
1422 name(_name),
1423 importedModule(_module.project.LocateModule(_name))
1424 {
1425 if ( module.name == name )
1426 {
1427 throw XMLInvalidBuildFileException (
1428 node->location,
1429 "module '%s' cannot link against itself",
1430 name.c_str() );
1431 }
1432 if ( !importedModule )
1433 {
1434 throw XMLInvalidBuildFileException (
1435 node->location,
1436 "module '%s' trying to import non-existant module '%s'",
1437 module.name.c_str(),
1438 name.c_str() );
1439 }
1440 }
1441
1442 Library::Library ( const Module& _module,
1443 const string& _name )
1444 : node(NULL),
1445 module(_module),
1446 name(_name),
1447 importedModule(_module.project.LocateModule(_name))
1448 {
1449 }
1450
1451 void
1452 Library::ProcessXML()
1453 {
1454 if ( node && !module.project.LocateModule ( name ) )
1455 {
1456 throw XMLInvalidBuildFileException (
1457 node->location,
1458 "module '%s' is trying to link against non-existant module '%s'",
1459 module.name.c_str(),
1460 name.c_str() );
1461 }
1462 }
1463
1464
1465 Invoke::Invoke ( const XMLElement& _node,
1466 const Module& _module )
1467 : node (_node),
1468 module (_module)
1469 {
1470 }
1471
1472 void
1473 Invoke::ProcessXML()
1474 {
1475 const XMLAttribute* att = node.GetAttribute ( "module", false );
1476 if (att == NULL)
1477 invokeModule = &module;
1478 else
1479 {
1480 invokeModule = module.project.LocateModule ( att->value );
1481 if ( invokeModule == NULL )
1482 {
1483 throw XMLInvalidBuildFileException (
1484 node.location,
1485 "module '%s' is trying to invoke non-existant module '%s'",
1486 module.name.c_str(),
1487 att->value.c_str() );
1488 }
1489 }
1490
1491 for ( size_t i = 0; i < node.subElements.size (); i++ )
1492 ProcessXMLSubElement ( *node.subElements[i] );
1493 }
1494
1495 void
1496 Invoke::ProcessXMLSubElement ( const XMLElement& e )
1497 {
1498 bool subs_invalid = false;
1499 if ( e.name == "input" )
1500 {
1501 for ( size_t i = 0; i < e.subElements.size (); i++ )
1502 ProcessXMLSubElementInput ( *e.subElements[i] );
1503 }
1504 else if ( e.name == "output" )
1505 {
1506 for ( size_t i = 0; i < e.subElements.size (); i++ )
1507 ProcessXMLSubElementOutput ( *e.subElements[i] );
1508 }
1509 if ( subs_invalid && e.subElements.size() > 0 )
1510 {
1511 throw XMLInvalidBuildFileException (
1512 e.location,
1513 "<%s> cannot have sub-elements",
1514 e.name.c_str() );
1515 }
1516 }
1517
1518 void
1519 Invoke::ProcessXMLSubElementInput ( const XMLElement& e )
1520 {
1521 bool subs_invalid = false;
1522 if ( e.name == "inputfile" && e.value.size () > 0 )
1523 {
1524 input.push_back ( new InvokeFile (
1525 e, FixSeparator ( module.output->relative_path + cSep + e.value ) ) );
1526 subs_invalid = true;
1527 }
1528 if ( subs_invalid && e.subElements.size() > 0 )
1529 {
1530 throw XMLInvalidBuildFileException (
1531 e.location,
1532 "<%s> cannot have sub-elements",
1533 e.name.c_str() );
1534 }
1535 }
1536
1537 void
1538 Invoke::ProcessXMLSubElementOutput ( const XMLElement& e )
1539 {
1540 bool subs_invalid = false;
1541 if ( e.name == "outputfile" && e.value.size () > 0 )
1542 {
1543 output.push_back ( new InvokeFile (
1544 e, FixSeparator ( module.output->relative_path + cSep + e.value ) ) );
1545 subs_invalid = true;
1546 }
1547 if ( subs_invalid && e.subElements.size() > 0 )
1548 {
1549 throw XMLInvalidBuildFileException (
1550 e.location,
1551 "<%s> cannot have sub-elements",
1552 e.name.c_str() );
1553 }
1554 }
1555
1556 void
1557 Invoke::GetTargets ( string_list& targets ) const
1558 {
1559 for ( size_t i = 0; i < output.size (); i++ )
1560 {
1561 InvokeFile& file = *output[i];
1562 targets.push_back ( NormalizeFilename ( file.name ) );
1563 }
1564 }
1565
1566 string
1567 Invoke::GetParameters () const
1568 {
1569 string parameters ( "" );
1570 size_t i;
1571 for ( i = 0; i < output.size (); i++ )
1572 {
1573 if ( parameters.length () > 0)
1574 parameters += " ";
1575 InvokeFile& invokeFile = *output[i];
1576 if ( invokeFile.switches.length () > 0 )
1577 {
1578 parameters += invokeFile.switches + " ";
1579 }
1580 parameters += invokeFile.name;
1581 }
1582
1583 for ( i = 0; i < input.size (); i++ )
1584 {
1585 if ( parameters.length () > 0 )
1586 parameters += " ";
1587 InvokeFile& invokeFile = *input[i];
1588 if ( invokeFile.switches.length () > 0 )
1589 {
1590 parameters += invokeFile.switches;
1591 parameters += " ";
1592 }
1593 parameters += invokeFile.name ;
1594 }
1595
1596 return parameters;
1597 }
1598
1599
1600 InvokeFile::InvokeFile ( const XMLElement& _node,
1601 const string& _name )
1602 : node (_node),
1603 name (_name)
1604 {
1605 const XMLAttribute* att = _node.GetAttribute ( "switches", false );
1606 if (att != NULL)
1607 switches = att->value;
1608 else
1609 switches = "";
1610 }
1611
1612 void
1613 InvokeFile::ProcessXML()
1614 {
1615 }
1616
1617
1618 Dependency::Dependency ( const XMLElement& _node,
1619 const Module& _module )
1620 : node (_node),
1621 module (_module),
1622 dependencyModule (NULL)
1623 {
1624 }
1625
1626 void
1627 Dependency::ProcessXML()
1628 {
1629 dependencyModule = module.project.LocateModule ( node.value );
1630 if ( dependencyModule == NULL )
1631 {
1632 throw XMLInvalidBuildFileException (
1633 node.location,
1634 "module '%s' depend on non-existant module '%s'",
1635 module.name.c_str(),
1636 node.value.c_str() );
1637 }
1638 }
1639
1640 Bootsector::Bootsector ( const XMLElement& _node,
1641 const Module* _module )
1642 : node (_node),
1643 module (_module),
1644 bootSectorModule (NULL)
1645 {
1646 if ( !IsSupportedModuleType ( module->type ) )
1647 {
1648 throw XMLInvalidBuildFileException (
1649 node.location,
1650 "<bootsector> is not applicable for this module type." );
1651 }
1652
1653 bootSectorModule = module->project.LocateModule ( node.value );
1654 if ( bootSectorModule == NULL )
1655 {
1656 throw XMLInvalidBuildFileException (
1657 node.location,
1658 "module '%s' depend on non-existant module '%s'",
1659 module->name.c_str(),
1660 node.value.c_str() );
1661 }
1662
1663 if (bootSectorModule->type != BootSector)
1664 {
1665 throw XMLInvalidBuildFileException (
1666 node.location,
1667 "module '%s' is referencing non BootSector module '%s'",
1668 module->name.c_str(),
1669 node.value.c_str() );
1670 }
1671 }
1672
1673 void
1674 Bootsector::ProcessXML()
1675 {
1676 }
1677
1678 bool
1679 Bootsector::IsSupportedModuleType ( ModuleType type )
1680 {
1681 if ( type == Iso ||
1682 type == LiveIso ||
1683 type == IsoRegTest ||
1684 type == LiveIsoRegTest )
1685 {
1686 return true;
1687 }
1688
1689 return false;
1690 }
1691
1692 Metadata::Metadata ( const XMLElement& _node,
1693 const Module& _module )
1694 : node (_node),
1695 module (_module)
1696 {
1697 /* The module name */
1698 const XMLAttribute* att = _node.GetAttribute ( "name", false );
1699 if (att != NULL)
1700 name = att->value;
1701 else
1702 name = module.name;
1703
1704 /* The module description */
1705 att = _node.GetAttribute ( "description", false );
1706 if (att != NULL)
1707 description = att->value;
1708 else
1709 description = "";
1710
1711 /* The module version */
1712 att = _node.GetAttribute ( "version", false );
1713 if (att != NULL)
1714 version = att->value;
1715 else
1716 version = "";
1717
1718 /* The module copyright */
1719 att = _node.GetAttribute ( "copyright", false );
1720 if (att != NULL)
1721 copyright = att->value;
1722 else
1723 copyright = "";
1724
1725 att = _node.GetAttribute ( "url", false );
1726 if (att != NULL)
1727 url = att->value;
1728 else
1729 url = "";
1730
1731 /* When was this module updated */
1732 att = _node.GetAttribute ( "date", false );
1733 if (att != NULL)
1734 date = att->value;
1735 else
1736 date = "?";
1737
1738 /* When was this module updated */
1739 att = _node.GetAttribute ( "owner", false );
1740 if (att != NULL)
1741 owner = att->value;
1742 else
1743 owner = "ReactOS";
1744 }
1745
1746
1747 ImportLibrary::~ImportLibrary ()
1748 {
1749 delete source;
1750 }
1751
1752
1753 ImportLibrary::ImportLibrary ( const Project& project,
1754 const XMLElement& node,
1755 const Module* module )
1756 : XmlNode ( project, node ),
1757 module (module)
1758 {
1759 DirectoryLocation directory = SourceDirectory;
1760 const Module* base = module;
1761 const XMLAttribute* dllname = node.GetAttribute ( "dllname", false );
1762 const XMLAttribute* definition = node.GetAttribute ( "definition", true );
1763 assert ( definition );
1764
1765 string relative_path;
1766 const XMLAttribute* att = node.GetAttribute ( "base", false );
1767 if ( att )
1768 {
1769 base = project.LocateModule ( att->value );
1770 if ( !base )
1771 throw XMLInvalidBuildFileException (
1772 node.location,
1773 "<importlibrary> attribute 'base' references non-existant module '%s'",
1774 att->value.c_str() );
1775
1776 }
1777
1778 if ( base )
1779 {
1780 relative_path = base->output->relative_path;
1781 if ( node.value.length () > 0 && node.value != "." )
1782 relative_path += sSep + node.value;
1783 }
1784 else
1785 relative_path = node.value;
1786
1787 att = node.GetAttribute ( "root", false );
1788 if ( att )
1789 {
1790 if ( att->value == "intermediate" )
1791 directory = IntermediateDirectory;
1792 else
1793 throw InvalidAttributeValueException ( node.location,
1794 "root",
1795 att->value );
1796 }
1797 else
1798 {
1799 size_t index = definition->value.rfind ( ".spec.def" );
1800 if ( index != string::npos )
1801 directory = IntermediateDirectory;
1802 }
1803
1804 if ( dllname )
1805 this->dllname = dllname->value;
1806 else if ( module->type == StaticLibrary || module->type == HostStaticLibrary )
1807 throw XMLInvalidBuildFileException (
1808 node.location,
1809 "<importlibrary> dllname attribute required." );
1810
1811 size_t index = definition->value.find_last_of ( "/\\" );
1812 if ( index == string::npos )
1813 {
1814 source = new FileLocation ( directory,
1815 base->output->relative_path,
1816 definition->value,
1817 &node );
1818 }
1819 else
1820 {
1821 string dir = definition->value.substr ( 0, index );
1822 string name = definition->value.substr ( index + 1);
1823 source = new FileLocation ( directory,
1824 NormalizeFilename ( base->output->relative_path + sSep + dir ),
1825 name,
1826 &node );
1827 }
1828 }
1829
1830
1831 If::If ( const XMLElement& node_,
1832 const Project& project_,
1833 const Module* module_,
1834 const bool negated_ )
1835 : node(node_), project(project_), module(module_), negated(negated_)
1836 {
1837 const XMLAttribute* att;
1838
1839 att = node.GetAttribute ( "property", true );
1840 assert(att);
1841 property = att->value;
1842
1843 att = node.GetAttribute ( "value", true );
1844 assert(att);
1845 value = att->value;
1846 }
1847
1848 If::~If ()
1849 {
1850 }
1851
1852 void
1853 If::ProcessXML()
1854 {
1855
1856 }
1857
1858
1859 Property::Property ( const XMLElement& node_,
1860 const Project& project_,
1861 const Module* module_ )
1862 : project(project_), module(module_)
1863 {
1864 const XMLAttribute* att;
1865
1866 att = node_.GetAttribute ( "name", true );
1867 assert(att);
1868 name = project.ResolveProperties ( att->value );
1869
1870 att = node_.GetAttribute ( "value", true );
1871 assert(att);
1872 value = att->value;
1873
1874 att = node_.GetAttribute ( "internal", false );
1875 if ( att != NULL )
1876 {
1877 const char* p = att->value.c_str();
1878 if ( !stricmp ( p, "true" ) || !stricmp ( p, "yes" ) )
1879 isInternal = true;
1880 else if ( !stricmp ( p, "false" ) || !stricmp ( p, "no" ) )
1881 isInternal = false;
1882 else
1883 {
1884 throw InvalidAttributeValueException (
1885 node_.location,
1886 "internal",
1887 att->value );
1888 }
1889 }
1890 else
1891 isInternal = false;
1892 }
1893
1894 Property::Property ( const Project& project_,
1895 const Module* module_,
1896 const std::string& name_,
1897 const std::string& value_ )
1898 : project(project_), module(module_), name(name_), value(value_)
1899 {
1900 }
1901
1902 void
1903 Property::ProcessXML()
1904 {
1905 }
1906
1907
1908 PchFile::PchFile (
1909 const XMLElement& node_,
1910 const Module& module_,
1911 const FileLocation *file_ )
1912 : node(node_), module(module_), file(file_)
1913 {
1914 }
1915
1916 PchFile::~PchFile()
1917 {
1918 delete file;
1919 }
1920
1921 void
1922 PchFile::ProcessXML()
1923 {
1924 }