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