Skip to content

Conversation

@jcbrill
Copy link
Contributor

@jcbrill jcbrill commented Jan 3, 2026

Changes:

  • MSVC: Remove the 32-bit arm target and host from the Visual Studio 2026 configuration. Visual Studio 2026 removed support for targeting arm. The arm libraries are not included in the latest Windows SDK (10.0.26100.0).
  • Document the potential issue with targeting 32-bit arm using Visual Studio 2022 and Windows SDK 10.0.26100 or later is installed in SCons/Tool/MSCommon/README.rst.

Contributor Checklist:

  • I have created a new test or updated the unit tests to cover the new/changed functionality.
  • I have updated CHANGES.txt and RELEASE.txt (and read the README.rst).
  • I have updated the appropriate documentation

Changes:
* MSVC: Remove the 32-bit arm target and host from the Visual Studio 2026 configuration.  Visual Studio 2026 removed support for targeting arm. The arm libraries are not included in the latest Windows SDK (10.0.26100.0).
* Document the potential issue with targeting 32-bit arm using Visual Studio 2022 when Windows SDK 10.0.26100 or later is installed.
@jcbrill
Copy link
Contributor Author

jcbrill commented Jan 3, 2026

FYI

Targeting 32-bit arm with VS 2022 and the latest Windows SDK installed

Visual Studio 2026 removed support for 32-bit arm targets. The 32-bit arm libraries are not included in the latest Windows SDK (10.0.26100.0).

The Visual Studio documentation states: "Developers needing to target ARM32 can continue using the Visual Studio 2022 v143 build tools".

As of Visual Studio 2022 17.14.23, builds targeting 32-bit arm on a machine that has Windows SDK 10.0.26100.0 or later installed, may fail due to the Visual Studio 2022 batch file implementation. If this happens, explicitly passing an earlier Windows SDK version via MSVC_SDK_VERSION may be required. For example, MSVC_SDK_VERSION="10.0.22621.0".

Experiment Configuration

Visual Studio Installations (latest):

  • VS 2026 Community
  • VS 2022 Community

Windows SDK Installations (latest):

  • 10.0.26100.0
  • 10.0.22621.0

Test configuration building a simple shared library with VS 2022:

  1. Implicit Windows SDK Version 10.0.26100.0 [FAIL]
    MSVC_VERSION="14.3", TARGET_ARCH="arm"
  2. Explicit Windows SDK Version 10.0.26100.0 [FAIL]
    MSVC_VERSION="14.3", TARGET_ARCH="arm", MSVC_SDK_VERSION="10.0.26100.0"
  3. Explicit Windows SDK Version 10.0.22621.0 [PASS]
    MSVC_VERSION="14.3", TARGET_ARCH="arm", MSVC_SDK_VERSION="10.0.22621.0"

Source file (hello-dll.c):

#include <windows.h>
#include <stdio.h>
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) {
    printf("hello");
    return TRUE;
}

SConstruct:

import os.path
import SCons

DefaultEnvironment(tools=[])

SCons.Script.AddOption(
    '--test',
    dest='test',
    type=int,
    default=1,
)

test = SCons.Script.GetOption('test')

env_kwargs = {'MSVC_VERSION': '14.3', 'TARGET_ARCH': 'arm'}

if test == 1:
    pass
elif test == 2:
    env_kwargs.update({'MSVC_SDK_VERSION': '10.0.26100.0'})
elif test == 3:
    env_kwargs.update({'MSVC_SDK_VERSION': '10.0.22621.0'})
else:
    raise RuntimeError(f"Unsupported test number: {test}")

print(f"env_kwargs = {env_kwargs}")
env = Environment(**env_kwargs , tools=['msvc', 'mslink'])

for key in ['INCLUDE', 'LIB', 'LIBPATH']:
    values = env['ENV'][key].split(';')
    for i, value in enumerate(values):
        status = '' if os.path.exists(value) else ' [***MISSING***]'
        print(f"env['ENV'][{key!r}][{i}]={value}{status} ")

env.SharedLibrary(target='hello-dll.dll', source=['hello-dll.c'])

Batch File:

@setlocal
@set SCONS_BRANCH=..\..\jbrill-msvc-vs2026\scripts\scons.py
@set OUTPUT_FILE=build_log.txt
@call E:\python\python-embed 64 3.7

@type NUL > %OUTPUT_FILE%
@echo === test 1: run === 1>>%OUTPUT_FILE% 2>&1
@echo. 1>>%OUTPUT_FILE% 2>&1
@%PYEXE% %SCONS_BRANCH% --test=1 1>>%OUTPUT_FILE% 2>&1
@echo. 1>>%OUTPUT_FILE% 2>&1
@echo === test 1: clean ===
@%PYEXE% %SCONS_BRANCH% --test=1 --clean

