943ef623427977ae8daa49400016e2a997488f83
6 #include "modulehandler.h"
13 typedef set
<string
> set_string
;
14 typedef map
<string
,Directory
*> directory_map
;
20 directory_map subdirs
;
21 Directory ( const string
& name
);
22 void Add ( const char* subdir
);
23 void CreateRule ( FILE* f
, const string
& parent
);
26 Directory::Directory ( const string
& name_
)
31 void Directory::Add ( const char* subdir
)
33 const char* p
= strpbrk ( subdir
, "/\\" );
35 p
= subdir
+ strlen(subdir
);
36 string
s ( subdir
, p
-subdir
);
37 if ( subdirs
.find(s
) == subdirs
.end() )
38 subdirs
[s
] = new Directory(s
);
40 subdirs
[s
]->Add ( p
);
44 Directory::CreateRule ( FILE* f
, const string
& parent
)
58 "\t$(ECHO_MKDIR)\n" );
63 path
= parent
+ SSEP
+ name
;
68 for ( directory_map::iterator i
= subdirs
.begin();
72 i
->second
->CreateRule ( f
, path
);
76 static class MingwFactory
: public Backend::Factory
79 MingwFactory() : Factory ( "mingw" ) {}
80 Backend
* operator() ( Project
& project
)
82 return new MingwBackend ( project
);
87 MingwBackend::MingwBackend ( Project
& project
)
88 : Backend ( project
),
89 int_directories ( new Directory("$(INTERMEDIATE)") ),
90 out_directories ( new Directory("$(OUTPUT)") )
94 MingwBackend::~MingwBackend()
96 delete int_directories
;
97 delete out_directories
;
101 MingwBackend::AddDirectoryTarget ( const string
& directory
, bool out
)
103 const char* dir_name
= "$(INTERMEDIATE)";
104 Directory
* dir
= int_directories
;
107 dir_name
= "$(OUTPUT)";
108 dir
= out_directories
;
110 dir
->Add ( directory
.c_str() );
115 MingwBackend::Process ()
123 GenerateGlobalVariables ();
124 GenerateXmlBuildFilesMacro();
126 vector
<MingwModuleHandler
*> v
;
128 for ( i
= 0; i
< ProjectNode
.modules
.size (); i
++ )
130 Module
& module
= *ProjectNode
.modules
[i
];
131 MingwModuleHandler
* h
= MingwModuleHandler::InstanciateHandler (
134 if ( module
.host
== HostDefault
)
136 module
.host
= h
->DefaultHost();
137 assert ( module
.host
!= HostDefault
);
142 size_t iend
= v
.size ();
144 for ( i
= 0; i
< iend
; i
++ )
145 v
[i
]->GenerateObjectMacro();
146 for ( i
= 0; i
< iend
; i
++ )
147 v
[i
]->GenerateTargetMacro();
148 fprintf ( fMakefile
, "\n" );
150 GenerateAllTarget ( v
);
151 GenerateInitTarget ();
153 for ( i
= 0; i
< iend
; i
++ )
154 v
[i
]->GenerateOtherMacros();
156 for ( i
= 0; i
< iend
; i
++ )
158 MingwModuleHandler
& h
= *v
[i
];
159 h
.GeneratePreconditionDependencies ();
161 h
.GenerateInvocations ();
162 h
.GenerateCleanTarget ();
166 GenerateDirectoryTargets ();
167 CheckAutomaticDependencies ();
172 MingwBackend::CreateMakefile ()
174 fMakefile
= fopen ( ProjectNode
.makefile
.c_str (), "w" );
176 throw AccessDeniedException ( ProjectNode
.makefile
);
177 MingwModuleHandler::SetBackend ( this );
178 MingwModuleHandler::SetMakefile ( fMakefile
);
179 MingwModuleHandler::SetUsePch ( use_pch
);
183 MingwBackend::CloseMakefile () const
186 fclose ( fMakefile
);
190 MingwBackend::GenerateHeader () const
192 fprintf ( fMakefile
, "# THIS FILE IS AUTOMATICALLY GENERATED, EDIT 'ReactOS.xml' INSTEAD\n\n" );
196 MingwBackend::GenerateProjectCFlagsMacro ( const char* assignmentOperation
,
197 IfableData
& data
) const
204 assignmentOperation
);
205 for ( i
= 0; i
< data
.includes
.size(); i
++ )
210 data
.includes
[i
]->directory
.c_str() );
213 for ( i
= 0; i
< data
.defines
.size(); i
++ )
215 Define
& d
= *data
.defines
[i
];
220 if ( d
.value
.size() )
226 fprintf ( fMakefile
, "\n" );
230 MingwBackend::GenerateGlobalCFlagsAndProperties (
231 const char* assignmentOperation
,
232 IfableData
& data
) const
236 for ( i
= 0; i
< data
.properties
.size(); i
++ )
238 Property
& prop
= *data
.properties
[i
];
239 fprintf ( fMakefile
, "%s := %s\n",
241 prop
.value
.c_str() );
244 if ( data
.includes
.size() || data
.defines
.size() )
246 GenerateProjectCFlagsMacro ( assignmentOperation
,
250 for ( i
= 0; i
< data
.ifs
.size(); i
++ )
252 If
& rIf
= *data
.ifs
[i
];
253 if ( rIf
.data
.defines
.size()
254 || rIf
.data
.includes
.size()
255 || rIf
.data
.ifs
.size() )
259 "ifeq (\"$(%s)\",\"%s\")\n",
260 rIf
.property
.c_str(),
262 GenerateGlobalCFlagsAndProperties (
273 MingwBackend::GenerateProjectLFLAGS () const
276 for ( size_t i
= 0; i
< ProjectNode
.linkerFlags
.size (); i
++ )
278 LinkerFlag
& linkerFlag
= *ProjectNode
.linkerFlags
[i
];
279 if ( lflags
.length () > 0 )
281 lflags
+= linkerFlag
.flag
;
287 MingwBackend::GenerateGlobalVariables () const
289 GenerateGlobalCFlagsAndProperties (
291 ProjectNode
.non_if_data
);
292 fprintf ( fMakefile
, "PROJECT_RCFLAGS = $(PROJECT_CFLAGS)\n" );
293 fprintf ( fMakefile
, "PROJECT_LFLAGS = %s\n",
294 GenerateProjectLFLAGS ().c_str () );
295 fprintf ( fMakefile
, "\n" );
299 MingwBackend::IncludeInAllTarget ( const Module
& module
) const
301 if ( module
.type
== ObjectLibrary
)
303 if ( module
.type
== BootSector
)
305 if ( module
.type
== Iso
)
311 MingwBackend::GenerateAllTarget ( const vector
<MingwModuleHandler
*>& handlers
) const
313 fprintf ( fMakefile
, "all:" );
315 size_t iend
= handlers
.size ();
316 for ( size_t i
= 0; i
< iend
; i
++ )
318 const Module
& module
= handlers
[i
]->module
;
319 if ( IncludeInAllTarget ( module
) )
321 if ( wrap_count
++ == 5 )
322 fprintf ( fMakefile
, " \\\n\t\t" ), wrap_count
= 0;
325 GetTargetMacro(module
).c_str () );
328 fprintf ( fMakefile
, "\n\t\n\n" );
332 MingwBackend::GetBuildToolDependencies () const
335 for ( size_t i
= 0; i
< ProjectNode
.modules
.size (); i
++ )
337 Module
& module
= *ProjectNode
.modules
[i
];
338 if ( module
.type
== BuildTool
)
340 if ( dependencies
.length () > 0 )
342 dependencies
+= module
.GetDependencyPath ();
349 MingwBackend::GenerateInitTarget () const
353 GetBuildToolDependencies ().c_str () );
354 fprintf ( fMakefile
, "\n" );
358 MingwBackend::GenerateXmlBuildFilesMacro() const
361 "XMLBUILDFILES = %s \\\n",
362 ProjectNode
.GetProjectFilename ().c_str () );
363 string xmlbuildFilenames
;
364 int numberOfExistingFiles
= 0;
365 for ( size_t i
= 0; i
< ProjectNode
.xmlbuildfiles
.size (); i
++ )
367 XMLInclude
& xmlbuildfile
= *ProjectNode
.xmlbuildfiles
[i
];
368 if ( !xmlbuildfile
.fileExists
)
370 numberOfExistingFiles
++;
371 if ( xmlbuildFilenames
.length () > 0 )
372 xmlbuildFilenames
+= " ";
373 xmlbuildFilenames
+= NormalizeFilename ( xmlbuildfile
.topIncludeFilename
);
374 if ( numberOfExistingFiles
% 5 == 4 || i
== ProjectNode
.xmlbuildfiles
.size () - 1 )
378 xmlbuildFilenames
.c_str ());
379 if ( i
== ProjectNode
.xmlbuildfiles
.size () - 1 )
381 fprintf ( fMakefile
, "\n" );
387 xmlbuildFilenames
.c_str () );
389 xmlbuildFilenames
.resize ( 0 );
391 numberOfExistingFiles
++;
393 fprintf ( fMakefile
, "\n" );
397 MingwBackend::CheckAutomaticDependencies ()
399 AutomaticDependency
automaticDependency ( ProjectNode
);
400 automaticDependency
.Process ();
401 automaticDependency
.CheckAutomaticDependencies ();
405 MingwBackend::IncludeDirectoryTarget ( const string
& directory
) const
407 if ( directory
== "$(INTERMEDIATE)" SSEP
"tools")
414 MingwBackend::GenerateDirectoryTargets ()
416 // TODO FIXME - write new directory creation
417 for ( int i
= 0; i
< 2; i
++ )
419 Directory
& d
= *(!i
? int_directories
: out_directories
);
420 if ( i
) fprintf ( fMakefile
, "ifneq ($(INTERMEDIATE),$(OUTPUT))\n" );
421 d
.CreateRule ( fMakefile
, "" );
422 if ( i
) fprintf ( fMakefile
, "endif\n" );
427 FixupTargetFilename ( const string
& targetFilename
)
429 return NormalizeFilename ( targetFilename
);
433 MingwBackend::DetectPCHSupport()
438 string sNUL
= "/dev/null";
440 string path
= "tools" SSEP
"rbuild" SSEP
"backend" SSEP
"mingw" SSEP
"pch_detection.h";
441 string cmd
= ssprintf(
445 system ( cmd
.c_str() );
448 FILE* f
= fopen ( path
.c_str(), "rb" );
453 unlink ( path
.c_str() );
458 // TODO FIXME - eventually check for ROS_USE_PCH env var and
459 // allow that to override use_pch if true