Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
6801590
change IDictionary<string, string> to TaskHostParameters
YuliiaKovalova Oct 8, 2025
c7140dc
adjustments
YuliiaKovalova Oct 8, 2025
b49b406
Update XML documentation to use 'null' instead of empty string
YuliiaKovalova Oct 8, 2025
6f56364
Refactor IsEmpty property for clarity
YuliiaKovalova Oct 8, 2025
c683f55
Conditionalize task factory parameter merging
YuliiaKovalova Oct 8, 2025
c560801
Enable continueOnError for code coverage publishing
YuliiaKovalova Oct 8, 2025
1e07648
fix review comments
YuliiaKovalova Oct 9, 2025
d2dbe50
add implicit architecture/runtime support
YuliiaKovalova Oct 10, 2025
9346436
more fixes + tests
YuliiaKovalova Oct 10, 2025
a0b3ebf
cover architecture with tests and do more cleanup
YuliiaKovalova Oct 13, 2025
3490ac9
fix the test
YuliiaKovalova Oct 14, 2025
9f1d1db
Merge branch 'main' into dev/ykovalova/infer_task_host_and_arch
YuliiaKovalova Oct 15, 2025
3d00709
Merge branch 'main' into dev/ykovalova_respect_task_arch_runtime
YuliiaKovalova Oct 15, 2025
593314c
Merge branch 'main' into dev/ykovalova/infer_task_host_and_arch
YuliiaKovalova Oct 20, 2025
cad02ba
remove ITaskHostFactory3
YuliiaKovalova Oct 21, 2025
e79b737
merge
YuliiaKovalova Oct 21, 2025
8a6948d
add Task2 compatibility checks
YuliiaKovalova Oct 24, 2025
2dae9bd
sidecar fixes
YuliiaKovalova Oct 27, 2025
f23b67e
fix remaining review comments
YuliiaKovalova Oct 29, 2025
9e6b65f
remove extra using
YuliiaKovalova Oct 29, 2025
11160dd
merge
YuliiaKovalova Oct 29, 2025
14d3483
merge
YuliiaKovalova Nov 4, 2025
4b2bff5
Merge branch 'main' into dev/ykovalova_respect_task_arch_runtime
YuliiaKovalova Nov 4, 2025
ecdd629
reshuffle a bit
YuliiaKovalova Nov 4, 2025
7b7519d
main
YuliiaKovalova Nov 12, 2025
1d50451
merge
YuliiaKovalova Nov 12, 2025
93b012e
Merge branch 'main' into dev/ykovalova_respect_task_arch_runtime
YuliiaKovalova Nov 19, 2025
3010ac2
Merge branch 'main' into dev/ykovalova_respect_task_arch_runtime
YuliiaKovalova Nov 24, 2025
ecac848
fix review comments
YuliiaKovalova Nov 25, 2025
4f86a7f
cleanup
YuliiaKovalova Nov 26, 2025
5220934
Merge branch 'main' into dev/ykovalova_respect_task_arch_runtime
YuliiaKovalova Nov 27, 2025
ae8d521
update localization
YuliiaKovalova Nov 27, 2025
4bf676c
Delete .mcp.json
YuliiaKovalova Nov 27, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 67 additions & 0 deletions src/Build.UnitTests/BackEnd/AssemblyTaskFactory_E2E_Tests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.IO;
using Microsoft.Build.Shared;
using Microsoft.Build.UnitTests;
using Microsoft.Build.UnitTests.Shared;
using Shouldly;
using Xunit;
using Xunit.Abstractions;

