2 // Parameters.cs: Class that contains information about command line parameters
5 // Marek Sieradzki (marek.sieradzki@gmail.com)
7 // (C) 2005 Marek Sieradzki
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.
32 using System
.Collections
;
33 using System
.Collections
.Generic
;
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
;
49 LoggerVerbosity loggerVerbosity
;
53 BuildPropertyGroup properties
;
54 IList remainingArguments
;
55 Hashtable responseFiles
;
58 string validationSchema
;
62 public Parameters (string binPath
)
64 consoleLoggerParameters
= "";
66 displayVersion
= true;
67 loggers
= new ArrayList ();
68 loggerVerbosity
= LoggerVerbosity
.Normal
;
69 noConsoleLogger
= false;
71 properties
= new BuildPropertyGroup ();
72 targets
= new string [0];
74 responseFile
= Path
.Combine (
75 Path
.GetDirectoryName (Assembly
.GetExecutingAssembly ().Location
),
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")) {
91 flatArguments
.Add (s
);
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];
137 projectFile
= proj_files
[0];
138 } else if (remainingArguments
.Count
== 1) {
139 projectFile
= (string) remainingArguments
[0];
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);
152 void LoadResponseFile (string filename
)
154 StreamReader sr
= null;
157 sr
= new StreamReader (filename
);
158 StringBuilder sb
= new StringBuilder ();
160 while ((line
= sr
.ReadLine ()) != null) {
163 for (int i
= 0; i
< t
; i
++) {
167 // comment, ignore rest of the line
170 if (c
== '"' || c
== '\'') {
173 for (i
++; i
< t
; i
++) {
180 } else if (c
== ' ') {
182 flatArguments
.Add (sb
.ToString ());
189 flatArguments
.Add (sb
.ToString ());
193 } catch (IOException x
) {
194 ErrorUtilities
.ReportWarning (2, String
.Format (
195 "Error loading response file. (Exception: {0}). Ignoring.",
203 private bool ParseFlatArgument (string s
)
209 ErrorUtilities
.ShowUsage ();
216 ErrorUtilities
.ShowVersion (true);
218 case "/noconsolelogger":
220 noConsoleLogger
= true;
227 if (s
.StartsWith ("/target:") || s
.StartsWith ("/t:")) {
229 } else if (s
.StartsWith ("/property:") || s
.StartsWith ("/p:")) {
230 if (!ProcessProperty (s
))
232 } else if (s
.StartsWith ("/logger:") || s
.StartsWith ("/l:")) {
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:")) {
248 internal void ProcessTarget (string s
)
250 TryProcessMultiOption (s
, "Target names must be specified as /t:Target1;Target2",
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
))
261 foreach (string st
in splitProperties
) {
262 if (st
.IndexOf ('=') < 0) {
264 "Invalid syntax. Property name and value expected as " +
265 "<prop name>=[<prop value>]");
268 string [] property
= st
.Split ('=');
269 properties
.SetProperty (property
[0], property
.Length
== 2 ? property
[1] : "");
275 bool TryProcessMultiOption (string s
, string error_message
, out string[] values
)
278 int colon
= s
.IndexOf (':');
279 if (colon
+ 1 == s
.Length
) {
280 ReportError (5, error_message
);
284 values
= s
.Substring (colon
+ 1).Split (';');
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 (':');
309 loggerVerbosity
= LoggerVerbosity
.Quiet
;
313 loggerVerbosity
= LoggerVerbosity
.Minimal
;
317 loggerVerbosity
= LoggerVerbosity
.Normal
;
321 loggerVerbosity
= LoggerVerbosity
.Detailed
;
325 loggerVerbosity
= LoggerVerbosity
.Diagnostic
;
330 internal void ProcessConsoleLoggerParameters (string s
)
332 consoleLoggerParameters
= s
;
335 internal void ProcessValidate (string s
)
339 temp
= s
.Split (':');
340 validationSchema
= temp
[1];
342 public bool DisplayHelp
{
343 get { return displayHelp; }
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; }