From e6c9eb4ce76b91712706749b920f46de4812d540 Mon Sep 17 00:00:00 2001 From: Tyrie Vella Date: Tue, 18 Aug 2026 15:00:25 -0700 Subject: [PATCH 1/4] Require Visual Studio 2026 (v145) for native C++ projects The native VFS projects pinned PlatformToolset v143, which ships only with Visual Studio 2022. Build agents and developer machines that carry Visual Studio 2026 do not have the v143 toolset, so a clean native build fails with "the build tools for v143 cannot be found". Retarget the native projects to the v145 toolset that ships with Visual Studio 2026 (product line 18.x) and update the build provisioning to match: - Set PlatformToolset to v145 in the five native .vcxproj files. - Update .vsconfig to request the v145 build tools component. - Update install-vs-cpp-workload.ps1 to require VS 2026 (18.0+) and to download the VS 2026 Build Tools bootstrapper. - Update the Readme and a stale Build.bat comment. Assisted-by: Claude Opus 4.8 Signed-off-by: Tyrie Vella --- .../scripts/install-vs-cpp-workload.ps1 | 28 +++++++++---------- .vsconfig | 2 +- .../GVFS.NativeTests/GVFS.NativeTests.vcxproj | 4 +-- .../GVFS.PostIndexChangedHook.vcxproj | 4 +-- .../GVFS.ReadObjectHook.vcxproj | 4 +-- .../GVFS.VirtualFileSystemHook.vcxproj | 4 +-- GVFS/GitHooksLoader/GitHooksLoader.vcxproj | 4 +-- Readme.md | 4 +-- scripts/Build.bat | 2 +- 9 files changed, 28 insertions(+), 28 deletions(-) diff --git a/.azure-pipelines/scripts/install-vs-cpp-workload.ps1 b/.azure-pipelines/scripts/install-vs-cpp-workload.ps1 index 9e8e77f993..0a45020427 100644 --- a/.azure-pipelines/scripts/install-vs-cpp-workload.ps1 +++ b/.azure-pipelines/scripts/install-vs-cpp-workload.ps1 @@ -1,20 +1,20 @@ # -# Ensure a Visual Studio 2022 (or newer) install with the "Desktop +# Ensure a Visual Studio 2026 (or newer) install with the "Desktop # development with C++" workload is present on the build agent. # # .NET NativeAOT publishing (used by every product-facing managed VFS for # Git project via PublishAot=true in Directory.Build.props) requires the # C++ build tools from this workload at publish time. The native VFS -# projects also build against the v143 toolset, which ships with VS 2022. +# projects also build against the v145 toolset, which ships with VS 2026. # # This script handles three situations: -# 1. A VS 2022+ install with the C++ workload is already present +# 1. A VS 2026+ install with the C++ workload is already present # -> exit early. -# 2. A VS 2022+ install (any product) is present but the C++ workload +# 2. A VS 2026+ install (any product) is present but the C++ workload # is missing -> modify that install to add it. -# 3. No VS 2022+ install at all -> install VS Build Tools 2022 with -# the VC tools workload. (An older VS install, e.g. VS 2019, is -# ignored here -- we leave it alone and install VS 2022 alongside.) +# 3. No VS 2026+ install at all -> install VS Build Tools 2026 with +# the VC tools workload. (An older VS install, e.g. VS 2022, is +# ignored here -- we leave it alone and install VS 2026 alongside.) # # vswhere.exe is bootstrapped from GitHub if not already on disk. # @@ -39,12 +39,12 @@ $vswherePath = Join-Path $vsInstallerDir 'vswhere.exe' $setupExePath = Join-Path $vsInstallerDir 'setup.exe' $vswhereDownloadUrl = 'https://github.com/microsoft/vswhere/releases/latest/download/vswhere.exe' -$buildToolsDownloadUrl = 'https://aka.ms/vs/17/release/vs_BuildTools.exe' +$buildToolsDownloadUrl = 'https://aka.ms/vs/18/release/vs_BuildTools.exe' -# The native VFS projects build against the v143 toolset, which ships with -# Visual Studio 2022 (product line 17.x). VS 2019 (16.x) carries v142 and -# is not sufficient -- so all vswhere queries below are scoped to 17.0+. -$minVsVersion = '[17.0,)' +# The native VFS projects build against the v145 toolset, which ships with +# Visual Studio 2026 (product line 18.x). VS 2022 (17.x) carries v143 and +# is not sufficient -- so all vswhere queries below are scoped to 18.0+. +$minVsVersion = '[18.0,)' # Either of these workloads provides the C++ build tools we need. # Microsoft.VisualStudio.Workload.NativeDesktop = "Desktop development with C++" (Community/Pro/Enterprise). @@ -132,9 +132,9 @@ if ($existing) { # --- Find any VS install (regardless of workloads) --- $install = Find-VsInstall -VswhereExe $vswhereExe -# --- If no VS 2022+ install at all, install VS Build Tools 2022 with the VC workload --- +# --- If no VS 2026+ install at all, install VS Build Tools 2026 with the VC workload --- if (-not $install) { - Write-Host "No Visual Studio 2022 (or newer) installation found; installing VS Build Tools 2022 with the C++ workload..." + Write-Host "No Visual Studio 2026 (or newer) installation found; installing VS Build Tools 2026 with the C++ workload..." $bootstrapper = Join-Path $env:TEMP 'vs_BuildTools.exe' Write-Host "Downloading VS Build Tools bootstrapper from $buildToolsDownloadUrl..." Invoke-WebRequest -Uri $buildToolsDownloadUrl -OutFile $bootstrapper -UseBasicParsing diff --git a/.vsconfig b/.vsconfig index 095606afa1..5ef63fc25d 100644 --- a/.vsconfig +++ b/.vsconfig @@ -5,7 +5,7 @@ "Microsoft.Net.Component.4.7.1.TargetingPack", "Microsoft.Net.Component.4.7.1.SDK", "Microsoft.Net.Core.Component.SDK.8.0", - "Microsoft.VisualStudio.Component.VC.v143.x86.x64", + "Microsoft.VisualStudio.Component.VC.v145.x86.x64", "Microsoft.VisualStudio.Component.Windows11SDK.26100", "Microsoft.VisualStudio.Workload.NativeDesktop", "Microsoft.VisualStudio.Workload.ManagedDesktop", diff --git a/GVFS/GVFS.NativeTests/GVFS.NativeTests.vcxproj b/GVFS/GVFS.NativeTests/GVFS.NativeTests.vcxproj index 041163bead..11aa6a7d30 100644 --- a/GVFS/GVFS.NativeTests/GVFS.NativeTests.vcxproj +++ b/GVFS/GVFS.NativeTests/GVFS.NativeTests.vcxproj @@ -31,14 +31,14 @@ DynamicLibrary true NotSet - v143 + v145 DynamicLibrary false true NotSet - v143 + v145 diff --git a/GVFS/GVFS.PostIndexChangedHook/GVFS.PostIndexChangedHook.vcxproj b/GVFS/GVFS.PostIndexChangedHook/GVFS.PostIndexChangedHook.vcxproj index 8e8f32a5ff..4150e90568 100644 --- a/GVFS/GVFS.PostIndexChangedHook/GVFS.PostIndexChangedHook.vcxproj +++ b/GVFS/GVFS.PostIndexChangedHook/GVFS.PostIndexChangedHook.vcxproj @@ -31,14 +31,14 @@ Application true MultiByte - v143 + v145 Application false true MultiByte - v143 + v145 diff --git a/GVFS/GVFS.ReadObjectHook/GVFS.ReadObjectHook.vcxproj b/GVFS/GVFS.ReadObjectHook/GVFS.ReadObjectHook.vcxproj index cd6ccc65e2..6ce96a44cc 100644 --- a/GVFS/GVFS.ReadObjectHook/GVFS.ReadObjectHook.vcxproj +++ b/GVFS/GVFS.ReadObjectHook/GVFS.ReadObjectHook.vcxproj @@ -31,14 +31,14 @@ Application true MultiByte - v143 + v145 Application false true MultiByte - v143 + v145 diff --git a/GVFS/GVFS.VirtualFileSystemHook/GVFS.VirtualFileSystemHook.vcxproj b/GVFS/GVFS.VirtualFileSystemHook/GVFS.VirtualFileSystemHook.vcxproj index 026b18af42..703ddd7a8e 100644 --- a/GVFS/GVFS.VirtualFileSystemHook/GVFS.VirtualFileSystemHook.vcxproj +++ b/GVFS/GVFS.VirtualFileSystemHook/GVFS.VirtualFileSystemHook.vcxproj @@ -31,14 +31,14 @@ Application true MultiByte - v143 + v145 Application false true MultiByte - v143 + v145 diff --git a/GVFS/GitHooksLoader/GitHooksLoader.vcxproj b/GVFS/GitHooksLoader/GitHooksLoader.vcxproj index 28513e8ef3..a99300ca6d 100644 --- a/GVFS/GitHooksLoader/GitHooksLoader.vcxproj +++ b/GVFS/GitHooksLoader/GitHooksLoader.vcxproj @@ -29,14 +29,14 @@ Application true Unicode - v143 + v145 Application false true Unicode - v143 + v145 diff --git a/Readme.md b/Readme.md index c72ae98d51..1927110cee 100644 --- a/Readme.md +++ b/Readme.md @@ -35,7 +35,7 @@ will notify you when new versions are available. ## Building VFS for Git If you'd like to build your own VFS for Git Windows installer: -* Install Visual Studio 2022 Community Edition or higher (https://www.visualstudio.com/downloads/). +* Install Visual Studio 2026 Community Edition or higher (https://www.visualstudio.com/downloads/). * Include the following workloads: * .NET desktop development * Desktop development with C++ @@ -50,7 +50,7 @@ If you'd like to build your own VFS for Git Windows installer: build will fail, and the second and subsequent builds will succeed. This is because the build requires a prebuild code generation step. For details, see the build script in the previous step. -Visual Studio 2022 will [automatically prompt you to install these dependencies](https://devblogs.microsoft.com/setup/configure-visual-studio-across-your-organization-with-vsconfig/) when you open the solution. The .vsconfig file that is present in the root of the repository specifies all required components. +Visual Studio 2026 will [automatically prompt you to install these dependencies](https://devblogs.microsoft.com/setup/configure-visual-studio-across-your-organization-with-vsconfig/) when you open the solution. The .vsconfig file that is present in the root of the repository specifies all required components. The installer can now be found at `C:\Repos\VFSForGit\out\GVFS.Installers\bin\[Debug|Release]\win-x64\SetupGVFS..exe` diff --git a/scripts/Build.bat b/scripts/Build.bat index 592020f594..da7b0e19fc 100644 --- a/scripts/Build.bat +++ b/scripts/Build.bat @@ -48,7 +48,7 @@ REM emits the literal vswhere "not recognized" stderr into the link command REM line and the publish step fails with a malformed link.rsp invocation. SET "PATH=%ProgramFiles(x86)%\Microsoft Visual Studio\Installer;%PATH%" -REM .NET 10 SDK ships MSBuild 18.x; VS 2022 ships MSBuild 17.x. +REM .NET 10 SDK ships MSBuild 18.x; VS 2026 ships MSBuild 18.x. REM Managed (csproj) projects require MSBuild 18.x via "dotnet build". REM Native C++ (vcxproj) projects require VS MSBuild with VC++ targets. From 72e2240595ae0918b19d7c2fa920394faa9093bd Mon Sep 17 00:00:00 2001 From: Tyrie Vella Date: Tue, 18 Aug 2026 15:20:18 -0700 Subject: [PATCH 2/4] CI: build arm64 on windows-11-vs2026-arm for v145 toolset The default windows-11-arm runner image still ships Visual Studio 2022, which lacks the v145 toolset the native projects now target. Use the preview windows-11-vs2026-arm image so the arm64 build has VS 2026. Revert to windows-11-arm once its default image migrates to VS 2026. Assisted-by: Claude Opus 4.8 Signed-off-by: Tyrie Vella --- .github/workflows/build.yaml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index d0b4a4509a..e6d9ab0701 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -255,7 +255,12 @@ jobs: path: MicrosoftGit build: - runs-on: ${{ matrix.architecture == 'arm64' && 'windows-11-arm' || 'windows-2025' }} + # arm64 uses the preview 'windows-11-vs2026-arm' image because the native + # C++ projects target the v145 toolset (VS 2026). The default + # 'windows-11-arm' image still ships VS 2022 (v145 absent); it migrates to + # VS 2026 in early September 2026, after which this can revert to + # 'windows-11-arm'. x64 'windows-2025' already ships VS 2026. + runs-on: ${{ matrix.architecture == 'arm64' && 'windows-11-vs2026-arm' || 'windows-2025' }} name: Build and Unit Test needs: validate From 028937241acf81886d2a4cf897c6bde1e626861e Mon Sep 17 00:00:00 2001 From: Tyrie Vella Date: Tue, 18 Aug 2026 15:40:22 -0700 Subject: [PATCH 3/4] Deterministically select VS 2026 MSBuild for native build Build agents (and the windows-11-vs2026-arm runner) carry both VS 2022 and VS 2026. Build.bat located MSBuild with a bare 'where msbuild.exe', which returned the VS 2022 MSBuild; the native projects target the v145 toolset, so that MSBuild failed with MSB8020 (v145 build tools not found). Prefer 'vswhere -latest' (newest install, 18.x before 17.x) for both MSBuild and vcvarsall, and fall back to PATH only when vswhere is unavailable. Pin the setup-msbuild CI step to VS 2026 (18.0+) as well. Use the canonical VC.Tools.x86.x64 component in .vsconfig so the latest (v145) toolset installs. Assisted-by: Claude Opus 4.8 Signed-off-by: Tyrie Vella --- .github/workflows/build.yaml | 5 +++++ .vsconfig | 2 +- scripts/Build.bat | 31 ++++++++++++++++++------------- 3 files changed, 24 insertions(+), 14 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index e6d9ab0701..49cb472e36 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -295,6 +295,11 @@ jobs: - name: Add MSBuild to PATH if: steps.skip.outputs.result != 'true' uses: microsoft/setup-msbuild@v3.0.0 + with: + # Pin to Visual Studio 2026 (18.0+). Runner images that still carry + # VS 2022 alongside VS 2026 would otherwise put the 2022 MSBuild on + # PATH, and the native projects (v145 toolset) fail with MSB8020. + vs-version: '[18.0,)' - name: Build VFS for Git if: steps.skip.outputs.result != 'true' diff --git a/.vsconfig b/.vsconfig index 5ef63fc25d..05d718a168 100644 --- a/.vsconfig +++ b/.vsconfig @@ -5,7 +5,7 @@ "Microsoft.Net.Component.4.7.1.TargetingPack", "Microsoft.Net.Component.4.7.1.SDK", "Microsoft.Net.Core.Component.SDK.8.0", - "Microsoft.VisualStudio.Component.VC.v145.x86.x64", + "Microsoft.VisualStudio.Component.VC.Tools.x86.x64", "Microsoft.VisualStudio.Component.Windows11SDK.26100", "Microsoft.VisualStudio.Workload.NativeDesktop", "Microsoft.VisualStudio.Workload.ManagedDesktop", diff --git a/scripts/Build.bat b/scripts/Build.bat index da7b0e19fc..2cc3cb8ab1 100644 --- a/scripts/Build.bat +++ b/scripts/Build.bat @@ -101,28 +101,33 @@ ECHO INFO: Using vcpkg at '%VCPKG_EXEC%' ECHO ^************************** ECHO ^* Building C++ Projects * ECHO ^************************** -REM Locate VS MSBuild for native C++ projects +REM Locate VS MSBuild for the native C++ projects. Prefer the newest Visual +REM Studio via "vswhere -latest" so MSBuild resolves the v145 toolset the +REM vcxproj files target (VS 2026). A build agent may also carry VS 2022 +REM (v170 / v143); a bare "where msbuild.exe" can return that older MSBuild, +REM which then fails with MSB8020 (v145 build tools not found). "-latest" +REM sorts installs by version and returns the newest (18.x before 17.x), so +REM query vswhere first and only fall back to PATH when vswhere is unavailable. SET MSBUILD_EXEC= -FOR /F "tokens=* USEBACKQ" %%F IN (`where msbuild.exe 2^>nul`) DO ( - SET MSBUILD_EXEC=%%F - ECHO INFO: Found msbuild.exe at '%%F' - GOTO :FOUND_MSBUILD -) - -:LOCATE_MSBUILD SET VSWHERE_EXEC="%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" IF EXIST %VSWHERE_EXEC% ( - FOR /F "tokens=* USEBACKQ" %%F IN (`%VSWHERE_EXEC% -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -find MSBuild\**\Bin\amd64\MSBuild.exe`) DO ( - SET MSBUILD_EXEC=%%F - ECHO INFO: Found msbuild.exe at '%%F' + FOR /F "tokens=* USEBACKQ" %%F IN (`%VSWHERE_EXEC% -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -find MSBuild\**\Bin\MSBuild.exe`) DO ( + SET "MSBUILD_EXEC=%%F" + ) +) +IF NOT DEFINED MSBUILD_EXEC ( + FOR /F "tokens=* USEBACKQ" %%F IN (`where msbuild.exe 2^>nul`) DO ( + SET "MSBUILD_EXEC=%%F" + GOTO :FOUND_MSBUILD ) ) :FOUND_MSBUILD IF NOT DEFINED MSBUILD_EXEC ( - ECHO ERROR: Could not find VS MSBuild. Install Visual Studio with the C++ workload to build native projects. + ECHO ERROR: Could not find Visual Studio 2026 MSBuild. Install Visual Studio 2026 with the C++ workload to build native projects. EXIT /B 1 ) +ECHO INFO: Using msbuild.exe at '%MSBUILD_EXEC%' REM Initialize the VC++ developer environment for the target architecture so REM MSBuild can locate the matching cl.exe / link.exe and the right INCLUDE/LIB @@ -136,7 +141,7 @@ IF EXIST %VSWHERE_VC% ( ) ) IF NOT DEFINED VCVARS_BAT ( - ECHO ERROR: Could not find vcvarsall.bat. Install Visual Studio with the C++ workload. + ECHO ERROR: Could not find Visual Studio 2026 vcvarsall.bat. Install Visual Studio 2026 with the C++ workload. EXIT /B 1 ) ECHO INFO: Initializing VC++ env for %ARCH% via "%VCVARS_BAT%" From b3d7733b43cb8cff698226aee9b460dea761f4b1 Mon Sep 17 00:00:00 2001 From: Tyrie Vella Date: Tue, 18 Aug 2026 15:56:11 -0700 Subject: [PATCH 4/4] Build arm64 native projects with the x64-hosted cross toolset The VS 2026 native arm64 compiler fails to build GVFS.NativeTests with C3859 (failed to create virtual memory for PCH) and C1076 (internal heap limit reached) -- a known limitation where ARM64 native compiler support lags x64. Initialize the VC++ environment with amd64_arm64 (x64-hosted arm64 cross toolset, which Visual Studio uses by default for arm64) instead of the native arm64 toolset. The cross compiler has the address space to build the PCH and produces equivalent arm64 binaries. x64 builds are unchanged. Assisted-by: Claude Opus 4.8 Signed-off-by: Tyrie Vella --- scripts/Build.bat | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/scripts/Build.bat b/scripts/Build.bat index 2cc3cb8ab1..fffa7ae7e0 100644 --- a/scripts/Build.bat +++ b/scripts/Build.bat @@ -144,8 +144,17 @@ IF NOT DEFINED VCVARS_BAT ( ECHO ERROR: Could not find Visual Studio 2026 vcvarsall.bat. Install Visual Studio 2026 with the C++ workload. EXIT /B 1 ) -ECHO INFO: Initializing VC++ env for %ARCH% via "%VCVARS_BAT%" -CALL "%VCVARS_BAT%" %ARCH% || GOTO ERROR +REM Select the vcvars host_target argument. For arm64 targets, use the +REM x64-hosted arm64 cross toolset (amd64_arm64) rather than the native arm64 +REM toolset (plain "arm64"). The VS 2026 native arm64 compiler fails to build +REM GVFS.NativeTests with C3859 / C1076 (PCH virtual-memory / internal heap +REM limit) -- a known ARM64-native-compiler limitation. The x64-hosted cross +REM compiler (which VS uses by default for arm64) has the address space to +REM build the PCH and produces equivalent arm64 binaries. +SET "VCVARS_ARG=%ARCH%" +IF "%ARCH%"=="arm64" SET "VCVARS_ARG=amd64_arm64" +ECHO INFO: Initializing VC++ env (%VCVARS_ARG%) for %ARCH% via "%VCVARS_BAT%" +CALL "%VCVARS_BAT%" %VCVARS_ARG% || GOTO ERROR FOR %%P IN ( "%VFS_SRCDIR%\GVFS\GitHooksLoader\GitHooksLoader.vcxproj"