* Implement <autoregister>
[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
21 #include <stdio.h>
22 #ifdef WIN32
23 #include <io.h>
24 #endif
25 #include <assert.h>
26
27 #include "rbuild.h"
28 #include "backend/backend.h"
29 #include "backend/mingw/mingw.h"
30
31 using std::string;
32 using std::vector;
33
34 static string BuildSystem;
35 static string RootXmlFile = "ReactOS.xml";
36 static Configuration configuration;
37
38 bool
39 ParseAutomaticDependencySwitch ( char switchChar2,
40 char* switchStart )
41 {
42 switch ( switchChar2 )
43 {
44 case 'd':
45 configuration.AutomaticDependencies = false;
46 break;
47 case 'm':
48 if ( strlen ( switchStart ) <= 3 )
49 {
50 printf ( "Switch -dm requires a module name\n" );
51 return false;
52 }
53 configuration.CheckDependenciesForModuleOnly = true;
54 configuration.CheckDependenciesForModuleOnlyModule = string(&switchStart[3]);
55 break;
56 default:
57 printf ( "Unknown switch -d%c\n",
58 switchChar2 );
59 return false;
60 }
61 return true;
62 }
63
64 bool
65 ParseCompilationUnitSwitch ( char switchChar2,
66 char* switchStart )
67 {
68 switch ( switchChar2 )
69 {
70 case 'd':
71 configuration.CompilationUnitsEnabled = false;
72 break;
73 default:
74 printf ( "Unknown switch -u%c\n",
75 switchChar2 );
76 return false;
77 }
78 return true;
79 }
80
81 bool
82 ParseVCProjectSwitch ( char switchChar2,
83 char* switchStart )
84 {
85 switch ( switchChar2 )
86 {
87 case 's':
88 if ( strlen ( switchStart ) <= 3 )
89 {
90 printf ( "Switch -dm requires a module name\n" );
91 return false;
92 }
93 configuration.VSProjectVersion = string(&switchStart[3]);
94
95 if (configuration.VSProjectVersion.at(0) == '{') {
96 printf ( "Error: invalid char {\n" );
97 return false;
98 }
99
100 if (configuration.VSProjectVersion.length() == 1) //7,8
101 configuration.VSProjectVersion.append(".00");
102
103 if (configuration.VSProjectVersion.length() == 3) //7.1
104 configuration.VSProjectVersion.append("0");
105
106 break;
107 default:
108 printf ( "Unknown switch -d%c\n",
109 switchChar2 );
110 return false;
111 }
112 return true;
113 }
114
115 bool
116 ParseMakeSwitch ( char switchChar2 )
117 {
118 switch ( switchChar2 )
119 {
120 case 'i':
121 configuration.MakeHandlesInstallDirectories = true;
122 break;
123 default:
124 printf ( "Unknown switch -m%c\n",
125 switchChar2 );
126 return false;
127 }
128 return true;
129 }
130
131 bool
132 ParseProxyMakefileSwitch ( char switchChar2 )
133 {
134 switch ( switchChar2 )
135 {
136 case 's':
137 configuration.GenerateProxyMakefilesInSourceTree = true;
138 break;
139 default:
140 printf ( "Unknown switch -p%c\n",
141 switchChar2 );
142 return false;
143 }
144 return true;
145 }
146
147 bool
148 ParseSwitch ( int argc, char** argv, int index )
149 {
150 char switchChar = strlen ( argv[index] ) > 1 ? argv[index][1] : ' ';
151 char switchChar2 = strlen ( argv[index] ) > 2 ? argv[index][2] : ' ';
152 switch ( switchChar )
153 {
154 case 'v':
155 if (switchChar2 == 's')
156 return ParseVCProjectSwitch ( switchChar2,
157 argv[index] );
158 else
159 configuration.Verbose = true;
160 break;
161 case 'c':
162 configuration.CleanAsYouGo = true;
163 break;
164 case 'd':
165 return ParseAutomaticDependencySwitch ( switchChar2,
166 argv[index] );
167 case 'u':
168 return ParseCompilationUnitSwitch ( switchChar2,
169 argv[index] );
170 case 'r':
171 RootXmlFile = string(&argv[index][2]);
172 break;
173 case 'm':
174 return ParseMakeSwitch ( switchChar2 );
175 case 'p':
176 return ParseProxyMakefileSwitch ( switchChar2 );
177 default:
178 printf ( "Unknown switch -%c\n",
179 switchChar );
180 return false;
181 }
182 return true;
183 }
184
185 bool
186 ParseArguments ( int argc, char** argv )
187 {
188 if ( argc < 2 )
189 return false;
190
191 for ( int i = 1; i < argc; i++ )
192 {
193 if ( argv[i][0] == '-' )
194 {
195 if ( !ParseSwitch ( argc, argv, i ) )
196 return false;
197 }
198 else
199 BuildSystem = argv[i];
200 }
201
202 return true;
203 }
204
205 int
206 main ( int argc, char** argv )
207 {
208 InitializeEnvironment ();
209
210 if ( !ParseArguments ( argc, argv ) )
211 {
212 printf ( "Generates project files for buildsystems\n\n" );
213 printf ( " rbuild [switches] buildsystem\n\n" );
214 printf ( "Switches:\n" );
215 printf ( " -v Be verbose.\n" );
216 printf ( " -c Clean as you go. Delete generated files as soon as they are not\n" );
217 printf ( " needed anymore.\n" );
218 printf ( " -r{file.xml} Name of the root xml file. Default is ReactOS.xml.\n" );
219 printf ( " -dd Disable automatic dependencies.\n" );
220 printf ( " -dm{module} Check only automatic dependencies for this module.\n" );
221 printf ( " -ud Disable multiple source files per compilation unit.\n" );
222 printf ( " -mi Let make handle creation of install directories. Rbuild will\n" );
223 printf ( " not generate the directories.\n" );
224 printf ( " -ps Generate proxy makefiles in source tree instead of the output.\n" );
225 printf ( " tree.\n" );
226 printf ( " -vs{version} Version of MS VS project files. Default is %s.\n", MS_VS_DEF_VERSION );
227 printf ( "\n" );
228 printf ( " buildsystem Target build system. Can be one of:\n" );
229 printf ( " mingw MinGW\n" );
230 printf ( " devcpp DevC++\n" );
231 printf ( " msvc MS Visual Studio\n" );
232 return 1;
233 }
234 try
235 {
236 string projectFilename ( RootXmlFile );
237 printf ( "Reading build files..." );
238 Project project ( configuration, projectFilename );
239 printf ( "done\n" );
240 project.WriteConfigurationFile ();
241 project.ExecuteInvocations ();
242 Backend* backend = Backend::Factory::Create ( BuildSystem,
243 project,
244 configuration );
245 backend->Process ();
246 delete backend;
247
248 return 0;
249 }
250 catch (Exception& ex)
251 {
252 printf ( "%s\n",
253 ex.Message.c_str () );
254 return 1;
255 }
256 }