Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
36 changes: 27 additions & 9 deletions src/Workspaces/MSBuild/Core/MSBuild/BuildHostProcessManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ internal sealed class BuildHostProcessManager : IAsyncDisposable
private readonly SemaphoreSlim _gate = new(initialCount: 1);
private readonly Dictionary<BuildHostProcessKind, BuildHostProcess> _processes = [];

private static string MSBuildWorkspaceDirectory => Path.GetDirectoryName(typeof(BuildHostProcessManager).Assembly.Location)!;
private static bool IsLoadedFromNuGetPackage => File.Exists(Path.Combine(MSBuildWorkspaceDirectory, "..", "..", "microsoft.codeanalysis.workspaces.msbuild.nuspec"));

public BuildHostProcessManager(ImmutableDictionary<string, string>? globalMSBuildProperties = null, IBinLogPathProvider? binaryLogPathProvider = null, ILoggerFactory? loggerFactory = null)
{
_globalMSBuildProperties = globalMSBuildProperties ?? ImmutableDictionary<string, string>.Empty;
Expand Down Expand Up @@ -186,10 +189,7 @@ private ProcessStartInfo CreateDotNetCoreBuildHostStartInfo(string pipeName)

internal static string GetNetCoreBuildHostPath()
{
// The .NET Core build host is deployed as a content folder next to the application into the BuildHost-netcore path
var buildHostPath = Path.Combine(Path.GetDirectoryName(typeof(BuildHostProcessManager).Assembly.Location)!, "BuildHost-netcore", "Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.dll");
AssertBuildHostExists(buildHostPath);
return buildHostPath;
return GetBuildHostPath("BuildHost-netcore", "Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.dll");
}

private ProcessStartInfo CreateDotNetFrameworkBuildHostStartInfo(string pipeName)
Expand Down Expand Up @@ -221,16 +221,34 @@ private ProcessStartInfo CreateMonoBuildHostStartInfo(string pipeName)

private static string GetDotNetFrameworkBuildHostPath()
{
// The .NET Framework build host is deployed as a content folder next to the application into the BuildHost-net472 path
var netFrameworkBuildHost = Path.Combine(Path.GetDirectoryName(typeof(BuildHostProcessManager).Assembly.Location)!, "BuildHost-net472", "Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.exe");
AssertBuildHostExists(netFrameworkBuildHost);
return netFrameworkBuildHost;
return GetBuildHostPath("BuildHost-net472", "Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.exe");
}

private static void AssertBuildHostExists(string buildHostPath)
private static string GetBuildHostPath(string contentFolderName, string assemblyName)
{
// Possible BuildHost paths are relative to where the Workspaces.MSBuild assembly was loaded.
string buildHostPath;

if (IsLoadedFromNuGetPackage)
{
// When Workspaces.MSBuild is loaded from the NuGet package (as is the case in .NET Interactive, NCrunch, and possibly other use cases)
// the Build host is deployed under the contentFiles folder.
//
// Workspaces.MSBuild.dll Path - .nuget/packages/microsoft.codeanalysis.workspaces.msbuild/{version}/lib/{tfm}/Microsoft.CodeAnalysis.Workspaces.MSBuild.dll
// MSBuild.BuildHost.dll Path - .nuget/packages/microsoft.codeanalysis.workspaces.msbuild/{version}/contentFiles/any/any/{contentFolderName}/{assemblyName}

buildHostPath = Path.GetFullPath(Path.Combine(MSBuildWorkspaceDirectory, "..", "..", "contentFiles", "any", "any", contentFolderName, assemblyName));
}
else
{
// When Workspaces.MSBuild is deployed as part of an application the build host is deployed as a content folder next to the application.
buildHostPath = Path.Combine(MSBuildWorkspaceDirectory, contentFolderName, assemblyName);
}

if (!File.Exists(buildHostPath))
throw new Exception(string.Format(WorkspaceMSBuildResources.The_build_host_could_not_be_found_at_0, buildHostPath));

return buildHostPath;
}

private void AppendBuildHostCommandLineArgumentsConfigureProcess(ProcessStartInfo processStartInfo, string pipeName)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@
<ItemGroup Condition="'$(DotNetBuildSourceOnly)' != 'true'">
<_NetFrameworkBuildHostProjectReference Include="..\..\..\Workspaces\MSBuild\BuildHost\Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.csproj">
<TargetFramework>net472</TargetFramework>
<!-- NOTE: Update the `BuildHostProcessManager.GetDotNetFrameworkBuildHostPath` method if ContentFolderName changes. -->
<ContentFolderName>BuildHost-net472</ContentFolderName>
</_NetFrameworkBuildHostProjectReference>
</ItemGroup>
Expand All @@ -105,6 +106,7 @@
<ItemGroup>
<_NetFrameworkBuildHostProjectReference Include="..\..\..\Workspaces\MSBuild\BuildHost\Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.csproj">
<TargetFramework>$(NetRoslynBuildHostNetCoreVersion)</TargetFramework>
<!-- NOTE: Update the `BuildHostProcessManager.GetNetCoreBuildHostPath` method if ContentFolderName changes. -->
<ContentFolderName>BuildHost-netcore</ContentFolderName>
</_NetFrameworkBuildHostProjectReference>
</ItemGroup>
Expand All @@ -118,6 +120,8 @@
<!-- We're setting both TargetPath and PackagePath here, the former when this is used in a regular build to deploy and the latter for
when this called during pack. By putting the PackagePath in any/any, we only have to deploy this once rather than per TFM.
Similarly, we set CopyToOutputDirectory for the regular build and PackageCopyToPutput for the packaging process. -->

<!-- NOTE: Update the `BuildHostProcessManager.GetBuildHostPath` method if the PackagePath changes. -->
<Content Include="%(NetFrameworkBuildHostAssets.Identity)"
Condition="'%(NetFrameworkBuildHostAssets.TargetPath)' != '' and '%(NetFrameworkBuildHostAssets.Extension)' != '.xml'"
TargetPath="$([System.IO.Path]::Combine('%(NetFrameworkBuildHostAssets.ContentFolderName)', '%(NetFrameworkBuildHostAssets.TargetPath)'))"
Expand Down
Loading