Browse Source

Fix "original.dll" file permission errors during build (#13840)

* Avoid constantly recompiling Avalonia Xaml files by implementing incremental build checks
- Should be a (or even the) fix for file permission errors during builds
CompileAvaloniaXaml no longer overwrites the Compile output, but creates its own output files
- This supports incremental build checks and is safer in general
Removed unused executable features from Avalonia.Build.Tasks
- This is instead of refactoring for the new ITaskItem properties
Updated Desktop SLNF

* Fixed tests

* Touch each copied output file
pull/14700/head
Tom Edwards 2 years ago
committed by GitHub
parent
commit
0cb855adf9
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 5
      Avalonia.Desktop.slnf
  2. 79
      packages/Avalonia/AvaloniaBuildTasks.targets
  3. 1
      src/Avalonia.Build.Tasks/Avalonia.Build.Tasks.csproj
  4. 116
      src/Avalonia.Build.Tasks/CompileAvaloniaXamlTask.cs
  5. 86
      src/Avalonia.Build.Tasks/Program.cs
  6. 1
      tests/Avalonia.Build.Tasks.UnitTest/Avalonia.Build.Tasks.UnitTest.csproj
  7. 17
      tests/Avalonia.Build.Tasks.UnitTest/CompileAvaloniaXamlTaskTest.cs

5
Avalonia.Desktop.slnf

@ -51,6 +51,7 @@
"src\\Windows\\Avalonia.Win32\\Avalonia.Win32.csproj",
"tests\\Avalonia.Base.UnitTests\\Avalonia.Base.UnitTests.csproj",
"tests\\Avalonia.Benchmarks\\Avalonia.Benchmarks.csproj",
"tests\\Avalonia.Build.Tasks.UnitTest\\Avalonia.Build.Tasks.UnitTest.csproj",
"tests\\Avalonia.Controls.DataGrid.UnitTests\\Avalonia.Controls.DataGrid.UnitTests.csproj",
"tests\\Avalonia.Controls.ItemsRepeater.UnitTests\\Avalonia.Controls.ItemsRepeater.UnitTests.csproj",
"tests\\Avalonia.Controls.UnitTests\\Avalonia.Controls.UnitTests.csproj",
@ -58,6 +59,7 @@
"tests\\Avalonia.DesignerSupport.Tests\\Avalonia.DesignerSupport.Tests.csproj",
"tests\\Avalonia.Direct2D1.RenderTests\\Avalonia.Direct2D1.RenderTests.csproj",
"tests\\Avalonia.Direct2D1.UnitTests\\Avalonia.Direct2D1.UnitTests.csproj",
"tests\\Avalonia.Generators.Tests\\Avalonia.Generators.Tests.csproj",
"tests\\Avalonia.IntegrationTests.Appium\\Avalonia.IntegrationTests.Appium.csproj",
"tests\\Avalonia.LeakTests\\Avalonia.LeakTests.csproj",
"tests\\Avalonia.Markup.UnitTests\\Avalonia.Markup.UnitTests.csproj",
@ -65,7 +67,8 @@
"tests\\Avalonia.ReactiveUI.UnitTests\\Avalonia.ReactiveUI.UnitTests.csproj",
"tests\\Avalonia.Skia.RenderTests\\Avalonia.Skia.RenderTests.csproj",
"tests\\Avalonia.Skia.UnitTests\\Avalonia.Skia.UnitTests.csproj",
"tests\\Avalonia.UnitTests\\Avalonia.UnitTests.csproj"
"tests\\Avalonia.UnitTests\\Avalonia.UnitTests.csproj",
"tests\\TestFiles\\BuildTasks\\PInvoke\\PInvoke.csproj"
]
}
}

79
packages/Avalonia/AvaloniaBuildTasks.targets