namespace Microsoft.Build.Engine.UnitTests
{
public class AssemblyTaskFactory_E2E_Tests
{
private static string AssemblyLocation { get; } = Path.Combine(Path.GetDirectoryName(typeof(NetTaskHost_E2E_Tests).Assembly.Location) ?? AppContext.BaseDirectory);

private static string TestAssetsRootPath { get; } = Path.Combine(AssemblyLocation, "TestAssets");

private readonly ITestOutputHelper _output;

public AssemblyTaskFactory_E2E_Tests(ITestOutputHelper output)
{
_output = output;
}

[WindowsFullFrameworkOnlyFact]
public void FrameworkTaskArchitectureMismatchHandledSuccessfullyTest()
{
using TestEnvironment env = TestEnvironment.Create(_output);

string testProjectPath = Path.Combine(TestAssetsRootPath, "ExampleFrameworkTask", "TestTask", "TestTask.csproj");

string testTaskOutput = RunnerUtilities.ExecBootstrapedMSBuild($"{testProjectPath} -restore -v:n", out bool successTestTask);

if (!successTestTask)
{
_output.WriteLine(testTaskOutput);
}

successTestTask.ShouldBeTrue();

testTaskOutput.ShouldContain("The task is executed in process: MSBuild");
testTaskOutput.ShouldContain("PlatformTarget: x86");
testTaskOutput.ShouldContain("PlatformTarget: x64");
}

[WindowsFullFrameworkOnlyFact]
public void FrameworkTaskArchitectureMismatchReportsWarningTest()
{
using TestEnvironment env = TestEnvironment.Create(_output);

string testProjectPath = Path.Combine(TestAssetsRootPath, "ExampleFrameworkTask", "TestTask", "TestTask.csproj");

string testTaskOutput = RunnerUtilities.ExecBootstrapedMSBuild($"{testProjectPath} -restore -v:n", out bool successTestTask);

if (!successTestTask)
{
_output.WriteLine(testTaskOutput);
}

successTestTask.ShouldBeTrue();
testTaskOutput.ShouldContain(ResourceUtilities.FormatResourceStringStripCodeAndKeyword("AssemblyLoad_Warning", "ExampleTaskX64"));
}
}
}
6 changes: 4 additions & 2 deletions src/Build.UnitTests/BackEnd/AssemblyTaskFactory_Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System.Reflection;
using Microsoft.Build.BackEnd;
using Microsoft.Build.Construction;
using Microsoft.Build.Engine.UnitTests;
using Microsoft.Build.Execution;
using Microsoft.Build.Framework;
using Microsoft.Build.Shared;
Expand Down Expand Up @@ -691,11 +692,12 @@ private void SetupTaskFactory(TaskHostParameters factoryParameters, bool explici
{
factoryParameters = factoryParameters.WithTaskHostFactoryExplicitlyRequested(true);
}
_loadedType = _taskFactory.InitializeFactory(_loadInfo, "TaskToTestFactories", new Dictionary<string, TaskPropertyInfo>(), string.Empty, factoryParameters, explicitlyLaunchTaskHost, null, ElementLocation.Create("NONE"), String.Empty);

_loadedType = _taskFactory.InitializeFactory(_loadInfo, "TaskToTestFactories", new Dictionary<string, TaskPropertyInfo>(), string.Empty, factoryParameters, explicitlyLaunchTaskHost, new TestLoggingContext(null!, new BuildEventContext(1, 2, 3, 4)), ElementLocation.Create("NONE"), String.Empty);
Assert.True(_loadedType.Assembly.Equals(_loadInfo)); // "Expected the AssemblyLoadInfo to be equal"
}

#endregion
#endregion

#region InternalClasses
/// <summary>
Expand Down
12 changes: 10 additions & 2 deletions src/Build.UnitTests/Microsoft.Build.Engine.UnitTests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,13 @@

<DefineConstants>$(DefineConstants);MICROSOFT_BUILD_ENGINE_UNITTESTS</DefineConstants>

<!-- Define a constant so we can skip tests that require MSBuildTaskHost -->
<!-- Define a constant so we can skip tests that require MSBuildTaskHost -->
<DefineConstants Condition="'$(MSBuildRuntimeType)' == 'Core'">$(DefineConstants);NO_MSBUILDTASKHOST</DefineConstants>

