msbuild: run manifest install only once (#51348)

Co-authored-by: Leander Schulten <Leander.Schulten@tetys.de>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
autoantwort 2026-05-07 02:58:01 +02:00 committed by GitHub
parent de03680510
commit d7ccba87c3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 162 additions and 13 deletions

View File

@ -0,0 +1,59 @@
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!-- Define the GetGlobalProperties task for retrieving the Global Properties from the current MSBuild engine.
The task has a single output parameter - GlobalPropertyNames - which is a semi-colon delimited list of the global
properties of the current MSBuild engine. -->
<UsingTask TaskName="GetGlobalProperties" TaskFactory="RoslynCodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll">
<ParameterGroup>
<GlobalPropertyNames ParameterType="System.String" Output="true" />
</ParameterGroup>
<Task>
<Reference Include="Microsoft.Build.Tasks.Core" />
<Code Type="Class" Language="cs">
<![CDATA[
#nullable enable
using System;
using System.Collections.Generic;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
/// <summary>
/// An MSBuild task that retrieves the MSBuild Global Properties.
/// </summary>
public class GetGlobalProperties : Task
{
/// <summary>
/// Initializes a new instance of the <see cref="GetGlobalProperties"/> class.
/// </summary>
public GetGlobalProperties()
{
}
/// <summary>
/// Executes the build task.
/// </summary>
/// <returns>True.</returns>
public override bool Execute()
{
IReadOnlyDictionary<string,string>? globalProperties = this.BuildEngine6?.GetGlobalProperties();
if (globalProperties is null)
{
Log.LogError("Unable to retrieve GlobalProperties");
return false;
}
this.GlobalPropertyNames = string.Join(";", globalProperties.Keys);
return true;
}
/// <summary>
/// Gets or sets the GlobalPropertyNames parameter.
/// </summary>
[Output]
public string GlobalPropertyNames { get; private set; } = string.Empty;
}
]]>
</Code>
</Task>
</UsingTask>
</Project>

View File

@ -0,0 +1,35 @@
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<UsingTask TaskName="GetVcpkgEnvVars" TaskFactory="RoslynCodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll">
<ParameterGroup>
<VcpkgEnvVars Output="true" ParameterType="System.String" />
</ParameterGroup>
<Task>
<Using Namespace="System" />
<Using Namespace="System.Text" />
<Using Namespace="System.Collections" />
<Code Type="Fragment" Language="cs">
<![CDATA[
var sb = new StringBuilder();
foreach (DictionaryEntry de in Environment.GetEnvironmentVariables())
{
string key = de.Key.ToString();
// Filter for both prefixes
if (key.StartsWith("VCPKG_", StringComparison.OrdinalIgnoreCase) ||
key.StartsWith("X_VCPKG_", StringComparison.OrdinalIgnoreCase))
{
string val = de.Value.ToString();
// To handle semicolons inside the value, we escape them
// so MSBuild doesn't split the value into a new property.
val = val.Replace(";", "%3B");
if (sb.Length > 0) sb.Append("____");
sb.Append(key + "=" + val);
}
}
VcpkgEnvVars = sb.ToString();
]]>
</Code>
</Task>
</UsingTask>
</Project>

View File

@ -0,0 +1,20 @@
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildThisFileDirectory)\RestoreEnvVars.task" />
<Target Name="VcpkgInstallImplementation">
<Message Text="Installing vcpkg dependencies to $(_ZVcpkgInstalledDir)" Importance="High" />
<RestoreEnvVars Condition="'$(_ZVcpkgEnvVars)' != ''" VcpkgEnvVars="$(_ZVcpkgEnvVars)" />
<MakeDir Directories="$(_ZVcpkgInstalledDir)" />
<Message Text="%22$(_ZVcpkgExecutable)%22 install $(_ZVcpkgHostTripletParameter) --x-wait-for-lock --triplet %22$(VcpkgTriplet)%22 --vcpkg-root %22$(_ZVcpkgRoot)\%22 %22--x-manifest-root=$(_ZVcpkgManifestRoot)\%22 %22--x-install-root=$(_ZVcpkgInstalledDir)\%22 $(VcpkgAdditionalInstallOptions)"
Importance="High" />
<Exec Command="%22$(_ZVcpkgExecutable)%22 install $(_ZVcpkgHostTripletParameter) --x-wait-for-lock --triplet %22$(VcpkgTriplet)%22 --vcpkg-root %22$(_ZVcpkgRoot)\%22 %22--x-manifest-root=$(_ZVcpkgManifestRoot)\%22 %22--x-install-root=$(_ZVcpkgInstalledDir)\%22 $(VcpkgAdditionalInstallOptions)"
StandardOutputImportance="High"
StandardErrorImportance="High"
UseUtf8Encoding="Always"
StdOutEncoding="utf-8"
StdErrEncoding="utf-8"
UseCommandProcessor="false"
/>
<Touch Files="$(_ZVcpkgMSBuildStampFile)" AlwaysCreate="true" />
</Target>
</Project>

View File

