[RTL]
[reactos.git] / reactos / tools / rbuild / backend / mingw / modulehandler.cpp
1 /*
2 * Copyright (C) 2005 Casper S. Hornstrup
3 * 2007-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 along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19 #include "../../pch.h"
20 #include <assert.h>
21 #include <algorithm>
22
23 #include "../../rbuild.h"
24 #include "mingw.h"
25 #include "modulehandler.h"
26 #include "rule.h"
27
28 using std::set;
29 using std::string;
30 using std::vector;
31
32 #define CLEAN_FILE(f) clean_files.push_back ( (f).name.length () > 0 ? backend->GetFullName ( f ) : backend->GetFullPath ( f ) );
33 #define IsStaticLibrary( module ) ( ( module.type == StaticLibrary ) || ( module.type == HostStaticLibrary ) )
34
35 MingwBackend*
36 MingwModuleHandler::backend = NULL;
37 FILE*
38 MingwModuleHandler::fMakefile = NULL;
39
40 string
41 PrefixFilename (
42 const string& filename,
43 const string& prefix )
44 {
45 if ( !prefix.length() )
46 return filename;
47 string out;
48 const char* pfilename = filename.c_str();
49 const char* p1 = strrchr ( pfilename, '/' );
50 const char* p2 = strrchr ( pfilename, '\\' );
51 if ( p1 || p2 )
52 {
53 if ( p2 > p1 )
54 p1 = p2;
55 out += string(pfilename,p1-pfilename) + cSep;
56 pfilename = p1 + 1;
57 }
58 out += prefix + pfilename;
59 return out;
60 }
61
62 string
63 GetTargetMacro ( const Module& module, bool with_dollar )
64 {
65 string s ( module.name );
66 s += "_TARGET";
67 if ( with_dollar )
68 return ssprintf ( "$(%s)", s.c_str() );
69 return s;
70 }
71
72 MingwModuleHandler::MingwModuleHandler (
73 const Module& module_ )
74
75 : module(module_)
76 {
77 use_pch = false;
78 }
79
80 MingwModuleHandler::~MingwModuleHandler()
81 {
82 }
83
84 /*static*/ void
85 MingwModuleHandler::SetBackend ( MingwBackend* backend_ )
86 {
87 backend = backend_;
88 }
89
90 /*static*/ void
91 MingwModuleHandler::SetMakefile ( FILE* f )
92 {
93 fMakefile = f;
94 }
95
96 void
97 MingwModuleHandler::EnablePreCompiledHeaderSupport ()
98 {
99 use_pch = true;
100 }
101
102 /*static*/ const FileLocation*
103 MingwModuleHandler::PassThruCacheDirectory (const FileLocation* file )
104 {
105 switch ( file->directory )
106 {
107 case SourceDirectory:
108 break;
109 case IntermediateDirectory:
110 backend->AddDirectoryTarget ( file->relative_path, backend->intermediateDirectory );
111 break;
112 case OutputDirectory:
113 backend->AddDirectoryTarget ( file->relative_path, backend->outputDirectory );
114 break;
115 case InstallDirectory:
116 backend->AddDirectoryTarget ( file->relative_path, backend->installDirectory );
117 break;
118 default:
119 throw InvalidOperationException ( __FILE__,
120 __LINE__,
121 "Invalid directory %d.",
122 file->directory );
123 }
124
125 return file;
126 }
127
128 /* caller needs to delete the returned object */
129 const FileLocation*
130 MingwModuleHandler::GetTargetFilename (
131 const Module& module,
132 string_list* pclean_files )
133 {
134 FileLocation *target = new FileLocation ( *module.output );
135 if ( pclean_files )
136 {
137 string_list& clean_files = *pclean_files;
138 CLEAN_FILE ( *target );
139 }
140 return target;
141 }
142
143 /* caller needs to delete the returned object */
144 const FileLocation*
145 MingwModuleHandler::GetImportLibraryFilename (
146 const Module& module,
147 string_list* pclean_files,
148 bool delayimp )
149 {
150 FileLocation *target;
151
152 if (module.HasImportLibrary())
153 {
154 if (delayimp)
155 {
156 target = new FileLocation ( *module.delayImportLibrary->target );
157 }
158 else
159 target = new FileLocation ( *module.importLibrary->target );
160 }
161 else
162 target = new FileLocation ( *module.dependency );
163
164 if ( pclean_files )
165 {
166 string_list& clean_files = *pclean_files;
167 CLEAN_FILE ( *target );
168 }
169 return target;
170 }
171
172 /* caller needs to delete the returned object */
173 MingwModuleHandler*
174 MingwModuleHandler::InstanciateHandler (
175 const Module& module,
176 MingwBackend* backend )
177 {
178 MingwModuleHandler* handler;
179 switch ( module.type )
180 {
181 case StaticLibrary:
182 case HostStaticLibrary:
183 case ObjectLibrary:
184 case RpcServer:
185 case RpcClient:
186 case RpcProxy:
187 case MessageHeader:
188 case IdlHeader:
189 case IdlInterface:
190 case EmbeddedTypeLib:
191 case BootSector:
192 handler = new MingwModuleHandler( module );
193 break;
194 case BuildTool:
195 handler = new MingwBuildToolModuleHandler ( module );
196 break;
197 case Kernel:
198 handler = new MingwKernelModuleHandler ( module );
199 break;
200 case NativeCUI:
201 handler = new MingwNativeCUIModuleHandler ( module );
202 break;
203 case Win32CUI:
204 handler = new MingwWin32CUIModuleHandler ( module );
205 break;
206 case Win32SCR:
207 case Win32GUI:
208 handler = new MingwWin32GUIModuleHandler ( module );
209 break;
210 case KeyboardLayout:
211 case KernelModeDLL:
212 case KernelModeDriver:
213 handler = new MingwKernelModeDLLModuleHandler ( module );
214 break;
215 case NativeDLL:
216 handler = new MingwNativeDLLModuleHandler ( module );
217 break;
218 case Win32DLL:
219 handler = new MingwWin32DLLModuleHandler ( module );
220 break;
221 case Win32OCX:
222 handler = new MingwWin32OCXModuleHandler ( module );
223 break;
224 case BootLoader:
225 handler = new MingwBootLoaderModuleHandler ( module );
226 break;
227 case BootProgram:
228 handler = new MingwBootProgramModuleHandler ( module );
229 break;
230 case Iso:
231 handler = new MingwIsoModuleHandler ( module );
232 break;
233 case LiveIso:
234 handler = new MingwLiveIsoModuleHandler ( module );
235 break;
236 case Test:
237 handler = new MingwTestModuleHandler ( module );
238 break;
239 case Alias:
240 handler = new MingwAliasModuleHandler ( module );
241 break;
242 case Cabinet:
243 handler = new MingwCabinetModuleHandler ( module );
244 break;
245 case ElfExecutable:
246 handler = new MingwElfExecutableModuleHandler ( module );
247 break;
248 default:
249 throw UnknownModuleTypeException (
250 module.node.location,
251 module.type );
252 break;
253 }
254 return handler;
255 }
256
257 string
258 MingwModuleHandler::GetWorkingDirectory () const
259 {
260 return ".";
261 }
262
263 string
264 MingwModuleHandler::GetBasename ( const string& filename ) const
265 {
266 size_t index = filename.find_last_of ( '.' );
267 if ( index != string::npos )
268 return filename.substr ( 0, index );
269 return "";
270 }
271
272 string
273 MingwModuleHandler::GetCompilationUnitDependencies (
274 const CompilationUnit& compilationUnit ) const
275 {
276 if ( compilationUnit.GetFiles ().size () <= 1 )
277 return "";
278 vector<string> sourceFiles;
279 for ( size_t i = 0; i < compilationUnit.GetFiles ().size (); i++ )
280 {
281 const File& file = *compilationUnit.GetFiles ()[i];
282 sourceFiles.push_back ( backend->GetFullName ( file.file ) );
283 }
284 return string ( " " ) + backend->v2s ( sourceFiles, 10 );
285 }
286
287 /* caller needs to delete the returned object */
288 const FileLocation*
289 MingwModuleHandler::GetModuleArchiveFilename () const
290 {
291 if ( IsStaticLibrary ( module ) )
292 return GetTargetFilename ( module, NULL );
293 return NULL;
294 }
295
296 /*static*/ bool
297 MingwModuleHandler::ReferenceObjects (
298 const Module& module )
299 {
300 if ( module.type == ObjectLibrary )
301 return true;
302 if ( module.type == RpcServer )
303 return true;
304 if ( module.type == RpcClient )
305 return true;
306 if ( module.type == RpcProxy )
307 return true;
308 if ( module.type == IdlHeader )
309 return true;
310 if ( module.type == IdlInterface )
311 return true;
312 if ( module.type == MessageHeader)
313 return true;
314 return false;
315 }
316
317 void
318 MingwModuleHandler::OutputCopyCommand ( const FileLocation& source,
319 const FileLocation& destination )
320 {
321 fprintf ( fMakefile, "# OUTPUT COPY COMMAND\n" );
322 fprintf ( fMakefile,
323 "\t$(ECHO_CP)\n" );
324 fprintf ( fMakefile,
325 "\t${cp} \"%s\" \"%s\" 1>$(NUL)\n",
326 backend->GetFullName ( source ).c_str (),
327 backend->GetFullName ( *PassThruCacheDirectory ( &destination ) ).c_str () );
328 }
329
330 void
331 MingwModuleHandler::OutputCopyCommandSingle ( const FileLocation& source,
332 const FileLocation& destination )
333 {
334 fprintf ( fMakefile,
335 "%s : %s\n",
336 backend->GetFullNamePrefixSpaces ( *PassThruCacheDirectory ( &destination ) ).c_str (),
337 backend->GetFullNamePrefixSpaces ( source ).c_str () );
338 fprintf ( fMakefile,
339 "\t$(ECHO_CP)\n" );
340 fprintf ( fMakefile,
341 "\t${cp} \"%s\" \"%s\" 1>$(NUL)\n",
342 backend->GetFullName ( source ).c_str (),
343 backend->GetFullName ( *PassThruCacheDirectory ( &destination ) ).c_str () );
344 }
345
346 string
347 MingwModuleHandler::GetImportLibraryDependency (
348 const Module& importedModule,
349 bool delayimp )
350 {
351 string dep;
352 if ( ReferenceObjects ( importedModule ) )
353 {
354 const vector<CompilationUnit*>& compilationUnits = importedModule.non_if_data.compilationUnits;
355 size_t i;
356
357 dep = GetTargetMacro ( importedModule );
358 for ( i = 0; i < compilationUnits.size (); i++ )
359 {
360 CompilationUnit& compilationUnit = *compilationUnits[i];
361 const FileLocation& compilationName = compilationUnit.GetFilename ();
362 const FileLocation *objectFilename = GetObjectFilename ( &compilationName, importedModule );
363 if ( GetExtension ( *objectFilename ) == ".h" )
364 dep += ssprintf ( " $(%s_HEADERS)", importedModule.name.c_str () );
365 else if ( GetExtension ( *objectFilename ) == ".rc" )
366 dep += ssprintf ( " $(%s_MCHEADERS)", importedModule.name.c_str () );
367 delete objectFilename;
368 }
369 }
370 else
371 {
372 const FileLocation *library_target = GetImportLibraryFilename ( importedModule, NULL, delayimp );
373 dep = backend->GetFullName ( *library_target );
374 delete library_target;
375 }
376
377 if ( IsStaticLibrary ( importedModule ) || importedModule.type == ObjectLibrary )
378 {
379 const std::vector<Library*>& libraries = importedModule.non_if_data.libraries;
380
381 for ( size_t i = 0; i < libraries.size (); ++ i )
382 {
383 dep += " ";
384 dep += GetImportLibraryDependency ( *libraries[i]->importedModule, libraries[i]->delayimp );
385 }
386 }
387
388 return dep;
389 }
390
391 void
392 MingwModuleHandler::GetTargets ( const Module& dependencyModule,
393 string_list& targets )
394 {
395 if ( dependencyModule.invocations.size () > 0 )
396 {
397 for ( size_t i = 0; i < dependencyModule.invocations.size (); i++ )
398 {
399 Invoke& invoke = *dependencyModule.invocations[i];
400 invoke.GetTargets ( targets );
401 }
402 }
403 else
404 targets.push_back ( GetImportLibraryDependency ( dependencyModule, false ) );
405 }
406
407 void
408 MingwModuleHandler::GetModuleDependencies (
409 string_list& dependencies )
410 {
411 size_t iend = module.dependencies.size ();
412
413 if ( iend == 0 )
414 return;
415
416 for ( size_t i = 0; i < iend; i++ )
417 {
418 const Dependency& dependency = *module.dependencies[i];
419 const Module& dependencyModule = *dependency.dependencyModule;
420 GetTargets ( dependencyModule,
421 dependencies );
422 }
423 vector<FileLocation> v;
424 GetDefinitionDependencies ( v );
425
426 for ( size_t i = 0; i < v.size (); i++ )
427 {
428 const FileLocation& file = v[i];
429 dependencies.push_back ( backend->GetFullName ( file ) );
430 }
431 }
432
433 /* caller needs to delete the returned object */
434 const FileLocation*
435 MingwModuleHandler::GetObjectFilename (
436 const FileLocation* sourceFile,
437 const Module& module ) const
438 {
439 DirectoryLocation destination_directory;
440 string newExtension;
441 string extension = GetExtension ( *sourceFile );
442
443 if ( module.type == BootSector )
444 return new FileLocation ( *module.output );
445 else if (extension == ".rc")
446 newExtension = "_" + module.name + ".coff";
447 else if (extension == ".mc")
448 newExtension = ".rc";
449 else if (extension == ".idl")
450 {
451 if ( module.type == RpcServer )
452 newExtension = "_s.o";
453 else if ( module.type == RpcClient )
454 newExtension = "_c.o";
455 else if ( module.type == RpcProxy )
456 newExtension = "_p.o";
457 else if ( module.type == IdlInterface )
458 newExtension = "_i.o";
459 else
460 newExtension = ".h";
461 }
462 else
463 newExtension = "_" + module.name + ".o";
464
465 if ( module.type == BootSector )
466 destination_directory = OutputDirectory;
467 else
468 destination_directory = IntermediateDirectory;
469
470 const FileLocation *obj_file = new FileLocation(
471 destination_directory,
472 sourceFile->relative_path,
473 ReplaceExtension ( sourceFile->name, newExtension ) );
474 PassThruCacheDirectory ( obj_file );
475
476 return obj_file;
477 }
478
479 string
480 MingwModuleHandler::GetModuleCleanTarget ( const Module& module ) const
481 {
482 return module.name + "_clean";
483 }
484
485 void
486 MingwModuleHandler::GetReferencedObjectLibraryModuleCleanTargets ( vector<string>& moduleNames ) const
487 {
488 for ( size_t i = 0; i < module.non_if_data.libraries.size (); i++ )
489 {
490 Library& library = *module.non_if_data.libraries[i];
491 if ( library.importedModule->type == ObjectLibrary )
492 moduleNames.push_back ( GetModuleCleanTarget ( *library.importedModule ) );
493 }
494 }
495
496 void
497 MingwModuleHandler::GenerateCleanTarget () const
498 {
499 if ( module.type == Alias )
500 return;
501
502 fprintf ( fMakefile, "# CLEAN TARGET\n" );
503 fprintf ( fMakefile,
504 ".PHONY: %s_clean\n",
505 module.name.c_str() );
506 vector<string> referencedModuleNames;
507 GetReferencedObjectLibraryModuleCleanTargets ( referencedModuleNames );
508 fprintf ( fMakefile,
509 "%s: %s\n\t-@${rm}",
510 GetModuleCleanTarget ( module ).c_str(),
511 backend->v2s ( referencedModuleNames, 10 ).c_str () );
512 for ( size_t i = 0; i < clean_files.size(); i++ )
513 {
514 if ( ( i + 1 ) % 10 == 9 )
515 fprintf ( fMakefile, " 2>$(NUL)\n\t-@${rm}" );
516 fprintf ( fMakefile, " %s", clean_files[i].c_str() );
517 }
518 fprintf ( fMakefile, " 2>$(NUL)\n" );
519
520 // Clean files generated by external rules
521 fprintf ( fMakefile, "\t-@${rm} $(%s_CLEANFILES) 2>$(NUL)\n", module.name.c_str() );
522
523 if( ProxyMakefile::GenerateProxyMakefile(module) )
524 {
525 DirectoryLocation root;
526
527 if ( backend->configuration.GenerateProxyMakefilesInSourceTree )
528 root = SourceDirectory;
529 else
530 root = OutputDirectory;
531
532 FileLocation proxyMakefile ( root,
533 module.output->relative_path,
534 "GNUmakefile" );
535 fprintf ( fMakefile, "\t-@${rm} %s 2>$(NUL)\n",
536 backend->GetFullName ( proxyMakefile ).c_str () );
537 }
538
539 fprintf ( fMakefile, "clean: %s_clean\n\n", module.name.c_str() );
540 }
541
542 void
543 MingwModuleHandler::GenerateInstallTarget () const
544 {
545 if ( !module.install )
546 return;
547 fprintf ( fMakefile, "# INSTALL TARGET\n" );
548 fprintf ( fMakefile, ".PHONY: %s_install\n", module.name.c_str() );
549 fprintf ( fMakefile,
550 "%s_install: %s\n",
551 module.name.c_str (),
552 backend->GetFullName ( *module.install ).c_str () );
553 }
554
555 void
556 MingwModuleHandler::GenerateDependsTarget () const
557 {
558 fprintf ( fMakefile, "# DEPENDS TARGET\n" );
559 fprintf ( fMakefile,
560 ".PHONY: %s_depends\n",
561 module.name.c_str() );
562 fprintf ( fMakefile,
563 "%s_depends: $(RBUILD_TARGET)\n",
564 module.name.c_str () );
565 fprintf ( fMakefile,
566 "\t$(ECHO_RBUILD)\n" );
567 fprintf ( fMakefile,
568 "\t$(Q)$(RBUILD_TARGET) $(RBUILD_FLAGS) -dm%s mingw\n",
569 module.name.c_str () );
570 }
571
572 static
573 const char * const CompilerPrefixTable [ CompilerTypesCount ] =
574 {
575 "C",
576 "CXX",
577 "CPP",
578 "AS",
579 "MIDL",
580 "RC",
581 "NASM",
582 };
583
584 /* static */ void
585 MingwModuleHandler::GenerateParameters (
586 const char* prefix,
587 const char* assignmentOperation,
588 const IfableData& data )
589 {
590 for ( unsigned type = CompilerTypeCC; type < CompilerTypesCount; ++ type )
591 {
592 CompilerType compiler = static_cast < CompilerType > ( type );
593
594 // Includes
595 std::string includes = GenerateIncludeParametersFromVector ( data.includes, compiler );
596
597 if ( includes.size() )
598 {
599 fprintf ( fMakefile,
600 "%s_%sINCLUDES%s%s\n",
601 prefix,
602 CompilerPrefixTable [ compiler ],
603 assignmentOperation,
604 includes.c_str () );
605 }
606
607 // Defines
608 std::string defines = GenerateDefineParametersFromVector ( data.defines, compiler );
609
610 if ( defines.size() )
611 {
612 fprintf ( fMakefile,
613 "%s_%sDEFINES%s%s\n",
614 prefix,
615 CompilerPrefixTable [ compiler ],
616 assignmentOperation,
617 defines.c_str () );
618 }
619
620 // Flags
621 std::string flags = GenerateCompilerParametersFromVector ( data.compilerFlags, compiler );
622
623 if ( flags.size() )
624 {
625 fprintf ( fMakefile,
626 "%s_%sFLAGS%s%s\n",
627 prefix,
628 CompilerPrefixTable [ compiler ],
629 assignmentOperation,
630 flags.c_str () );
631 }
632 }
633 }
634
635 /* static */ string
636 MingwModuleHandler::GenerateGccDefineParametersFromVector (
637 const vector<Define*>& defines,
638 set<string>& used_defs)
639 {
640 string parameters;
641
642 for ( size_t i = 0; i < defines.size (); i++ )
643 {
644 Define& define = *defines[i];
645 if (used_defs.find(define.name) != used_defs.end())
646 continue;
647 if (define.redefine)
648 {
649 if (parameters.length () > 0)
650 parameters += " ";
651 parameters += "-U";
652 parameters += define.name;
653 }
654 if (parameters.length () > 0)
655 parameters += " ";
656 if (define.arguments.length ())
657 parameters += "$(QT)";
658 parameters += "-D";
659 parameters += define.name;
660 parameters += define.arguments;
661 if (define.value.length () > 0)
662 {
663 parameters += "=";
664 parameters += define.value;
665 }
666 if (define.arguments.length ())
667 parameters += "$(QT)";
668 used_defs.insert(used_defs.begin(),define.name);
669 }
670 return parameters;
671 }
672
673 /* static */ string
674 MingwModuleHandler::GenerateDefineParametersFromVector (
675 const std::vector<Define*>& defines,
676 CompilerType compiler )
677 {
678 string parameters;
679
680 for ( size_t i = 0; i < defines.size (); i++ )
681 {
682 Define& define = *defines[i];
683 if (!define.IsCompilerSet (compiler))
684 continue;
685 if (define.redefine)
686 {
687 if (parameters.length () > 0)
688 parameters += " ";
689 parameters += "-U";
690 parameters += define.name;
691 }
692 if (parameters.length () > 0)
693 parameters += " ";
694 if (define.arguments.length ())
695 parameters += "$(QT)";
696 parameters += "-D";
697 parameters += define.name;
698 parameters += define.arguments;
699 if (define.value.length () > 0)
700 {
701 parameters += "=";
702 parameters += define.value;
703 }
704 if (define.arguments.length ())
705 parameters += "$(QT)";
706 }
707 return parameters;
708 }
709
710 string
711 MingwModuleHandler::ConcatenatePaths (
712 const string& path1,
713 const string& path2 ) const
714 {
715 if ( ( path1.length () == 0 ) || ( path1 == "." ) || ( path1 == "./" ) )
716 return path2;
717 if ( path1[path1.length ()] == cSep )
718 return path1 + path2;
719 else
720 return path1 + cSep + path2;
721 }
722
723 /* static */ string
724 MingwModuleHandler::GenerateIncludeParametersFromVector ( const vector<Include*>& includes, const CompilerType type )
725 {
726 string parameters, path_prefix;
727 for ( size_t i = 0; i < includes.size (); i++ )
728 {
729 Include& include = *includes[i];
730 if ( include.IsCompilerSet( type ) )
731 parameters += " -I" + backend->GetFullPath ( *include.directory );
732 }
733 return parameters;
734 }
735
736 /* static */ string
737 MingwModuleHandler::GenerateCompilerParametersFromVector ( const vector<CompilerFlag*>& compilerFlags, const CompilerType type )
738 {
739 string parameters;
740 for ( size_t i = 0; i < compilerFlags.size (); i++ )
741 {
742 CompilerFlag& compilerFlag = *compilerFlags[i];
743 if ( compilerFlag.IsCompilerSet( type ) )
744 parameters += " " + compilerFlag.flag;
745 }
746 return parameters;
747 }
748
749 string
750 MingwModuleHandler::GenerateLinkerParametersFromVector ( const vector<LinkerFlag*>& linkerFlags ) const
751 {
752 string parameters;
753 for ( size_t i = 0; i < linkerFlags.size (); i++ )
754 {
755 LinkerFlag& linkerFlag = *linkerFlags[i];
756 if ( parameters.length () > 0 )
757 parameters += " ";
758 parameters += linkerFlag.flag;
759 }
760 return parameters;
761 }
762
763 string
764 MingwModuleHandler::GenerateImportLibraryDependenciesFromVector (
765 const vector<Library*>& libraries )
766 {
767 string dependencies ( "" );
768 int wrap_count = 0;
769 for ( size_t i = 0; i < libraries.size (); i++ )
770 {
771 if ( wrap_count++ == 5 )
772 dependencies += " \\\n\t\t", wrap_count = 0;
773 else if ( dependencies.size () > 0 )
774 dependencies += " ";
775 dependencies += GetImportLibraryDependency ( *libraries[i]->importedModule, libraries[i]->delayimp );
776 }
777 return dependencies;
778 }
779
780 string
781 MingwModuleHandler::GenerateLinkerParameters () const
782 {
783 return GenerateLinkerParametersFromVector ( module.linkerFlags );
784 }
785
786 void
787 MingwModuleHandler::GenerateMacros (
788 const char* assignmentOperation,
789 const IfableData& data,
790 const vector<LinkerFlag*>* linkerFlags,
791 set<const Define *>& used_defs )
792 {
793 if ( linkerFlags != NULL )
794 {
795 string linkerParameters = GenerateLinkerParametersFromVector ( *linkerFlags );
796 if ( linkerParameters.size () > 0 )
797 {
798 fprintf (
799 fMakefile,
800 "%s %s %s\n",
801 linkerflagsMacro.c_str (),
802 assignmentOperation,
803 linkerParameters.c_str() );
804 }
805 }
806
807 if ( data.libraries.size () > 0 )
808 {
809 // Check if host and target modules are not mixed up
810 HostType current = ModuleHandlerInformations[module.type].DefaultHost;
811 std::vector<Library*>::const_iterator it;
812 for ( it = data.libraries.begin(); it != data.libraries.end(); ++it )
813 {
814 HostType imported = ModuleHandlerInformations[(*it)->importedModule->type].DefaultHost;
815 if (current != imported)
816 {
817 throw InvalidOperationException ( __FILE__,
818 __LINE__,
819 "Module '%s' imports module '%s', which is not of the right type",
820 module.name.c_str (),
821 (*it)->importedModule->name.c_str () );
822 }
823 }
824
825 string deps = GenerateImportLibraryDependenciesFromVector ( data.libraries );
826 if ( deps.size () > 0 )
827 {
828 fprintf (
829 fMakefile,
830 "%s %s %s\n",
831 libsMacro.c_str(),
832 assignmentOperation,
833 deps.c_str() );
834 }
835 }
836 }
837
838 void
839 MingwModuleHandler::CleanupCompilationUnitVector ( vector<CompilationUnit*>& compilationUnits )
840 {
841 for ( size_t i = 0; i < compilationUnits.size (); i++ )
842 delete compilationUnits[i];
843 }
844
845 void
846 MingwModuleHandler::GetModuleSpecificCompilationUnits ( vector<CompilationUnit*>& compilationUnits )
847 {
848 }
849
850 void
851 MingwModuleHandler::GenerateSourceMacros (
852 const IfableData& data )
853 {
854 size_t i;
855
856 const vector<CompilationUnit*>& compilationUnits = data.compilationUnits;
857 vector<const FileLocation *> headers;
858 if ( compilationUnits.size () > 0 )
859 {
860 fprintf (
861 fMakefile,
862 "%s =",
863 sourcesMacro.c_str () );
864 for ( i = 0; i < compilationUnits.size(); i++ )
865 {
866 CompilationUnit& compilationUnit = *compilationUnits[i];
867 const FileLocation& compilationName = compilationUnit.GetFilename ();
868 fprintf (
869 fMakefile,
870 "%s%s",
871 ( i%10 == 9 ? " \\\n\t" : " " ),
872 backend->GetFullName ( compilationName ).c_str () );
873 }
874 fprintf ( fMakefile, "\n" );
875 }
876
877 vector<CompilationUnit*> sourceCompilationUnits;
878 GetModuleSpecificCompilationUnits ( sourceCompilationUnits );
879 for ( i = 0; i < sourceCompilationUnits.size (); i++ )
880 {
881 const FileLocation& compilationName = sourceCompilationUnits[i]->GetFilename ();
882 fprintf (
883 fMakefile,
884 "%s += %s\n",
885 sourcesMacro.c_str(),
886 backend->GetFullName ( compilationName ).c_str () );
887 }
888 CleanupCompilationUnitVector ( sourceCompilationUnits );
889 }
890
891 void
892 MingwModuleHandler::GenerateObjectMacros (
893 const IfableData& data )
894 {
895 size_t i;
896 const char* assignmentOperation = "=";
897
898 const vector<CompilationUnit*>& compilationUnits = data.compilationUnits;
899 vector<const FileLocation *> headers;
900 vector<const FileLocation *> mcheaders;
901 vector<const FileLocation *> mcresources;
902 if ( compilationUnits.size () > 0 )
903 {
904 for ( i = 0; i < compilationUnits.size (); i++ )
905 {
906 CompilationUnit& compilationUnit = *compilationUnits[i];
907 if ( compilationUnit.IsFirstFile () )
908 {
909 const FileLocation& compilationName = compilationUnit.GetFilename ();
910 const FileLocation *object_file = GetObjectFilename ( &compilationName, module );
911 fprintf ( fMakefile,
912 "%s := %s\n",
913 objectsMacro.c_str(),
914 backend->GetFullName ( *object_file ).c_str () );
915 delete object_file;
916 assignmentOperation = "+=";
917 break;
918 }
919 }
920 fprintf (
921 fMakefile,
922 "%s %s",
923 objectsMacro.c_str (),
924 assignmentOperation );
925 for ( i = 0; i < compilationUnits.size(); i++ )
926 {
927 CompilationUnit& compilationUnit = *compilationUnits[i];
928 if ( !compilationUnit.IsFirstFile () )
929 {
930 const FileLocation& compilationName = compilationUnit.GetFilename ();
931 const FileLocation *objectFilename = GetObjectFilename ( &compilationName, module );
932 if ( GetExtension ( *objectFilename ) == ".h" )
933 headers.push_back ( objectFilename );
934 else if ( GetExtension ( *objectFilename ) == ".rc" )
935 {
936 const FileLocation *headerFilename = GetMcHeaderFilename ( &compilationUnit.GetFilename () );
937 mcheaders.push_back ( headerFilename );
938 mcresources.push_back ( objectFilename );
939 }
940 else
941 {
942 fprintf (
943 fMakefile,
944 "%s%s",
945 ( i%10 == 9 ? " \\\n\t" : " " ),
946 backend->GetFullName ( *objectFilename ).c_str () );
947 delete objectFilename;
948 }
949 }
950 }
951 fprintf ( fMakefile, "\n" );
952 }
953 if ( headers.size () > 0 )
954 {
955 fprintf (
956 fMakefile,
957 "%s_HEADERS %s",
958 module.name.c_str (),
959 assignmentOperation );
960 for ( i = 0; i < headers.size (); i++ )
961 {
962 fprintf (
963 fMakefile,
964 "%s%s",
965 ( i%10 == 9 ? " \\\n\t" : " " ),
966 backend->GetFullName ( *headers[i] ).c_str () );
967 delete headers[i];
968 }
969 fprintf ( fMakefile, "\n" );
970 }
971
972 if ( mcheaders.size () > 0 )
973 {
974 fprintf (
975 fMakefile,
976 "%s_MCHEADERS %s",
977 module.name.c_str (),
978 assignmentOperation );
979 for ( i = 0; i < mcheaders.size (); i++ )
980 {
981 fprintf (
982 fMakefile,
983 "%s%s",
984 ( i%10 == 9 ? " \\\n\t" : " " ),
985 backend->GetFullName ( *mcheaders[i] ).c_str () );
986 delete mcheaders[i];
987 }
988 fprintf ( fMakefile, "\n" );
989 }
990
991 if ( mcresources.size () > 0 )
992 {
993 fprintf (
994 fMakefile,
995 "%s_RESOURCES %s",
996 module.name.c_str (),
997 assignmentOperation );
998 for ( i = 0; i < mcresources.size (); i++ )
999 {
1000 fprintf (
1001 fMakefile,
1002 "%s%s",
1003 ( i%10 == 9 ? " \\\n\t" : " " ),
1004 backend->GetFullName ( *mcresources[i] ).c_str () );
1005 delete mcresources[i];
1006 }
1007 fprintf ( fMakefile, "\n" );
1008 }
1009
1010 vector<CompilationUnit*> sourceCompilationUnits;
1011 GetModuleSpecificCompilationUnits ( sourceCompilationUnits );
1012 for ( i = 0; i < sourceCompilationUnits.size (); i++ )
1013 {
1014 const FileLocation& compilationName = sourceCompilationUnits[i]->GetFilename ();
1015 const FileLocation *object_file = GetObjectFilename ( &compilationName, module );
1016 fprintf (
1017 fMakefile,
1018 "%s += %s\n",
1019 objectsMacro.c_str(),
1020 backend->GetFullName ( *object_file ).c_str () );
1021 delete object_file;
1022 }
1023 CleanupCompilationUnitVector ( sourceCompilationUnits );
1024
1025 if ( module.IsSpecDefinitionFile() )
1026 {
1027 const FileLocation *stubs_file = new FileLocation(
1028 IntermediateDirectory,
1029 module.importLibrary->source->relative_path,
1030 ReplaceExtension ( module.importLibrary->source->name, "_" + module.name + ".stubs.o" ) );
1031
1032 fprintf (
1033 fMakefile,
1034 "%s += %s\n",
1035 objectsMacro.c_str(),
1036 backend->GetFullName ( *stubs_file ).c_str () );
1037
1038 delete stubs_file;
1039 }
1040
1041 if ( module.type == RpcProxy )
1042 {
1043 const FileLocation *dlldata_file = GetDlldataFilename();
1044
1045 fprintf (
1046 fMakefile,
1047 "%s += %s\n",
1048 objectsMacro.c_str(),
1049 ReplaceExtension ( backend->GetFullName ( *dlldata_file ), ".o" ).c_str() );
1050
1051 delete dlldata_file;
1052 }
1053 }
1054
1055 const FileLocation*
1056 MingwModuleHandler::GetDlldataFilename() const
1057 {
1058 std::string dlldata_path = "";
1059 size_t dlldata_path_len = module.xmlbuildFile.find_last_of(cSep);
1060
1061 if ( dlldata_path_len != std::string::npos && dlldata_path_len != 0 )
1062 dlldata_path = module.xmlbuildFile.substr(0, dlldata_path_len);
1063
1064 return new FileLocation( IntermediateDirectory, dlldata_path, module.name + ".dlldata.c" );
1065 }
1066
1067 const FileLocation*
1068 MingwModuleHandler::GetPrecompiledHeaderPath () const
1069 {
1070 if ( !module.pch || !use_pch )
1071 return NULL;
1072 return new FileLocation ( IntermediateDirectory,
1073 module.pch->file->relative_path,
1074 ".gch_" + module.name );
1075 }
1076
1077 const FileLocation*
1078 MingwModuleHandler::GetPrecompiledHeaderFilename () const
1079 {
1080 if ( !module.pch || !use_pch )
1081 return NULL;
1082 return new FileLocation ( IntermediateDirectory,
1083 module.pch->file->relative_path + "/.gch_" + module.name,
1084 module.pch->file->name + ".gch" );
1085 }
1086
1087 Rule windresRule ( "$(eval $(call RBUILD_WRC_RULE,$(module_name),$(source),$(dependencies),$(compiler_flags)))\n",
1088 "$(intermediate_path_unique).coff",
1089 "$(intermediate_path_unique).res",
1090 "$(intermediate_path_unique).res.d",
1091 "$(intermediate_dir)$(SEP)", NULL );
1092 Rule winebuildPRule ( "$(eval $(call RBUILD_WINEBUILD_WITH_CPP_RULE,$(module_name),$(source),$(dependencies),$(compiler_flags),$(module_dllname)))\n",
1093 "$(intermediate_path_unique).spec",
1094 "$(intermediate_path_unique).spec.d",
1095 "$(intermediate_path_unique).auto.def",
1096 "$(intermediate_path_unique).stubs.c",
1097 "$(intermediate_path_unique).stubs.o",
1098 "$(intermediate_path_unique).stubs.o.d",
1099 "$(intermediate_dir)$(SEP)", NULL );
1100 Rule winebuildRule ( "$(eval $(call RBUILD_WINEBUILD_RULE,$(module_name),$(source),$(dependencies),$(compiler_flags),$(module_dllname)))\n",
1101 "$(intermediate_path_unique).auto.def",
1102 "$(intermediate_path_unique).stubs.c",
1103 "$(intermediate_path_unique).stubs.o",
1104 "$(intermediate_path_unique).stubs.o.d",
1105 "$(intermediate_dir)$(SEP)", NULL );
1106 Rule gasRule ( "$(eval $(call RBUILD_GAS_RULE,$(module_name),$(source),$(dependencies),$(compiler_flags)))\n",
1107 "$(intermediate_path_unique).o",
1108 "$(intermediate_path_unique).o.d", NULL );
1109 Rule gccRule ( "$(eval $(call RBUILD_CC_RULE,$(module_name),$(source),$(dependencies),$(compiler_flags)))\n",
1110 "$(intermediate_path_unique).o",
1111 "$(intermediate_path_unique).o.d", NULL );
1112 Rule gccHostRule ( "$(eval $(call RBUILD_HOST_GCC_RULE,$(module_name),$(source),$(dependencies),$(compiler_flags)))\n",
1113 "$(intermediate_path_unique).o", NULL );
1114 Rule gppRule ( "$(eval $(call RBUILD_CXX_RULE,$(module_name),$(source),$(dependencies),$(compiler_flags)))\n",
1115 "$(intermediate_path_unique).o",
1116 "$(intermediate_path_unique).o.d", NULL );
1117 Rule gppHostRule ( "$(eval $(call RBUILD_HOST_GPP_RULE,$(module_name),$(source),$(dependencies),$(compiler_flags)))\n",
1118 "$(intermediate_path_unique).o", NULL );
1119 Rule widlHeaderRule ( "$(eval $(call RBUILD_WIDL_HEADER_RULE,$(module_name),$(source),$(dependencies),$(compiler_flags)))\n",
1120 "$(intermediate_path_noext).h",
1121 "$(intermediate_dir)$(SEP)", NULL );
1122 Rule widlServerRule ( "$(eval $(call RBUILD_WIDL_SERVER_RULE,$(module_name),$(source),$(dependencies),$(compiler_flags)))\n",
1123 "$(intermediate_path_noext)_s.h",
1124 "$(intermediate_path_noext)_s.c",
1125 "$(intermediate_path_noext)_s.o",
1126 "$(intermediate_dir)$(SEP)", NULL );
1127 Rule widlClientRule ( "$(eval $(call RBUILD_WIDL_CLIENT_RULE,$(module_name),$(source),$(dependencies),$(compiler_flags)))\n",
1128 "$(intermediate_path_noext)_c.h",
1129 "$(intermediate_path_noext)_c.c",
1130 "$(intermediate_path_noext)_c.o",
1131 "$(intermediate_dir)$(SEP)", NULL );
1132 Rule widlProxyRule ( "$(eval $(call RBUILD_WIDL_PROXY_RULE,$(module_name),$(source),$(dependencies),$(compiler_flags)))\n",
1133 "$(intermediate_path_noext)_p.h",
1134 "$(intermediate_path_noext)_p.c",
1135 "$(intermediate_path_noext)_p.o",
1136 "$(intermediate_dir)$(SEP)", NULL );
1137 Rule widlInterfaceRule ( "$(eval $(call RBUILD_WIDL_INTERFACE_RULE,$(module_name),$(source),$(dependencies),$(compiler_flags)))\n",
1138 "$(intermediate_path_noext)_i.c",
1139 "$(intermediate_path_noext)_i.o",
1140 "$(intermediate_dir)$(SEP)", NULL );
1141 Rule widlDlldataRule ( "$(eval $(call RBUILD_WIDL_DLLDATA_RULE,$(module_name),$(source),$(dependencies),$(compiler_flags),$(bare_dependencies)))\n",
1142 "$(intermediate_path_noext).o", NULL );
1143 Rule widlTlbRule ( "$(eval $(call RBUILD_WIDL_TLB_RULE,$(module_name),$(source),$(dependencies),$(compiler_flags)))\n",
1144 "$(intermediate_dir)$(SEP)", NULL );
1145 Rule pchRule ( "$(eval $(call RBUILD_CC_PCH_RULE,$(module_name),$(source),$(dependencies),$(compiler_flags)))\n",
1146 "$(intermediate_dir)$(SEP).gch_$(module_name)$(SEP)$(source_name).gch",
1147 "$(intermediate_dir)$(SEP).gch_$(module_name)$(SEP)$(source_name).gch.d",
1148 "$(intermediate_dir)$(SEP).gch_$(module_name)$(SEP)", NULL );
1149 Rule pchCxxRule ( "$(eval $(call RBUILD_CXX_PCH_RULE,$(module_name),$(source),$(dependencies),$(compiler_flags)))\n",
1150 "$(intermediate_dir)$(SEP).gch_$(module_name)$(SEP)$(source_name).gch",
1151 "$(intermediate_dir)$(SEP).gch_$(module_name)$(SEP)$(source_name).gch.d",
1152 "$(intermediate_dir)$(SEP).gch_$(module_name)$(SEP)", NULL );
1153 Rule bootRule ( "$(eval $(call RBUILD_NASM,$(module_name),$(source),$(dependencies),,$(module_output)))\n",
1154 "$(module_output)",
1155 "$(OUTPUT)$(SEP)$(source_dir)$(SEP)", NULL );
1156 Rule nasmRule ( "$(eval $(call RBUILD_NASM,$(module_name),$(source),$(dependencies),,$(intermediate_path_unique).o))\n",
1157 "$(intermediate_path_unique).o",
1158 "$(intermediate_dir)$(SEP)", NULL );
1159
1160 /* TODO: move these to rules.mak */
1161 Rule wmcRule ( "$(intermediate_path_noext).rc $(INTERMEDIATE)$(SEP)include$(SEP)reactos$(SEP)$(source_name_noext).h: $(wmc_TARGET) $(source) | $(intermediate_dir)\n"
1162 "\t$(ECHO_WMC)\n"
1163 "\t$(Q)$(wmc_TARGET) -i -H $(INTERMEDIATE)$(SEP)include$(SEP)reactos$(SEP)$(source_name_noext).h -o $(intermediate_path_noext).rc $(source)\n",
1164 "$(intermediate_path_noext).rc",
1165 "$(INTERMEDIATE)$(SEP)include$(SEP)reactos$(SEP)$(source_name_noext).h",
1166 "$(intermediate_dir)$(SEP)", NULL );
1167 /* TODO: if possible, move these to rules.mak */
1168 Rule arRule1 ( "$(intermediate_path_noext).a: $($(module_name)_OBJS) $(dependencies) | $(intermediate_dir)\n",
1169 "$(intermediate_path_noext).a",
1170 "$(intermediate_dir)$(SEP)", NULL );
1171 Rule arRule2 ( "\t$(ECHO_AR)\n"
1172 "\t${ar} -rc $@ $($(module_name)_OBJS)\n",
1173 NULL );
1174 Rule arHostRule2 ( "\t$(ECHO_HOSTAR)\n"
1175 "\t${host_ar} -rc $@ $($(module_name)_OBJS)\n",
1176 NULL );
1177
1178 Rule emptyRule ( "", NULL );
1179
1180 void
1181 MingwModuleHandler::GenerateGccCommand (
1182 const FileLocation* sourceFile,
1183 const Rule *rule,
1184 const string& extraDependencies )
1185 {
1186 const FileLocation *pchFilename = GetPrecompiledHeaderFilename ();
1187 string dependencies = extraDependencies;
1188
1189 if ( pchFilename )
1190 {
1191 dependencies += " " + backend->GetFullName ( *pchFilename );
1192 delete pchFilename;
1193 }
1194
1195 /* WIDL generated headers may be used */
1196 vector<FileLocation> rpcDependencies;
1197 GetRpcHeaderDependencies ( rpcDependencies );
1198 if ( rpcDependencies.size () > 0 )
1199 dependencies += " " + backend->v2s ( rpcDependencies, 5 );
1200
1201 rule->Execute ( fMakefile, backend, module, sourceFile, clean_files, dependencies );
1202 }
1203
1204 string
1205 MingwModuleHandler::GetPropertyValue ( const Module& module, const std::string& name )
1206 {
1207 const Property* property = module.project.LookupProperty(name);
1208
1209 if (property)
1210 return property->value;
1211 else
1212 return string ( "" );
1213 }
1214
1215 /* caller needs to delete the returned object */
1216 const FileLocation*
1217 MingwModuleHandler::GetRpcServerHeaderFilename ( const FileLocation *base ) const
1218 {
1219 string newname = GetBasename ( base->name ) + "_s.h";
1220 return new FileLocation ( IntermediateDirectory, base->relative_path, newname );
1221 }
1222
1223 /* caller needs to delete the returned object */
1224 const FileLocation*
1225 MingwModuleHandler::GetRpcClientHeaderFilename ( const FileLocation *base ) const
1226 {
1227 string newname = GetBasename ( base->name ) + "_c.h";
1228 return new FileLocation ( IntermediateDirectory, base->relative_path, newname );
1229 }
1230
1231 /* caller needs to delete the returned object */
1232 const FileLocation*
1233 MingwModuleHandler::GetRpcProxyHeaderFilename ( const FileLocation *base ) const
1234 {
1235 string newname = GetBasename ( base->name ) + "_p.h";
1236 return new FileLocation ( IntermediateDirectory, base->relative_path, newname );
1237 }
1238
1239 /* caller needs to delete the returned object */
1240 const FileLocation*
1241 MingwModuleHandler::GetIdlHeaderFilename ( const FileLocation *base ) const
1242 {
1243 string newname = GetBasename ( base->name ) + ".h";
1244 return new FileLocation ( IntermediateDirectory, base->relative_path, newname );
1245 }
1246
1247 /* caller needs to delete the returned object */
1248 const FileLocation*
1249 MingwModuleHandler::GetMcHeaderFilename ( const FileLocation *base ) const
1250 {
1251 string newname = GetBasename ( base->name ) + ".h";
1252 return new FileLocation ( IntermediateDirectory, "include/reactos" , newname );
1253 }
1254
1255 void
1256 MingwModuleHandler::GenerateCommands (
1257 const CompilationUnit& compilationUnit,
1258 const string& extraDependencies )
1259 {
1260 const FileLocation& sourceFile = compilationUnit.GetFilename ();
1261 string extension = GetExtension ( sourceFile );
1262 std::transform ( extension.begin (), extension.end (), extension.begin (), tolower );
1263
1264 struct
1265 {
1266 HostType host;
1267 ModuleType type;
1268 string extension;
1269 Rule* rule;
1270 } rules[] = {
1271 { HostDontCare, TypeDontCare, ".s", &gasRule },
1272 { HostDontCare, BootSector, ".asm", &bootRule },
1273 { HostDontCare, TypeDontCare, ".asm", &nasmRule },
1274 { HostDontCare, TypeDontCare, ".rc", &windresRule },
1275 { HostDontCare, TypeDontCare, ".mc", &wmcRule },
1276 { HostDontCare, RpcServer, ".idl", &widlServerRule },
1277 { HostDontCare, RpcClient, ".idl", &widlClientRule },
1278 { HostDontCare, RpcProxy, ".idl", &widlProxyRule },
1279 { HostDontCare, IdlInterface, ".idl", &widlInterfaceRule },
1280 { HostDontCare, EmbeddedTypeLib, ".idl", &widlTlbRule },
1281 { HostDontCare, TypeDontCare, ".idl", &widlHeaderRule },
1282 { HostTrue, TypeDontCare, ".c", &gccHostRule },
1283 { HostTrue, TypeDontCare, ".cc", &gppHostRule },
1284 { HostTrue, TypeDontCare, ".cpp", &gppHostRule },
1285 { HostTrue, TypeDontCare, ".cxx", &gppHostRule },
1286 { HostFalse, TypeDontCare, ".c", &gccRule },
1287 { HostFalse, TypeDontCare, ".cc", &gppRule },
1288 { HostFalse, TypeDontCare, ".cpp", &gppRule },
1289 { HostFalse, TypeDontCare, ".cxx", &gppRule },
1290 { HostFalse, Cabinet, ".*", &emptyRule }
1291 };
1292 size_t i;
1293 Rule *customRule = NULL;
1294
1295 for ( i = 0; i < sizeof ( rules ) / sizeof ( rules[0] ); i++ )
1296 {
1297 if ( rules[i].host != HostDontCare && rules[i].host != ModuleHandlerInformations[module.type].DefaultHost )
1298 continue;
1299 if ( rules[i].type != TypeDontCare && rules[i].type != module.type )
1300 continue;
1301 if ( rules[i].extension != extension && rules[i].extension != ".*")
1302 continue;
1303 customRule = rules[i].rule;
1304 break;
1305 }
1306
1307 if ( extension == ".c" || extension == ".cc" || extension == ".cpp" || extension == ".cxx" )
1308 {
1309 GenerateGccCommand ( &sourceFile,
1310 customRule,
1311 GetCompilationUnitDependencies ( compilationUnit ) + extraDependencies );
1312 }
1313 else if ( customRule )
1314 customRule->Execute ( fMakefile, backend, module, &sourceFile, clean_files );
1315 else
1316 {
1317 throw InvalidOperationException ( __FILE__,
1318 __LINE__,
1319 "Unsupported filename extension '%s' in file '%s'",
1320 extension.c_str (),
1321 backend->GetFullName ( sourceFile ).c_str () );
1322 }
1323 }
1324
1325 void
1326 MingwModuleHandler::GenerateBuildMapCode ( const FileLocation *mapTarget )
1327 {
1328 fprintf ( fMakefile, "# BUILD MAP CODE\n" );
1329
1330 fprintf ( fMakefile,
1331 "ifeq ($(ROS_BUILDMAP),full)\n" );
1332
1333 FileLocation mapFilename ( OutputDirectory,
1334 module.output->relative_path,
1335 GetBasename ( module.output->name ) + ".map" );
1336 CLEAN_FILE ( mapFilename );
1337
1338 fprintf ( fMakefile,
1339 "\t$(ECHO_OBJDUMP)\n" );
1340 fprintf ( fMakefile,
1341 "\t$(Q)${objdump} -d -S %s > %s\n",
1342 mapTarget ? backend->GetFullName ( *mapTarget ).c_str () : "$@",
1343 backend->GetFullName ( mapFilename ).c_str () );
1344
1345 fprintf ( fMakefile,
1346 "else\n" );
1347 fprintf ( fMakefile,
1348 "ifeq ($(ROS_BUILDMAP),yes)\n" );
1349
1350 fprintf ( fMakefile,
1351 "\t$(ECHO_NM)\n" );
1352 fprintf ( fMakefile,
1353 "\t$(Q)${nm} --numeric-sort %s > %s\n",
1354 mapTarget ? backend->GetFullName ( *mapTarget ).c_str () : "$@",
1355 backend->GetFullName ( mapFilename ).c_str () );
1356
1357 fprintf ( fMakefile,
1358 "endif\n" );
1359
1360 fprintf ( fMakefile,
1361 "endif\n" );
1362 }
1363
1364 void
1365 MergeStringVector ( const Backend* backend,
1366 const vector<FileLocation>& input,
1367 vector<string>& output )
1368 {
1369 int wrap_at = 25;
1370 string s;
1371 int wrap_count = -1;
1372 for ( size_t i = 0; i < input.size (); i++ )
1373 {
1374 if ( wrap_count++ == wrap_at )
1375 {
1376 output.push_back ( s );
1377 s = "";
1378 wrap_count = 0;
1379 }
1380 else if ( s.size () > 0)
1381 s += " ";
1382 s += backend->GetFullName ( input[i] );
1383 }
1384 if ( s.length () > 0 )
1385 output.push_back ( s );
1386 }
1387
1388 void
1389 MingwModuleHandler::GetObjectsVector ( const IfableData& data,
1390 vector<FileLocation>& objectFiles ) const
1391 {
1392 for ( size_t i = 0; i < data.compilationUnits.size (); i++ )
1393 {
1394 CompilationUnit& compilationUnit = *data.compilationUnits[i];
1395 const FileLocation& compilationName = compilationUnit.GetFilename ();
1396 const FileLocation *object_file = GetObjectFilename ( &compilationName, module );
1397 objectFiles.push_back ( *object_file );
1398 delete object_file;
1399 }
1400 }
1401
1402 void
1403 MingwModuleHandler::GenerateCleanObjectsAsYouGoCode () const
1404 {
1405 if ( backend->configuration.CleanAsYouGo )
1406 {
1407 vector<FileLocation> objectFiles;
1408 GetObjectsVector ( module.non_if_data,
1409 objectFiles );
1410 vector<string> lines;
1411 MergeStringVector ( backend,
1412 objectFiles,
1413 lines );
1414 for ( size_t i = 0; i < lines.size (); i++ )
1415 {
1416 fprintf ( fMakefile,
1417 "\t-@${rm} %s 2>$(NUL)\n",
1418 lines[i].c_str () );
1419 }
1420 }
1421 }
1422
1423 void
1424 MingwModuleHandler::GenerateLinkerCommand () const
1425 {
1426 string definitionFilename;
1427
1428 const FileLocation *DefinitionFilename = GetDefinitionFilename ();
1429
1430 if ( DefinitionFilename ) {
1431 definitionFilename = backend->GetFullName (*DefinitionFilename);
1432 delete DefinitionFilename;
1433 }
1434
1435 string linkerScriptArgument;
1436 if ( module.linkerScript != NULL ) {
1437 if ( module.project.configuration.Linker == GnuLd )
1438 linkerScriptArgument = ssprintf ( " -T %s", backend->GetFullName ( *module.linkerScript->file ).c_str () );
1439 else
1440 fprintf ( stderr,
1441 "Linker doesn't support linker scripts: linker script %s ignored for module %s\n",
1442 backend->GetFullName ( *module.linkerScript->file ).c_str (),
1443 module.name.c_str() );
1444 }
1445
1446 string extraLibraries;
1447 if ( ModuleHandlerInformations[module.type].DefaultHost == HostFalse ) {
1448 if ( module.cplusplus ) {
1449 switch ( module.type )
1450 {
1451 case Win32DLL:
1452 case Win32OCX:
1453 case Win32CUI:
1454 case Win32GUI:
1455 case Win32SCR:
1456 extraLibraries = "$$(PROJECT_CXXLIBS)";
1457 break;
1458
1459 default:
1460 extraLibraries = "$$(PROJECT_CCLIBS)";
1461 break;
1462 }
1463 } else
1464 extraLibraries = "$$(PROJECT_CCLIBS)";
1465 }
1466
1467 delete PassThruCacheDirectory ( new FileLocation ( module.output->directory, module.output->relative_path, "" ) );
1468 delete PassThruCacheDirectory ( new FileLocation ( IntermediateDirectory, module.output->relative_path, "" ) );
1469
1470 fprintf ( fMakefile,
1471 "$(eval $(call RBUILD_LINK_RULE,%s,%s,%s,%s,%s,%s,%s))\n",
1472 module.name.c_str(),
1473 definitionFilename.c_str(),
1474 module.xmlbuildFile.c_str(),
1475 linkerScriptArgument.c_str(),
1476 extraLibraries.c_str(),
1477 module.GetEntryPoint().c_str(),
1478 module.baseaddress.c_str() );
1479 }
1480
1481 void
1482 MingwModuleHandler::GenerateObjectFileTargets ( const IfableData& data )
1483 {
1484 size_t i;
1485 string moduleDependencies;
1486
1487 const vector<CompilationUnit*>& compilationUnits = data.compilationUnits;
1488 for ( i = 0; i < compilationUnits.size (); i++ )
1489 {
1490 CompilationUnit& compilationUnit = *compilationUnits[i];
1491 const FileLocation& compilationName = compilationUnit.GetFilename ();
1492 const FileLocation *objectFilename = GetObjectFilename ( &compilationName, module );
1493 if ( GetExtension ( *objectFilename ) == ".h" )
1494 moduleDependencies += ssprintf ( " $(%s_HEADERS)", module.name.c_str () );
1495 else if ( GetExtension ( *objectFilename ) == ".rc" )
1496 moduleDependencies += ssprintf ( " $(%s_RESOURCES)", module.name.c_str () );
1497 delete objectFilename;
1498 }
1499
1500 for ( i = 0; i < compilationUnits.size (); i++ )
1501 {
1502 GenerateCommands ( *compilationUnits[i],
1503 moduleDependencies );
1504 }
1505
1506 vector<CompilationUnit*> sourceCompilationUnits;
1507 GetModuleSpecificCompilationUnits ( sourceCompilationUnits );
1508 for ( i = 0; i < sourceCompilationUnits.size (); i++ )
1509 {
1510 GenerateCommands ( *sourceCompilationUnits[i],
1511 moduleDependencies );
1512 }
1513 CleanupCompilationUnitVector ( sourceCompilationUnits );
1514
1515 if ( module.type == RpcProxy )
1516 {
1517 widlDlldataRule.Execute ( fMakefile,
1518 backend,
1519 module,
1520 GetDlldataFilename(),
1521 clean_files,
1522 ssprintf ( "$(%s_SOURCES)", module.name.c_str ()) );
1523 }
1524 }
1525
1526 void
1527 MingwModuleHandler::GenerateObjectFileTargets ()
1528 {
1529 if ( module.pch && use_pch )
1530 {
1531
1532 std::map<string, string> vars;
1533
1534 /* WIDL generated headers may be used */
1535 string dependencies;
1536 vector<FileLocation> rpcDependencies;
1537 GetRpcHeaderDependencies ( rpcDependencies );
1538 if ( rpcDependencies.size () > 0 )
1539 dependencies = " " + backend->v2s ( rpcDependencies, 5 );
1540
1541 if ( module.cplusplus )
1542 pchCxxRule.Execute ( fMakefile, backend, module, module.pch->file, clean_files, dependencies );
1543 else
1544 pchRule.Execute ( fMakefile, backend, module, module.pch->file, clean_files, dependencies );
1545 }
1546
1547 GenerateObjectFileTargets ( module.non_if_data );
1548 }
1549
1550 /* caller needs to delete the returned object */
1551 const FileLocation*
1552 MingwModuleHandler::GenerateArchiveTarget ()
1553 {
1554 const FileLocation *archiveFilename = GetModuleArchiveFilename ();
1555
1556 if ( archiveFilename == NULL )
1557 return NULL;
1558
1559 const FileLocation *definitionFilename = GetDefinitionFilename ();
1560
1561 fprintf ( fMakefile, "# ARCHIVE TARGET\n" );
1562
1563 if ( IsStaticLibrary ( module ) && definitionFilename )
1564 {
1565 arRule1.Execute ( fMakefile,
1566 backend,
1567 module,
1568 archiveFilename,
1569 clean_files,
1570 backend->GetFullName ( *definitionFilename ).c_str () );
1571
1572 fprintf ( fMakefile,
1573 "\t${dlltool} --def %s --kill-at --output-lib $@\n",
1574 backend->GetFullName ( *definitionFilename ).c_str () );
1575 }
1576 else
1577 arRule1.Execute ( fMakefile, backend, module, archiveFilename, clean_files );
1578
1579 if ( definitionFilename )
1580 delete definitionFilename;
1581
1582 if(module.type == HostStaticLibrary)
1583 arHostRule2.Execute ( fMakefile, backend, module, archiveFilename, clean_files );
1584 else
1585 arRule2.Execute ( fMakefile, backend, module, archiveFilename, clean_files );
1586
1587 GenerateCleanObjectsAsYouGoCode ();
1588
1589 fprintf ( fMakefile, "\n" );
1590
1591 return archiveFilename;
1592 }
1593
1594 /*static*/ string
1595 MingwModuleHandler::GetObjectsMacro ( const Module& module )
1596 {
1597 return ssprintf ( "$(%s_OBJS)",
1598 module.name.c_str () );
1599 }
1600
1601 string
1602 MingwModuleHandler::GetLibsMacro () const
1603 {
1604 return ssprintf ( "$(%s_LIBS)", module.name.c_str () );
1605 }
1606
1607 string
1608 MingwModuleHandler::GetLinkerMacro () const
1609 {
1610 return ssprintf ( "$(%s_LDFLAGS)",
1611 module.name.c_str () );
1612 }
1613
1614 string
1615 MingwModuleHandler::GetDebugFormat ()
1616 {
1617 if (Environment::GetArch() == "amd64")
1618 {
1619 return "dwarf-2";
1620 }
1621 return "stabs+";
1622 }
1623
1624 string
1625 MingwModuleHandler::GetModuleTargets ( const Module& module )
1626 {
1627 if ( ReferenceObjects ( module ) )
1628 return GetObjectsMacro ( module );
1629 else
1630 {
1631 const FileLocation *target_file = GetTargetFilename ( module, NULL );
1632 string target = backend->GetFullName ( *target_file ).c_str ();
1633 delete target_file;
1634 return target;
1635 }
1636 }
1637
1638 void
1639 MingwModuleHandler::GenerateSourceMacro ()
1640 {
1641 sourcesMacro = ssprintf ( "%s_SOURCES", module.name.c_str ());
1642
1643 if ( module.type == RpcProxy || module.type == Cabinet )
1644 GenerateSourceMacros ( module.non_if_data );
1645
1646 // future references to the macro will be to get its values
1647 sourcesMacro = ssprintf ("$(%s)", sourcesMacro.c_str ());
1648 }
1649
1650 void
1651 MingwModuleHandler::GenerateObjectMacro ()
1652 {
1653 objectsMacro = ssprintf ("%s_OBJS", module.name.c_str ());
1654
1655 GenerateObjectMacros ( module.non_if_data );
1656
1657 // future references to the macro will be to get its values
1658 objectsMacro = ssprintf ("$(%s)", objectsMacro.c_str ());
1659 }
1660
1661 void
1662 MingwModuleHandler::GenerateTargetMacro ()
1663 {
1664 fprintf ( fMakefile,
1665 "%s := %s\n",
1666 GetTargetMacro ( module, false ).c_str (),
1667 GetModuleTargets ( module ).c_str () );
1668 }
1669
1670 void
1671 MingwModuleHandler::GetRpcHeaderDependencies (
1672 vector<FileLocation>& dependencies ) const
1673 {
1674 for ( size_t i = 0; i < module.non_if_data.libraries.size (); i++ )
1675 {
1676 Library& library = *module.non_if_data.libraries[i];
1677 if ( library.importedModule->type == RpcServer ||
1678 library.importedModule->type == RpcClient ||
1679 library.importedModule->type == RpcProxy ||
1680 library.importedModule->type == IdlHeader )
1681 {
1682 for ( size_t j = 0; j < library.importedModule->non_if_data.compilationUnits.size (); j++ )
1683 {
1684 CompilationUnit& compilationUnit = *library.importedModule->non_if_data.compilationUnits[j];
1685 const FileLocation& sourceFile = compilationUnit.GetFilename ();
1686 string extension = GetExtension ( sourceFile );
1687 if ( extension == ".idl" || extension == ".IDL" )
1688 {
1689 string basename = GetBasename ( sourceFile.name );
1690 if ( library.importedModule->type == RpcServer )
1691 {
1692 const FileLocation *header = GetRpcServerHeaderFilename ( &sourceFile );
1693 dependencies.push_back ( *header );
1694 delete header;
1695 }
1696 if ( library.importedModule->type == RpcClient )
1697 {
1698 const FileLocation *header = GetRpcClientHeaderFilename ( &sourceFile );
1699 dependencies.push_back ( *header );
1700 delete header;
1701 }
1702 if ( library.importedModule->type == RpcProxy )
1703 {
1704 const FileLocation *header = GetRpcProxyHeaderFilename ( &sourceFile );
1705 dependencies.push_back ( *header );
1706 delete header;
1707 }
1708 if ( library.importedModule->type == IdlHeader )
1709 {
1710 const FileLocation *header = GetIdlHeaderFilename ( &sourceFile );
1711 dependencies.push_back ( *header );
1712 delete header;
1713 }
1714 }
1715 }
1716 }
1717 }
1718 }
1719
1720 void
1721 MingwModuleHandler::GenerateOtherMacros ()
1722 {
1723 set<const Define *> used_defs;
1724
1725 linkerflagsMacro = ssprintf ("%s_LDFLAGS", module.name.c_str ());
1726 libsMacro = ssprintf("%s_LIBS", module.name.c_str ());
1727
1728 const FileLocation * pchPath = GetPrecompiledHeaderPath ();
1729
1730 if ( pchPath )
1731 {
1732 string pchPathStr = backend->GetFullName ( *pchPath );
1733 delete pchPath;
1734
1735 fprintf ( fMakefile,
1736 "%s_%sINCLUDES+= -I%s\n",
1737 module.name.c_str(),
1738 CompilerPrefixTable[CompilerTypeCC],
1739 pchPathStr.c_str() );
1740
1741 fprintf ( fMakefile,
1742 "%s_%sINCLUDES+= -I%s\n",
1743 module.name.c_str(),
1744 CompilerPrefixTable[CompilerTypeCXX],
1745 pchPathStr.c_str() );
1746 }
1747
1748 const char * toolPrefix = "";
1749
1750 if ( ModuleHandlerInformations[module.type].DefaultHost == HostTrue )
1751 toolPrefix = "HOST_";
1752
1753 // FIXME: this is very ugly and generates lots of useless entries
1754 for ( unsigned type = CompilerTypeCC; type < CompilerTypesCount; ++ type )
1755 {
1756 string flags;
1757
1758 if ( module.dynamicCRT )
1759 flags += ssprintf ( " $(%s%sFLAG_CRTDLL)", toolPrefix, CompilerPrefixTable[type] );
1760
1761 // FIXME: this duplicates the flag for CPP and C/CXX
1762 if ( !module.allowWarnings )
1763 flags += ssprintf ( " $(%s%sFLAG_WERROR)", toolPrefix, CompilerPrefixTable[type] );
1764
1765 if ( module.isUnicode )
1766 flags += ssprintf ( " $(%s%sFLAG_UNICODE)", toolPrefix, CompilerPrefixTable[type] );
1767
1768 if ( flags.size() )
1769 {
1770 fprintf ( fMakefile,
1771 "%s_%sFLAGS+=%s\n",
1772 module.name.c_str(),
1773 CompilerPrefixTable[type],
1774 flags.c_str() );
1775 }
1776 }
1777
1778 GenerateParameters ( module.name.c_str(), "+=", module.non_if_data );
1779
1780 GenerateMacros (
1781 "+=",
1782 module.non_if_data,
1783 &module.linkerFlags,
1784 used_defs );
1785
1786 fprintf ( fMakefile, "\n\n" );
1787 }
1788
1789 void
1790 MingwModuleHandler::GenerateRules ()
1791 {
1792 SpecFileType spec;
1793
1794 fprintf ( fMakefile, "# RULES\n" );
1795 string targetMacro = GetTargetMacro ( module );
1796 //CLEAN_FILE ( targetMacro );
1797 CLEAN_FILE ( FileLocation ( SourceDirectory, "", targetMacro ) );
1798
1799 // generate phony target for module name
1800 fprintf ( fMakefile, ".PHONY: %s\n",
1801 module.name.c_str () );
1802 string dependencies = GetTargetMacro ( module );
1803 if ( module.type == Test )
1804 dependencies += " $(regtests_run_TARGET)";
1805 fprintf ( fMakefile, "%s: %s\n\n",
1806 module.name.c_str (),
1807 dependencies.c_str () );
1808 if ( module.type == Test )
1809 {
1810 fprintf ( fMakefile,
1811 "\t@%s\n",
1812 targetMacro.c_str ());
1813 }
1814
1815 if ( !ReferenceObjects ( module ) )
1816 {
1817 const FileLocation* ar_target = GenerateArchiveTarget ();
1818
1819 if ( ar_target )
1820 delete ar_target;
1821 }
1822
1823
1824 spec = module.IsSpecDefinitionFile();
1825
1826 if(spec)
1827 {
1828 Rule * defRule;
1829
1830 if (spec == PSpec)
1831 defRule = &winebuildPRule;
1832 else
1833 defRule = &winebuildRule;
1834
1835 defRule->Execute ( fMakefile, backend, module, module.importLibrary->source, clean_files );
1836 }
1837
1838 GenerateObjectFileTargets ();
1839 }
1840
1841 void
1842 MingwModuleHandler::GetInvocationDependencies (
1843 const Module& module,
1844 string_list& dependencies )
1845 {
1846 for ( size_t i = 0; i < module.invocations.size (); i++ )
1847 {
1848 Invoke& invoke = *module.invocations[i];
1849 if ( invoke.invokeModule == &module )
1850 /* Protect against circular dependencies */
1851 continue;
1852 invoke.GetTargets ( dependencies );
1853 }
1854 }
1855
1856 void
1857 MingwModuleHandler::GenerateInvocations () const
1858 {
1859 if ( module.invocations.size () == 0 )
1860 return;
1861
1862 fprintf ( fMakefile, "# INVOCATIONS\n" );
1863
1864 size_t iend = module.invocations.size ();
1865 for ( size_t i = 0; i < iend; i++ )
1866 {
1867 const Invoke& invoke = *module.invocations[i];
1868
1869 if ( invoke.invokeModule->type != BuildTool )
1870 {
1871 throw XMLInvalidBuildFileException (
1872 module.node.location,
1873 "Only modules of type buildtool can be invoked." );
1874 }
1875
1876 string invokeTarget = module.GetInvocationTarget ( i );
1877 string_list invoke_targets;
1878 assert ( invoke_targets.size() );
1879 invoke.GetTargets ( invoke_targets );
1880 fprintf ( fMakefile,
1881 ".PHONY: %s\n\n",
1882 invokeTarget.c_str () );
1883 fprintf ( fMakefile,
1884 "%s:",
1885 invokeTarget.c_str () );
1886 size_t j, jend = invoke_targets.size();
1887 for ( j = 0; j < jend; j++ )
1888 {
1889 fprintf ( fMakefile,
1890 " %s",
1891 invoke_targets[i].c_str () );
1892 }
1893 fprintf ( fMakefile, "\n\n%s", invoke_targets[0].c_str () );
1894 for ( j = 1; j < jend; j++ )
1895 fprintf ( fMakefile,
1896 " %s",
1897 invoke_targets[i].c_str () );
1898 fprintf ( fMakefile,
1899 ": %s\n",
1900 NormalizeFilename ( backend->GetFullName ( *invoke.invokeModule->output ) ).c_str () );
1901 fprintf ( fMakefile, "\t$(ECHO_INVOKE)\n" );
1902 fprintf ( fMakefile,
1903 "\t%s %s\n\n",
1904 NormalizeFilename ( backend->GetFullName ( *invoke.invokeModule->output ) ).c_str (),
1905 invoke.GetParameters ().c_str () );
1906 }
1907 }
1908
1909 string
1910 MingwModuleHandler::GetPreconditionDependenciesName () const
1911 {
1912 return module.name + "_precondition";
1913 }
1914
1915 void
1916 MingwModuleHandler::GetDefaultDependencies (
1917 string_list& dependencies ) const
1918 {
1919 /* Avoid circular dependency */
1920 if ( ModuleHandlerInformations[module.type].DefaultHost == HostTrue )
1921 return;
1922
1923 if (module.name != "psdk" &&
1924 module.name != "dxsdk")
1925 {
1926 dependencies.push_back ( "$(psdk_TARGET) $(psdk_HEADERS)" );
1927 dependencies.push_back ( "$(dxsdk_TARGET) $(dxsdk_HEADERS)" );
1928 }
1929
1930 if (module.name != "errcodes" &&
1931 module.name != "bugcodes" &&
1932 module.name != "ntstatus")
1933 {
1934 dependencies.push_back ( "$(errcodes_TARGET) $(ERRCODES_MCHEADERS)" );
1935 dependencies.push_back ( "$(bugcodes_TARGET) $(BUGCODES_MCHEADERS)" );
1936 dependencies.push_back ( "$(ntstatus_TARGET) $(NTSTATUS_MCHEADERS)" );
1937 }
1938
1939 ///* Check if any dependent library relies on the generated headers */
1940 //for ( size_t i = 0; i < module.project.modules.size (); i++ )
1941 //{
1942 // const Module& m = *module.project.modules[i];
1943 // for ( size_t j = 0; j < m.non_if_data.compilationUnits.size (); j++ )
1944 // {
1945 // CompilationUnit& compilationUnit = *m.non_if_data.compilationUnits[j];
1946 // const FileLocation& sourceFile = compilationUnit.GetFilename ();
1947 // string extension = GetExtension ( sourceFile );
1948 // if (extension == ".mc" || extension == ".MC" )
1949 // {
1950 // string dependency = ssprintf ( "$(%s_MCHEADERS)", m.name.c_str () );
1951 // dependencies.push_back ( dependency );
1952 // }
1953 // }
1954 //}
1955 }
1956
1957 void
1958 MingwModuleHandler::GeneratePreconditionDependencies ()
1959 {
1960 fprintf ( fMakefile, "# PRECONDITION DEPENDENCIES\n" );
1961 string preconditionDependenciesName = GetPreconditionDependenciesName ();
1962 string_list dependencies;
1963 GetDefaultDependencies ( dependencies );
1964 GetModuleDependencies ( dependencies );
1965
1966 GetInvocationDependencies ( module, dependencies );
1967
1968 if ( dependencies.size() )
1969 {
1970 fprintf ( fMakefile,
1971 "%s =",
1972 preconditionDependenciesName.c_str () );
1973 for ( size_t i = 0; i < dependencies.size(); i++ )
1974 fprintf ( fMakefile,
1975 " %s",
1976 dependencies[i].c_str () );
1977 fprintf ( fMakefile, "\n\n" );
1978 }
1979
1980 fprintf ( fMakefile, "\n" );
1981 }
1982
1983 /* caller needs to delete the returned object */
1984 const FileLocation*
1985 MingwModuleHandler::GetDefinitionFilename () const
1986 {
1987 if ( module.importLibrary == NULL )
1988 return NULL;
1989
1990 if ( module.IsSpecDefinitionFile () )
1991 {
1992 return new FileLocation ( IntermediateDirectory,
1993 module.importLibrary->source->relative_path,
1994 GetBasename ( module.importLibrary->source->name ) + "_" + module.name + ".auto.def" );
1995 }
1996 else
1997 {
1998 return new FileLocation ( SourceDirectory,
1999 module.importLibrary->source->relative_path,
2000 module.importLibrary->source->name );
2001 }
2002 }
2003
2004 void
2005 MingwModuleHandler::GetSpecObjectDependencies (
2006 vector<FileLocation>& dependencies,
2007 const FileLocation *file ) const
2008 {
2009 dependencies.push_back ( FileLocation ( IntermediateDirectory,
2010 file->relative_path,
2011 GetBasename ( file->name ) + "_" + module.name + ".stubs.c" ) );
2012 }
2013
2014 void
2015 MingwModuleHandler::GetMcObjectDependencies (
2016 vector<FileLocation>& dependencies,
2017 const FileLocation *file ) const
2018 {
2019 string basename = GetBasename ( file->name );
2020
2021 FileLocation defDependency ( IntermediateDirectory,
2022 "include/reactos",
2023 basename + ".h" );
2024 dependencies.push_back ( defDependency );
2025
2026 FileLocation stubsDependency ( IntermediateDirectory,
2027 file->relative_path,
2028 basename + ".rc" );
2029 dependencies.push_back ( stubsDependency );
2030 }
2031
2032 void
2033 MingwModuleHandler::GetWidlObjectDependencies (
2034 vector<FileLocation>& dependencies,
2035 const FileLocation *file ) const
2036 {
2037 string basename = GetBasename ( file->name );
2038 const FileLocation *generatedHeaderFilename = GetRpcServerHeaderFilename ( file );
2039
2040 FileLocation serverSourceDependency ( IntermediateDirectory,
2041 file->relative_path,
2042 basename + "_s.c" );
2043 dependencies.push_back ( serverSourceDependency );
2044 dependencies.push_back ( *generatedHeaderFilename );
2045
2046 delete generatedHeaderFilename;
2047 }
2048
2049 void
2050 MingwModuleHandler::GetDefinitionDependencies (
2051 vector<FileLocation>& dependencies ) const
2052 {
2053 const vector<CompilationUnit*>& compilationUnits = module.non_if_data.compilationUnits;
2054 for ( size_t i = 0; i < compilationUnits.size (); i++ )
2055 {
2056 const CompilationUnit& compilationUnit = *compilationUnits[i];
2057 const FileLocation& sourceFile = compilationUnit.GetFilename ();
2058 string extension = GetExtension ( sourceFile );
2059
2060 if (extension == ".spec" || extension == ".pspec")
2061 GetSpecObjectDependencies ( dependencies, &sourceFile );
2062
2063 if (extension == ".idl")
2064 {
2065 if ( ( module.type == RpcServer ) || ( module.type == RpcClient ) || ( module.type == RpcProxy ) )
2066 GetWidlObjectDependencies ( dependencies, &sourceFile );
2067 }
2068 }
2069 }
2070
2071 enum DebugSupportType
2072 {
2073 DebugKernelMode,
2074 DebugUserMode
2075 };
2076
2077 static void
2078 MingwAddDebugSupportLibraries ( Module& module, DebugSupportType type )
2079 {
2080 Library* pLibrary;
2081
2082 switch(type)
2083 {
2084 case DebugKernelMode:
2085 pLibrary = new Library ( module, "debugsup_ntoskrnl" );
2086 break;
2087
2088 case DebugUserMode:
2089 pLibrary = new Library ( module, "debugsup_ntdll" );
2090 break;
2091
2092 default:
2093 assert(0);
2094 }
2095
2096 module.non_if_data.libraries.push_back(pLibrary);
2097 }
2098
2099 static void
2100 MingwAddCRTLibrary( Module &module )
2101 {
2102 const char * crtAttr = module.CRT.c_str ();
2103 const char * crtLib = NULL;
2104
2105 if ( stricmp ( crtAttr, "libc" ) == 0 )
2106 crtLib = "crt";
2107 else if ( stricmp ( crtAttr, "msvcrt" ) == 0 )
2108 crtLib = "msvcrt";
2109 else if ( stricmp ( crtAttr, "libcntpr" ) == 0 )
2110 crtLib = "libcntpr";
2111 else if ( stricmp ( crtAttr, "ntdll" ) == 0 )
2112 crtLib = "ntdll";
2113
2114 if ( crtLib )
2115 {
2116 Library* pLibrary = new Library ( module, std::string ( crtLib ) );
2117
2118 if ( pLibrary->importedModule == NULL)
2119 {
2120 throw XMLInvalidBuildFileException (
2121 module.node.location,
2122 "module '%s' trying to import non-existant C runtime module '%s'",
2123 module.name.c_str(),
2124 crtLib );
2125 }
2126
2127 module.non_if_data.libraries.push_back ( pLibrary );
2128 }
2129 }
2130
2131 MingwBuildToolModuleHandler::MingwBuildToolModuleHandler ( const Module& module_ )
2132 : MingwModuleHandler ( module_ )
2133 {
2134 }
2135
2136 void
2137 MingwBuildToolModuleHandler::Process ()
2138 {
2139 GenerateBuildToolModuleTarget ();
2140 }
2141
2142 void
2143 MingwBuildToolModuleHandler::GenerateBuildToolModuleTarget ()
2144 {
2145 string targetMacro ( GetTargetMacro (module) );
2146 string objectsMacro = GetObjectsMacro ( module );
2147 string libsMacro = GetLibsMacro ();
2148
2149 GenerateRules ();
2150
2151 fprintf ( fMakefile, "# BUILD TOOL MODULE TARGET\n" );
2152
2153 string linker;
2154 if ( module.cplusplus )
2155 linker = "${host_gpp}";
2156 else
2157 linker = "${host_gcc}";
2158
2159 const FileLocation *target_file = GetTargetFilename ( module, NULL );
2160 fprintf ( fMakefile, "%s: %s %s | %s\n",
2161 targetMacro.c_str (),
2162 objectsMacro.c_str (),
2163 libsMacro.c_str (),
2164 backend->GetFullPath ( *target_file ).c_str () );
2165 fprintf ( fMakefile, "\t$(ECHO_HOSTLD)\n" );
2166 fprintf ( fMakefile,
2167 "\t%s %s -o $@ %s %s\n\n",
2168 linker.c_str (),
2169 GetLinkerMacro ().c_str (),
2170 objectsMacro.c_str (),
2171 libsMacro.c_str () );
2172
2173 delete target_file;
2174 }
2175
2176
2177 MingwKernelModuleHandler::MingwKernelModuleHandler (
2178 const Module& module_ )
2179
2180 : MingwModuleHandler ( module_ )
2181 {
2182 }
2183
2184 void
2185 MingwKernelModuleHandler::Process ()
2186 {
2187 GenerateKernelModuleTarget ();
2188 }
2189
2190 void
2191 MingwKernelModuleHandler::GenerateKernelModuleTarget ()
2192 {
2193 GenerateRules ();
2194 GenerateLinkerCommand ();
2195 }
2196
2197
2198 MingwKernelModeDLLModuleHandler::MingwKernelModeDLLModuleHandler (
2199 const Module& module_ )
2200
2201 : MingwModuleHandler ( module_ )
2202 {
2203 }
2204
2205
2206 void
2207 MingwKernelModeDLLModuleHandler::AddImplicitLibraries ( Module& module )
2208 {
2209 MingwAddCRTLibrary ( module );
2210 MingwAddDebugSupportLibraries ( module, DebugKernelMode );
2211 }
2212
2213 void
2214 MingwKernelModeDLLModuleHandler::Process ()
2215 {
2216 GenerateKernelModeDLLModuleTarget ();
2217 }
2218
2219 void
2220 MingwKernelModeDLLModuleHandler::GenerateKernelModeDLLModuleTarget ()
2221 {
2222 GenerateRules ();
2223 GenerateLinkerCommand ();
2224 }
2225
2226
2227 MingwNativeDLLModuleHandler::MingwNativeDLLModuleHandler (
2228 const Module& module_ )
2229
2230 : MingwModuleHandler ( module_ )
2231 {
2232 }
2233
2234 void
2235 MingwNativeDLLModuleHandler::AddImplicitLibraries ( Module& module )
2236 {
2237 MingwAddCRTLibrary ( module );
2238 MingwAddDebugSupportLibraries ( module, DebugUserMode );
2239 }
2240
2241 void
2242 MingwNativeDLLModuleHandler::Process ()
2243 {
2244 GenerateNativeDLLModuleTarget ();
2245 }
2246
2247 void
2248 MingwNativeDLLModuleHandler::GenerateNativeDLLModuleTarget ()
2249 {
2250 GenerateRules ();
2251 GenerateLinkerCommand ();
2252 }
2253
2254
2255 MingwNativeCUIModuleHandler::MingwNativeCUIModuleHandler (
2256 const Module& module_ )
2257
2258 : MingwModuleHandler ( module_ )
2259 {
2260 }
2261
2262 void
2263 MingwNativeCUIModuleHandler::AddImplicitLibraries ( Module& module )
2264 {
2265 MingwAddCRTLibrary ( module );
2266 MingwAddDebugSupportLibraries ( module, DebugUserMode );
2267 }
2268
2269 void
2270 MingwNativeCUIModuleHandler::Process ()
2271 {
2272 GenerateNativeCUIModuleTarget ();
2273 }
2274
2275 void
2276 MingwNativeCUIModuleHandler::GenerateNativeCUIModuleTarget ()
2277 {
2278 GenerateRules ();
2279 GenerateLinkerCommand ();
2280 }
2281
2282
2283 MingwWin32DLLModuleHandler::MingwWin32DLLModuleHandler (
2284 const Module& module_ )
2285
2286 : MingwModuleHandler ( module_ )
2287 {
2288 }
2289
2290 MingwWin32OCXModuleHandler::MingwWin32OCXModuleHandler (
2291 const Module& module_ )
2292
2293 : MingwModuleHandler ( module_ )
2294 {
2295 }
2296
2297 static void
2298 MingwAddImplicitLibraries( Module &module )
2299 {
2300 Library* pLibrary;
2301
2302 if ( module.type != Win32DLL
2303 && module.type != Win32OCX
2304 && module.type != Win32CUI
2305 && module.type != Win32GUI
2306 && module.type != Win32SCR)
2307 {
2308 return;
2309 }
2310
2311 if ( module.isDefaultEntryPoint )
2312 {
2313 if ( module.IsDLL () )
2314 {
2315 //pLibrary = new Library ( module, "__mingw_dllmain" );
2316 //module.non_if_data.libraries.insert ( module.non_if_data.libraries.begin(), pLibrary );
2317 }
2318 else
2319 {
2320 pLibrary = new Library ( module, module.isUnicode ? "mingw_wmain" : "mingw_main" );
2321 module.non_if_data.libraries.insert ( module.non_if_data.libraries.begin(), pLibrary );
2322 }
2323 }
2324
2325 pLibrary = new Library ( module, "mingw_common" );
2326 module.non_if_data.libraries.push_back ( pLibrary );
2327
2328 MingwAddCRTLibrary ( module );
2329 MingwAddDebugSupportLibraries ( module, DebugUserMode );
2330 }
2331
2332 void
2333 MingwWin32DLLModuleHandler::AddImplicitLibraries ( Module& module )
2334 {
2335 MingwAddImplicitLibraries ( module );
2336 }
2337
2338 void
2339 MingwWin32DLLModuleHandler::Process ()
2340 {
2341 GenerateWin32DLLModuleTarget ();
2342 }
2343
2344 void
2345 MingwWin32DLLModuleHandler::GenerateWin32DLLModuleTarget ()
2346 {
2347 GenerateRules ();
2348 GenerateLinkerCommand ();
2349 }
2350
2351
2352 void
2353 MingwWin32OCXModuleHandler::AddImplicitLibraries ( Module& module )
2354 {
2355 MingwAddImplicitLibraries ( module );
2356 }
2357
2358 void
2359 MingwWin32OCXModuleHandler::Process ()
2360 {
2361 GenerateWin32OCXModuleTarget ();
2362 }
2363
2364 void
2365 MingwWin32OCXModuleHandler::GenerateWin32OCXModuleTarget ()
2366 {
2367 GenerateRules ();
2368 GenerateLinkerCommand ();
2369 }
2370
2371
2372 MingwWin32CUIModuleHandler::MingwWin32CUIModuleHandler (
2373 const Module& module_ )
2374
2375 : MingwModuleHandler ( module_ )
2376 {
2377 }
2378
2379 void
2380 MingwWin32CUIModuleHandler::AddImplicitLibraries ( Module& module )
2381 {
2382 MingwAddImplicitLibraries ( module );
2383 }
2384
2385 void
2386 MingwWin32CUIModuleHandler::Process ()
2387 {
2388 GenerateWin32CUIModuleTarget ();
2389 }
2390
2391 void
2392 MingwWin32CUIModuleHandler::GenerateWin32CUIModuleTarget ()
2393 {
2394 GenerateRules ();
2395 GenerateLinkerCommand ();
2396 }
2397
2398
2399 MingwWin32GUIModuleHandler::MingwWin32GUIModuleHandler (
2400 const Module& module_ )
2401
2402 : MingwModuleHandler ( module_ )
2403 {
2404 }
2405
2406 void
2407 MingwWin32GUIModuleHandler::AddImplicitLibraries ( Module& module )
2408 {
2409 MingwAddImplicitLibraries ( module );
2410 }
2411
2412 void
2413 MingwWin32GUIModuleHandler::Process ()
2414 {
2415 GenerateWin32GUIModuleTarget ();
2416 }
2417
2418 void
2419 MingwWin32GUIModuleHandler::GenerateWin32GUIModuleTarget ()
2420 {
2421 GenerateRules ();
2422 GenerateLinkerCommand ();
2423 }
2424
2425
2426 MingwBootLoaderModuleHandler::MingwBootLoaderModuleHandler (
2427 const Module& module_ )
2428
2429 : MingwModuleHandler ( module_ )
2430 {
2431 }
2432
2433 void
2434 MingwBootLoaderModuleHandler::Process ()
2435 {
2436 GenerateBootLoaderModuleTarget ();
2437 }
2438
2439 void
2440 MingwBootLoaderModuleHandler::GenerateBootLoaderModuleTarget ()
2441 {
2442 fprintf ( fMakefile, "# BOOT LOADER MODULE TARGET\n" );
2443 string targetMacro ( GetTargetMacro (module) );
2444 string objectsMacro = GetObjectsMacro ( module );
2445 string libsMacro = GetLibsMacro ();
2446
2447 GenerateRules ();
2448
2449 string objectsDir = "${call RBUILD_intermediate_dir,$(" + module.name + "_TARGET)}";
2450 string rspFile = objectsDir + "$(SEP)" + module.name + "_objs.rsp";
2451
2452 /* Generate the rsp rule */
2453 fprintf(fMakefile, "%s: $(%s_OBJS) %s | %s\n"
2454 "\t$(ECHO_RSP)\n"
2455 "\t-@${rm} $@ 2>$(NUL)\n"
2456 "\t${cp} $(NUL) $@ >$(NUL)\n"
2457 "\t$(foreach obj,$(%s_LIBS),$(Q)echo $(QUOTE)$(subst \\,\\\\,$(obj))$(QUOTE)>>$@$(NL))\n\n",
2458 rspFile.c_str(),
2459 module.name.c_str(),
2460 module.xmlbuildFile.c_str(),
2461 objectsDir.c_str(),
2462 module.name.c_str());
2463
2464 const FileLocation *target_file = GetTargetFilename ( module, NULL );
2465 fprintf ( fMakefile, "%s: %s %s | %s\n",
2466 targetMacro.c_str (),
2467 rspFile.c_str(),
2468 libsMacro.c_str (),
2469 backend->GetFullPath ( *target_file ).c_str () );
2470
2471 fprintf ( fMakefile, "\t$(ECHO_LD)\n" );
2472
2473 string linkerScriptArgument;
2474 if ( module.linkerScript != NULL ) {
2475 linkerScriptArgument = ssprintf(" -T %s", backend->GetFullName(*module.linkerScript->file).c_str());
2476 }
2477
2478 /* Link the stripped booloader */
2479 fprintf(fMakefile,
2480 "\t${ld} --strip-all --subsystem native --entry=%s --image-base=%s @%s $(PROJECT_CCLIBS) "
2481 "$(BUILTIN_LDFLAGS) $(PROJECT_LDFLAGS) $(LDFLAG_DRIVER) %s -o $@\n",
2482 module.GetEntryPoint().c_str(),
2483 module.baseaddress.c_str(),
2484 rspFile.c_str(),
2485 linkerScriptArgument.c_str() );
2486
2487 /* Link an unstripped version */
2488 fprintf(fMakefile,
2489 "ifeq ($(ROS_BUILDNOSTRIP),yes)\n"
2490 "\t${ld} --subsystem native --entry=%s --image-base=%s @%s $(PROJECT_CCLIBS) "
2491 "$(BUILTIN_LDFLAGS) $(PROJECT_LDFLAGS) $(LDFLAG_DRIVER) %s -o %s$(SEP)%s.nostrip.sys\n"
2492 "endif\n",
2493 module.GetEntryPoint().c_str(),
2494 module.baseaddress.c_str(),
2495 rspFile.c_str(),
2496 linkerScriptArgument.c_str(),
2497 backend->GetFullPath(*target_file).c_str(),
2498 module.name.c_str());
2499 }
2500
2501
2502 MingwBootProgramModuleHandler::MingwBootProgramModuleHandler (
2503 const Module& module_ )
2504 : MingwModuleHandler ( module_ )
2505 {
2506 }
2507
2508 void
2509 MingwBootProgramModuleHandler::Process ()
2510 {
2511 GenerateBootProgramModuleTarget ();
2512 }
2513
2514 void
2515 MingwBootProgramModuleHandler::GenerateBootProgramModuleTarget ()
2516 {
2517 fprintf ( fMakefile, "# BOOT PROGRAM MODULE TARGET\n" );
2518
2519 string targetName ( module.output->name );
2520 string targetMacro ( GetTargetMacro (module) );
2521 string workingDirectory = GetWorkingDirectory ();
2522 FileLocation junk_tmp ( TemporaryDirectory,
2523 "",
2524 module.name + ".junk.tmp" );
2525 FileLocation junk_elf ( TemporaryDirectory,
2526 "",
2527 module.name + ".junk.elf" );
2528 FileLocation junk_cpy ( TemporaryDirectory,
2529 "",
2530 module.name + ".junk.elf" );
2531 CLEAN_FILE ( junk_tmp );
2532 CLEAN_FILE ( junk_elf );
2533 CLEAN_FILE ( junk_cpy );
2534 string objectsMacro = GetObjectsMacro ( module );
2535 string libsMacro = GetLibsMacro ();
2536 const Module *payload = module.project.LocateModule ( module.payload );
2537
2538 GenerateRules ();
2539
2540 const FileLocation *target_file = GetTargetFilename ( module, NULL );
2541 fprintf ( fMakefile, "%s: %s %s %s | %s\n",
2542 targetMacro.c_str (),
2543 objectsMacro.c_str (),
2544 libsMacro.c_str (),
2545 payload->name.c_str (),
2546 backend->GetFullPath ( *target_file ).c_str () );
2547
2548 fprintf ( fMakefile, "\t$(ECHO_BOOTPROG)\n" );
2549
2550 fprintf ( fMakefile, "\t$(%s_PREPARE) $(OUTPUT)$(SEP)%s %s\n",
2551 module.buildtype.c_str (),
2552 NormalizeFilename( backend->GetFullName ( *payload->output ) ).c_str (),
2553 backend->GetFullName ( junk_cpy ).c_str () );
2554
2555 fprintf ( fMakefile, "\t${objcopy} $(%s_FLATFORMAT) %s %s\n",
2556 module.buildtype.c_str (),
2557 backend->GetFullName ( junk_cpy ).c_str (),
2558 backend->GetFullName ( junk_tmp ).c_str () );
2559
2560 fprintf ( fMakefile, "\t${ld} $(%s_LINKFORMAT) %s %s -o %s\n",
2561 module.buildtype.c_str (),
2562 libsMacro.c_str (),
2563 backend->GetFullName ( junk_tmp ).c_str (),
2564 backend->GetFullName ( junk_elf ).c_str () );
2565
2566 fprintf ( fMakefile, "\t${objcopy} $(%s_COPYFORMAT) %s $(INTERMEDIATE)$(SEP)%s\n",
2567 module.buildtype.c_str (),
2568 backend->GetFullName ( junk_elf ).c_str (),
2569 backend->GetFullName ( *module.output ) .c_str () );
2570
2571 fprintf ( fMakefile,
2572 "\t-@${rm} %s %s %s 2>$(NUL)\n",
2573 backend->GetFullName ( junk_tmp ).c_str (),
2574 backend->GetFullName ( junk_elf ).c_str (),
2575 backend->GetFullName ( junk_cpy ).c_str () );
2576
2577 delete target_file;
2578 }
2579
2580
2581 MingwIsoModuleHandler::MingwIsoModuleHandler (
2582 const Module& module_ )
2583
2584 : MingwModuleHandler ( module_ )
2585 {
2586 }
2587
2588 void
2589 MingwIsoModuleHandler::Process ()
2590 {
2591 GenerateIsoModuleTarget ();
2592 }
2593
2594 void
2595 MingwIsoModuleHandler::OutputBootstrapfileCopyCommands (
2596 const string& bootcdDirectory,
2597 vector<FileLocation>& destinations )
2598 {
2599 for ( std::map<std::string, Module*>::const_iterator p = module.project.modules.begin (); p != module.project.modules.end (); ++ p )
2600 {
2601 const Module& m = *p->second;
2602 if ( !m.enabled )
2603 continue;
2604 if ( m.bootstrap != NULL )
2605 {
2606 FileLocation targetFile ( OutputDirectory,
2607 m.bootstrap->base.length () > 0
2608 ? bootcdDirectory + sSep + m.bootstrap->base
2609 : bootcdDirectory,
2610 m.bootstrap->nameoncd );
2611 OutputCopyCommandSingle ( *m.output, targetFile );
2612 destinations.push_back ( targetFile );
2613 }
2614 }
2615 }
2616
2617 void
2618 MingwIsoModuleHandler::OutputCdfileCopyCommands (
2619 const string& bootcdDirectory,
2620 std::vector<FileLocation>& destinations )
2621 {
2622 for ( size_t i = 0; i < module.project.cdfiles.size (); i++ )
2623 {
2624 const CDFile& cdfile = *module.project.cdfiles[i];
2625 FileLocation targetFile ( OutputDirectory,
2626 cdfile.target->relative_path.length () > 0
2627 ? bootcdDirectory + sSep + cdfile.target->relative_path
2628 : bootcdDirectory,
2629 cdfile.target->name );
2630 OutputCopyCommandSingle ( *cdfile.source, targetFile );
2631 destinations.push_back ( targetFile );
2632 }
2633 for ( size_t i = 0; i < module.cdfiles.size (); i++ )
2634 {
2635 const CDFile& cdfile = *module.cdfiles[i];
2636 FileLocation targetFile ( OutputDirectory,
2637 cdfile.target->relative_path.length () > 0
2638 ? bootcdDirectory + sSep + cdfile.target->relative_path
2639 : bootcdDirectory,
2640 cdfile.target->name );
2641 OutputCopyCommandSingle ( *cdfile.source, targetFile );
2642 destinations.push_back ( targetFile );
2643 }
2644 }
2645
2646 void
2647 MingwIsoModuleHandler::GetBootstrapCdDirectories ( vector<FileLocation>& out,
2648 const string& bootcdDirectory )
2649 {
2650 for ( std::map<std::string, Module*>::const_iterator p = module.project.modules.begin (); p != module.project.modules.end (); ++ p )
2651 {
2652 const Module& m = *p->second;
2653 if ( !m.enabled )
2654 continue;
2655 if ( m.bootstrap != NULL )
2656 {
2657 FileLocation targetDirectory ( OutputDirectory,
2658 m.bootstrap->base.length () > 0
2659 ? bootcdDirectory + sSep + m.bootstrap->base
2660 : bootcdDirectory,
2661 "" );
2662 out.push_back ( targetDirectory );
2663 }
2664 }
2665 }
2666
2667 void
2668 MingwIsoModuleHandler::GetNonModuleCdDirectories ( vector<FileLocation>& out,
2669 const string& bootcdDirectory )
2670 {
2671 for ( size_t i = 0; i < module.project.cdfiles.size (); i++ )
2672 {
2673 const CDFile& cdfile = *module.project.cdfiles[i];
2674 FileLocation targetDirectory ( OutputDirectory,
2675 cdfile.target->relative_path.length () > 0
2676 ? bootcdDirectory + sSep + cdfile.target->relative_path
2677 : bootcdDirectory,
2678 "" );
2679 out.push_back( targetDirectory );
2680 }
2681 }
2682
2683 void
2684 MingwIsoModuleHandler::GetCdDirectories ( vector<FileLocation>& out,
2685 const string& bootcdDirectory )
2686 {
2687 GetBootstrapCdDirectories ( out, bootcdDirectory );
2688 GetNonModuleCdDirectories ( out, bootcdDirectory );
2689 }
2690
2691 void
2692 MingwIsoModuleHandler::GetBootstrapCdFiles (
2693 vector<FileLocation>& out ) const
2694 {
2695 for ( std::map<std::string, Module*>::const_iterator p = module.project.modules.begin (); p != module.project.modules.end (); ++ p )
2696 {
2697 const Module& m = *p->second;
2698 if ( !m.enabled )
2699 continue;
2700 if ( m.bootstrap != NULL )
2701 {
2702 out.push_back ( *m.output );
2703 }
2704 }
2705 }
2706
2707 void
2708 MingwIsoModuleHandler::GetNonModuleCdFiles (
2709 vector<FileLocation>& out ) const
2710 {
2711 for ( size_t i = 0; i < module.project.cdfiles.size (); i++ )
2712 {
2713 const CDFile& cdfile = *module.project.cdfiles[i];
2714 out.push_back ( *cdfile.source );
2715 }
2716 }
2717
2718 void
2719 MingwIsoModuleHandler::GetCdFiles (
2720 vector<FileLocation>& out ) const
2721 {
2722 GetBootstrapCdFiles ( out );
2723 GetNonModuleCdFiles ( out );
2724 }
2725
2726 void
2727 MingwIsoModuleHandler::GenerateIsoModuleTarget ()
2728 {
2729 fprintf ( fMakefile, "# ISO MODULE TARGET\n" );
2730 string bootcdDirectory = module.name;
2731 FileLocation bootcd ( OutputDirectory,
2732 bootcdDirectory,
2733 "" );
2734 FileLocation bootcdReactos ( OutputDirectory,
2735 bootcdDirectory + sSep + Environment::GetCdOutputPath (),
2736 "" );
2737
2738 // bootsector
2739 const Module* bootModule = module.bootSector->bootSectorModule;
2740
2741 if (!bootModule)
2742 {
2743 throw InvalidOperationException ( module.node.location.c_str(),
2744 0,
2745 "Invalid bootsector. module '%s' requires <bootsector>",
2746 module.name.c_str ());
2747 }
2748
2749 const FileLocation *isoboot = bootModule->output;
2750
2751 // prepare reactos.dff and reactos.inf
2752 FileLocation reactosDff ( SourceDirectory,
2753 "boot" + sSep + "bootdata" + sSep + "packages",
2754 "reactos.dff" );
2755 FileLocation reactosInf ( bootcdReactos.directory,
2756 bootcdReactos.relative_path,
2757 "reactos.inf" );
2758
2759 /*
2760 We use only the name and not full FileLocation(ouput) because Iso/LiveIso are an exception to the general rule.
2761 Iso/LiveIso outputs are generated in code base root
2762 */
2763 string IsoName = module.output->name;
2764
2765 fprintf ( fMakefile, ".PHONY: %s_CABINET\n\n",
2766 module.name.c_str () );
2767 fprintf ( fMakefile, "%s_CABINET: all $(cabman_TARGET) %s | %s\n",
2768 module.name.c_str (),
2769 backend->GetFullName ( reactosDff ).c_str (),
2770 backend->GetFullPath ( bootcdReactos ).c_str () );
2771 fprintf ( fMakefile,
2772 "\t$(Q)$(cabman_TARGET) -C %s -L %s -I -P $(OUTPUT)\n",
2773 backend->GetFullName ( reactosDff ).c_str (),
2774 backend->GetFullPath ( bootcdReactos ).c_str () );
2775 fprintf ( fMakefile,
2776 "\t$(Q)$(cabman_TARGET) -C %s -RC %s -L %s -N -P $(OUTPUT)\n",
2777 backend->GetFullName ( reactosDff ).c_str (),
2778 backend->GetFullName ( reactosInf ).c_str (),
2779 backend->GetFullPath ( bootcdReactos ).c_str ());
2780 fprintf ( fMakefile,
2781 "\t-@${rm} %s 2>$(NUL)\n\n",
2782 backend->GetFullName ( reactosInf ).c_str () );
2783
2784 std::vector<FileLocation> sourceFiles;
2785 OutputBootstrapfileCopyCommands ( bootcdDirectory, sourceFiles );
2786 OutputCdfileCopyCommands ( bootcdDirectory, sourceFiles );
2787
2788 fprintf( fMakefile,
2789 "\n%s_OBJS := %s\n\n",
2790 module.name.c_str (),
2791 backend->v2s ( sourceFiles, 5, true ).c_str () );
2792
2793 fprintf ( fMakefile, ".PHONY: %s\n\n",
2794 module.name.c_str ());
2795 fprintf ( fMakefile,
2796 "%s: $(%s_OBJS) %s_CABINET %s $(cdmake_TARGET) | %s\n",
2797 module.name.c_str (),
2798 module.name.c_str (),
2799 module.name.c_str (),
2800 backend->GetFullName ( *isoboot ).c_str (),
2801 backend->GetFullPath ( FileLocation ( OutputDirectory,
2802 bootcdDirectory,
2803 "" ) ).c_str () );
2804
2805 fprintf ( fMakefile, "\t$(ECHO_CDMAKE)\n" );
2806 fprintf ( fMakefile,
2807 "\t$(Q)$(cdmake_TARGET) -v -j -m -b %s %s REACTOS %s\n",
2808 backend->GetFullName ( *isoboot ).c_str (),
2809 backend->GetFullPath ( bootcd ).c_str (),
2810 IsoName.c_str() );
2811 fprintf ( fMakefile,
2812 "\n" );
2813 }
2814
2815
2816 MingwLiveIsoModuleHandler::MingwLiveIsoModuleHandler (
2817 const Module& module_ )
2818
2819 : MingwModuleHandler ( module_ )
2820 {
2821 }
2822
2823 void
2824 MingwLiveIsoModuleHandler::Process ()
2825 {
2826 GenerateLiveIsoModuleTarget ();
2827 }
2828
2829 void
2830 MingwLiveIsoModuleHandler::CreateDirectory ( const string& directory )
2831 {
2832 FileLocation dir ( OutputDirectory,
2833 directory,
2834 "" );
2835 MingwModuleHandler::PassThruCacheDirectory ( &dir );
2836 }
2837
2838 void
2839 MingwLiveIsoModuleHandler::OutputModuleCopyCommands ( string& livecdDirectory,
2840 string& reactosDirectory,
2841 std::vector<FileLocation>& destinations )
2842 {
2843 for ( std::map<std::string, Module*>::const_iterator p = module.project.modules.begin (); p != module.project.modules.end (); ++ p )
2844 {
2845 const Module& m = *p->second;
2846 if ( !m.enabled )
2847 continue;
2848 if ( m.install )
2849 {
2850 const Module& aliasedModule = backend->GetAliasedModuleOrModule ( m );
2851 FileLocation destination ( OutputDirectory,
2852 m.install->relative_path.length () > 0
2853 ? livecdDirectory + sSep + reactosDirectory + sSep + m.install->relative_path
2854 : livecdDirectory + sSep + reactosDirectory,
2855 m.install->name );
2856 OutputCopyCommandSingle ( *aliasedModule.output,
2857 destination);
2858 destinations.push_back ( destination );
2859 }
2860 }
2861 }
2862
2863 void
2864 MingwLiveIsoModuleHandler::OutputNonModuleCopyCommands ( string& livecdDirectory,
2865 string& reactosDirectory,
2866 std::vector<FileLocation>& destinations )
2867 {
2868 for ( size_t i = 0; i < module.project.installfiles.size (); i++ )
2869 {
2870 const InstallFile& installfile = *module.project.installfiles[i];
2871 FileLocation target ( OutputDirectory,
2872 installfile.target->relative_path.length () > 0
2873 ? livecdDirectory + sSep + reactosDirectory + sSep + installfile.target->relative_path
2874 : livecdDirectory + sSep + reactosDirectory,
2875 installfile.target->name );
2876 OutputCopyCommandSingle ( *installfile.source, target );
2877 destinations.push_back ( target );
2878 }
2879 }
2880
2881 void
2882 MingwLiveIsoModuleHandler::OutputProfilesDirectoryCommands ( string& livecdDirectory,
2883 vector<FileLocation>& destinations )
2884 {
2885 CreateDirectory ( livecdDirectory + sSep + "Profiles" );
2886 CreateDirectory ( livecdDirectory + sSep + "Profiles" + sSep + "All Users") ;
2887 CreateDirectory ( livecdDirectory + sSep + "Profiles" + sSep + "All Users" + sSep + "Desktop" );
2888 CreateDirectory ( livecdDirectory + sSep + "Profiles" + sSep + "Default User" );
2889 CreateDirectory ( livecdDirectory + sSep + "Profiles" + sSep + "Default User" + sSep + "Desktop" );
2890 CreateDirectory ( livecdDirectory + sSep + "Profiles" + sSep + "Default User" + sSep + "My Documents" );
2891
2892 FileLocation livecdIni ( SourceDirectory,
2893 "boot" + sSep + "bootdata",
2894 "livecd.ini" );
2895 FileLocation destination ( OutputDirectory,
2896 livecdDirectory,
2897 "freeldr.ini" );
2898 OutputCopyCommandSingle ( livecdIni,
2899 destination );
2900 destinations.push_back ( destination );
2901 }
2902
2903 void
2904 MingwLiveIsoModuleHandler::OutputLoaderCommands ( string& livecdDirectory,
2905 std::vector<FileLocation>& destinations )
2906 {
2907 FileLocation freeldr ( OutputDirectory,
2908 "boot" + sSep + "freeldr" + sSep + "freeldr",
2909 "freeldr.sys" );
2910 FileLocation destination ( OutputDirectory,
2911 livecdDirectory + sSep + "loader",
2912 "setupldr.sys" );
2913 OutputCopyCommandSingle ( freeldr,
2914 destination );
2915 destinations.push_back ( destination );
2916 }
2917
2918 void
2919 MingwLiveIsoModuleHandler::OutputMakeLinkCommand ( const string name,
2920 const string application,
2921 const string &path,
2922 vector<FileLocation>& destinations )
2923 {
2924 FileLocation location ( OutputDirectory, path, name + ".lnk" );
2925 fprintf ( fMakefile,
2926 "%s : $(mkshelllink_TARGET)\n",
2927 backend->GetFullNamePrefixSpaces ( *PassThruCacheDirectory ( &location ) ).c_str () );
2928 fprintf ( fMakefile,
2929 "\t$(Q)$(mkshelllink_TARGET) -o \"%s\" -g {450D8FBA-AD25-11D0-98A8-0800361B1103} -c %s -i %s -m livecd_start.cmd\n",
2930 backend->GetFullName ( location ).c_str (),
2931 application.c_str (),
2932 application.c_str () );
2933 destinations.push_back ( location );
2934 }
2935
2936 void
2937 MingwLiveIsoModuleHandler::OutputShortcutCommands ( string& livecdDirectory,
2938 vector<FileLocation>& destinations )
2939 {
2940 string allUsersDir = livecdDirectory + sSep + "Profiles" + sSep + "All Users";
2941 string defaultUserDir = livecdDirectory + sSep + "Profiles" + sSep + "Default User";
2942 FileLocation helperSource ( SourceDirectory, "boot" + sSep + "bootdata", "livecd_start.cmd" );
2943 FileLocation helperDest ( OutputDirectory, defaultUserDir + sSep + "My Documents", "livecd_start.cmd" );
2944 OutputCopyCommandSingle ( helperSource, helperDest );
2945 destinations.push_back ( helperDest );
2946
2947 string desktopDir = allUsersDir + sSep + "Desktop";
2948 OutputMakeLinkCommand ( "Command Prompt", "cmd.exe", desktopDir, destinations );
2949
2950 string startMenuDir = allUsersDir + sSep + "Start Menu";
2951 OutputMakeLinkCommand ( "ReactOS Explorer", "explorer.exe", startMenuDir + sSep + "Programs", destinations );
2952
2953 string adminToolsDir = startMenuDir + sSep + "Programs" + sSep + "Administrative Tools";
2954 OutputMakeLinkCommand ( "Device Manager", "devmgmt.exe", adminToolsDir, destinations );
2955 OutputMakeLinkCommand ( "Event Viewer", "eventvwr.exe", adminToolsDir, destinations );
2956 OutputMakeLinkCommand ( "Service Manager", "servman.exe", adminToolsDir, destinations );
2957 OutputMakeLinkCommand ( "System Configuration", "msconfig.exe", adminToolsDir, destinations );
2958
2959 string accessibilityDir = startMenuDir + sSep + "Programs" + sSep + "Accessibility";
2960 OutputMakeLinkCommand ( "Magnify", "magnify.exe", accessibilityDir, destinations );
2961
2962 string accessoriesDir = startMenuDir + sSep + "Programs" + sSep + "Accessories";
2963 OutputMakeLinkCommand ( "Calculator", "calc.exe", accessoriesDir, destinations );
2964 OutputMakeLinkCommand ( "Command Prompt", "cmd.exe", accessoriesDir, destinations );
2965 OutputMakeLinkCommand ( "Paint", "mspaint.exe", accessoriesDir, destinations );
2966 OutputMakeLinkCommand ( "Notepad", "notepad.exe", accessoriesDir, destinations );
2967 OutputMakeLinkCommand ( "Remote desktop", "mstsc.exe", accessoriesDir, destinations );
2968 OutputMakeLinkCommand ( "WordPad", "wordpad.exe", accessoriesDir, destinations );
2969
2970 string entertainmentDir = startMenuDir + sSep + "Programs" + sSep + "Entertainment";
2971 OutputMakeLinkCommand ( "Audiorecorder", "sndrec32.exe", entertainmentDir, destinations );
2972 OutputMakeLinkCommand ( "Multimedia Player", "mplay32.exe", entertainmentDir, destinations );
2973 OutputMakeLinkCommand ( "Volume Control", "sndvol32.exe", entertainmentDir, destinations );
2974
2975 string gamesDir = startMenuDir + sSep + "Programs" + sSep + "Games";
2976 OutputMakeLinkCommand ( "Solitaire", "sol.exe", gamesDir, destinations );
2977 OutputMakeLinkCommand ( "Spider Solitaire", "spider.exe", gamesDir, destinations );
2978 OutputMakeLinkCommand ( "WineMine", "winmine.exe", gamesDir, destinations );
2979
2980 string sysToolsDir = startMenuDir + sSep + "Programs" + sSep + "System Tools";
2981 OutputMakeLinkCommand ( "Character Map", "charmap.exe", sysToolsDir, destinations );
2982 OutputMakeLinkCommand ( "Keyboard Layout Switcher", "kbswitch.exe", sysToolsDir, destinations );
2983 OutputMakeLinkCommand ( "ReactX Diagnostic", "dxdiag.exe", sysToolsDir, destinations );
2984 OutputMakeLinkCommand ( "Regedit", "regedit.exe", sysToolsDir, destinations );
2985 }
2986
2987 void
2988 MingwLiveIsoModuleHandler::OutputRegistryCommands ( string& livecdDirectory )
2989 {
2990 string registrySourceFiles = backend->GetRegistrySourceFiles ();
2991 fprintf ( fMakefile, "# REGISTRY COMMANDS\n" );
2992 FileLocation reactosSystem32ConfigDirectory ( OutputDirectory,
2993 livecdDirectory + sSep + "reactos" + sSep + "system32" + sSep + "config",
2994 "" );
2995 fprintf ( fMakefile,
2996 "\t$(ECHO_MKHIVE)\n" );
2997 fprintf ( fMakefile,
2998 "\t$(Q)$(mkhive_TARGET) %s %s boot%cbootdata%clivecd.inf\n",
2999 backend->GetFullPath ( reactosSystem32ConfigDirectory ).c_str (),
3000 registrySourceFiles.c_str(),
3001 cSep, cSep );
3002 }
3003
3004 void
3005 MingwLiveIsoModuleHandler::GenerateLiveIsoModuleTarget ()
3006 {
3007 fprintf ( fMakefile, "# LIVE ISO MODULE TARGET\n" );
3008 string livecdDirectory = module.name;
3009 FileLocation livecd ( OutputDirectory, livecdDirectory, "" );
3010
3011 string IsoName;
3012
3013 // bootsector
3014 const Module* bootModule = module.bootSector->bootSectorModule;
3015
3016 if (!bootModule)
3017 {
3018 throw InvalidOperationException ( module.node.location.c_str(),
3019 0,
3020 "Invalid bootsector. module '%s' requires <bootsector>",
3021 module.name.c_str ());
3022 }
3023
3024 const FileLocation *isoboot = bootModule->output;
3025
3026 /*
3027 We use only the name and not full FileLocation(ouput) because Iso/LiveIso are an exception to the general rule.
3028 Iso/LiveIso outputs are generated in code base root
3029 */
3030 IsoName = module.output->name;
3031
3032 string reactosDirectory = "reactos";
3033 string livecdReactosNoFixup = livecdDirectory + sSep + reactosDirectory;
3034 FileLocation livecdReactos ( OutputDirectory,
3035 livecdReactosNoFixup,
3036 "" );
3037 CLEAN_FILE ( livecdReactos );
3038
3039 std::vector<FileLocation> sourceFiles;
3040 OutputModuleCopyCommands ( livecdDirectory,
3041 reactosDirectory,
3042 sourceFiles );
3043 OutputNonModuleCopyCommands ( livecdDirectory,
3044 reactosDirectory,
3045 sourceFiles );
3046 OutputProfilesDirectoryCommands ( livecdDirectory, sourceFiles );
3047 OutputLoaderCommands ( livecdDirectory, sourceFiles );
3048 OutputShortcutCommands ( livecdDirectory, sourceFiles );
3049
3050 fprintf( fMakefile,
3051 "\n%s_OBJS := %s\n\n",
3052 module.name.c_str (),
3053 backend->v2s ( sourceFiles, 5, true ).c_str () );
3054
3055 fprintf ( fMakefile, ".PHONY: %s\n\n",
3056 module.name.c_str ());
3057 fprintf ( fMakefile,
3058 "%s : $(%s_OBJS) %s %s $(mkhive_TARGET) $(cdmake_TARGET)\n",
3059 module.name.c_str (),
3060 module.name.c_str (),
3061 backend->GetFullName ( *isoboot) .c_str (),
3062 backend->GetFullPath ( FileLocation ( OutputDirectory,
3063 livecdDirectory,
3064 "" ) ).c_str () );
3065 OutputRegistryCommands ( livecdDirectory );
3066 fprintf ( fMakefile, "\t$(ECHO_CDMAKE)\n" );
3067 fprintf ( fMakefile,
3068 "\t$(Q)$(cdmake_TARGET) -v -m -j -b %s %s REACTOS %s\n",
3069 backend->GetFullName( *isoboot ).c_str (),
3070 backend->GetFullPath ( livecd ).c_str (),
3071 IsoName.c_str() );
3072 fprintf ( fMakefile,
3073 "\n" );
3074 }
3075
3076
3077 MingwTestModuleHandler::MingwTestModuleHandler (
3078 const Module& module_ )
3079
3080 : MingwModuleHandler ( module_ )
3081 {
3082 }
3083
3084 void
3085 MingwTestModuleHandler::Process ()
3086 {
3087 GenerateTestModuleTarget ();
3088 }
3089
3090 /* caller needs to delete the returned object */
3091 void
3092 MingwTestModuleHandler::GetModuleSpecificCompilationUnits ( vector<CompilationUnit*>& compilationUnits )
3093 {
3094 compilationUnits.push_back ( new CompilationUnit ( new File ( IntermediateDirectory, module.output->relative_path + sSep + "..", module.name + "_hooks.c", false, "", false ) ) );
3095 compilationUnits.push_back ( new CompilationUnit ( new File ( IntermediateDirectory, module.output->relative_path + sSep + "..", module.name + "_stubs.S", false, "", false ) ) );
3096 compilationUnits.push_back ( new CompilationUnit ( new File ( IntermediateDirectory, module.output->relative_path + sSep + "..", module.name + "_startup.c", false, "", false ) ) );
3097 }
3098
3099 void
3100 MingwTestModuleHandler::GenerateTestModuleTarget ()
3101 {
3102 GenerateRules ();
3103 GenerateLinkerCommand ();
3104 }
3105
3106
3107 MingwAliasModuleHandler::MingwAliasModuleHandler (
3108 const Module& module_ )
3109
3110 : MingwModuleHandler ( module_ )
3111 {
3112 }
3113
3114 void
3115 MingwAliasModuleHandler::Process ()
3116 {
3117 }
3118
3119
3120 MingwCabinetModuleHandler::MingwCabinetModuleHandler (
3121 const Module& module_ )
3122
3123 : MingwModuleHandler ( module_ )
3124 {
3125 }
3126
3127 void
3128 MingwCabinetModuleHandler::Process ()
3129 {
3130 fprintf ( fMakefile, "# CABINET MODULE TARGET\n" );
3131 string targetMacro ( GetTargetMacro (module) );
3132
3133 GenerateRules ();
3134
3135 const FileLocation *target_file = GetTargetFilename ( module, NULL );
3136 fprintf ( fMakefile, "%s: $(cabman_TARGET) | %s\n",
3137 targetMacro.c_str (),
3138 backend->GetFullPath ( *target_file ).c_str () );
3139
3140 fprintf ( fMakefile, "\t$(ECHO_CABMAN)\n" );
3141 fprintf ( fMakefile,
3142 "\t$(Q)$(cabman_TARGET) -M raw -S %s $(%s_SOURCES)\n", // Escape the asterisk for Make
3143 targetMacro.c_str (),
3144 module.name.c_str());
3145 }
3146
3147 MingwElfExecutableModuleHandler::MingwElfExecutableModuleHandler (
3148 const Module& module_ )
3149
3150 : MingwModuleHandler ( module_ )
3151 {
3152 }
3153
3154 void
3155 MingwElfExecutableModuleHandler::Process ()
3156 {
3157 string targetName ( module.output->name );
3158 string targetMacro ( GetTargetMacro (module) );
3159 string workingDirectory = GetWorkingDirectory ();
3160 string objectsMacro = GetObjectsMacro ( module );
3161 string libsMacro = GetLibsMacro ();
3162 string debugFormat = GetDebugFormat ();
3163
3164 fprintf ( fMakefile, "# ELF EXECUTABLE TARGET\n" );
3165 GenerateRules ();
3166
3167 const FileLocation *target_file = GetTargetFilename ( module, NULL );
3168 fprintf ( fMakefile, "%s: %s %s | %s\n",
3169 targetMacro.c_str (),
3170 objectsMacro.c_str (),
3171 libsMacro.c_str (),
3172 backend->GetFullPath ( *target_file ).c_str () );
3173
3174 fprintf ( fMakefile, "\t$(ECHO_BOOTPROG)\n" );
3175
3176 fprintf ( fMakefile, "\t${gcc} $(%s_LINKFORMAT) %s %s -g%s -o %s\n",
3177 module.buildtype.c_str(),
3178 objectsMacro.c_str(),
3179 libsMacro.c_str(),
3180 debugFormat.c_str(),
3181 targetMacro.c_str () );
3182
3183 delete target_file;
3184 fprintf ( fMakefile, "#/ELF EXECUTABLE TARGET\n" );
3185 }