Browse Source

IT'S ALIVE

pull/4971/head
Nikita Tsukanov 6 years ago
parent
commit
8de6823e5d
  1. 2
      packages/Avalonia/AvaloniaBuildTasks.targets
  2. 3
      src/Avalonia.Build.Tasks/CompileAvaloniaXamlTask.cs
  3. 57
      src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.cs
  4. 14
      src/Avalonia.MicroCom/Avalonia.MicroCom.csproj
  5. 3
      src/Avalonia.MicroCom/MicroComRuntime.cs
  6. 1
      src/Avalonia.MicroCom/MicroComVtblBase.cs
  7. 8
      src/Avalonia.Native/Avalonia.Native.csproj
  8. 13
      src/tools/MicroComGenerator/CSharpGen.InterfaceGen.cs

2
packages/Avalonia/AvaloniaBuildTasks.targets

@ -4,6 +4,7 @@
<_AvaloniaUseExternalMSBuild Condition="'$(_AvaloniaForceInternalMSBuild)' == 'true'">false</_AvaloniaUseExternalMSBuild> <_AvaloniaUseExternalMSBuild Condition="'$(_AvaloniaForceInternalMSBuild)' == 'true'">false</_AvaloniaUseExternalMSBuild>
<AvaloniaXamlReportImportance Condition="'$(AvaloniaXamlReportImportance)' == ''">low</AvaloniaXamlReportImportance> <AvaloniaXamlReportImportance Condition="'$(AvaloniaXamlReportImportance)' == ''">low</AvaloniaXamlReportImportance>
<_AvaloniaPatchComInterop Condition="'$(_AvaloniaPatchComInterop)' == ''">false</_AvaloniaPatchComInterop> <_AvaloniaPatchComInterop Condition="'$(_AvaloniaPatchComInterop)' == ''">false</_AvaloniaPatchComInterop>
<_AvaloniaSkipXamlCompilation Condition="'$(_AvaloniaSkipXamlCompilation)' == ''">false</_AvaloniaSkipXamlCompilation>
</PropertyGroup> </PropertyGroup>
<!-- Unfortunately we have to update default items in .targets since custom nuget props are improted before Microsoft.NET.Sdk.DefaultItems.props --> <!-- Unfortunately we have to update default items in .targets since custom nuget props are improted before Microsoft.NET.Sdk.DefaultItems.props -->
@ -92,6 +93,7 @@
SignAssembly="$(SignAssembly)" SignAssembly="$(SignAssembly)"
DelaySign="$(DelaySign)" DelaySign="$(DelaySign)"
EnableComInteropPatching="$(_AvaloniaPatchComInterop)" EnableComInteropPatching="$(_AvaloniaPatchComInterop)"
SkipXamlCompilation="$(_AvaloniaSkipXamlCompilation)"
/> />
<Exec <Exec
Condition="'$(_AvaloniaUseExternalMSBuild)' == 'true'" Condition="'$(_AvaloniaUseExternalMSBuild)' == 'true'"

3
src/Avalonia.Build.Tasks/CompileAvaloniaXamlTask.cs

@ -41,7 +41,7 @@ namespace Avalonia.Build.Tasks
File.ReadAllLines(ReferencesFilePath).Where(l => !string.IsNullOrWhiteSpace(l)).ToArray(), File.ReadAllLines(ReferencesFilePath).Where(l => !string.IsNullOrWhiteSpace(l)).ToArray(),
ProjectDirectory, OutputPath, VerifyIl, outputImportance, ProjectDirectory, OutputPath, VerifyIl, outputImportance,
(SignAssembly && !DelaySign) ? AssemblyOriginatorKeyFile : null, (SignAssembly && !DelaySign) ? AssemblyOriginatorKeyFile : null,
EnableComInteropPatching); EnableComInteropPatching, SkipXamlCompilation);
if (!res.Success) if (!res.Success)
return false; return false;
if (!res.WrittenFile) if (!res.WrittenFile)
@ -77,6 +77,7 @@ namespace Avalonia.Build.Tasks
public bool VerifyIl { get; set; } public bool VerifyIl { get; set; }
public bool EnableComInteropPatching { get; set; } public bool EnableComInteropPatching { get; set; }
public bool SkipXamlCompilation { get; set; }
public string AssemblyOriginatorKeyFile { get; set; } public string AssemblyOriginatorKeyFile { get; set; }
public bool SignAssembly { get; set; } public bool SignAssembly { get; set; }

