Browse Source

Merge pull request #6972 from workgroupengineering/features/Issue_6971

feat: Allow to debug XamlIl Compilation
release/0.10.11-rc.1
Dan Walmsley 4 years ago
parent
commit
3dba0e00ec
  1. 2
      packages/Avalonia/AvaloniaBuildTasks.targets
  2. 7
      src/Avalonia.Build.Tasks/CompileAvaloniaXamlTask.cs
  3. 52
      src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.cs

2
packages/Avalonia/AvaloniaBuildTasks.targets

@ -88,6 +88,7 @@
<AvaloniaXamlReferencesTemporaryFilePath Condition="'$(AvaloniaXamlReferencesTemporaryFilePath)' == ''">$(IntermediateOutputPath)/Avalonia/references</AvaloniaXamlReferencesTemporaryFilePath> <AvaloniaXamlReferencesTemporaryFilePath Condition="'$(AvaloniaXamlReferencesTemporaryFilePath)' == ''">$(IntermediateOutputPath)/Avalonia/references</AvaloniaXamlReferencesTemporaryFilePath>
<AvaloniaXamlOriginalCopyFilePath Condition="'$(AvaloniaXamlOriginalCopyFilePath)' == ''">$(IntermediateOutputPath)/Avalonia/original.dll</AvaloniaXamlOriginalCopyFilePath> <AvaloniaXamlOriginalCopyFilePath Condition="'$(AvaloniaXamlOriginalCopyFilePath)' == ''">$(IntermediateOutputPath)/Avalonia/original.dll</AvaloniaXamlOriginalCopyFilePath>
<AvaloniaXamlIlVerifyIl Condition="'$(AvaloniaXamlIlVerifyIl)' == ''">false</AvaloniaXamlIlVerifyIl> <AvaloniaXamlIlVerifyIl Condition="'$(AvaloniaXamlIlVerifyIl)' == ''">false</AvaloniaXamlIlVerifyIl>
<AvaloniaXamlIlDebuggerLaunch Condition="'$(AvaloniaXamlIlDebuggerLaunch)' == ''">false</AvaloniaXamlIlDebuggerLaunch>
</PropertyGroup> </PropertyGroup>
<WriteLinesToFile <WriteLinesToFile
Condition="'$(_AvaloniaForceInternalMSBuild)' != 'true'" Condition="'$(_AvaloniaForceInternalMSBuild)' != 'true'"
@ -107,6 +108,7 @@
DelaySign="$(DelaySign)" DelaySign="$(DelaySign)"
EnableComInteropPatching="$(_AvaloniaPatchComInterop)" EnableComInteropPatching="$(_AvaloniaPatchComInterop)"
SkipXamlCompilation="$(_AvaloniaSkipXamlCompilation)" SkipXamlCompilation="$(_AvaloniaSkipXamlCompilation)"
DebuggerLaunch="$(AvaloniaXamlIlDebuggerLaunch)"
/> />
<Exec <Exec
Condition="'$(_AvaloniaUseExternalMSBuild)' == 'true'" Condition="'$(_AvaloniaUseExternalMSBuild)' == 'true'"

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

@ -1,9 +1,6 @@
using System; using System;
using System.Diagnostics;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Reflection;
using System.Threading;
using Microsoft.Build.Framework; using Microsoft.Build.Framework;
namespace Avalonia.Build.Tasks namespace Avalonia.Build.Tasks
@ -41,7 +38,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, SkipXamlCompilation); EnableComInteropPatching, SkipXamlCompilation, DebuggerLaunch);
if (!res.Success) if (!res.Success)
return false; return false;
if (!res.WrittenFile) if (!res.WrittenFile)
@ -87,5 +84,7 @@ namespace Avalonia.Build.Tasks
public IBuildEngine BuildEngine { get; set; } public IBuildEngine BuildEngine { get; set; }
public ITaskHost HostObject { get; set; } public ITaskHost HostObject { get; set; }
public bool DebuggerLaunch { get; set; }
} }
} }

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

