6d8a484067467fcecc3333c6bc34b130b79dcfc8
[reactos.git] / reactos / tools / rbuild / project.cpp
1
2 #include "pch.h"
3 #include <assert.h>
4
5 #include "rbuild.h"
6
7 using std::string;
8 using std::vector;
9
10 /*Project::Project()
11 : node(NULL), head(NULL)
12 {
13 }*/
14
15 Project::Project ( const string& filename )
16 : xmlfile(filename),
17 node(NULL),
18 head(NULL)
19 {
20 ReadXml();
21 }
22
23 Project::~Project ()
24 {
25 size_t i;
26 for ( i = 0; i < modules.size (); i++ )
27 delete modules[i];
28 for ( i = 0; i < includes.size(); i++ )
29 delete includes[i];
30 for ( i = 0; i < defines.size(); i++ )
31 delete defines[i];
32 for ( i = 0; i < linkerFlags.size(); i++ )
33 delete linkerFlags[i];
34 for ( i = 0; i < properties.size(); i++ )
35 delete properties[i];
36 for ( i = 0; i < ifs.size(); i++ )
37 delete ifs[i];
38 delete head;
39 }
40
41 void
42 Project::ReadXml()
43 {
44 Path path;
45 head = XMLLoadFile ( xmlfile, path );
46 node = NULL;
47 for ( size_t i = 0; i < head->subElements.size(); i++ )
48 {
49 if ( head->subElements[i]->name == "project" )
50 {
51 node = head->subElements[i];
52 this->ProcessXML ( "." );
53 return;
54 }
55 }
56
57 throw InvalidBuildFileException (
58 node->location,
59 "Document contains no 'project' tag." );
60 }
61
62 void
63 Project::ProcessXML ( const string& path )
64 {
65 const XMLAttribute *att;
66 if ( node->name != "project" )
67 throw Exception ( "internal tool error: Project::ProcessXML() called with non-<project> node" );
68
69 att = node->GetAttribute ( "name", false );
70 if ( !att )
71 name = "Unnamed";
72 else
73 name = att->value;
74
75 att = node->GetAttribute ( "makefile", true );
76 assert(att);
77 makefile = att->value;
78
79 size_t i;
80 for ( i = 0; i < node->subElements.size(); i++ )
81 ProcessXMLSubElement ( *node->subElements[i], path );
82 for ( i = 0; i < modules.size(); i++ )
83 modules[i]->ProcessXML();
84 for ( i = 0; i < includes.size(); i++ )
85 includes[i]->ProcessXML();
86 for ( i = 0; i < defines.size(); i++ )
87 defines[i]->ProcessXML();
88 for ( i = 0; i < linkerFlags.size(); i++ )
89 linkerFlags[i]->ProcessXML();
90 for ( i = 0; i < properties.size(); i++ )
91 properties[i]->ProcessXML();
92 for ( i = 0; i < ifs.size(); i++ )
93 ifs[i]->ProcessXML();
94 }
95
96 void
97 Project::ProcessXMLSubElement ( const XMLElement& e,
98 const string& path,
99 If* pIf /*= NULL*/ )
100 {
101 bool subs_invalid = false;
102 string subpath(path);
103 if ( e.name == "module" )
104 {
105 if ( pIf )
106 throw InvalidBuildFileException (
107 e.location,
108 "<module> is not a valid sub-element of <if>" );
109 Module* module = new Module ( *this, e, path );
110 if ( LocateModule ( module->name ) )
111 throw InvalidBuildFileException (
112 node->location,
113 "module name conflict: '%s' (originally defined at %s)",
114 module->name.c_str(),
115 module->node.location.c_str() );
116 modules.push_back ( module );
117 return; // defer processing until later
118 }
119 else if ( e.name == "directory" )
120 {
121 const XMLAttribute* att = e.GetAttribute ( "name", true );
122 assert(att);
123 subpath = path + CSEP + att->value;
124 }
125 else if ( e.name == "include" )
126 {
127 Include* include = new Include ( *this, e );
128 if ( pIf )
129 pIf->includes.push_back ( include );
130 else
131 includes.push_back ( include );
132 subs_invalid = true;
133 }
134 else if ( e.name == "define" )
135 {
136 Define* define = new Define ( *this, e );
137 if ( pIf )
138 pIf->defines.push_back ( define );
139 else
140 defines.push_back ( define );
141 subs_invalid = true;
142 }
143 else if ( e.name == "linkerflag" )
144 {
145 linkerFlags.push_back ( new LinkerFlag ( *this, e ) );
146 subs_invalid = true;
147 }
148 else if ( e.name == "if" )
149 {
150 If* pOldIf = pIf;
151 pIf = new If ( e, *this, NULL );
152 if ( pOldIf )
153 pOldIf->ifs.push_back ( pIf );
154 else
155 ifs.push_back ( pIf );
156 subs_invalid = false;
157 }
158 else if ( e.name == "property" )
159 {
160 Property* property = new Property ( e, *this, NULL );
161 if ( pIf )
162 pIf->properties.push_back ( property );
163 else
164 properties.push_back ( property );
165 }
166 if ( subs_invalid && e.subElements.size() )
167 throw InvalidBuildFileException (
168 e.location,
169 "<%s> cannot have sub-elements",
170 e.name.c_str() );
171 for ( size_t i = 0; i < e.subElements.size (); i++ )
172 ProcessXMLSubElement ( *e.subElements[i], subpath, pIf );
173 }
174
175 Module*
176 Project::LocateModule ( const string& name )
177 {
178 for ( size_t i = 0; i < modules.size (); i++ )
179 {
180 if (modules[i]->name == name)
181 return modules[i];
182 }
183
184 return NULL;
185 }
186
187 const Module*
188 Project::LocateModule ( const string& name ) const
189 {
190 for ( size_t i = 0; i < modules.size (); i++ )
191 {
192 if (modules[i]->name == name)
193 return modules[i];
194 }
195
196 return NULL;
197 }