57
src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.cs

@ -40,17 +40,48 @@ namespace Avalonia.Build.Tasks
WrittenFile = writtenFile; WrittenFile = writtenFile;
} }
} }
public static CompileResult Compile(IBuildEngine engine, string input, string[] references,
string projectDirectory,
string output, bool verifyIl, MessageImportance logImportance, string strongNameKey, bool patchCom,
bool skipXamlCompilation)
{
var typeSystem = new CecilTypeSystem(references.Concat(new[] { input }), input);
var asm = typeSystem.TargetAssemblyDefinition;
if (!skipXamlCompilation)
{
var compileRes = CompileCore(engine, typeSystem, projectDirectory, verifyIl, logImportance);
if (compileRes == null && !patchCom)
return new CompileResult(true);
if (compileRes == false)
return new CompileResult(false);
}
if (patchCom)
ComInteropHelper.PatchAssembly(asm, typeSystem);
var writerParameters = new WriterParameters { WriteSymbols = asm.MainModule.HasSymbols };
if (!string.IsNullOrWhiteSpace(strongNameKey))
writerParameters.StrongNameKeyBlob = File.ReadAllBytes(strongNameKey);
asm.Write(output, writerParameters);
return new CompileResult(true, true);
}
public static CompileResult Compile(IBuildEngine engine, string input, string[] references, string projectDirectory, static bool? CompileCore(IBuildEngine engine, CecilTypeSystem typeSystem,
string output, bool verifyIl, MessageImportance logImportance, string strongNameKey, bool patchCom) string projectDirectory, bool verifyIl,
MessageImportance logImportance)
{ {
var typeSystem = new CecilTypeSystem(references.Concat(new[] {input}), input);
var asm = typeSystem.TargetAssemblyDefinition; var asm = typeSystem.TargetAssemblyDefinition;
var emres = new EmbeddedResources(asm); var emres = new EmbeddedResources(asm);
var avares = new AvaloniaResources(asm, projectDirectory); var avares = new AvaloniaResources(asm, projectDirectory);
if (avares.Resources.Count(CheckXamlName) == 0 && emres.Resources.Count(CheckXamlName) == 0 && !patchCom) if (avares.Resources.Count(CheckXamlName) == 0 && emres.Resources.Count(CheckXamlName) == 0)
// Nothing to do // Nothing to do
return new CompileResult(true); return null;
var clrPropertiesDef = new TypeDefinition("CompiledAvaloniaXaml", "XamlIlHelpers", var clrPropertiesDef = new TypeDefinition("CompiledAvaloniaXaml", "XamlIlHelpers",
TypeAttributes.Class, asm.MainModule.TypeSystem.Object); TypeAttributes.Class, asm.MainModule.TypeSystem.Object);
@ -364,27 +395,17 @@ namespace Avalonia.Build.Tasks
if (emres.Resources.Count(CheckXamlName) != 0) if (emres.Resources.Count(CheckXamlName) != 0)
if (!CompileGroup(emres)) if (!CompileGroup(emres))
return new CompileResult(false); return false;
if (avares.Resources.Count(CheckXamlName) != 0) if (avares.Resources.Count(CheckXamlName) != 0)
{ {
if (!CompileGroup(avares)) if (!CompileGroup(avares))
return new CompileResult(false); return false;
avares.Save(); avares.Save();
} }
loaderDispatcherMethod.Body.Instructions.Add(Instruction.Create(OpCodes.Ldnull)); loaderDispatcherMethod.Body.Instructions.Add(Instruction.Create(OpCodes.Ldnull));
loaderDispatcherMethod.Body.Instructions.Add(Instruction.Create(OpCodes.Ret)); loaderDispatcherMethod.Body.Instructions.Add(Instruction.Create(OpCodes.Ret));
return true;
if (patchCom)
ComInteropHelper.PatchAssembly(asm, typeSystem);
var writerParameters = new WriterParameters { WriteSymbols = asm.MainModule.HasSymbols };
if (!string.IsNullOrWhiteSpace(strongNameKey))
writerParameters.StrongNameKeyBlob = File.ReadAllBytes(strongNameKey);
asm.Write(output, writerParameters);
return new CompileResult(true, true);
} }
} }