@ -1,13 +1,10 @@
using System; using System;
using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Text;
using Avalonia.Markup.Xaml.XamlIl.CompilerExtensions; using Avalonia.Markup.Xaml.XamlIl.CompilerExtensions;
using Microsoft.Build.Framework; using Microsoft.Build.Framework;
using Mono.Cecil; using Mono.Cecil;
using Avalonia.Utilities;
using Mono.Cecil.Cil; using Mono.Cecil.Cil;
using Mono.Cecil.Rocks; using Mono.Cecil.Rocks;
using XamlX; using XamlX;
@ -44,16 +41,23 @@ namespace Avalonia.Build.Tasks
string projectDirectory, string projectDirectory,
string output, bool verifyIl, MessageImportance logImportance, string strongNameKey, bool patchCom, string output, bool verifyIl, MessageImportance logImportance, string strongNameKey, bool patchCom,
bool skipXamlCompilation) bool skipXamlCompilation)
{
return Compile(engine, input, references, projectDirectory, output, verifyIl, logImportance, strongNameKey, patchCom, skipXamlCompilation, debuggerLaunch:false);
}
internal static CompileResult Compile(IBuildEngine engine, string input, string[] references,
string projectDirectory,
string output, bool verifyIl, MessageImportance logImportance, string strongNameKey, bool patchCom, bool skipXamlCompilation, bool debuggerLaunch)
{ {
var typeSystem = new CecilTypeSystem(references var typeSystem = new CecilTypeSystem(references
.Where(r => !r.ToLowerInvariant().EndsWith("avalonia.build.tasks.dll")) .Where(r => !r.ToLowerInvariant().EndsWith("avalonia.build.tasks.dll"))
.Concat(new[] { input }), input); .Concat(new[] { input }), input);
var asm = typeSystem.TargetAssemblyDefinition; var asm = typeSystem.TargetAssemblyDefinition;
if (!skipXamlCompilation) if (!skipXamlCompilation)
{ {
var compileRes = CompileCore(engine, typeSystem, projectDirectory, verifyIl, logImportance); var compileRes = CompileCore(engine, typeSystem, projectDirectory, verifyIl, logImportance, debuggerLaunch);
if (compileRes == null && !patchCom) if (compileRes == null && !patchCom)
return new CompileResult(true); return new CompileResult(true);
if (compileRes == false) if (compileRes == false)
@ -62,7 +66,7 @@ namespace Avalonia.Build.Tasks
if (patchCom) if (patchCom)
ComInteropHelper.PatchAssembly(asm, typeSystem); ComInteropHelper.PatchAssembly(asm, typeSystem);
var writerParameters = new WriterParameters { WriteSymbols = asm.MainModule.HasSymbols }; var writerParameters = new WriterParameters { WriteSymbols = asm.MainModule.HasSymbols };
if (!string.IsNullOrWhiteSpace(strongNameKey)) if (!string.IsNullOrWhiteSpace(strongNameKey))
writerParameters.StrongNameKeyBlob = File.ReadAllBytes(strongNameKey); writerParameters.StrongNameKeyBlob = File.ReadAllBytes(strongNameKey);
@ -70,13 +74,43 @@ namespace Avalonia.Build.Tasks
asm.Write(output, writerParameters); asm.Write(output, writerParameters);
return new CompileResult(true, true); return new CompileResult(true, true);
} }
static bool? CompileCore(IBuildEngine engine, CecilTypeSystem typeSystem, static bool? CompileCore(IBuildEngine engine, CecilTypeSystem typeSystem,
string projectDirectory, bool verifyIl, string projectDirectory, bool verifyIl,
MessageImportance logImportance) MessageImportance logImportance
, bool debuggerLaunch = false)
{ {
if (debuggerLaunch)
{
// According this https://docs.microsoft.com/en-us/dotnet/api/system.diagnostics.debugger.launch?view=net-6.0#remarks
// documentation, on not windows platform Debugger.Launch() always return true without running a debugger.
if (System.Diagnostics.Debugger.Launch())
{
// Set timeout at 1 minut.
var time = new System.Diagnostics.Stopwatch();
var timeout = TimeSpan.FromMinutes(1);
time.Start();
// wait for the debugger to be attacked or timeout.
while (!System.Diagnostics.Debugger.IsAttached && time.Elapsed < timeout)
{
engine.LogMessage($"[PID:{System.Diagnostics.Process.GetCurrentProcess().Id}] Wating attach debugger. Elapsed {time.Elapsed}...", MessageImportance.High);
System.Threading.Thread.Sleep(100);
}
time.Stop();
if (time.Elapsed >= timeout)
{
engine.LogMessage("Wating attach debugger timeout.", MessageImportance.Normal);
}
}
else
{
engine.LogMessage("Debugging cancelled.", MessageImportance.Normal);
}
}
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);

Loading…
Cancel
Save