@ -0,0 +1,28 @@
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<UsingTask TaskName="RestoreEnvVars" TaskFactory="RoslynCodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll">
<ParameterGroup>
<VcpkgEnvVars ParameterType="System.String" Required="true" />
</ParameterGroup>
<Task>
<Code Type="Fragment" Language="cs">
<![CDATA[
if (string.IsNullOrEmpty(VcpkgEnvVars)) return true;
var pairs = VcpkgEnvVars.Split( new[] { "____" }, StringSplitOptions.None);
foreach (var pair in pairs)
{
var parts = pair.Split(new[] { '=' }, 2);
if (parts.Length == 2)
{
// Unescape the %3B back to ;
string key = parts[0];
string val = parts[1].Replace("%3B", ";");
Environment.SetEnvironmentVariable(key, val);
Log.LogMessage(MessageImportance.Low, "Restored Env Var: {0}", key);
}
}
]]>
</Code>
</Task>
</UsingTask>
</Project>

View File

@ -168,31 +168,38 @@
<_ZVcpkgInstallManifestDependenciesInputs Include="$(_ZVcpkgConfigurationFileLocation)" Condition="Exists('$(_ZVcpkgConfigurationFileLocation)')"/>
</ItemGroup>
<Import Project="$(MSBuildThisFileDirectory)support\GetVcpkgEnvVars.task"
Condition="'$(VcpkgEnabled)' == 'true' and '$(VcpkgEnableManifest)' == 'true' and '$(VcpkgManifestInstall)' == 'true'"
/>
<Import Project="$(MSBuildThisFileDirectory)support\GetGlobalProperties.task"
Condition="'$(VcpkgEnabled)' == 'true' and '$(VcpkgEnableManifest)' == 'true' and '$(VcpkgManifestInstall)' == 'true'"
/>
<Target Name="VcpkgInstallManifestDependencies" BeforeTargets="ClCompile"
Condition="'$(VcpkgEnabled)' == 'true' and '$(VcpkgEnableManifest)' == 'true' and '$(VcpkgManifestInstall)' == 'true'"
Inputs="@(_ZVcpkgInstallManifestDependenciesInputs)"
Outputs="$(_ZVcpkgMSBuildStampFile)">
<GetGlobalProperties>
<Output TaskParameter="GlobalPropertyNames" PropertyName="_ZVcpkgGlobalPropertyNames" />
</GetGlobalProperties>
<GetVcpkgEnvVars>
<Output TaskParameter="VcpkgEnvVars" PropertyName="_ZVcpkgEnvVars" />
</GetVcpkgEnvVars>
<!-- This is set inside the target because $(TLogLocation) may not be set yet when parsing the .targets on VS2015 -->
<PropertyGroup>
<_ZVcpkgTLogFileLocation>$(TLogLocation)VcpkgInstallManifest$(VcpkgTriplet).$(_ZVcpkgHostTripletSuffix)read.1u.tlog</_ZVcpkgTLogFileLocation>
</PropertyGroup>
<Message Text="Installing vcpkg dependencies to $(_ZVcpkgInstalledDir)" Importance="High" />
<MakeDir Directories="$(_ZVcpkgInstalledDir)" />
<Message Text="%22$(_ZVcpkgExecutable)%22 install $(_ZVcpkgHostTripletParameter) --x-wait-for-lock --triplet %22$(VcpkgTriplet)%22 --vcpkg-root %22$(_ZVcpkgRoot)\%22 %22--x-manifest-root=$(_ZVcpkgManifestRoot)\%22 %22--x-install-root=$(_ZVcpkgInstalledDir)\%22 $(VcpkgAdditionalInstallOptions)"
Importance="High" />
<Exec Command="%22$(_ZVcpkgExecutable)%22 install $(_ZVcpkgHostTripletParameter) --x-wait-for-lock --triplet %22$(VcpkgTriplet)%22 --vcpkg-root %22$(_ZVcpkgRoot)\%22 %22--x-manifest-root=$(_ZVcpkgManifestRoot)\%22 %22--x-install-root=$(_ZVcpkgInstalledDir)\%22 $(VcpkgAdditionalInstallOptions)"
StandardOutputImportance="High"
StandardErrorImportance="High"
UseUtf8Encoding="Always"
StdOutEncoding="utf-8"
StdErrEncoding="utf-8"
UseCommandProcessor="false"
/>
<MSBuild BuildInParallel="true"
Projects="$(MSBuildThisFileDirectory)\support\InstallImplementation.targets"
Targets="VcpkgInstallImplementation"
RemoveProperties="$(_ZVcpkgGlobalPropertyNames)"
Properties="_ZVcpkgMSBuildStampFile=$(_ZVcpkgMSBuildStampFile);_ZVcpkgRoot=$(_ZVcpkgRoot);_ZVcpkgHostTripletSuffix=$(_ZVcpkgHostTripletSuffix);_ZVcpkgInstalledDir=$(_ZVcpkgInstalledDir);_ZVcpkgExecutable=$(_ZVcpkgExecutable);_ZVcpkgHostTripletParameter=$(_ZVcpkgHostTripletParameter);VcpkgTriplet=$(VcpkgTriplet);_ZVcpkgManifestRoot=$(_ZVcpkgManifestRoot);VcpkgAdditionalInstallOptions=$([MSBuild]::Escape($(VcpkgAdditionalInstallOptions)));_ZVcpkgEnvVars=$(_ZVcpkgEnvVars)"
/>
<WriteLinesToFile File="$(_ZVcpkgTLogFileLocation)"
Lines="@(_ZVcpkgInstallManifestDependenciesInputs -> '^%(Identity)')"
Encoding="Unicode"
Overwrite="true"/>
<Touch Files="$(_ZVcpkgMSBuildStampFile)" AlwaysCreate="true" />
<CreateProperty Value="false">
<Output TaskParameter="ValueSetByTask" PropertyName="Link_MinimalRebuildFromTracking" />