@ -58,7 +58,7 @@
<PropertyGroup>
<BuildAvaloniaResourcesDependsOn>$(BuildAvaloniaResourcesDependsOn);AddAvaloniaResources;ResolveReferences;_GenerateAvaloniaResourcesDependencyCache;_GenerateNoWarnForExec</BuildAvaloniaResourcesDependsOn>
<CompileAvaloniaXamlDependsOn>$(CompileAvaloniaXamlDependsOn);_GenerateNoWarnForExec</CompileAvaloniaXamlDependsOn>
<CompileAvaloniaXamlDependsOn>$(CompileAvaloniaXamlDependsOn);PrepareToCompileAvaloniaXaml;_GenerateNoWarnForExec</CompileAvaloniaXamlDependsOn>
</PropertyGroup>
<Target Name="_GenerateAvaloniaResourcesDependencyCache" BeforeTargets="GenerateAvaloniaResources">
@ -114,38 +114,44 @@
Command="dotnet msbuild /nodereuse:false $(MSBuildProjectFile) /t:GenerateAvaloniaResources /p:NoWarn=$(_NoWarnForExec) /p:_AvaloniaForceInternalMSBuild=true /p:Configuration=$(Configuration) /p:TargetFramework=$(TargetFramework) /p:RuntimeIdentifier=$(RuntimeIdentifier) /p:BuildProjectReferences=false"/>
</Target>
<Target
Name="CompileAvaloniaXaml"
AfterTargets="AfterCompile"
DependsOnTargets="$(CompileAvaloniaXamlDependsOn)"
Condition="
(('@(AvaloniaResource->Count())' &gt; 0)
or ('@(AvaloniaXaml->Count())' &gt; 0))
and Exists('@(IntermediateAssembly)')
And $(DesignTimeBuild) != true
And $(EnableAvaloniaXamlCompilation) != false"
>
<Target Name="PrepareToCompileAvaloniaXaml">
<PropertyGroup>
<AvaloniaXamlReferencesTemporaryFilePath Condition="'$(AvaloniaXamlReferencesTemporaryFilePath)' == ''">$(IntermediateOutputPath)/Avalonia/references</AvaloniaXamlReferencesTemporaryFilePath>
<AvaloniaXamlOriginalCopyFilePath Condition="'$(AvaloniaXamlOriginalCopyFilePath)' == ''">$(IntermediateOutputPath)/Avalonia/original.dll</AvaloniaXamlOriginalCopyFilePath>
<AvaloniaXamlIlVerifyIl Condition="'$(AvaloniaXamlIlVerifyIl)' == ''">false</AvaloniaXamlIlVerifyIl>
<AvaloniaXamlIlDebuggerLaunch Condition="'$(AvaloniaXamlIlDebuggerLaunch)' == ''">false</AvaloniaXamlIlDebuggerLaunch>
<AvaloniaXamlVerboseExceptions Condition="'$(AvaloniaXamlVerboseExceptions)' == ''">false</AvaloniaXamlVerboseExceptions>
<_AvaloniaHasCompiledXaml>true</_AvaloniaHasCompiledXaml>
</PropertyGroup>
<WriteLinesToFile
Condition="'$(_AvaloniaForceInternalMSBuild)' != 'true'"
File="$(AvaloniaXamlReferencesTemporaryFilePath)"
Lines="@(ReferencePathWithRefAssemblies)"
Overwrite="true" />
<ItemGroup Condition="'$(_AvaloniaForceInternalMSBuild)' != 'true'">
<ItemGroup>
<IntermediateAssembly Update="*" AvaloniaCompileOutput="%(RelativeDir)Avalonia\%(Filename)%(Extension)"/>
<_DebugSymbolsIntermediatePath Update="*" AvaloniaCompileOutput="%(RelativeDir)Avalonia\%(Filename)%(Extension)"/>
<IntermediateRefAssembly Update="*" AvaloniaCompileOutput="%(RelativeDir)Avalonia\%(Filename)%(Extension)"/>
<CompileAvaloniaXamlInputs Include="@(IntermediateAssembly);@(_DebugSymbolsIntermediatePath);@(IntermediateRefAssembly)"/>
<CompileAvaloniaXamlOutputs Include="@(CompileAvaloniaXamlInputs->'%(AvaloniaCompileOutput)')"/>
<CompileAvaloniaXamlInputs Include="@(AvaloniaResource);@(AvaloniaXaml)"/>
<FileWrites Include="@(CompileAvaloniaXamlOutputs)"/>
<FileWrites Include="$(AvaloniaXamlReferencesTemporaryFilePath)" />
</ItemGroup>
</Target>
<Target
Name="CompileAvaloniaXaml"
AfterTargets="AfterCompile"
DependsOnTargets="$(CompileAvaloniaXamlDependsOn)"
Inputs="@(CompileAvaloniaXamlInputs)"
Outputs="@(CompileAvaloniaXamlOutputs)"
Condition="'@(AvaloniaResource)@(AvaloniaXaml)' != '' AND $(DesignTimeBuild) != true AND $(EnableAvaloniaXamlCompilation) != false">
<ReadLinesFromFile File="$(AvaloniaXamlReferencesTemporaryFilePath)" Condition="'$(_AvaloniaUseExternalMSBuild)' != 'true' AND '@(ReferencePathWithRefAssemblies)' == ''">
<Output TaskParameter="Lines" ItemName="ReferencePathWithRefAssemblies"/>
</ReadLinesFromFile>
<CompileAvaloniaXamlTask
Condition="'$(_AvaloniaUseExternalMSBuild)' != 'true'"
AssemblyFile="@(IntermediateAssembly)"
ReferencesFilePath="$(AvaloniaXamlReferencesTemporaryFilePath)"
OriginalCopyPath="$(AvaloniaXamlOriginalCopyFilePath)"
References="@(ReferencePathWithRefAssemblies)"
RefAssemblyFile="@(IntermediateRefAssembly)"
ProjectDirectory="$(MSBuildProjectDirectory)"
VerifyIl="$(AvaloniaXamlIlVerifyIl)"
@ -157,14 +163,39 @@
DebuggerLaunch="$(AvaloniaXamlIlDebuggerLaunch)"
DefaultCompileBindings="$(AvaloniaUseCompiledBindingsByDefault)"
VerboseExceptions="$(AvaloniaXamlVerboseExceptions)"
AnalyzerConfigFiles="@(EditorConfigFiles)">
<Output TaskParameter="WrittenFilePaths" ItemName="FileWrites" />
</CompileAvaloniaXamlTask>
AnalyzerConfigFiles="@(EditorConfigFiles)"/>
<WriteLinesToFile File="$(AvaloniaXamlReferencesTemporaryFilePath)" Lines="@(ReferencePathWithRefAssemblies)" Overwrite="true"
Condition="'$(_AvaloniaUseExternalMSBuild)' == 'true'" />
<Exec
Condition="'$(_AvaloniaUseExternalMSBuild)' == 'true'"
Command="dotnet msbuild /nodereuse:false $(MSBuildProjectFile) /t:CompileAvaloniaXaml /p:NoWarn=$(_NoWarnForExec) /p:_AvaloniaForceInternalMSBuild=true /p:Configuration=$(Configuration) /p:TargetFramework=$(TargetFramework) /p:RuntimeIdentifier=$(RuntimeIdentifier) /p:BuildProjectReferences=false"/>
</Target>
<Target Name="InjectAvaloniaXamlOutput" DependsOnTargets="PrepareToCompileAvaloniaXaml" AfterTargets="CompileAvaloniaXaml" BeforeTargets="CopyFilesToOutputDirectory;BuiltProjectOutputGroup"
Condition="'@(AvaloniaResource)@(AvaloniaXaml)' != '' AND $(EnableAvaloniaXamlCompilation) != false">
<ItemGroup>
<_AvaloniaXamlCompiledAssembly Include="@(IntermediateAssembly->Metadata('AvaloniaCompileOutput'))"/>
<IntermediateAssembly Remove="@(IntermediateAssembly)"/>
<IntermediateAssembly Include="@(_AvaloniaXamlCompiledAssembly)"/>
<_AvaloniaXamlCompiledRefAssembly Include="@(IntermediateRefAssembly->Metadata('AvaloniaCompileOutput'))"/>
<IntermediateRefAssembly Remove="@(IntermediateRefAssembly)"/>
<IntermediateRefAssembly Include="@(_AvaloniaXamlCompiledRefAssembly)"/>
<_AvaloniaXamlCompiledSymbols Include="@(_DebugSymbolsIntermediatePath->Metadata('AvaloniaCompileOutput'))"/>
<_DebugSymbolsIntermediatePath Remove="@(_DebugSymbolsIntermediatePath)"/>
<_DebugSymbolsIntermediatePath Include="@(_AvaloniaXamlCompiledSymbols)"/>
</ItemGroup>
</Target>
<Target Name="Avalonia_CollectUpToDateCheckOutputDesignTime" Condition="'@(AvaloniaResource)@(AvaloniaXaml)' != '' AND $(EnableAvaloniaXamlCompilation) != false"
BeforeTargets="CollectUpToDateCheckOutputDesignTime" DependsOnTargets="PrepareToCompileAvaloniaXaml">
<ItemGroup>
<UpToDateCheckOutput Include="@(CompileAvaloniaXamlOutputs)"/>
</ItemGroup>
</Target>
<ItemGroup>
<UpToDateCheckInput Include="@(AvaloniaResource)" />

