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
;
65 consoleLoggerParameters
= "";
67 displayVersion
= true;
68 loggers
= new ArrayList ();
69 loggerVerbosity
= LoggerVerbosity
.Normal
;
70 noConsoleLogger
= false;
72 properties
= new BuildPropertyGroup ();
73 targets
= new string [0];
75 responseFile
= Path
.Combine (
76 Path
.GetDirectoryName (Assembly
.GetExecutingAssembly ().Location
),
80 public void ParseArguments (string[] args
)
82 bool autoResponse
= true;
83 flatArguments
= new ArrayList ();
84 remainingArguments
= new ArrayList ();
85 responseFiles
= new Hashtable ();
86 foreach (string s
in args
) {
87 if (s
.StartsWith ("/noautoresponse") || s
.StartsWith ("/noautorsp")) {
92 flatArguments
.Add (s
);
95 string responseFilename
= Path
.GetFullPath (UnquoteIfNeeded (s
.Substring (1)));
96 if (responseFiles
.ContainsKey (responseFilename
))
97 ReportError (1, String
.Format ("We already have {0} file.", responseFilename
));
98 responseFiles
[responseFilename
] = responseFilename
;
99 LoadResponseFile (responseFilename
);
101 if (autoResponse
== true) {
102 // FIXME: we do not allow nested auto response file
103 LoadResponseFile (responseFile
);
105 foreach (string s
in flatArguments
) {
106 if (s
[0] != '/' || !ParseFlatArgument (s
))
107 remainingArguments
.Add (s
);
109 if (remainingArguments
.Count
== 0) {
110 string[] sln_files
= Directory
.GetFiles (Directory
.GetCurrentDirectory (), "*.sln");
111 string[] proj_files
= Directory
.GetFiles (Directory
.GetCurrentDirectory (), "*proj");
113 if (sln_files
.Length
== 0 && proj_files
.Length
== 0)
114 ReportError (3, "Please specify the project or solution file " +
115 "to build, as none was found in the current directory.");
117 if (sln_files
.Length
== 1 && proj_files
.Length
> 0) {
118 var projects_table
= new Dictionary
<string, string> ();
119 foreach (string pfile
in SolutionParser
.GetAllProjectFileNames (sln_files
[0])) {
120 string full_path
= Path
.GetFullPath (pfile
);
121 projects_table
[full_path
] = full_path
;
124 if (!proj_files
.Any (p
=> !projects_table
.ContainsKey (Path
.GetFullPath (p
))))
125 // if all the project files in the cur dir, are referenced
126 // from the single .sln in the cur dir, then pick the sln
127 proj_files
= new string [0];
130 if (sln_files
.Length
+ proj_files
.Length
> 1)
131 ReportError (5, "Please specify the project or solution file " +
132 "to build, as more than one solution or project file was found " +
133 "in the current directory");
135 if (sln_files
.Length
== 1)
136 projectFile
= sln_files
[0];
138 projectFile
= proj_files
[0];
139 } else if (remainingArguments
.Count
== 1) {
140 projectFile
= (string) remainingArguments
[0];
142 ReportError (4, "Too many project files specified");
146 private string UnquoteIfNeeded(string arg
)
148 if (arg
.StartsWith("\""))
149 return arg
.Substring(1, arg
.Length
- 2);
153 void LoadResponseFile (string filename
)
155 StreamReader sr
= null;
158 sr
= new StreamReader (filename
);
159 StringBuilder sb
= new StringBuilder ();
161 while ((line
= sr
.ReadLine ()) != null) {
164 for (int i
= 0; i
< t
; i
++) {
168 // comment, ignore rest of the line
171 if (c
== '"' || c
== '\'') {
174 for (i
++; i
< t
; i
++) {
181 } else if (c
== ' ') {
183 flatArguments
.Add (sb
.ToString ());
190 flatArguments
.Add (sb
.ToString ());
194 } catch (IOException x
) {
195 ErrorUtilities
.ReportWarning (2, String
.Format (
196 "Error loading response file. (Exception: {0}). Ignoring.",
204 private bool ParseFlatArgument (string s
)
210 ErrorUtilities
.ShowUsage ();
217 ErrorUtilities
.ShowVersion (true);
219 case "/noconsolelogger":
221 noConsoleLogger
= true;
228 if (s
.StartsWith ("/target:") || s
.StartsWith ("/t:")) {
230 } else if (s
.StartsWith ("/property:") || s
.StartsWith ("/p:")) {
231 if (!ProcessProperty (s
))
233 } else if (s
.StartsWith ("/logger:") || s
.StartsWith ("/l:")) {
235 } else if (s
.StartsWith ("/verbosity:") || s
.StartsWith ("/v:")) {
236 ProcessVerbosity (s
);
237 } else if (s
.StartsWith ("/consoleloggerparameters:") || s
.StartsWith ("/clp:")) {
238 ProcessConsoleLoggerParameters (s
);
239 } else if (s
.StartsWith ("/validate:") || s
.StartsWith ("/val:")) {
241 } else if (s
.StartsWith ("/toolsversion:") || s
.StartsWith ("/tv:")) {
242 ToolsVersion
= s
.Split (':') [1];
251 internal void ProcessTarget (string s
)
253 TryProcessMultiOption (s
, "Target names must be specified as /t:Target1;Target2",
257 internal bool ProcessProperty (string s
)
259 string[] splitProperties
;
260 if (!TryProcessMultiOption (s
, "Property name and value expected as /p:<prop name>=<prop value>",
261 out splitProperties
))
264 foreach (string st
in splitProperties
) {
265 if (st
.IndexOf ('=') < 0) {
267 "Invalid syntax. Property name and value expected as " +
268 "<prop name>=[<prop value>]");
271 string [] property
= st
.Split ('=');
272 properties
.SetProperty (property
[0], property
.Length
== 2 ? property
[1] : "");
278 bool TryProcessMultiOption (string s
, string error_message
, out string[] values
)
281 int colon
= s
.IndexOf (':');
282 if (colon
+ 1 == s
.Length
) {
283 ReportError (5, error_message
);
287 values
= s
.Substring (colon
+ 1).Split (';');
291 private void ReportError (int errorCode
, string message
)
293 throw new CommandLineException (message
, errorCode
);
296 private void ReportError (int errorCode
, string message
, Exception cause
)
298 throw new CommandLineException (message
, cause
, errorCode
);
301 internal void ProcessLogger (string s
)
303 loggers
.Add (new LoggerInfo (s
));
306 internal void ProcessVerbosity (string s
)
308 string[] temp
= s
.Split (':');
312 loggerVerbosity
= LoggerVerbosity
.Quiet
;
316 loggerVerbosity
= LoggerVerbosity
.Minimal
;
320 loggerVerbosity
= LoggerVerbosity
.Normal
;
324 loggerVerbosity
= LoggerVerbosity
.Detailed
;
328 loggerVerbosity
= LoggerVerbosity
.Diagnostic
;
333 internal void ProcessConsoleLoggerParameters (string s
)
335 consoleLoggerParameters
= s
;
338 internal void ProcessValidate (string s
)
342 temp
= s
.Split (':');
343 validationSchema
= temp
[1];
345 public bool DisplayHelp
{
346 get { return displayHelp; }
350 get { return noLogo; }
353 public bool DisplayVersion
{
354 get { return displayVersion; }
357 public string ProjectFile
{
358 get { return projectFile; }
361 public string[] Targets
{
362 get { return targets; }
365 public BuildPropertyGroup Properties
{
366 get { return properties; }
369 public IList Loggers
{
370 get { return loggers; }
373 public LoggerVerbosity LoggerVerbosity
{
374 get { return loggerVerbosity; }
377 public string ConsoleLoggerParameters
{
378 get { return consoleLoggerParameters; }
381 public bool NoConsoleLogger
{
382 get { return noConsoleLogger; }
385 public bool Validate
{
386 get { return validate; }
389 public string ValidationSchema
{
390 get { return validationSchema; }
393 public string ToolsVersion
{
394 get { return toolsVersion; }
395 private set { toolsVersion = value; }