Skip to content

Commit c415697

Browse files
authored
Add a fallback path when launching the BuildHost (#78826)
Resolves #78824
2 parents f111c95 + 9d0162e commit c415697

File tree

2 files changed

+31
-9
lines changed

2 files changed

+31
-9
lines changed

src/Workspaces/MSBuild/Core/MSBuild/BuildHostProcessManager.cs

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ internal sealed class BuildHostProcessManager : IAsyncDisposable
3030
private readonly SemaphoreSlim _gate = new(initialCount: 1);
3131
private readonly Dictionary<BuildHostProcessKind, BuildHostProcess> _processes = [];
3232

33+
private static string MSBuildWorkspaceDirectory => Path.GetDirectoryName(typeof(BuildHostProcessManager).Assembly.Location)!;
34+
private static bool IsLoadedFromNuGetPackage => File.Exists(Path.Combine(MSBuildWorkspaceDirectory, "..", "..", "microsoft.codeanalysis.workspaces.msbuild.nuspec"));
35+
3336
public BuildHostProcessManager(ImmutableDictionary<string, string>? globalMSBuildProperties = null, IBinLogPathProvider? binaryLogPathProvider = null, ILoggerFactory? loggerFactory = null)
3437
{
3538
_globalMSBuildProperties = globalMSBuildProperties ?? ImmutableDictionary<string, string>.Empty;
@@ -186,10 +189,7 @@ private ProcessStartInfo CreateDotNetCoreBuildHostStartInfo(string pipeName)
186189

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

195195
private ProcessStartInfo CreateDotNetFrameworkBuildHostStartInfo(string pipeName)
@@ -221,16 +221,34 @@ private ProcessStartInfo CreateMonoBuildHostStartInfo(string pipeName)
221221

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

230-
private static void AssertBuildHostExists(string buildHostPath)
227+
private static string GetBuildHostPath(string contentFolderName, string assemblyName)
231228
{
229+
// Possible BuildHost paths are relative to where the Workspaces.MSBuild assembly was loaded.
230+
string buildHostPath;
231+
232+
if (IsLoadedFromNuGetPackage)
233+
{
234+
// When Workspaces.MSBuild is loaded from the NuGet package (as is the case in .NET Interactive, NCrunch, and possibly other use cases)
235+
// the Build host is deployed under the contentFiles folder.
236+
//
237+
// Workspaces.MSBuild.dll Path - .nuget/packages/microsoft.codeanalysis.workspaces.msbuild/{version}/lib/{tfm}/Microsoft.CodeAnalysis.Workspaces.MSBuild.dll
238+
// MSBuild.BuildHost.dll Path - .nuget/packages/microsoft.codeanalysis.workspaces.msbuild/{version}/contentFiles/any/any/{contentFolderName}/{assemblyName}
239+
240+
buildHostPath = Path.GetFullPath(Path.Combine(MSBuildWorkspaceDirectory, "..", "..", "contentFiles", "any", "any", contentFolderName, assemblyName));
241+
}
242+
else
243+
{
244+
// When Workspaces.MSBuild is deployed as part of an application the build host is deployed as a content folder next to the application.
245+
buildHostPath = Path.Combine(MSBuildWorkspaceDirectory, contentFolderName, assemblyName);
246+
}
247+
232248
if (!File.Exists(buildHostPath))
233249
throw new Exception(string.Format(WorkspaceMSBuildResources.The_build_host_could_not_be_found_at_0, buildHostPath));
250+
251+
return buildHostPath;
234252
}
235253

236254
private void AppendBuildHostCommandLineArgumentsConfigureProcess(ProcessStartInfo processStartInfo, string pipeName)

src/Workspaces/MSBuild/Core/Microsoft.CodeAnalysis.Workspaces.MSBuild.csproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@
9797
<ItemGroup Condition="'$(DotNetBuildSourceOnly)' != 'true'">
9898
<_NetFrameworkBuildHostProjectReference Include="..\..\..\Workspaces\MSBuild\BuildHost\Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.csproj">
9999
<TargetFramework>net472</TargetFramework>
100+
<!-- NOTE: Update the `BuildHostProcessManager.GetDotNetFrameworkBuildHostPath` method if ContentFolderName changes. -->
100101
<ContentFolderName>BuildHost-net472</ContentFolderName>
101102
</_NetFrameworkBuildHostProjectReference>
102103
</ItemGroup>
@@ -105,6 +106,7 @@
105106
<ItemGroup>
106107
<_NetFrameworkBuildHostProjectReference Include="..\..\..\Workspaces\MSBuild\BuildHost\Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.csproj">
107108
<TargetFramework>$(NetRoslynBuildHostNetCoreVersion)</TargetFramework>
109+
<!-- NOTE: Update the `BuildHostProcessManager.GetNetCoreBuildHostPath` method if ContentFolderName changes. -->
108110
<ContentFolderName>BuildHost-netcore</ContentFolderName>
109111
</_NetFrameworkBuildHostProjectReference>
110112
</ItemGroup>
@@ -118,6 +120,8 @@
118120
<!-- We're setting both TargetPath and PackagePath here, the former when this is used in a regular build to deploy and the latter for
119121
when this called during pack. By putting the PackagePath in any/any, we only have to deploy this once rather than per TFM.
120122
Similarly, we set CopyToOutputDirectory for the regular build and PackageCopyToPutput for the packaging process. -->
123+
124+
<!-- NOTE: Update the `BuildHostProcessManager.GetBuildHostPath` method if the PackagePath changes. -->
121125
<Content Include="%(NetFrameworkBuildHostAssets.Identity)"
122126
Condition="'%(NetFrameworkBuildHostAssets.TargetPath)' != '' and '%(NetFrameworkBuildHostAssets.Extension)' != '.xml'"
123127
TargetPath="$([System.IO.Path]::Combine('%(NetFrameworkBuildHostAssets.ContentFolderName)', '%(NetFrameworkBuildHostAssets.TargetPath)'))"

0 commit comments

Comments
 (0)