gh-149786: Fixes venvlauncher builds on Windows free-threaded (GH-149847)

This commit is contained in:
Steve Dower 2026-05-15 14:43:41 +01:00 committed by GitHub
parent 4aa296f9c4
commit 1c5fe21eb2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 38 additions and 12 deletions

View file

@ -301,9 +301,9 @@ def test_sysconfig(self):
self.assertEqual(out.strip(), expected, err)
for attr, expected in (
('executable', self.envpy()),
# Usually compare to sys.executable, but if we're running in our own
# venv then we really need to compare to our base executable
('_base_executable', sys._base_executable),
# Usually compare to sys.prefix, but if we're running in our own
# venv then we really need to compare to our base prefix
('base_prefix', sys.base_prefix),
):
with self.subTest(attr):
cmd[2] = f'import sys; print(sys.{attr})'
@ -916,10 +916,10 @@ def test_venvwlauncher(self):
exename = exename.replace("python", "pythonw")
envpyw = os.path.join(self.env_dir, self.bindir, exename)
try:
subprocess.check_call([envpyw, "-c", "import sys; "
"assert sys._base_executable.endswith('%s')" % exename])
subprocess.check_call([envpyw, "-c", "import fnmatch, sys; "
"assert fnmatch.fnmatch(sys._base_executable, '**/pythonw*.exe')"])
except subprocess.CalledProcessError:
self.fail("venvwlauncher.exe did not run %s" % exename)
self.fail("venvwlauncher.exe did not run pythonw.exe")
@requireVenvCreate

View file

@ -0,0 +1 @@
Fixes virtual environment launchers on Windows free-threaded builds.

View file

@ -112,6 +112,7 @@ def public(f):
"venv",
"dev",
"html-doc",
"alias",
"install-json",
"builddetails-json",
],
@ -128,6 +129,7 @@ def public(f):
"html-doc",
"symbols",
"tests",
"alias",
"install-test-json",
"builddetails-json",
],

View file

@ -66,8 +66,9 @@ def calculate_install_json(ns, *, for_embed=False, for_test=False):
if ns.include_freethreaded:
# Free-threaded distro comes with a tag suffix
TAG_SUFFIX = "t"
TARGET = f"python{VER_MAJOR}.{VER_MINOR}t.exe"
TARGETW = f"pythonw{VER_MAJOR}.{VER_MINOR}t.exe"
if not ns.include_alias:
TARGET = f"python{VER_MAJOR}.{VER_MINOR}t.exe"
TARGETW = f"pythonw{VER_MAJOR}.{VER_MINOR}t.exe"
DISPLAY_TAGS.append("free-threaded")
FILE_SUFFIX = f"t-{ns.arch}"

View file

@ -135,6 +135,14 @@
set PYTHONPATH=$(PySourcePath)Lib
"$(OutDir)$(PyExeName)$(PyDebugExt).exe" "$(PySourcePath)PC\validate_ucrtbase.py" $(UcrtName)' ContinueOnError="true" />
</Target>
<Target Name="CopyFreethreadedBinary" AfterTargets="AfterBuild"
Condition="$(DisableGil) == 'true' and $(Configuration) != 'PGInstrument'">
<Message Text="Duplicating $(TargetPath) to $(PyExeName)$(MajorVersionNumber).$(MinorVersionNumber)t$(PyDebugExt).exe for free-threaded compatibility" />
<Copy SourceFiles="$(TargetPath)"
DestinationFiles="$(OutDir)\$(PyExeName)$(MajorVersionNumber).$(MinorVersionNumber)t$(PyDebugExt).exe"
SkipUnchangedFiles="true"
UseHardLinksIfPossible="true" />
</Target>
<Target Name="GeneratePythonBat" AfterTargets="AfterBuild">
<PropertyGroup>
<_Content>@rem This script invokes the most recently built Python with all arguments

View file

@ -115,4 +115,12 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
<Target Name="CopyFreethreadedBinary" AfterTargets="AfterBuild"
Condition="$(DisableGil) == 'true' and $(Configuration) != 'PGInstrument'">
<Message Text="Duplicating $(TargetPath) to $(PyWExeName)$(MajorVersionNumber).$(MinorVersionNumber)t$(PyDebugExt).exe for free-threaded compatibility" />
<Copy SourceFiles="$(TargetPath)"
DestinationFiles="$(OutDir)\$(PyWExeName)$(MajorVersionNumber).$(MinorVersionNumber)t$(PyDebugExt).exe"
SkipUnchangedFiles="true"
UseHardLinksIfPossible="true" />
</Target>
</Project>

View file

@ -89,10 +89,13 @@
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="pyproject.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Label="UserMacros">
<ExeName>$(PyExeName)$(PyDebugExt).exe</ExeName>
<ExeName Condition="$(DisableGil) == 'true'">$(PyExeName)$(MajorVersionNumber).$(MinorVersionNumber)t$(PyDebugExt).exe</ExeName>
</PropertyGroup>
<ItemDefinitionGroup>
<ClCompile>
<PreprocessorDefinitions>EXENAME=L"$(PyExeName)$(PyDebugExt).exe";_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>EXENAME=L"$(ExeName)";_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<ResourceCompile>

View file

@ -89,10 +89,13 @@
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="pyproject.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Label="UserMacros">
<ExeName>$(PyWExeName)$(PyDebugExt).exe</ExeName>
<ExeName Condition="$(DisableGil) == 'true'">$(PyWExeName)$(MajorVersionNumber).$(MinorVersionNumber)t$(PyDebugExt).exe</ExeName>
</PropertyGroup>
<ItemDefinitionGroup>
<ClCompile>
<PreprocessorDefinitions>EXENAME=L"$(PyWExeName)$(PyDebugExt).exe";_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>EXENAME=L"$(ExeName)";_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<ResourceCompile>