14
src/Avalonia.MicroCom/Avalonia.MicroCom.csproj

@ -1,8 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<PropertyGroup> <TargetFramework>netstandard2.0</TargetFramework>
<TargetFramework>netstandard2.0</TargetFramework> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> </PropertyGroup>
</PropertyGroup> <PropertyGroup>
<_AvaloniaPatchComInterop>true</_AvaloniaPatchComInterop>
</PropertyGroup>
<Import Project="..\..\build\BuildTargets.targets" />
</Project> </Project>

3
src/Avalonia.MicroCom/MicroComRuntime.cs

@ -41,6 +41,8 @@ namespace Avalonia.MicroCom
public static void* GetNativePointer<T>(T obj, bool owned = false) where T : IUnknown public static void* GetNativePointer<T>(T obj, bool owned = false) where T : IUnknown
{ {
if (obj == null)
return null;
if (obj is MicroComProxyBase proxy) if (obj is MicroComProxyBase proxy)
return (void*)proxy.NativePointer; return (void*)proxy.NativePointer;
if (obj is IMicroComShadowContainer container) if (obj is IMicroComShadowContainer container)
@ -55,6 +57,7 @@ namespace Avalonia.MicroCom
res); res);
if (owned) if (owned)
container.Shadow.AddRef((Ccw*)ptr); container.Shadow.AddRef((Ccw*)ptr);
return ptr;
} }
throw new ArgumentException("Unable to get a native pointer for " + obj); throw new ArgumentException("Unable to get a native pointer for " + obj);
} }

1
src/Avalonia.MicroCom/MicroComVtblBase.cs

@ -18,6 +18,7 @@ namespace Avalonia.MicroCom
{ {
AddMethod((QueryInterfaceDelegate)QueryInterface); AddMethod((QueryInterfaceDelegate)QueryInterface);
AddMethod((AddRefDelegate)AddRef); AddMethod((AddRefDelegate)AddRef);
AddMethod((AddRefDelegate)Release);
} }
protected void AddMethod(Delegate d) protected void AddMethod(Delegate d)

8
src/Avalonia.Native/Avalonia.Native.csproj

@ -37,7 +37,7 @@
<Target Name="GenerateAvaloniaNativeComInterop" <Target Name="GenerateAvaloniaNativeComInterop"
BeforeTargets="CoreCompile" BeforeTargets="CoreCompile"
DependsOnTargets="ResolveReferences" DependsOnTargets="ResolveReferences"
Inputs="avn.idl" Inputs="avn.idl;$(MSBuildThisFileDirectory)/../tools/MicroComGenerator/**/*.cs"
Outputs="Interop.Generated.cs"> Outputs="Interop.Generated.cs">
<Message Importance="high" Text="Generating Interop.Generated.cs" /> <Message Importance="high" Text="Generating Interop.Generated.cs" />
<Exec Command="dotnet ../tools/MicroComGenerator/bin/$(Configuration)/netcoreapp3.1/MicroComGenerator.dll -i avn.idl --cs Interop.Generated.cs" LogStandardErrorAsError="true" /> <Exec Command="dotnet ../tools/MicroComGenerator/bin/$(Configuration)/netcoreapp3.1/MicroComGenerator.dll -i avn.idl --cs Interop.Generated.cs" LogStandardErrorAsError="true" />
@ -47,8 +47,12 @@
<Compile Include="Interop.Generated.cs"/> <Compile Include="Interop.Generated.cs"/>
</ItemGroup> </ItemGroup>
</Target> </Target>
<ItemGroup>
<UpToDateCheckInput Include="avn.idl"/>
<UpToDateCheckInput Include="$(MSBuildThisFileDirectory)/../tools/MicroComGenerator/**/*.cs"/>
</ItemGroup>
<PropertyGroup> <PropertyGroup>
<_AvaloniaPatchComInterop>true</_AvaloniaPatchComInterop> <_AvaloniaPatchComInterop>true</_AvaloniaPatchComInterop>
</PropertyGroup> </PropertyGroup>
<Import Project="..\..\build\BuildTargets.targets" /> <Import Project="..\..\build\BuildTargets.targets" />
</Project> </Project>