1
src/Avalonia.Build.Tasks/Avalonia.Build.Tasks.csproj

@ -1,7 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0</TargetFrameworks>
<OutputType>exe</OutputType>
<GenerateDocumentationFile>false</GenerateDocumentationFile>
<BuildOutputTargetFolder>tools</BuildOutputTargetFolder>
<DefineConstants>$(DefineConstants);BUILDTASK;XAMLX_CECIL_INTERNAL;XAMLX_INTERNAL</DefineConstants>

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

@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Microsoft.Build.Framework;
@ -8,110 +7,70 @@ namespace Avalonia.Build.Tasks
{
public class CompileAvaloniaXamlTask: ITask
{
public const string AvaloniaCompileOutputMetadataName = "AvaloniaCompileOutput";
public bool Execute()
{
Enum.TryParse(ReportImportance, true, out MessageImportance outputImportance);
var writtenFilePaths = new List<string>();
OutputPath ??= AssemblyFile;
RefOutputPath ??= RefAssemblyFile;
var outputPdb = GetPdbPath(OutputPath);
var input = AssemblyFile;
var refInput = RefOutputPath;
var inputPdb = GetPdbPath(input);
// Make a copy and delete the original file to prevent MSBuild from thinking that everything is OK
if (OriginalCopyPath != null)
{
var originalCopyPathRef = Path.ChangeExtension(OriginalCopyPath, ".ref.dll");
File.Copy(AssemblyFile, OriginalCopyPath, true);
writtenFilePaths.Add(OriginalCopyPath);
input = OriginalCopyPath;
File.Delete(AssemblyFile);
var outputPath = AssemblyFile.GetMetadata(AvaloniaCompileOutputMetadataName);
var refOutputPath = RefAssemblyFile?.GetMetadata(AvaloniaCompileOutputMetadataName);
if (File.Exists(inputPdb))
{
var copyPdb = GetPdbPath(OriginalCopyPath);
File.Copy(inputPdb, copyPdb, true);
writtenFilePaths.Add(copyPdb);
File.Delete(inputPdb);
inputPdb = copyPdb;
}
if (!string.IsNullOrWhiteSpace(RefAssemblyFile) && File.Exists(RefAssemblyFile))
{
// We also copy ref assembly just for case if needed later for testing.
// But do not remove the original one, as MSBuild actually complains about it with multi-thread compiling.
File.Copy(RefAssemblyFile, originalCopyPathRef, true);
writtenFilePaths.Add(originalCopyPathRef);
refInput = originalCopyPathRef;
}
Directory.CreateDirectory(Path.GetDirectoryName(outputPath));
if (!string.IsNullOrEmpty(refOutputPath))
{
Directory.CreateDirectory(Path.GetDirectoryName(refOutputPath));
}
var msg = $"CompileAvaloniaXamlTask -> AssemblyFile:{AssemblyFile}, ProjectDirectory:{ProjectDirectory}, OutputPath:{OutputPath}";
var msg = $"CompileAvaloniaXamlTask -> AssemblyFile:{AssemblyFile}, ProjectDirectory:{ProjectDirectory}, OutputPath:{outputPath}";
BuildEngine.LogMessage(msg, outputImportance < MessageImportance.Low ? MessageImportance.High : outputImportance);
var res = XamlCompilerTaskExecutor.Compile(BuildEngine,
input, OutputPath,
refInput, RefOutputPath,
File.ReadAllLines(ReferencesFilePath).Where(l => !string.IsNullOrWhiteSpace(l)).ToArray(),
AssemblyFile.ItemSpec, outputPath,
RefAssemblyFile?.ItemSpec, refOutputPath,
References?.Select(i => i.ItemSpec).ToArray() ?? Array.Empty<string>(),
ProjectDirectory, VerifyIl, DefaultCompileBindings, outputImportance,
new XamlCompilerDiagnosticsFilter(AnalyzerConfigFiles),
(SignAssembly && !DelaySign) ? AssemblyOriginatorKeyFile : null,
SkipXamlCompilation, DebuggerLaunch, VerboseExceptions);
if (!res.Success)
{
WrittenFilePaths = writtenFilePaths.ToArray();
return false;
}
if (!res.WrittenFile)
if (res.Success && !res.WrittenFile)
{
File.Copy(input, OutputPath, true);
if (File.Exists(inputPdb))
File.Copy(inputPdb, outputPdb, true);
}
else if (!string.IsNullOrWhiteSpace(RefOutputPath) && File.Exists(RefOutputPath))
writtenFilePaths.Add(RefOutputPath);
// To simplify incremental build checks, copy the input files to the expected output locations even if the Xaml compiler didn't do anything.
CopyAndTouch(AssemblyFile.ItemSpec, outputPath);
CopyAndTouch(Path.ChangeExtension(AssemblyFile.ItemSpec, ".pdb"), Path.ChangeExtension(outputPath, ".pdb"));
writtenFilePaths.Add(OutputPath);
if (File.Exists(outputPdb))
writtenFilePaths.Add(outputPdb);
if (!string.IsNullOrEmpty(refOutputPath))
{
CopyAndTouch(RefAssemblyFile.ItemSpec, refOutputPath);
}
}
WrittenFilePaths = writtenFilePaths.ToArray();
return true;
return res.Success;
}
string GetPdbPath(string p)
private static void CopyAndTouch(string source, string destination)
{
var d = Path.GetDirectoryName(p);
var f = Path.GetFileNameWithoutExtension(p);
var rv = f + ".pdb";
if (d != null)
rv = Path.Combine(d, rv);
return rv;
File.Copy(source, destination, overwrite: true);
File.SetLastWriteTimeUtc(destination, DateTime.UtcNow);
}
[Required]
public string AssemblyFile { get; set; }
[Required]
public string ReferencesFilePath { get; set; }
[Required]
public string OriginalCopyPath { get; set; }
[Required]
public string ProjectDirectory { get; set; }
public string RefAssemblyFile { get; set; }
public string RefOutputPath { get; set; }
public string OutputPath { get; set; }
[Required]
public ITaskItem AssemblyFile { get; set; }
public ITaskItem? RefAssemblyFile { get; set; }
public ITaskItem[]? References { get; set; }
public bool VerifyIl { get; set; }
public bool DefaultCompileBindings { get; set; }
public bool SkipXamlCompilation { get; set; }
public string AssemblyOriginatorKeyFile { get; set; }
public bool SignAssembly { get; set; }
public bool DelaySign { get; set; }
@ -124,10 +83,7 @@ namespace Avalonia.Build.Tasks
public bool DebuggerLaunch { get; set; }
public bool VerboseExceptions { get; set; }
public ITaskItem[] AnalyzerConfigFiles { get; set; }
[Output]
public string[] WrittenFilePaths { get; private set; } = Array.Empty<string>();
}
}

