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