<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>

<!-- Suppression in needed to build ExampleTaskX86 that targets x86 architecture. -->
<NoWarn>$(NoWarn);MSB3270</NoWarn>
</PropertyGroup>

<ItemGroup>
Expand Down Expand Up @@ -125,11 +128,16 @@
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemDefinitionGroup>

<ItemGroup Label="TestAssests" Condition="'$(TargetFrameworkIdentifier)' != '.NETFramework'">
<ProjectReference Include=".\TestAssets\ExampleNetTask\ExampleTask\ExampleTask.csproj" />
</ItemGroup>

<ItemGroup Label="TestAssests" Condition="'$(TargetFrameworkIdentifier)' == '.NETFramework'">
<ProjectReference Include=".\TestAssets\ExampleFrameworkTask\ExampleTaskX64\ExampleTaskX64.csproj" />
<ProjectReference Include=".\TestAssets\ExampleFrameworkTask\ExampleTaskX86\ExampleTaskX86.csproj" />
</ItemGroup>

<ItemGroup>
<EmbeddedResource Include="TestAssets\ExampleNetTask\TestMSBuildTaskInNet\global.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
Expand Down
10 changes: 9 additions & 1 deletion src/Build.UnitTests/NetTaskHost_E2E_Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ public void NetTaskHost_CorrectPathsEscapingTest()
testTaskOutput,
@"Arg\[0\]:\s*(.+)",
System.Text.RegularExpressions.RegexOptions.CultureInvariant);

msBuildDllPathMatch.Success.ShouldBeTrue();
string msBuildDllPath = msBuildDllPathMatch.Groups[1].Value.Trim();

Expand Down Expand Up @@ -151,9 +151,17 @@ public void NetTaskWithImplicitHostParamsTest()
}

successTestTask.ShouldBeTrue();

// Output from the task where only Runtime was specified
testTaskOutput.ShouldContain($"The task is executed in process: dotnet");
testTaskOutput.ShouldContain($"Process path: {dotnetPath}", customMessage: testTaskOutput);
testTaskOutput.ShouldContain("/nodereuse:True");

// Output from the task where only TaskHost was specified
testTaskOutput.ShouldContain($"Hello TEST FROM MESSAGE");

// Output from the task where neither TaskHost nor Runtime were specified
testTaskOutput.ShouldContain("Found item: Banana");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System.Diagnostics;
using Microsoft.Build.Framework;

