2010-04-03 Jb Evain <jbevain@novell.com>
[mcs.git] / tools / xbuild / Parameters.cs
blob0dab523418c62c2fab0e00b8373bb19d98088be4
1 //
2 // Parameters.cs: Class that contains information about command line parameters
3 //
4 // Author:
5 // Marek Sieradzki (marek.sieradzki@gmail.com)
6 //
7 // (C) 2005 Marek Sieradzki
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 #if NET_2_0
30 using System;
31 using System.IO;
32 using System.Collections;
33 using System.Collections.Generic;
34 using System.Linq;
35 using System.Text;
36 using System.Reflection;
37 using Microsoft.Build.BuildEngine;
38 using Microsoft.Build.Framework;
39 using Microsoft.Build.Utilities;
41 namespace Mono.XBuild.CommandLine {
42 public class Parameters {
44 string consoleLoggerParameters;
45 bool displayHelp;
46 bool displayVersion;
47 IList flatArguments;
48 IList loggers;
49 LoggerVerbosity loggerVerbosity;
50 bool noConsoleLogger;
51 bool noLogo;
52 string projectFile;
53 BuildPropertyGroup properties;
54 IList remainingArguments;
55 Hashtable responseFiles;
56 string[] targets;
57 bool validate;
58 string validationSchema;
60 string responseFile;
62 public Parameters (string binPath)
64 consoleLoggerParameters = "";
65 displayHelp = false;
66 displayVersion = true;
67 loggers = new ArrayList ();
68 loggerVerbosity = LoggerVerbosity.Normal;
69 noConsoleLogger = false;
70 noLogo = false;
71 properties = new BuildPropertyGroup ();
72 targets = new string [0];
74 responseFile = Path.Combine (
75 Path.GetDirectoryName (Assembly.GetExecutingAssembly ().Location),
76 "xbuild.rsp");
79 public void ParseArguments (string[] args)
81 bool autoResponse = true;
82 flatArguments = new ArrayList ();
83 remainingArguments = new ArrayList ();
84 responseFiles = new Hashtable ();
85 foreach (string s in args) {
86 if (s.StartsWith ("/noautoresponse") || s.StartsWith ("/noautorsp")) {
87 autoResponse = false;
88 continue;
90 if (s [0] != '@') {
91 flatArguments.Add (s);
92 continue;
94 string responseFilename = Path.GetFullPath (UnquoteIfNeeded (s.Substring (1)));
95 if (responseFiles.ContainsKey (responseFilename))
96 ReportError (1, String.Format ("We already have {0} file.", responseFilename));
97 responseFiles [responseFilename] = responseFilename;
98 LoadResponseFile (responseFilename);
100 if (autoResponse == true) {
101 // FIXME: we do not allow nested auto response file
102 LoadResponseFile (responseFile);
104 foreach (string s in flatArguments) {
105 if (s [0] != '/' || !ParseFlatArgument (s))
106 remainingArguments.Add (s);
108 if (remainingArguments.Count == 0) {
109 string[] sln_files = Directory.GetFiles (Directory.GetCurrentDirectory (), "*.sln");
110 string[] proj_files = Directory.GetFiles (Directory.GetCurrentDirectory (), "*proj");
112 if (sln_files.Length == 0 && proj_files.Length == 0)
113 ReportError (3, "Please specify the project or solution file " +
114 "to build, as none was found in the current directory.");
116 if (sln_files.Length == 1 && proj_files.Length > 0) {
117 var projects_table = new Dictionary<string, string> ();
118 foreach (string pfile in SolutionParser.GetAllProjectFileNames (sln_files [0])) {
119 string full_path = Path.GetFullPath (pfile);
120 projects_table [full_path] = full_path;
123 if (!proj_files.Any (p => !projects_table.ContainsKey (Path.GetFullPath (p))))
124 // if all the project files in the cur dir, are referenced
125 // from the single .sln in the cur dir, then pick the sln
126 proj_files = new string [0];
129 if (sln_files.Length + proj_files.Length > 1)
130 ReportError (5, "Please specify the project or solution file " +
131 "to build, as more than one solution or project file was found " +
132 "in the current directory");
134 if (sln_files.Length == 1)
135 projectFile = sln_files [0];
136 else
137 projectFile = proj_files [0];
138 } else if (remainingArguments.Count == 1) {
139 projectFile = (string) remainingArguments [0];
140 } else {
141 ReportError (4, "Too many project files specified");
145 private string UnquoteIfNeeded(string arg)
147 if (arg.StartsWith("\""))
148 return arg.Substring(1, arg.Length - 2);
149 return arg;
152 void LoadResponseFile (string filename)
154 StreamReader sr = null;
155 string line;
156 try {
157 sr = new StreamReader (filename);
158 StringBuilder sb = new StringBuilder ();
160 while ((line = sr.ReadLine ()) != null) {
161 int t = line.Length;
163 for (int i = 0; i < t; i++) {
164 char c = line [i];
166 if (c == '#')
167 // comment, ignore rest of the line
168 break;
170 if (c == '"' || c == '\'') {
171 char end = c;
173 for (i++; i < t; i++) {
174 c = line [i];
176 if (c == end)
177 break;
178 sb.Append (c);
180 } else if (c == ' ') {
181 if (sb.Length > 0) {
182 flatArguments.Add (sb.ToString ());
183 sb.Length = 0;
185 } else
186 sb.Append (c);
188 if (sb.Length > 0){
189 flatArguments.Add (sb.ToString ());
190 sb.Length = 0;
193 } catch (IOException x) {
194 ErrorUtilities.ReportWarning (2, String.Format (
195 "Error loading response file. (Exception: {0}). Ignoring.",
196 x.Message));
197 } finally {
198 if (sr != null)
199 sr.Close ();
203 private bool ParseFlatArgument (string s)
205 switch (s) {
206 case "/help":
207 case "/h":
208 case "/?":
209 ErrorUtilities.ShowUsage ();
210 break;
211 case "/nologo":
212 noLogo = true;
213 break;
214 case "/version":
215 case "/ver":
216 ErrorUtilities.ShowVersion (true);
217 break;
218 case "/noconsolelogger":
219 case "/noconlog":
220 noConsoleLogger = true;
221 break;
222 case "/validate":
223 case "/val":
224 validate = true;
225 break;
226 default:
227 if (s.StartsWith ("/target:") || s.StartsWith ("/t:")) {
228 ProcessTarget (s);
229 } else if (s.StartsWith ("/property:") || s.StartsWith ("/p:")) {
230 if (!ProcessProperty (s))
231 return false;
232 } else if (s.StartsWith ("/logger:") || s.StartsWith ("/l:")) {
233 ProcessLogger (s);
234 } else if (s.StartsWith ("/verbosity:") || s.StartsWith ("/v:")) {
235 ProcessVerbosity (s);
236 } else if (s.StartsWith ("/consoleloggerparameters:") || s.StartsWith ("/clp:")) {
237 ProcessConsoleLoggerParameters (s);
238 } else if (s.StartsWith ("/validate:") || s.StartsWith ("/val:")) {
239 ProcessValidate (s);
240 } else
241 return false;
242 break;
245 return true;
248 internal void ProcessTarget (string s)
250 TryProcessMultiOption (s, "Target names must be specified as /t:Target1;Target2",
251 out targets);
254 internal bool ProcessProperty (string s)
256 string[] splitProperties;
257 if (!TryProcessMultiOption (s, "Property name and value expected as /p:<prop name>=<prop value>",
258 out splitProperties))
259 return false;
261 foreach (string st in splitProperties) {
262 if (st.IndexOf ('=') < 0) {
263 ReportError (5,
264 "Invalid syntax. Property name and value expected as " +
265 "<prop name>=[<prop value>]");
266 return false;
268 string [] property = st.Split ('=');
269 properties.SetProperty (property [0], property.Length == 2 ? property [1] : "");
272 return true;
275 bool TryProcessMultiOption (string s, string error_message, out string[] values)
277 values = null;
278 int colon = s.IndexOf (':');
279 if (colon + 1 == s.Length) {
280 ReportError (5, error_message);
281 return false;
284 values = s.Substring (colon + 1).Split (';');
285 return true;
288 private void ReportError (int errorCode, string message)
290 throw new CommandLineException (message, errorCode);
293 private void ReportError (int errorCode, string message, Exception cause)
295 throw new CommandLineException (message, cause, errorCode);
298 internal void ProcessLogger (string s)
300 loggers.Add (new LoggerInfo (s));
303 internal void ProcessVerbosity (string s)
305 string[] temp = s.Split (':');
306 switch (temp [1]) {
307 case "q":
308 case "quiet":
309 loggerVerbosity = LoggerVerbosity.Quiet;
310 break;
311 case "m":
312 case "minimal":
313 loggerVerbosity = LoggerVerbosity.Minimal;
314 break;
315 case "n":
316 case "normal":
317 loggerVerbosity = LoggerVerbosity.Normal;
318 break;
319 case "d":
320 case "detailed":
321 loggerVerbosity = LoggerVerbosity.Detailed;
322 break;
323 case "diag":
324 case "diagnostic":
325 loggerVerbosity = LoggerVerbosity.Diagnostic;
326 break;
330 internal void ProcessConsoleLoggerParameters (string s)
332 consoleLoggerParameters = s;
335 internal void ProcessValidate (string s)
337 string[] temp;
338 validate = true;
339 temp = s.Split (':');
340 validationSchema = temp [1];
342 public bool DisplayHelp {
343 get { return displayHelp; }
346 public bool NoLogo {
347 get { return noLogo; }
350 public bool DisplayVersion {
351 get { return displayVersion; }
354 public string ProjectFile {
355 get { return projectFile; }
358 public string[] Targets {
359 get { return targets; }
362 public BuildPropertyGroup Properties {
363 get { return properties; }
366 public IList Loggers {
367 get { return loggers; }
370 public LoggerVerbosity LoggerVerbosity {
371 get { return loggerVerbosity; }
374 public string ConsoleLoggerParameters {
375 get { return consoleLoggerParameters; }
378 public bool NoConsoleLogger {
379 get { return noConsoleLogger; }
382 public bool Validate {
383 get { return validate; }
386 public string ValidationSchema {
387 get { return validationSchema; }
393 #endif