using System;
using System.IO;
using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
using System.Text;
+using System.Reflection;
using Microsoft.Build.BuildEngine;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
string[] targets;
bool validate;
string validationSchema;
+ string toolsVersion;
string responseFile;
- public Parameters (string binPath)
+ public Parameters ()
{
consoleLoggerParameters = "";
displayHelp = false;
properties = new BuildPropertyGroup ();
targets = new string [0];
- responseFile = Path.Combine (binPath, "xbuild.rsp");
+ responseFile = Path.Combine (
+ Path.GetDirectoryName (Assembly.GetExecutingAssembly ().Location),
+ "xbuild.rsp");
}
public void ParseArguments (string[] args)
flatArguments.Add (s);
continue;
}
- string responseFilename = Path.GetFullPath (s.Substring (1));
+ string responseFilename = Path.GetFullPath (UnquoteIfNeeded (s.Substring (1)));
if (responseFiles.ContainsKey (responseFilename))
- ErrorUtilities.ReportError (1, String.Format ("We already have {0} file.", responseFilename));
+ ReportError (1, String.Format ("We already have {0} file.", responseFilename));
responseFiles [responseFilename] = responseFilename;
LoadResponseFile (responseFilename);
}
LoadResponseFile (responseFile);
}
foreach (string s in flatArguments) {
- if (s [0] == '/') {
- ParseFlatArgument (s);
- } else
+ if (s [0] != '/' || !ParseFlatArgument (s))
remainingArguments.Add (s);
}
if (remainingArguments.Count == 0) {
- string[] files = Directory.GetFiles (Directory.GetCurrentDirectory (), "*.??proj");
- if (files.Length > 0)
- projectFile = files [0];
+ string[] sln_files = Directory.GetFiles (Directory.GetCurrentDirectory (), "*.sln");
+ string[] proj_files = Directory.GetFiles (Directory.GetCurrentDirectory (), "*proj");
+
+ if (sln_files.Length == 0 && proj_files.Length == 0)
+ ReportError (3, "Please specify the project or solution file " +
+ "to build, as none was found in the current directory.");
+
+ if (sln_files.Length == 1 && proj_files.Length > 0) {
+ var projects_table = new Dictionary<string, string> ();
+ foreach (string pfile in SolutionParser.GetAllProjectFileNames (sln_files [0])) {
+ string full_path = Path.GetFullPath (pfile);
+ projects_table [full_path] = full_path;
+ }
+
+ if (!proj_files.Any (p => !projects_table.ContainsKey (Path.GetFullPath (p))))
+ // if all the project files in the cur dir, are referenced
+ // from the single .sln in the cur dir, then pick the sln
+ proj_files = new string [0];
+ }
+
+ if (sln_files.Length + proj_files.Length > 1)
+ ReportError (5, "Please specify the project or solution file " +
+ "to build, as more than one solution or project file was found " +
+ "in the current directory");
+
+ if (sln_files.Length == 1)
+ projectFile = sln_files [0];
else
- ErrorUtilities.ReportError (3, "No .proj file specified and no found in current directory.");
+ projectFile = proj_files [0];
} else if (remainingArguments.Count == 1) {
projectFile = (string) remainingArguments [0];
} else {
- ErrorUtilities.ReportError (4, "Too many project files specified");
+ ReportError (4, "Too many project files specified");
}
}
-
- private void LoadResponseFile (string filename)
+
+ private string UnquoteIfNeeded(string arg)
+ {
+ if (arg.StartsWith("\""))
+ return arg.Substring(1, arg.Length - 2);
+ return arg;
+ }
+
+ void LoadResponseFile (string filename)
{
StreamReader sr = null;
string line;
for (int i = 0; i < t; i++) {
char c = line [i];
+ if (c == '#')
+ // comment, ignore rest of the line
+ break;
+
if (c == '"' || c == '\'') {
char end = c;
sb.Length = 0;
}
}
- } catch (Exception) {
- // FIXME: we lose exception message
- ErrorUtilities.ReportError (2, "Error during loading response file.");
+ } catch (IOException x) {
+ ErrorUtilities.ReportWarning (2, String.Format (
+ "Error loading response file. (Exception: {0}). Ignoring.",
+ x.Message));
} finally {
if (sr != null)
sr.Close ();
}
}
- private void ParseFlatArgument (string s)
+ private bool ParseFlatArgument (string s)
{
switch (s) {
case "/help":
default:
if (s.StartsWith ("/target:") || s.StartsWith ("/t:")) {
ProcessTarget (s);
- }
- if (s.StartsWith ("/property:") || s.StartsWith ("/p:")) {
- ProcessProperty (s);
- }
- if (s.StartsWith ("/logger:") || s.StartsWith ("/l:")) {
+ } else if (s.StartsWith ("/property:") || s.StartsWith ("/p:")) {
+ if (!ProcessProperty (s))
+ return false;
+ } else if (s.StartsWith ("/logger:") || s.StartsWith ("/l:")) {
ProcessLogger (s);
- }
- if (s.StartsWith ("/verbosity:") || s.StartsWith ("/v:")) {
+ } else if (s.StartsWith ("/verbosity:") || s.StartsWith ("/v:")) {
ProcessVerbosity (s);
- }
- if (s.StartsWith ("/consoleloggerparameters:") || s.StartsWith ("/clp:")) {
+ } else if (s.StartsWith ("/consoleloggerparameters:") || s.StartsWith ("/clp:")) {
ProcessConsoleLoggerParameters (s);
- }
- if (s.StartsWith ("/validate:") || s.StartsWith ("/val:")) {
+ } else if (s.StartsWith ("/validate:") || s.StartsWith ("/val:")) {
ProcessValidate (s);
- }
+ } else if (s.StartsWith ("/toolsversion:") || s.StartsWith ("/tv:")) {
+ ToolsVersion = s.Split (':') [1];
+ } else
+ return false;
break;
}
+
+ return true;
}
internal void ProcessTarget (string s)
{
- string[] temp = s.Split (':');
- targets = temp [1].Split (';');
+ TryProcessMultiOption (s, "Target names must be specified as /t:Target1;Target2",
+ out targets);
}
- internal void ProcessProperty (string s)
+ internal bool ProcessProperty (string s)
{
- string[] parameter, splittedProperties, property;
- parameter = s.Split (':');
- splittedProperties = parameter [1].Split (';');
- foreach (string st in splittedProperties) {
- property = st.Split ('=');
- properties.AddNewProperty (property [0], property [1]);
+ string[] splitProperties;
+ if (!TryProcessMultiOption (s, "Property name and value expected as /p:<prop name>=<prop value>",
+ out splitProperties))
+ return false;
+
+ foreach (string st in splitProperties) {
+ if (st.IndexOf ('=') < 0) {
+ ReportError (5,
+ "Invalid syntax. Property name and value expected as " +
+ "<prop name>=[<prop value>]");
+ return false;
+ }
+ string [] property = st.Split ('=');
+ properties.SetProperty (property [0], property.Length == 2 ? property [1] : "");
}
+
+ return true;
}
-
+
+ bool TryProcessMultiOption (string s, string error_message, out string[] values)
+ {
+ values = null;
+ int colon = s.IndexOf (':');
+ if (colon + 1 == s.Length) {
+ ReportError (5, error_message);
+ return false;
+ }
+
+ values = s.Substring (colon + 1).Split (';');
+ return true;
+ }
+
+ private void ReportError (int errorCode, string message)
+ {
+ throw new CommandLineException (message, errorCode);
+ }
+
+ private void ReportError (int errorCode, string message, Exception cause)
+ {
+ throw new CommandLineException (message, cause, errorCode);
+ }
+
internal void ProcessLogger (string s)
{
loggers.Add (new LoggerInfo (s));
internal void ProcessConsoleLoggerParameters (string s)
{
- consoleLoggerParameters = s;
+ int colon = s.IndexOf (':');
+ if (colon + 1 == s.Length)
+ ReportError (5, "Invalid syntax, specify parameters as /clp:parameters");
+
+ consoleLoggerParameters = s.Substring (colon + 1);
}
internal void ProcessValidate (string s)
public string ValidationSchema {
get { return validationSchema; }
}
+
+ public string ToolsVersion {
+ get { return toolsVersion; }
+ private set { toolsVersion = value; }
+ }
}
}