/// <summary> /// This is the main procedure /// </summary> /// <param name="args">Command line parameters</param> /// <returns>Error codes (0 for success, non-zero on Error)</returns> private int main(IEnumerable<string> args) { var options = args.Where(each => each.StartsWith("--")).Switches(); var parameters = args.Parameters().ToArray(); var buildinfo = string.Empty; Console.CancelKeyPress += (x, y) => { Console.WriteLine("Stopping ptk."); if (_cmdexe != null) _cmdexe.Kill(); if (_gitexe != null) _gitexe.Kill(); if (_hgexe != null) _hgexe.Kill(); if (_ptk != null) _ptk.Kill(); // if (_traceexe != null) { // _traceexe.Kill(); // } }; #region Parse Options // set up options which were defined by the user foreach (string arg in options.Keys) { IEnumerable<string> argumentParameters = options[arg]; switch (arg) { case "nologo": // disable logo (will print "\n" anyway) this.Assembly().SetLogo(""); break; case "verbose": _verbose = true; break; case "skip-built": _skipBuilt = true; _originalEnvironment.AddOrSet("skip-built", "true"); break; case "load": // user specified a custom PropertySheet buildinfo = argumentParameters.LastOrDefault().GetFullPath(); if (!File.Exists(buildinfo)) { return Fail("Unable to find buildinfo file [{0}]. \r\n\r\n Use --help for command line help.", buildinfo); } break; case "mingw-install": case "msys-install": _searchPaths += argumentParameters.LastOrDefault().GetFullPath() + ";"; break; case "rescan-tools": ProgramFinder.IgnoreCache = true; break; case "show-tools": _showTools = true; break; case "help": return Help(); default: var p = argumentParameters.LastOrDefault(); if (string.IsNullOrEmpty(p)) { if( _originalEnvironment.ContainsKey(arg) ) { _originalEnvironment.Remove(arg); } } else{ _originalEnvironment.AddOrSet(arg, p); } break; } } // _originalEnvironment.Add("COAPP", CoApp.Toolkit.Engine.PackageManagerSettings.CoAppRootDirectory); _originalEnvironment.AddOrSet("COAPP", "C:/programdata/"); while (string.IsNullOrEmpty(buildinfo) || !File.Exists(buildinfo)) { // if the user didn't pass in the file, walk up the tree to find the first directory that has a COPKG\.buildinfo file buildinfo = (from a in @".\COPKG\".DirectoryEnumerateFilesSmarter("*.buildinfo", SearchOption.TopDirectoryOnly) orderby a.Length ascending select a.GetFullPath()).FirstOrDefault() ?? @".\COPKG\.buildinfo".GetFullPath(); // try the parent directory. var p = Path.GetDirectoryName(Environment.CurrentDirectory); if (string.IsNullOrEmpty(p)) { return Fail("Unable to find buildinfo file [COPKG\\.buildinfo]--Even walking up the current tree.\r\n\r\n Use --help for command line help."); } Environment.CurrentDirectory = p; } // make sure that we're in the parent directory of the .buildinfo file. Environment.CurrentDirectory = Path.GetDirectoryName(Path.GetDirectoryName(buildinfo)); sessionFeeds = new[] {Environment.CurrentDirectory, Path.GetDirectoryName(buildinfo)}; // tell the user what we are Logo(); #endregion // connect to coapp service // set up several tools we need _cmdexe = new ProcessUtility("cmd.exe"); //var f = new ProgramFinder("").ScanForFile("trace.exe"); //if(!string.IsNullOrEmpty(f)) { //_traceexe = new ProcessUtility(new ProgramFinder("").ScanForFile("trace.exe")); //} _ptk = new ProcessUtility(Assembly.GetEntryAssembly().Location); // if this package is tracked by git, we can use git _useGit = Directory.Exists(".git".GetFullPath()); // if this package is tracked by mercurial, we can use mercurial _useHg = _useGit ? false : Directory.Exists(".hg".GetFullPath()); // source control is mandatory! create a repository for this package if (!(_useGit || _useHg) && _verbose) { Console.WriteLine("WARNING: Source should be checked out using git or hg-git."); } // find git in the file system // - we prefer the CMD script over git.exe // git.exe may be located at "C:\Program Files\Git\bin" // git.cmd may be located at "C:\Program Files\Git\cmd" if (_useGit) { if (_verbose) { Console.WriteLine("Using git for verification"); } // attemt to find git.cmd _gitcmd = ProgramFinder.ProgramFilesAndDotNet.ScanForFile("git.cmd"); _gitexe = null; if (string.IsNullOrEmpty(_gitcmd)) { var f = ProgramFinder.ProgramFilesAndDotNet.ScanForFile("git.exe"); if (string.IsNullOrEmpty(f)) { return Fail("Can not find git.cmd or git.exe (required to perform verification.)"); } _gitexe = new ProcessUtility(ProgramFinder.ProgramFilesAndDotNet.ScanForFile("git.exe")); } } if (_useHg) { var f = ProgramFinder.ProgramFilesAndDotNet.ScanForFile("hg.exe"); if (string.IsNullOrEmpty(f)) { return Fail("Can not find hg.exe (required to perform verification.)"); } _hgexe = new ProcessUtility(f); } // find sdk batch files. /* FIXME: URGENT. * C:\Program Files (x86)\Microsoft Visual Studio 8\VC\vcvarsall.bat C:\Program Files (x86)\Microsoft Visual Studio 8\VC\bin\vcvars32.bat C:\Program Files (x86)\Microsoft Visual Studio 8\VC\bin\amd64\vcvarsamd64.bat C:\Program Files (x86)\Microsoft Visual Studio 8\VC\bin\x86_amd64\vcvarsx86_amd64.bat * VC7.0: C:\Program Files\Microsoft Visual Studio .NET\Vc7\bin\vcvars32.bat * */ _setenvcmd71 = ProgramFinder.ProgramFilesAndDotNetAndSdk.ScanForFile("setenv.cmd", excludeFilters: new[] { @"\Windows Azure SDK\**" , "winddk**" }, includeFilters: new [] {"sdk**", "v7.1**"}, rememberMissingFile:true, tagWithCosmeticVersion:"7.1"); _setenvcmd7 = ProgramFinder.ProgramFilesAndDotNetAndSdk.ScanForFile("setenv.cmd", excludeFilters: new[] { @"\Windows Azure SDK\**", "7.1**", "winddk**" }, includeFilters: new[] { "sdk**", "v7**" }, rememberMissingFile: true, tagWithCosmeticVersion: "7.0"); _setenvcmd6 = ProgramFinder.ProgramFilesAndDotNetAndSdk.ScanForFile("setenv.cmd", excludeFilters: new[] { @"\Windows Azure SDK\**", "winddk**" }, includeFilters: new[] { "sdk**", "6**" }, rememberMissingFile: true, tagWithCosmeticVersion: "6"); _wdksetenvcmd7600 = ProgramFinder.ProgramFilesAndDotNetAndSdk.ScanForFile("setenv.bat", excludeFilters: new[] { @"\Windows Azure SDK\**"}, includeFilters: new[] { "winddk**" }, rememberMissingFile: true, tagWithCosmeticVersion: "7600.16385.1"); /// SDK Setenv (sdk2003): c:\program files (x86)\Microsoft SDK\SetEnv.bat _vcvarsallbat10 = ProgramFinder.ProgramFilesAndDotNetAndSdk.ScanForFile("vcvarsall.bat", includeFilters: new[] { "vc**", "10.0**" }, rememberMissingFile: true, tagWithCosmeticVersion: "10.0"); _vcvarsallbat9 = ProgramFinder.ProgramFilesAndDotNetAndSdk.ScanForFile("vcvarsall.bat", includeFilters: new[] { "vc**", "9.0**" }, rememberMissingFile: true, tagWithCosmeticVersion: "9.0"); _vcvarsallbat8 = ProgramFinder.ProgramFilesAndDotNetAndSdk.ScanForFile("vcvarsall.bat", includeFilters: new[] { "vc**", "8**" }, rememberMissingFile: true, tagWithCosmeticVersion: "8"); _vcvarsallbat7 = ProgramFinder.ProgramFilesAndDotNetAndSdk.ScanForFile("vcvarsall.bat", includeFilters: new[] { "vc**", "7.0**" }, rememberMissingFile: true, tagWithCosmeticVersion: "7.0"); _vcvarsallbat71 = ProgramFinder.ProgramFilesAndDotNetAndSdk.ScanForFile("vcvarsall.bat", includeFilters: new[] { "vc**", "7.1**" }, rememberMissingFile: true, tagWithCosmeticVersion: "7.1"); _vcvars32bat = ProgramFinder.ProgramFilesAndDotNetAndSdk.ScanForFile("vcvars32.bat", includeFilters: new[] { "vc98**" }, rememberMissingFile: true, tagWithCosmeticVersion: "6"); // _originalEnvironment.AddOrSet("COAPP", "C:/programdata/"); var sdks = new List<string>(); if (_setenvcmd71 != null) { sdks.Add("sdk7.1"); } if (_setenvcmd7 != null) { sdks.Add("sdk7"); } if (_setenvcmd6 != null) { sdks.Add("sdk6"); } _originalEnvironment.AddOrSet("installed_sdks", sdks.Aggregate((s, s1) => s + ", " + s1)); var compilers = new List<string>(); if( _vcvarsallbat10 != null ) { compilers.Add("vc10"); } if( _vcvarsallbat9 != null ) { compilers.Add("vc9"); } if( _vcvarsallbat8 != null ) { compilers.Add("vc8"); } if( _vcvarsallbat71 != null ) { compilers.Add("vc7.1"); } if( _vcvarsallbat7 != null ) { compilers.Add("vc7"); } if( _vcvars32bat != null ) { compilers.Add("vc6"); } _originalEnvironment.AddOrSet("installed_compilers", sdks.Aggregate((s, s1) => s + ", " + s1)); if (_showTools) { if (_useGit) { Console.WriteLine("Git: {0}", _gitcmd ?? (_gitexe != null ? _gitexe.Executable : "Not-Found")); } if (_useHg) { Console.WriteLine("hg: {0}", _hgexe.Executable); } Console.WriteLine("SDK Setenv (7.1): {0}", _setenvcmd71 ?? "Not-Found"); Console.WriteLine("SDK Setenv (7.0): {0}", _setenvcmd7 ?? "Not-Found"); Console.WriteLine("SDK Setenv (6): {0}", _setenvcmd6 ?? "Not-Found"); Console.WriteLine("VC vcvarsall (10.0): {0}", _vcvarsallbat10 ?? "Not-Found"); Console.WriteLine("VC vcvarsall (9.0): {0}", _vcvarsallbat9 ?? "Not-Found"); Console.WriteLine("VC vcvarsall (8.0): {0}", _vcvarsallbat8 ?? "Not-Found"); Console.WriteLine("VC vcvarsall (7.0): {0}", _vcvarsallbat7 ?? "Not-Found"); Console.WriteLine("VC vcvarsall (7.1): {0}", _vcvarsallbat71 ?? "Not-Found"); Console.WriteLine("VC vcvars32 (6): {0}", _vcvars32bat ?? "Not-Found"); Console.WriteLine("ptk: {0}", _ptk.Executable); //Console.WriteLine("trace: {0}", _traceexe.Executable); } // tell the user we can't work without instructions if (!parameters.Any()) { return Fail("Missing action . \r\n\r\n Use --help for command line help."); } // load property sheet (that is the .buildinfo file by default) _propertySheet = null; try { // load and parse. propertySheet will contain everything else we need for later _propertySheet = PropertySheet.Load(buildinfo); DefineRules = _propertySheet.Rules.Where(each => each.Id == "define" && each.Name == "*").ToArray(); _propertySheet.GetMacroValue += (valueName) => { if (valueName == "DEFAULTLAMBDAVALUE") { return "."; } string defaultValue = null; if( valueName.Contains("??")) { var parts = valueName.Split(new[] {'?'}, StringSplitOptions.RemoveEmptyEntries); defaultValue = parts.Length > 1 ? parts[1].Trim() : string.Empty; valueName = parts[0]; } var property = (from rule in DefineRules where rule.HasProperty(valueName) select rule[valueName]).FirstOrDefault(); if (property != null && property.HasValues && property.Values.Count() > 1) { // it's a collection of values. // let's take the collection and return it as a comma seperated string. return property.Values.Aggregate((s, s1) => s + ", " + s1); } return (from rule in DefineRules where rule.HasProperty(valueName) select rule[valueName].Value).FirstOrDefault() ?? Environment.GetEnvironmentVariable(valueName) ?? defaultValue; }; _propertySheet.GetCollection += (collectionName) => { var property = (from rule in DefineRules where rule.HasProperty(collectionName) select rule[collectionName]).FirstOrDefault(); if( property != null && property.HasValues && property.Values.Count() > 1 ) { return property.Values; } var collection = _propertySheet.GetMacroValue(collectionName); return collection != null ? collection.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(each => each.Trim()) : Enumerable.Empty<object>(); }; } catch (EndUserParseException pspe) { using (new ConsoleColors(ConsoleColor.Yellow, ConsoleColor.Black)) { Console.Write(pspe.Message); Console.WriteLine("--found '{0}'", pspe.Token.Data); } return Fail("Error parsing .buildinfo file"); } var builds = from rule in _propertySheet.Rules where rule.Name != "*" && (rule.HasProperty("default") && rule["default"].Value.IsTrue()) select rule; var command = string.Empty; switch(parameters.FirstOrDefault().ToLower()) { case "build ": case "clean": case "verify": case "status": case "trace": case "list": command = parameters.FirstOrDefault().ToLower(); parameters = parameters.Skip(1).ToArray(); break; default: command = "build"; break; } if (parameters.Any()) { var allbuilds = from rule in _propertySheet.Rules where rule.Name != "*" select rule; builds = parameters.Aggregate(Enumerable.Empty<Rule>(), (current, p) => current.Union(from build in allbuilds where build.Name.NewIsWildcardMatch(p) select build)); } // are there even builds present? if(!builds.Any() ) { return Fail("No valid build configurations selected."); } // do the user's bidding try { switch (command) { case "build": ResetEnvironment(); Build(builds); break; case "clean": ResetEnvironment(); Clean(builds); using (new ConsoleColors(ConsoleColor.White, ConsoleColor.Black)) { Console.WriteLine("Project Cleaned."); } break; case "verify": ResetEnvironment(); // Clean(builds); // clean up other builds in the list first. Verify(builds); using (new ConsoleColors(ConsoleColor.White, ConsoleColor.Black)) { Console.WriteLine("Project Verified."); } break; case "status": ResetEnvironment(); Status(builds); using (new ConsoleColors(ConsoleColor.White, ConsoleColor.Black)) { Console.WriteLine("Project is in clean state."); } break; //case "trace": // Trace(builds); //break; case "list": Console.WriteLine("Buildinfo from [{0}]\r\n", buildinfo); (from build in builds let compiler = build["compiler"] let sdk = build["sdk"] let platform = build["platform"] let targets = build["targets"] select new { Configuration = build.Name, Compiler = compiler != null ? compiler.Value : "sdk7.1", Sdk = sdk != null ? sdk.Value : "sdk7.1", Platform = platform != null ? platform.Value.NormalizePlatform() : "x86", Number_of_Outputs = targets != null ? targets.Values.Count() : 0 }).ToTable().ConsoleOut(); break; default: return Fail("'{0}' is not a valid command. \r\n\r\n Use --help for assistance.", command); } } catch (ConsoleException e) { // these exceptions are expected return Fail(" {0}", e.Message); } catch (Exception e) { // it's probably okay to crash within proper commands (because something else crashed) Console.WriteLine(e.StackTrace); return Fail(" {0}", e.Message); } return 0; }