namespace SampleTask
{
public class ExampleTaskX64 : Microsoft.Build.Utilities.Task
{
public string? PlatformTarget { get; set; }

public override bool Execute()
{
try
{
var currentProcess = Process.GetCurrentProcess();
var executingProcess = currentProcess.ProcessName;
var processPath = currentProcess.MainModule?.FileName ?? "Unknown";

Log.LogMessage(MessageImportance.High, $"The task is executed in process: {executingProcess}");
Log.LogMessage(MessageImportance.High, $"PlatformTarget: {PlatformTarget ?? "Not specified"}");

return true;
}
catch (System.Exception ex)
{
Log.LogError($"Failed to determine executing process: {ex.Message}");
return false;
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net472</TargetFramework>
<PlatformTarget>x64</PlatformTarget>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Build.Utilities.Core" />
</ItemGroup>

<ItemGroup>
<PackageVersion Include="Microsoft.Build.Utilities.Core" Version="17.14.28" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System.Diagnostics;
using Microsoft.Build.Framework;

namespace SampleTask
{
public class ExampleTaskX86 : Microsoft.Build.Utilities.Task
{
public string? PlatformTarget { get; set; }

public override bool Execute()
{
try
{
var currentProcess = Process.GetCurrentProcess();
var executingProcess = currentProcess.ProcessName;
var processPath = currentProcess.MainModule?.FileName ?? "Unknown";

Log.LogMessage(MessageImportance.High, $"The task is executed in process: {executingProcess}");
Log.LogMessage(MessageImportance.High, $"PlatformTarget: {PlatformTarget ?? "Not specified"}");

return true;
}
catch (System.Exception ex)
{
Log.LogError($"Failed to determine executing process: {ex.Message}");
return false;
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net472</TargetFramework>
<PlatformTarget>x86</PlatformTarget>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Build.Utilities.Core" />
</ItemGroup>

<ItemGroup>
<PackageVersion Include="Microsoft.Build.Utilities.Core" Version="17.14.28" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<Project ToolsVersion="msbuilddefaulttoolsversion" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

<PropertyGroup>
<TargetFramework>net472</TargetFramework>
</PropertyGroup>

<PropertyGroup>
<TestProjectFolder>$([System.IO.Path]::GetFullPath('$([System.IO.Path]::Combine('$(AssemblyLocation)', '..'))'))</TestProjectFolder>
<ExampleTaskX86Path>$([System.IO.Path]::Combine('$(TestProjectFolder)', '$(TargetFramework)', 'ExampleTaskX86.dll'))</ExampleTaskX86Path>
<ExampleTaskX64Path>$([System.IO.Path]::Combine('$(TestProjectFolder)', '$(TargetFramework)', 'ExampleTaskX64.dll'))</ExampleTaskX64Path>
</PropertyGroup>

<UsingTask TaskName="ExampleTaskX86" AssemblyFile="$(ExampleTaskX86Path)"/>
<UsingTask TaskName="ExampleTaskX64" AssemblyFile="$(ExampleTaskX64Path)"/>

<Target Name="TestTask" BeforeTargets="Build">
<ExampleTaskX86 PlatformTarget="x86" />
<ExampleTaskX64 PlatformTarget="x64" />
</Target>

</Project>
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<TargetFrameworks>net10.0</TargetFrameworks>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,35 @@
<ExampleTaskPath>$([System.IO.Path]::Combine('$(TestProjectFolder)', '$(TargetFramework)', 'ExampleTask.dll'))</ExampleTaskPath>
</PropertyGroup>

<UsingTask TaskName="ExampleTask" AssemblyFile="$(ExampleTaskPath)" Runtime="NET"/>
<UsingTask TaskName="ExampleTask"
AssemblyFile="$(ExampleTaskPath)"
Runtime="NET"/>

<UsingTask TaskName="Microsoft.Build.Tasks.Message"
AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll"
TaskFactory="TaskHostFactory" />

<UsingTask TaskName="Microsoft.Build.Tasks.FindInList"
AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll" />

<ItemGroup>
<MyItems Include="Apple" />
<MyItems Include="Banana" />
<MyItems Include="Cherry" />
<MyItems Include="Date" />
</ItemGroup>

<Target Name="TestTask" BeforeTargets="Build">
<ExampleTask />

<Message Text="Hello TEST FROM MESSAGE" Importance="high" />

<FindInList List="@(MyItems)"
ItemSpecToFind="Banana"
CaseSensitive="false">
<Output TaskParameter="ItemFound" PropertyName="FoundItem"/>
</FindInList>
<Message Text="Found item: $(FoundItem)" Importance="high" Condition="'$(FoundItem)' != ''" />
</Target>

</Project>
2 changes: 1 addition & 1 deletion src/Build/BackEnd/TaskExecutionHost/TaskExecutionHost.cs
Original file line number Diff line number Diff line change
Expand Up @@ -425,7 +425,7 @@ public bool SetTaskParameters(IDictionary<string, (string, ElementLocation)> par
}
}

if (this.TaskInstance is IIncrementalTask incrementalTask)
if (TaskInstance is IIncrementalTask incrementalTask)
{
incrementalTask.FailIfNotIncremental = _buildComponentHost.BuildParameters.Question;
}
Expand Down
Loading