@echo === test 2: run === 1>>%OUTPUT_FILE% 2>&1
@echo. 1>>%OUTPUT_FILE% 2>&1
@%PYEXE% %SCONS_BRANCH% --test=2 1>>%OUTPUT_FILE% 2>&1
@echo. 1>>%OUTPUT_FILE% 2>&1
@echo === test 2: clean ===
@%PYEXE% %SCONS_BRANCH% --test=2 --clean

@echo === test 3: run === 1>>%OUTPUT_FILE% 2>&1
@echo. 1>>%OUTPUT_FILE% 2>&1
@%PYEXE% %SCONS_BRANCH% --test=3 1>>%OUTPUT_FILE% 2>&1
@echo. 1>>%OUTPUT_FILE% 2>&1
@echo === test 3: clean ===
@%PYEXE% %SCONS_BRANCH% --test=3 --clean

@endlocal

Output (annotated for missing directories):

=== test 1: run === 
 
scons: Reading SConscript files ...
env_kwargs = {'MSVC_VERSION': '14.3', 'TARGET_ARCH': 'arm'}
env['ENV']['INCLUDE'][0]=C:\Software\MSVS-2022-143-Com\VC\Tools\MSVC\14.44.35207\include 
env['ENV']['INCLUDE'][1]=C:\Software\MSVS-2022-143-Com\VC\Tools\MSVC\14.44.35207\ATLMFC\include 
env['ENV']['INCLUDE'][2]=C:\Software\MSVS-2022-143-Com\VC\Auxiliary\VS\include 
env['ENV']['INCLUDE'][3]=C:\Program Files (x86)\Windows Kits\10\include\10.0.22621.0\ucrt 
env['ENV']['INCLUDE'][4]=C:\Program Files (x86)\Windows Kits\10\\include\10.0.26100.0\\um 
env['ENV']['INCLUDE'][5]=C:\Program Files (x86)\Windows Kits\10\\include\10.0.26100.0\\shared 
env['ENV']['INCLUDE'][6]=C:\Program Files (x86)\Windows Kits\10\\include\10.0.26100.0\\winrt 
env['ENV']['INCLUDE'][7]=C:\Program Files (x86)\Windows Kits\10\\include\10.0.26100.0\\cppwinrt 
env['ENV']['INCLUDE'][8]=C:\Program Files (x86)\Windows Kits\NETFXSDK\4.8\include\um 
env['ENV']['LIB'][0]=C:\Software\MSVS-2022-143-Com\VC\Tools\MSVC\14.44.35207\ATLMFC\lib\ARM 
env['ENV']['LIB'][1]=C:\Software\MSVS-2022-143-Com\VC\Tools\MSVC\14.44.35207\lib\ARM 
env['ENV']['LIB'][2]=C:\Program Files (x86)\Windows Kits\NETFXSDK\4.8\lib\um\arm 
env['ENV']['LIB'][3]=C:\Program Files (x86)\Windows Kits\10\lib\10.0.22621.0\ucrt\arm 
env['ENV']['LIB'][4]=C:\Program Files (x86)\Windows Kits\10\\lib\10.0.26100.0\\um\arm [***MISSING***] 
env['ENV']['LIBPATH'][0]=C:\Software\MSVS-2022-143-Com\VC\Tools\MSVC\14.44.35207\ATLMFC\lib\ARM 
env['ENV']['LIBPATH'][1]=C:\Software\MSVS-2022-143-Com\VC\Tools\MSVC\14.44.35207\lib\ARM 
env['ENV']['LIBPATH'][2]=C:\Software\MSVS-2022-143-Com\VC\Tools\MSVC\14.44.35207\lib\x86\store\references 
env['ENV']['LIBPATH'][3]=C:\Program Files (x86)\Windows Kits\10\UnionMetadata\10.0.26100.0 
env['ENV']['LIBPATH'][4]=C:\Program Files (x86)\Windows Kits\10\References\10.0.26100.0 
env['ENV']['LIBPATH'][5]=C:\Windows\Microsoft.NET\Framework64\v4.0.30319 
scons: done reading SConscript files.
scons: Building targets ...
cl /Fohello-dll.obj /c hello-dll.c /nologo
hello-dll.c
link /nologo /dll /out:hello-dll.dll /implib:hello-dll.lib hello-dll.obj
LINK : fatal error LNK1104: cannot open file 'uuid.lib'
scons: *** [hello-dll.dll] Error 1104
scons: building terminated because of errors.
 
=== test 2: run === 
 
