7a9e4a657819fd85560c7f15ba82937243b1051d
[reactos.git] / reactos / tools / rbuild / module.cpp
1 #include "pch.h"
2 #include <assert.h>
3
4 #include "rbuild.h"
5
6 using std::string;
7 using std::vector;
8
9 string
10 FixSeparator ( const string& s )
11 {
12 string s2(s);
13 char* p = strchr ( &s2[0], CBAD_SEP );
14 while ( p )
15 {
16 *p++ = CSEP;
17 p = strchr ( p, CBAD_SEP );
18 }
19 return s2;
20 }
21
22 string
23 GetExtension ( const string& filename )
24 {
25 size_t index = filename.find_last_of ( '/' );
26 if (index == string::npos) index = 0;
27 string tmp = filename.substr( index, filename.size() - index );
28 size_t ext_index = tmp.find_last_of( '.' );
29 if (ext_index != string::npos)
30 return filename.substr ( index + ext_index, filename.size() );
31 return "";
32 }
33
34 string
35 GetDirectory ( const string& filename )
36 {
37 size_t index = filename.find_last_of ( CSEP );
38 if ( index == string::npos )
39 return filename;
40 else
41 return filename.substr ( 0, index );
42 }
43
44 string
45 NormalizeFilename ( const string& filename )
46 {
47 Path path;
48 string normalizedPath = path.Fixup ( filename, true );
49 string relativeNormalizedPath = path.RelativeFromWorkingDirectory ( normalizedPath );
50 return FixSeparator ( relativeNormalizedPath );
51 }
52
53 IfableData::~IfableData()
54 {
55 size_t i;
56 for ( i = 0; i < files.size(); i++ )
57 delete files[i];
58 for ( i = 0; i < includes.size(); i++ )
59 delete includes[i];
60 for ( i = 0; i < defines.size(); i++ )
61 delete defines[i];
62 for ( i = 0; i < libraries.size(); i++ )
63 delete libraries[i];
64 for ( i = 0; i < properties.size(); i++ )
65 delete properties[i];
66 for ( i = 0; i < ifs.size(); i++ )
67 delete ifs[i];
68 }
69
70 void IfableData::ProcessXML ()
71 {
72 size_t i;
73 for ( i = 0; i < files.size (); i++ )
74 files[i]->ProcessXML ();
75 for ( i = 0; i < includes.size (); i++ )
76 includes[i]->ProcessXML ();
77 for ( i = 0; i < defines.size (); i++ )
78 defines[i]->ProcessXML ();
79 for ( i = 0; i < libraries.size (); i++ )
80 libraries[i]->ProcessXML ();
81 for ( i = 0; i < properties.size(); i++ )
82 properties[i]->ProcessXML ();
83 for ( i = 0; i < ifs.size (); i++ )
84 ifs[i]->ProcessXML ();
85 }
86
87 Module::Module ( const Project& project,
88 const XMLElement& moduleNode,
89 const string& modulePath )
90 : project (project),
91 node (moduleNode),
92 importLibrary (NULL),
93 bootstrap (NULL),
94 pch (NULL),
95 cplusplus (false),
96 host (HostDefault)
97 {
98 if ( node.name != "module" )
99 throw Exception ( "internal tool error: Module created with non-<module> node" );
100
101 path = FixSeparator ( modulePath );
102
103 const XMLAttribute* att = moduleNode.GetAttribute ( "name", true );
104 assert(att);
105 name = att->value;
106
107 att = moduleNode.GetAttribute ( "type", true );
108 assert(att);
109 type = GetModuleType ( node.location, *att );
110
111 att = moduleNode.GetAttribute ( "extension", false );
112 if ( att != NULL )
113 extension = att->value;
114 else
115 extension = GetDefaultModuleExtension ();
116
117 att = moduleNode.GetAttribute ( "entrypoint", false );
118 if ( att != NULL )
119 entrypoint = att->value;
120 else
121 entrypoint = GetDefaultModuleEntrypoint ();
122
123 att = moduleNode.GetAttribute ( "baseaddress", false );
124 if ( att != NULL )
125 baseaddress = att->value;
126 else
127 baseaddress = GetDefaultModuleBaseaddress ();
128
129 att = moduleNode.GetAttribute ( "mangledsymbols", false );
130 if ( att != NULL )
131 {
132 const char* p = att->value.c_str();
133 if ( !stricmp ( p, "true" ) || !stricmp ( p, "yes" ) )
134 mangledSymbols = true;
135 else if ( !stricmp ( p, "false" ) || !stricmp ( p, "no" ) )
136 mangledSymbols = false;
137 else
138 {
139 throw InvalidAttributeValueException (
140 moduleNode.location,
141 "mangledsymbols",
142 att->value );
143 }
144 }
145 else
146 mangledSymbols = false;
147
148 att = moduleNode.GetAttribute ( "host", false );
149 if ( att != NULL )
150 {
151 const char* p = att->value.c_str();
152 if ( !stricmp ( p, "true" ) || !stricmp ( p, "yes" ) )
153 host = HostTrue;
154 else if ( !stricmp ( p, "false" ) || !stricmp ( p, "no" ) )
155 host = HostFalse;
156 else
157 {
158 throw InvalidAttributeValueException (
159 moduleNode.location,
160 "host",
161 att->value );
162 }
163 }
164
165 att = moduleNode.GetAttribute ( "prefix", false );
166 if ( att != NULL )
167 prefix = att->value;
168 }
169
170 Module::~Module ()
171 {
172 size_t i;
173 for ( i = 0; i < invocations.size(); i++ )
174 delete invocations[i];
175 for ( i = 0; i < dependencies.size(); i++ )
176 delete dependencies[i];
177 for ( i = 0; i < compilerFlags.size(); i++ )
178 delete compilerFlags[i];
179 for ( i = 0; i < linkerFlags.size(); i++ )
180 delete linkerFlags[i];
181 if ( pch )
182 delete pch;
183 }
184
185 void
186 Module::ProcessXML()
187 {
188 size_t i;
189 for ( i = 0; i < node.subElements.size(); i++ )
190 ProcessXMLSubElement ( *node.subElements[i], path );
191 for ( i = 0; i < invocations.size(); i++ )
192 invocations[i]->ProcessXML ();
193 for ( i = 0; i < dependencies.size(); i++ )
194 dependencies[i]->ProcessXML ();
195 for ( i = 0; i < compilerFlags.size(); i++ )
196 compilerFlags[i]->ProcessXML();
197 for ( i = 0; i < linkerFlags.size(); i++ )
198 linkerFlags[i]->ProcessXML();
199 non_if_data.ProcessXML();
200 if ( pch )
201 pch->ProcessXML();
202 }
203
204 void
205 Module::ProcessXMLSubElement ( const XMLElement& e,
206 const string& path,
207 If* pIf /*= NULL*/ )
208 {
209 bool subs_invalid = false;
210 string subpath ( path );
211 if ( e.name == "file" && e.value.size () > 0 )
212 {
213 bool first = false;
214 const XMLAttribute* att = e.GetAttribute ( "first", false );
215 if ( att )
216 {
217 if ( !stricmp ( att->value.c_str(), "true" ) )
218 first = true;
219 else if ( stricmp ( att->value.c_str(), "false" ) )
220 throw InvalidBuildFileException (
221 e.location,
222 "attribute 'first' of <file> element can only be 'true' or 'false'" );
223 }
224 if ( !cplusplus )
225 {
226 // check for c++ file
227 string ext = GetExtension ( e.value );
228 if ( !stricmp ( ext.c_str(), ".cpp" ) )
229 cplusplus = true;
230 else if ( !stricmp ( ext.c_str(), ".cc" ) )
231 cplusplus = true;
232 else if ( !stricmp ( ext.c_str(), ".cxx" ) )
233 cplusplus = true;
234 }
235 File* pFile = new File ( FixSeparator ( path + CSEP + e.value ), first );
236 if ( pIf )
237 pIf->data.files.push_back ( pFile );
238 else
239 non_if_data.files.push_back ( pFile );
240 subs_invalid = true;
241 }
242 else if ( e.name == "library" && e.value.size () )
243 {
244 Library* pLibrary = new Library ( e, *this, e.value );
245 if ( pIf )
246 pIf->data.libraries.push_back ( pLibrary );
247 else
248 non_if_data.libraries.push_back ( pLibrary );
249 subs_invalid = true;
250 }
251 else if ( e.name == "directory" )
252 {
253 const XMLAttribute* att = e.GetAttribute ( "name", true );
254 assert(att);
255 subpath = FixSeparator ( path + CSEP + att->value );
256 }
257 else if ( e.name == "include" )
258 {
259 Include* include = new Include ( project, this, e );
260 if ( pIf )
261 pIf->data.includes.push_back ( include );
262 else
263 non_if_data.includes.push_back ( include );
264 subs_invalid = true;
265 }
266 else if ( e.name == "define" )
267 {
268 Define* pDefine = new Define ( project, this, e );
269 if ( pIf )
270 pIf->data.defines.push_back ( pDefine );
271 else
272 non_if_data.defines.push_back ( pDefine );
273 subs_invalid = true;
274 }
275 else if ( e.name == "invoke" )
276 {
277 if ( pIf )
278 throw InvalidBuildFileException (
279 e.location,
280 "<invoke> is not a valid sub-element of <if>" );
281 invocations.push_back ( new Invoke ( e, *this ) );
282 subs_invalid = false;
283 }
284 else if ( e.name == "dependency" )
285 {
286 if ( pIf )
287 throw InvalidBuildFileException (
288 e.location,
289 "<dependency> is not a valid sub-element of <if>" );
290 dependencies.push_back ( new Dependency ( e, *this ) );
291 subs_invalid = true;
292 }
293 else if ( e.name == "importlibrary" )
294 {
295 if ( pIf )
296 throw InvalidBuildFileException (
297 e.location,
298 "<importlibrary> is not a valid sub-element of <if>" );
299 if ( importLibrary )
300 throw InvalidBuildFileException (
301 e.location,
302 "Only one <importlibrary> is valid per module" );
303 importLibrary = new ImportLibrary ( e, *this );
304 subs_invalid = true;
305 }
306 else if ( e.name == "if" )
307 {
308 If* pOldIf = pIf;
309 pIf = new If ( e, project, this );
310 if ( pOldIf )
311 pOldIf->data.ifs.push_back ( pIf );
312 else
313 non_if_data.ifs.push_back ( pIf );
314 subs_invalid = false;
315 }
316 else if ( e.name == "compilerflag" )
317 {
318 compilerFlags.push_back ( new CompilerFlag ( project, this, e ) );
319 subs_invalid = true;
320 }
321 else if ( e.name == "linkerflag" )
322 {
323 linkerFlags.push_back ( new LinkerFlag ( project, this, e ) );
324 subs_invalid = true;
325 }
326 else if ( e.name == "property" )
327 {
328 throw InvalidBuildFileException (
329 e.location,
330 "<property> is not a valid sub-element of <module>" );
331 }
332 else if ( e.name == "bootstrap" )
333 {
334 bootstrap = new Bootstrap ( project, this, e );
335 subs_invalid = true;
336 }
337 else if ( e.name == "pch" )
338 {
339 if ( pIf )
340 throw InvalidBuildFileException (
341 e.location,
342 "<pch> is not a valid sub-element of <if>" );
343 if ( pch )
344 throw InvalidBuildFileException (
345 e.location,
346 "Only one <pch> is valid per module" );
347 pch = new PchFile (
348 e, *this, FixSeparator ( path + CSEP + e.value ) );
349 subs_invalid = true;
350 }
351 if ( subs_invalid && e.subElements.size() > 0 )
352 throw InvalidBuildFileException (
353 e.location,
354 "<%s> cannot have sub-elements",
355 e.name.c_str() );
356 for ( size_t i = 0; i < e.subElements.size (); i++ )
357 ProcessXMLSubElement ( *e.subElements[i], subpath, pIf );
358 }
359
360 ModuleType
361 Module::GetModuleType ( const string& location, const XMLAttribute& attribute )
362 {
363 if ( attribute.value == "buildtool" )
364 return BuildTool;
365 if ( attribute.value == "staticlibrary" )
366 return StaticLibrary;
367 if ( attribute.value == "objectlibrary" )
368 return ObjectLibrary;
369 if ( attribute.value == "kernel" )
370 return Kernel;
371 if ( attribute.value == "kernelmodedll" )
372 return KernelModeDLL;
373 if ( attribute.value == "kernelmodedriver" )
374 return KernelModeDriver;
375 if ( attribute.value == "nativedll" )
376 return NativeDLL;
377 if ( attribute.value == "nativecui" )
378 return NativeCUI;
379 if ( attribute.value == "win32dll" )
380 return Win32DLL;
381 if ( attribute.value == "win32cui" )
382 return Win32CUI;
383 if ( attribute.value == "win32gui" )
384 return Win32GUI;
385 if ( attribute.value == "bootloader" )
386 return BootLoader;
387 if ( attribute.value == "bootsector" )
388 return BootSector;
389 if ( attribute.value == "iso" )
390 return Iso;
391 throw InvalidAttributeValueException ( location,
392 attribute.name,
393 attribute.value );
394 }
395
396 string
397 Module::GetDefaultModuleExtension () const
398 {
399 switch (type)
400 {
401 case BuildTool:
402 return EXEPOSTFIX;
403 case StaticLibrary:
404 return ".a";
405 case ObjectLibrary:
406 return ".o";
407 case Kernel:
408 case NativeCUI:
409 case Win32CUI:
410 case Win32GUI:
411 return ".exe";
412 case KernelModeDLL:
413 case NativeDLL:
414 case Win32DLL:
415 return ".dll";
416 case KernelModeDriver:
417 case BootLoader:
418 return ".sys";
419 case BootSector:
420 return ".o";
421 case Iso:
422 return ".iso";
423 }
424 throw InvalidOperationException ( __FILE__,
425 __LINE__ );
426 }
427
428 string
429 Module::GetDefaultModuleEntrypoint () const
430 {
431 switch (type)
432 {
433 case Kernel:
434 return "_NtProcessStartup";
435 case KernelModeDLL:
436 return "_DriverEntry@8";
437 case NativeDLL:
438 return "_DllMainCRTStartup@12";
439 case NativeCUI:
440 return "_NtProcessStartup@4";
441 case Win32DLL:
442 return "_DllMain@12";
443 case Win32CUI:
444 return "_mainCRTStartup";
445 case Win32GUI:
446 return "_WinMainCRTStartup";
447 case KernelModeDriver:
448 return "_DriverEntry@8";
449 case BuildTool:
450 case StaticLibrary:
451 case ObjectLibrary:
452 case BootLoader:
453 case BootSector:
454 case Iso:
455 return "";
456 }
457 throw InvalidOperationException ( __FILE__,
458 __LINE__ );
459 }
460
461 string
462 Module::GetDefaultModuleBaseaddress () const
463 {
464 switch (type)
465 {
466 case Kernel:
467 return "0xc0000000";
468 case KernelModeDLL:
469 return "0x10000";
470 case NativeDLL:
471 return "0x10000";
472 case NativeCUI:
473 return "0x10000";
474 case Win32DLL:
475 return "0x10000";
476 case Win32CUI:
477 return "0x00400000";
478 case Win32GUI:
479 return "0x00400000";
480 case KernelModeDriver:
481 return "0x10000";
482 case BuildTool:
483 case StaticLibrary:
484 case ObjectLibrary:
485 case BootLoader:
486 case BootSector:
487 case Iso:
488 return "";
489 }
490 throw InvalidOperationException ( __FILE__,
491 __LINE__ );
492 }
493
494 bool
495 Module::HasImportLibrary () const
496 {
497 return importLibrary != NULL;
498 }
499
500 string
501 Module::GetTargetName () const
502 {
503 return name + extension;
504 }
505
506 string
507 Module::GetDependencyPath () const
508 {
509 if ( HasImportLibrary () )
510 {
511 return ssprintf ( "dk%snkm%slib%slib%s.a",
512 SSEP,
513 SSEP,
514 SSEP,
515 name.c_str () );
516 }
517 else
518 return GetPath();
519 }
520
521 string
522 Module::GetBasePath () const
523 {
524 return path;
525 }
526
527 string
528 Module::GetPath () const
529 {
530 return path + CSEP + GetTargetName ();
531 }
532
533 string
534 Module::GetPathWithPrefix ( const string& prefix ) const
535 {
536 return path + CSEP + prefix + GetTargetName ();
537 }
538
539 string
540 Module::GetTargets () const
541 {
542 if ( invocations.size () > 0 )
543 {
544 string targets ( "" );
545 for ( size_t i = 0; i < invocations.size (); i++ )
546 {
547 Invoke& invoke = *invocations[i];
548 if ( targets.length () > 0 )
549 targets += " ";
550 targets += invoke.GetTargets ();
551 }
552 return targets;
553 }
554 else
555 return GetPath ();
556 }
557
558 string
559 Module::GetInvocationTarget ( const int index ) const
560 {
561 return ssprintf ( "%s_invoke_%d",
562 name.c_str (),
563 index );
564 }
565
566 bool
567 Module::HasFileWithExtension (
568 const IfableData& data,
569 const std::string& extension ) const
570 {
571 size_t i;
572 for ( i = 0; i < data.files.size (); i++ )
573 {
574 File& file = *data.files[i];
575 string file_ext = GetExtension ( file.name );
576 if ( !stricmp ( file_ext.c_str (), extension.c_str () ) )
577 return true;
578 }
579 for ( i = 0; i < data.ifs.size (); i++ )
580 {
581 if ( HasFileWithExtension ( data.ifs[i]->data, extension ) )
582 return true;
583 }
584 return false;
585 }
586
587 void
588 Module::InvokeModule () const
589 {
590 for ( size_t i = 0; i < invocations.size (); i++ )
591 {
592 Invoke& invoke = *invocations[i];
593 string command = invoke.invokeModule->GetPath () + " " + invoke.GetParameters ();
594 printf ( "Executing '%s'\n\n", command.c_str () );
595 int exitcode = system ( command.c_str () );
596 if ( exitcode != 0 )
597 throw InvocationFailedException ( command,
598 exitcode );
599 }
600 }
601
602
603 File::File ( const string& _name, bool _first )
604 : name(_name), first(_first)
605 {
606 }
607
608 void
609 File::ProcessXML()
610 {
611 }
612
613
614 Library::Library ( const XMLElement& _node,
615 const Module& _module,
616 const string& _name )
617 : node(_node),
618 module(_module),
619 name(_name),
620 imported_module(_module.project.LocateModule(_name))
621 {
622 if ( module.name == name )
623 throw InvalidBuildFileException (
624 node.location,
625 "module '%s' cannot link against itself",
626 name.c_str() );
627 if ( !imported_module )
628 throw InvalidBuildFileException (
629 node.location,
630 "module '%s' trying to import non-existant module '%s'",
631 module.name.c_str(),
632 name.c_str() );
633 }
634
635 void
636 Library::ProcessXML()
637 {
638 if ( !module.project.LocateModule ( name ) )
639 throw InvalidBuildFileException (
640 node.location,
641 "module '%s' is trying to link against non-existant module '%s'",
642 module.name.c_str(),
643 name.c_str() );
644 }
645
646
647 Invoke::Invoke ( const XMLElement& _node,
648 const Module& _module )
649 : node (_node),
650 module (_module)
651 {
652 }
653
654 void
655 Invoke::ProcessXML()
656 {
657 const XMLAttribute* att = node.GetAttribute ( "module", false );
658 if (att == NULL)
659 invokeModule = &module;
660 else
661 {
662 invokeModule = module.project.LocateModule ( att->value );
663 if ( invokeModule == NULL )
664 throw InvalidBuildFileException (
665 node.location,
666 "module '%s' is trying to invoke non-existant module '%s'",
667 module.name.c_str(),
668 att->value.c_str() );
669 }
670
671 for ( size_t i = 0; i < node.subElements.size (); i++ )
672 ProcessXMLSubElement ( *node.subElements[i] );
673 }
674
675 void
676 Invoke::ProcessXMLSubElement ( const XMLElement& e )
677 {
678 bool subs_invalid = false;
679 if ( e.name == "input" )
680 {
681 for ( size_t i = 0; i < e.subElements.size (); i++ )
682 ProcessXMLSubElementInput ( *e.subElements[i] );
683 }
684 else if ( e.name == "output" )
685 {
686 for ( size_t i = 0; i < e.subElements.size (); i++ )
687 ProcessXMLSubElementOutput ( *e.subElements[i] );
688 }
689 if ( subs_invalid && e.subElements.size() > 0 )
690 throw InvalidBuildFileException ( e.location,
691 "<%s> cannot have sub-elements",
692 e.name.c_str() );
693 }
694
695 void
696 Invoke::ProcessXMLSubElementInput ( const XMLElement& e )
697 {
698 bool subs_invalid = false;
699 if ( e.name == "inputfile" && e.value.size () > 0 )
700 {
701 input.push_back ( new InvokeFile ( e, FixSeparator ( module.path + CSEP + e.value ) ) );
702 subs_invalid = true;
703 }
704 if ( subs_invalid && e.subElements.size() > 0 )
705 throw InvalidBuildFileException ( e.location,
706 "<%s> cannot have sub-elements",
707 e.name.c_str() );
708 }
709
710 void
711 Invoke::ProcessXMLSubElementOutput ( const XMLElement& e )
712 {
713 bool subs_invalid = false;
714 if ( e.name == "outputfile" && e.value.size () > 0 )
715 {
716 output.push_back ( new InvokeFile ( e, FixSeparator ( module.path + CSEP + e.value ) ) );
717 subs_invalid = true;
718 }
719 if ( subs_invalid && e.subElements.size() > 0 )
720 throw InvalidBuildFileException ( e.location,
721 "<%s> cannot have sub-elements",
722 e.name.c_str() );
723 }
724
725 string
726 Invoke::GetTargets () const
727 {
728 string targets ( "" );
729 for ( size_t i = 0; i < output.size (); i++ )
730 {
731 InvokeFile& file = *output[i];
732 if ( targets.length () > 0 )
733 targets += " ";
734 targets += NormalizeFilename ( file.name );
735 }
736 return targets;
737 }
738
739 string
740 Invoke::GetParameters () const
741 {
742 string parameters ( "" );
743 size_t i;
744 for ( i = 0; i < output.size (); i++ )
745 {
746 if ( parameters.length () > 0)
747 parameters += " ";
748 InvokeFile& invokeFile = *output[i];
749 if ( invokeFile.switches.length () > 0 )
750 {
751 parameters += invokeFile.switches;
752 parameters += " ";
753 }
754 parameters += invokeFile.name;
755 }
756
757 for ( i = 0; i < input.size (); i++ )
758 {
759 if ( parameters.length () > 0 )
760 parameters += " ";
761 InvokeFile& invokeFile = *input[i];
762 if ( invokeFile.switches.length () > 0 )
763 {
764 parameters += invokeFile.switches;
765 parameters += " ";
766 }
767 parameters += invokeFile.name ;
768 }
769
770 return parameters;
771 }
772
773
774 InvokeFile::InvokeFile ( const XMLElement& _node,
775 const string& _name )
776 : node (_node),
777 name (_name)
778 {
779 const XMLAttribute* att = _node.GetAttribute ( "switches", false );
780 if (att != NULL)
781 switches = att->value;
782 else
783 switches = "";
784 }
785
786 void
787 InvokeFile::ProcessXML()
788 {
789 }
790
791
792 Dependency::Dependency ( const XMLElement& _node,
793 const Module& _module )
794 : node (_node),
795 module (_module),
796 dependencyModule (NULL)
797 {
798 }
799
800 void
801 Dependency::ProcessXML()
802 {
803 dependencyModule = module.project.LocateModule ( node.value );
804 if ( dependencyModule == NULL )
805 throw InvalidBuildFileException ( node.location,
806 "module '%s' depend on non-existant module '%s'",
807 module.name.c_str(),
808 node.value.c_str() );
809 }
810
811
812 ImportLibrary::ImportLibrary ( const XMLElement& _node,
813 const Module& _module )
814 : node (_node),
815 module (_module)
816 {
817 const XMLAttribute* att = _node.GetAttribute ( "basename", false );
818 if (att != NULL)
819 basename = att->value;
820 else
821 basename = module.name;
822
823 att = _node.GetAttribute ( "definition", true );
824 assert (att);
825 definition = FixSeparator(att->value);
826 }
827
828
829 If::If ( const XMLElement& node_,
830 const Project& project_,
831 const Module* module_ )
832 : node(node_), project(project_), module(module_)
833 {
834 const XMLAttribute* att;
835
836 att = node.GetAttribute ( "property", true );
837 assert(att);
838 property = att->value;
839
840 att = node.GetAttribute ( "value", true );
841 assert(att);
842 value = att->value;
843 }
844
845 If::~If ()
846 {
847 }
848
849 void
850 If::ProcessXML()
851 {
852 }
853
854
855 Property::Property ( const XMLElement& node_,
856 const Project& project_,
857 const Module* module_ )
858 : node(node_), project(project_), module(module_)
859 {
860 const XMLAttribute* att;
861
862 att = node.GetAttribute ( "name", true );
863 assert(att);
864 name = att->value;
865
866 att = node.GetAttribute ( "value", true );
867 assert(att);
868 value = att->value;
869 }
870
871 void
872 Property::ProcessXML()
873 {
874 }
875
876
877 PchFile::PchFile (
878 const XMLElement& node_,
879 const Module& module_,
880 const string& header_ )
881 : node(node_), module(module_), header(header_)
882 {
883 }
884
885 void
886 PchFile::ProcessXML()
887 {
888 }