Copy msiexec from trunk
[reactos.git] / reactos / tools / rbuild / backend / mingw / mingw.cpp
1
2 #include "../../pch.h"
3
4 #include "mingw.h"
5 #include <assert.h>
6
7 using std::string;
8 using std::vector;
9
10 static class MingwFactory : public Backend::Factory
11 {
12 public:
13 MingwFactory() : Factory ( "mingw" ) {}
14 Backend* operator() ( Project& project )
15 {
16 return new MingwBackend ( project );
17 }
18 } factory;
19
20
21 MingwBackend::MingwBackend ( Project& project )
22 : Backend ( project )
23 {
24 }
25
26 void
27 MingwBackend::Process ()
28 {
29 CreateMakefile ();
30 GenerateHeader ();
31 GenerateGlobalVariables ();
32 GenerateAllTarget ();
33 GenerateInitTarget ();
34 for ( size_t i = 0; i < ProjectNode.modules.size (); i++ )
35 {
36 Module& module = *ProjectNode.modules[i];
37 ProcessModule ( module );
38 }
39 CheckAutomaticDependencies ();
40 CloseMakefile ();
41 }
42
43 void
44 MingwBackend::CreateMakefile ()
45 {
46 fMakefile = fopen ( ProjectNode.makefile.c_str (), "w" );
47 if ( !fMakefile )
48 throw AccessDeniedException ( ProjectNode.makefile );
49 MingwModuleHandler::SetMakefile ( fMakefile );
50 }
51
52 void
53 MingwBackend::CloseMakefile () const
54 {
55 if (fMakefile)
56 fclose ( fMakefile );
57 }
58
59 void
60 MingwBackend::GenerateHeader () const
61 {
62 fprintf ( fMakefile, "# THIS FILE IS AUTOMATICALLY GENERATED, EDIT 'ReactOS.xml' INSTEAD\n\n" );
63 }
64
65 void
66 MingwBackend::GenerateProjectCFlagsMacro ( const char* assignmentOperation,
67 const vector<Include*>& includes,
68 const vector<Define*>& defines ) const
69 {
70 size_t i;
71
72 fprintf (
73 fMakefile,
74 "PROJECT_CFLAGS %s",
75 assignmentOperation );
76 for ( i = 0; i < includes.size(); i++ )
77 {
78 fprintf (
79 fMakefile,
80 " -I%s",
81 includes[i]->directory.c_str() );
82 }
83
84 for ( i = 0; i < defines.size(); i++ )
85 {
86 Define& d = *defines[i];
87 fprintf (
88 fMakefile,
89 " -D%s",
90 d.name.c_str() );
91 if ( d.value.size() )
92 fprintf (
93 fMakefile,
94 "=%s",
95 d.value.c_str() );
96 }
97 fprintf ( fMakefile, "\n" );
98 }
99
100 void
101 MingwBackend::GenerateGlobalCFlagsAndProperties (
102 const char* assignmentOperation,
103 const vector<Property*>& properties,
104 const vector<Include*>& includes,
105 const vector<Define*>& defines,
106 const vector<If*>& ifs ) const
107 {
108 size_t i;
109
110 for ( i = 0; i < properties.size(); i++ )
111 {
112 Property& prop = *properties[i];
113 fprintf ( fMakefile, "%s := %s\n",
114 prop.name.c_str(),
115 prop.value.c_str() );
116 }
117
118 if ( includes.size() || defines.size() )
119 {
120 GenerateProjectCFlagsMacro ( assignmentOperation,
121 includes,
122 defines );
123 }
124
125 for ( i = 0; i < ifs.size(); i++ )
126 {
127 If& rIf = *ifs[i];
128 if ( rIf.defines.size() || rIf.includes.size() || rIf.ifs.size() )
129 {
130 fprintf (
131 fMakefile,
132 "ifeq (\"$(%s)\",\"%s\")\n",
133 rIf.property.c_str(),
134 rIf.value.c_str() );
135 GenerateGlobalCFlagsAndProperties (
136 "+=",
137 rIf.properties,
138 rIf.includes,
139 rIf.defines,
140 rIf.ifs );
141 fprintf (
142 fMakefile,
143 "endif\n\n" );
144 }
145 }
146 }
147
148 string
149 MingwBackend::GenerateProjectLFLAGS () const
150 {
151 string lflags;
152 for ( size_t i = 0; i < ProjectNode.linkerFlags.size (); i++ )
153 {
154 LinkerFlag& linkerFlag = *ProjectNode.linkerFlags[i];
155 if ( lflags.length () > 0 )
156 lflags += " ";
157 lflags += linkerFlag.flag;
158 }
159 return lflags;
160 }
161
162 void
163 MingwBackend::GenerateGlobalVariables () const
164 {
165 fprintf ( fMakefile, "mkdir = tools" SSEP "rmkdir" EXEPOSTFIX "\n" );
166 fprintf ( fMakefile, "winebuild = tools" SSEP "winebuild" SSEP "winebuild" EXEPOSTFIX "\n" );
167 fprintf ( fMakefile, "bin2res = tools" SSEP "bin2res" SSEP "bin2res" EXEPOSTFIX "\n" );
168 fprintf ( fMakefile, "cabman = tools" SSEP "cabman" SSEP "cabman" EXEPOSTFIX "\n" );
169 fprintf ( fMakefile, "cdmake = tools" SSEP "cdmake" SSEP "cdmake" EXEPOSTFIX "\n" );
170 fprintf ( fMakefile, "wrc = tools" SSEP "wrc" SSEP "wrc" EXEPOSTFIX "\n" );
171 fprintf ( fMakefile, "\n" );
172 GenerateGlobalCFlagsAndProperties (
173 "=",
174 ProjectNode.properties,
175 ProjectNode.includes,
176 ProjectNode.defines,
177 ProjectNode.ifs );
178 fprintf ( fMakefile, "PROJECT_RCFLAGS = $(PROJECT_CFLAGS)\n" );
179 fprintf ( fMakefile, "PROJECT_LFLAGS = %s\n",
180 GenerateProjectLFLAGS ().c_str () );
181 fprintf ( fMakefile, "\n" );
182 }
183
184 bool
185 MingwBackend::IncludeInAllTarget ( const Module& module ) const
186 {
187 if ( module.type == ObjectLibrary )
188 return false;
189 if ( module.type == BootSector )
190 return false;
191 if ( module.type == Iso )
192 return false;
193 return true;
194 }
195
196 void
197 MingwBackend::GenerateAllTarget () const
198 {
199 fprintf ( fMakefile, "all:" );
200 for ( size_t i = 0; i < ProjectNode.modules.size (); i++ )
201 {
202 Module& module = *ProjectNode.modules[i];
203 if ( IncludeInAllTarget ( module ) )
204 {
205 fprintf ( fMakefile,
206 " %s",
207 FixupTargetFilename ( module.GetPath () ).c_str () );
208 }
209 }
210 fprintf ( fMakefile, "\n\t\n\n" );
211 }
212
213 string
214 MingwBackend::GetBuildToolDependencies () const
215 {
216 string dependencies;
217 for ( size_t i = 0; i < ProjectNode.modules.size (); i++ )
218 {
219 Module& module = *ProjectNode.modules[i];
220 if ( module.type == BuildTool )
221 {
222 if ( dependencies.length () > 0 )
223 dependencies += " ";
224 dependencies += module.GetDependencyPath ();
225 }
226 }
227 return dependencies;
228 }
229
230 void
231 MingwBackend::GenerateInitTarget () const
232 {
233 fprintf ( fMakefile,
234 "init:");
235 fprintf ( fMakefile,
236 " $(ROS_INTERMEDIATE)." SSEP "tools" );
237 fprintf ( fMakefile,
238 " %s",
239 GetBuildToolDependencies ().c_str () );
240 fprintf ( fMakefile,
241 " %s",
242 "include" SSEP "reactos" SSEP "buildno.h" );
243 fprintf ( fMakefile,
244 "\n\t\n\n" );
245
246 fprintf ( fMakefile,
247 "$(ROS_INTERMEDIATE)." SSEP "tools:\n" );
248 fprintf ( fMakefile,
249 "ifneq ($(ROS_INTERMEDIATE),)\n" );
250 fprintf ( fMakefile,
251 "\t${nmkdir} $(ROS_INTERMEDIATE)\n" );
252 fprintf ( fMakefile,
253 "endif\n" );
254 fprintf ( fMakefile,
255 "\t${nmkdir} $(ROS_INTERMEDIATE)." SSEP "tools\n" );
256 fprintf ( fMakefile,
257 "\n" );
258 }
259
260 void
261 MingwBackend::CheckAutomaticDependencies ()
262 {
263 AutomaticDependency automaticDependency ( ProjectNode );
264 automaticDependency.Process ();
265 automaticDependency.CheckAutomaticDependencies ();
266 }
267
268 void
269 MingwBackend::ProcessModule ( Module& module ) const
270 {
271 MingwModuleHandler* h = MingwModuleHandler::LookupHandler (
272 module.node.location,
273 module.type );
274 h->Process ( module );
275 h->GenerateDirectoryTargets ();
276 }
277
278 string
279 FixupTargetFilename ( const string& targetFilename )
280 {
281 return string("$(ROS_INTERMEDIATE)") + NormalizeFilename ( targetFilename );
282 }