86
src/Avalonia.Build.Tasks/Program.cs

@ -1,86 +0,0 @@
using System;
using System.Collections;
using System.IO;
using System.Linq;
using Microsoft.Build.Framework;
namespace Avalonia.Build.Tasks
{
public class Program
{
private const string OriginalDll = "original.dll";
private const string References = "references";
private const string OutDll = "out.dll";
static int Main(string[] args)
{
if (args.Length < 3)
{
if (args.Length == 1)
{
args = new[] {OriginalDll, References, OutDll}
.Select(x => Path.Combine(args[0], x)).ToArray();
}
else
{
const string referencesOutputPath = "path/to/Avalonia/samples/Sandbox/obj/Debug/net60/Avalonia";
Console.WriteLine(@$"Usage:
1) dotnet ./Avalonia.Build.Tasks.dll <ReferencesOutputPath>
, where <ReferencesOutputPath> likes {referencesOutputPath}
2) dotnet ./Avalonia.Build.Tasks.dll <AssemblyFilePath> <ReferencesFilePath> <OutputPath> <RefAssemblyFile>
, where:
- <AssemblyFilePath> likes {referencesOutputPath}/{OriginalDll}
- <ReferencesFilePath> likes {referencesOutputPath}/{References}
- <OutputPath> likes {referencesOutputPath}/{OutDll}
- <RefAssemblyFile> Likes {referencesOutputPath}/original.ref.dll");
return 1;
}
}
return new CompileAvaloniaXamlTask()
{
AssemblyFile = args[0],
ReferencesFilePath = args[1],
OutputPath = args[2],
RefAssemblyFile = args.Length > 3 ? args[3] : null,
BuildEngine = new ConsoleBuildEngine(),
ProjectDirectory = Directory.GetCurrentDirectory(),
VerifyIl = true
}.Execute() ?
0 :
2;
}
class ConsoleBuildEngine : IBuildEngine
{
public void LogErrorEvent(BuildErrorEventArgs e)
{
Console.WriteLine($"ERROR: {e.Code} {e.Message} in {e.File} {e.LineNumber}:{e.ColumnNumber}-{e.EndLineNumber}:{e.EndColumnNumber}");
}
public void LogWarningEvent(BuildWarningEventArgs e)
{
Console.WriteLine($"WARNING: {e.Code} {e.Message} in {e.File} {e.LineNumber}:{e.ColumnNumber}-{e.EndLineNumber}:{e.EndColumnNumber}");
}
public void LogMessageEvent(BuildMessageEventArgs e)
{
Console.WriteLine($"MESSAGE: {e.Code} {e.Message} in {e.File} {e.LineNumber}:{e.ColumnNumber}-{e.EndLineNumber}:{e.EndColumnNumber}");
}
public void LogCustomEvent(CustomBuildEventArgs e)
{
Console.WriteLine($"CUSTOM: {e.Message}");
}
public bool BuildProjectFile(string projectFileName, string[] targetNames, IDictionary globalProperties,
IDictionary targetOutputs) => throw new NotSupportedException();
public bool ContinueOnError { get; }
public int LineNumberOfTaskNode { get; }
public int ColumnNumberOfTaskNode { get; }
public string ProjectFileOfTaskNode { get; }
}
}
}

