From b9bb6da75453e1fb2c78648a53a741951c048301 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Fri, 17 May 2019 16:36:19 -0700 Subject: [PATCH] Enable users to instruct SharpGenTools to only generate code for a subset of platforms (enables users who are wrapping a platform-specific library to only generate code for the platforms they support) --- SharpGen.Interactive/CodeGenApp.cs | 2 +- SharpGen/Generator/CallableCodeGenerator.cs | 1 + SharpGen/Generator/DefaultGenerators.cs | 4 +++ SharpGen/Generator/GeneratorConfig.cs | 12 +++++++ SharpGen/Generator/GeneratorHelpers.cs | 19 ++++++++---- SharpGen/Generator/IGeneratorRegistry.cs | 1 + SharpGen/Generator/RoslynGenerator.cs | 4 +-- SharpGen/Generator/ShadowCallbackGenerator.cs | 2 +- SharpGen/Generator/VtblGenerator.cs | 2 +- SharpGen/Logging/LoggingCodes.cs | 2 ++ SharpGen/Model/PlatformDetectionType.cs | 4 +-- .../Transform/InteropSignatureTransform.cs | 2 +- SharpGenTools.Sdk/SharpGenTools.Sdk.targets | 1 + SharpGenTools.Sdk/Tasks/GenerateCSharp.cs | 31 ++++++++++++++++++- 14 files changed, 72 insertions(+), 15 deletions(-) create mode 100644 SharpGen/Generator/GeneratorConfig.cs diff --git a/SharpGen.Interactive/CodeGenApp.cs b/SharpGen.Interactive/CodeGenApp.cs index 206838c1..26935ebb 100644 --- a/SharpGen.Interactive/CodeGenApp.cs +++ b/SharpGen.Interactive/CodeGenApp.cs @@ -457,7 +457,7 @@ private HashSet GenerateHeaders(IReadOnlyCollection filesWit private void GenerateCode(IDocumentationLinker docAggregator, CsAssembly asm, ExternalDocCommentsReader docCommentsReader) { - var generator = new RoslynGenerator(Logger, GlobalNamespace, docAggregator, docCommentsReader); + var generator = new RoslynGenerator(Logger, GlobalNamespace, docAggregator, docCommentsReader, new GeneratorConfig { Platforms = PlatformDetectionType.Any }); generator.Run(asm, _generatedPath, GeneratedCodeFolder); // Update check files for all assemblies diff --git a/SharpGen/Generator/CallableCodeGenerator.cs b/SharpGen/Generator/CallableCodeGenerator.cs index 2f49055e..32f6a347 100644 --- a/SharpGen/Generator/CallableCodeGenerator.cs +++ b/SharpGen/Generator/CallableCodeGenerator.cs @@ -129,6 +129,7 @@ public override IEnumerable GenerateCode(CsCallable csE var callStmt = GeneratorHelpers.GetPlatformSpecificStatements( globalNamespace, + Generators.Config, csElement.InteropSignatures.Keys, (platform) => ExpressionStatement( diff --git a/SharpGen/Generator/DefaultGenerators.cs b/SharpGen/Generator/DefaultGenerators.cs index e204d2c6..08e02b82 100644 --- a/SharpGen/Generator/DefaultGenerators.cs +++ b/SharpGen/Generator/DefaultGenerators.cs @@ -14,6 +14,7 @@ class DefaultGenerators : IGeneratorRegistry GlobalNamespaceProvider globalNamespace, IDocumentationLinker documentation, ExternalDocCommentsReader docReader, + GeneratorConfig config, Logger logger) { Constant = new ConstantCodeGenerator(); @@ -36,6 +37,7 @@ class DefaultGenerators : IGeneratorRegistry Vtbl = new VtblGenerator(this, globalNamespace); Shadow = new ShadowGenerator(this, globalNamespace); Marshalling = new MarshallingRegistry(globalNamespace, logger); + Config = config; } public IMultiCodeGenerator Constant { get; } @@ -65,5 +67,7 @@ class DefaultGenerators : IGeneratorRegistry public IMultiCodeGenerator<(CsCallable, InteropMethodSignature), StatementSyntax> ReverseCallableProlog { get; } public MarshallingRegistry Marshalling { get; } + + public GeneratorConfig Config { get; } } } diff --git a/SharpGen/Generator/GeneratorConfig.cs b/SharpGen/Generator/GeneratorConfig.cs new file mode 100644 index 00000000..c3f21dc4 --- /dev/null +++ b/SharpGen/Generator/GeneratorConfig.cs @@ -0,0 +1,12 @@ +using SharpGen.Model; +using System; +using System.Collections.Generic; +using System.Text; + +namespace SharpGen.Generator +{ + public class GeneratorConfig + { + public PlatformDetectionType Platforms { get; set; } + } +} diff --git a/SharpGen/Generator/GeneratorHelpers.cs b/SharpGen/Generator/GeneratorHelpers.cs index c6d86eff..958451ea 100644 --- a/SharpGen/Generator/GeneratorHelpers.cs +++ b/SharpGen/Generator/GeneratorHelpers.cs @@ -11,9 +11,9 @@ internal static class GeneratorHelpers { private static readonly PlatformDetectionType[] platforms = (PlatformDetectionType[])Enum.GetValues(typeof(PlatformDetectionType)); - private static StatementSyntax PlatformSpecificStatement(GlobalNamespaceProvider globalNamespace, PlatformDetectionType platform, StatementSyntax statement) + private static StatementSyntax PlatformSpecificStatement(GlobalNamespaceProvider globalNamespace, PlatformDetectionType allPlatformBitmap, PlatformDetectionType platform, StatementSyntax statement) { - if (platform == PlatformDetectionType.Any) + if ((platform & allPlatformBitmap) == allPlatformBitmap) { return statement; } @@ -45,6 +45,11 @@ private static StatementSyntax PlatformSpecificStatement(GlobalNamespaceProvider public static string GetPlatformSpecificSuffix(PlatformDetectionType platform) { + if (platform == PlatformDetectionType.Any) + { + return "_"; + } + StringBuilder str = new StringBuilder("_"); foreach (PlatformDetectionType flag in platforms) { @@ -57,18 +62,20 @@ public static string GetPlatformSpecificSuffix(PlatformDetectionType platform) return str.ToString(); } - public static StatementSyntax GetPlatformSpecificStatements(GlobalNamespaceProvider globalNamespace, IEnumerable types, Func syntaxBuilder) + public static StatementSyntax GetPlatformSpecificStatements(GlobalNamespaceProvider globalNamespace, GeneratorConfig config, IEnumerable types, Func syntaxBuilder) { List ifStatements = new List(); + var allPlatformBitmap = config.Platforms; + foreach (var platform in types) { - if (platform == PlatformDetectionType.Any) + if ((platform & allPlatformBitmap) == allPlatformBitmap) { - return PlatformSpecificStatement(globalNamespace, platform, syntaxBuilder(platform)); + return PlatformSpecificStatement(globalNamespace, allPlatformBitmap, platform, syntaxBuilder(platform)); } - IfStatementSyntax statement = (IfStatementSyntax)PlatformSpecificStatement(globalNamespace, platform, syntaxBuilder(platform)); + IfStatementSyntax statement = (IfStatementSyntax)PlatformSpecificStatement(globalNamespace, allPlatformBitmap, platform, syntaxBuilder(platform)); ifStatements.Add(statement); } diff --git a/SharpGen/Generator/IGeneratorRegistry.cs b/SharpGen/Generator/IGeneratorRegistry.cs index 70c16f92..0393ddd9 100644 --- a/SharpGen/Generator/IGeneratorRegistry.cs +++ b/SharpGen/Generator/IGeneratorRegistry.cs @@ -29,5 +29,6 @@ public interface IGeneratorRegistry IMultiCodeGenerator InteropMethod { get; } MarshallingRegistry Marshalling { get; } + GeneratorConfig Config { get; } } } diff --git a/SharpGen/Generator/RoslynGenerator.cs b/SharpGen/Generator/RoslynGenerator.cs index 66baa38f..eeedeb61 100644 --- a/SharpGen/Generator/RoslynGenerator.cs +++ b/SharpGen/Generator/RoslynGenerator.cs @@ -17,10 +17,10 @@ public class RoslynGenerator { public IGeneratorRegistry Generators { get; } - public RoslynGenerator(Logger logger, GlobalNamespaceProvider globalNamespace, IDocumentationLinker documentation, ExternalDocCommentsReader docReader) + public RoslynGenerator(Logger logger, GlobalNamespaceProvider globalNamespace, IDocumentationLinker documentation, ExternalDocCommentsReader docReader, GeneratorConfig config) { Logger = logger; - Generators = new DefaultGenerators(globalNamespace, documentation, docReader, logger); + Generators = new DefaultGenerators(globalNamespace, documentation, docReader, config, logger); } public Logger Logger { get; } diff --git a/SharpGen/Generator/ShadowCallbackGenerator.cs b/SharpGen/Generator/ShadowCallbackGenerator.cs index 0c535054..ae0a01a8 100644 --- a/SharpGen/Generator/ShadowCallbackGenerator.cs +++ b/SharpGen/Generator/ShadowCallbackGenerator.cs @@ -22,7 +22,7 @@ public ShadowCallbackGenerator(IGeneratorRegistry generators, GlobalNamespacePro public IEnumerable GenerateCode(CsCallable csElement) { - foreach (var sig in csElement.InteropSignatures) + foreach (var sig in csElement.InteropSignatures.Where(sig => (sig.Key & generators.Config.Platforms) != 0)) { yield return GenerateDelegateDeclaration(csElement, sig.Key, sig.Value); yield return GenerateShadowCallback(csElement, sig.Key, sig.Value); diff --git a/SharpGen/Generator/VtblGenerator.cs b/SharpGen/Generator/VtblGenerator.cs index a2cd2942..37b4e5d3 100644 --- a/SharpGen/Generator/VtblGenerator.cs +++ b/SharpGen/Generator/VtblGenerator.cs @@ -68,7 +68,7 @@ public MemberDeclarationSyntax GenerateCode(CsInterface csElement) .WithBody( Block(csElement.Methods .OrderBy(method => method.Offset) - .Select(method => GeneratorHelpers.GetPlatformSpecificStatements(globalNamespace, method.InteropSignatures.Keys, + .Select(method => GeneratorHelpers.GetPlatformSpecificStatements(globalNamespace, generators.Config, method.InteropSignatures.Keys, platform => ExpressionStatement( InvocationExpression( diff --git a/SharpGen/Logging/LoggingCodes.cs b/SharpGen/Logging/LoggingCodes.cs index 80bda485..ad963e18 100644 --- a/SharpGen/Logging/LoggingCodes.cs +++ b/SharpGen/Logging/LoggingCodes.cs @@ -48,6 +48,8 @@ public static class LoggingCodes public const string InvalidRelationInScenario = "SG0022"; + public const string InvalidPlatformDetectionType = "SG0023"; + public const string CastXmlError = "CX0001"; public const string CastXmlWarning = "CX0002"; diff --git a/SharpGen/Model/PlatformDetectionType.cs b/SharpGen/Model/PlatformDetectionType.cs index 66349895..4e518b43 100644 --- a/SharpGen/Model/PlatformDetectionType.cs +++ b/SharpGen/Model/PlatformDetectionType.cs @@ -7,8 +7,8 @@ namespace SharpGen.Model [Flags] public enum PlatformDetectionType { - Any = 0, IsWindows = 0b000001, - IsSystemV = 0b000010 + IsSystemV = 0b000010, + Any = IsWindows | IsSystemV } } diff --git a/SharpGen/Transform/InteropSignatureTransform.cs b/SharpGen/Transform/InteropSignatureTransform.cs index ba135012..1b21fa7a 100644 --- a/SharpGen/Transform/InteropSignatureTransform.cs +++ b/SharpGen/Transform/InteropSignatureTransform.cs @@ -123,7 +123,7 @@ private void InitCalliSignatureParameters(CsCallable callable, InteropMethodSign private void InitSignatureWithReturnType(CsCallable callable, InteropMethodSignature cSharpInteropCalliSignature, PlatformDetectionType platform) { - Debug.Assert((platform & (PlatformDetectionType.IsWindows | PlatformDetectionType.IsSystemV)) != (PlatformDetectionType.IsWindows | PlatformDetectionType.IsSystemV)); + Debug.Assert((platform & (PlatformDetectionType.IsWindows | PlatformDetectionType.IsSystemV)) != (PlatformDetectionType.IsWindows | PlatformDetectionType.IsSystemV) || !callable.IsReturnStructLarge); var platformSpecificReturnTypeOverrides = (platform & PlatformDetectionType.IsWindows) != 0 ? windowsOnlyReturnTypeOverrides : systemvOnlyReturnTypeOverrides; diff --git a/SharpGenTools.Sdk/SharpGenTools.Sdk.targets b/SharpGenTools.Sdk/SharpGenTools.Sdk.targets index 3493619e..d52a1f6a 100644 --- a/SharpGenTools.Sdk/SharpGenTools.Sdk.targets +++ b/SharpGenTools.Sdk/SharpGenTools.Sdk.targets @@ -263,6 +263,7 @@ GlobalNamespaceOverrides="@(SharpGenGlobalNamespaceOverrides)" DocLinkCache="@(DocLinksCache)" ExternalDocumentation="@(SharpGenExternalDocs)" + Platforms="@(SharpGenPlatforms)" /> diff --git a/SharpGenTools.Sdk/Tasks/GenerateCSharp.cs b/SharpGenTools.Sdk/Tasks/GenerateCSharp.cs index 478a7c30..80ce4fb9 100644 --- a/SharpGenTools.Sdk/Tasks/GenerateCSharp.cs +++ b/SharpGenTools.Sdk/Tasks/GenerateCSharp.cs @@ -11,6 +11,7 @@ using System.IO; using SharpGen.Transform; using System.Linq; +using SharpGen.Logging; namespace SharpGenTools.Sdk.Tasks { @@ -33,6 +34,8 @@ public class GenerateCSharp : Task [Required] public string GlobalNamespace { get; set; } + public ITaskItem[] Platforms { get; set; } + public ITaskItem[] GlobalNamespaceOverrides { get; set; } public ITaskItem[] ExternalDocumentation { get; set; } @@ -63,11 +66,37 @@ public override bool Execute() } } + PlatformDetectionType platformMask = 0; + + foreach (var platform in Platforms ?? Enumerable.Empty()) + { + if (!Enum.TryParse("Is" + platform.ItemSpec, out var parsedPlatform)) + { + Log.LogWarning(null, LoggingCodes.InvalidPlatformDetectionType, null, null, 0, 0, 0, 0, $"The platform type {platform} is an unknown platform to SharpGenTools. Falling back to Any platform detection."); + platformMask = PlatformDetectionType.Any; + } + else + { + platformMask |= parsedPlatform; + } + } + + if (platformMask == 0) + { + platformMask = PlatformDetectionType.Any; + } + + var config = new GeneratorConfig + { + Platforms = platformMask + }; + var generator = new RoslynGenerator( new Logger(new MsBuildSharpGenLogger(Log), null), globalNamespace, new CachedDocumentationLinker(DocLinkCache.ItemSpec), - new ExternalDocCommentsReader(documentationFiles)); + new ExternalDocCommentsReader(documentationFiles), + config); generator.Run(CsAssembly.Read(Model.ItemSpec), OutputDirectory, GeneratedCodeFolder);