Fix bootcd build, hope this fix is not too hackish...
[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 bootstrap (NULL),
246 autoRegister(NULL),
247 linkerScript (NULL),
248 pch (NULL),
249 cplusplus (false),
250 host (HostDefault)
251 {
252 if ( node.name != "module" )
253 throw InvalidOperationException ( __FILE__,
254 __LINE__,
255 "Module created with non-<module> node" );
256
257 xmlbuildFile = Path::RelativeFromWorkingDirectory ( moduleNode.xmlFile->filename () );
258
259 const XMLAttribute* att = moduleNode.GetAttribute ( "name", true );
260 assert(att);
261 name = att->value;
262
263 enabled = true;
264
265 att = moduleNode.GetAttribute ( "if", false );
266 if ( att != NULL )
267 enabled = GetBooleanValue ( project.ResolveProperties ( att->value ) );
268
269 att = moduleNode.GetAttribute ( "ifnot", false );
270 if ( att != NULL )
271 enabled = !GetBooleanValue ( project.ResolveProperties ( att->value ) );
272
273 if ( !enabled && project.configuration.Verbose )
274 printf("Module '%s' has been disabled.\n", name.c_str () );
275
276 att = moduleNode.GetAttribute ( "type", true );
277 assert(att);
278 type = GetModuleType ( node.location, *att );
279
280 att = moduleNode.GetAttribute ( "extension", false );
281 if ( att != NULL )
282 extension = att->value;
283 else
284 extension = GetDefaultModuleExtension ();
285
286 output = new FileLocation ( GetTargetDirectoryTree (),
287 modulePath,
288 name + extension,
289 &moduleNode );
290
291 att = moduleNode.GetAttribute ( "unicode", false );
292 if ( att != NULL )
293 {
294 const char* p = att->value.c_str();
295 if ( !stricmp ( p, "true" ) || !stricmp ( p, "yes" ) )
296 isUnicode = true;
297 else if ( !stricmp ( p, "false" ) || !stricmp ( p, "no" ) )
298 isUnicode = false;
299 else
300 {
301 throw InvalidAttributeValueException (
302 moduleNode.location,
303 "unicode",
304 att->value );
305 }
306 }
307 else
308 isUnicode = false;
309
310 if (isUnicode)
311 {
312 // Always define UNICODE and _UNICODE
313 Define* pDefine = new Define ( project, this, "UNICODE" );
314 non_if_data.defines.push_back ( pDefine );
315
316 pDefine = new Define ( project, this, "_UNICODE" );
317 non_if_data.defines.push_back ( pDefine );
318 }
319
320 att = moduleNode.GetAttribute ( "entrypoint", false );
321 if ( att != NULL )
322 {
323 if ( att->value == "" )
324 {
325 throw InvalidAttributeValueException (
326 moduleNode.location,
327 "entrypoint",
328 att->value );
329 }
330
331 entrypoint = att->value;
332 isDefaultEntryPoint = false;
333 }
334 else
335 {
336 entrypoint = GetDefaultModuleEntrypoint ();
337 isDefaultEntryPoint = true;
338 }
339
340 att = moduleNode.GetAttribute ( "baseaddress", false );
341 if ( att != NULL )
342 baseaddress = att->value;
343 else
344 baseaddress = GetDefaultModuleBaseaddress ();
345
346 att = moduleNode.GetAttribute ( "mangledsymbols", false );
347 if ( att != NULL )
348 {
349 const char* p = att->value.c_str();
350 if ( !stricmp ( p, "true" ) || !stricmp ( p, "yes" ) )
351 mangledSymbols = true;
352 else if ( !stricmp ( p, "false" ) || !stricmp ( p, "no" ) )
353 mangledSymbols = false;
354 else
355 {
356 throw InvalidAttributeValueException (
357 moduleNode.location,
358 "mangledsymbols",
359 att->value );
360 }
361 }
362 else
363 mangledSymbols = false;
364
365 att = moduleNode.GetAttribute ( "underscoresymbols", false );
366 if ( att != NULL )
367 underscoreSymbols = att->value == "true";
368 else
369 underscoreSymbols = false;
370
371 att = moduleNode.GetAttribute ( "host", false );
372 if ( att != NULL )
373 {
374 const char* p = att->value.c_str();
375 if ( !stricmp ( p, "true" ) || !stricmp ( p, "yes" ) )
376 host = HostTrue;
377 else if ( !stricmp ( p, "false" ) || !stricmp ( p, "no" ) )
378 host = HostFalse;
379 else
380 {
381 throw InvalidAttributeValueException (
382 moduleNode.location,
383 "host",
384 att->value );
385 }
386 }
387
388 att = moduleNode.GetAttribute ( "isstartuplib", false );
389 if ( att != NULL )
390 {
391 const char* p = att->value.c_str();
392 if ( !stricmp ( p, "true" ) || !stricmp ( p, "yes" ) )
393 isStartupLib = true;
394 else if ( !stricmp ( p, "false" ) || !stricmp ( p, "no" ) )
395 isStartupLib = false;
396 else
397 {
398 throw InvalidAttributeValueException (
399 moduleNode.location,
400 "host",
401 att->value );
402 }
403 }
404 else
405 isStartupLib = false;
406
407 att = moduleNode.GetAttribute ( "prefix", false );
408 if ( att != NULL )
409 prefix = att->value;
410
411 att = moduleNode.GetAttribute ( "installname", false );
412 if ( att != NULL )
413 {
414 const XMLAttribute* installbase = moduleNode.GetAttribute ( "installbase", false );
415 install = new FileLocation ( InstallDirectory,
416 installbase ? installbase->value : "",
417 att->value,
418 &moduleNode );
419 }
420 else
421 install = NULL;
422
423 att = moduleNode.GetAttribute ( "allowwarnings", false );
424 if ( att == NULL )
425 {
426 att = moduleNode.GetAttribute ( "warnings", false );
427 if ( att != NULL )
428 {
429 printf ( "%s: WARNING: 'warnings' attribute of <module> is deprecated, use 'allowwarnings' instead\n",
430 moduleNode.location.c_str() );
431 }
432 }
433 if ( att != NULL )
434 allowWarnings = att->value == "true";
435 else
436 allowWarnings = false;
437
438 att = moduleNode.GetAttribute ( "aliasof", false );
439 if ( type == Alias && att != NULL )
440 aliasedModuleName = att->value;
441 else
442 aliasedModuleName = "";
443
444 if ( type == BootProgram )
445 {
446 att = moduleNode.GetAttribute ( "payload", true );
447 payload = att->value;
448 }
449
450 if ( type == BootProgram || type == ElfExecutable )
451 {
452 att = moduleNode.GetAttribute ( "buildtype", false );
453 if ( att != NULL )
454 {
455 buildtype = att->value;
456 }
457 else
458 {
459 buildtype = "BOOTPROG";
460 }
461 }
462
463 SetImportLibrary ( NULL );
464 }
465
466 Module::~Module ()
467 {
468 size_t i;
469 for ( i = 0; i < invocations.size(); i++ )
470 delete invocations[i];
471 for ( i = 0; i < dependencies.size(); i++ )
472 delete dependencies[i];
473 for ( i = 0; i < compilerFlags.size(); i++ )
474 delete compilerFlags[i];
475 for ( i = 0; i < linkerFlags.size(); i++ )
476 delete linkerFlags[i];
477 for ( i = 0; i < stubbedComponents.size(); i++ )
478 delete stubbedComponents[i];
479 if ( linkerScript )
480 delete linkerScript;
481 if ( pch )
482 delete pch;
483 }
484
485 void
486 Module::ProcessXML()
487 {
488 if ( type == Alias )
489 {
490 aliasedModuleName = project.ResolveProperties ( aliasedModuleName );
491 if ( aliasedModuleName == name )
492 {
493 throw XMLInvalidBuildFileException (
494 node.location,
495 "module '%s' cannot link against itself",
496 name.c_str() );
497 }
498 const Module* m = project.LocateModule ( aliasedModuleName );
499 if ( !m && enabled )
500 {
501 throw XMLInvalidBuildFileException (
502 node.location,
503 "module '%s' trying to alias non-existant module '%s'",
504 name.c_str(),
505 aliasedModuleName.c_str() );
506 }
507 }
508
509 size_t i;
510 for ( i = 0; i < node.subElements.size(); i++ )
511 {
512 ParseContext parseContext;
513 ProcessXMLSubElement ( *node.subElements[i], SourceDirectory, output->relative_path, parseContext );
514 }
515 for ( i = 0; i < invocations.size(); i++ )
516 invocations[i]->ProcessXML ();
517 for ( i = 0; i < dependencies.size(); i++ )
518 dependencies[i]->ProcessXML ();
519 for ( i = 0; i < compilerFlags.size(); i++ )
520 compilerFlags[i]->ProcessXML();
521 for ( i = 0; i < linkerFlags.size(); i++ )
522 linkerFlags[i]->ProcessXML();
523 for ( i = 0; i < stubbedComponents.size(); i++ )
524 stubbedComponents[i]->ProcessXML();
525 non_if_data.ProcessXML();
526 if ( linkerScript )
527 linkerScript->ProcessXML();
528 if ( pch )
529 pch->ProcessXML();
530 if ( autoRegister )
531 autoRegister->ProcessXML();
532 }
533
534 void
535 Module::ProcessXMLSubElement ( const XMLElement& e,
536 DirectoryLocation directory,
537 const string& relative_path,
538 ParseContext& parseContext )
539 {
540 If* pOldIf = parseContext.ifData;
541 CompilationUnit* pOldCompilationUnit = parseContext.compilationUnit;
542 bool subs_invalid = false;
543 string subpath ( relative_path );
544 DirectoryLocation subdirectory = SourceDirectory;
545 if ( e.name == "file" && e.value.size () > 0 )
546 {
547 bool first = false;
548 const XMLAttribute* att = e.GetAttribute ( "first", false );
549 if ( att != NULL )
550 {
551 if ( !stricmp ( att->value.c_str(), "true" ) )
552 first = true;
553 else if ( stricmp ( att->value.c_str(), "false" ) )
554 {
555 throw XMLInvalidBuildFileException (
556 e.location,
557 "attribute 'first' of <file> element can only be 'true' or 'false'" );
558 }
559 }
560 string switches = "";
561 att = e.GetAttribute ( "switches", false );
562 if ( att != NULL )
563 switches = att->value;
564 if ( !cplusplus )
565 {
566 // check for c++ file
567 string ext = GetExtension ( e.value );
568 if ( !stricmp ( ext.c_str(), ".cpp" ) )
569 cplusplus = true;
570 else if ( !stricmp ( ext.c_str(), ".cc" ) )
571 cplusplus = true;
572 else if ( !stricmp ( ext.c_str(), ".cxx" ) )
573 cplusplus = true;
574 }
575 File* pFile = new File ( directory,
576 relative_path,
577 e.value,
578 first,
579 switches,
580 false );
581 if ( parseContext.compilationUnit )
582 parseContext.compilationUnit->files.push_back ( pFile );
583 else
584 {
585 CompilationUnit* pCompilationUnit = new CompilationUnit ( pFile );
586 if ( parseContext.ifData )
587 parseContext.ifData->data.compilationUnits.push_back ( pCompilationUnit );
588 else
589 {
590 string ext = ToLower ( GetExtension ( e.value ) );
591 if ( ext == ".idl" )
592 {
593 // put .idl files at the start of the module
594 non_if_data.compilationUnits.insert (
595 non_if_data.compilationUnits.begin(),
596 pCompilationUnit );
597 }
598 else if ( ext == ".asm" || ext == ".s" )
599 {
600 // put .asm files at the end of the module
601 non_if_data.compilationUnits.push_back ( pCompilationUnit );
602 non_if_data.asmFiles++;
603 }
604 else
605 {
606 // put other files in the middle
607 non_if_data.compilationUnits.insert (
608 non_if_data.compilationUnits.end() - non_if_data.asmFiles,
609 pCompilationUnit );
610 }
611 }
612 }
613 if ( parseContext.ifData )
614 parseContext.ifData->data.files.push_back ( pFile );
615 else
616 non_if_data.files.push_back ( pFile );
617 subs_invalid = true;
618 }
619 else if ( e.name == "library" && e.value.size () )
620 {
621 Library* pLibrary = new Library ( e, *this, e.value );
622 if ( parseContext.ifData )
623 parseContext.ifData->data.libraries.push_back ( pLibrary );
624 else
625 non_if_data.libraries.push_back ( pLibrary );
626 subs_invalid = true;
627 }
628 else if ( e.name == "directory" )
629 {
630 const XMLAttribute* att = e.GetAttribute ( "name", true );
631 const XMLAttribute* root = e.GetAttribute ( "root", false );
632 assert(att);
633 if ( root )
634 {
635 if ( root->value == "intermediate" )
636 subdirectory = IntermediateDirectory;
637 else if ( root->value == "output" )
638 subdirectory = OutputDirectory;
639 else
640 {
641 throw InvalidAttributeValueException (
642 e.location,
643 "root",
644 root->value );
645 }
646 }
647 subpath = GetSubPath ( this->project, e.location, relative_path, att->value );
648 }
649 else if ( e.name == "include" )
650 {
651 Include* include = new Include ( project, &e, this );
652 if ( parseContext.ifData )
653 parseContext.ifData->data.includes.push_back ( include );
654 else
655 non_if_data.includes.push_back ( include );
656 subs_invalid = true;
657 }
658 else if ( e.name == "define" )
659 {
660 Define* pDefine = new Define ( project, this, e );
661 if ( parseContext.ifData )
662 parseContext.ifData->data.defines.push_back ( pDefine );
663 else
664 non_if_data.defines.push_back ( pDefine );
665 subs_invalid = true;
666 }
667 else if ( e.name == "metadata" )
668 {
669 if ( parseContext.ifData )
670 {
671 throw XMLInvalidBuildFileException (
672 e.location,
673 "<metadata> is not a valid sub-element of <if>" );
674 }
675 metadata = new Metadata ( e, *this );
676 subs_invalid = false;
677 }
678 else if ( e.name == "invoke" )
679 {
680 if ( parseContext.ifData )
681 {
682 throw XMLInvalidBuildFileException (
683 e.location,
684 "<invoke> is not a valid sub-element of <if>" );
685 }
686 invocations.push_back ( new Invoke ( e, *this ) );
687 subs_invalid = false;
688 }
689 else if ( e.name == "dependency" )
690 {
691 if ( parseContext.ifData )
692 {
693 throw XMLInvalidBuildFileException (
694 e.location,
695 "<dependency> is not a valid sub-element of <if>" );
696 }
697 dependencies.push_back ( new Dependency ( e, *this ) );
698 subs_invalid = true;
699 }
700 else if ( e.name == "importlibrary" )
701 {
702 if ( parseContext.ifData )
703 {
704 throw XMLInvalidBuildFileException (
705 e.location,
706 "<importlibrary> is not a valid sub-element of <if>" );
707 }
708 if ( importLibrary )
709 {
710 throw XMLInvalidBuildFileException (
711 e.location,
712 "Only one <importlibrary> is valid per module" );
713 }
714 SetImportLibrary ( new ImportLibrary ( project, e, *this ) );
715 subs_invalid = true;
716 }
717 else if ( e.name == "if" )
718 {
719 parseContext.ifData = new If ( e, project, this );
720 if ( pOldIf )
721 pOldIf->data.ifs.push_back ( parseContext.ifData );
722 else
723 non_if_data.ifs.push_back ( parseContext.ifData );
724 subs_invalid = false;
725 }
726 else if ( e.name == "ifnot" )
727 {
728 parseContext.ifData = new If ( e, project, this, true );
729 if ( pOldIf )
730 pOldIf->data.ifs.push_back ( parseContext.ifData );
731 else
732 non_if_data.ifs.push_back ( parseContext.ifData );
733 subs_invalid = false;
734 }
735 else if ( e.name == "compilerflag" )
736 {
737 CompilerFlag* pCompilerFlag = new CompilerFlag ( project, this, e );
738 if ( parseContext.ifData )
739 parseContext.ifData->data.compilerFlags.push_back ( pCompilerFlag );
740 else
741 non_if_data.compilerFlags.push_back ( pCompilerFlag );
742 subs_invalid = true;
743 }
744 else if ( e.name == "linkerflag" )
745 {
746 linkerFlags.push_back ( new LinkerFlag ( project, this, e ) );
747 subs_invalid = true;
748 }
749 else if ( e.name == "linkerscript" )
750 {
751 if ( parseContext.ifData )
752 {
753 throw XMLInvalidBuildFileException (
754 e.location,
755 "<linkerscript> is not a valid sub-element of <if>" );
756 }
757 if ( linkerScript )
758 {
759 throw XMLInvalidBuildFileException (
760 e.location,
761 "Only one <linkerscript> is valid per module" );
762 }
763 size_t pos = e.value.find_last_of ( "/\\" );
764 if ( pos == string::npos )
765 {
766 linkerScript = new LinkerScript (
767 e, *this, FileLocation ( SourceDirectory, relative_path, e.value, &e ) );
768 }
769 else
770 {
771 string dir = e.value.substr ( 0, pos );
772 string name = e.value.substr ( pos + 1);
773 linkerScript = new LinkerScript (
774 e, *this, FileLocation ( SourceDirectory, relative_path + sSep + dir, name, &e ) );
775 }
776 subs_invalid = true;
777 }
778 else if ( e.name == "component" )
779 {
780 stubbedComponents.push_back ( new StubbedComponent ( this, e ) );
781 subs_invalid = false;
782 }
783 else if ( e.name == "property" )
784 {
785 throw XMLInvalidBuildFileException (
786 e.location,
787 "<property> is not a valid sub-element of <module>" );
788 }
789 else if ( e.name == "bootstrap" )
790 {
791 bootstrap = new Bootstrap ( project, this, e );
792 subs_invalid = true;
793 }
794 else if ( e.name == "pch" )
795 {
796 if ( parseContext.ifData )
797 {
798 throw XMLInvalidBuildFileException (
799 e.location,
800 "<pch> is not a valid sub-element of <if>" );
801 }
802 if ( pch )
803 {
804 throw XMLInvalidBuildFileException (
805 e.location,
806 "Only one <pch> is valid per module" );
807 }
808 size_t pos = e.value.find_last_of ( "/\\" );
809 if ( pos == string::npos )
810 {
811 pch = new PchFile (
812 e, *this, FileLocation ( SourceDirectory, relative_path, e.value, &e ) );
813 }
814 else
815 {
816 string dir = e.value.substr ( 0, pos );
817 string name = e.value.substr ( pos + 1);
818 pch = new PchFile (
819 e, *this, FileLocation ( SourceDirectory, relative_path + sSep + dir, name, &e ) );
820 }
821 subs_invalid = true;
822 }
823 else if ( e.name == "compilationunit" )
824 {
825 if ( project.configuration.CompilationUnitsEnabled )
826 {
827 CompilationUnit* pCompilationUnit = new CompilationUnit ( &project, this, &e );
828 if ( parseContext.ifData )
829 parseContext.ifData->data.compilationUnits.push_back ( pCompilationUnit );
830 else
831 non_if_data.compilationUnits.push_back ( pCompilationUnit );
832 parseContext.compilationUnit = pCompilationUnit;
833 }
834 subs_invalid = false;
835 }
836 else if ( e.name == "autoregister" )
837 {
838 if ( autoRegister != NULL)
839 {
840 throw XMLInvalidBuildFileException (
841 e.location,
842 "there can be only one <%s> element for a module",
843 e.name.c_str() );
844 }
845 autoRegister = new AutoRegister ( project, this, e );
846 subs_invalid = true;
847 }
848 if ( subs_invalid && e.subElements.size() > 0 )
849 {
850 throw XMLInvalidBuildFileException (
851 e.location,
852 "<%s> cannot have sub-elements",
853 e.name.c_str() );
854 }
855 for ( size_t i = 0; i < e.subElements.size (); i++ )
856 ProcessXMLSubElement ( *e.subElements[i], subdirectory, subpath, parseContext );
857 parseContext.ifData = pOldIf;
858 parseContext.compilationUnit = pOldCompilationUnit;
859 }
860
861 ModuleType
862 Module::GetModuleType ( const string& location, const XMLAttribute& attribute )
863 {
864 if ( attribute.value == "buildtool" )
865 return BuildTool;
866 if ( attribute.value == "staticlibrary" )
867 return StaticLibrary;
868 if ( attribute.value == "objectlibrary" )
869 return ObjectLibrary;
870 if ( attribute.value == "kernel" )
871 return Kernel;
872 if ( attribute.value == "kernelmodedll" )
873 return KernelModeDLL;
874 if ( attribute.value == "kernelmodedriver" )
875 return KernelModeDriver;
876 if ( attribute.value == "nativedll" )
877 return NativeDLL;
878 if ( attribute.value == "nativecui" )
879 return NativeCUI;
880 if ( attribute.value == "win32dll" )
881 return Win32DLL;
882 if ( attribute.value == "win32ocx" )
883 return Win32OCX;
884 if ( attribute.value == "win32cui" )
885 return Win32CUI;
886 if ( attribute.value == "win32gui" )
887 return Win32GUI;
888 if ( attribute.value == "win32scr" )
889 return Win32SCR;
890 if ( attribute.value == "bootloader" )
891 return BootLoader;
892 if ( attribute.value == "bootsector" )
893 return BootSector;
894 if ( attribute.value == "bootprogram" )
895 return BootProgram;
896 if ( attribute.value == "iso" )
897 return Iso;
898 if ( attribute.value == "liveiso" )
899 return LiveIso;
900 if ( attribute.value == "isoregtest" )
901 return IsoRegTest;
902 if ( attribute.value == "liveisoregtest" )
903 return LiveIsoRegTest;
904 if ( attribute.value == "test" )
905 return Test;
906 if ( attribute.value == "rpcserver" )
907 return RpcServer;
908 if ( attribute.value == "rpcclient" )
909 return RpcClient;
910 if ( attribute.value == "alias" )
911 return Alias;
912 if ( attribute.value == "idlheader" )
913 return IdlHeader;
914 if ( attribute.value == "embeddedtypelib" )
915 return EmbeddedTypeLib;
916 if ( attribute.value == "elfexecutable" )
917 return ElfExecutable;
918 throw InvalidAttributeValueException ( location,
919 attribute.name,
920 attribute.value );
921 }
922
923 DirectoryLocation
924 Module::GetTargetDirectoryTree () const
925 {
926 switch ( type )
927 {
928 case Kernel:
929 case KernelModeDLL:
930 case NativeDLL:
931 case Win32DLL:
932 case Win32OCX:
933 case KernelModeDriver:
934 case NativeCUI:
935 case Win32CUI:
936 case Test:
937 case Win32SCR:
938 case Win32GUI:
939 case BuildTool:
940 case BootLoader:
941 case BootSector:
942 case BootProgram:
943 case Iso:
944 case LiveIso:
945 case IsoRegTest:
946 case LiveIsoRegTest:
947 case EmbeddedTypeLib:
948 case ElfExecutable:
949 return OutputDirectory;
950 case StaticLibrary:
951 case ObjectLibrary:
952 case RpcServer:
953 case RpcClient:
954 case Alias:
955 case IdlHeader:
956 return IntermediateDirectory;
957 }
958 throw InvalidOperationException ( __FILE__,
959 __LINE__,
960 "Invalid module type %d.",
961 type );
962 }
963
964 string
965 Module::GetDefaultModuleExtension () const
966 {
967 switch (type)
968 {
969 case BuildTool:
970 return ExePostfix;
971 case BootProgram:
972 case StaticLibrary:
973 return ".a";
974 case ObjectLibrary:
975 return ".o";
976 case Kernel:
977 case NativeCUI:
978 case Win32CUI:
979 case Win32GUI:
980 return ".exe";
981 case Win32SCR:
982 return ".scr";
983
984 case KernelModeDLL:
985 case NativeDLL:
986 case Win32DLL:
987 return ".dll";
988 case Win32OCX:
989 return ".ocx";
990 case KernelModeDriver:
991 case BootLoader:
992 return ".sys";
993 case BootSector:
994 return "_" + this->name + ".o";
995 case Iso:
996 case LiveIso:
997 case IsoRegTest:
998 case LiveIsoRegTest:
999 return ".iso";
1000 case Test:
1001 return ".exe";
1002 case RpcServer:
1003 return ".o";
1004 case RpcClient:
1005 return ".o";
1006 case Alias:
1007 case ElfExecutable:
1008 case IdlHeader:
1009 return "";
1010 case EmbeddedTypeLib:
1011 return ".tlb";
1012 }
1013 throw InvalidOperationException ( __FILE__,
1014 __LINE__ );
1015 }
1016
1017 string
1018 Module::GetDefaultModuleEntrypoint () const
1019 {
1020 switch ( type )
1021 {
1022 case Kernel:
1023 return "NtProcessStartup";
1024 case KernelModeDLL:
1025 case KernelModeDriver:
1026 return "DriverEntry@8";
1027 case NativeDLL:
1028 return "DllMainCRTStartup@12";
1029 case NativeCUI:
1030 return "NtProcessStartup@4";
1031 case Win32DLL:
1032 case Win32OCX:
1033 return "DllMain@12";
1034 case Win32CUI:
1035 case Test:
1036 if ( isUnicode )
1037 return "wmainCRTStartup";
1038 else
1039 return "mainCRTStartup";
1040 case Win32SCR:
1041 case Win32GUI:
1042 if ( isUnicode )
1043 return "wWinMainCRTStartup";
1044 else
1045 return "WinMainCRTStartup";
1046 case BuildTool:
1047 case StaticLibrary:
1048 case ObjectLibrary:
1049 case BootLoader:
1050 case BootSector:
1051 case Iso:
1052 case LiveIso:
1053 case IsoRegTest:
1054 case LiveIsoRegTest:
1055 case RpcServer:
1056 case RpcClient:
1057 case Alias:
1058 case BootProgram:
1059 case IdlHeader:
1060 case ElfExecutable:
1061 case EmbeddedTypeLib:
1062 return "";
1063 }
1064 throw InvalidOperationException ( __FILE__,
1065 __LINE__ );
1066 }
1067
1068 string
1069 Module::GetDefaultModuleBaseaddress () const
1070 {
1071 switch ( type )
1072 {
1073 case Kernel:
1074 return "0x80800000";
1075 case Win32DLL:
1076 case Win32OCX:
1077 return "0x10000000";
1078 case NativeDLL:
1079 case NativeCUI:
1080 case Win32CUI:
1081 case Test:
1082 return "0x00400000";
1083 case Win32SCR:
1084 case Win32GUI:
1085 return "0x00400000";
1086 case KernelModeDLL:
1087 case KernelModeDriver:
1088 return "0x00010000";
1089 case ElfExecutable:
1090 return "0xe00000";
1091 case BuildTool:
1092 case StaticLibrary:
1093 case ObjectLibrary:
1094 case BootLoader:
1095 case BootSector:
1096 case Iso:
1097 case LiveIso:
1098 case IsoRegTest:
1099 case LiveIsoRegTest:
1100 case RpcServer:
1101 case RpcClient:
1102 case Alias:
1103 case BootProgram:
1104 case IdlHeader:
1105 case EmbeddedTypeLib:
1106 return "";
1107 }
1108 throw InvalidOperationException ( __FILE__,
1109 __LINE__ );
1110 }
1111
1112 bool
1113 Module::HasImportLibrary () const
1114 {
1115 return importLibrary != NULL && type != StaticLibrary;
1116 }
1117
1118 bool
1119 Module::IsDLL () const
1120 {
1121 switch ( type )
1122 {
1123 case Kernel:
1124 case KernelModeDLL:
1125 case NativeDLL:
1126 case Win32DLL:
1127 case Win32OCX:
1128 case KernelModeDriver:
1129 return true;
1130 case NativeCUI:
1131 case Win32CUI:
1132 case Test:
1133 case Win32SCR:
1134 case Win32GUI:
1135 case BuildTool:
1136 case StaticLibrary:
1137 case ObjectLibrary:
1138 case BootLoader:
1139 case BootSector:
1140 case BootProgram:
1141 case Iso:
1142 case LiveIso:
1143 case IsoRegTest:
1144 case LiveIsoRegTest:
1145 case RpcServer:
1146 case RpcClient:
1147 case Alias:
1148 case IdlHeader:
1149 case EmbeddedTypeLib:
1150 case ElfExecutable:
1151 return false;
1152 }
1153 throw InvalidOperationException ( __FILE__,
1154 __LINE__ );
1155 }
1156
1157 string
1158 Module::GetPathWithPrefix ( const string& prefix ) const
1159 {
1160 return output->relative_path + cSep + prefix + output->name;
1161 }
1162
1163 string
1164 Module::GetPathToBaseDir () const
1165 {
1166 string temp_path = output->relative_path;
1167 string result = "..\\";
1168 while(temp_path.find ('\\') != string::npos)
1169 {
1170 temp_path.erase (0, temp_path.find('\\')+1);
1171 result += "..\\";
1172 }
1173 return result;
1174 }
1175
1176 string
1177 Module::GetInvocationTarget ( const int index ) const
1178 {
1179 return ssprintf ( "%s_invoke_%d",
1180 name.c_str (),
1181 index );
1182 }
1183
1184 string
1185 Module::GetEntryPoint(bool leadingUnderscore) const
1186 {
1187 string result = "";
1188 if (entrypoint == "0" || entrypoint == "0x0")
1189 return "0";
1190 if (leadingUnderscore)
1191 result = "_";
1192
1193 result += entrypoint;
1194 return result;
1195 }
1196
1197 bool
1198 Module::HasFileWithExtension (
1199 const IfableData& data,
1200 const std::string& extension ) const
1201 {
1202 size_t i;
1203 for ( i = 0; i < data.compilationUnits.size (); i++ )
1204 {
1205 CompilationUnit* compilationUnit = data.compilationUnits[i];
1206 if ( compilationUnit->HasFileWithExtension ( extension ) )
1207 return true;
1208 }
1209 for ( i = 0; i < data.ifs.size (); i++ )
1210 {
1211 if ( HasFileWithExtension ( data.ifs[i]->data, extension ) )
1212 return true;
1213 }
1214 return false;
1215 }
1216
1217 void
1218 Module::InvokeModule () const
1219 {
1220 for ( size_t i = 0; i < invocations.size (); i++ )
1221 {
1222 Invoke& invoke = *invocations[i];
1223 string command = FixSeparatorForSystemCommand(invoke.invokeModule->output->relative_path + "/" + invoke.invokeModule->output->name ) + " " + invoke.GetParameters ();
1224 printf ( "Executing '%s'\n\n", command.c_str () );
1225 int exitcode = system ( command.c_str () );
1226 if ( exitcode != 0 )
1227 throw InvocationFailedException ( command,
1228 exitcode );
1229 }
1230 }
1231
1232
1233 void
1234 Module::SetImportLibrary ( ImportLibrary* importLibrary )
1235 {
1236 this->importLibrary = importLibrary;
1237 dependency = new FileLocation ( HasImportLibrary () ? IntermediateDirectory : output->directory,
1238 output->relative_path,
1239 HasImportLibrary () ? "lib" + name + ".a" : output->name );
1240 }
1241
1242
1243 File::File ( DirectoryLocation directory,
1244 const string& relative_path,
1245 const string& name,
1246 bool _first,
1247 const string& _switches,
1248 bool _isPreCompiledHeader )
1249 : file ( directory, relative_path, name ),
1250 first(_first),
1251 switches(_switches),
1252 isPreCompiledHeader(_isPreCompiledHeader)
1253 {
1254 }
1255
1256
1257 void
1258 File::ProcessXML()
1259 {
1260 }
1261
1262
1263 std::string File::GetFullPath () const
1264 {
1265 string directory ( "" );
1266 switch ( file.directory )
1267 {
1268 case SourceDirectory:
1269 break;
1270 case IntermediateDirectory:
1271 directory = Environment::GetIntermediatePath () + sSep;
1272 break;
1273 default:
1274 throw InvalidOperationException ( __FILE__,
1275 __LINE__,
1276 "Invalid directory %d.",
1277 file.directory );
1278 }
1279
1280 if ( file.relative_path.length () > 0 )
1281 directory += file.relative_path + sSep;
1282
1283
1284 return directory + file.name;
1285 }
1286
1287
1288 Library::Library ( const XMLElement& _node,
1289 const Module& _module,
1290 const string& _name )
1291 : node(&_node),
1292 module(_module),
1293 name(_name),
1294 importedModule(_module.project.LocateModule(_name))
1295 {
1296 if ( module.name == name )
1297 {
1298 throw XMLInvalidBuildFileException (
1299 node->location,
1300 "module '%s' cannot link against itself",
1301 name.c_str() );
1302 }
1303 if ( !importedModule )
1304 {
1305 throw XMLInvalidBuildFileException (
1306 node->location,
1307 "module '%s' trying to import non-existant module '%s'",
1308 module.name.c_str(),
1309 name.c_str() );
1310 }
1311 }
1312
1313 Library::Library ( const Module& _module,
1314 const string& _name )
1315 : node(NULL),
1316 module(_module),
1317 name(_name),
1318 importedModule(_module.project.LocateModule(_name))
1319 {
1320 }
1321
1322 void
1323 Library::ProcessXML()
1324 {
1325 if ( node && !module.project.LocateModule ( name ) )
1326 {
1327 throw XMLInvalidBuildFileException (
1328 node->location,
1329 "module '%s' is trying to link against non-existant module '%s'",
1330 module.name.c_str(),
1331 name.c_str() );
1332 }
1333 }
1334
1335
1336 Invoke::Invoke ( const XMLElement& _node,
1337 const Module& _module )
1338 : node (_node),
1339 module (_module)
1340 {
1341 }
1342
1343 void
1344 Invoke::ProcessXML()
1345 {
1346 const XMLAttribute* att = node.GetAttribute ( "module", false );
1347 if (att == NULL)
1348 invokeModule = &module;
1349 else
1350 {
1351 invokeModule = module.project.LocateModule ( att->value );
1352 if ( invokeModule == NULL )
1353 {
1354 throw XMLInvalidBuildFileException (
1355 node.location,
1356 "module '%s' is trying to invoke non-existant module '%s'",
1357 module.name.c_str(),
1358 att->value.c_str() );
1359 }
1360 }
1361
1362 for ( size_t i = 0; i < node.subElements.size (); i++ )
1363 ProcessXMLSubElement ( *node.subElements[i] );
1364 }
1365
1366 void
1367 Invoke::ProcessXMLSubElement ( const XMLElement& e )
1368 {
1369 bool subs_invalid = false;
1370 if ( e.name == "input" )
1371 {
1372 for ( size_t i = 0; i < e.subElements.size (); i++ )
1373 ProcessXMLSubElementInput ( *e.subElements[i] );
1374 }
1375 else if ( e.name == "output" )
1376 {
1377 for ( size_t i = 0; i < e.subElements.size (); i++ )
1378 ProcessXMLSubElementOutput ( *e.subElements[i] );
1379 }
1380 if ( subs_invalid && e.subElements.size() > 0 )
1381 {
1382 throw XMLInvalidBuildFileException (
1383 e.location,
1384 "<%s> cannot have sub-elements",
1385 e.name.c_str() );
1386 }
1387 }
1388
1389 void
1390 Invoke::ProcessXMLSubElementInput ( const XMLElement& e )
1391 {
1392 bool subs_invalid = false;
1393 if ( e.name == "inputfile" && e.value.size () > 0 )
1394 {
1395 input.push_back ( new InvokeFile (
1396 e, FixSeparator ( module.output->relative_path + cSep + e.value ) ) );
1397 subs_invalid = true;
1398 }
1399 if ( subs_invalid && e.subElements.size() > 0 )
1400 {
1401 throw XMLInvalidBuildFileException (
1402 e.location,
1403 "<%s> cannot have sub-elements",
1404 e.name.c_str() );
1405 }
1406 }
1407
1408 void
1409 Invoke::ProcessXMLSubElementOutput ( const XMLElement& e )
1410 {
1411 bool subs_invalid = false;
1412 if ( e.name == "outputfile" && e.value.size () > 0 )
1413 {
1414 output.push_back ( new InvokeFile (
1415 e, FixSeparator ( module.output->relative_path + cSep + e.value ) ) );
1416 subs_invalid = true;
1417 }
1418 if ( subs_invalid && e.subElements.size() > 0 )
1419 {
1420 throw XMLInvalidBuildFileException (
1421 e.location,
1422 "<%s> cannot have sub-elements",
1423 e.name.c_str() );
1424 }
1425 }
1426
1427 void
1428 Invoke::GetTargets ( string_list& targets ) const
1429 {
1430 for ( size_t i = 0; i < output.size (); i++ )
1431 {
1432 InvokeFile& file = *output[i];
1433 targets.push_back ( NormalizeFilename ( file.name ) );
1434 }
1435 }
1436
1437 string
1438 Invoke::GetParameters () const
1439 {
1440 string parameters ( "" );
1441 size_t i;
1442 for ( i = 0; i < output.size (); i++ )
1443 {
1444 if ( parameters.length () > 0)
1445 parameters += " ";
1446 InvokeFile& invokeFile = *output[i];
1447 if ( invokeFile.switches.length () > 0 )
1448 {
1449 parameters += invokeFile.switches + " ";
1450 }
1451 parameters += invokeFile.name;
1452 }
1453
1454 for ( i = 0; i < input.size (); i++ )
1455 {
1456 if ( parameters.length () > 0 )
1457 parameters += " ";
1458 InvokeFile& invokeFile = *input[i];
1459 if ( invokeFile.switches.length () > 0 )
1460 {
1461 parameters += invokeFile.switches;
1462 parameters += " ";
1463 }
1464 parameters += invokeFile.name ;
1465 }
1466
1467 return parameters;
1468 }
1469
1470
1471 InvokeFile::InvokeFile ( const XMLElement& _node,
1472 const string& _name )
1473 : node (_node),
1474 name (_name)
1475 {
1476 const XMLAttribute* att = _node.GetAttribute ( "switches", false );
1477 if (att != NULL)
1478 switches = att->value;
1479 else
1480 switches = "";
1481 }
1482
1483 void
1484 InvokeFile::ProcessXML()
1485 {
1486 }
1487
1488
1489 Dependency::Dependency ( const XMLElement& _node,
1490 const Module& _module )
1491 : node (_node),
1492 module (_module),
1493 dependencyModule (NULL)
1494 {
1495 }
1496
1497 void
1498 Dependency::ProcessXML()
1499 {
1500 dependencyModule = module.project.LocateModule ( node.value );
1501 if ( dependencyModule == NULL )
1502 {
1503 throw XMLInvalidBuildFileException (
1504 node.location,
1505 "module '%s' depend on non-existant module '%s'",
1506 module.name.c_str(),
1507 node.value.c_str() );
1508 }
1509 }
1510
1511
1512 Metadata::Metadata ( const XMLElement& _node,
1513 const Module& _module )
1514 : node (_node),
1515 module (_module)
1516 {
1517 /* The module name */
1518 const XMLAttribute* att = _node.GetAttribute ( "name", false );
1519 if (att != NULL)
1520 name = att->value;
1521 else
1522 name = module.name;
1523
1524 /* The module description */
1525 att = _node.GetAttribute ( "description", false );
1526 if (att != NULL)
1527 description = att->value;
1528 else
1529 description = "";
1530
1531 /* The module version */
1532 att = _node.GetAttribute ( "version", false );
1533 if (att != NULL)
1534 version = att->value;
1535 else
1536 version = "";
1537
1538 /* The module copyright */
1539 att = _node.GetAttribute ( "copyright", false );
1540 if (att != NULL)
1541 copyright = att->value;
1542 else
1543 copyright = "";
1544
1545 att = _node.GetAttribute ( "url", false );
1546 if (att != NULL)
1547 url = att->value;
1548 else
1549 url = "";
1550
1551 /* When was this module updated */
1552 att = _node.GetAttribute ( "date", false );
1553 if (att != NULL)
1554 date = att->value;
1555 else
1556 date = "?";
1557
1558 /* When was this module updated */
1559 att = _node.GetAttribute ( "owner", false );
1560 if (att != NULL)
1561 owner = att->value;
1562 else
1563 owner = "ReactOS";
1564 }
1565
1566
1567 ImportLibrary::ImportLibrary ( const Project& project,
1568 const XMLElement& node,
1569 const Module& module )
1570 : XmlNode ( project, node ),
1571 module (module)
1572 {
1573 const XMLAttribute* dllname = node.GetAttribute ( "dllname", false );
1574 const XMLAttribute* definition = node.GetAttribute ( "definition", true );
1575 assert ( definition );
1576
1577 if ( dllname )
1578 this->dllname = dllname->value;
1579 else if ( module.type == StaticLibrary )
1580 throw XMLInvalidBuildFileException (
1581 node.location,
1582 "<importlibrary> dllname attribute required." );
1583
1584 DirectoryLocation directory = SourceDirectory;
1585 size_t index = definition->value.rfind ( ".spec.def" );
1586 if ( index != string::npos )
1587 directory = IntermediateDirectory;
1588
1589 index = definition->value.find_last_of ( "/\\" );
1590 if ( index == string::npos )
1591 {
1592 source = new FileLocation ( directory,
1593 module.output->relative_path,
1594 definition->value,
1595 &node );
1596 }
1597 else
1598 {
1599 string dir = definition->value.substr ( 0, index );
1600 string name = definition->value.substr ( index + 1);
1601 source = new FileLocation ( directory,
1602 NormalizeFilename ( module.output->relative_path + sSep + dir ),
1603 name,
1604 &node );
1605 }
1606 }
1607
1608
1609 If::If ( const XMLElement& node_,
1610 const Project& project_,
1611 const Module* module_,
1612 const bool negated_ )
1613 : node(node_), project(project_), module(module_), negated(negated_)
1614 {
1615 const XMLAttribute* att;
1616
1617 att = node.GetAttribute ( "property", true );
1618 assert(att);
1619 property = att->value;
1620
1621 att = node.GetAttribute ( "value", true );
1622 assert(att);
1623 value = att->value;
1624 }
1625
1626 If::~If ()
1627 {
1628 }
1629
1630 void
1631 If::ProcessXML()
1632 {
1633
1634 }
1635
1636
1637 Property::Property ( const XMLElement& node_,
1638 const Project& project_,
1639 const Module* module_ )
1640 : project(project_), module(module_)
1641 {
1642 const XMLAttribute* att;
1643
1644 att = node_.GetAttribute ( "name", true );
1645 assert(att);
1646 name = project.ResolveProperties ( att->value );
1647
1648 att = node_.GetAttribute ( "value", true );
1649 assert(att);
1650 value = att->value;
1651 }
1652
1653 Property::Property ( const Project& project_,
1654 const Module* module_,
1655 const std::string& name_,
1656 const std::string& value_ )
1657 : project(project_), module(module_), name(name_), value(value_)
1658 {
1659 }
1660
1661 void
1662 Property::ProcessXML()
1663 {
1664 }
1665
1666
1667 PchFile::PchFile (
1668 const XMLElement& node_,
1669 const Module& module_,
1670 const FileLocation& file_ )
1671 : node(node_), module(module_), file(file_)
1672 {
1673 }
1674
1675 void
1676 PchFile::ProcessXML()
1677 {
1678 }