1
tests/Avalonia.Build.Tasks.UnitTest/Avalonia.Build.Tasks.UnitTest.csproj

@ -25,6 +25,7 @@
<ItemGroup>
<PackageReference Include="Microsoft.Build.Framework" Version="15.1.548" PrivateAssets="All" />
<PackageReference Include="Microsoft.Build.Utilities.Core" Version="15.1.548" />
</ItemGroup>
<ItemGroup>

17
tests/Avalonia.Build.Tasks.UnitTest/CompileAvaloniaXamlTaskTest.cs

@ -1,6 +1,8 @@
using System;
using System.IO;
using System.Linq;
using System.Reflection;
using Microsoft.Build.Utilities;
using Xunit;
namespace Avalonia.Build.Tasks.UnitTest;
@ -13,19 +15,16 @@ public class CompileAvaloniaXamlTaskTest
{
using var engine = UnitTestBuildEngine.Start();
var basePath = Path.Combine(Path.GetDirectoryName(new Uri(Assembly.GetExecutingAssembly().CodeBase).LocalPath), "Assets");
var originalAssemblyPath = Path.Combine(basePath,
"PInvoke.dll");
var referencesPath = Path.Combine(basePath,
"PInvoke.dll.refs");
var compiledAssemblyPath = "PInvoke.dll";
var assembly = new TaskItem(Path.Combine(basePath, "PInvoke.dll"));
assembly.SetMetadata(CompileAvaloniaXamlTask.AvaloniaCompileOutputMetadataName, Path.Combine(basePath, "Avalonia", Path.GetFileName(assembly.ItemSpec)));
var references = File.ReadAllLines(Path.Combine(basePath, "PInvoke.dll.refs")).Select(p => new TaskItem(p)).ToArray();
Assert.True(File.Exists(originalAssemblyPath), $"The original {originalAssemblyPath} don't exists.");
Assert.True(File.Exists(assembly.ItemSpec), $"The original {assembly.ItemSpec} don't exist.");
new CompileAvaloniaXamlTask()
{
AssemblyFile = originalAssemblyPath,
ReferencesFilePath = referencesPath,
OutputPath = compiledAssemblyPath,
AssemblyFile = assembly,
References = references,
RefAssemblyFile = null,
BuildEngine = engine,
ProjectDirectory = Directory.GetCurrentDirectory(),

Loading…
Cancel
Save