scons: Reading SConscript files ...
env_kwargs = {'MSVC_VERSION': '14.3', 'TARGET_ARCH': 'arm', 'MSVC_SDK_VERSION': '10.0.26100.0'}
env['ENV']['INCLUDE'][0]=C:\Software\MSVS-2022-143-Com\VC\Tools\MSVC\14.44.35207\include 
env['ENV']['INCLUDE'][1]=C:\Software\MSVS-2022-143-Com\VC\Tools\MSVC\14.44.35207\ATLMFC\include 
env['ENV']['INCLUDE'][2]=C:\Software\MSVS-2022-143-Com\VC\Auxiliary\VS\include 
env['ENV']['INCLUDE'][3]=C:\Program Files (x86)\Windows Kits\10\include\10.0.22621.0\ucrt 
env['ENV']['INCLUDE'][4]=C:\Program Files (x86)\Windows Kits\10\\include\10.0.26100.0\\um 
env['ENV']['INCLUDE'][5]=C:\Program Files (x86)\Windows Kits\10\\include\10.0.26100.0\\shared 
env['ENV']['INCLUDE'][6]=C:\Program Files (x86)\Windows Kits\10\\include\10.0.26100.0\\winrt 
env['ENV']['INCLUDE'][7]=C:\Program Files (x86)\Windows Kits\10\\include\10.0.26100.0\\cppwinrt 
env['ENV']['INCLUDE'][8]=C:\Program Files (x86)\Windows Kits\NETFXSDK\4.8\include\um 
env['ENV']['LIB'][0]=C:\Software\MSVS-2022-143-Com\VC\Tools\MSVC\14.44.35207\ATLMFC\lib\ARM 
env['ENV']['LIB'][1]=C:\Software\MSVS-2022-143-Com\VC\Tools\MSVC\14.44.35207\lib\ARM 
env['ENV']['LIB'][2]=C:\Program Files (x86)\Windows Kits\NETFXSDK\4.8\lib\um\arm 
env['ENV']['LIB'][3]=C:\Program Files (x86)\Windows Kits\10\lib\10.0.22621.0\ucrt\arm 
env['ENV']['LIB'][4]=C:\Program Files (x86)\Windows Kits\10\\lib\10.0.26100.0\\um\arm [***MISSING***] 
env['ENV']['LIBPATH'][0]=C:\Software\MSVS-2022-143-Com\VC\Tools\MSVC\14.44.35207\ATLMFC\lib\ARM 
env['ENV']['LIBPATH'][1]=C:\Software\MSVS-2022-143-Com\VC\Tools\MSVC\14.44.35207\lib\ARM 
env['ENV']['LIBPATH'][2]=C:\Software\MSVS-2022-143-Com\VC\Tools\MSVC\14.44.35207\lib\x86\store\references 
env['ENV']['LIBPATH'][3]=C:\Program Files (x86)\Windows Kits\10\UnionMetadata\10.0.26100.0 
env['ENV']['LIBPATH'][4]=C:\Program Files (x86)\Windows Kits\10\References\10.0.26100.0 
env['ENV']['LIBPATH'][5]=C:\Windows\Microsoft.NET\Framework64\v4.0.30319 
scons: done reading SConscript files.
scons: Building targets ...
cl /Fohello-dll.obj /c hello-dll.c /nologo
hello-dll.c
link /nologo /dll /out:hello-dll.dll /implib:hello-dll.lib hello-dll.obj
LINK : fatal error LNK1104: cannot open file 'uuid.lib'
scons: *** [hello-dll.dll] Error 1104
scons: building terminated because of errors.
 
=== test 3: run === 
 
