[netcore] Remove local copy of static alc resolve methods
[mono-project.git] / mcs / tools / xbuild / Parameters.cs
blob8ecaeccd42a9447c54ad5b6cbf336dc0e8a74da3
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.
29 using System;
30 using System.IO;
31 using System.Collections;
32 using System.Collections.Generic;
33 using System.Linq;
34 using System.Text;
35 using System.Reflection;
36 using Microsoft.Build.BuildEngine;
37 using Microsoft.Build.Framework;
38 using Microsoft.Build.Utilities;
40 namespace Mono.XBuild.CommandLine {
41 public class Parameters {
43 string consoleLoggerParameters;
44 bool displayHelp;
45 IList flatArguments;
46 IList loggers;
47 LoggerVerbosity loggerVerbosity;
48 bool noConsoleLogger;
49 bool noLogo;
50 string projectFile;
51 BuildPropertyGroup properties;
52 IList remainingArguments;
53 Hashtable responseFiles;
54 string[] targets;
55 bool validate;
56 string validationSchema;
57 string toolsVersion;
59 string responseFile;
61 public Parameters ()
63 consoleLoggerParameters = "";
64 displayHelp = false;
65 loggers = new ArrayList ();
66 loggerVerbosity = LoggerVerbosity.Normal;
67 noConsoleLogger = false;
68 noLogo = false;
69 properties = new BuildPropertyGroup ();
70 targets = new string [0];
72 responseFile = Path.Combine (
73 Path.GetDirectoryName (Assembly.GetExecutingAssembly ().Location),
74 "xbuild.rsp");
77 public void ParseArguments (string[] args)
79 bool autoResponse = true;
80 flatArguments = new ArrayList ();
81 remainingArguments = new ArrayList ();
82 responseFiles = new Hashtable ();
83 FileLoggerParameters = new string[10];
84 foreach (string s in args) {
85 if (s.StartsWith ("/noautoresponse") || s.StartsWith ("/noautorsp")) {
86 autoResponse = false;
87 continue;
89 if (s [0] != '@') {
90 flatArguments.Add (s);
91 continue;
93 string responseFilename = Path.GetFullPath (UnquoteIfNeeded (s.Substring (1)));
94 if (responseFiles.ContainsKey (responseFilename))
95 ReportError (1, String.Format ("We already have {0} file.", responseFilename));
96 responseFiles [responseFilename] = responseFilename;
97 LoadResponseFile (responseFilename);
99 if (autoResponse == true) {
100 // FIXME: we do not allow nested auto response file
101 LoadResponseFile (responseFile);
103 foreach (string s in flatArguments) {
104 if (s [0] != '/' || !ParseFlatArgument (s))
105 remainingArguments.Add (s);
107 if (remainingArguments.Count == 0) {
108 string[] sln_files = Directory.GetFiles (Directory.GetCurrentDirectory (), "*.sln");
109 string[] proj_files = Directory.GetFiles (Directory.GetCurrentDirectory (), "*proj");
111 if (sln_files.Length == 0 && proj_files.Length == 0)
112 ReportError (3, "Please specify the project or solution file " +
113 "to build, as none was found in the current directory.");
115 if (sln_files.Length == 1 && proj_files.Length > 0) {
116 var projects_table = new Dictionary<string, string> ();
117 foreach (string pfile in SolutionParser.GetAllProjectFileNames (sln_files [0])) {
118 string full_path = Path.GetFullPath (pfile);
119 projects_table [full_path] = full_path;
122 if (!proj_files.Any (p => !projects_table.ContainsKey (Path.GetFullPath (p))))
123 // if all the project files in the cur dir, are referenced
124 // from the single .sln in the cur dir, then pick the sln
125 proj_files = new string [0];
128 if (sln_files.Length + proj_files.Length > 1)
129 ReportError (5, "Please specify the project or solution file " +
130 "to build, as more than one solution or project file was found " +
131 "in the current directory");
133 if (sln_files.Length == 1)
134 projectFile = sln_files [0];
135 else
136 projectFile = proj_files [0];
137 } else if (remainingArguments.Count == 1) {
138 projectFile = (string) remainingArguments [0];
139 } else {
140 ReportError (4, "Too many project files specified");
144 private string UnquoteIfNeeded(string arg)
146 if (arg.StartsWith("\""))
147 return arg.Substring(1, arg.Length - 2);
148 return arg;
151 void LoadResponseFile (string filename)
153 StreamReader sr = null;
154 string line;
155 try {
156 sr = new StreamReader (filename);
157 StringBuilder sb = new StringBuilder ();
159 while ((line = sr.ReadLine ()) != null) {
160 int t = line.Length;
162 for (int i = 0; i < t; i++) {
163 char c = line [i];
165 if (c == '#')
166 // comment, ignore rest of the line
167 break;
169 if (c == '"' || c == '\'') {
170 char end = c;
172 for (i++; i < t; i++) {
173 c = line [i];
175 if (c == end)
176 break;
177 sb.Append (c);
179 } else if (c == ' ') {
180 if (sb.Length > 0) {
181 flatArguments.Add (sb.ToString ());
182 sb.Length = 0;
184 } else
185 sb.Append (c);
187 if (sb.Length > 0){
188 flatArguments.Add (sb.ToString ());
189 sb.Length = 0;
192 } catch (IOException x) {
193 ErrorUtilities.ReportWarning (2, String.Format (
194 "Error loading response file. (Exception: {0}). Ignoring.",
195 x.Message));
196 } finally {
197 if (sr != null)
198 sr.Close ();
202 private bool ParseFlatArgument (string s)
204 switch (s) {
205 case "/help":
206 case "/h":
207 case "/?":
208 ErrorUtilities.ShowUsage ();
209 break;
210 case "/nologo":
211 noLogo = true;
212 break;
213 case "/version":
214 case "/ver":
215 ErrorUtilities.ShowVersion (true);
216 break;
217 case "/noconsolelogger":
218 case "/noconlog":
219 noConsoleLogger = true;
220 break;
221 case "/validate":
222 case "/val":
223 validate = true;
224 break;
225 case "/fl":
226 case "/filelogger":
227 if (FileLoggerParameters [0] == null)
228 FileLoggerParameters [0] = String.Empty;
229 break;
230 default:
231 if (s.StartsWith ("/fl") && s.Length == 4 && Char.IsDigit (s[3])) {
232 int index = Int32.Parse (s[3].ToString ());
233 if (FileLoggerParameters [index] == null)
234 FileLoggerParameters [index] = String.Empty;
235 } else if (s.StartsWith ("/fileloggerparameters") || s.StartsWith ("/flp")) {
236 ProcessFileLoggerParameters (s);
237 } else if (s.StartsWith ("/target:") || s.StartsWith ("/t:")) {
238 ProcessTarget (s);
239 } else if (s.StartsWith ("/property:") || s.StartsWith ("/p:")) {
240 if (!ProcessProperty (s))
241 return false;
242 } else if (s.StartsWith ("/logger:") || s.StartsWith ("/l:")) {
243 ProcessLogger (s);
244 } else if (s.StartsWith ("/verbosity:") || s.StartsWith ("/v:")) {
245 ProcessVerbosity (s);
246 } else if (s.StartsWith ("/consoleloggerparameters:") || s.StartsWith ("/clp:")) {
247 ProcessConsoleLoggerParameters (s);
248 } else if (s.StartsWith ("/validate:") || s.StartsWith ("/val:")) {
249 ProcessValidate (s);
250 } else if (s.StartsWith ("/toolsversion:") || s.StartsWith ("/tv:")) {
251 ToolsVersion = s.Split (':') [1];
252 } else
253 return false;
254 break;
257 return true;
260 internal void ProcessTarget (string s)
262 TryProcessMultiOption (s, "Target names must be specified as /t:Target1;Target2",
263 out targets);
266 internal bool ProcessProperty (string s)
268 string[] splitProperties;
269 if (!TryProcessMultiOption (s, "Property name and value expected as /p:<prop name>=<prop value>",
270 out splitProperties))
271 return false;
273 foreach (string st in splitProperties) {
274 if (st.IndexOf ('=') < 0) {
275 ReportError (5,
276 "Invalid syntax. Property name and value expected as " +
277 "<prop name>=[<prop value>]");
278 return false;
280 string [] property = st.Split ('=');
281 properties.SetProperty (property [0], property.Length == 2 ? property [1] : "");
284 return true;
287 bool TryProcessMultiOption (string s, string error_message, out string[] values)
289 values = null;
290 int colon = s.IndexOf (':');
291 if (colon + 1 == s.Length) {
292 ReportError (5, error_message);
293 return false;
296 values = s.Substring (colon + 1).Split (';');
297 return true;
300 private void ReportError (int errorCode, string message)
302 throw new CommandLineException (message, errorCode);
305 private void ReportError (int errorCode, string message, Exception cause)
307 throw new CommandLineException (message, cause, errorCode);
310 internal void ProcessLogger (string s)
312 loggers.Add (new LoggerInfo (s));
315 internal void ProcessVerbosity (string s)
317 string[] temp = s.Split (':');
318 switch (temp [1]) {
319 case "q":
320 case "quiet":
321 loggerVerbosity = LoggerVerbosity.Quiet;
322 break;
323 case "m":
324 case "minimal":
325 loggerVerbosity = LoggerVerbosity.Minimal;
326 break;
327 case "n":
328 case "normal":
329 loggerVerbosity = LoggerVerbosity.Normal;
330 break;
331 case "d":
332 case "detailed":
333 loggerVerbosity = LoggerVerbosity.Detailed;
334 break;
335 case "diag":
336 case "diagnostic":
337 loggerVerbosity = LoggerVerbosity.Diagnostic;
338 break;
342 void ProcessFileLoggerParameters (string s)
344 int colon = s.IndexOf (':');
345 if (colon + 1 == s.Length)
346 ReportError (5, "Invalid syntax, specify parameters as /fileloggerparameters[n]:parameters");
348 int index = 0;
349 string key = s.Substring (0, colon);
350 if (Char.IsDigit (key [key.Length - 1]))
351 //if (key.Length == 22 && Char.IsDigit (key [21]))
352 index = Int32.Parse (key [key.Length - 1].ToString ());
354 FileLoggerParameters [index] = s.Substring (colon + 1);
357 internal void ProcessConsoleLoggerParameters (string s)
359 int colon = s.IndexOf (':');
360 if (colon + 1 == s.Length)
361 ReportError (5, "Invalid syntax, specify parameters as /clp:parameters");
363 consoleLoggerParameters = s.Substring (colon + 1);
366 internal void ProcessValidate (string s)
368 string[] temp;
369 validate = true;
370 temp = s.Split (':');
371 validationSchema = temp [1];
373 public bool DisplayHelp {
374 get { return displayHelp; }
377 public bool NoLogo {
378 get { return noLogo; }
381 public string ProjectFile {
382 get { return projectFile; }
385 public string[] Targets {
386 get { return targets; }
389 public BuildPropertyGroup Properties {
390 get { return properties; }
393 public IList Loggers {
394 get { return loggers; }
397 public LoggerVerbosity LoggerVerbosity {
398 get { return loggerVerbosity; }
401 public string ConsoleLoggerParameters {
402 get { return consoleLoggerParameters; }
405 public bool NoConsoleLogger {
406 get { return noConsoleLogger; }
409 public string[] FileLoggerParameters { get; set; }
411 public bool Validate {
412 get { return validate; }
415 public string ValidationSchema {
416 get { return validationSchema; }
419 public string ToolsVersion {
420 get { return toolsVersion; }
421 private set { toolsVersion = value; }