From 1db675d3ea7040baf64d8286c094e6ce2583b754 Mon Sep 17 00:00:00 2001 From: josetr <37419832+josetr@users.noreply.github.com> Date: Wed, 16 Mar 2022 20:02:30 +0000 Subject: [PATCH] Add option to load Driver options from a YAML config file --- Directory.Packages.props | 1 + src/AST/Module.cs | 18 ++--- src/Generator/Config/Cfg.cs | 13 ++++ src/Generator/Config/CfgLoader.cs | 93 +++++++++++++++++++++++++ src/Generator/CppSharp.Generator.csproj | 1 + src/Generator/Driver.cs | 7 ++ 6 files changed, 124 insertions(+), 9 deletions(-) create mode 100644 src/Generator/Config/Cfg.cs create mode 100644 src/Generator/Config/CfgLoader.cs diff --git a/Directory.Packages.props b/Directory.Packages.props index 0fc3db60..aa3042f4 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -4,5 +4,6 @@ + \ No newline at end of file diff --git a/src/AST/Module.cs b/src/AST/Module.cs index 7e2b9611..5e4dbc3b 100644 --- a/src/AST/Module.cs +++ b/src/AST/Module.cs @@ -5,17 +5,17 @@ namespace CppSharp.AST { public class Module { - public List IncludeDirs { get; } = new List(); - public List Headers { get; } = new List(); + public List IncludeDirs { get; set; } = new List(); + public List Headers { get; set; } = new List(); public List LibraryDirs { get; } = new List(); - public List Libraries { get; } = new List(); - public List Defines { get; } = new List(); - public List Undefines { get; } = new List(); + public List Libraries { get; set; } = new List(); + public List Defines { get; set; } = new List(); + public List Undefines { get; set; } = new List(); public string OutputNamespace { get; set; } - public List Units { get; } = new List(); - public List CodeFiles { get; } = new List(); - public List ReferencedAssemblies { get; } = new List(); - public List Dependencies { get; } = new List(); + public List Units { get; set; } = new List(); + public List CodeFiles { get; set; } = new List(); + public List ReferencedAssemblies { get; set; } = new List(); + public List Dependencies { get; set; } = new List(); [Obsolete("Use Module(string libraryName) instead.")] public Module() diff --git a/src/Generator/Config/Cfg.cs b/src/Generator/Config/Cfg.cs new file mode 100644 index 00000000..d509e33c --- /dev/null +++ b/src/Generator/Config/Cfg.cs @@ -0,0 +1,13 @@ +namespace CppSharp.Config +{ + using CppSharp.AST; + using CppSharp.Parser; + + internal class Cfg + { + public bool SetupMSVC { get; set; } + public ParserOptions ParserOptions { get; set; } + public Module Module { get; set; } + public DriverOptions Options { get; set; } + } +} \ No newline at end of file diff --git a/src/Generator/Config/CfgLoader.cs b/src/Generator/Config/CfgLoader.cs new file mode 100644 index 00000000..99663766 --- /dev/null +++ b/src/Generator/Config/CfgLoader.cs @@ -0,0 +1,93 @@ +namespace CppSharp.Config +{ + using CppSharp; + using System; + using System.Collections.Generic; + using System.IO; + using System.Text.RegularExpressions; + using YamlDotNet.Core; + using YamlDotNet.Core.Events; + using YamlDotNet.Serialization; + using YamlDotNet.Serialization.NamingConventions; + + internal static partial class CfgLoader + { + public static Cfg LoadConfig(string path, Driver driver) + { + var deserializer = new DeserializerBuilder() + .WithTypeConverter(new YamlTypeConverter()) + .WithNodeDeserializer(new NodeDeserializer()) + .WithNamingConvention(PascalCaseNamingConvention.Instance) + .Build(); + + var yaml = File.ReadAllText(path); + var config = deserializer.Deserialize(yaml); + + if (config.SetupMSVC) + config.ParserOptions.SetupMSVC(); + + driver.Options = config.Options; + driver.ParserOptions = config.ParserOptions; + return config; + } + + private class NodeDeserializer : INodeDeserializer + { + bool INodeDeserializer.Deserialize(IParser parser, Type expectedType, Func nestedObjectDeserializer, out object value) + { + if (expectedType != typeof(string) || !parser.TryConsume(out var scalar)) + { + value = null; + return false; + } + + var template = scalar.Value; + + value = Regex.Replace(template, @"\${(\w+)}", match => + { + var result = Environment.GetEnvironmentVariable(match.Groups[1].Value); + return result; + }); + + return true; + } + } + + private class YamlTypeConverter : IYamlTypeConverter + { + public bool Accepts(Type type) + { + if (type != typeof(List)) + return false; + return true; + } + + public object ReadYaml(IParser parser, Type type) + { + if (parser.Current.GetType() != typeof(SequenceStart)) + throw new InvalidDataException("Invalid YAML."); + + var list = new List(); + + parser.MoveNext(); + + do + { + if (parser.Current is not Scalar s) + throw new InvalidDataException("Invalid YAML."); + + list.AddRange(s.Value.Split(';')); + parser.MoveNext(); + } while (parser.Current.GetType() != typeof(SequenceEnd)); + + parser.MoveNext(); + return list; + } + + public void WriteYaml(IEmitter emitter, object value, Type type) + { + throw new NotImplementedException(); + } + } + } +} \ No newline at end of file diff --git a/src/Generator/CppSharp.Generator.csproj b/src/Generator/CppSharp.Generator.csproj index a96a8f78..db25456e 100644 --- a/src/Generator/CppSharp.Generator.csproj +++ b/src/Generator/CppSharp.Generator.csproj @@ -11,5 +11,6 @@ + \ No newline at end of file diff --git a/src/Generator/Driver.cs b/src/Generator/Driver.cs index 110dfefe..9d798ce5 100644 --- a/src/Generator/Driver.cs +++ b/src/Generator/Driver.cs @@ -13,6 +13,7 @@ using CppSharp.Parser; using CppSharp.Passes; using CppSharp.Utils; using CppSharp.Types; +using CppSharp.Config; namespace CppSharp { @@ -31,6 +32,12 @@ namespace CppSharp ParserOptions = new ParserOptions(); } + public void LoadConfig(string path) + { + var config = CfgLoader.LoadConfig(path, this); + Options.Modules.Add(config.Module); + } + Generator CreateGeneratorFromKind(GeneratorKind kind) { switch (kind)