scons: Reading SConscript files ...
env_kwargs = {'MSVC_VERSION': '14.3', 'TARGET_ARCH': 'arm', 'MSVC_SDK_VERSION': '10.0.22621.0'}
env['ENV']['INCLUDE'][0]=C:\Software\MSVS-2022-143-Com\VC\Tools\MSVC\14.44.35207\include 
env['ENV']['INCLUDE'][1]=C:\Software\MSVS-2022-143-Com\VC\Tools\MSVC\14.44.35207\ATLMFC\include 
env['ENV']['INCLUDE'][2]=C:\Software\MSVS-2022-143-Com\VC\Auxiliary\VS\include 
env['ENV']['INCLUDE'][3]=C:\Program Files (x86)\Windows Kits\10\include\10.0.22621.0\ucrt 
env['ENV']['INCLUDE'][4]=C:\Program Files (x86)\Windows Kits\10\\include\10.0.22621.0\\um 
env['ENV']['INCLUDE'][5]=C:\Program Files (x86)\Windows Kits\10\\include\10.0.22621.0\\shared 
env['ENV']['INCLUDE'][6]=C:\Program Files (x86)\Windows Kits\10\\include\10.0.22621.0\\winrt 
env['ENV']['INCLUDE'][7]=C:\Program Files (x86)\Windows Kits\10\\include\10.0.22621.0\\cppwinrt 
env['ENV']['INCLUDE'][8]=C:\Program Files (x86)\Windows Kits\NETFXSDK\4.8\include\um 
env['ENV']['LIB'][0]=C:\Software\MSVS-2022-143-Com\VC\Tools\MSVC\14.44.35207\ATLMFC\lib\ARM 
env['ENV']['LIB'][1]=C:\Software\MSVS-2022-143-Com\VC\Tools\MSVC\14.44.35207\lib\ARM 
env['ENV']['LIB'][2]=C:\Program Files (x86)\Windows Kits\NETFXSDK\4.8\lib\um\arm 
env['ENV']['LIB'][3]=C:\Program Files (x86)\Windows Kits\10\lib\10.0.22621.0\ucrt\arm 
env['ENV']['LIB'][4]=C:\Program Files (x86)\Windows Kits\10\\lib\10.0.22621.0\\um\arm 
env['ENV']['LIBPATH'][0]=C:\Software\MSVS-2022-143-Com\VC\Tools\MSVC\14.44.35207\ATLMFC\lib\ARM 
env['ENV']['LIBPATH'][1]=C:\Software\MSVS-2022-143-Com\VC\Tools\MSVC\14.44.35207\lib\ARM 
env['ENV']['LIBPATH'][2]=C:\Software\MSVS-2022-143-Com\VC\Tools\MSVC\14.44.35207\lib\x86\store\references 
env['ENV']['LIBPATH'][3]=C:\Program Files (x86)\Windows Kits\10\UnionMetadata\10.0.22621.0 
env['ENV']['LIBPATH'][4]=C:\Program Files (x86)\Windows Kits\10\References\10.0.22621.0 
env['ENV']['LIBPATH'][5]=C:\Windows\Microsoft.NET\Framework64\v4.0.30319 
scons: done reading SConscript files.
scons: Building targets ...
cl /Fohello-dll.obj /c hello-dll.c /nologo
hello-dll.c
link /nologo /dll /out:hello-dll.dll /implib:hello-dll.lib hello-dll.obj
scons: done building targets.

Comments:

  • The VS2022 batch files check for the existence of files when determining the Windows SDK version for the ucrt.
  • The VS2022 batch files do not check for the existence of files when determining the Windows SDK version for the um, shared, winrt libraries.

@mwichmann
Copy link
Collaborator

Haven't looked at this in any detail, but if you can't build for that target, it's hard to argue it should be kept in the 2026-specific parts of the tables...

@jcbrill
Copy link
Contributor Author

jcbrill commented Jan 5, 2026

@mwichmann It might be best to move the update to SCons/Tool/MSCommon/README.rst to it's own PR. I'm not convinced modifying the tables is the best idea pending further research.

The way the tables are currently constructed, for each table there may be table entries that are not necessarily valid for all of the VS versions that use the table.

The concern with VS2026 is that it is possible to install the v143, v142, v141, and v140 toolsets targeting arm. However, they can't be used from the "main" VS batch file. Perhaps future versions of the installer will remove the options for the older toolsets targeting arm.

The installer does not appear to add the arm specific batch files that call the "main" VS batch file which is likely sufficient for SCons even if the toolset proper is installed.

There is a difference in behavior between a host/target pair not defined in the table (an unsupported warning eventually followed by the installed versions message) and defined in the table but not found (from memory a toolset not found error).

Prior to VS2026, I don't think it was possible to install a toolset that couldn't be used.

More information to follow.

@bdbaddog
Copy link
Contributor

bdbaddog commented Jan 5, 2026

@jcbrill - sounds reasonable. If the README file is getting to large and a version specific file make sense, then maybe add README-VS2026 with a not in the main README or change README to README-Pre-2026..

Is this PR otherwise good to go, or wait for more updates?

@jcbrill
Copy link
Contributor Author

jcbrill commented Jan 5, 2026

@bdbaddog Wait for more updates which shouldn't take very long.

I'm not sure the tables should be changed. I need to compare the current behavior with the proposed behavior. I think the current behavior might be more desirable.

@jcbrill
Copy link
Contributor Author

jcbrill commented Jan 5, 2026

FYI: msvc batch files and table configurations.

Typically, a new table was added when one or more of the following occurred:

  • A new target was added.
  • An msvc batch file was renamed/added/deleted (i.e., the batch file name changed).
  • An msvc batch file was moved (i.e., the batch file relative path changed).

Prior to VS 2026, it wasn't necessary to add a new table when a target was dropped because the toolset could not be installed. That is not quite true for VS 2026 but it may not matter pending testing.

