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