Browse Source

IT'S ALIVE

pull/4971/head
Nikita Tsukanov 5 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>
<AvaloniaXamlReportImportance Condition="'$(AvaloniaXamlReportImportance)' == ''">low</AvaloniaXamlReportImportance>
<_AvaloniaPatchComInterop Condition="'$(_AvaloniaPatchComInterop)' == ''">false</_AvaloniaPatchComInterop>
<_AvaloniaSkipXamlCompilation Condition="'$(_AvaloniaSkipXamlCompilation)' == ''">false</_AvaloniaSkipXamlCompilation>
</PropertyGroup>
<!-- 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)"
DelaySign="$(DelaySign)"
EnableComInteropPatching="$(_AvaloniaPatchComInterop)"
SkipXamlCompilation="$(_AvaloniaSkipXamlCompilation)"
/>
<Exec
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(),
ProjectDirectory, OutputPath, VerifyIl, outputImportance,
(SignAssembly && !DelaySign) ? AssemblyOriginatorKeyFile : null,
EnableComInteropPatching);
EnableComInteropPatching, SkipXamlCompilation);
if (!res.Success)
return false;
if (!res.WrittenFile)
@ -77,6 +77,7 @@ namespace Avalonia.Build.Tasks
public bool VerifyIl { get; set; }
public bool EnableComInteropPatching { get; set; }
public bool SkipXamlCompilation { get; set; }
public string AssemblyOriginatorKeyFile { get; set; }
public bool SignAssembly { get; set; }

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

@ -40,17 +40,48 @@ namespace Avalonia.Build.Tasks
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,
string output, bool verifyIl, MessageImportance logImportance, string strongNameKey, bool patchCom)
static bool? CompileCore(IBuildEngine engine, CecilTypeSystem typeSystem,
string projectDirectory, bool verifyIl,
MessageImportance logImportance)
{
var typeSystem = new CecilTypeSystem(references.Concat(new[] {input}), input);
var asm = typeSystem.TargetAssemblyDefinition;
var emres = new EmbeddedResources(asm);
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
return new CompileResult(true);
return null;
var clrPropertiesDef = new TypeDefinition("CompiledAvaloniaXaml", "XamlIlHelpers",
TypeAttributes.Class, asm.MainModule.TypeSystem.Object);
@ -364,27 +395,17 @@ namespace Avalonia.Build.Tasks
if (emres.Resources.Count(CheckXamlName) != 0)
if (!CompileGroup(emres))
return new CompileResult(false);
return false;
if (avares.Resources.Count(CheckXamlName) != 0)
{
if (!CompileGroup(avares))
return new CompileResult(false);
return false;
avares.Save();
}
loaderDispatcherMethod.Body.Instructions.Add(Instruction.Create(OpCodes.Ldnull));
loaderDispatcherMethod.Body.Instructions.Add(Instruction.Create(OpCodes.Ret));
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);
return true;
}
}

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

@ -1,8 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup>
<_AvaloniaPatchComInterop>true</_AvaloniaPatchComInterop>
</PropertyGroup>
<Import Project="..\..\build\BuildTargets.targets" />
</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
{
if (obj == null)
return null;
if (obj is MicroComProxyBase proxy)
return (void*)proxy.NativePointer;
if (obj is IMicroComShadowContainer container)
@ -55,6 +57,7 @@ namespace Avalonia.MicroCom
res);
if (owned)
container.Shadow.AddRef((Ccw*)ptr);
return ptr;
}
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((AddRefDelegate)AddRef);
AddMethod((AddRefDelegate)Release);
}
protected void AddMethod(Delegate d)

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

@ -37,7 +37,7 @@
<Target Name="GenerateAvaloniaNativeComInterop"
BeforeTargets="CoreCompile"
DependsOnTargets="ResolveReferences"
Inputs="avn.idl"
Inputs="avn.idl;$(MSBuildThisFileDirectory)/../tools/MicroComGenerator/**/*.cs"
Outputs="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" />
@ -47,8 +47,12 @@
<Compile Include="Interop.Generated.cs"/>
</ItemGroup>
</Target>
<ItemGroup>
<UpToDateCheckInput Include="avn.idl"/>
<UpToDateCheckInput Include="$(MSBuildThisFileDirectory)/../tools/MicroComGenerator/**/*.cs"/>
</ItemGroup>
<PropertyGroup>
<_AvaloniaPatchComInterop>true</_AvaloniaPatchComInterop>
</PropertyGroup>
<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)
{
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)
@ -238,8 +238,11 @@ namespace MicroComGenerator
.AddArgumentListArguments(Argument(ParseExpression("PPV")))
.AddArgumentListArguments(args
.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
if (!isVoidReturn)
callExpr = AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, ParseExpression("__result"),
@ -369,6 +372,10 @@ namespace MicroComGenerator
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 signature = returnType + "::" + name + "::" + string.Join("::", args);
if (_existing.Add(signature))
@ -427,7 +434,7 @@ namespace MicroComGenerator
.AddModifiers(Token(SyntaxKind.StaticKeyword), Token(SyntaxKind.InternalKeyword))
.WithExpressionBody(ArrowExpressionClause(
ParseExpression("Avalonia.MicroCom.MicroComRuntime.RegisterVTable(typeof(" +
proxyClassName + "), new " + vtbl.Identifier.Text + "().CreateVTable())")))
iface.Name + "), new " + vtbl.Identifier.Text + "().CreateVTable())")))
.WithSemicolonToken(Semicolon()));

Loading…
Cancel
Save