diff --git a/AddIn/External/ICSharpCode.NRefactory.dll b/AddIn/External/ICSharpCode.NRefactory.dll index 0c824bf..5e54c43 100755 Binary files a/AddIn/External/ICSharpCode.NRefactory.dll and b/AddIn/External/ICSharpCode.NRefactory.dll differ diff --git a/AddIn/External/Mono.Addins.dll b/AddIn/External/Mono.Addins.dll new file mode 100755 index 0000000..d502984 Binary files /dev/null and b/AddIn/External/Mono.Addins.dll differ diff --git a/AddIn/External/Mono.Debugger.Soft.dll b/AddIn/External/Mono.Debugger.Soft.dll new file mode 100755 index 0000000..2b89dd9 Binary files /dev/null and b/AddIn/External/Mono.Debugger.Soft.dll differ diff --git a/AddIn/External/Mono.Debugging.Soft.dll b/AddIn/External/Mono.Debugging.Soft.dll index 7ec7a75..c925b9b 100755 Binary files a/AddIn/External/Mono.Debugging.Soft.dll and b/AddIn/External/Mono.Debugging.Soft.dll differ diff --git a/AddIn/External/Mono.Debugging.dll b/AddIn/External/Mono.Debugging.dll index 53c2520..7b85483 100755 Binary files a/AddIn/External/Mono.Debugging.dll and b/AddIn/External/Mono.Debugging.dll differ diff --git a/AddIn/External/MonoDevelop.Core.dll b/AddIn/External/MonoDevelop.Core.dll index fc9f41d..173f04a 100755 Binary files a/AddIn/External/MonoDevelop.Core.dll and b/AddIn/External/MonoDevelop.Core.dll differ diff --git a/AddIn/External/MonoDevelop.Debugger.Soft.dll b/AddIn/External/MonoDevelop.Debugger.Soft.dll index 9324f01..dff79c6 100755 Binary files a/AddIn/External/MonoDevelop.Debugger.Soft.dll and b/AddIn/External/MonoDevelop.Debugger.Soft.dll differ diff --git a/AddIn/External/MonoDevelop.Debugger.dll b/AddIn/External/MonoDevelop.Debugger.dll index 9432ecb..38eda91 100755 Binary files a/AddIn/External/MonoDevelop.Debugger.dll and b/AddIn/External/MonoDevelop.Debugger.dll differ diff --git a/AddIn/External/MonoDevelop.Ide.dll b/AddIn/External/MonoDevelop.Ide.dll index ee6c3b7..f9279f9 100755 Binary files a/AddIn/External/MonoDevelop.Ide.dll and b/AddIn/External/MonoDevelop.Ide.dll differ diff --git a/AddIn/MonoBrickAddin.csproj b/AddIn/MonoBrickAddin.csproj index 15d6e4e..9851fb0 100644 --- a/AddIn/MonoBrickAddin.csproj +++ b/AddIn/MonoBrickAddin.csproj @@ -10,8 +10,6 @@ MonoBrickAddin false MonoBrick addin for EV3 development. - 8.0.30703 - 2.0 true @@ -77,6 +75,9 @@ External\Renci.SshNet.dll + + External\Mono.Addins.dll + @@ -95,6 +96,8 @@ + + @@ -128,6 +131,14 @@ True Always + + + + + + + + @@ -136,10 +147,4 @@ - - - {67261E03-D263-4C42-A5AD-2A4820231B28} - MonoBrickFirmware - - \ No newline at end of file diff --git a/AddIn/Source/AssemblyInfo.cs b/AddIn/Source/AssemblyInfo.cs index 47f919d..5ba701c 100644 --- a/AddIn/Source/AssemblyInfo.cs +++ b/AddIn/Source/AssemblyInfo.cs @@ -4,19 +4,18 @@ // Information about this assembly is defined by the following attributes. // Change them to the values specific to your project. [assembly: AssemblyTitle ("MonoBrickAddin")] -[assembly: AssemblyDescription ("")] +[assembly: AssemblyDescription ("MonoBrick solution and debugging")] [assembly: AssemblyConfiguration ("")] [assembly: AssemblyCompany ("")] -[assembly: AssemblyProduct ("")] -[assembly: AssemblyCopyright ("Bernhard Straub")] +[assembly: AssemblyProduct ("MonoBrickAddin")] +[assembly: AssemblyCopyright ("MIT X11")] [assembly: AssemblyTrademark ("")] [assembly: AssemblyCulture ("")] // The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". // The form "{Major}.{Minor}.*" will automatically update the build and revision, // and "{Major}.{Minor}.{Build}.*" will update just the revision. -[assembly: AssemblyVersion ("0.1.*")] +[assembly: AssemblyVersion ("0.3")] // The following attributes are used to specify the signing key for the assembly, // if desired. See the Mono documentation for more information about signing. //[assembly: AssemblyDelaySign(false)] -//[assembly: AssemblyKeyFile("")] - +//[assembly: AssemblyKeyFile("")] \ No newline at end of file diff --git a/AddIn/Source/MonoBrickAddin.addin.xml b/AddIn/Source/MonoBrickAddin.addin.xml index e72f250..adf5fe4 100644 --- a/AddIn/Source/MonoBrickAddin.addin.xml +++ b/AddIn/Source/MonoBrickAddin.addin.xml @@ -1,25 +1,15 @@ - name="MonoBrickAddin" - author="Bernhard Straub" - copyright="MIT X11" description="MonoBrick solution and debugging" category="Mindstorms" - version="0.1"> - - - - - - - + version="0.3"> + - + @@ -39,6 +29,10 @@ + + + + diff --git a/AddIn/Source/MonoBrickAddinDebuggerSession.cs b/AddIn/Source/MonoBrickAddinDebuggerSession.cs index f26e173..9079e59 100644 --- a/AddIn/Source/MonoBrickAddinDebuggerSession.cs +++ b/AddIn/Source/MonoBrickAddinDebuggerSession.cs @@ -60,7 +60,9 @@ void StartProcess(MonoBrickSoftDebuggerStartInfo dsi) string debugOptions = string.Format("transport=dt_socket,address=0.0.0.0:{0},server=y", args.DebugPort); bool EV3Verbose = UserSettings.Instance.Verbose; - process = MonoBrickUtility.ExecuteCommand(EV3IPAddress, dsi.ExecutionCommand, debugOptions, dsi.ExecutionCommand.Console, EV3Verbose); + dsi.ExecutionCommand.Console.Log.WriteLine("Debugging on brick ..."); + + process = MonoBrickUtility.ExecuteCommand(EV3IPAddress, dsi.ExecutionCommand, debugOptions, EV3Verbose); process.Execute(); process.WaitForExecuted(); } diff --git a/AddIn/Source/MonoBrickAddinExecutionCommand.cs b/AddIn/Source/MonoBrickAddinExecutionCommand.cs index 83cf34e..2a49972 100644 --- a/AddIn/Source/MonoBrickAddinExecutionCommand.cs +++ b/AddIn/Source/MonoBrickAddinExecutionCommand.cs @@ -34,17 +34,23 @@ public class MonoBrickExecutionCommand: ExecutionCommand { public IConsole Console { get; set; } public IList UserAssemblyPaths { get; set; } + public bool AOT { get; set; } + public int LastError { get; set; } public MonoBrickExecutionCommand() { this.Config = null; Console = null; + AOT = false; + LastError = 0; } - public MonoBrickExecutionCommand(MonoBrickProjectConfiguration config)// : base(config.CompiledOutputName) + public MonoBrickExecutionCommand(MonoBrickProjectConfiguration config) { this.Config = config; Console = null; + AOT = false; + LastError = 0; } public MonoBrickProjectConfiguration Config { get; private set; } @@ -64,7 +70,7 @@ public string CommandString public string DeviceDirectory { get { - return "./apps/" + Path.GetFileNameWithoutExtension(Config.OutputAssembly) + "/"; + return "/home/root/apps/" + Path.GetFileNameWithoutExtension(Config.OutputAssembly) + "/"; } } diff --git a/AddIn/Source/MonoBrickAddinExecutionHandler.cs b/AddIn/Source/MonoBrickAddinExecutionHandler.cs index 115e4cd..ff2af1e 100644 --- a/AddIn/Source/MonoBrickAddinExecutionHandler.cs +++ b/AddIn/Source/MonoBrickAddinExecutionHandler.cs @@ -31,18 +31,41 @@ namespace MonoBrickAddin { class MonoBrickExecutionHandler : IExecutionHandler { + public bool AOT { get; private set; } + + public MonoBrickExecutionHandler() + { + AOT = false; + } + + public MonoBrickExecutionHandler(bool _aot) + { + AOT = _aot; + } + public bool CanExecute(ExecutionCommand command) { - return command is MonoBrickExecutionCommand; + MonoBrickExecutionCommand cmd = command as MonoBrickExecutionCommand; + if (cmd == null) + return false; + + if (AOT && cmd.Config.Name != "Release") + return false; + + return true; } public IProcessAsyncOperation Execute(ExecutionCommand command, IConsole console) { - var cmd = (MonoBrickExecutionCommand)command; + var cmd = command as MonoBrickExecutionCommand; + cmd.AOT = AOT; + string EV3IPAddress = UserSettings.Instance.IPAddress; bool EV3Verbose = UserSettings.Instance.Verbose; - var proc = MonoBrickUtility.ExecuteCommand(EV3IPAddress, cmd, null, console, EV3Verbose); + console.Log.WriteLine(cmd.AOT ? "Running on brick in AOT mode ..." : "Running on brick ..."); + + var proc = MonoBrickUtility.ExecuteCommand(EV3IPAddress, cmd, null, EV3Verbose); proc.Execute(); return proc; } diff --git a/AddIn/Source/MonoBrickAddinExecutionModeSet.cs b/AddIn/Source/MonoBrickAddinExecutionModeSet.cs new file mode 100644 index 0000000..d3c88ca --- /dev/null +++ b/AddIn/Source/MonoBrickAddinExecutionModeSet.cs @@ -0,0 +1,62 @@ +// MonoBrickAddinExecutionModeSet.cs +// +// Author: +// Bernhard Straub +// +// Copyright (c) 2014 Bernhard Straub +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using MonoDevelop.Core.Execution; +using System.Collections.Generic; + +namespace MonoBrickAddin +{ + public class MonoBrickExecutionModeSet : IExecutionModeSet + { + MonoBrickExecutionMode mode; + + public string Name { get { return "MonoBrick"; } } + + public IEnumerable ExecutionModes + { + get { + yield return mode ?? (mode = new MonoBrickExecutionMode()); + } + } + } + + class MonoBrickExecutionMode : IExecutionMode + { + MonoBrickExecutionHandler handler; + + public string Name { get { return "MonoBrick AOT"; } } + + public string Id { get { return "MonoBrickExecutionMode"; } } + + public IExecutionHandler ExecutionHandler + { + get { + return handler ?? (handler = new MonoBrickExecutionHandler(true)); + } + } + } +} + diff --git a/AddIn/Source/MonoBrickAddinInfo.cs b/AddIn/Source/MonoBrickAddinInfo.cs new file mode 100644 index 0000000..eb9363c --- /dev/null +++ b/AddIn/Source/MonoBrickAddinInfo.cs @@ -0,0 +1,20 @@ +using System; +using Mono.Addins; +using Mono.Addins.Description; + +[assembly:Addin ( + "MonoBrickAddin", + Namespace = "MonoBrickAddin", + Version = "0.3", + Url = "http://github.com/Larsjep/monoev3" +)] + +[assembly:AddinName ("MonoBrickAddin")] +[assembly:AddinCategory ("Mindstorms")] +[assembly:AddinDescription ("MonoBrick solution and debugging")] +[assembly:AddinAuthor ("Bernhard Straub")] + +[assembly:AddinDependency ("::MonoDevelop.Core", MonoDevelop.BuildInfo.Version)] +[assembly:AddinDependency ("::MonoDevelop.Ide", MonoDevelop.BuildInfo.Version)] +[assembly:AddinDependency ("::MonoDevelop.Debugger", MonoDevelop.BuildInfo.Version)] +[assembly:AddinDependency ("::MonoDevelop.Debugger.Soft", MonoDevelop.BuildInfo.Version)] \ No newline at end of file diff --git a/AddIn/Source/MonoBrickAddinProjects.cs b/AddIn/Source/MonoBrickAddinProjects.cs index ac81a96..8cf9a74 100644 --- a/AddIn/Source/MonoBrickAddinProjects.cs +++ b/AddIn/Source/MonoBrickAddinProjects.cs @@ -61,7 +61,7 @@ public MonoBrickProject(string languageName, ProjectCreateInformation info, XmlE void Init() { if (!referencePath.IsEmpty) - CreateReference(referencePath); + CreateReference(referencePath, "MonoBrickFirmware.dll"); } public override SolutionItemConfiguration CreateConfiguration(string name) @@ -90,20 +90,15 @@ protected override ExecutionCommand CreateExecutionCommand(ConfigurationSelector }; } - protected void CreateReference(FilePath sPath) + protected void CreateReference(FilePath sPath, string sName) { - // Get the resource and write it out? - FilePath sFileName = sPath.Combine("MonoBrickFirmware.dll"); + // Get the assembly file and write it out + FilePath sFileNameOut = sPath.Combine(sName); - FileStream OutputStream = new FileStream(sFileName, FileMode.Create); - Assembly ass = Assembly.GetExecutingAssembly(); - - Stream DBStream = ass.GetManifestResourceStream("MonoBrick.MonoBrickFirmware.dll"); - for (int l = 0; l < DBStream.Length; l++) - { - OutputStream.WriteByte((byte)DBStream.ReadByte()); - } - OutputStream.Close(); + FilePath assemblyPath = Assembly.GetExecutingAssembly().Location; + FilePath assemblyDirectory = Path.GetDirectoryName(assemblyPath); + FilePath sFileNameIn = assemblyDirectory.Combine(sName); + File.Copy(sFileNameIn, sFileNameOut, true); } protected override void OnExecute(IProgressMonitor monitor, ExecutionContext context, ConfigurationSelector configSel) @@ -142,30 +137,37 @@ protected override void OnExecute(IProgressMonitor monitor, ExecutionContext con return; } - console.Log.WriteLine("Upload to brick..."); - string EV3IPAddress = UserSettings.Instance.IPAddress; - var uploadOp = MonoBrickUtility.Upload(EV3IPAddress, cmd); - opMon.AddOperation(uploadOp); - - uploadOp.WaitForCompleted(); - - if (!uploadOp.Success) + for (int pass = 0; pass < 2; ++pass) { - console.Log.WriteLine(uploadOp.ErrorMessage); - monitor.ReportError(uploadOp.ErrorMessage, null); - return; - } + console.Log.WriteLine(pass == 0 ? "Upload to brick..." : "Forcing upload to brick..."); + + var uploadOp = MonoBrickUtility.Upload(EV3IPAddress, cmd); + opMon.AddOperation(uploadOp); - console.Log.WriteLine("Running on brick..."); + uploadOp.WaitForCompleted(); + + if (!uploadOp.Success) + { + console.Log.WriteLine(uploadOp.ErrorMessage); + monitor.ReportError(uploadOp.ErrorMessage, null); + return; + } - var ex = context.ExecutionHandler.Execute(cmd, console); - opMon.AddOperation(ex); - ex.WaitForCompleted(); + var ex = context.ExecutionHandler.Execute(cmd, console); + opMon.AddOperation(ex); + ex.WaitForCompleted(); + + if (pass == 1 || cmd.LastError == 0) + break; + + // force upload + console.Log.WriteLine("First attempt to run failed!"); + UserSettings.Instance.LastUploadHash = ""; + } - console.Log.WriteLine(""); - console.Log.WriteLine("Finished!"); + console.Log.WriteLine("Finished with exit code {0}", cmd.LastError); } finally { diff --git a/AddIn/Source/MonoBrickAddinScpUpload.cs b/AddIn/Source/MonoBrickAddinScpUpload.cs index 2f3d01b..418b05b 100644 --- a/AddIn/Source/MonoBrickAddinScpUpload.cs +++ b/AddIn/Source/MonoBrickAddinScpUpload.cs @@ -28,8 +28,10 @@ using System.IO; using System.Linq; using System.Text; +using System.Text.RegularExpressions; using System.Security.Cryptography; using MonoDevelop.Core; +using MonoDevelop.Core.Execution; using Renci.SshNet; namespace MonoBrickAddin @@ -38,10 +40,10 @@ class ScpUpload : IAsyncOperation { private string _localPath; private string _remotePath; + private IConsole _console = null; private ScpClient _scpClient = null; private SshCommandHelper _sshHelper = null; private string _fileHash; - // IAsyncOperation public bool IsCompleted { get; private set; } @@ -69,13 +71,14 @@ public void Cancel() wait.Set(); } - public ScpUpload(string IPAddress, string localPath, string remotePath) + public ScpUpload(string IPAddress, MonoBrickExecutionCommand cmd) { - _localPath = localPath; - _remotePath = remotePath; + _localPath = cmd.Config.OutputDirectory; + _remotePath = cmd.DeviceDirectory; _scpClient = new ScpClient(IPAddress, "root", ""); _sshHelper = new SshCommandHelper(IPAddress); _fileHash = UserSettings.Instance.LastUploadHash; + _console = cmd.Console; Success = false; SuccessWithWarnings = false; @@ -123,10 +126,14 @@ public void Upload() private void DoUpload() { string newUploadHash = CreateMd5ForFolder(_localPath); - if (newUploadHash == _fileHash) - return; // nothing to do + if (newUploadHash == _fileHash && VerifiyRemoteFiles()) + { + _console.Log.WriteLine("Data unchanged, skipping upload!"); + return; + } - _sshHelper.WriteSSHCommand(GetDirectoryCommand()); + _sshHelper.WriteSSHCommand(_sshHelper.GetDirectoryCommand(_remotePath)); + _sshHelper.WriteSSHCommand(_sshHelper.GetCleanCommand(_remotePath, _fileHash == "")); _scpClient.Connect(); @@ -140,12 +147,25 @@ private void DoUpload() UserSettings.Save(); } - private string GetDirectoryCommand() + private bool VerifiyRemoteFiles() { - string makeDirString = string.Format("mkdir -p {0}", _remotePath); - return makeDirString; + string fileListRemote = _sshHelper.WriteSSHCommand(_sshHelper.GetFileListCommand(_remotePath), false, true); + + var usedFileListRemote = _sshHelper.RegexExecutionFiles.Matches(fileListRemote) + .OfType() + .Select(m => m.Groups[0].Value) + .ToArray(); + + var usedFileListLocal = new DirectoryInfo(_localPath).GetFiles().Select(o => o.Name).Where(f => _sshHelper.RegexExtension.IsMatch(f)).ToArray(); + + var missingFileList = usedFileListLocal.Where(file => !usedFileListRemote.Contains(file)).ToArray(); + string missingFiles = string.Concat(missingFileList.ToArray().Select(a => a += ", ").ToArray()); + if (missingFileList.Count() > 0) + _console.Log.WriteLine("Found missing remote file(s): {0} forcing upload...", missingFiles); + + return (missingFileList.Count() == 0); } - + private static string CreateMd5ForFolder(string path) { string newHash = ""; @@ -158,7 +178,7 @@ private static string CreateMd5ForFolder(string path) MD5 md5 = MD5.Create(); - for(int i = 0; i < files.Count; i++) + for (int i = 0; i < files.Count; i++) { string file = files[i]; diff --git a/AddIn/Source/MonoBrickAddinSshCommandHelper.cs b/AddIn/Source/MonoBrickAddinSshCommandHelper.cs index 0b5bef9..273766e 100644 --- a/AddIn/Source/MonoBrickAddinSshCommandHelper.cs +++ b/AddIn/Source/MonoBrickAddinSshCommandHelper.cs @@ -26,6 +26,8 @@ using System; using System.IO; using System.Threading; +using System.Text.RegularExpressions; +using System.Globalization; using MonoDevelop.Core.Execution; using Renci.SshNet; @@ -33,17 +35,28 @@ namespace MonoBrickAddin { class SshCommandHelper { + public int ErrorCode { get; private set; } + private SshClient _sshClient = null; private IConsole _console = null; private bool _verbose = false; private ManualResetEvent _executed; + // regex + public Regex RegexAot = new Regex("(-{1,2}(full)?-{0,2}aot=?(full)?)", RegexOptions.Compiled); + public Regex RegexExeDll = new Regex(@"\b\w+\.(exe|dll)(?!\.)\b", RegexOptions.Compiled); + public Regex RegexExecutionFiles = new Regex(@"\b\w+\.(exe|dll)(?:\.mdb|\.pdb)?(?!\.so)\b", RegexOptions.Compiled); + public Regex RegexSo = new Regex(@"\b\w+\.(exe|dll)(?=\.so)\b", RegexOptions.Compiled); + public Regex RegexResponse = new Regex(@"(?<=sh: )(-?[0-9]+)(?!"")", RegexOptions.Compiled); + public Regex RegexExtension = new Regex(@"$(?<=\.(exe|mdb|pdb|dll))", RegexOptions.Compiled); + public SshCommandHelper(string IPAddress, ManualResetEvent executed = null, IConsole console = null, bool verbose = false) { _executed = executed; _console = console; _verbose = verbose; _sshClient = new SshClient(IPAddress, "root", ""); + ErrorCode = 0; } public void Cancel() @@ -52,15 +65,18 @@ public void Cancel() _sshClient.Disconnect(); } - public void WriteSSHCommand(string command, bool waitUntilFinished = false) + public string WriteSSHCommand(string command, bool waitUntilFinished = false, bool scriptWithEcho = false) { + string result = ""; + if (_executed != null) _executed.Reset(); _sshClient.Connect(); - using (var stream = _sshClient.CreateShellStream("MonoBrickShell", 80, 24, 800, 600, 1024)) + using (var stream = _sshClient.CreateShellStream("MonoBrickShell", 200, 80, 800, 600, 1024)) { + ErrorCode = -1; var writer = new StreamWriter(stream); writer.AutoFlush = true; @@ -71,42 +87,84 @@ public void WriteSSHCommand(string command, bool waitUntilFinished = false) if (_executed != null) _executed.Set(); - WaitForPrompt(stream, !waitUntilFinished); + result = WaitForPrompt(stream, !waitUntilFinished); + + // get error code + if (!scriptWithEcho) + { + writer.WriteLine("$?"); + result = WaitForPrompt(stream, true); + + string error = RegexResponse.Match(result).Value; + + if (!String.IsNullOrEmpty(error)) + ErrorCode = int.Parse(error); + } } _sshClient.Disconnect(); + + if (_verbose && _console != null) + _console.Log.Write(Environment.NewLine); + + return result; } - private void WaitForPrompt(ShellStream stream, bool timeOut) + private string WaitForPrompt(ShellStream stream, bool timeOut) { - if (_verbose) + string result = ""; + + if (timeOut) { - if (timeOut) - { - stream.Expect(TimeSpan.FromSeconds(5), new Renci.SshNet.ExpectAction("#", - (output) => + stream.Expect(TimeSpan.FromSeconds(5), new Renci.SshNet.ExpectAction("#", + (output) => { - if (_console != null) - _console.Log.Write(output); + result = output; })); - } - else - { - stream.Expect(new Renci.SshNet.ExpectAction("#", - (output) => - { - if (_console != null) - _console.Log.Write(output); - })); - } } else { - if (timeOut) - stream.Expect("#", TimeSpan.FromSeconds(5)); - else - stream.Expect("#"); + stream.Expect(new Renci.SshNet.ExpectAction("#", + (output) => + { + result = output; + })); } + + if (_verbose && _console != null) + _console.Log.Write(result); + + return result; + } + + public string GetKillCommand(string appToKill) + { + string killString = string.Format("kill -9 `ps | grep {0} | grep mono | awk '{{print $1}}'`", appToKill); + return killString; + } + + public string GetFileListCommand(string remotePath) + { + string getFileListString = string.Format(@"find {0} -maxdepth 1 -type f -regex "".*/.*\.\(exe\|mdb\|pdb\|dll\|so\)""", remotePath); + return getFileListString; + } + + public string GetDirectoryCommand(string remotePath) + { + string makeDirString = string.Format("mkdir -p {0}", remotePath); + return makeDirString; + } + + public string GetCleanCommand(string remotePath, bool bFull) + { + string cleanString = ""; + + if (bFull) + cleanString = string.Format(@"find {0} -maxdepth 1 -type f -regex "".*/.*\.\(exe\|mdb\|pdb\|so\)"" -delete", remotePath); + else + cleanString = string.Format(@"find {0} -maxdepth 1 -type f -regex "".*/.*\.\(exe\|mdb\|pdb\|exe.so\)"" -delete", remotePath); + + return cleanString; } } } \ No newline at end of file diff --git a/AddIn/Source/MonoBrickAddinSshExecute.cs b/AddIn/Source/MonoBrickAddinSshExecute.cs index a98e676..757ba40 100644 --- a/AddIn/Source/MonoBrickAddinSshExecute.cs +++ b/AddIn/Source/MonoBrickAddinSshExecute.cs @@ -25,12 +25,14 @@ using System; using System.Text; +using System.Text.RegularExpressions; +using System.Collections.Generic; using System.IO; using System.Threading; +using System.Linq; using MonoDevelop.Core; using MonoDevelop.Core.Execution; using Renci.SshNet; -using System.Text.RegularExpressions; namespace MonoBrickAddin { @@ -76,17 +78,15 @@ public void WaitForExecuted() public void Cancel() { _sshHelper.Cancel(); - - //DoKill (); wait.Set(); } - public SshExecute(string IPAddress, MonoBrickExecutionCommand cmd, string sdbOptions, IConsole console, bool verbose) + public SshExecute(string IPAddress, MonoBrickExecutionCommand cmd, string sdbOptions, bool verbose) { _cmd = cmd; _sdbOptions = sdbOptions; - _console = console; - _sshHelper = new SshCommandHelper(IPAddress, _executed, console, verbose); + _console = cmd.Console; + _sshHelper = new SshCommandHelper(IPAddress, _executed, cmd.Console, verbose); Success = false; SuccessWithWarnings = false; } @@ -124,12 +124,14 @@ public void Execute() wait.Set(); if (Completed != null) Completed(this); + + _cmd.LastError = _sshHelper.ErrorCode; }); } private void DoKill(string appToKill) { - _sshHelper.WriteSSHCommand(GetKillCommand(appToKill)); + _sshHelper.WriteSSHCommand(_sshHelper.GetKillCommand(appToKill)); } private void DoRun() @@ -139,52 +141,65 @@ private void DoRun() private string GetRunString() { - Regex regexAot = new Regex("(-{1,2}(full)?-{0,2}aot=?(full)?)", RegexOptions.Compiled); - string additionalParameters = string.IsNullOrEmpty(_cmd.Config.CommandLineParameters) ? "" : _cmd.Config.CommandLineParameters; - MatchCollection matches = regexAot.Matches(additionalParameters); + MatchCollection matches = _sshHelper.RegexAot.Matches(additionalParameters); - bool aotMode = matches.Count > 0; - bool debugging = !string.IsNullOrEmpty(_sdbOptions); - bool debugMode = false; + if (matches.Count > 0) + { + _console.Log.WriteLine("Please use build in AOT run mode!"); + additionalParameters = _sshHelper.RegexAot.Replace(additionalParameters, ""); + } + + if (_cmd.AOT) + DoAOTCompile(); var sb = new StringBuilder(); sb.Append("mono "); if (_cmd.Config.ToString().Contains("Debug")) - { sb.Append("--debug "); - debugMode = true; - } - - if (aotMode && (debugging || debugMode)) - { - aotMode = false; - _console.Log.WriteLine("Aot not supported in debug mode or for softdebugger, discarding!"); - additionalParameters = regexAot.Replace(additionalParameters, ""); - } if (!string.IsNullOrEmpty(_sdbOptions)) sb.AppendFormat("--debugger-agent={0}", _sdbOptions); - sb.AppendFormat("{0} '{1}'", additionalParameters, _cmd.DeviceExePath); + if (_cmd.AOT) + sb.Append("--full-aot "); - if (aotMode) - sb.AppendFormat(" && mono '{0}'", _cmd.DeviceExePath); + sb.AppendFormat("{0} '{1}'", additionalParameters, _cmd.DeviceExePath); return sb.ToString(); } - private string GetKillCommand(string appToKill) + private void DoAOTCompile() { - if (appToKill == "") - appToKill = _cmd.AppName; + string fileList = _sshHelper.WriteSSHCommand(_sshHelper.GetFileListCommand(_cmd.DeviceDirectory), false, true); + + var exeDllList = _sshHelper.RegexExeDll.Matches(fileList) + .OfType() + .Select(m => m.Groups[0].Value) + .ToArray(); + + var soList = _sshHelper.RegexSo.Matches(fileList) + .OfType() + .Select(m => m.Groups[0].Value) + .ToArray(); - string killString = string.Format("kill -9 `ps | grep {0} | grep mono | awk '{{print $1}}'`", appToKill); - return killString; + var compileList = exeDllList.Where(fileNative => !soList.Contains(fileNative)).ToArray(); + + if (compileList.Count() == 0) + _console.Log.WriteLine("All files compiled, nothing to do!"); + + foreach (var file in compileList) + { + string compileTarget = string.Format(@"mono --aot=full {0}{1}", _cmd.DeviceDirectory, file); + _console.Log.WriteLine(string.Format("Compiling {0} for AOT execution", file)); + _sshHelper.WriteSSHCommand(compileTarget, true); + } } + + } } \ No newline at end of file diff --git a/AddIn/Source/MonoBrickAddinUtility.cs b/AddIn/Source/MonoBrickAddinUtility.cs index 3d9c5f5..d5c7f68 100644 --- a/AddIn/Source/MonoBrickAddinUtility.cs +++ b/AddIn/Source/MonoBrickAddinUtility.cs @@ -35,14 +35,14 @@ class MonoBrickUtility { public static ScpUpload Upload(string IPAddress, MonoBrickExecutionCommand cmd) { - var scp = new ScpUpload(IPAddress, cmd.Config.OutputDirectory, cmd.DeviceDirectory); + var scp = new ScpUpload(IPAddress, cmd); scp.Upload(); return scp; } - public static SshExecute ExecuteCommand(string IPAddress, MonoBrickExecutionCommand cmd, string sdbOptions, IConsole console, bool verbose) + public static SshExecute ExecuteCommand(string IPAddress, MonoBrickExecutionCommand cmd, string sdbOptions, bool verbose) { - var sshC = new SshExecute(IPAddress, cmd, sdbOptions, console, verbose); + var sshC = new SshExecute(IPAddress, cmd, sdbOptions, verbose); return sshC; } diff --git a/AddIn/Templates/MonoBrickProject.xpt.xml b/AddIn/Templates/MonoBrickProject.xpt.xml index 9c91330..ceea86a 100644 --- a/AddIn/Templates/MonoBrickProject.xpt.xml +++ b/AddIn/Templates/MonoBrickProject.xpt.xml @@ -59,7 +59,7 @@ namespace MonoBrickHelloWorld }; LcdConsole.WriteLine("Hello World"); - + LcdConsole.WriteLine("Esc. terminate"); stopped.WaitOne(); } } diff --git a/AddIn/gtk-gui/MonoBrickAddin.EV3OptionsPanel.cs b/AddIn/gtk-gui/MonoBrickAddin.EV3OptionsPanel.cs index cdca0dd..bab98f9 100644 --- a/AddIn/gtk-gui/MonoBrickAddin.EV3OptionsPanel.cs +++ b/AddIn/gtk-gui/MonoBrickAddin.EV3OptionsPanel.cs @@ -5,16 +5,27 @@ namespace MonoBrickAddin public partial class EV3OptionsPanel { private global::Gtk.VBox vbox1; + private global::Gtk.Frame frame1; + private global::Gtk.Alignment GtkAlignment; + private global::Gtk.Table table1; + private global::Gtk.HBox hbox2; + private global::Gtk.CheckButton wEV3Verbose; + private global::Gtk.HSeparator hseparator1; + private global::Gtk.Label label2; + private global::Gtk.Label label3; + private global::Gtk.Entry wEV3DebugPort; + private global::Gtk.Entry wEV3IPAddress; + private global::Gtk.Label GtkLabel2; protected virtual void Build () diff --git a/AddIn/gtk-gui/generated.cs b/AddIn/gtk-gui/generated.cs index 75935e2..3285e87 100644 --- a/AddIn/gtk-gui/generated.cs +++ b/AddIn/gtk-gui/generated.cs @@ -17,6 +17,7 @@ internal static void Initialize (Gtk.Widget iconRenderer) internal class BinContainer { private Gtk.Widget child; + private Gtk.UIManager uimanager; public static BinContainer Attach (Gtk.Bin bin) diff --git a/AddIn/gtk-gui/gui.stetic b/AddIn/gtk-gui/gui.stetic index 068b327..290f405 100644 --- a/AddIn/gtk-gui/gui.stetic +++ b/AddIn/gtk-gui/gui.stetic @@ -5,9 +5,7 @@ 2.12 - - - + diff --git a/MonoBrick.sln b/MonoBrick.sln index a55bf1c..9dd4303 100644 --- a/MonoBrick.sln +++ b/MonoBrick.sln @@ -76,13 +76,11 @@ Global {11C84BA4-9A8A-4BF2-AA7B-2D45AC63ACAE}.Release|x86.ActiveCfg = Release|x86 {11C84BA4-9A8A-4BF2-AA7B-2D45AC63ACAE}.Release|x86.Build.0 = Release|x86 {314570C2-D0F1-45D2-868D-FA54E2F538F8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {314570C2-D0F1-45D2-868D-FA54E2F538F8}.Debug|Any CPU.Build.0 = Debug|Any CPU {314570C2-D0F1-45D2-868D-FA54E2F538F8}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU {314570C2-D0F1-45D2-868D-FA54E2F538F8}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU {314570C2-D0F1-45D2-868D-FA54E2F538F8}.Debug|x86.ActiveCfg = Debug|Any CPU {314570C2-D0F1-45D2-868D-FA54E2F538F8}.Debug|x86.Build.0 = Debug|Any CPU {314570C2-D0F1-45D2-868D-FA54E2F538F8}.Release|Any CPU.ActiveCfg = Release|Any CPU - {314570C2-D0F1-45D2-868D-FA54E2F538F8}.Release|Any CPU.Build.0 = Release|Any CPU {314570C2-D0F1-45D2-868D-FA54E2F538F8}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU {314570C2-D0F1-45D2-868D-FA54E2F538F8}.Release|Mixed Platforms.Build.0 = Release|Any CPU {314570C2-D0F1-45D2-868D-FA54E2F538F8}.Release|x86.ActiveCfg = Release|Any CPU