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})'
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
--- /dev/null
+Fixes virtual environment launchers on Windows free-threaded builds.
"venv",
"dev",
"html-doc",
+ "alias",
"install-json",
"builddetails-json",
],
"html-doc",
"symbols",
"tests",
+ "alias",
"install-test-json",
"builddetails-json",
],
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}"
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
<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>
\ No newline at end of file
<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>
<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>