Skip to content

Resolve net task host params from the project properties #11543

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 29 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
f0a46e4
draft for dotnet host support
YuliiaKovalova Feb 4, 2025
90a63c1
cleanup
YuliiaKovalova Feb 4, 2025
e0db3b1
more changes
YuliiaKovalova Feb 4, 2025
9b892e9
handle issue with net task host communication
YuliiaKovalova Feb 5, 2025
a6f8bf9
add new runtime value to xsd
YuliiaKovalova Feb 5, 2025
f1781fb
add comment
YuliiaKovalova Feb 5, 2025
65691df
adjust net task host implementation
YuliiaKovalova Feb 17, 2025
be15f3f
Merge branch 'dotnet:main' into dev/ykovalova/support_launching_net_t…
YuliiaKovalova Feb 17, 2025
0509411
Merge branch 'main' into dev/ykovalova/support_launching_net_taskhost
YuliiaKovalova Mar 3, 2025
bae84bd
temp
YuliiaKovalova Mar 4, 2025
33fcee0
resolve net task host params from the project properties
YuliiaKovalova Mar 5, 2025
01baf54
Update BootstrapSdkVersion in Versions.props
YuliiaKovalova Mar 5, 2025
f6890ea
add null ref check
YuliiaKovalova Mar 5, 2025
4c21504
add version validation
YuliiaKovalova Mar 6, 2025
20f9302
add packet versioning support
YuliiaKovalova Mar 6, 2025
d34adec
Merge branch 'main' into dev/ykovalova/use_project_props_for_sdk_reso…
YuliiaKovalova Mar 6, 2025
d1d72fa
cleanup TaskHostConfiguration
YuliiaKovalova Mar 6, 2025
76f7d1f
Merge branch 'dev/ykovalova/support_launching_net_taskhost' of https:…
YuliiaKovalova Mar 6, 2025
2d68448
extend version tracking infra
YuliiaKovalova Mar 6, 2025
0764a61
Merge branch 'dev/ykovalova/use_project_props_for_sdk_resolution' of …
YuliiaKovalova Mar 6, 2025
80c7a24
adjust msbuildserver to the packet version extended flag presence
YuliiaKovalova Mar 7, 2025
98324e9
loosen the version check on handshake for taskhost
YuliiaKovalova Mar 7, 2025
e9669a5
loosen the version check for net task host
YuliiaKovalova Mar 7, 2025
2434531
Merge branch 'main' into dev/ykovalova/support_launching_net_taskhost
YuliiaKovalova Apr 3, 2025
c742aa1
fix typo in naming
YuliiaKovalova Apr 3, 2025
a6635cb
Merge branch 'dev/ykovalova/support_launching_net_taskhost' of https:…
YuliiaKovalova Apr 3, 2025
9e17694
fix conflicts
YuliiaKovalova Apr 3, 2025
0061add
merge
YuliiaKovalova Apr 7, 2025
13a68ba
fix merge
YuliiaKovalova Apr 7, 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
4 changes: 2 additions & 2 deletions src/Build.UnitTests/BackEnd/BuildManager_Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1725,7 +1725,7 @@ public void CancelledBuildWithDelay40_WithThreatSwap()
/// A canceled build which waits for the task to get started before canceling. Because it is a 12.0 task, we should
/// cancel the task and exit out after a short period wherein we wait for the task to exit cleanly.
/// </summary>
[Fact]
[WindowsFullFrameworkOnlyFact]
public void CancelledBuildInTaskHostWithDelay40()
{
string contents = CleanupFileContents(@$"
Expand Down Expand Up @@ -4384,7 +4384,7 @@ public override bool Execute()
}
}