In the tables below, rows ${\color{#FF798A} \text{with red text}}$ indicate that the host/target combination is not supported by the VS Batch files for:

  • MSVC 2026 (prior to this PR)
  • MSVC 2015
  • MSVC 2013
  • MSVC 2012
  • MSVC 2010

MSVC batch file symbols and partial internal table configuration:

  • MSVC 2026 [14.5]

    _GE2022_HOST_TARGET_BATCHFILE_CLPATHCOMPS

    VCBatch Arg Tool Arch Target Arch
    amd64 amd64 amd64
    amd64_x86 amd64 x86
    ${\color{#FF798A} \text{amd64\_arm}}$ ${\color{#FF798A} \text{amd64}}$ ${\color{#FF798A} \text{arm}}$
    amd64_arm64 amd64 arm64
    x86_amd64 x86 amd64
    x86 x86 x86
    ${\color{#FF798A} \text{x86\_arm}}$ ${\color{#FF798A} \text{x86}}$ ${\color{#FF798A} \text{arm}}$
    x86_arm64 x86 arm64
    arm64_amd64 arm64 amd64
    arm64_x86 arm64 x86
    ${\color{#FF798A} \text{arm64\_arm}}$ ${\color{#FF798A} \text{arm64}}$ ${\color{#FF798A} \text{arm}}$
    arm64 arm64 arm64
  • MSVC 2022 [14.3]

    _GE2022_HOST_TARGET_BATCHFILE_CLPATHCOMPS

    VCBatch Arg Tool Arch Target Arch
    amd64 amd64 amd64
    amd64_x86 amd64 x86
    amd64_arm amd64 arm
    amd64_arm64 amd64 arm64
    x86_amd64 x86 amd64
    x86 x86 x86
    x86_arm x86 arm
    x86_arm64 x86 arm64
    arm64_amd64 arm64 amd64
    arm64_x86 arm64 x86
    arm64_arm arm64 arm
    arm64 arm64 arm64
  • MSVC 2019 [14.2]

    _LE2019_HOST_TARGET_BATCHFILE_CLPATHCOMPS

    VCBatch Arg Tool Arch Target Arch
    amd64 amd64 amd64
    amd64_x86 amd64 x86
    amd64_arm amd64 arm
    amd64_arm64 amd64 arm64
    x86_amd64 x86 amd64
    x86 x86 x86
    x86_arm x86 arm
    x86_arm64 x86 arm64
  • MSVC 2017 [14.1]

    _LE2019_HOST_TARGET_BATCHFILE_CLPATHCOMPS

    VCBatch Arg Tool Arch Target Arch
    amd64 amd64 amd64
    amd64_x86 amd64 x86
    amd64_arm amd64 arm
    amd64_arm64 amd64 arm64
    x86 x86 x86
    x86_amd64 x86 amd64
    x86_arm x86 arm
    x86_arm64 x86 arm64
  • MSVC 2015 [14.0]

    _LE2015_HOST_TARGET_BATCHARG_BATCHFILE_CLPATHCOMPS

    VCBatch Arg Tool Arch Target Arch
    amd64 amd64 amd64
    amd64_x86 amd64 x86
    amd64_arm amd64 arm
    x86_amd64 x86 amd64
    x86 x86 x86
    x86_arm x86 arm
    ${\color{#FF798A} \text{x86\_ia64}}$ ${\color{#FF798A} \text{x86}}$ ${\color{#FF798A} \text{ia64}}$
    arm arm arm
    ${\color{#FF798A} \text{ia64}}$ ${\color{#FF798A} \text{ia64}}$ ${\color{#FF798A} \text{ia64}}$
  • MSVC 2013 [12.0]

    _LE2015_HOST_TARGET_BATCHARG_BATCHFILE_CLPATHCOMPS

    VCBatch Arg Tool Arch Target Arch
    amd64 amd64 amd64
    amd64_x86 amd64 x86
    amd64_arm amd64 arm
    x86_amd64 x86 amd64
    x86 x86 x86
    x86_arm x86 arm
    ${\color{#FF798A} \text{x86\_ia64}}$ ${\color{#FF798A} \text{x86}}$ ${\color{#FF798A} \text{ia64}}$
    arm arm arm
    ${\color{#FF798A} \text{ia64}}$ ${\color{#FF798A} \text{ia64}}$ ${\color{#FF798A} \text{ia64}}$
  • MSVC 2012 [11.0]

    _LE2015_HOST_TARGET_BATCHARG_BATCHFILE_CLPATHCOMPS

    VCBatch Arg Tool Arch Target Arch
    amd64 amd64 amd64
    ${\color{#FF798A} \text{amd64\_x86}}$ ${\color{#FF798A} \text{amd64}}$ ${\color{#FF798A} \text{x86}}$
    ${\color{#FF798A} \text{amd64\_arm}}$ ${\color{#FF798A} \text{amd64}}$ ${\color{#FF798A} \text{arm}}$
    x86 x86 x86
    x86_amd64 x86 amd64
    x86_arm x86 arm
    ${\color{#FF798A} \text{x86\_ia64}}$ ${\color{#FF798A} \text{x86}}$ ${\color{#FF798A} \text{ia64}}$
    arm arm arm
    ${\color{#FF798A} \text{ia64}}$ ${\color{#FF798A} \text{ia64}}$ ${\color{#FF798A} \text{ia64}}$
  • MSVC 2010 [10.0]

    _LE2015_HOST_TARGET_BATCHARG_BATCHFILE_CLPATHCOMPS

    VCBatch Arg Tool Arch Target Arch
    amd64 amd64 amd64
    ${\color{#FF798A} \text{amd64\_x86}}$ ${\color{#FF798A} \text{amd64}}$ ${\color{#FF798A} \text{x86}}$
    ${\color{#FF798A} \text{amd64\_arm}}$ ${\color{#FF798A} \text{amd64}}$ ${\color{#FF798A} \text{arm}}$
    x86 x86 x86
    x86_amd64 x86 amd64
    ${\color{#FF798A} \text{x86\_arm}}$ ${\color{#FF798A} \text{x86}}$ ${\color{#FF798A} \text{arm}}$
    x86_ia64 x86 ia64
    ${\color{#FF798A} \text{arm}}$ ${\color{#FF798A} \text{arm}}$ ${\color{#FF798A} \text{arm}}$
    ia64 ia64 ia64
  • MSVC 2008 [9.0]

    _LE2008_HOST_TARGET_BATCHARG_BATCHFILE_CLPATHCOMPS

    VCBatch Arg Tool Arch Target Arch
    amd64 amd64 amd64
    x86_amd64 x86 amd64
    x86 x86 x86
    x86_ia64 x86 ia64
    ia64 ia64 ia64
  • MSVC 2005 [8.0]

    _LE2008_HOST_TARGET_BATCHARG_BATCHFILE_CLPATHCOMPS

    VCBatch Arg Tool Arch Target Arch
    amd64 amd64 amd64
    x86_amd64 x86 amd64
    x86 x86 x86
    x86_ia64 x86 ia64
    ia64 ia64 ia64
  • MSVC 2003 [7.1]

    _LE2003_HOST_TARGET_CFG

    VCBatch Arg Tool Arch Target Arch
    x86 x86
  • MSVC 2002 [7.0]

    _LE2003_HOST_TARGET_CFG

    VCBatch Arg Tool Arch Target Arch
    x86 x86
  • MSVC 1998 [6.0]

    _LE2003_HOST_TARGET_CFG

    VCBatch Arg Tool Arch Target Arch
    x86 x86

@jcbrill
Copy link
Contributor Author

jcbrill commented Jan 5, 2026

In case you missed it, Visual Studio moving to an annual release cycle in November.

https://learn.microsoft.com/en-us/visualstudio/releases/2026/release-rhythm:

In keeping with the new Modern Lifecycle, beginning with Visual Studio 2026 we plan to deliver new major versions annually in November along with the new version of .NET. These annual releases will be in-place updates to the prior major version, rather than side-by-side as with Visual Studio 2022 and earlier.

The annual release will receive cumulative monthly feature updates and servicing releases. Along with the next annual release, we will make a Long-Term Servicing Channel (LTSC) release available, providing a pause point for Visual Studio Professional and Enterprise customers who need additional time to update to the next major version.

Each annual release will be supported for 1 year of feature updates and servicing plus 1 year of security servicing as an LTSC.

@bdbaddog
Copy link
Contributor

bdbaddog commented Jan 5, 2026

@jcbrill hmm These annual releases will be in-place updates to the prior major version, rather than side-by-side as with Visual Studio 2022 and earlier. that'll have implications for msvc caching as well. So they'll overwrite the prior version? (Probably best to move this bit to a discussion?)

@jcbrill
Copy link
Contributor Author

jcbrill commented Jan 5, 2026

@bdbaddog That was the same sentence that caught my eye as well. I'm not sure what that means. Hopefully, it will show up earlier in the preview/insiders build to assess the impact to SCons before it shows up in the release build.

@jcbrill
Copy link
Contributor Author

jcbrill commented Jan 5, 2026

The results when attempting to build a VS 2026 arm target for the current master branch and this PR are shown below.

SConstruct:

DefaultEnvironment(tools=[])
env = Environment(MSVC_VERSION="14.5", TARGET_ARCH="arm", tools=["msvc", "mslink"])
env.Program("foo.c")

Current SCons master:

scons: Reading SConscript files ...

scons: warning: MSVC version '14.5' working host/target script was not found.
  Host = 'amd64', Target = 'arm'
  Visual Studio C/C++ compilers may not be set correctly
File "../../scons-master/scripts/scons.py", line 97, in <module>
scons: done reading SConscript files.
scons: Building targets ...
cl /Fofoo.obj /c foo.c /nologo
'cl' is not recognized as an internal or external command,
operable program or batch file.
scons: *** [foo.obj] Error 1
scons: building terminated because of errors.

This PR:

scons: Reading SConscript files ...

scons: warning: unsupported host, target combination ('amd64', 'arm') for MSVC version 14.5
File "../../jbrill-msvc-vs2026/scripts/scons.py", line 97, in <module>

scons: warning: MSVC version '14.5' was not found.
  Visual Studio C/C++ compilers may not be set correctly.
  Installed versions are: ['14.5', '14.3', '14.2', '14.1', '14.1Exp', '14.0', '12.0', '11.0', '11.0Exp', '10.0', '10.0Exp', '9.0', '8.0', '7.1', '7.0', '6.0']
File "../../jbrill-msvc-vs2026/scripts/scons.py", line 97, in <module>
scons: done reading SConscript files.
scons: Building targets ...
cl /Fofoo.obj /c foo.c /nologo
'cl' is not recognized as an internal or external command,
operable program or batch file.
scons: *** [foo.obj] Error 1
scons: building terminated because of errors.

Staying with the current main branch would require fewer tables and possibly less future maintenance. The working host/target script warning message is accurate. Possibly misleading though.

For this PR, the first warning message is accurate but the second warning is not particularly helpful.

From the tables above, when ia64 is ignored, VS 2012 would be the next oldest implementation that accepts an unsupported host/target combination and exhibits the behavior above.

Options:

  1. Do not change the existing tables (abandon table changes in this PR)
  2. Make the table changes for VS2026 only.
  3. Make the table changes for all earlier VS versions (ignoring ia64).

I'm leaning towards option 1: not changing the tables as it makes maintenance easier. I have no idea how popular 32-bit arm is as a target for MSVC.

Notes:

  • If somehow the arm batch files (i.e., vcvarsamd64_arm.bat, vcvarsx86_arm.bat, and/or vcvarsarm64_arm.bat) were to be installed, there could be a circumstance where all of the SCons existence checks pass but the "main" msvc batch fails when using an older toolset via MSVC_TOOSET_VERSION.

    I believe the error reported by the batch file would be detected and a batch file executation error should be raised by SCons. I can't be certain though.

  • Some of the message behavior, while seemingly unintuitive, may be necessary as there can be a loop of host/target combinations that are evaluated. For example, older Express versions where only the x86 tools are installed.

@jcbrill
Copy link
Contributor Author

jcbrill commented Jan 5, 2026

@bdbaddog "... that'll have implications for msvc caching as well."

It might not have any more implications than already exist in the current implementation.

They might just install a new default build tools version and toolset version(s). A new build tool series and toolset is traditionally installed in a versioned directory name.

I believe there can be issues today with the current cache implementation when a new toolset is installed but the previous toolset is not uninstalled (i.e., the cache entries are all valid; they are just not the latest).

Note: There is an undocumented feature setting that forces the MSVC_TOOLSET_VERSION and MSVC_SDK_VERSION arguments to be defined. This binds the cache entry to the toolset version and Windows SDK version. A new default toolset version and/or sdk version would use a different cache key. This is described in the SCons/Tool/MSCommon/README.rst. I haven't tested it in a long time but it should still work.

What will be curious is if vswhere will have multiple VS versions with the same installation folder. This might have implications for the definition of MSVC_VERSION.

For RELEASE.txt, the text was moved from the FIXES section to the DEVELOPMENT section as this PR is not necessarily a fix or an improvement.
@jcbrill
Copy link
Contributor Author

jcbrill commented Jan 6, 2026

This PR is now complete.

Based on the earlier behavior of the host/target batch file configuration tables, this PR is not strictly necessary.

However, given the Microsoft changes to the release schedule it may not be the worst idea to have a configuration anchored specifically to VS 2026 now.

I've been waffling back and forth if this should be included or abandoned. Either way is fine with me.

The RELEASE.txt blurb was moved from FIXES to DEVELOPMENT.


label = 'GE2026',

host_all_hosts = OrderedDict([
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it necessary to use OrderedDict() anymore? Isn't insertion order maintained in all supported python versions?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the usage here, OrderedDict is not necessary.

}

_GE2022_HOST_TARGET_CFG = _host_target_config_factory(
_LE2022_HOST_TARGET_CFG = _host_target_config_factory(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this covers only VS2022 can you change var names to _E2022_* ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps the variable names should match the version number range usage?

For example,

_GE2026_*           2026
_LT2026_GE2022_*    2022
_LT2022_GE2017_*    2019, 2017
_LT2017_GE2010_*    2015, 2013, 2012, 2010
_LT2010_GE2005_*    2008, 2005,
_LT2005_*           2003, 2002, 1998 [6.0] 

How they are currently used:

    if vernum_int >= 145:
        # 14.5 (VS2026) and later
        host_target_cfg = _GE2026_HOST_TARGET_CFG
    elif 145 > vernum_int >= 143:
        # 14.3 (VS2022)
        host_target_cfg = _LE2022_HOST_TARGET_CFG
    elif 143 > vernum_int >= 141:
        # 14.2 (VS2019) to 14.1 (VS2017)
        host_target_cfg = _LE2019_HOST_TARGET_CFG
    elif 141 > vernum_int >= 100:
        # 14.0 (VS2015) to 10.0 (VS2010)
        host_target_cfg = _LE2015_HOST_TARGET_CFG
    elif 100 > vernum_int >= 80:
        # 9.0 (VS2008) to 8.0 (VS2005)
        host_target_cfg = _LE2008_HOST_TARGET_CFG
    else: # 80 > vernum_int
        # 7.1 (VS2003) and earlier
        host_target_cfg = _LE2003_HOST_TARGET_CFG
    if vernum_int >= 145:
        # 14.5 (VS2026) and later
        batfiledir = os.path.join(pdir, "Auxiliary", "Build")
        batfile, _ = _GE2026_HOST_TARGET_BATCHFILE_CLPATHCOMPS[(host_arch, target_arch)]
        batfilename = os.path.join(batfiledir, batfile)
        vcdir = pdir
    elif 145 > vernum_int >= 143:
        # 14.3 (VS2022)
        batfiledir = os.path.join(pdir, "Auxiliary", "Build")
        batfile, _ = _LE2022_HOST_TARGET_BATCHFILE_CLPATHCOMPS[(host_arch, target_arch)]
        batfilename = os.path.join(batfiledir, batfile)
        vcdir = pdir
    elif 143 > vernum_int >= 141:
        # 14.2 (VS2019) to 14.1 (VS2017)
        batfiledir = os.path.join(pdir, "Auxiliary", "Build")
        batfile, _ = _LE2019_HOST_TARGET_BATCHFILE_CLPATHCOMPS[(host_arch, target_arch)]
        batfilename = os.path.join(batfiledir, batfile)
        vcdir = pdir
    elif 141 > vernum_int >= 100:
        # 14.0 (VS2015) to 10.0 (VS2010)
        arg, batfile, cl_path_comps = _LE2015_HOST_TARGET_BATCHARG_BATCHFILE_CLPATHCOMPS[(host_arch, target_arch)]
        batfilename = os.path.join(pdir, "vcvarsall.bat")
        depbat = os.path.join(pdir, *cl_path_comps, batfile)
        clexe = os.path.join(pdir, *cl_path_comps, _CL_EXE_NAME)
    elif 100 > vernum_int >= 80:
        # 9.0 (VS2008) to 8.0 (VS2005)
        arg, batfile, cl_path_comps = _LE2008_HOST_TARGET_BATCHARG_BATCHFILE_CLPATHCOMPS[(host_arch, target_arch)]
        if vernum_int == 90 and MSVC.Kind.msvc_version_is_vcforpython(msvc_version):
            # 9.0 (VS2008) Visual C++ for Python:
            #     sdk batch files do not point to the VCForPython installation
            #     vcvarsall batch file is in installdir not productdir (e.g., vc\..\vcvarsall.bat)
            #     dependency batch files are not called from vcvarsall.bat
            sdk_pdir = None
            batfilename = os.path.join(pdir, os.pardir, "vcvarsall.bat")
            depbat = None
        else:
            batfilename = os.path.join(pdir, "vcvarsall.bat")
            depbat = os.path.join(pdir, *cl_path_comps, batfile)
        clexe = os.path.join(pdir, *cl_path_comps, _CL_EXE_NAME)
    else:  # 80 > vernum_int
        # 7.1 (VS2003) and earlier
        pdir = os.path.join(pdir, "Bin")
        batfilename = os.path.join(pdir, "vcvars32.bat")
        clexe = os.path.join(pdir, _CL_EXE_NAME)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about?

_GE2026_*           2026
_LE2022_GE2022_*    2022
_LE2019_GE2017_*    2019, 2017
_LE2015_GE2010_*    2015, 2013, 2012, 2010
_LE2008_GE2005_*    2008, 2005,
_LE2003_*           2003, 2002, 1998 [6.0] 

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it only covers one version, then EVERSION seeems better than an range which can only be one version? At least less confusing to me... otherwise I have to go google the list of all versions to see which versions fit in that range...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Acceptable?

_GE2026_*           2026
_EQ2022_*           2022
_LE2019_GE2017_*    2019, 2017
_LE2015_GE2010_*    2015, 2013, 2012, 2010
_LE2008_GE2005_*    2008, 2005,
_LE2003_*           2003, 2002, 1998 [6.0]

* remove OrderedDict
* rename batch file configuration variables for the version or range of versions supported.
@jcbrill
Copy link
Contributor Author

jcbrill commented Jan 6, 2026

The msvc/msvs tests passed (83) or skipped (3) with python versions 3.7 to 3.14 locally.

@bdbaddog bdbaddog merged commit ff3c36b into SCons:master Jan 6, 2026
8 of 9 checks passed
@mwichmann mwichmann added this to the NextRelease milestone Jan 6, 2026
@jcbrill jcbrill deleted the jbrill-msvc-vs2026 branch January 6, 2026 19:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

3 participants