Add ROS_ARCH environment variable
[reactos.git] / reactos / tools / rbuild / rbuild.cpp
1 /*
2 * Copyright (C) 2005 Casper S. Hornstrup
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 */
18 #include "pch.h"
19 #include <typeinfo>
20 #include <algorithm>
21
22 #include <stdio.h>
23 #ifdef WIN32
24 #include <io.h>
25 #endif
26 #include <assert.h>
27
28 #include "rbuild.h"
29 #include "backend/backend.h"
30 #include "backend/mingw/mingw.h"
31
32 using std::string;
33 using std::vector;
34
35 static string BuildSystem;
36 static string RootXmlFile;
37 static Configuration configuration;
38
39 bool
40 ParseAutomaticDependencySwitch (
41 char switchChar2,
42 char* switchStart )
43 {
44 switch ( switchChar2 )
45 {
46 case 'd':
47 configuration.AutomaticDependencies = false;
48 break;
49 case 'm':
50 if ( strlen ( switchStart ) <= 3 )
51 {
52 printf ( "Switch -dm requires a module name\n" );
53 return false;
54 }
55 configuration.CheckDependenciesForModuleOnly = true;
56 configuration.CheckDependenciesForModuleOnlyModule = string(&switchStart[3]);
57 break;
58 default:
59 printf ( "Unknown switch -d%c\n",
60 switchChar2 );
61 return false;
62 }
63 return true;
64 }
65
66 bool
67 ParseCompilationUnitSwitch (
68 char switchChar2,
69 char* switchStart )
70 {
71 switch ( switchChar2 )
72 {
73 case 'd':
74 configuration.CompilationUnitsEnabled = false;
75 break;
76 default:
77 printf ( "Unknown switch -u%c\n",
78 switchChar2 );
79 return false;
80 }
81 return true;
82 }
83
84 bool
85 ParseVCProjectSwitch (
86 char switchChar2,
87 char* switchStart )
88 {
89 string temp;
90
91 switch ( switchChar2 )
92 {
93 case 's':
94 if ( strlen ( switchStart ) <= 3 )
95 {
96 printf ( "Switch -dm requires a module name\n" );
97 return false;
98 }
99 configuration.VSProjectVersion = string(&switchStart[3]);
100
101 if (configuration.VSProjectVersion.at(0) == '{') {
102 printf ( "Error: invalid char {\n" );
103 return false;
104 }
105
106 if (configuration.VSProjectVersion.length() == 1) //7,8
107 configuration.VSProjectVersion.append(".00");
108
109 if (configuration.VSProjectVersion.length() == 3) //7.1
110 configuration.VSProjectVersion.append("0");
111
112 break;
113 case 'c':
114 configuration.VSConfigurationType = string (&switchStart[3]);
115 configuration.InstallFiles = true;
116 break;
117 case 'o':
118 if ( strlen ( switchStart ) <= 3 )
119 {
120 printf ( "Invalid switch\n" );
121 return false;
122 }
123 temp = string (&switchStart[3]);
124 if ( temp.find ("configuration") != string::npos )
125 configuration.UseConfigurationInPath = true;
126
127 if ( temp.find ("version") != string::npos )
128 configuration.UseVSVersionInPath = true;
129 break;
130 default:
131 printf ( "Unknown switch -d%c\n",
132 switchChar2 );
133 return false;
134 }
135 return true;
136 }
137
138 bool
139 ParseMakeSwitch ( char switchChar2 )
140 {
141 switch ( switchChar2 )
142 {
143 case 'i':
144 configuration.MakeHandlesInstallDirectories = true;
145 break;
146 default:
147 printf ( "Unknown switch -m%c\n",
148 switchChar2 );
149 return false;
150 }
151 return true;
152 }
153
154 bool
155 ParseProxyMakefileSwitch ( char switchChar2 )
156 {
157 switch ( switchChar2 )
158 {
159 case 's':
160 configuration.GenerateProxyMakefilesInSourceTree = true;
161 break;
162 default:
163 printf ( "Unknown switch -p%c\n",
164 switchChar2 );
165 return false;
166 }
167 return true;
168 }
169
170 bool
171 ParseSwitch ( int argc, char** argv, int index )
172 {
173 char switchChar = strlen ( argv[index] ) > 1 ? argv[index][1] : ' ';
174 char switchChar2 = strlen ( argv[index] ) > 2 ? argv[index][2] : ' ';
175 switch ( switchChar )
176 {
177 case 'v':
178 if (switchChar2 == 's' || switchChar2 == 'c' || switchChar2 == 'o')
179 {
180 return ParseVCProjectSwitch (
181 switchChar2,
182 argv[index] );
183 }
184 else
185 configuration.Verbose = true;
186 break;
187 case 'c':
188 configuration.CleanAsYouGo = true;
189 break;
190 case 'd':
191 return ParseAutomaticDependencySwitch (
192 switchChar2,
193 argv[index] );
194 case 'u':
195 return ParseCompilationUnitSwitch (
196 switchChar2,
197 argv[index] );
198 case 'r':
199 RootXmlFile = string(&argv[index][2]);
200 break;
201 case 'm':
202 return ParseMakeSwitch ( switchChar2 );
203 case 'p':
204 return ParseProxyMakefileSwitch ( switchChar2 );
205 default:
206 printf (
207 "Unknown switch -%c\n",
208 switchChar );
209 return false;
210 }
211 return true;
212 }
213
214 bool
215 ParseArguments ( int argc, char** argv )
216 {
217 if ( argc < 2 )
218 return false;
219
220 for ( int i = 1; i < argc; i++ )
221 {
222 if ( argv[i][0] == '-' )
223 {
224 if ( !ParseSwitch ( argc, argv, i ) )
225 return false;
226 }
227 else
228 BuildSystem = argv[i];
229 }
230
231 return true;
232 }
233
234 int
235 main ( int argc, char** argv )
236 {
237 InitializeEnvironment ();
238
239 if ( !ParseArguments ( argc, argv ) )
240 {
241 printf ( "Generates project files for buildsystems\n\n" );
242 printf ( " rbuild [switches] -r{rootfile.rbuild} buildsystem\n\n" );
243 printf ( "Switches:\n" );
244 printf ( " -v Be verbose.\n" );
245 printf ( " -c Clean as you go. Delete generated files as soon as they are not\n" );
246 printf ( " needed anymore.\n" );
247 printf ( " -dd Disable automatic dependencies.\n" );
248 printf ( " -dm{module} Check only automatic dependencies for this module.\n" );
249 printf ( " -ud Disable multiple source files per compilation unit.\n" );
250 printf ( " -mi Let make handle creation of install directories. Rbuild will\n" );
251 printf ( " not generate the directories.\n" );
252 printf ( " -ps Generate proxy makefiles in source tree instead of the output.\n" );
253 printf ( " tree.\n" );
254 printf ( " -vs{version} Version of MS VS project files. Default is %s.\n", MS_VS_DEF_VERSION );
255 printf ( " -vo{version|configuration} Adds subdirectory path to the default Intermediate-Outputdirectory.\n" );
256 printf ( "\n" );
257 printf ( " buildsystem Target build system. Can be one of:\n" );
258
259 std::map<std::string,Backend::Factory*>::iterator iter;
260 for (iter = Backend::Factory::map_begin(); iter != Backend::Factory::map_end(); iter++)
261 {
262 Backend::Factory *factory = iter->second;
263 printf ( " %-10s %s\n", factory->Name(), factory->Description());
264 }
265 return 1;
266 }
267 try
268 {
269 if ( RootXmlFile.length () == 0 )
270 throw MissingArgumentException ( "-r" );
271
272 string projectFilename ( RootXmlFile );
273
274 printf ( "Reading build files..." );
275 Project project ( configuration, projectFilename );
276 printf ( "done\n" );
277
278 project.SetBackend ( Backend::Factory::Create (
279 BuildSystem,
280 project,
281 configuration ) );
282
283 project.WriteConfigurationFile ();
284 project.ExecuteInvocations ();
285 project.GetBackend().Process();
286
287 return 0;
288 }
289 catch ( Exception& ex )
290 {
291 printf ( "%s\n", (*ex).c_str () );
292 return 1;
293 }
294 catch ( XMLException& ex )
295 {
296 printf ( "%s\n", (*ex).c_str () );
297 return 1;
298 }
299 }