13
src/tools/MicroComGenerator/CSharpGen.InterfaceGen.cs

@ -135,7 +135,7 @@ namespace MicroComGenerator
public override void PreMarshal(List<StatementSyntax> body) public override void PreMarshal(List<StatementSyntax> body)
{ {
body.Add(ParseStatement($"var {BName} = new byte[System.Text.Encoding.UTF8.GetByteCount({Name})+1];")); body.Add(ParseStatement($"var {BName} = new byte[System.Text.Encoding.UTF8.GetByteCount({Name})+1];"));
body.Add(ParseStatement($"System.Text.Encoding.UTF8.GetBytes({Name}, 0, {Name.Length}, {BName}, 0);")); body.Add(ParseStatement($"System.Text.Encoding.UTF8.GetBytes({Name}, 0, {Name}.Length, {BName}, 0);"));
} }
public override StatementSyntax CreateFixed(StatementSyntax inner) public override StatementSyntax CreateFixed(StatementSyntax inner)
@ -238,8 +238,11 @@ namespace MicroComGenerator
.AddArgumentListArguments(Argument(ParseExpression("PPV"))) .AddArgumentListArguments(Argument(ParseExpression("PPV")))
.AddArgumentListArguments(args .AddArgumentListArguments(args
.Select((a, i) => Argument(a.Value(isHresultLastArgumentReturn && i == args.Count - 1))).ToArray()) .Select((a, i) => Argument(a.Value(isHresultLastArgumentReturn && i == args.Count - 1))).ToArray())
.AddArgumentListArguments(Argument(ParseExpression("PPV[base.VTableSize + " + num + "]"))); .AddArgumentListArguments(Argument(ParseExpression("(*PPV)[base.VTableSize + " + num + "]")));
if (!isVoidReturn)
callExpr = CastExpression(ParseTypeName(returnArg.NativeType), callExpr);
// Save call result if needed // Save call result if needed
if (!isVoidReturn) if (!isVoidReturn)
callExpr = AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, ParseExpression("__result"), callExpr = AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, ParseExpression("__result"),
@ -369,6 +372,10 @@ namespace MicroComGenerator
public ExpressionSyntax GetCaller(string returnType, List<string> args) public ExpressionSyntax GetCaller(string returnType, List<string> args)
{ {
string ConvertType(string t) => t.EndsWith("*") ? "void*" : t;
returnType = ConvertType(returnType);
args = args.Select(ConvertType).ToList();
var name = "CalliStdCall" + returnType.Replace("*", "_ptr"); var name = "CalliStdCall" + returnType.Replace("*", "_ptr");
var signature = returnType + "::" + name + "::" + string.Join("::", args); var signature = returnType + "::" + name + "::" + string.Join("::", args);
if (_existing.Add(signature)) if (_existing.Add(signature))
@ -427,7 +434,7 @@ namespace MicroComGenerator
.AddModifiers(Token(SyntaxKind.StaticKeyword), Token(SyntaxKind.InternalKeyword)) .AddModifiers(Token(SyntaxKind.StaticKeyword), Token(SyntaxKind.InternalKeyword))
.WithExpressionBody(ArrowExpressionClause( .WithExpressionBody(ArrowExpressionClause(
ParseExpression("Avalonia.MicroCom.MicroComRuntime.RegisterVTable(typeof(" + ParseExpression("Avalonia.MicroCom.MicroComRuntime.RegisterVTable(typeof(" +
proxyClassName + "), new " + vtbl.Identifier.Text + "().CreateVTable())"))) iface.Name + "), new " + vtbl.Identifier.Text + "().CreateVTable())")))
.WithSemicolonToken(Semicolon())); .WithSemicolonToken(Semicolon()));

Loading…
Cancel
Save