* Nasm support
[reactos.git] / reactos / tools / rbuild / module.cpp
1 // module.cpp
2
3 #include "pch.h"
4 #include <assert.h>
5
6 #include "rbuild.h"
7
8 using std::string;
9 using std::vector;
10
11 string
12 FixSeparator ( const string& s )
13 {
14 string s2(s);
15 char* p = strchr ( &s2[0], CBAD_SEP );
16 while ( p )
17 {
18 *p++ = CSEP;
19 p = strchr ( p, CBAD_SEP );
20 }
21 return s2;
22 }
23
24 Module::Module ( const Project& project,
25 const XMLElement& moduleNode,
26 const string& modulePath )
27 : project (project),
28 node (moduleNode),
29 importLibrary (NULL)
30 {
31 if ( node.name != "module" )
32 throw Exception ( "internal tool error: Module created with non-<module> node" );
33
34 path = FixSeparator ( modulePath );
35
36 const XMLAttribute* att = moduleNode.GetAttribute ( "name", true );
37 assert(att);
38 name = att->value;
39
40 att = moduleNode.GetAttribute ( "type", true );
41 assert(att);
42 type = GetModuleType ( node.location, *att );
43
44 att = moduleNode.GetAttribute ( "extension", false );
45 if (att != NULL)
46 extension = att->value;
47 else
48 extension = GetDefaultModuleExtension ();
49 }
50
51 Module::~Module ()
52 {
53 size_t i;
54 for ( i = 0; i < files.size(); i++ )
55 delete files[i];
56 for ( i = 0; i < libraries.size(); i++ )
57 delete libraries[i];
58 for ( i = 0; i < includes.size(); i++ )
59 delete includes[i];
60 for ( i = 0; i < defines.size(); i++ )
61 delete defines[i];
62 for ( i = 0; i < invocations.size(); i++ )
63 delete invocations[i];
64 for ( i = 0; i < dependencies.size(); i++ )
65 delete dependencies[i];
66 }
67
68 void
69 Module::ProcessXML()
70 {
71 size_t i;
72 for ( i = 0; i < node.subElements.size(); i++ )
73 ProcessXMLSubElement ( *node.subElements[i], path );
74 for ( i = 0; i < files.size (); i++ )
75 files[i]->ProcessXML ();
76 for ( i = 0; i < libraries.size(); i++ )
77 libraries[i]->ProcessXML ();
78 for ( i = 0; i < includes.size(); i++ )
79 includes[i]->ProcessXML ();
80 for ( i = 0; i < defines.size(); i++ )
81 defines[i]->ProcessXML ();
82 for ( i = 0; i < invocations.size(); i++ )
83 invocations[i]->ProcessXML ();
84 for ( i = 0; i < dependencies.size(); i++ )
85 dependencies[i]->ProcessXML ();
86 }
87
88 void
89 Module::ProcessXMLSubElement ( const XMLElement& e,
90 const string& path )
91 {
92 bool subs_invalid = false;
93 string subpath ( path );
94 if ( e.name == "file" && e.value.size () > 0 )
95 {
96 files.push_back ( new File ( FixSeparator ( path + CSEP + e.value ) ) );
97 subs_invalid = true;
98 }
99 else if ( e.name == "library" && e.value.size () )
100 {
101 libraries.push_back ( new Library ( e, *this, e.value ) );
102 subs_invalid = true;
103 }
104 else if ( e.name == "directory" )
105 {
106 const XMLAttribute* att = e.GetAttribute ( "name", true );
107 assert(att);
108 subpath = FixSeparator ( path + CSEP + att->value );
109 }
110 else if ( e.name == "include" )
111 {
112 includes.push_back ( new Include ( project, this, e ) );
113 subs_invalid = true;
114 }
115 else if ( e.name == "define" )
116 {
117 defines.push_back ( new Define ( project, this, e ) );
118 subs_invalid = true;
119 }
120 else if ( e.name == "invoke" )
121 {
122 invocations.push_back ( new Invoke ( e, *this ) );
123 subs_invalid = false;
124 }
125 else if ( e.name == "dependency" )
126 {
127 dependencies.push_back ( new Dependency ( e, *this ) );
128 subs_invalid = true;
129 }
130 else if ( e.name == "importlibrary" )
131 {
132 importLibrary = new ImportLibrary ( e, *this );
133 subs_invalid = true;
134 }
135 if ( subs_invalid && e.subElements.size() > 0 )
136 throw InvalidBuildFileException (
137 e.location,
138 "<%s> cannot have sub-elements",
139 e.name.c_str() );
140 for ( size_t i = 0; i < e.subElements.size (); i++ )
141 ProcessXMLSubElement ( *e.subElements[i], subpath );
142 }
143
144 ModuleType
145 Module::GetModuleType ( const string& location, const XMLAttribute& attribute )
146 {
147 if ( attribute.value == "buildtool" )
148 return BuildTool;
149 if ( attribute.value == "staticlibrary" )
150 return StaticLibrary;
151 if ( attribute.value == "kernel" )
152 return Kernel;
153 if ( attribute.value == "kernelmodedll" )
154 return KernelModeDLL;
155 throw InvalidAttributeValueException ( location,
156 attribute.name,
157 attribute.value );
158 }
159
160 string
161 Module::GetDefaultModuleExtension () const
162 {
163 switch (type)
164 {
165 case BuildTool:
166 return EXEPOSTFIX;
167 case StaticLibrary:
168 return ".a";
169 case Kernel:
170 return ".exe";
171 case KernelModeDLL:
172 return ".dll";
173 }
174 throw InvalidOperationException (__FILE__,
175 __LINE__);
176 }
177
178 string
179 Module::GetTargetName () const
180 {
181 return name + extension;
182 }
183
184 string
185 Module::GetDependencyPath () const
186 {
187 if ( type == KernelModeDLL )
188 return ssprintf ( "dk%snkm%slib%slib%s.a",
189 SSEP,
190 SSEP,
191 SSEP,
192 name.c_str () );
193 else
194 return GetPath ();
195 }
196
197 string
198 Module::GetBasePath () const
199 {
200 return path;
201 }
202
203 string
204 Module::GetPath () const
205 {
206 return path + CSEP + GetTargetName ();
207 }
208
209 string
210 Module::GetPathWithPrefix ( const string& prefix ) const
211 {
212 return path + CSEP + prefix + GetTargetName ();
213 }
214
215 string
216 Module::GetTargets () const
217 {
218 if ( invocations.size () > 0 )
219 {
220 string targets ( "" );
221 for ( size_t i = 0; i < invocations.size (); i++ )
222 {
223 Invoke& invoke = *invocations[i];
224 if ( targets.length () > 0 )
225 targets += " ";
226 targets += invoke.GetTargets ();
227 }
228 return targets;
229 }
230 else
231 return GetPath ();
232 }
233
234 string
235 Module::GetInvocationTarget ( const int index ) const
236 {
237 return ssprintf ( "%s_invoke_%d",
238 name.c_str (),
239 index );
240 }
241
242
243 File::File ( const string& _name )
244 : name(_name)
245 {
246 }
247
248 void
249 File::ProcessXML()
250 {
251 }
252
253
254 Library::Library ( const XMLElement& _node,
255 const Module& _module,
256 const string& _name )
257 : node(_node),
258 module(_module),
259 name(_name)
260 {
261 if ( module.name == name )
262 throw InvalidBuildFileException (
263 node.location,
264 "module '%s' cannot link against itself",
265 name.c_str() );
266 }
267
268 void
269 Library::ProcessXML()
270 {
271 if ( !module.project.LocateModule ( name ) )
272 throw InvalidBuildFileException (
273 node.location,
274 "module '%s' is trying to link against non-existant module '%s'",
275 module.name.c_str(),
276 name.c_str() );
277 }
278
279
280 Invoke::Invoke ( const XMLElement& _node,
281 const Module& _module )
282 : node (_node),
283 module (_module)
284 {
285 }
286
287 void
288 Invoke::ProcessXML()
289 {
290 const XMLAttribute* att = node.GetAttribute ( "module", false );
291 if (att == NULL)
292 invokeModule = &module;
293 else
294 {
295 invokeModule = module.project.LocateModule ( att->value );
296 if ( invokeModule == NULL )
297 throw InvalidBuildFileException (
298 node.location,
299 "module '%s' is trying to invoke non-existant module '%s'",
300 module.name.c_str(),
301 att->value.c_str() );
302 }
303
304 for ( size_t i = 0; i < node.subElements.size (); i++ )
305 ProcessXMLSubElement ( *node.subElements[i] );
306 }
307
308 void
309 Invoke::ProcessXMLSubElement ( const XMLElement& e )
310 {
311 bool subs_invalid = false;
312 if ( e.name == "input" )
313 {
314 for ( size_t i = 0; i < e.subElements.size (); i++ )
315 ProcessXMLSubElementInput ( *e.subElements[i] );
316 }
317 else if ( e.name == "output" )
318 {
319 for ( size_t i = 0; i < e.subElements.size (); i++ )
320 ProcessXMLSubElementOutput ( *e.subElements[i] );
321 }
322 if ( subs_invalid && e.subElements.size() > 0 )
323 throw InvalidBuildFileException ( e.location,
324 "<%s> cannot have sub-elements",
325 e.name.c_str() );
326 }
327
328 void
329 Invoke::ProcessXMLSubElementInput ( const XMLElement& e )
330 {
331 bool subs_invalid = false;
332 if ( e.name == "inputfile" && e.value.size () > 0 )
333 {
334 input.push_back ( new InvokeFile ( e, FixSeparator ( module.path + CSEP + e.value ) ) );
335 subs_invalid = true;
336 }
337 if ( subs_invalid && e.subElements.size() > 0 )
338 throw InvalidBuildFileException ( e.location,
339 "<%s> cannot have sub-elements",
340 e.name.c_str() );
341 }
342
343 void
344 Invoke::ProcessXMLSubElementOutput ( const XMLElement& e )
345 {
346 bool subs_invalid = false;
347 if ( e.name == "outputfile" && e.value.size () > 0 )
348 {
349 output.push_back ( new InvokeFile ( e, FixSeparator ( module.path + CSEP + e.value ) ) );
350 subs_invalid = true;
351 }
352 if ( subs_invalid && e.subElements.size() > 0 )
353 throw InvalidBuildFileException ( e.location,
354 "<%s> cannot have sub-elements",
355 e.name.c_str() );
356 }
357
358 string
359 Invoke::GetTargets () const
360 {
361 string targets ( "" );
362 for ( size_t i = 0; i < output.size (); i++ )
363 {
364 InvokeFile& file = *output[i];
365 if ( targets.length () > 0 )
366 targets += " ";
367 targets += file.name;
368 }
369 return targets;
370 }
371
372
373 InvokeFile::InvokeFile ( const XMLElement& _node,
374 const string& _name )
375 : node (_node),
376 name (_name)
377 {
378 const XMLAttribute* att = _node.GetAttribute ( "switches", false );
379 if (att != NULL)
380 switches = att->value;
381 else
382 switches = "";
383 }
384
385 void
386 InvokeFile::ProcessXML()
387 {
388 }
389
390
391 Dependency::Dependency ( const XMLElement& _node,
392 const Module& _module )
393 : node (_node),
394 module (_module),
395 dependencyModule (NULL)
396 {
397 }
398
399 void
400 Dependency::ProcessXML()
401 {
402 dependencyModule = module.project.LocateModule ( node.value );
403 if ( dependencyModule == NULL )
404 throw InvalidBuildFileException ( node.location,
405 "module '%s' depend on non-existant module '%s'",
406 module.name.c_str(),
407 node.value.c_str() );
408 }
409
410
411 ImportLibrary::ImportLibrary ( const XMLElement& _node,
412 const Module& _module )
413 : node (_node),
414 module (_module)
415 {
416 const XMLAttribute* att = _node.GetAttribute ( "basename", false );
417 if (att != NULL)
418 basename = att->value;
419 else
420 basename = module.name;
421
422 att = _node.GetAttribute ( "definition", true );
423 assert (att);
424 definition = att->value;
425 }