Implement linkerscript element
[reactos.git] / reactos / tools / rbuild / rbuild.h
1 /*
2 * Copyright (C) 2005 Casper S. Hornstrup
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 */
18 #ifndef __RBUILD_H
19 #define __RBUILD_H
20
21 #include "pch.h"
22
23 #ifdef WIN32
24 #include <direct.h>
25 #include <io.h>
26 #endif/*WIN32*/
27 #include <sys/stat.h>
28 #include <time.h>
29 #ifdef _MSC_VER
30 #include <sys/utime.h>
31 #else/*_MSC_VER*/
32 #include <utime.h>
33 #ifdef WIN32
34 #include <process.h>
35 #endif/*WIN32*/
36 #endif/*_MSC_VER*/
37
38 #include "ssprintf.h"
39 #include "exception.h"
40 #include "XML.h"
41
42 typedef std::vector<std::string> string_list;
43
44 #ifdef WIN32
45 #define EXEPREFIX ""
46 #define EXEPOSTFIX ".exe"
47 #define CSEP '\\'
48 #define CBAD_SEP '/'
49 #define SSEP "\\"
50 #define SBAD_SEP "/"
51 #else
52 #define EXEPREFIX "./"
53 #define EXEPOSTFIX ""
54 #define CSEP '/'
55 #define CBAD_SEP '\\'
56 #define SSEP "/"
57 #define SBAD_SEP "\\"
58 #endif
59
60 #define MS_VS_DEF_VERSION "7.10"
61
62 class Project;
63 class IfableData;
64 class Module;
65 class Include;
66 class Define;
67 class File;
68 class Library;
69 class Invoke;
70 class InvokeFile;
71 class Dependency;
72 class ImportLibrary;
73 class If;
74 class CompilerFlag;
75 class LinkerFlag;
76 class LinkerScript;
77 class Property;
78 class TestSupportCode;
79 class WineResource;
80 class AutomaticDependency;
81 class Bootstrap;
82 class CDFile;
83 class InstallFile;
84 class PchFile;
85 class StubbedComponent;
86 class StubbedSymbol;
87
88 class SourceFileTest;
89
90
91 class Configuration
92 {
93 public:
94 Configuration ();
95 ~Configuration ();
96 bool Verbose;
97 bool CleanAsYouGo;
98 bool AutomaticDependencies;
99 bool CheckDependenciesForModuleOnly;
100 std::string CheckDependenciesForModuleOnlyModule;
101 std::string VSProjectVersion;
102 bool MakeHandlesInstallDirectories;
103 bool GenerateProxyMakefilesInSourceTree;
104 };
105
106 class Environment
107 {
108 public:
109 static std::string GetVariable ( const std::string& name );
110 static std::string GetIntermediatePath ();
111 static std::string GetOutputPath ();
112 static std::string GetInstallPath ();
113 static std::string GetEnvironmentVariablePathOrDefault ( const std::string& name,
114 const std::string& defaultValue );
115 };
116
117 class FileSupportCode
118 {
119 public:
120 static void WriteIfChanged ( char* outbuf,
121 std::string filename );
122 };
123
124 class IfableData
125 {
126 public:
127 std::vector<File*> files;
128 std::vector<Include*> includes;
129 std::vector<Define*> defines;
130 std::vector<Library*> libraries;
131 std::vector<Property*> properties;
132 std::vector<CompilerFlag*> compilerFlags;
133 std::vector<If*> ifs;
134
135 ~IfableData();
136 void ProcessXML();
137 };
138
139 class Project
140 {
141 std::string xmlfile;
142 XMLElement *node, *head;
143 public:
144 std::string name;
145 std::string makefile;
146 XMLIncludes xmlbuildfiles;
147 std::vector<Module*> modules;
148 std::vector<LinkerFlag*> linkerFlags;
149 std::vector<CDFile*> cdfiles;
150 std::vector<InstallFile*> installfiles;
151 IfableData non_if_data;
152
153 Project ( const std::string& filename );
154 ~Project ();
155 void WriteConfigurationFile ();
156 void ExecuteInvocations ();
157 void ProcessXML ( const std::string& path );
158 Module* LocateModule ( const std::string& name );
159 const Module* LocateModule ( const std::string& name ) const;
160 std::string GetProjectFilename () const;
161 std::string ResolveProperties ( const std::string& s ) const;
162 private:
163 std::string ResolveNextProperty ( std::string& s ) const;
164 const Property* LookupProperty ( const std::string& name ) const;
165 void SetConfigurationOption ( char* s,
166 std::string name,
167 std::string* alternativeName );
168 void SetConfigurationOption ( char* s,
169 std::string name );
170 void ReadXml ();
171 void ProcessXMLSubElement ( const XMLElement& e,
172 const std::string& path,
173 If* pIf = NULL );
174
175 // disable copy semantics
176 Project ( const Project& );
177 Project& operator = ( const Project& );
178 };
179
180
181 enum ModuleType
182 {
183 BuildTool = 0,
184 StaticLibrary = 1,
185 ObjectLibrary = 2,
186 Kernel = 3,
187 KernelModeDLL = 4,
188 KernelModeDriver = 5,
189 NativeDLL = 6,
190 NativeCUI = 7,
191 Win32DLL = 8,
192 Win32CUI = 9,
193 Win32GUI = 10,
194 BootLoader = 11,
195 BootSector = 12,
196 Iso = 13,
197 LiveIso = 14,
198 Test = 15,
199 RpcServer = 16,
200 RpcClient = 17,
201 Alias = 18
202 };
203
204 enum HostType
205 {
206 HostFalse,
207 HostDefault,
208 HostTrue
209 };
210
211 class Module
212 {
213 public:
214 const Project& project;
215 const XMLElement& node;
216 std::string xmlbuildFile;
217 std::string name;
218 std::string guid;
219 std::string extension;
220 std::string entrypoint;
221 std::string baseaddress;
222 std::string path;
223 ModuleType type;
224 ImportLibrary* importLibrary;
225 bool mangledSymbols;
226 bool isUnicode;
227 Bootstrap* bootstrap;
228 IfableData non_if_data;
229 std::vector<Invoke*> invocations;
230 std::vector<Dependency*> dependencies;
231 std::vector<CompilerFlag*> compilerFlags;
232 std::vector<LinkerFlag*> linkerFlags;
233 std::vector<StubbedComponent*> stubbedComponents;
234 LinkerScript* linkerScript;
235 PchFile* pch;
236 bool cplusplus;
237 std::string prefix;
238 HostType host;
239 std::string installBase;
240 std::string installName;
241 std::string aliasedModuleName;
242 bool useWRC;
243 bool allowWarnings;
244 bool enabled;
245
246 Module ( const Project& project,
247 const XMLElement& moduleNode,
248 const std::string& modulePath );
249 ~Module ();
250 ModuleType GetModuleType ( const std::string& location,
251 const XMLAttribute& attribute );
252 bool HasImportLibrary () const;
253 bool IsDLL () const;
254 bool GenerateInOutputTree () const;
255 std::string GetTargetName () const; // "foo.exe"
256 std::string GetDependencyPath () const; // "path/foo.exe" or "path/libfoo.a"
257 std::string GetBasePath () const; // "path"
258 std::string GetPath () const; // "path/foo.exe"
259 std::string GetPathWithPrefix ( const std::string& prefix ) const; // "path/prefixfoo.exe"
260 void GetTargets ( string_list& ) const;
261 std::string GetInvocationTarget ( const int index ) const;
262 bool HasFileWithExtension ( const IfableData&, const std::string& extension ) const;
263 void InvokeModule () const;
264 void ProcessXML ();
265 void GetSourceFilenames ( string_list& list,
266 bool includeGeneratedFiles ) const;
267 private:
268 std::string GetDefaultModuleExtension () const;
269 std::string GetDefaultModuleEntrypoint () const;
270 std::string GetDefaultModuleBaseaddress () const;
271 void ProcessXMLSubElement ( const XMLElement& e,
272 const std::string& path,
273 If* pIf = NULL );
274 };
275
276
277 class Include
278 {
279 public:
280 const Project& project;
281 const Module* module;
282 const XMLElement* node;
283 const Module* baseModule;
284 std::string directory;
285 std::string basePath;
286
287 Include ( const Project& project,
288 const XMLElement* includeNode );
289 Include ( const Project& project,
290 const Module* module,
291 const XMLElement* includeNode );
292 Include ( const Project& project,
293 std::string directory,
294 std::string basePath );
295 ~Include ();
296 void ProcessXML();
297 private:
298 };
299
300
301 class Define
302 {
303 public:
304 const Project& project;
305 const Module* module;
306 const XMLElement& node;
307 std::string name;
308 std::string value;
309
310 Define ( const Project& project,
311 const XMLElement& defineNode );
312 Define ( const Project& project,
313 const Module* module,
314 const XMLElement& defineNode );
315 ~Define();
316 void ProcessXML();
317 private:
318 void Initialize();
319 };
320
321
322 class File
323 {
324 public:
325 std::string name;
326 bool first;
327 std::string switches;
328 bool isPreCompiledHeader;
329
330 File ( const std::string& _name,
331 bool _first,
332 std::string _switches,
333 bool _isPreCompiledHeader );
334
335 void ProcessXML();
336 bool IsGeneratedFile () const;
337 };
338
339
340 class Library
341 {
342 public:
343 const XMLElement& node;
344 const Module& module;
345 std::string name;
346 const Module* importedModule;
347
348 Library ( const XMLElement& _node,
349 const Module& _module,
350 const std::string& _name );
351
352 void ProcessXML();
353 };
354
355
356 class Invoke
357 {
358 public:
359 const XMLElement& node;
360 const Module& module;
361 const Module* invokeModule;
362 std::vector<InvokeFile*> input;
363 std::vector<InvokeFile*> output;
364
365 Invoke ( const XMLElement& _node,
366 const Module& _module );
367
368 void ProcessXML();
369 void GetTargets ( string_list& targets ) const;
370 std::string GetParameters () const;
371 private:
372 void ProcessXMLSubElement ( const XMLElement& e );
373 void ProcessXMLSubElementInput ( const XMLElement& e );
374 void ProcessXMLSubElementOutput ( const XMLElement& e );
375 };
376
377
378 class InvokeFile
379 {
380 public:
381 const XMLElement& node;
382 std::string name;
383 std::string switches;
384
385 InvokeFile ( const XMLElement& _node,
386 const std::string& _name );
387
388 void ProcessXML ();
389 };
390
391
392 class Dependency
393 {
394 public:
395 const XMLElement& node;
396 const Module& module;
397 const Module* dependencyModule;
398
399 Dependency ( const XMLElement& _node,
400 const Module& _module );
401
402 void ProcessXML();
403 };
404
405
406 class ImportLibrary
407 {
408 public:
409 const XMLElement& node;
410 const Module& module;
411 std::string basename;
412 std::string definition;
413
414 ImportLibrary ( const XMLElement& _node,
415 const Module& module );
416
417 void ProcessXML ();
418 };
419
420
421 class If
422 {
423 public:
424 const XMLElement& node;
425 const Project& project;
426 const Module* module;
427 const bool negated;
428 std::string property, value;
429 IfableData data;
430
431 If ( const XMLElement& node_,
432 const Project& project_,
433 const Module* module_,
434 const bool negated_ = false );
435 ~If();
436
437 void ProcessXML();
438 };
439
440
441 class CompilerFlag
442 {
443 public:
444 const Project& project;
445 const Module* module;
446 const XMLElement& node;
447 std::string flag;
448
449 CompilerFlag ( const Project& project,
450 const XMLElement& compilerFlagNode );
451 CompilerFlag ( const Project& project,
452 const Module* module,
453 const XMLElement& compilerFlagNode );
454 ~CompilerFlag ();
455 void ProcessXML();
456 private:
457 void Initialize();
458 };
459
460
461 class LinkerFlag
462 {
463 public:
464 const Project& project;
465 const Module* module;
466 const XMLElement& node;
467 std::string flag;
468
469 LinkerFlag ( const Project& project,
470 const XMLElement& linkerFlagNode );
471 LinkerFlag ( const Project& project,
472 const Module* module,
473 const XMLElement& linkerFlagNode );
474 ~LinkerFlag ();
475 void ProcessXML();
476 private:
477 void Initialize();
478 };
479
480
481 class LinkerScript
482 {
483 public:
484 const Project& project;
485 const Module* module;
486 const XMLElement& node;
487 const Module* baseModule;
488 std::string directory;
489 std::string basePath;
490
491 LinkerScript ( const Project& project,
492 const Module* module,
493 const XMLElement& node );
494 ~LinkerScript ();
495 void ProcessXML();
496 };
497
498
499 class Property
500 {
501 public:
502 const XMLElement& node;
503 const Project& project;
504 const Module* module;
505 std::string name, value;
506
507 Property ( const XMLElement& node_,
508 const Project& project_,
509 const Module* module_ );
510
511 void ProcessXML();
512 };
513
514
515 class TestSupportCode
516 {
517 public:
518 const Project& project;
519
520 TestSupportCode ( const Project& project );
521 ~TestSupportCode ();
522 void GenerateTestSupportCode ( bool verbose );
523 private:
524 bool IsTestModule ( const Module& module );
525 void GenerateTestSupportCodeForModule ( Module& module,
526 bool verbose );
527 std::string GetHooksFilename ( Module& module );
528 char* WriteStubbedSymbolToHooksFile ( char* buffer,
529 const StubbedComponent& component,
530 const StubbedSymbol& symbol );
531 char* WriteStubbedComponentToHooksFile ( char* buffer,
532 const StubbedComponent& component );
533 void WriteHooksFile ( Module& module );
534 std::string GetStubsFilename ( Module& module );
535 char* WriteStubbedSymbolToStubsFile ( char* buffer,
536 const StubbedComponent& component,
537 const StubbedSymbol& symbol,
538 int stubIndex );
539 char* WriteStubbedComponentToStubsFile ( char* buffer,
540 const StubbedComponent& component,
541 int* stubIndex );
542 void WriteStubsFile ( Module& module );
543 std::string GetStartupFilename ( Module& module );
544 bool IsUnknownCharacter ( char ch );
545 std::string GetTestDispatcherName ( std::string filename );
546 bool IsTestFile ( std::string& filename ) const;
547 void GetSourceFilenames ( string_list& list,
548 Module& module ) const;
549 char* WriteTestDispatcherPrototypesToStartupFile ( char* buffer,
550 Module& module );
551 char* WriteRegisterTestsFunctionToStartupFile ( char* buffer,
552 Module& module );
553 void WriteStartupFile ( Module& module );
554 };
555
556
557 class WineResource
558 {
559 public:
560 const Project& project;
561 std::string bin2res;
562
563 WineResource ( const Project& project,
564 std::string bin2res );
565 ~WineResource ();
566 void UnpackResources ( bool verbose );
567 private:
568 bool IsSpecFile ( const File& file );
569 bool IsWineModule ( const Module& module );
570 bool IsResourceFile ( const File& file );
571 std::string GetResourceFilename ( const Module& module );
572 void UnpackResourcesInModule ( Module& module,
573 bool verbose );
574 };
575
576
577 class SourceFile
578 {
579 public:
580 SourceFile ( AutomaticDependency* automaticDependency,
581 const Module& module,
582 const std::string& filename,
583 SourceFile* parent,
584 bool isNonAutomaticDependency );
585 SourceFile* ParseFile ( const std::string& normalizedFilename );
586 void Parse ();
587 std::string Location () const;
588 std::vector<SourceFile*> files;
589 AutomaticDependency* automaticDependency;
590 const Module& module;
591 std::string filename;
592 std::string filenamePart;
593 std::string directoryPart;
594 std::vector<SourceFile*> parents; /* List of files, this file is included from */
595 bool isNonAutomaticDependency;
596 std::string cachedDependencies;
597 time_t lastWriteTime;
598 time_t youngestLastWriteTime; /* Youngest last write time of this file and all children */
599 SourceFile* youngestFile;
600 private:
601 void GetDirectoryAndFilenameParts ();
602 void Close ();
603 void Open ();
604 void SkipWhitespace ();
605 bool ReadInclude ( std::string& filename,
606 bool& searchCurrentDirectory,
607 bool& includeNext );
608 bool IsIncludedFrom ( const std::string& normalizedFilename );
609 SourceFile* GetParentSourceFile ();
610 bool CanProcessFile ( const std::string& extension );
611 bool IsParentOf ( const SourceFile* parent,
612 const SourceFile* child );
613 std::string buf;
614 const char *p;
615 const char *end;
616 };
617
618
619 class AutomaticDependency
620 {
621 friend class SourceFileTest;
622 public:
623 const Project& project;
624
625 AutomaticDependency ( const Project& project );
626 ~AutomaticDependency ();
627 std::string GetFilename ( const std::string& filename );
628 bool LocateIncludedFile ( const std::string& directory,
629 const std::string& includedFilename,
630 std::string& resolvedFilename );
631 bool LocateIncludedFile ( SourceFile* sourceFile,
632 const Module& module,
633 const std::string& includedFilename,
634 bool searchCurrentDirectory,
635 bool includeNext,
636 std::string& resolvedFilename );
637 SourceFile* RetrieveFromCacheOrParse ( const Module& module,
638 const std::string& filename,
639 SourceFile* parentSourceFile );
640 SourceFile* RetrieveFromCache ( const std::string& filename );
641 void CheckAutomaticDependencies ( bool verbose );
642 void CheckAutomaticDependenciesForModule ( Module& module,
643 bool verbose );
644 private:
645 void GetModulesToCheck ( Module& module, std::vector<const Module*>& modules );
646 void CheckAutomaticDependencies ( const Module& module,
647 bool verbose );
648 void CheckAutomaticDependenciesForFile ( SourceFile* sourceFile );
649 void GetIncludeDirectories ( std::vector<Include*>& includes,
650 const Module& module,
651 Include& currentDirectory,
652 bool searchCurrentDirectory );
653 void GetModuleFiles ( const Module& module,
654 std::vector<File*>& files ) const;
655 void ParseFiles ();
656 void ParseFiles ( const Module& module );
657 void ParseFile ( const Module& module,
658 const File& file );
659 std::map<std::string, SourceFile*> sourcefile_map;
660 };
661
662
663 class Bootstrap
664 {
665 public:
666 const Project& project;
667 const Module* module;
668 const XMLElement& node;
669 std::string base;
670 std::string nameoncd;
671
672 Bootstrap ( const Project& project,
673 const Module* module,
674 const XMLElement& bootstrapNode );
675 ~Bootstrap ();
676 void ProcessXML();
677 private:
678 bool IsSupportedModuleType ( ModuleType type );
679 void Initialize();
680 };
681
682
683 class CDFile
684 {
685 public:
686 const Project& project;
687 const XMLElement& node;
688 std::string name;
689 std::string base;
690 std::string nameoncd;
691 std::string path;
692
693 CDFile ( const Project& project,
694 const XMLElement& bootstrapNode,
695 const std::string& path );
696 ~CDFile ();
697 void ProcessXML();
698 std::string GetPath () const;
699 };
700
701
702 class InstallFile
703 {
704 public:
705 const Project& project;
706 const XMLElement& node;
707 std::string name;
708 std::string base;
709 std::string newname;
710 std::string path;
711
712 InstallFile ( const Project& project,
713 const XMLElement& bootstrapNode,
714 const std::string& path );
715 ~InstallFile ();
716 void ProcessXML ();
717 std::string GetPath () const;
718 };
719
720
721 class PchFile
722 {
723 public:
724 const XMLElement& node;
725 const Module& module;
726 File file;
727
728 PchFile (
729 const XMLElement& node,
730 const Module& module,
731 const File file );
732 void ProcessXML();
733 };
734
735
736 class StubbedComponent
737 {
738 public:
739 const Module* module;
740 const XMLElement& node;
741 std::string name;
742 std::vector<StubbedSymbol*> symbols;
743
744 StubbedComponent ( const Module* module_,
745 const XMLElement& stubbedComponentNode );
746 ~StubbedComponent ();
747 void ProcessXML ();
748 void ProcessXMLSubElement ( const XMLElement& e );
749 };
750
751
752 class StubbedSymbol
753 {
754 public:
755 const XMLElement& node;
756 std::string symbol;
757 std::string newname;
758 std::string strippedName;
759
760 StubbedSymbol ( const XMLElement& stubbedSymbolNode );
761 ~StubbedSymbol ();
762 void ProcessXML();
763 private:
764 std::string StripSymbol ( std::string symbol );
765 };
766
767 extern std::string
768 Right ( const std::string& s, size_t n );
769
770 extern std::string
771 Replace ( const std::string& s, const std::string& find, const std::string& with );
772
773 extern std::string
774 FixSeparator ( const std::string& s );
775
776 extern std::string
777 DosSeparator ( const std::string& s );
778
779 extern std::string
780 ReplaceExtension (
781 const std::string& filename,
782 const std::string& newExtension );
783
784 extern std::string
785 GetSubPath (
786 const std::string& location,
787 const std::string& path,
788 const std::string& att_value );
789
790 extern std::string
791 GetExtension ( const std::string& filename );
792
793 extern std::string
794 GetDirectory ( const std::string& filename );
795
796 extern std::string
797 GetFilename ( const std::string& filename );
798
799 extern std::string
800 NormalizeFilename ( const std::string& filename );
801
802 #endif /* __RBUILD_H */