[Theory]
[WindowsFullFrameworkOnlyTheory]
[InlineData("", false)] // regular task host, input logging disabled
[InlineData("", true)] // regular task host, input logging enabled
[InlineData("TaskHostFactory", false)] // OOP task host, input logging disabled
Expand Down
17 changes: 17 additions & 0 deletions src/Build.UnitTests/BackEnd/TaskHostConfiguration_Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ public void ConstructorWithNullName()
Assert.Throws<InternalErrorException>(() =>
{
TaskHostConfiguration config = new TaskHostConfiguration(
runtime: "TaskHost",
nodeId: 1,
startupDirectory: Directory.GetCurrentDirectory(),
buildProcessEnvironment: null,
Expand Down Expand Up @@ -73,6 +74,7 @@ public void ConstructorWithEmptyName()
Assert.Throws<InternalErrorException>(() =>
{
TaskHostConfiguration config = new TaskHostConfiguration(
runtime: "TaskHost",
nodeId: 1,
startupDirectory: Directory.GetCurrentDirectory(),
buildProcessEnvironment: null,
Expand Down Expand Up @@ -108,6 +110,7 @@ public void ConstructorWithNullLocation()
Assert.Throws<InternalErrorException>(() =>
{
TaskHostConfiguration config = new TaskHostConfiguration(
runtime: "TaskHost",
nodeId: 1,
startupDirectory: Directory.GetCurrentDirectory(),
buildProcessEnvironment: null,
Expand Down Expand Up @@ -145,6 +148,7 @@ public void ConstructorWithEmptyLocation()
Assert.Throws<InternalErrorException>(() =>
{
TaskHostConfiguration config = new TaskHostConfiguration(
runtime: "TaskHost",
nodeId: 1,
startupDirectory: Directory.GetCurrentDirectory(),
buildProcessEnvironment: null,
Expand Down Expand Up @@ -180,6 +184,7 @@ public void ConstructorWithEmptyLocation()
public void TestValidConstructors()
{
TaskHostConfiguration config = new TaskHostConfiguration(
runtime: "TaskHost",
nodeId: 1,
startupDirectory: Directory.GetCurrentDirectory(),
buildProcessEnvironment: null,
Expand All @@ -206,6 +211,7 @@ public void TestValidConstructors()
warningsAsMessages: null);

TaskHostConfiguration config2 = new TaskHostConfiguration(
runtime: "TaskHost",
nodeId: 1,
startupDirectory: Directory.GetCurrentDirectory(),
buildProcessEnvironment: null,
Expand Down Expand Up @@ -233,6 +239,7 @@ public void TestValidConstructors()

IDictionary<string, object> parameters = new Dictionary<string, object>();
TaskHostConfiguration config3 = new TaskHostConfiguration(
runtime: "TaskHost",
nodeId: 1,
startupDirectory: Directory.GetCurrentDirectory(),
buildProcessEnvironment: null,
Expand Down Expand Up @@ -265,6 +272,7 @@ public void TestValidConstructors()
parameters2.Add("ItemArray", new ITaskItem[] { new TaskItem("DEF"), new TaskItem("GHI"), new TaskItem("JKL") });

TaskHostConfiguration config4 = new TaskHostConfiguration(
runtime: "TaskHost",
nodeId: 1,
startupDirectory: Directory.GetCurrentDirectory(),
buildProcessEnvironment: null,
Expand Down Expand Up @@ -297,6 +305,7 @@ public void TestValidConstructors()
WarningsAsErrors.Add("MSB1237");

TaskHostConfiguration config5 = new TaskHostConfiguration(
runtime: "TaskHost",
nodeId: 1,
startupDirectory: Directory.GetCurrentDirectory(),
buildProcessEnvironment: null,
Expand Down Expand Up @@ -336,6 +345,7 @@ public void TestTranslationWithNullDictionary()
};

TaskHostConfiguration config = new TaskHostConfiguration(
runtime: "TaskHost",
nodeId: 1,
startupDirectory: Directory.GetCurrentDirectory(),
buildProcessEnvironment: null,
Expand Down Expand Up @@ -387,6 +397,7 @@ public void TestTranslationWithAppDomainSetup(byte[] configBytes)
AppDomainSetup setup = new AppDomainSetup();

TaskHostConfiguration config = new TaskHostConfiguration(
runtime: "TaskHost",
nodeId: 1,
startupDirectory: Directory.GetCurrentDirectory(),
buildProcessEnvironment: null,
Expand Down Expand Up @@ -433,6 +444,7 @@ public void TestTranslationWithAppDomainSetup(byte[] configBytes)
public void TestTranslationWithEmptyDictionary()
{
TaskHostConfiguration config = new TaskHostConfiguration(
runtime: "TaskHost",
nodeId: 1,
startupDirectory: Directory.GetCurrentDirectory(),
buildProcessEnvironment: null,
Expand Down Expand Up @@ -484,6 +496,7 @@ public void TestTranslationWithValueTypesInDictionary()
parameters.Add("Text", "Foo");
parameters.Add("BoolValue", false);
TaskHostConfiguration config = new TaskHostConfiguration(
runtime: "TaskHost",
nodeId: 1,
startupDirectory: Directory.GetCurrentDirectory(),
buildProcessEnvironment: null,
Expand Down Expand Up @@ -533,6 +546,7 @@ public void TestTranslationWithITaskItemInDictionary()
IDictionary<string, object> parameters = new Dictionary<string, object>();
parameters.Add("TaskItemValue", new TaskItem("Foo"));
TaskHostConfiguration config = new TaskHostConfiguration(
runtime: "TaskHost",
nodeId: 1,
startupDirectory: Directory.GetCurrentDirectory(),
buildProcessEnvironment: null,
Expand Down Expand Up @@ -581,6 +595,7 @@ public void TestTranslationWithITaskItemArrayInDictionary()
IDictionary<string, object> parameters = new Dictionary<string, object>();
parameters.Add("TaskItemArrayValue", new ITaskItem[] { new TaskItem("Foo"), new TaskItem("Baz") });
TaskHostConfiguration config = new TaskHostConfiguration(
runtime: "TaskHost",
nodeId: 1,
startupDirectory: Directory.GetCurrentDirectory(),
buildProcessEnvironment: null,
Expand Down Expand Up @@ -636,6 +651,7 @@ public void TestTranslationWithWarningsAsErrors()
WarningsAsErrors.Add("MSB1236");
WarningsAsErrors.Add("MSB1237");
TaskHostConfiguration config = new TaskHostConfiguration(
runtime: "TaskHost",
nodeId: 1,
startupDirectory: Directory.GetCurrentDirectory(),
buildProcessEnvironment: null,
Expand Down Expand Up @@ -686,6 +702,7 @@ public void TestTranslationWithWarningsAsMessages()
WarningsAsMessages.Add("MSB1236");
WarningsAsMessages.Add("MSB1237");
TaskHostConfiguration config = new TaskHostConfiguration(
runtime: "TaskHost",
nodeId: 1,
startupDirectory: Directory.GetCurrentDirectory(),
buildProcessEnvironment: null,
Expand Down
14 changes: 7 additions & 7 deletions src/Build.UnitTests/BackEnd/TaskHostFactory_Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@
using System;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using Microsoft.Build.Execution;
using Microsoft.Build.Framework;
using Microsoft.Build.UnitTests;
using Microsoft.Build.UnitTests.BackEnd;

using Microsoft.Build.UnitTests.Shared;
using Microsoft.VisualStudio.TestPlatform.Utilities;
using Shouldly;
using Xunit;
using Xunit.Abstractions;
Expand All @@ -21,12 +23,9 @@ public sealed class TaskHostFactory_Tests
{
private ITestOutputHelper _output;

public TaskHostFactory_Tests(ITestOutputHelper testOutputHelper)
{
_output = testOutputHelper;
}
public TaskHostFactory_Tests(ITestOutputHelper testOutputHelper) => _output = testOutputHelper;

[Fact]
[WindowsFullFrameworkOnlyFact]
public void TaskNodesDieAfterBuild()
{
using (TestEnvironment env = TestEnvironment.Create())
Expand All @@ -40,6 +39,7 @@ public void TaskNodesDieAfterBuild()
</ProcessIdTask>
</Target>
</Project>";

TransientTestFile project = env.CreateFile("testProject.csproj", pidTaskProject);
ProjectInstance projectInstance = new(project.Path);
projectInstance.Build().ShouldBeTrue();
Expand All @@ -60,7 +60,7 @@ public void TaskNodesDieAfterBuild()
}
}

[Fact]
[WindowsFullFrameworkOnlyFact]
private void VariousParameterTypesCanBeTransmittedToAndReceivedFromTaskHost()
{
using TestEnvironment env = TestEnvironment.Create(_output);
Expand Down
6 changes: 3 additions & 3 deletions src/Build.UnitTests/EscapingInProjects_Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ public void SemicolonInPropertyPassedIntoStringParam()
/// Make sure I can define a property with escaped characters and pass it into
/// a string parameter of a task, in this case the Message task.
/// </summary>
[Fact]
[WindowsFullFrameworkOnlyFact]
public void SemicolonInPropertyPassedIntoStringParam_UsingTaskHost()
{
MockLogger logger = Helpers.BuildProjectWithNewOMExpectSuccess(@"
Expand Down Expand Up @@ -603,7 +603,7 @@ public void ItemTransformContainingSemicolon()
/// Do an item transform, where the transform expression contains an unescaped semicolon as well
/// as an escaped percent sign.
/// </summary>
[Fact]
[WindowsFullFrameworkOnlyFact]
public void ItemTransformContainingSemicolon_InTaskHost()
{
MockLogger logger = Helpers.BuildProjectWithNewOMExpectSuccess(@"
Expand Down Expand Up @@ -730,7 +730,7 @@ public void EscapedWildcardsShouldNotBeExpanded()
/// If %2A (escaped '*') or %3F (escaped '?') is in an item's Include, it should be treated
/// literally, not as a wildcard
/// </summary>
[Fact]
[WindowsFullFrameworkOnlyFact]
public void EscapedWildcardsShouldNotBeExpanded_InTaskHost()
{
MockLogger logger = new();
Expand Down
4 changes: 2 additions & 2 deletions src/Build.UnitTests/Instance/TaskItem_Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@ public void Escaping1()
/// <summary>
/// Flushing an item through a task run in the task host also should not mess up special characters on the metadata.
/// </summary>
[Fact]
[WindowsFullFrameworkOnlyFact]
public void Escaping2()
{
string content = ObjectModelHelpers.CleanupFileContents(@"
Expand Down Expand Up @@ -342,7 +342,7 @@ public void Escaping2()
/// <summary>
/// Flushing an item through a task run in the task host also should not mess up the escaping of the itemspec either.
/// </summary>
[Fact]
[WindowsFullFrameworkOnlyFact]
public void Escaping3()
{
string content = ObjectModelHelpers.CleanupFileContents(@"
Expand Down
4 changes: 2 additions & 2 deletions src/Build/BackEnd/Client/MSBuildClientPacketPump.cs
Original file line number Diff line number Diff line change
Expand Up @@ -203,8 +203,8 @@ private void RunReadLoop(Stream localStream, ManualResetEvent localPacketPumpShu
bool continueReading = true;
do
{
// Ordering of the wait handles is important. The first signalled wait handle in the array
// will be returned by WaitAny if multiple wait handles are signalled. We prefer to have the
// Ordering of the wait handles is important. The first signaled wait handle in the array
// will be returned by WaitAny if multiple wait handles are signaled. We prefer to have the
// terminate event triggered so that we cannot get into a situation where packets are being
// spammed to the client and it never gets an opportunity to shutdown.
WaitHandle[] handles =
Expand Down
4 changes: 2 additions & 2 deletions src/Build/BackEnd/Components/Communications/NodeLauncher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,12 @@ public void ShutdownComponent()
public Process Start(string msbuildLocation, string commandLineArgs, int nodeId)
{
// Disable MSBuild server for a child process.
// In case of starting msbuild server it prevents an infinite recurson. In case of starting msbuild node we also do not want this variable to be set.
// In case of starting msbuild server it prevents an infinite recursion. In case of starting msbuild node we also do not want this variable to be set.
return DisableMSBuildServer(() => StartInternal(msbuildLocation, commandLineArgs));
}

/// <summary>
/// Creates a new MSBuild process
/// Creates new MSBuild or dotnet process.
/// </summary>
private Process StartInternal(string msbuildLocation, string commandLineArgs)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,8 @@ protected void ShutdownAllNodes(bool nodeReuse, NodeContextTerminateDelegate ter
/// <summary>
/// Finds or creates a child processes which can act as a node.
/// </summary>
protected IList<NodeContext> GetNodes(string msbuildLocation,
protected IList<NodeContext> GetNodes(
string msbuildLocation,
string commandLineArgs,
int nextNodeId,
INodePacketFactory factory,
Expand Down Expand Up @@ -335,6 +336,7 @@ bool StartNewNode(int nodeId)
// Create the node process
INodeLauncher nodeLauncher = (INodeLauncher)_componentHost.GetComponent(BuildComponentType.NodeLauncher);
Process msbuildProcess = nodeLauncher.Start(msbuildLocation, commandLineArgs, nodeId);

_processesToIgnore.TryAdd(GetProcessesToIgnoreKey(hostHandshake, msbuildProcess.Id), default);

// Note, when running under IMAGEFILEEXECUTIONOPTIONS registry key to debug, the process ID
Expand Down Expand Up @@ -397,7 +399,7 @@ void CreateNodeContext(int nodeId, Process nodeToReuse, Stream nodeStream)
{
if (String.IsNullOrEmpty(msbuildLocation))
{
msbuildLocation = "MSBuild.exe";
msbuildLocation = Constants.MSBuildExecutableName;
}

var expectedProcessName = Path.GetFileNameWithoutExtension(CurrentHost.GetCurrentHost() ?? msbuildLocation);
Expand Down Expand Up @@ -507,11 +509,11 @@ internal static void ConnectToPipeStream(NamedPipeClientStream nodeStream, strin
}
#endif

int[] handshakeComponents = handshake.RetrieveHandshakeComponents();
KeyValuePair<string, int>[] handshakeComponents = handshake.RetrieveHandshakeComponents();
for (int i = 0; i < handshakeComponents.Length; i++)
{
CommunicationsUtilities.Trace("Writing handshake part {0} ({1}) to pipe {2}", i, handshakeComponents[i], pipeName);
nodeStream.WriteIntForHandshake(handshakeComponents[i]);
nodeStream.WriteIntForHandshake(handshakeComponents[i].Value);
}

// This indicates that we have finished all the parts of our handshake; hopefully the endpoint has as well.
Expand Down Expand Up @@ -753,13 +755,20 @@ static async Task SendDataCoreAsync(Task _, object state)
// clear the buffer but keep the underlying capacity to avoid reallocations
writeStream.SetLength(0);

ITranslator writeTranslator = BinaryTranslator.GetWriteTranslator(writeStream);
NodePacketType packetType = packet.Type;
ITranslator writeTranslator = BinaryTranslator.GetWriteTranslator(writeStream, PacketTypeExtensions.PacketVersion);
try
{
writeStream.WriteByte((byte)packet.Type);
// Write packet type with extended header.
byte rawPackageType = PacketTypeExtensions.CreateExtendedHeaderType(packetType);
writeStream.WriteByte(rawPackageType);

// Pad for the packet length
WriteInt32(writeStream, 0);

// Write extended header with version
PacketTypeExtensions.WriteVersion(writeStream, PacketTypeExtensions.PacketVersion);

packet.Translate(writeTranslator);

int writeStreamLength = (int)writeStream.Position;
Expand Down
Loading