Skip to content

Commit

Permalink
Enable users to instruct SharpGenTools to only generate code for a su…
Browse files Browse the repository at this point in the history
…bset of platforms (enables users who are wrapping a platform-specific library to only generate code for the platforms they support)
  • Loading branch information
jkoritzinsky committed May 17, 2019
1 parent d6cf323 commit b9bb6da
Show file tree
Hide file tree
Showing 14 changed files with 72 additions and 15 deletions.
2 changes: 1 addition & 1 deletion SharpGen.Interactive/CodeGenApp.cs
Expand Up @@ -457,7 +457,7 @@ private HashSet<ConfigFile> GenerateHeaders(IReadOnlyCollection<string> 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
Expand Down
1 change: 1 addition & 0 deletions SharpGen/Generator/CallableCodeGenerator.cs
Expand Up @@ -129,6 +129,7 @@ public override IEnumerable<MemberDeclarationSyntax> GenerateCode(CsCallable csE

var callStmt = GeneratorHelpers.GetPlatformSpecificStatements(
globalNamespace,
Generators.Config,
csElement.InteropSignatures.Keys,
(platform) =>
ExpressionStatement(
Expand Down
4 changes: 4 additions & 0 deletions SharpGen/Generator/DefaultGenerators.cs
Expand Up @@ -14,6 +14,7 @@ class DefaultGenerators : IGeneratorRegistry
GlobalNamespaceProvider globalNamespace,
IDocumentationLinker documentation,
ExternalDocCommentsReader docReader,
GeneratorConfig config,
Logger logger)
{
Constant = new ConstantCodeGenerator();
Expand All @@ -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<CsVariable, MemberDeclarationSyntax> Constant { get; }
Expand Down Expand Up @@ -65,5 +67,7 @@ class DefaultGenerators : IGeneratorRegistry
public IMultiCodeGenerator<(CsCallable, InteropMethodSignature), StatementSyntax> ReverseCallableProlog { get; }

public MarshallingRegistry Marshalling { get; }

public GeneratorConfig Config { get; }
}
}
12 changes: 12 additions & 0 deletions 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; }
}
}
19 changes: 13 additions & 6 deletions SharpGen/Generator/GeneratorHelpers.cs
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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)
{
Expand All @@ -57,18 +62,20 @@ public static string GetPlatformSpecificSuffix(PlatformDetectionType platform)
return str.ToString();
}

public static StatementSyntax GetPlatformSpecificStatements(GlobalNamespaceProvider globalNamespace, IEnumerable<PlatformDetectionType> types, Func<PlatformDetectionType, StatementSyntax> syntaxBuilder)
public static StatementSyntax GetPlatformSpecificStatements(GlobalNamespaceProvider globalNamespace, GeneratorConfig config, IEnumerable<PlatformDetectionType> types, Func<PlatformDetectionType, StatementSyntax> syntaxBuilder)
{
List<IfStatementSyntax> ifStatements = new List<IfStatementSyntax>();

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);
}

Expand Down
1 change: 1 addition & 0 deletions SharpGen/Generator/IGeneratorRegistry.cs
Expand Up @@ -29,5 +29,6 @@ public interface IGeneratorRegistry

IMultiCodeGenerator<InteropMethodSignature, MemberDeclarationSyntax> InteropMethod { get; }
MarshallingRegistry Marshalling { get; }
GeneratorConfig Config { get; }
}
}
4 changes: 2 additions & 2 deletions SharpGen/Generator/RoslynGenerator.cs
Expand Up @@ -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; }
Expand Down
2 changes: 1 addition & 1 deletion SharpGen/Generator/ShadowCallbackGenerator.cs
Expand Up @@ -22,7 +22,7 @@ public ShadowCallbackGenerator(IGeneratorRegistry generators, GlobalNamespacePro

public IEnumerable<MemberDeclarationSyntax> 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);
Expand Down
2 changes: 1 addition & 1 deletion SharpGen/Generator/VtblGenerator.cs
Expand Up @@ -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(
Expand Down
2 changes: 2 additions & 0 deletions SharpGen/Logging/LoggingCodes.cs
Expand Up @@ -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";
Expand Down
4 changes: 2 additions & 2 deletions SharpGen/Model/PlatformDetectionType.cs
Expand Up @@ -7,8 +7,8 @@ namespace SharpGen.Model
[Flags]
public enum PlatformDetectionType
{
Any = 0,
IsWindows = 0b000001,
IsSystemV = 0b000010
IsSystemV = 0b000010,
Any = IsWindows | IsSystemV
}
}
2 changes: 1 addition & 1 deletion SharpGen/Transform/InteropSignatureTransform.cs
Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions SharpGenTools.Sdk/SharpGenTools.Sdk.targets
Expand Up @@ -263,6 +263,7 @@
GlobalNamespaceOverrides="@(SharpGenGlobalNamespaceOverrides)"
DocLinkCache="@(DocLinksCache)"
ExternalDocumentation="@(SharpGenExternalDocs)"
Platforms="@(SharpGenPlatforms)"
/>
</Target>

Expand Down
31 changes: 30 additions & 1 deletion SharpGenTools.Sdk/Tasks/GenerateCSharp.cs
Expand Up @@ -11,6 +11,7 @@
using System.IO;
using SharpGen.Transform;
using System.Linq;
using SharpGen.Logging;

namespace SharpGenTools.Sdk.Tasks
{
Expand All @@ -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; }
Expand Down Expand Up @@ -63,11 +66,37 @@ public override bool Execute()
}
}

PlatformDetectionType platformMask = 0;

foreach (var platform in Platforms ?? Enumerable.Empty<ITaskItem>())
{
if (!Enum.TryParse<PlatformDetectionType>("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);

Expand Down

0 comments on commit b9bb6da

Please sign in to comment.