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