From 4fbe47ccac2bdcae52aafa07d6a80176e9606bd9 Mon Sep 17 00:00:00 2001 From: Roy Ben-Shabat Date: Mon, 30 Oct 2017 19:38:10 +0200 Subject: Some more work on protobuf compilers. --- Software/Tango.NET/Tango.Core/AssemblyHelper.cs | 21 ++++ Software/Tango.NET/Tango.Core/PathHelper.cs | 32 ++++++ .../Tango.Core/Properties/AssemblyInfo.cs | 6 + Software/Tango.NET/Tango.Core/Tango.Core.csproj | 48 ++++++++ .../Tango.Protobuf/Compilers/CSharpCompiler.cs | 18 +++ .../Tango.NET/Tango.Protobuf/IProtoCompiler.cs | 22 +++- Software/Tango.NET/Tango.Protobuf/ProtoCompiler.cs | 123 ++++++++++++++++----- Software/Tango.NET/Tango.Protobuf/ProtoLanguage.cs | 36 ++++++ Software/Tango.NET/Tango.Protobuf/ProtoResult.cs | 51 +++++++++ .../Tango.NET/Tango.Protobuf/Tango.Protobuf.csproj | 9 ++ Software/Tango.NET/Tango.sln | 6 + 11 files changed, 344 insertions(+), 28 deletions(-) create mode 100644 Software/Tango.NET/Tango.Core/AssemblyHelper.cs create mode 100644 Software/Tango.NET/Tango.Core/PathHelper.cs create mode 100644 Software/Tango.NET/Tango.Core/Properties/AssemblyInfo.cs create mode 100644 Software/Tango.NET/Tango.Core/Tango.Core.csproj create mode 100644 Software/Tango.NET/Tango.Protobuf/Compilers/CSharpCompiler.cs create mode 100644 Software/Tango.NET/Tango.Protobuf/ProtoLanguage.cs create mode 100644 Software/Tango.NET/Tango.Protobuf/ProtoResult.cs (limited to 'Software/Tango.NET') diff --git a/Software/Tango.NET/Tango.Core/AssemblyHelper.cs b/Software/Tango.NET/Tango.Core/AssemblyHelper.cs new file mode 100644 index 000000000..5a78f9fe3 --- /dev/null +++ b/Software/Tango.NET/Tango.Core/AssemblyHelper.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.Core +{ + public static class AssemblyHelper + { + public static String GetCurrentAssemblyFolder() + { + string codeBase = Assembly.GetExecutingAssembly().CodeBase; + UriBuilder uri = new UriBuilder(codeBase); + string path = Uri.UnescapeDataString(uri.Path); + return Path.GetDirectoryName(path); + } + } +} diff --git a/Software/Tango.NET/Tango.Core/PathHelper.cs b/Software/Tango.NET/Tango.Core/PathHelper.cs new file mode 100644 index 000000000..08dbf1c16 --- /dev/null +++ b/Software/Tango.NET/Tango.Core/PathHelper.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.Core +{ + public static class PathHelper + { + public static String GetTempFolderPath() + { + String tempDirectory = Path.Combine(Path.GetTempPath(), "Twine", Path.GetRandomFileName()); + Directory.CreateDirectory(tempDirectory); + return tempDirectory; + } + + public static bool TryDeleteFolder(String path) + { + try + { + Directory.Delete(path, true); + return true; + } + catch + { + return false; + } + } + } +} diff --git a/Software/Tango.NET/Tango.Core/Properties/AssemblyInfo.cs b/Software/Tango.NET/Tango.Core/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..f76af4bb8 --- /dev/null +++ b/Software/Tango.NET/Tango.Core/Properties/AssemblyInfo.cs @@ -0,0 +1,6 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle("Twine - Core Components")] +[assembly: ComVisible(false)] \ No newline at end of file diff --git a/Software/Tango.NET/Tango.Core/Tango.Core.csproj b/Software/Tango.NET/Tango.Core/Tango.Core.csproj new file mode 100644 index 000000000..803d9e3e6 --- /dev/null +++ b/Software/Tango.NET/Tango.Core/Tango.Core.csproj @@ -0,0 +1,48 @@ + + + + + Debug + AnyCPU + {A34EE0F0-649D-41C8-8489-B6F1CC6924EE} + Library + Properties + Tango.Core + Tango.Core + v4.5 + 512 + + + true + full + false + ..\Build\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Software/Tango.NET/Tango.Protobuf/Compilers/CSharpCompiler.cs b/Software/Tango.NET/Tango.Protobuf/Compilers/CSharpCompiler.cs new file mode 100644 index 000000000..4f9e52a74 --- /dev/null +++ b/Software/Tango.NET/Tango.Protobuf/Compilers/CSharpCompiler.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.Protobuf.Compilers +{ + public class CSharpCompiler : ProtoCompiler + { + public override ProtoLanguage Language => ProtoLanguage.CSharp; + + protected override string GetProtoArguments() + { + return "--csharp_out"; + } + } +} diff --git a/Software/Tango.NET/Tango.Protobuf/IProtoCompiler.cs b/Software/Tango.NET/Tango.Protobuf/IProtoCompiler.cs index bd2923ede..3d7e05411 100644 --- a/Software/Tango.NET/Tango.Protobuf/IProtoCompiler.cs +++ b/Software/Tango.NET/Tango.Protobuf/IProtoCompiler.cs @@ -15,8 +15,24 @@ namespace Tango.Protobuf /// Compiles the specified .proto message file and saves the result at the specified output folder. /// /// .proto file to compile - /// Output folder to save the resulted source code. - /// A list of output source code files. - List Compile(String inputFile, String outputFolder); + /// A list of compiled results. + IEnumerable Compile(String inputFile); + + /// + /// Compiles the specified .proto message file asynchronously and saves the result at the specified output folder. + /// + /// .proto file to compile + /// A list of compiled results. + Task> CompileAsync(String inputFile); + + /// + /// Gets the compiler language. + /// + ProtoLanguage Language { get; } + + /// + /// Gets the proto imports folders. + /// + List ImportsFolders { get; } } } diff --git a/Software/Tango.NET/Tango.Protobuf/ProtoCompiler.cs b/Software/Tango.NET/Tango.Protobuf/ProtoCompiler.cs index 0095046ce..eedebf63b 100644 --- a/Software/Tango.NET/Tango.Protobuf/ProtoCompiler.cs +++ b/Software/Tango.NET/Tango.Protobuf/ProtoCompiler.cs @@ -1,51 +1,124 @@ using System; using System.Collections.Generic; +using System.Diagnostics; +using System.IO; using System.Linq; +using System.Reflection; using System.Text; using System.Threading.Tasks; +using Tango.Core; namespace Tango.Protobuf { + /// + /// Represents a protobuf compiler base class. + /// + /// public abstract class ProtoCompiler : IProtoCompiler { - public List Compile(string inputFile, string outputFolder) + private const String COMPILERS_FOLDER_NAME = "ProtoCompilers"; //Compilers folder name. + protected String _compilersPath; //Compilers folder path. + + /// + /// Gets the compiler language. + /// + public abstract ProtoLanguage Language { get; } + + /// + /// Gets the proto imports folders. + /// + public List ImportsFolders { get; private set; } + + /// + /// Initializes a new instance of the class. + /// + public ProtoCompiler() { - throw new NotImplementedException(); + _compilersPath = Path.Combine(AssemblyHelper.GetCurrentAssemblyFolder(), COMPILERS_FOLDER_NAME); } - #region IDisposable Support - private bool disposedValue = false; // To detect redundant calls - - protected virtual void Dispose(bool disposing) + /// + /// Compiles the specified .proto message file and saves the result at the specified output folder. + /// + /// .proto file to compile + /// + /// A list of compiled results. + /// + public virtual IEnumerable Compile(string inputFile) { - if (!disposedValue) + String tmpPath = PathHelper.GetTempFolderPath(); + + String importsString = String.Empty; + + foreach (var path in ImportsFolders) { - if (disposing) - { - // TODO: dispose managed state (managed objects). - } + importsString = "--proto_path \"" + path + "\" "; + } + + Process p = new Process(); + p.StartInfo.FileName = Path.Combine(_compilersPath, GetProtoCompilerName()); + p.StartInfo.Arguments = String.Format( + "{0} {1}=\"{2}\" \"{3}\"", + importsString, + GetProtoArguments(), + tmpPath, + inputFile); + + p.StartInfo.CreateNoWindow = true; + p.StartInfo.UseShellExecute = false; + p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden; + + p.Start(); + p.WaitForExit(5000); - // TODO: free unmanaged resources (unmanaged objects) and override a finalizer below. - // TODO: set large fields to null. + List results = new List(); - disposedValue = true; + foreach (var file in Directory.GetFiles(tmpPath)) + { + ProtoResult result = new ProtoResult(Path.GetFileName(file), File.ReadAllText(file), Language); } + + PathHelper.TryDeleteFolder(tmpPath); + + return results; } - // TODO: override a finalizer only if Dispose(bool disposing) above has code to free unmanaged resources. - // ~ProtoCompiler() { - // // Do not change this code. Put cleanup code in Dispose(bool disposing) above. - // Dispose(false); - // } + /// + /// Compiles the specified .proto message file asynchronously and saves the result at the specified output folder. + /// + /// .proto file to compile + /// + /// A list of compiled results. + /// + public async Task> CompileAsync(string inputFile) + { + return await new Task>(() => { return Compile(inputFile); }); + } + + /// + /// Gets the protobuf compiler CLI arguments (without input/output files!). + /// + /// + protected abstract String GetProtoArguments(); + + /// + /// Gets the protobuf compiler CLI file name (override when using a compiler other than the default 'protoc.exe'). + /// + /// + /// The compiler program must be located in the compilers folder. + /// + /// + protected virtual String GetProtoCompilerName() + { + return "protoc.exe"; + } - // This code added to correctly implement the disposable pattern. + /// + /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. + /// public void Dispose() { - // Do not change this code. Put cleanup code in Dispose(bool disposing) above. - Dispose(true); - // TODO: uncomment the following line if the finalizer is overridden above. - // GC.SuppressFinalize(this); + //TODO: Dispose... } - #endregion } } diff --git a/Software/Tango.NET/Tango.Protobuf/ProtoLanguage.cs b/Software/Tango.NET/Tango.Protobuf/ProtoLanguage.cs new file mode 100644 index 000000000..0a53a3c01 --- /dev/null +++ b/Software/Tango.NET/Tango.Protobuf/ProtoLanguage.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.Protobuf +{ + /// + /// Represents an enumeration for available protobuf compiler languages. + /// + public enum ProtoLanguage + { + [Description("C#")] + CSharp, + [Description("Java")] + Java, + [Description("Java Nano")] + JavaNano, + [Description("C++")] + CPP, + [Description("C")] + C, + [Description("Embedded C")] + EmbeddedC, + [Description("JavaScript")] + JS, + [Description("Python")] + Python, + [Description("PHP")] + PHP, + [Description("Ruby")] + Ruby, + } +} diff --git a/Software/Tango.NET/Tango.Protobuf/ProtoResult.cs b/Software/Tango.NET/Tango.Protobuf/ProtoResult.cs new file mode 100644 index 000000000..5b35f9b5a --- /dev/null +++ b/Software/Tango.NET/Tango.Protobuf/ProtoResult.cs @@ -0,0 +1,51 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.Protobuf +{ + /// + /// Represents a single protobuf compile result. + /// + public class ProtoResult + { + /// + /// Gets the compiled language. + /// + public ProtoLanguage Language { get; private set; } + + /// + /// Gets the name of the file. + /// + /// Gets the file content. + /// + public String Content { get; private set; } + + /// + /// Initializes a new instance of the class. + /// + /// Name of the file. + /// The content. + /// The language. + public ProtoResult(String fileName, String content, ProtoLanguage language) + { + FileName = fileName; + Content = content; + Language = language; + } + + /// + /// Saves the result to the specified folder. + /// + /// The folder. + public void Save(String folder) + { + + } + } +} diff --git a/Software/Tango.NET/Tango.Protobuf/Tango.Protobuf.csproj b/Software/Tango.NET/Tango.Protobuf/Tango.Protobuf.csproj index 87aa6bc31..80caa9c98 100644 --- a/Software/Tango.NET/Tango.Protobuf/Tango.Protobuf.csproj +++ b/Software/Tango.NET/Tango.Protobuf/Tango.Protobuf.csproj @@ -40,9 +40,12 @@ + + + @@ -58,5 +61,11 @@ PreserveNewest + + + {a34ee0f0-649d-41c8-8489-b6f1cc6924ee} + Tango.Core + + \ No newline at end of file diff --git a/Software/Tango.NET/Tango.sln b/Software/Tango.NET/Tango.sln index f6a1c1940..dbcaa7e2a 100644 --- a/Software/Tango.NET/Tango.sln +++ b/Software/Tango.NET/Tango.sln @@ -10,6 +10,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Versioning", "Versioning", Versioning\GlobalVersionInfo.cs = Versioning\GlobalVersionInfo.cs EndProjectSection EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tango.Core", "Tango.Core\Tango.Core.csproj", "{A34EE0F0-649D-41C8-8489-B6F1CC6924EE}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -20,6 +22,10 @@ Global {40073806-914E-4E78-97AB-FA9639308EBE}.Debug|Any CPU.Build.0 = Debug|Any CPU {40073806-914E-4E78-97AB-FA9639308EBE}.Release|Any CPU.ActiveCfg = Release|Any CPU {40073806-914E-4E78-97AB-FA9639308EBE}.Release|Any CPU.Build.0 = Release|Any CPU + {A34EE0F0-649D-41C8-8489-B6F1CC6924EE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A34EE0F0-649D-41C8-8489-B6F1CC6924EE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A34EE0F0-649D-41C8-8489-B6F1CC6924EE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A34EE0F0-649D-41C8-8489-B6F1CC6924EE}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE -- cgit v1.3.1