mirror of https://github.com/python/cpython
gh-112984 Update Windows build and installer for free-threaded builds (GH-113129)
This commit is contained in:
parent
78fcde039a
commit
f56d132deb
|
@ -32,6 +32,8 @@ jobs:
|
|||
strategy:
|
||||
matrix:
|
||||
type: [x86, x64, arm64]
|
||||
env:
|
||||
IncludeFreethreaded: true
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Build CPython installer
|
||||
|
|
|
@ -20,7 +20,7 @@ jobs:
|
|||
- name: Display build info
|
||||
run: .\python.bat -m test.pythoninfo
|
||||
- name: Tests
|
||||
run: .\PCbuild\rt.bat -p Win32 -d -q --fast-ci
|
||||
run: .\PCbuild\rt.bat -p Win32 -d -q --fast-ci ${{ inputs.free-threading && '--disable-gil' || '' }}
|
||||
|
||||
build_win_amd64:
|
||||
name: 'build and test (x64)'
|
||||
|
@ -37,7 +37,7 @@ jobs:
|
|||
- name: Display build info
|
||||
run: .\python.bat -m test.pythoninfo
|
||||
- name: Tests
|
||||
run: .\PCbuild\rt.bat -p x64 -d -q --fast-ci
|
||||
run: .\PCbuild\rt.bat -p x64 -d -q --fast-ci ${{ inputs.free-threading && '--disable-gil' || '' }}
|
||||
|
||||
build_win_arm64:
|
||||
name: 'build (arm64)'
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 231 KiB |
|
@ -307,6 +307,46 @@ settings and replace any that have been removed or modified.
|
|||
"Uninstall" will remove Python entirely, with the exception of the
|
||||
:ref:`launcher`, which has its own entry in Programs and Features.
|
||||
|
||||
.. _install-freethreaded-windows:
|
||||
|
||||
Installing Free-threaded Binaries
|
||||
---------------------------------
|
||||
|
||||
.. versionadded:: 3.13 (Experimental)
|
||||
|
||||
.. note::
|
||||
|
||||
Everything described in this section is considered experimental,
|
||||
and should be expected to change in future releases.
|
||||
|
||||
To install pre-built binaries with free-threading enabled (see :pep:`703`), you
|
||||
should select "Customize installation". The second page of options includes the
|
||||
"Download free-threaded binaries" checkbox.
|
||||
|
||||
.. image:: win_install_freethreaded.png
|
||||
|
||||
Selecting this option will download and install additional binaries to the same
|
||||
location as the main Python install. The main executable is called
|
||||
``python3.13t.exe``, and other binaries either receive a ``t`` suffix or a full
|
||||
ABI suffix. Python source files and bundled third-party dependencies are shared
|
||||
with the main install.
|
||||
|
||||
The free-threaded version is registered as a regular Python install with the
|
||||
tag ``3.13t`` (with a ``-32`` or ``-arm64`` suffix as normal for those
|
||||
platforms). This allows tools to discover it, and for the :ref:`launcher` to
|
||||
support ``py.exe -3.13t``. Note that the launcher will interpret ``py.exe -3``
|
||||
(or a ``python3`` shebang) as "the latest 3.x install", which will prefer the
|
||||
free-threaded binaries over the regular ones, while ``py.exe -3.13`` will not.
|
||||
If you use the short style of option, you may prefer to not install the
|
||||
free-threaded binaries at this time.
|
||||
|
||||
To specify the install option at the command line, use
|
||||
``Include_freethreaded=1``. See :ref:`install-layout-option` for instructions on
|
||||
pre-emptively downloading the additional binaries for offline install. The
|
||||
options to include debug symbols and binaries also apply to the free-threaded
|
||||
builds.
|
||||
|
||||
Free-threaded binaries are also available :ref:`on nuget.org <windows-nuget>`.
|
||||
|
||||
.. _windows-store:
|
||||
|
||||
|
@ -450,9 +490,29 @@ automatically use the headers and import libraries in your build.
|
|||
|
||||
The package information pages on nuget.org are
|
||||
`www.nuget.org/packages/python <https://www.nuget.org/packages/python>`_
|
||||
for the 64-bit version and `www.nuget.org/packages/pythonx86
|
||||
<https://www.nuget.org/packages/pythonx86>`_ for the 32-bit version.
|
||||
for the 64-bit version, `www.nuget.org/packages/pythonx86
|
||||
<https://www.nuget.org/packages/pythonx86>`_ for the 32-bit version, and
|
||||
`www.nuget.org/packages/pythonarm64
|
||||
<https://www.nuget.org/packages/pythonarm64>`_ for the ARM64 version
|
||||
|
||||
Free-threaded packages
|
||||
----------------------
|
||||
|
||||
.. versionadded:: 3.13 (Experimental)
|
||||
|
||||
.. note::
|
||||
|
||||
Everything described in this section is considered experimental,
|
||||
and should be expected to change in future releases.
|
||||
|
||||
Packages containing free-threaded binaries are named
|
||||
`python-freethreaded <https://www.nuget.org/packages/python-freethreaded>`_
|
||||
for the 64-bit version, `pythonx86-freethreaded
|
||||
<https://www.nuget.org/packages/pythonx86-freethreaded>`_ for the 32-bit
|
||||
version, and `pythonarm64-freethreaded
|
||||
<https://www.nuget.org/packages/pythonarm64-freethreaded>`_ for the ARM64
|
||||
version. These packages contain both the ``python3.13t.exe`` and
|
||||
``python.exe`` entry points, both of which run free threaded.
|
||||
|
||||
.. _windows-embeddable:
|
||||
|
||||
|
|
|
@ -141,7 +141,7 @@ class LoaderTest(unittest.TestCase):
|
|||
def test_load_dll_with_flags(self):
|
||||
_sqlite3 = import_helper.import_module("_sqlite3")
|
||||
src = _sqlite3.__file__
|
||||
if src.lower().endswith("_d.pyd"):
|
||||
if src.partition(".")[0].lower().endswith("_d"):
|
||||
ext = "_d.dll"
|
||||
else:
|
||||
ext = ".dll"
|
||||
|
|
|
@ -19,8 +19,10 @@ import winreg
|
|||
|
||||
|
||||
PY_EXE = "py.exe"
|
||||
DEBUG_BUILD = False
|
||||
if sys.executable.casefold().endswith("_d.exe".casefold()):
|
||||
PY_EXE = "py_d.exe"
|
||||
DEBUG_BUILD = True
|
||||
|
||||
# Registry data to create. On removal, everything beneath top-level names will
|
||||
# be deleted.
|
||||
|
@ -232,7 +234,7 @@ class RunPyMixin:
|
|||
p.stdin.close()
|
||||
p.wait(10)
|
||||
out = p.stdout.read().decode("utf-8", "replace")
|
||||
err = p.stderr.read().decode("ascii", "replace")
|
||||
err = p.stderr.read().decode("ascii", "replace").replace("\uFFFD", "?")
|
||||
if p.returncode != expect_returncode and support.verbose and not allow_fail:
|
||||
print("++ COMMAND ++")
|
||||
print([self.py_exe, *args])
|
||||
|
@ -273,7 +275,7 @@ class RunPyMixin:
|
|||
def fake_venv(self):
|
||||
venv = Path.cwd() / "Scripts"
|
||||
venv.mkdir(exist_ok=True, parents=True)
|
||||
venv_exe = (venv / Path(sys.executable).name)
|
||||
venv_exe = (venv / ("python_d.exe" if DEBUG_BUILD else "python.exe"))
|
||||
venv_exe.touch()
|
||||
try:
|
||||
yield venv_exe, {"VIRTUAL_ENV": str(venv.parent)}
|
||||
|
@ -521,6 +523,9 @@ class TestLauncher(unittest.TestCase, RunPyMixin):
|
|||
self.assertEqual(str(venv_exe), m.group(1))
|
||||
break
|
||||
else:
|
||||
if support.verbose:
|
||||
print(data["stdout"])
|
||||
print(data["stderr"])
|
||||
self.fail("did not find active venv path")
|
||||
|
||||
data = self.run_py(["-0"], env=env)
|
||||
|
@ -616,25 +621,29 @@ class TestLauncher(unittest.TestCase, RunPyMixin):
|
|||
self.assertEqual("True", data["SearchInfo.oldStyleTag"])
|
||||
|
||||
def test_search_path(self):
|
||||
stem = Path(sys.executable).stem
|
||||
exe = Path("arbitrary-exe-name.exe").absolute()
|
||||
exe.touch()
|
||||
self.addCleanup(exe.unlink)
|
||||
with self.py_ini(TEST_PY_DEFAULTS):
|
||||
with self.script(f"#! /usr/bin/env {stem} -prearg") as script:
|
||||
with self.script(f"#! /usr/bin/env {exe.stem} -prearg") as script:
|
||||
data = self.run_py(
|
||||
[script, "-postarg"],
|
||||
env={"PATH": f"{Path(sys.executable).parent};{os.getenv('PATH')}"},
|
||||
env={"PATH": f"{exe.parent};{os.getenv('PATH')}"},
|
||||
)
|
||||
self.assertEqual(f"{sys.executable} -prearg {script} -postarg", data["stdout"].strip())
|
||||
self.assertEqual(f"{exe} -prearg {script} -postarg", data["stdout"].strip())
|
||||
|
||||
def test_search_path_exe(self):
|
||||
# Leave the .exe on the name to ensure we don't add it a second time
|
||||
name = Path(sys.executable).name
|
||||
exe = Path("arbitrary-exe-name.exe").absolute()
|
||||
exe.touch()
|
||||
self.addCleanup(exe.unlink)
|
||||
with self.py_ini(TEST_PY_DEFAULTS):
|
||||
with self.script(f"#! /usr/bin/env {name} -prearg") as script:
|
||||
with self.script(f"#! /usr/bin/env {exe.name} -prearg") as script:
|
||||
data = self.run_py(
|
||||
[script, "-postarg"],
|
||||
env={"PATH": f"{Path(sys.executable).parent};{os.getenv('PATH')}"},
|
||||
env={"PATH": f"{exe.parent};{os.getenv('PATH')}"},
|
||||
)
|
||||
self.assertEqual(f"{sys.executable} -prearg {script} -postarg", data["stdout"].strip())
|
||||
self.assertEqual(f"{exe} -prearg {script} -postarg", data["stdout"].strip())
|
||||
|
||||
def test_recursive_search_path(self):
|
||||
stem = self.get_py_exe().stem
|
||||
|
@ -727,15 +736,18 @@ class TestLauncher(unittest.TestCase, RunPyMixin):
|
|||
data = self.run_py([script], expect_returncode=103)
|
||||
|
||||
with self.fake_venv() as (venv_exe, env):
|
||||
# Put a real Python (ourselves) on PATH as a distraction.
|
||||
# Put a "normal" Python on PATH as a distraction.
|
||||
# The active VIRTUAL_ENV should be preferred when the name isn't an
|
||||
# exact match.
|
||||
env["PATH"] = f"{Path(sys.executable).parent};{os.environ['PATH']}"
|
||||
exe = Path(Path(venv_exe).name).absolute()
|
||||
exe.touch()
|
||||
self.addCleanup(exe.unlink)
|
||||
env["PATH"] = f"{exe.parent};{os.environ['PATH']}"
|
||||
|
||||
with self.script(f'#! /usr/bin/env {stem} arg1') as script:
|
||||
data = self.run_py([script], env=env)
|
||||
self.assertEqual(data["stdout"].strip(), f"{venv_exe} arg1 {script}")
|
||||
|
||||
with self.script(f'#! /usr/bin/env {Path(sys.executable).stem} arg1') as script:
|
||||
with self.script(f'#! /usr/bin/env {exe.stem} arg1') as script:
|
||||
data = self.run_py([script], env=env)
|
||||
self.assertEqual(data["stdout"].strip(), f"{sys.executable} arg1 {script}")
|
||||
self.assertEqual(data["stdout"].strip(), f"{exe} arg1 {script}")
|
||||
|
|
|
@ -845,6 +845,8 @@ class ProgramsTestCase(BaseTestCase):
|
|||
test_args.append('-x64') # 64-bit build
|
||||
if not support.Py_DEBUG:
|
||||
test_args.append('+d') # Release build, use python.exe
|
||||
if sysconfig.get_config_var("Py_GIL_DISABLED"):
|
||||
test_args.append('--disable-gil')
|
||||
self.run_batch(script, *test_args, *self.tests)
|
||||
|
||||
@unittest.skipUnless(sys.platform == 'win32', 'Windows only')
|
||||
|
@ -862,6 +864,8 @@ class ProgramsTestCase(BaseTestCase):
|
|||
rt_args.append('-x64') # 64-bit build
|
||||
if support.Py_DEBUG:
|
||||
rt_args.append('-d') # Debug build, use python_d.exe
|
||||
if sysconfig.get_config_var("Py_GIL_DISABLED"):
|
||||
rt_args.append('--disable-gil')
|
||||
self.run_batch(script, *rt_args, *self.regrtest_args, *self.tests)
|
||||
|
||||
|
||||
|
|
|
@ -223,8 +223,14 @@ class BasicTest(BaseTest):
|
|||
|
||||
def test_upgrade_dependencies(self):
|
||||
builder = venv.EnvBuilder()
|
||||
bin_path = 'Scripts' if sys.platform == 'win32' else 'bin'
|
||||
bin_path = 'bin'
|
||||
python_exe = os.path.split(sys.executable)[1]
|
||||
if sys.platform == 'win32':
|
||||
bin_path = 'Scripts'
|
||||
if os.path.normcase(os.path.splitext(python_exe)[0]).endswith('_d'):
|
||||
python_exe = 'python_d.exe'
|
||||
else:
|
||||
python_exe = 'python.exe'
|
||||
with tempfile.TemporaryDirectory() as fake_env_dir:
|
||||
expect_exe = os.path.normcase(
|
||||
os.path.join(fake_env_dir, bin_path, python_exe)
|
||||
|
@ -283,7 +289,9 @@ class BasicTest(BaseTest):
|
|||
# build environment
|
||||
('is_python_build()', str(sysconfig.is_python_build())),
|
||||
('get_makefile_filename()', sysconfig.get_makefile_filename()),
|
||||
('get_config_h_filename()', sysconfig.get_config_h_filename())):
|
||||
('get_config_h_filename()', sysconfig.get_config_h_filename()),
|
||||
('get_config_var("Py_GIL_DISABLED")',
|
||||
str(sysconfig.get_config_var("Py_GIL_DISABLED")))):
|
||||
with self.subTest(call):
|
||||
cmd[2] = 'import sysconfig; print(sysconfig.%s)' % call
|
||||
out, err = check_output(cmd, encoding='utf-8')
|
||||
|
@ -315,7 +323,9 @@ class BasicTest(BaseTest):
|
|||
# build environment
|
||||
('is_python_build()', str(sysconfig.is_python_build())),
|
||||
('get_makefile_filename()', sysconfig.get_makefile_filename()),
|
||||
('get_config_h_filename()', sysconfig.get_config_h_filename())):
|
||||
('get_config_h_filename()', sysconfig.get_config_h_filename()),
|
||||
('get_config_var("Py_GIL_DISABLED")',
|
||||
str(sysconfig.get_config_var("Py_GIL_DISABLED")))):
|
||||
with self.subTest(call):
|
||||
cmd[2] = 'import sysconfig; print(sysconfig.%s)' % call
|
||||
out, err = check_output(cmd, encoding='utf-8')
|
||||
|
|
|
@ -139,6 +139,11 @@ class EnvBuilder:
|
|||
'check that your PATH environment variable is '
|
||||
'correctly set.')
|
||||
dirname, exename = os.path.split(os.path.abspath(executable))
|
||||
if sys.platform == 'win32':
|
||||
# Always create the simplest name in the venv. It will either be a
|
||||
# link back to executable, or a copy of the appropriate launcher
|
||||
_d = '_d' if os.path.splitext(exename)[0].endswith('_d') else ''
|
||||
exename = f'python{_d}.exe'
|
||||
context.executable = executable
|
||||
context.python_dir = dirname
|
||||
context.python_exe = exename
|
||||
|
@ -222,11 +227,13 @@ class EnvBuilder:
|
|||
args = ' '.join(args)
|
||||
f.write(f'command = {sys.executable} -m venv {args}\n')
|
||||
|
||||
if os.name != 'nt':
|
||||
def symlink_or_copy(self, src, dst, relative_symlinks_ok=False):
|
||||
"""
|
||||
Try symlinking a file, and if that fails, fall back to copying.
|
||||
(Unused on Windows, because we can't just copy a failed symlink file: we
|
||||
switch to a different set of files instead.)
|
||||
"""
|
||||
assert os.name != 'nt'
|
||||
force_copy = not self.symlinks
|
||||
if not force_copy:
|
||||
try:
|
||||
|
@ -241,49 +248,6 @@ class EnvBuilder:
|
|||
force_copy = True
|
||||
if force_copy:
|
||||
shutil.copyfile(src, dst)
|
||||
else:
|
||||
def symlink_or_copy(self, src, dst, relative_symlinks_ok=False):
|
||||
"""
|
||||
Try symlinking a file, and if that fails, fall back to copying.
|
||||
"""
|
||||
bad_src = os.path.lexists(src) and not os.path.exists(src)
|
||||
if self.symlinks and not bad_src and not os.path.islink(dst):
|
||||
try:
|
||||
if relative_symlinks_ok:
|
||||
assert os.path.dirname(src) == os.path.dirname(dst)
|
||||
os.symlink(os.path.basename(src), dst)
|
||||
else:
|
||||
os.symlink(src, dst)
|
||||
return
|
||||
except Exception: # may need to use a more specific exception
|
||||
logger.warning('Unable to symlink %r to %r', src, dst)
|
||||
|
||||
# On Windows, we rewrite symlinks to our base python.exe into
|
||||
# copies of venvlauncher.exe
|
||||
basename, ext = os.path.splitext(os.path.basename(src))
|
||||
srcfn = os.path.join(os.path.dirname(__file__),
|
||||
"scripts",
|
||||
"nt",
|
||||
basename + ext)
|
||||
# Builds or venv's from builds need to remap source file
|
||||
# locations, as we do not put them into Lib/venv/scripts
|
||||
if sysconfig.is_python_build() or not os.path.isfile(srcfn):
|
||||
if basename.endswith('_d'):
|
||||
ext = '_d' + ext
|
||||
basename = basename[:-2]
|
||||
if basename == 'python':
|
||||
basename = 'venvlauncher'
|
||||
elif basename == 'pythonw':
|
||||
basename = 'venvwlauncher'
|
||||
src = os.path.join(os.path.dirname(src), basename + ext)
|
||||
else:
|
||||
src = srcfn
|
||||
if not os.path.exists(src):
|
||||
if not bad_src:
|
||||
logger.warning('Unable to copy %r', src)
|
||||
return
|
||||
|
||||
shutil.copyfile(src, dst)
|
||||
|
||||
def create_git_ignore_file(self, context):
|
||||
"""
|
||||
|
@ -298,6 +262,7 @@ class EnvBuilder:
|
|||
'see https://docs.python.org/3/library/venv.html\n')
|
||||
file.write('*\n')
|
||||
|
||||
if os.name != 'nt':
|
||||
def setup_python(self, context):
|
||||
"""
|
||||
Set up a Python executable in the environment.
|
||||
|
@ -309,11 +274,11 @@ class EnvBuilder:
|
|||
path = context.env_exe
|
||||
copier = self.symlink_or_copy
|
||||
dirname = context.python_dir
|
||||
if os.name != 'nt':
|
||||
copier(context.executable, path)
|
||||
if not os.path.islink(path):
|
||||
os.chmod(path, 0o755)
|
||||
for suffix in ('python', 'python3', f'python3.{sys.version_info[1]}'):
|
||||
for suffix in ('python', 'python3',
|
||||
f'python3.{sys.version_info[1]}'):
|
||||
path = os.path.join(binpath, suffix)
|
||||
if not os.path.exists(path):
|
||||
# Issue 18807: make copies if
|
||||
|
@ -321,30 +286,105 @@ class EnvBuilder:
|
|||
copier(context.env_exe, path, relative_symlinks_ok=True)
|
||||
if not os.path.islink(path):
|
||||
os.chmod(path, 0o755)
|
||||
else:
|
||||
if self.symlinks:
|
||||
# For symlinking, we need a complete copy of the root directory
|
||||
# If symlinks fail, you'll get unnecessary copies of files, but
|
||||
# we assume that if you've opted into symlinks on Windows then
|
||||
# you know what you're doing.
|
||||
suffixes = [
|
||||
f for f in os.listdir(dirname) if
|
||||
os.path.normcase(os.path.splitext(f)[1]) in ('.exe', '.dll')
|
||||
]
|
||||
if sysconfig.is_python_build():
|
||||
suffixes = [
|
||||
f for f in suffixes if
|
||||
os.path.normcase(f).startswith(('python', 'vcruntime'))
|
||||
]
|
||||
else:
|
||||
suffixes = {'python.exe', 'python_d.exe', 'pythonw.exe', 'pythonw_d.exe'}
|
||||
base_exe = os.path.basename(context.env_exe)
|
||||
suffixes.add(base_exe)
|
||||
|
||||
for suffix in suffixes:
|
||||
src = os.path.join(dirname, suffix)
|
||||
if os.path.lexists(src):
|
||||
copier(src, os.path.join(binpath, suffix))
|
||||
else:
|
||||
def setup_python(self, context):
|
||||
"""
|
||||
Set up a Python executable in the environment.
|
||||
|
||||
:param context: The information for the environment creation request
|
||||
being processed.
|
||||
"""
|
||||
binpath = context.bin_path
|
||||
dirname = context.python_dir
|
||||
exename = os.path.basename(context.env_exe)
|
||||
exe_stem = os.path.splitext(exename)[0]
|
||||
exe_d = '_d' if os.path.normcase(exe_stem).endswith('_d') else ''
|
||||
if sysconfig.is_python_build():
|
||||
scripts = dirname
|
||||
else:
|
||||
scripts = os.path.join(os.path.dirname(__file__),
|
||||
'scripts', 'nt')
|
||||
if not sysconfig.get_config_var("Py_GIL_DISABLED"):
|
||||
python_exe = os.path.join(dirname, f'python{exe_d}.exe')
|
||||
pythonw_exe = os.path.join(dirname, f'pythonw{exe_d}.exe')
|
||||
link_sources = {
|
||||
'python.exe': python_exe,
|
||||
f'python{exe_d}.exe': python_exe,
|
||||
'pythonw.exe': pythonw_exe,
|
||||
f'pythonw{exe_d}.exe': pythonw_exe,
|
||||
}
|
||||
python_exe = os.path.join(scripts, f'venvlauncher{exe_d}.exe')
|
||||
pythonw_exe = os.path.join(scripts, f'venvwlauncher{exe_d}.exe')
|
||||
copy_sources = {
|
||||
'python.exe': python_exe,
|
||||
f'python{exe_d}.exe': python_exe,
|
||||
'pythonw.exe': pythonw_exe,
|
||||
f'pythonw{exe_d}.exe': pythonw_exe,
|
||||
}
|
||||
else:
|
||||
exe_t = f'3.{sys.version_info[1]}t'
|
||||
python_exe = os.path.join(dirname, f'python{exe_t}{exe_d}.exe')
|
||||
pythonw_exe = os.path.join(dirname, f'pythonw{exe_t}{exe_d}.exe')
|
||||
link_sources = {
|
||||
'python.exe': python_exe,
|
||||
f'python{exe_d}.exe': python_exe,
|
||||
f'python{exe_t}.exe': python_exe,
|
||||
f'python{exe_t}{exe_d}.exe': python_exe,
|
||||
'pythonw.exe': pythonw_exe,
|
||||
f'pythonw{exe_d}.exe': pythonw_exe,
|
||||
f'pythonw{exe_t}.exe': pythonw_exe,
|
||||
f'pythonw{exe_t}{exe_d}.exe': pythonw_exe,
|
||||
}
|
||||
python_exe = os.path.join(scripts, f'venvlaunchert{exe_d}.exe')
|
||||
pythonw_exe = os.path.join(scripts, f'venvwlaunchert{exe_d}.exe')
|
||||
copy_sources = {
|
||||
'python.exe': python_exe,
|
||||
f'python{exe_d}.exe': python_exe,
|
||||
f'python{exe_t}.exe': python_exe,
|
||||
f'python{exe_t}{exe_d}.exe': python_exe,
|
||||
'pythonw.exe': pythonw_exe,
|
||||
f'pythonw{exe_d}.exe': pythonw_exe,
|
||||
f'pythonw{exe_t}.exe': pythonw_exe,
|
||||
f'pythonw{exe_t}{exe_d}.exe': pythonw_exe,
|
||||
}
|
||||
|
||||
do_copies = True
|
||||
if self.symlinks:
|
||||
do_copies = False
|
||||
# For symlinking, we need all the DLLs to be available alongside
|
||||
# the executables.
|
||||
link_sources.update({
|
||||
f: os.path.join(dirname, f) for f in os.listdir(dirname)
|
||||
if os.path.normcase(f).startswith(('python', 'vcruntime'))
|
||||
and os.path.normcase(os.path.splitext(f)[1]) == '.dll'
|
||||
})
|
||||
|
||||
to_unlink = []
|
||||
for dest, src in link_sources.items():
|
||||
dest = os.path.join(binpath, dest)
|
||||
try:
|
||||
os.symlink(src, dest)
|
||||
to_unlink.append(dest)
|
||||
except OSError:
|
||||
logger.warning('Unable to symlink %r to %r', src, dst)
|
||||
do_copies = True
|
||||
for f in to_unlink:
|
||||
try:
|
||||
os.unlink(f)
|
||||
except OSError:
|
||||
logger.warning('Failed to clean up symlink %r',
|
||||
f)
|
||||
logger.warning('Retrying with copies')
|
||||
break
|
||||
|
||||
if do_copies:
|
||||
for dest, src in copy_sources.items():
|
||||
dest = os.path.join(binpath, dest)
|
||||
try:
|
||||
shutil.copy2(src, dest)
|
||||
except OSError:
|
||||
logger.warning('Unable to copy %r to %r', src, dest)
|
||||
|
||||
if sysconfig.is_python_build():
|
||||
# copy init.tcl
|
||||
|
@ -437,6 +477,14 @@ class EnvBuilder:
|
|||
"""
|
||||
binpath = context.bin_path
|
||||
plen = len(path)
|
||||
if os.name == 'nt':
|
||||
def skip_file(f):
|
||||
f = os.path.normcase(f)
|
||||
return (f.startswith(('python', 'venv'))
|
||||
and f.endswith(('.exe', '.pdb')))
|
||||
else:
|
||||
def skip_file(f):
|
||||
return False
|
||||
for root, dirs, files in os.walk(path):
|
||||
if root == path: # at top-level, remove irrelevant dirs
|
||||
for d in dirs[:]:
|
||||
|
@ -444,8 +492,7 @@ class EnvBuilder:
|
|||
dirs.remove(d)
|
||||
continue # ignore files in top level
|
||||
for f in files:
|
||||
if (os.name == 'nt' and f.startswith('python')
|
||||
and f.endswith(('.exe', '.pdb'))):
|
||||
if skip_file(f):
|
||||
continue
|
||||
srcfile = os.path.join(root, f)
|
||||
suffix = root[plen:].split(os.sep)[2:]
|
||||
|
@ -456,20 +503,25 @@ class EnvBuilder:
|
|||
if not os.path.exists(dstdir):
|
||||
os.makedirs(dstdir)
|
||||
dstfile = os.path.join(dstdir, f)
|
||||
if os.name == 'nt' and srcfile.endswith(('.exe', '.pdb')):
|
||||
shutil.copy2(srcfile, dstfile)
|
||||
continue
|
||||
with open(srcfile, 'rb') as f:
|
||||
data = f.read()
|
||||
if not srcfile.endswith(('.exe', '.pdb')):
|
||||
try:
|
||||
data = data.decode('utf-8')
|
||||
data = self.replace_variables(data, context)
|
||||
data = data.encode('utf-8')
|
||||
new_data = (
|
||||
self.replace_variables(data.decode('utf-8'), context)
|
||||
.encode('utf-8')
|
||||
)
|
||||
except UnicodeError as e:
|
||||
data = None
|
||||
logger.warning('unable to copy script %r, '
|
||||
'may be binary: %s', srcfile, e)
|
||||
if data is not None:
|
||||
continue
|
||||
if new_data == data:
|
||||
shutil.copy2(srcfile, dstfile)
|
||||
else:
|
||||
with open(dstfile, 'wb') as f:
|
||||
f.write(data)
|
||||
f.write(new_data)
|
||||
shutil.copymode(srcfile, dstfile)
|
||||
|
||||
def upgrade_dependencies(self, context):
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Adds free-threaded binaries to Windows installer as an optional component.
|
|
@ -41,7 +41,7 @@ TCLTK_FILES_ONLY = FileNameSet("turtle.py")
|
|||
|
||||
VENV_DIRS_ONLY = FileNameSet("venv", "ensurepip")
|
||||
|
||||
EXCLUDE_FROM_PYDS = FileStemSet("python*", "pyshellext", "vcruntime*")
|
||||
EXCLUDE_FROM_DLLS = FileStemSet("python*", "pyshellext", "vcruntime*")
|
||||
EXCLUDE_FROM_LIB = FileNameSet("*.pyc", "__pycache__", "*.pickle")
|
||||
EXCLUDE_FROM_PACKAGED_LIB = FileNameSet("readme.txt")
|
||||
EXCLUDE_FROM_COMPILE = FileNameSet("badsyntax_*", "bad_*")
|
||||
|
@ -126,9 +126,9 @@ def get_layout(ns):
|
|||
n = new_name or n
|
||||
src = ns.build / f
|
||||
if ns.debug and src not in REQUIRED_DLLS:
|
||||
if not src.stem.endswith("_d"):
|
||||
if not "_d." in src.name:
|
||||
src = src.parent / (src.stem + "_d" + src.suffix)
|
||||
if not n.endswith("_d"):
|
||||
if "_d." not in f:
|
||||
n += "_d"
|
||||
f = n + "." + x
|
||||
yield dest + n + "." + x, src
|
||||
|
@ -141,16 +141,44 @@ def get_layout(ns):
|
|||
if lib.is_file():
|
||||
yield "libs/" + n + ".lib", lib
|
||||
|
||||
source = "python.exe"
|
||||
sourcew = "pythonw.exe"
|
||||
alias = [
|
||||
"python",
|
||||
"python{}".format(VER_MAJOR) if ns.include_alias3 else "",
|
||||
"python{}".format(VER_DOT) if ns.include_alias3x else "",
|
||||
]
|
||||
aliasw = [
|
||||
"pythonw",
|
||||
"pythonw{}".format(VER_MAJOR) if ns.include_alias3 else "",
|
||||
"pythonw{}".format(VER_DOT) if ns.include_alias3x else "",
|
||||
]
|
||||
if ns.include_appxmanifest:
|
||||
yield from in_build("python_uwp.exe", new_name="python{}".format(VER_DOT))
|
||||
yield from in_build("pythonw_uwp.exe", new_name="pythonw{}".format(VER_DOT))
|
||||
# For backwards compatibility, but we don't reference these ourselves.
|
||||
yield from in_build("python_uwp.exe", new_name="python")
|
||||
yield from in_build("pythonw_uwp.exe", new_name="pythonw")
|
||||
else:
|
||||
yield from in_build("python.exe", new_name="python")
|
||||
yield from in_build("pythonw.exe", new_name="pythonw")
|
||||
source = "python_uwp.exe"
|
||||
sourcew = "pythonw_uwp.exe"
|
||||
elif ns.include_freethreaded:
|
||||
source = "python{}t.exe".format(VER_DOT)
|
||||
sourcew = "pythonw{}t.exe".format(VER_DOT)
|
||||
if not ns.include_alias:
|
||||
alias = []
|
||||
aliasw = []
|
||||
alias.extend([
|
||||
"python{}t".format(VER_DOT),
|
||||
"python{}t".format(VER_MAJOR) if ns.include_alias3 else None,
|
||||
])
|
||||
aliasw.extend([
|
||||
"pythonw{}t".format(VER_DOT),
|
||||
"pythonw{}t".format(VER_MAJOR) if ns.include_alias3 else None,
|
||||
])
|
||||
|
||||
for a in filter(None, alias):
|
||||
yield from in_build(source, new_name=a)
|
||||
for a in filter(None, aliasw):
|
||||
yield from in_build(sourcew, new_name=a)
|
||||
|
||||
if ns.include_freethreaded:
|
||||
yield from in_build(FREETHREADED_PYTHON_DLL_NAME)
|
||||
else:
|
||||
yield from in_build(PYTHON_DLL_NAME)
|
||||
|
||||
if ns.include_launchers and ns.include_appxmanifest:
|
||||
|
@ -160,6 +188,9 @@ def get_layout(ns):
|
|||
yield from in_build("pythonw_uwp.exe", new_name="idle{}".format(VER_DOT))
|
||||
|
||||
if ns.include_stable:
|
||||
if ns.include_freethreaded:
|
||||
yield from in_build(FREETHREADED_PYTHON_STABLE_DLL_NAME)
|
||||
else:
|
||||
yield from in_build(PYTHON_STABLE_DLL_NAME)
|
||||
|
||||
found_any = False
|
||||
|
@ -171,16 +202,28 @@ def get_layout(ns):
|
|||
|
||||
yield "LICENSE.txt", ns.build / "LICENSE.txt"
|
||||
|
||||
for dest, src in rglob(ns.build, ("*.pyd", "*.dll")):
|
||||
if src.stem.endswith("_d") != bool(ns.debug) and src not in REQUIRED_DLLS:
|
||||
for dest, src in rglob(ns.build, "*.pyd"):
|
||||
if ns.include_freethreaded:
|
||||
if not src.match("*.cp*t-win*.pyd"):
|
||||
continue
|
||||
if src in EXCLUDE_FROM_PYDS:
|
||||
if bool(src.match("*_d.cp*.pyd")) != bool(ns.debug):
|
||||
continue
|
||||
else:
|
||||
if src.match("*.cp*t-win*.pyd"):
|
||||
continue
|
||||
if bool(src.match("*_d.pyd")) != bool(ns.debug):
|
||||
continue
|
||||
if src in TEST_PYDS_ONLY and not ns.include_tests:
|
||||
continue
|
||||
if src in TCLTK_PYDS_ONLY and not ns.include_tcltk:
|
||||
continue
|
||||
yield from in_build(src.name, dest="" if ns.flat_dlls else "DLLs/")
|
||||
|
||||
for dest, src in rglob(ns.build, "*.dll"):
|
||||
if src.stem.endswith("_d") != bool(ns.debug) and src not in REQUIRED_DLLS:
|
||||
continue
|
||||
if src in EXCLUDE_FROM_DLLS:
|
||||
continue
|
||||
yield from in_build(src.name, dest="" if ns.flat_dlls else "DLLs/")
|
||||
|
||||
if ns.zip_lib:
|
||||
|
@ -191,8 +234,12 @@ def get_layout(ns):
|
|||
yield "Lib/{}".format(dest), src
|
||||
|
||||
if ns.include_venv:
|
||||
yield from in_build("venvlauncher.exe", "Lib/venv/scripts/nt/", "python")
|
||||
yield from in_build("venvwlauncher.exe", "Lib/venv/scripts/nt/", "pythonw")
|
||||
if ns.include_freethreaded:
|
||||
yield from in_build("venvlaunchert.exe", "Lib/venv/scripts/nt/")
|
||||
yield from in_build("venvwlaunchert.exe", "Lib/venv/scripts/nt/")
|
||||
else:
|
||||
yield from in_build("venvlauncher.exe", "Lib/venv/scripts/nt/")
|
||||
yield from in_build("venvwlauncher.exe", "Lib/venv/scripts/nt/")
|
||||
|
||||
if ns.include_tools:
|
||||
|
||||
|
@ -208,7 +255,6 @@ def get_layout(ns):
|
|||
yield PYTHON_PTH_NAME, ns.temp / PYTHON_PTH_NAME
|
||||
|
||||
if ns.include_dev:
|
||||
|
||||
for dest, src in rglob(ns.source / "Include", "**/*.h"):
|
||||
yield "include/{}".format(dest), src
|
||||
yield "include/pyconfig.h", ns.build / "pyconfig.h"
|
||||
|
@ -552,7 +598,6 @@ def main():
|
|||
|
||||
ns.source = ns.source or (Path(__file__).resolve().parent.parent.parent)
|
||||
ns.build = ns.build or Path(sys.executable).parent
|
||||
ns.temp = ns.temp or Path(tempfile.mkdtemp())
|
||||
ns.doc_build = ns.doc_build or (ns.source / "Doc" / "build")
|
||||
if not ns.source.is_absolute():
|
||||
ns.source = (Path.cwd() / ns.source).resolve()
|
||||
|
@ -565,7 +610,12 @@ def main():
|
|||
if ns.include_cat and not ns.include_cat.is_absolute():
|
||||
ns.include_cat = (Path.cwd() / ns.include_cat).resolve()
|
||||
if not ns.arch:
|
||||
ns.arch = "amd64" if sys.maxsize > 2 ** 32 else "win32"
|
||||
if sys.winver.endswith("-arm64"):
|
||||
ns.arch = "arm64"
|
||||
elif sys.winver.endswith("-32"):
|
||||
ns.arch = "win32"
|
||||
else:
|
||||
ns.arch = "amd64"
|
||||
|
||||
if ns.copy and not ns.copy.is_absolute():
|
||||
ns.copy = (Path.cwd() / ns.copy).resolve()
|
||||
|
@ -574,6 +624,14 @@ def main():
|
|||
if ns.catalog and not ns.catalog.is_absolute():
|
||||
ns.catalog = (Path.cwd() / ns.catalog).resolve()
|
||||
|
||||
if not ns.temp:
|
||||
# Put temp on a Dev Drive for speed if we're copying to one.
|
||||
# If not, the regular temp dir will have to do.
|
||||
if ns.copy and getattr(os.path, "isdevdrive", lambda d: False)(ns.copy):
|
||||
ns.temp = ns.copy.with_name(ns.copy.name + "_temp")
|
||||
else:
|
||||
ns.temp = Path(tempfile.mkdtemp())
|
||||
|
||||
configure_logger(ns)
|
||||
|
||||
log_info(
|
||||
|
@ -602,6 +660,12 @@ Catalog: {ns.catalog}""",
|
|||
log_warning("Assuming --include-tcltk to support --include-idle")
|
||||
ns.include_tcltk = True
|
||||
|
||||
if not (ns.include_alias or ns.include_alias3 or ns.include_alias3x):
|
||||
if ns.include_freethreaded:
|
||||
ns.include_alias3x = True
|
||||
else:
|
||||
ns.include_alias = True
|
||||
|
||||
try:
|
||||
generate_source_files(ns)
|
||||
files = list(get_layout(ns))
|
||||
|
|
|
@ -39,3 +39,6 @@ PYTHON_PTH_NAME = "python{}{}._pth".format(VER_MAJOR, VER_MINOR)
|
|||
PYTHON_CHM_NAME = "python{}{}{}{}.chm".format(
|
||||
VER_MAJOR, VER_MINOR, VER_MICRO, VER_SUFFIX
|
||||
)
|
||||
|
||||
FREETHREADED_PYTHON_DLL_NAME = "python{}{}t.dll".format(VER_MAJOR, VER_MINOR)
|
||||
FREETHREADED_PYTHON_STABLE_DLL_NAME = "python{}t.dll".format(VER_MAJOR)
|
||||
|
|
|
@ -24,6 +24,10 @@ NUSPEC_PLATFORM_DATA = dict(
|
|||
amd64=("64-bit", "python", "Python"),
|
||||
arm32=("ARM", "pythonarm", "Python (ARM)"),
|
||||
arm64=("ARM64", "pythonarm64", "Python (ARM64)"),
|
||||
win32t=("32-bit free-threaded", "pythonx86-freethreaded", "Python (32-bit, free-threaded)"),
|
||||
amd64t=("64-bit free-threaded", "python-freethreaded", "Python (free-threaded)"),
|
||||
arm32t=("ARM free-threaded", "pythonarm-freethreaded", "Python (ARM, free-threaded)"),
|
||||
arm64t=("ARM64 free-threaded", "pythonarm64-freethreaded", "Python (ARM64, free-threaded)"),
|
||||
)
|
||||
|
||||
if not NUSPEC_DATA["PYTHON_VERSION"]:
|
||||
|
@ -58,7 +62,10 @@ NUSPEC_TEMPLATE = r"""<?xml version="1.0"?>
|
|||
|
||||
|
||||
def _get_nuspec_data_overrides(ns):
|
||||
for k, v in zip(NUSPEC_PLATFORM_DATA["_keys"], NUSPEC_PLATFORM_DATA[ns.arch]):
|
||||
arch = ns.arch
|
||||
if ns.include_freethreaded:
|
||||
arch += "t"
|
||||
for k, v in zip(NUSPEC_PLATFORM_DATA["_keys"], NUSPEC_PLATFORM_DATA[arch]):
|
||||
ev = os.getenv("PYTHON_NUSPEC_" + k)
|
||||
if ev:
|
||||
yield k, ev
|
||||
|
|
|
@ -32,6 +32,10 @@ OPTIONS = {
|
|||
"nuspec": {"help": "a python.nuspec file"},
|
||||
"chm": {"help": "the CHM documentation"},
|
||||
"html-doc": {"help": "the HTML documentation"},
|
||||
"freethreaded": {"help": "freethreaded binaries", "not-in-all": True},
|
||||
"alias": {"help": "aliased python.exe entry-point binaries"},
|
||||
"alias3": {"help": "aliased python3.exe entry-point binaries"},
|
||||
"alias3x": {"help": "aliased python3.x.exe entry-point binaries"},
|
||||
}
|
||||
|
||||
|
||||
|
@ -47,6 +51,8 @@ PRESETS = {
|
|||
"dev",
|
||||
"launchers",
|
||||
"appxmanifest",
|
||||
"alias",
|
||||
"alias3x",
|
||||
# XXX: Disabled for now "precompile",
|
||||
],
|
||||
},
|
||||
|
@ -59,9 +65,10 @@ PRESETS = {
|
|||
"venv",
|
||||
"props",
|
||||
"nuspec",
|
||||
"alias",
|
||||
],
|
||||
},
|
||||
"iot": {"help": "Windows IoT Core", "options": ["stable", "pip"]},
|
||||
"iot": {"help": "Windows IoT Core", "options": ["alias", "stable", "pip"]},
|
||||
"default": {
|
||||
"help": "development kit package",
|
||||
"options": [
|
||||
|
@ -74,11 +81,19 @@ PRESETS = {
|
|||
"dev",
|
||||
"symbols",
|
||||
"html-doc",
|
||||
"alias",
|
||||
],
|
||||
},
|
||||
"embed": {
|
||||
"help": "embeddable package",
|
||||
"options": ["stable", "zip-lib", "flat-dlls", "underpth", "precompile"],
|
||||
"options": [
|
||||
"alias",
|
||||
"stable",
|
||||
"zip-lib",
|
||||
"flat-dlls",
|
||||
"underpth",
|
||||
"precompile",
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
|
|
|
@ -94,6 +94,9 @@ WIN32 is still required for the locale module.
|
|||
#endif
|
||||
#endif /* Py_BUILD_CORE || Py_BUILD_CORE_BUILTIN || Py_BUILD_CORE_MODULE */
|
||||
|
||||
/* Define to 1 if you want to disable the GIL */
|
||||
#undef Py_GIL_DISABLED
|
||||
|
||||
/* Compiler specific defines */
|
||||
|
||||
/* ------------------------------------------------------------------------*/
|
||||
|
@ -305,8 +308,16 @@ Py_NO_ENABLE_SHARED to find out. Also support MS_NO_COREDLL for b/w compat */
|
|||
/* not building the core - must be an ext */
|
||||
# if defined(_MSC_VER)
|
||||
/* So MSVC users need not specify the .lib
|
||||
file in their Makefile (other compilers are
|
||||
generally taken care of by distutils.) */
|
||||
file in their Makefile */
|
||||
# if defined(Py_GIL_DISABLED)
|
||||
# if defined(_DEBUG)
|
||||
# pragma comment(lib,"python313t_d.lib")
|
||||
# elif defined(Py_LIMITED_API)
|
||||
# pragma comment(lib,"python3t.lib")
|
||||
# else
|
||||
# pragma comment(lib,"python313t.lib")
|
||||
# endif /* _DEBUG */
|
||||
# else /* Py_GIL_DISABLED */
|
||||
# if defined(_DEBUG)
|
||||
# pragma comment(lib,"python313_d.lib")
|
||||
# elif defined(Py_LIMITED_API)
|
||||
|
@ -314,6 +325,7 @@ Py_NO_ENABLE_SHARED to find out. Also support MS_NO_COREDLL for b/w compat */
|
|||
# else
|
||||
# pragma comment(lib,"python313.lib")
|
||||
# endif /* _DEBUG */
|
||||
# endif /* Py_GIL_DISABLED */
|
||||
# endif /* _MSC_VER */
|
||||
# endif /* Py_BUILD_CORE */
|
||||
#endif /* MS_COREDLL */
|
||||
|
@ -739,7 +751,4 @@ Py_NO_ENABLE_SHARED to find out. Also support MS_NO_COREDLL for b/w compat */
|
|||
/* Define if libssl has X509_VERIFY_PARAM_set1_host and related function */
|
||||
#define HAVE_X509_VERIFY_PARAM_SET1_HOST 1
|
||||
|
||||
/* Define if you want to disable the GIL */
|
||||
#undef Py_GIL_DISABLED
|
||||
|
||||
#endif /* !Py_CONFIG_H */
|
||||
|
|
|
@ -0,0 +1,510 @@
|
|||
/*
|
||||
* venv redirector for Windows
|
||||
*
|
||||
* This launcher looks for a nearby pyvenv.cfg to find the correct home
|
||||
* directory, and then launches the original Python executable from it.
|
||||
* The name of this executable is passed as argv[0].
|
||||
*/
|
||||
|
||||
#define __STDC_WANT_LIB_EXT1__ 1
|
||||
|
||||
#include <windows.h>
|
||||
#include <pathcch.h>
|
||||
#include <fcntl.h>
|
||||
#include <io.h>
|
||||
#include <shlobj.h>
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
#include <tchar.h>
|
||||
#include <assert.h>
|
||||
|
||||
#define MS_WINDOWS
|
||||
#include "patchlevel.h"
|
||||
|
||||
#define MAXLEN PATHCCH_MAX_CCH
|
||||
#define MSGSIZE 1024
|
||||
|
||||
#define RC_NO_STD_HANDLES 100
|
||||
#define RC_CREATE_PROCESS 101
|
||||
#define RC_NO_PYTHON 103
|
||||
#define RC_NO_MEMORY 104
|
||||
#define RC_NO_VENV_CFG 106
|
||||
#define RC_BAD_VENV_CFG 107
|
||||
#define RC_NO_COMMANDLINE 108
|
||||
#define RC_INTERNAL_ERROR 109
|
||||
|
||||
// This should always be defined when we build for real,
|
||||
// but it's handy to have a definition for quick testing
|
||||
#ifndef EXENAME
|
||||
#define EXENAME L"python.exe"
|
||||
#endif
|
||||
|
||||
#ifndef CFGNAME
|
||||
#define CFGNAME L"pyvenv.cfg"
|
||||
#endif
|
||||
|
||||
static FILE * log_fp = NULL;
|
||||
|
||||
void
|
||||
debug(wchar_t * format, ...)
|
||||
{
|
||||
va_list va;
|
||||
|
||||
if (log_fp != NULL) {
|
||||
wchar_t buffer[MAXLEN];
|
||||
int r = 0;
|
||||
va_start(va, format);
|
||||
r = vswprintf_s(buffer, MAXLEN, format, va);
|
||||
va_end(va);
|
||||
|
||||
if (r <= 0) {
|
||||
return;
|
||||
}
|
||||
fwprintf(log_fp, L"%ls\n", buffer);
|
||||
while (r && isspace(buffer[r])) {
|
||||
buffer[r--] = L'\0';
|
||||
}
|
||||
if (buffer[0]) {
|
||||
OutputDebugStringW(buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
formatWinerror(int rc, wchar_t * message, int size)
|
||||
{
|
||||
FormatMessageW(
|
||||
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL, rc, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||
message, size, NULL);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
winerror(int err, wchar_t * format, ... )
|
||||
{
|
||||
va_list va;
|
||||
wchar_t message[MSGSIZE];
|
||||
wchar_t win_message[MSGSIZE];
|
||||
int len;
|
||||
|
||||
if (err == 0) {
|
||||
err = GetLastError();
|
||||
}
|
||||
|
||||
va_start(va, format);
|
||||
len = _vsnwprintf_s(message, MSGSIZE, _TRUNCATE, format, va);
|
||||
va_end(va);
|
||||
|
||||
formatWinerror(err, win_message, MSGSIZE);
|
||||
if (len >= 0) {
|
||||
_snwprintf_s(&message[len], MSGSIZE - len, _TRUNCATE, L": %ls",
|
||||
win_message);
|
||||
}
|
||||
|
||||
#if !defined(_WINDOWS)
|
||||
fwprintf(stderr, L"%ls\n", message);
|
||||
#else
|
||||
MessageBoxW(NULL, message, L"Python venv launcher is sorry to say ...",
|
||||
MB_OK);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
error(wchar_t * format, ... )
|
||||
{
|
||||
va_list va;
|
||||
wchar_t message[MSGSIZE];
|
||||
|
||||
va_start(va, format);
|
||||
_vsnwprintf_s(message, MSGSIZE, _TRUNCATE, format, va);
|
||||
va_end(va);
|
||||
|
||||
#if !defined(_WINDOWS)
|
||||
fwprintf(stderr, L"%ls\n", message);
|
||||
#else
|
||||
MessageBoxW(NULL, message, L"Python venv launcher is sorry to say ...",
|
||||
MB_OK);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
isEnvVarSet(const wchar_t *name)
|
||||
{
|
||||
/* only looking for non-empty, which means at least one character
|
||||
and the null terminator */
|
||||
return GetEnvironmentVariableW(name, NULL, 0) >= 2;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
join(wchar_t *buffer, size_t bufferLength, const wchar_t *fragment)
|
||||
{
|
||||
if (SUCCEEDED(PathCchCombineEx(buffer, bufferLength, buffer, fragment, PATHCCH_ALLOW_LONG_PATHS))) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
split_parent(wchar_t *buffer, size_t bufferLength)
|
||||
{
|
||||
return SUCCEEDED(PathCchRemoveFileSpec(buffer, bufferLength));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Path calculation
|
||||
*/
|
||||
|
||||
int
|
||||
calculate_pyvenvcfg_path(wchar_t *pyvenvcfg_path, size_t maxlen)
|
||||
{
|
||||
if (!pyvenvcfg_path) {
|
||||
error(L"invalid buffer provided");
|
||||
return RC_INTERNAL_ERROR;
|
||||
}
|
||||
if ((DWORD)maxlen != maxlen) {
|
||||
error(L"path buffer is too large");
|
||||
return RC_INTERNAL_ERROR;
|
||||
}
|
||||
if (!GetModuleFileNameW(NULL, pyvenvcfg_path, (DWORD)maxlen)) {
|
||||
winerror(GetLastError(), L"failed to read executable directory");
|
||||
return RC_NO_COMMANDLINE;
|
||||
}
|
||||
// Remove 'python.exe' from our path
|
||||
if (!split_parent(pyvenvcfg_path, maxlen)) {
|
||||
error(L"failed to remove segment from '%ls'", pyvenvcfg_path);
|
||||
return RC_NO_COMMANDLINE;
|
||||
}
|
||||
// Replace with 'pyvenv.cfg'
|
||||
if (!join(pyvenvcfg_path, maxlen, CFGNAME)) {
|
||||
error(L"failed to append '%ls' to '%ls'", CFGNAME, pyvenvcfg_path);
|
||||
return RC_NO_MEMORY;
|
||||
}
|
||||
// If it exists, return
|
||||
if (GetFileAttributesW(pyvenvcfg_path) != INVALID_FILE_ATTRIBUTES) {
|
||||
return 0;
|
||||
}
|
||||
// Otherwise, remove 'pyvenv.cfg' and (probably) 'Scripts'
|
||||
if (!split_parent(pyvenvcfg_path, maxlen) ||
|
||||
!split_parent(pyvenvcfg_path, maxlen)) {
|
||||
error(L"failed to remove segments from '%ls'", pyvenvcfg_path);
|
||||
return RC_NO_COMMANDLINE;
|
||||
}
|
||||
// Replace 'pyvenv.cfg'
|
||||
if (!join(pyvenvcfg_path, maxlen, CFGNAME)) {
|
||||
error(L"failed to append '%ls' to '%ls'", CFGNAME, pyvenvcfg_path);
|
||||
return RC_NO_MEMORY;
|
||||
}
|
||||
// If it exists, return
|
||||
if (GetFileAttributesW(pyvenvcfg_path) != INVALID_FILE_ATTRIBUTES) {
|
||||
return 0;
|
||||
}
|
||||
// Otherwise, we fail
|
||||
winerror(GetLastError(), L"failed to locate %ls", CFGNAME);
|
||||
return RC_NO_VENV_CFG;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* pyvenv.cfg parsing
|
||||
*/
|
||||
|
||||
static int
|
||||
find_home_value(const char *buffer, DWORD maxlen, const char **start, DWORD *length)
|
||||
{
|
||||
if (!buffer || !start || !length) {
|
||||
error(L"invalid find_home_value parameters()");
|
||||
return 0;
|
||||
}
|
||||
for (const char *s = strstr(buffer, "home");
|
||||
s && ((ptrdiff_t)s - (ptrdiff_t)buffer) < maxlen;
|
||||
s = strstr(s + 1, "\nhome")
|
||||
) {
|
||||
if (*s == '\n') {
|
||||
++s;
|
||||
}
|
||||
for (int i = 4; i > 0 && *s; --i, ++s);
|
||||
|
||||
while (*s && iswspace(*s)) {
|
||||
++s;
|
||||
}
|
||||
if (*s != L'=') {
|
||||
continue;
|
||||
}
|
||||
|
||||
do {
|
||||
++s;
|
||||
} while (*s && iswspace(*s));
|
||||
|
||||
*start = s;
|
||||
char *nl = strchr(s, '\n');
|
||||
if (nl) {
|
||||
while (nl != s && iswspace(nl[-1])) {
|
||||
--nl;
|
||||
}
|
||||
*length = (DWORD)((ptrdiff_t)nl - (ptrdiff_t)s);
|
||||
} else {
|
||||
*length = (DWORD)strlen(s);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
read_home(const wchar_t *pyvenv_cfg, wchar_t *home_path, size_t maxlen)
|
||||
{
|
||||
HANDLE hFile = CreateFileW(pyvenv_cfg, GENERIC_READ,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||
NULL, OPEN_EXISTING, 0, NULL);
|
||||
|
||||
if (hFile == INVALID_HANDLE_VALUE) {
|
||||
winerror(GetLastError(), L"failed to open '%ls'", pyvenv_cfg);
|
||||
return RC_BAD_VENV_CFG;
|
||||
}
|
||||
|
||||
// 8192 characters ought to be enough for anyone
|
||||
// (doubled compared to the old implementation!)
|
||||
char buffer[8192];
|
||||
DWORD len;
|
||||
if (!ReadFile(hFile, buffer, sizeof(buffer) - 1, &len, NULL)) {
|
||||
winerror(GetLastError(), L"failed to read '%ls'", pyvenv_cfg);
|
||||
CloseHandle(hFile);
|
||||
return RC_BAD_VENV_CFG;
|
||||
}
|
||||
CloseHandle(hFile);
|
||||
// Ensure null termination
|
||||
buffer[len] = '\0';
|
||||
|
||||
char *home;
|
||||
DWORD home_len;
|
||||
if (!find_home_value(buffer, sizeof(buffer), &home, &home_len)) {
|
||||
error(L"no home= specified in '%ls'", pyvenv_cfg);
|
||||
return RC_BAD_VENV_CFG;
|
||||
}
|
||||
|
||||
if ((DWORD)maxlen != maxlen) {
|
||||
maxlen = 8192;
|
||||
}
|
||||
len = MultiByteToWideChar(CP_UTF8, 0, home, home_len, home_path, (DWORD)maxlen);
|
||||
if (!len) {
|
||||
winerror(GetLastError(), L"failed to decode home setting in '%ls'", pyvenv_cfg);
|
||||
return RC_BAD_VENV_CFG;
|
||||
}
|
||||
home_path[len] = L'\0';
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
locate_python(wchar_t *path, size_t maxlen)
|
||||
{
|
||||
if (!join(path, maxlen, EXENAME)) {
|
||||
error(L"failed to append %ls to '%ls'", EXENAME, path);
|
||||
return RC_NO_MEMORY;
|
||||
}
|
||||
|
||||
if (GetFileAttributesW(path) == INVALID_FILE_ATTRIBUTES) {
|
||||
winerror(GetLastError(), L"did not find executable at '%ls'", path);
|
||||
return RC_NO_PYTHON;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
smuggle_path()
|
||||
{
|
||||
wchar_t buffer[MAXLEN];
|
||||
// We could use argv[0], but that may be wrong in certain rare cases (if the
|
||||
// user is doing something weird like symlinks to venv redirectors), and
|
||||
// what we _really_ want is the directory of the venv. We always copy the
|
||||
// redirectors, so if we've made the venv, this will be correct.
|
||||
DWORD len = GetModuleFileNameW(NULL, buffer, MAXLEN);
|
||||
if (!len) {
|
||||
winerror(GetLastError(), L"Failed to get own executable path");
|
||||
return RC_INTERNAL_ERROR;
|
||||
}
|
||||
buffer[len] = L'\0';
|
||||
debug(L"Setting __PYVENV_LAUNCHER__ = '%s'", buffer);
|
||||
|
||||
if (!SetEnvironmentVariableW(L"__PYVENV_LAUNCHER__", buffer)) {
|
||||
winerror(GetLastError(), L"Failed to set launcher environment");
|
||||
return RC_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Process creation
|
||||
*/
|
||||
|
||||
static BOOL
|
||||
safe_duplicate_handle(HANDLE in, HANDLE * pout, const wchar_t *name)
|
||||
{
|
||||
BOOL ok;
|
||||
HANDLE process = GetCurrentProcess();
|
||||
DWORD rc;
|
||||
|
||||
*pout = NULL;
|
||||
ok = DuplicateHandle(process, in, process, pout, 0, TRUE,
|
||||
DUPLICATE_SAME_ACCESS);
|
||||
if (!ok) {
|
||||
rc = GetLastError();
|
||||
if (rc == ERROR_INVALID_HANDLE) {
|
||||
debug(L"DuplicateHandle(%ls) returned ERROR_INVALID_HANDLE\n", name);
|
||||
ok = TRUE;
|
||||
}
|
||||
else {
|
||||
debug(L"DuplicateHandle(%ls) returned %d\n", name, rc);
|
||||
}
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
static BOOL WINAPI
|
||||
ctrl_c_handler(DWORD code)
|
||||
{
|
||||
return TRUE; /* We just ignore all control events. */
|
||||
}
|
||||
|
||||
static int
|
||||
launch(const wchar_t *executable, wchar_t *cmdline)
|
||||
{
|
||||
HANDLE job;
|
||||
JOBOBJECT_EXTENDED_LIMIT_INFORMATION info;
|
||||
DWORD rc;
|
||||
BOOL ok;
|
||||
STARTUPINFOW si;
|
||||
PROCESS_INFORMATION pi;
|
||||
|
||||
#if defined(_WINDOWS)
|
||||
/*
|
||||
When explorer launches a Windows (GUI) application, it displays
|
||||
the "app starting" (the "pointer + hourglass") cursor for a number
|
||||
of seconds, or until the app does something UI-ish (eg, creating a
|
||||
window, or fetching a message). As this launcher doesn't do this
|
||||
directly, that cursor remains even after the child process does these
|
||||
things. We avoid that by doing a simple post+get message.
|
||||
See http://bugs.python.org/issue17290
|
||||
*/
|
||||
MSG msg;
|
||||
|
||||
PostMessage(0, 0, 0, 0);
|
||||
GetMessage(&msg, 0, 0, 0);
|
||||
#endif
|
||||
|
||||
debug(L"run_child: about to run '%ls' with '%ls'\n", executable, cmdline);
|
||||
job = CreateJobObject(NULL, NULL);
|
||||
ok = QueryInformationJobObject(job, JobObjectExtendedLimitInformation,
|
||||
&info, sizeof(info), &rc);
|
||||
if (!ok || (rc != sizeof(info)) || !job) {
|
||||
winerror(GetLastError(), L"Job information querying failed");
|
||||
return RC_CREATE_PROCESS;
|
||||
}
|
||||
info.BasicLimitInformation.LimitFlags |= JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE |
|
||||
JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK;
|
||||
ok = SetInformationJobObject(job, JobObjectExtendedLimitInformation, &info,
|
||||
sizeof(info));
|
||||
if (!ok) {
|
||||
winerror(GetLastError(), L"Job information setting failed");
|
||||
return RC_CREATE_PROCESS;
|
||||
}
|
||||
memset(&si, 0, sizeof(si));
|
||||
GetStartupInfoW(&si);
|
||||
ok = safe_duplicate_handle(GetStdHandle(STD_INPUT_HANDLE), &si.hStdInput, L"stdin");
|
||||
if (!ok) {
|
||||
return RC_NO_STD_HANDLES;
|
||||
}
|
||||
ok = safe_duplicate_handle(GetStdHandle(STD_OUTPUT_HANDLE), &si.hStdOutput, L"stdout");
|
||||
if (!ok) {
|
||||
return RC_NO_STD_HANDLES;
|
||||
}
|
||||
ok = safe_duplicate_handle(GetStdHandle(STD_ERROR_HANDLE), &si.hStdError, L"stderr");
|
||||
if (!ok) {
|
||||
return RC_NO_STD_HANDLES;
|
||||
}
|
||||
|
||||
ok = SetConsoleCtrlHandler(ctrl_c_handler, TRUE);
|
||||
if (!ok) {
|
||||
winerror(GetLastError(), L"control handler setting failed");
|
||||
return RC_CREATE_PROCESS;
|
||||
}
|
||||
|
||||
si.dwFlags = STARTF_USESTDHANDLES;
|
||||
ok = CreateProcessW(executable, cmdline, NULL, NULL, TRUE,
|
||||
0, NULL, NULL, &si, &pi);
|
||||
if (!ok) {
|
||||
winerror(GetLastError(), L"Unable to create process using '%ls'", cmdline);
|
||||
return RC_CREATE_PROCESS;
|
||||
}
|
||||
AssignProcessToJobObject(job, pi.hProcess);
|
||||
CloseHandle(pi.hThread);
|
||||
WaitForSingleObjectEx(pi.hProcess, INFINITE, FALSE);
|
||||
ok = GetExitCodeProcess(pi.hProcess, &rc);
|
||||
if (!ok) {
|
||||
winerror(GetLastError(), L"Failed to get exit code of process");
|
||||
return RC_CREATE_PROCESS;
|
||||
}
|
||||
debug(L"child process exit code: %d", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
process(int argc, wchar_t ** argv)
|
||||
{
|
||||
int exitCode;
|
||||
wchar_t pyvenvcfg_path[MAXLEN];
|
||||
wchar_t home_path[MAXLEN];
|
||||
|
||||
if (isEnvVarSet(L"PYLAUNCHER_DEBUG")) {
|
||||
setvbuf(stderr, (char *)NULL, _IONBF, 0);
|
||||
log_fp = stderr;
|
||||
}
|
||||
|
||||
exitCode = calculate_pyvenvcfg_path(pyvenvcfg_path, MAXLEN);
|
||||
if (exitCode) return exitCode;
|
||||
|
||||
exitCode = read_home(pyvenvcfg_path, home_path, MAXLEN);
|
||||
if (exitCode) return exitCode;
|
||||
|
||||
exitCode = locate_python(home_path, MAXLEN);
|
||||
if (exitCode) return exitCode;
|
||||
|
||||
// We do not update argv[0] to point at the target runtime, and so we do not
|
||||
// pass through our original argv[0] in an environment variable.
|
||||
//exitCode = smuggle_path();
|
||||
//if (exitCode) return exitCode;
|
||||
|
||||
exitCode = launch(home_path, GetCommandLineW());
|
||||
return exitCode;
|
||||
}
|
||||
|
||||
|
||||
#if defined(_WINDOWS)
|
||||
|
||||
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
|
||||
LPWSTR lpstrCmd, int nShow)
|
||||
{
|
||||
return process(__argc, __wargv);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
int cdecl wmain(int argc, wchar_t ** argv)
|
||||
{
|
||||
return process(argc, argv);
|
||||
}
|
||||
|
||||
#endif
|
|
@ -79,7 +79,7 @@
|
|||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<PropertyGroup>
|
||||
<TargetExt>.pyd</TargetExt>
|
||||
<TargetExt>$(PyStdlibPydExt)</TargetExt>
|
||||
</PropertyGroup>
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
|
|
|
@ -80,7 +80,7 @@
|
|||
<PropertyGroup Label="Configuration" />
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<PropertyGroup>
|
||||
<TargetExt>.pyd</TargetExt>
|
||||
<TargetExt>$(PyStdlibPydExt)</TargetExt>
|
||||
</PropertyGroup>
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
|
|
|
@ -79,7 +79,7 @@
|
|||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<PropertyGroup>
|
||||
<TargetExt>.pyd</TargetExt>
|
||||
<TargetExt>$(PyStdlibPydExt)</TargetExt>
|
||||
</PropertyGroup>
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
|
|
|
@ -80,7 +80,7 @@
|
|||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<PropertyGroup>
|
||||
<TargetExt>.pyd</TargetExt>
|
||||
<TargetExt>$(PyStdlibPydExt)</TargetExt>
|
||||
</PropertyGroup>
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
|
|
|
@ -79,7 +79,7 @@
|
|||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<PropertyGroup>
|
||||
<TargetExt>.pyd</TargetExt>
|
||||
<TargetExt>$(PyStdlibPydExt)</TargetExt>
|
||||
</PropertyGroup>
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
|
|
|
@ -79,7 +79,7 @@
|
|||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<PropertyGroup>
|
||||
<TargetExt>.pyd</TargetExt>
|
||||
<TargetExt>$(PyStdlibPydExt)</TargetExt>
|
||||
</PropertyGroup>
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
|
|
|
@ -79,7 +79,7 @@
|
|||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<PropertyGroup>
|
||||
<TargetExt>.pyd</TargetExt>
|
||||
<TargetExt>$(PyStdlibPydExt)</TargetExt>
|
||||
</PropertyGroup>
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
|
|
|
@ -79,7 +79,7 @@
|
|||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<PropertyGroup>
|
||||
<TargetExt>.pyd</TargetExt>
|
||||
<TargetExt>$(PyStdlibPydExt)</TargetExt>
|
||||
</PropertyGroup>
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
|
|
|
@ -79,7 +79,7 @@
|
|||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<PropertyGroup>
|
||||
<TargetExt>.pyd</TargetExt>
|
||||
<TargetExt>$(PyStdlibPydExt)</TargetExt>
|
||||
</PropertyGroup>
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
|
|
|
@ -79,7 +79,7 @@
|
|||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<PropertyGroup>
|
||||
<TargetExt>.pyd</TargetExt>
|
||||
<TargetExt>$(PyStdlibPydExt)</TargetExt>
|
||||
</PropertyGroup>
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
|
|
|
@ -79,7 +79,7 @@
|
|||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<PropertyGroup>
|
||||
<TargetExt>.pyd</TargetExt>
|
||||
<TargetExt>$(PyStdlibPydExt)</TargetExt>
|
||||
</PropertyGroup>
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
|
|
|
@ -79,7 +79,7 @@
|
|||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<PropertyGroup>
|
||||
<TargetExt>.pyd</TargetExt>
|
||||
<TargetExt>$(PyStdlibPydExt)</TargetExt>
|
||||
</PropertyGroup>
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
|
|
|
@ -79,7 +79,7 @@
|
|||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<PropertyGroup>
|
||||
<TargetExt>.pyd</TargetExt>
|
||||
<TargetExt>$(PyStdlibPydExt)</TargetExt>
|
||||
</PropertyGroup>
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
|
|
|
@ -79,7 +79,7 @@
|
|||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<PropertyGroup>
|
||||
<TargetExt>.pyd</TargetExt>
|
||||
<TargetExt>$(PyStdlibPydExt)</TargetExt>
|
||||
</PropertyGroup>
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
|
|
|
@ -80,7 +80,7 @@
|
|||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<PropertyGroup>
|
||||
<TargetExt>.pyd</TargetExt>
|
||||
<TargetExt>$(PyStdlibPydExt)</TargetExt>
|
||||
</PropertyGroup>
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
|
|
|
@ -80,7 +80,7 @@
|
|||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<PropertyGroup>
|
||||
<TargetExt>.pyd</TargetExt>
|
||||
<TargetExt>$(PyStdlibPydExt)</TargetExt>
|
||||
</PropertyGroup>
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
|
|
|
@ -80,7 +80,7 @@
|
|||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<PropertyGroup>
|
||||
<TargetExt>.pyd</TargetExt>
|
||||
<TargetExt>$(PyStdlibPydExt)</TargetExt>
|
||||
</PropertyGroup>
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
|
|
|
@ -79,7 +79,7 @@
|
|||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<PropertyGroup>
|
||||
<TargetExt>.pyd</TargetExt>
|
||||
<TargetExt>$(PyStdlibPydExt)</TargetExt>
|
||||
</PropertyGroup>
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
|
|
|
@ -80,7 +80,7 @@
|
|||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<PropertyGroup>
|
||||
<TargetExt>.pyd</TargetExt>
|
||||
<TargetExt>$(PyStdlibPydExt)</TargetExt>
|
||||
</PropertyGroup>
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
|
|
|
@ -80,7 +80,7 @@
|
|||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<PropertyGroup>
|
||||
<TargetExt>.pyd</TargetExt>
|
||||
<TargetExt>$(PyStdlibPydExt)</TargetExt>
|
||||
</PropertyGroup>
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
|
|
|
@ -80,7 +80,7 @@
|
|||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<PropertyGroup>
|
||||
<TargetExt>.pyd</TargetExt>
|
||||
<TargetExt>$(PyStdlibPydExt)</TargetExt>
|
||||
</PropertyGroup>
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
|
|
|
@ -80,7 +80,7 @@
|
|||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<PropertyGroup>
|
||||
<TargetExt>.pyd</TargetExt>
|
||||
<TargetExt>$(PyStdlibPydExt)</TargetExt>
|
||||
</PropertyGroup>
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
|
|
|
@ -80,7 +80,7 @@
|
|||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<PropertyGroup>
|
||||
<TargetExt>.pyd</TargetExt>
|
||||
<TargetExt>$(PyStdlibPydExt)</TargetExt>
|
||||
</PropertyGroup>
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
|
|
|
@ -79,7 +79,7 @@
|
|||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<PropertyGroup>
|
||||
<TargetExt>.pyd</TargetExt>
|
||||
<TargetExt>$(PyStdlibPydExt)</TargetExt>
|
||||
</PropertyGroup>
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
|
|
|
@ -80,7 +80,7 @@
|
|||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<PropertyGroup>
|
||||
<TargetExt>.pyd</TargetExt>
|
||||
<TargetExt>$(PyStdlibPydExt)</TargetExt>
|
||||
</PropertyGroup>
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
|
|
|
@ -80,7 +80,7 @@
|
|||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<PropertyGroup>
|
||||
<TargetExt>.pyd</TargetExt>
|
||||
<TargetExt>$(PyStdlibPydExt)</TargetExt>
|
||||
</PropertyGroup>
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
|
|
|
@ -79,7 +79,7 @@
|
|||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<PropertyGroup>
|
||||
<TargetExt>.pyd</TargetExt>
|
||||
<TargetExt>$(PyStdlibPydExt)</TargetExt>
|
||||
</PropertyGroup>
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
|
|
|
@ -79,7 +79,7 @@
|
|||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<PropertyGroup>
|
||||
<TargetExt>.pyd</TargetExt>
|
||||
<TargetExt>$(PyStdlibPydExt)</TargetExt>
|
||||
</PropertyGroup>
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
|
|
|
@ -24,6 +24,13 @@
|
|||
<LinkIncremental Condition="$(Configuration) != 'Debug'">false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="$(TargetExt) != ''">
|
||||
<TargetNameExt>$(TargetName)$(TargetExt)</TargetNameExt>
|
||||
<_TargetNameSep>$(TargetNameExt.LastIndexOf(`.`))</_TargetNameSep>
|
||||
<TargetName>$(TargetNameExt.Substring(0, $(_TargetNameSep)))</TargetName>
|
||||
<TargetExt>$(TargetNameExt.Substring($(_TargetNameSep)))</TargetExt>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Label="MSVC Bug Workarounds" Condition="$(VCToolsVersion) != ''">
|
||||
<_VCToolsVersion>$([System.Version]::Parse(`$(VCToolsVersion)`).Major).$([System.Version]::Parse(`$(VCToolsVersion)`).Minor)</_VCToolsVersion>
|
||||
|
||||
|
@ -38,7 +45,7 @@
|
|||
<_PlatformPreprocessorDefinition>_WIN32;</_PlatformPreprocessorDefinition>
|
||||
<_PlatformPreprocessorDefinition Condition="$(Platform) == 'x64'">_WIN64;</_PlatformPreprocessorDefinition>
|
||||
<_PlatformPreprocessorDefinition Condition="$(Platform) == 'x64' and $(PlatformToolset) != 'ClangCL'">_M_X64;$(_PlatformPreprocessorDefinition)</_PlatformPreprocessorDefinition>
|
||||
<_Py3NamePreprocessorDefinition>PY3_DLLNAME=L"$(Py3DllName)";</_Py3NamePreprocessorDefinition>
|
||||
<_Py3NamePreprocessorDefinition>PY3_DLLNAME=L"$(Py3DllName)$(PyDebugExt)";</_Py3NamePreprocessorDefinition>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
|
@ -158,8 +165,8 @@ public override bool Execute() {
|
|||
</UsingTask>
|
||||
|
||||
<Target Name="KillPython" BeforeTargets="PrepareForBuild" Condition="'$(KillPython)' == 'true'">
|
||||
<Message Text="Killing any running python$(PyDebugExt)$(PyTestExt).exe instances..." Importance="high" />
|
||||
<KillPython FileName="$(OutDir)python$(PyDebugExt)$(PyTestExt).exe" />
|
||||
<Message Text="Killing any running $(PyExeName)$(PyDebugExt)$(PyTestExt).exe instances..." Importance="high" />
|
||||
<KillPython FileName="$(OutDir)$(PyExeName)$(PyDebugExt)$(PyTestExt).exe" />
|
||||
</Target>
|
||||
|
||||
<!--
|
||||
|
|
|
@ -93,9 +93,6 @@
|
|||
<PyArchExt Condition="'$(ArchName)' == 'arm32'">-arm32</PyArchExt>
|
||||
<PyArchExt Condition="'$(ArchName)' == 'arm64'">-arm64</PyArchExt>
|
||||
|
||||
<!-- Full path of the resulting python.exe binary -->
|
||||
<PythonExe Condition="'$(PythonExe)' == ''">$(BuildPath)python$(PyDebugExt).exe</PythonExe>
|
||||
|
||||
<!-- Include Tkinter by default -->
|
||||
<IncludeTkinter Condition="'$(IncludeTkinter)' == ''">true</IncludeTkinter>
|
||||
</PropertyGroup>
|
||||
|
@ -224,10 +221,19 @@
|
|||
))</Field3Value>
|
||||
<Field3Value Condition="$(UseTestMarker) == 'true'">$([msbuild]::Add($(Field3Value), 9000))</Field3Value>
|
||||
|
||||
<!-- Name and full path of the resulting python.exe binary -->
|
||||
<PyExeName Condition="$(DisableGil) == 'true'">python$(MajorVersionNumber).$(MinorVersionNumber)t</PyExeName>
|
||||
<PyExeName Condition="$(PyExeName) == ''">python</PyExeName>
|
||||
<PythonExe Condition="'$(PythonExe)' == ''">$(BuildPath)$(PyExeName)$(PyDebugExt).exe</PythonExe>
|
||||
<PyWExeName Condition="$(DisableGil) == 'true'">pythonw$(MajorVersionNumber).$(MinorVersionNumber)t</PyWExeName>
|
||||
<PyWExeName Condition="$(PyWExeName) == ''">pythonw</PyWExeName>
|
||||
|
||||
<!-- The name of the resulting pythonXY.dll (without the extension) -->
|
||||
<PyDllName>python$(MajorVersionNumber)$(MinorVersionNumber)$(PyDebugExt)</PyDllName>
|
||||
<PyDllName Condition="$(DisableGil) == 'true'">python$(MajorVersionNumber)$(MinorVersionNumber)t$(PyDebugExt)</PyDllName>
|
||||
<PyDllName Condition="$(PyDllName) == ''">python$(MajorVersionNumber)$(MinorVersionNumber)$(PyDebugExt)</PyDllName>
|
||||
<!-- The name of the resulting pythonX.dll (without the extension) -->
|
||||
<Py3DllName>python3$(PyDebugExt)</Py3DllName>
|
||||
<Py3DllName Condition="$(DisableGil) == 'true'">python3t</Py3DllName>
|
||||
<Py3DllName Condition="$(Py3DllName) == ''">python3</Py3DllName>
|
||||
|
||||
<!-- The version and platform tag to include in .pyd filenames -->
|
||||
<PydTag Condition="$(ArchName) == 'win32'">.cp$(MajorVersionNumber)$(MinorVersionNumber)-win32</PydTag>
|
||||
|
@ -237,6 +243,30 @@
|
|||
|
||||
<!-- The version number for sys.winver -->
|
||||
<SysWinVer>$(MajorVersionNumber).$(MinorVersionNumber)$(PyArchExt)$(PyTestExt)</SysWinVer>
|
||||
|
||||
<!-- The version and platform tag to include in .pyd filenames for freethreaded builds -->
|
||||
<FreethreadedPydTag Condition="$(ArchName) == 'win32'">.cp$(MajorVersionNumber)$(MinorVersionNumber)t-win32</FreethreadedPydTag>
|
||||
<FreethreadedPydTag Condition="$(ArchName) == 'arm32'">.cp$(MajorVersionNumber)$(MinorVersionNumber)t-win_arm32</FreethreadedPydTag>
|
||||
<FreethreadedPydTag Condition="$(ArchName) == 'arm64'">.cp$(MajorVersionNumber)$(MinorVersionNumber)t-win_arm64</FreethreadedPydTag>
|
||||
<FreethreadedPydTag Condition="$(ArchName) == 'amd64'">.cp$(MajorVersionNumber)$(MinorVersionNumber)t-win_amd64</FreethreadedPydTag>
|
||||
|
||||
<!-- The version number for sys.winver for freethreaded builds -->
|
||||
<FreethreadedSysWinVer>$(MajorVersionNumber).$(MinorVersionNumber)t$(PyArchExt)$(PyTestExt)</FreethreadedSysWinVer>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="$(DisableGil) != 'true'">
|
||||
<!-- The extension to use for standard library PYDs -->
|
||||
<PyStdlibPydExt>.pyd</PyStdlibPydExt>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="$(DisableGil) == 'true'">
|
||||
<PydTag>$(FreethreadedPydTag)</PydTag>
|
||||
|
||||
<!-- The extension to use for standard library PYDs -->
|
||||
<PyStdlibPydExt>$(PydTag).pyd</PyStdlibPydExt>
|
||||
|
||||
<!-- The version number for sys.winver -->
|
||||
<SysWinVer>$(FreethreadedSysWinVer)</SysWinVer>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- Displays the calculated version info -->
|
||||
|
|
|
@ -72,6 +72,7 @@
|
|||
<Import Project="python.props" />
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Label="Configuration">
|
||||
<TargetName>$(PyExeName)</TargetName>
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseOfMfc>false</UseOfMfc>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
|
@ -132,7 +133,7 @@
|
|||
</PropertyGroup>
|
||||
<Exec Command='setlocal
|
||||
set PYTHONPATH=$(PySourcePath)Lib
|
||||
"$(OutDir)python$(PyDebugExt).exe" "$(PySourcePath)PC\validate_ucrtbase.py" $(UcrtName)' ContinueOnError="true" />
|
||||
"$(OutDir)$(PyExeName)$(PyDebugExt).exe" "$(PySourcePath)PC\validate_ucrtbase.py" $(UcrtName)' ContinueOnError="true" />
|
||||
</Target>
|
||||
<Target Name="GeneratePythonBat" AfterTargets="AfterBuild">
|
||||
<PropertyGroup>
|
||||
|
@ -145,7 +146,7 @@ set PYTHONPATH=$(PySourcePath)Lib
|
|||
@echo Running $(Configuration)^|$(Platform) interpreter...
|
||||
@setlocal
|
||||
@set PYTHONHOME=$(PySourcePath)
|
||||
@"$(OutDir)python$(PyDebugExt).exe" %*
|
||||
@"$(OutDir)$(PyExeName)$(PyDebugExt).exe" %*
|
||||
</_Content>
|
||||
<_ExistingContent Condition="Exists('$(PySourcePath)python.bat')">$([System.IO.File]::ReadAllText('$(PySourcePath)python.bat'))</_ExistingContent>
|
||||
</PropertyGroup>
|
||||
|
|
|
@ -70,12 +70,12 @@
|
|||
<ProjectGuid>{885D4898-D08D-4091-9C40-C700CFE3FC5A}</ProjectGuid>
|
||||
<RootNamespace>python3dll</RootNamespace>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<TargetName>python3</TargetName>
|
||||
<SupportPGO>false</SupportPGO>
|
||||
</PropertyGroup>
|
||||
<Import Project="python.props" />
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Label="Configuration">
|
||||
<TargetName>$(Py3DllName)</TargetName>
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
|
|
|
@ -73,6 +73,7 @@
|
|||
<Import Project="python.props" />
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Label="Configuration">
|
||||
<TargetName>$(PyWExeName)</TargetName>
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseOfMfc>false</UseOfMfc>
|
||||
</PropertyGroup>
|
||||
|
|
|
@ -9,6 +9,7 @@ rem -q runs the tests just once, and without deleting .pyc files.
|
|||
rem -p <Win32|x64|ARM|ARM64> or -win32, -x64, -arm32, -arm64
|
||||
rem Run the specified architecture of python (or python_d if -d
|
||||
rem was specified). If omitted, uses %PREFIX% if set or 64-bit.
|
||||
rem --disable-gil Run free-threaded build.
|
||||
rem All leading instances of these switches are shifted off, and
|
||||
rem whatever remains (up to 9 arguments) is passed to regrtest.py.
|
||||
rem For example,
|
||||
|
@ -29,6 +30,7 @@ rem rt -u "network,largefile"
|
|||
setlocal
|
||||
|
||||
set pcbuild=%~dp0
|
||||
set pyname=python
|
||||
set suffix=
|
||||
set qmode=
|
||||
set dashO=
|
||||
|
@ -39,15 +41,18 @@ set exe=
|
|||
if "%1"=="-O" (set dashO=-O) & shift & goto CheckOpts
|
||||
if "%1"=="-q" (set qmode=yes) & shift & goto CheckOpts
|
||||
if "%1"=="-d" (set suffix=_d) & shift & goto CheckOpts
|
||||
rem HACK: Need some way to infer the version number in this script
|
||||
if "%1"=="--disable-gil" (set pyname=python3.13t) & shift & goto CheckOpts
|
||||
if "%1"=="-win32" (set prefix=%pcbuild%win32) & shift & goto CheckOpts
|
||||
if "%1"=="-x64" (set prefix=%pcbuild%amd64) & shift & goto CheckOpts
|
||||
if "%1"=="-amd64" (set prefix=%pcbuild%amd64) & shift & goto CheckOpts
|
||||
if "%1"=="-arm64" (set prefix=%pcbuild%arm64) & shift & goto CheckOpts
|
||||
if "%1"=="-arm32" (set prefix=%pcbuild%arm32) & shift & goto CheckOpts
|
||||
if "%1"=="-p" (call :SetPlatform %~2) & shift & shift & goto CheckOpts
|
||||
if NOT "%1"=="" (set regrtestargs=%regrtestargs% %1) & shift & goto CheckOpts
|
||||
|
||||
if not defined prefix set prefix=%pcbuild%amd64
|
||||
set exe=%prefix%\python%suffix%.exe
|
||||
set exe=%prefix%\%pyname%%suffix%.exe
|
||||
set cmd="%exe%" %dashO% -m test %regrtestargs%
|
||||
if defined qmode goto Qmode
|
||||
|
||||
|
|
|
@ -78,7 +78,7 @@
|
|||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<PropertyGroup>
|
||||
<TargetExt>.pyd</TargetExt>
|
||||
<TargetExt>$(PyStdlibPydExt)</TargetExt>
|
||||
</PropertyGroup>
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
|
|
|
@ -69,12 +69,12 @@
|
|||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{A1A295E5-463C-437F-81CA-1F32367685DA}</ProjectGuid>
|
||||
<RootNamespace>sqlite3</RootNamespace>
|
||||
<TargetExt>.pyd</TargetExt>
|
||||
<SupportPGO>false</SupportPGO>
|
||||
</PropertyGroup>
|
||||
<Import Project="python.props" />
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Label="Configuration">
|
||||
<TargetExt>$(PyStdlibPydExt)</TargetExt>
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<CharacterSet>NotSet</CharacterSet>
|
||||
</PropertyGroup>
|
||||
|
|
|
@ -79,7 +79,7 @@
|
|||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<PropertyGroup>
|
||||
<TargetExt>.pyd</TargetExt>
|
||||
<TargetExt>$(PyStdlibPydExt)</TargetExt>
|
||||
</PropertyGroup>
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
|
|
|
@ -69,12 +69,13 @@
|
|||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{494BAC80-A60C-43A9-99E7-ACB691CE2C4D}</ProjectGuid>
|
||||
<RootNamespace>venvlauncher</RootNamespace>
|
||||
<TargetName>venvlauncher</TargetName>
|
||||
<SupportPGO>false</SupportPGO>
|
||||
</PropertyGroup>
|
||||
<Import Project="python.props" />
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Label="Configuration">
|
||||
<TargetName>venvlauncher</TargetName>
|
||||
<TargetName Condition="$(DisableGil) == 'true'">$(TargetName)t</TargetName>
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
|
@ -91,19 +92,19 @@
|
|||
<PropertyGroup Label="UserMacros" />
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>_CONSOLE;VENV_REDIRECT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>EXENAME=L"$(PyExeName)$(PyDebugExt).exe";_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<ResourceCompile>
|
||||
<PreprocessorDefinitions>PY_ICON;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ResourceCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>version.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>pathcch.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<SubSystem>Console</SubSystem>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\PC\launcher.c" />
|
||||
<ClCompile Include="..\PC\venvlauncher.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\PC\launcher.ico" />
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
</ResourceCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\PC\launcher.c">
|
||||
<ClCompile Include="..\PC\venvlauncher.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
|
|
|
@ -69,12 +69,13 @@
|
|||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{FDB84CBB-2FB6-47C8-A2D6-091E0833239D}</ProjectGuid>
|
||||
<RootNamespace>venvwlauncher</RootNamespace>
|
||||
<TargetName>venvwlauncher</TargetName>
|
||||
<SupportPGO>false</SupportPGO>
|
||||
</PropertyGroup>
|
||||
<Import Project="python.props" />
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Label="Configuration">
|
||||
<TargetName>venvwlauncher</TargetName>
|
||||
<TargetName Condition="$(DisableGil) == 'true'">$(TargetName)t</TargetName>
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
|
@ -91,19 +92,19 @@
|
|||
<PropertyGroup Label="UserMacros" />
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>_WINDOWS;VENV_REDIRECT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>EXENAME=L"$(PyExeName)$(PyDebugExt).exe";_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<ResourceCompile>
|
||||
<PreprocessorDefinitions>PYW_ICON;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ResourceCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>version.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>pathcch.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\PC\launcher.c" />
|
||||
<ClCompile Include="..\PC\venvlauncher.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\PC\launcher.ico" />
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\PC\launcher.c">
|
||||
<ClCompile Include="..\PC\venvlauncher.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
|
|
|
@ -80,7 +80,7 @@
|
|||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<PropertyGroup>
|
||||
<TargetExt>.pyd</TargetExt>
|
||||
<TargetExt>$(PyStdlibPydExt)</TargetExt>
|
||||
</PropertyGroup>
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
|
|
|
@ -80,7 +80,7 @@
|
|||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<PropertyGroup>
|
||||
<TargetExt>.pyd</TargetExt>
|
||||
<TargetExt>$(PyStdlibPydExt)</TargetExt>
|
||||
</PropertyGroup>
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
|
|
|
@ -80,7 +80,7 @@
|
|||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<PropertyGroup>
|
||||
<TargetExt>.pyd</TargetExt>
|
||||
<TargetExt>$(PyStdlibPydExt)</TargetExt>
|
||||
</PropertyGroup>
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
|
|
|
@ -22,6 +22,9 @@ if "%~1" EQU "--no-test-marker" (set BUILDTEST=) && shift && goto CheckOpts
|
|||
if "%~1" EQU "--test-marker" (set BUILDTEST=--test-marker) && shift && goto CheckOpts
|
||||
if "%~1" EQU "--pack" (set BUILDPACK=1) && shift && goto CheckOpts
|
||||
if "%~1" EQU "-r" (set REBUILD=-r) && shift && goto CheckOpts
|
||||
rem %IncludeFreethreaded% is recognised by the MSI build, but not the regular build.
|
||||
rem We use it to build twice and then build the installer with its extra option
|
||||
if /I "%~1" EQU "--disable-gil" (set IncludeFreethreaded=true) && shift && goto CheckOpts
|
||||
|
||||
if not defined BUILDX86 if not defined BUILDX64 if not defined BUILDARM64 (set BUILDX86=1) && (set BUILDX64=1)
|
||||
|
||||
|
@ -44,6 +47,20 @@ if errorlevel 1 exit /B %ERRORLEVEL%
|
|||
if defined BUILDARM64 call "%PCBUILD%build.bat" -p ARM64 -e %REBUILD% %BUILDTEST%
|
||||
if errorlevel 1 exit /B %ERRORLEVEL%
|
||||
|
||||
if /I "%IncludeFreethreaded%"=="true" (
|
||||
rem Cannot "exit /B" inside an if block because %ERRORLEVEL% will be wrong.
|
||||
rem We just skip everything after the first "errorlevel 1" and then exit after
|
||||
if defined BUILDX86 call "%PCBUILD%build.bat" -p Win32 -d -e %REBUILD% %BUILDTEST% --disable-gil
|
||||
if not errorlevel 1 if defined BUILDX86 call "%PCBUILD%build.bat" -p Win32 -e %REBUILD% %BUILDTEST% --disable-gil
|
||||
|
||||
if not errorlevel 1 if defined BUILDX64 call "%PCBUILD%build.bat" -p x64 -d -e %REBUILD% %BUILDTEST% --disable-gil
|
||||
if not errorlevel 1 if defined BUILDX64 call "%PCBUILD%build.bat" -p x64 -e %REBUILD% %BUILDTEST% --disable-gil
|
||||
|
||||
if not errorlevel 1 if defined BUILDARM64 call "%PCBUILD%build.bat" -p ARM64 -d -e %REBUILD% %BUILDTEST% --disable-gil
|
||||
if not errorlevel 1 if defined BUILDARM64 call "%PCBUILD%build.bat" -p ARM64 -e %REBUILD% %BUILDTEST% --disable-gil
|
||||
)
|
||||
if errorlevel 1 exit /B %ERRORLEVEL%
|
||||
|
||||
if defined BUILDDOC call "%PCBUILD%..\Doc\make.bat" html
|
||||
if errorlevel 1 exit /B %ERRORLEVEL%
|
||||
|
||||
|
|
|
@ -83,6 +83,7 @@
|
|||
<Checkbox Name="CompileAll" X="185" Y="151" Width="-11" Height="24" TabStop="yes" FontId="3" HideWhenDisabled="no">#(loc.PrecompileLabel)</Checkbox>
|
||||
<Checkbox Name="Include_symbols" X="185" Y="176" Width="-11" Height="24" TabStop="yes" FontId="3" HideWhenDisabled="no">#(loc.Include_symbolsLabel)</Checkbox>
|
||||
<Checkbox Name="Include_debug" X="185" Y="201" Width="-11" Height="24" TabStop="yes" FontId="3" HideWhenDisabled="no">#(loc.Include_debugLabel)</Checkbox>
|
||||
<Checkbox Name="Include_freethreaded" X="185" Y="226" Width="-11" Height="24" TabStop="yes" FontId="3" HideWhenDisabled="yes">#(loc.Include_freethreadedLabel)</Checkbox>
|
||||
|
||||
<Text X="185" Y="256" Width="-11" Height="17" FontId="3">#(loc.CustomLocationLabel)</Text>
|
||||
<Editbox Name="TargetDir" X="185" Y="277" Width="-101" Height="27" TabStop="yes" FontId="3" FileSystemAutoComplete="yes" />
|
||||
|
|
|
@ -91,6 +91,7 @@ Select Customize to review current options.</String>
|
|||
<String Id="PrecompileLabel">&Precompile standard library</String>
|
||||
<String Id="Include_symbolsLabel">Download debugging &symbols</String>
|
||||
<String Id="Include_debugLabel">Download debu&g binaries (requires VS 2017 or later)</String>
|
||||
<String Id="Include_freethreadedLabel">Download &free-threaded binaries (experimental)</String>
|
||||
|
||||
<String Id="ProgressHeader">[ActionLikeInstallation] Progress</String>
|
||||
<String Id="ProgressLabel">[ActionLikeInstalling]:</String>
|
||||
|
|
|
@ -72,6 +72,7 @@
|
|||
<Package Include="..\tcltk\tcltk*.wixproj" />
|
||||
<Package Include="..\test\test*.wixproj" />
|
||||
<Package Include="..\ucrt\ucrt*.wixproj" Condition="$(Platform) != 'ARM64'" />
|
||||
<Package Include="..\freethreaded\freethreaded*.wixproj" Condition="$(IncludeFreethreaded) == 'true'" />
|
||||
</ItemGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
|
|
|
@ -82,6 +82,13 @@
|
|||
<?endif ?>
|
||||
<Variable Name="Include_symbols" Value="0" bal:Overridable="yes" />
|
||||
<Variable Name="Include_debug" Value="0" bal:Overridable="yes" />
|
||||
<?if $(var.IncludeFreethreaded)~="true" ?>
|
||||
<Variable Name="Include_freethreaded" Value="0" bal:Overridable="yes" />
|
||||
<Variable Name="Include_freethreadedState" Value="enabled" />
|
||||
<?else ?>
|
||||
<Variable Name="Include_freethreaded" Value="0" />
|
||||
<Variable Name="Include_freethreadedState" Value="disable" />
|
||||
<?endif ?>
|
||||
|
||||
<Variable Name="LauncherOnly" Value="0" bal:Overridable="yes" />
|
||||
<Variable Name="DetectedLauncher" Value="0" />
|
||||
|
@ -104,6 +111,9 @@
|
|||
<PackageGroupRef Id="exe" />
|
||||
<PackageGroupRef Id="dev" />
|
||||
<PackageGroupRef Id="lib" />
|
||||
<?if $(var.IncludeFreethreaded)~="true" ?>
|
||||
<PackageGroupRef Id="freethreaded" />
|
||||
<?endif ?>
|
||||
<PackageGroupRef Id="test" />
|
||||
<PackageGroupRef Id="doc" />
|
||||
<PackageGroupRef Id="tcltk" />
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
<?xml version="1.0"?>
|
||||
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
|
||||
<Fragment>
|
||||
<PackageGroup Id="freethreaded">
|
||||
<MsiPackage Id="freethreaded_AllUsers"
|
||||
SourceFile="freethreaded.msi"
|
||||
Compressed="no"
|
||||
DownloadUrl="$(var.DownloadUrl)"
|
||||
ForcePerMachine="yes"
|
||||
InstallCondition="InstallAllUsers and (Include_freethreaded) and not LauncherOnly">
|
||||
<MsiProperty Name="TARGETDIR" Value="[TargetDir]" />
|
||||
<MsiProperty Name="OPTIONALFEATURESREGISTRYKEY" Value="[OptionalFeaturesRegistryKey]" />
|
||||
</MsiPackage>
|
||||
<MsiPackage Id="freethreaded_AllUsers_pdb"
|
||||
SourceFile="freethreaded_pdb.msi"
|
||||
Compressed="no"
|
||||
DownloadUrl="$(var.DownloadUrl)"
|
||||
ForcePerMachine="yes"
|
||||
InstallCondition="InstallAllUsers and (Include_freethreaded) and Include_symbols and not LauncherOnly">
|
||||
<MsiProperty Name="TARGETDIR" Value="[TargetDir]" />
|
||||
<MsiProperty Name="OPTIONALFEATURESREGISTRYKEY" Value="[OptionalFeaturesRegistryKey]" />
|
||||
</MsiPackage>
|
||||
<MsiPackage Id="freethreaded_AllUsers_d"
|
||||
SourceFile="freethreaded_d.msi"
|
||||
Compressed="no"
|
||||
DownloadUrl="$(var.DownloadUrl)"
|
||||
ForcePerMachine="yes"
|
||||
InstallCondition="InstallAllUsers and (Include_freethreaded) and Include_debug and not LauncherOnly">
|
||||
<MsiProperty Name="TARGETDIR" Value="[TargetDir]" />
|
||||
<MsiProperty Name="OPTIONALFEATURESREGISTRYKEY" Value="[OptionalFeaturesRegistryKey]" />
|
||||
</MsiPackage>
|
||||
|
||||
<MsiPackage Id="freethreaded_JustForMe"
|
||||
SourceFile="freethreaded.msi"
|
||||
Compressed="no"
|
||||
DownloadUrl="$(var.DownloadUrl)"
|
||||
ForcePerMachine="no"
|
||||
InstallCondition="not InstallAllUsers and (Include_freethreaded) and not LauncherOnly">
|
||||
<MsiProperty Name="TARGETDIR" Value="[TargetDir]" />
|
||||
<MsiProperty Name="OPTIONALFEATURESREGISTRYKEY" Value="[OptionalFeaturesRegistryKey]" />
|
||||
</MsiPackage>
|
||||
<MsiPackage Id="freethreaded_JustForMe_pdb"
|
||||
SourceFile="freethreaded_pdb.msi"
|
||||
Compressed="no"
|
||||
DownloadUrl="$(var.DownloadUrl)"
|
||||
ForcePerMachine="no"
|
||||
InstallCondition="not InstallAllUsers and (Include_freethreaded) and Include_symbols and not LauncherOnly">
|
||||
<MsiProperty Name="TARGETDIR" Value="[TargetDir]" />
|
||||
<MsiProperty Name="OPTIONALFEATURESREGISTRYKEY" Value="[OptionalFeaturesRegistryKey]" />
|
||||
</MsiPackage>
|
||||
<MsiPackage Id="freethreaded_JustForMe_d"
|
||||
SourceFile="freethreaded_d.msi"
|
||||
Compressed="no"
|
||||
DownloadUrl="$(var.DownloadUrl)"
|
||||
ForcePerMachine="no"
|
||||
InstallCondition="not InstallAllUsers and (Include_freethreaded) and Include_debug and not LauncherOnly">
|
||||
<MsiProperty Name="TARGETDIR" Value="[TargetDir]" />
|
||||
<MsiProperty Name="OPTIONALFEATURESREGISTRYKEY" Value="[OptionalFeaturesRegistryKey]" />
|
||||
</MsiPackage>
|
||||
</PackageGroup>
|
||||
</Fragment>
|
||||
</Wix>
|
|
@ -0,0 +1,20 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<ProjectGuid>{1B4502D5-B627-4F50-ABEA-4CC5A8E88265}</ProjectGuid>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<OutputName>freethreaded</OutputName>
|
||||
<OutputType>Package</OutputType>
|
||||
</PropertyGroup>
|
||||
<Import Project="..\msi.props" />
|
||||
<ItemGroup>
|
||||
<Compile Include="freethreaded.wxs" />
|
||||
<Compile Include="freethreaded_files.wxs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="*.wxl" />
|
||||
<WxlTemplate Include="*.wxl_template" />
|
||||
</ItemGroup>
|
||||
|
||||
<Import Project="..\msi.targets" />
|
||||
</Project>
|
|
@ -0,0 +1,18 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
|
||||
<Product Id="*" Language="!(loc.LCID)" Name="!(loc.Title)" Version="$(var.Version)" Manufacturer="!(loc.Manufacturer)" UpgradeCode="$(var.UpgradeCode)">
|
||||
<Package InstallerVersion="500" Compressed="yes" InstallScope="perUser" />
|
||||
<MediaTemplate EmbedCab="yes" CompressionLevel="high" />
|
||||
|
||||
<PropertyRef Id="UpgradeTable" />
|
||||
<PropertyRef Id="REGISTRYKEY" />
|
||||
|
||||
<Feature Id="DefaultFeature" AllowAdvertise="no" Title="!(loc.Title)" Description="!(loc.Description)">
|
||||
<ComponentGroupRef Id="freethreaded_reg" Primary="yes" />
|
||||
<ComponentGroupRef Id="freethreaded_exe" />
|
||||
<ComponentGroupRef Id="freethreaded_lib_files" />
|
||||
<ComponentGroupRef Id="freethreaded_lib_extensions" />
|
||||
<ComponentRef Id="OptionalFeature" />
|
||||
</Feature>
|
||||
</Product>
|
||||
</Wix>
|
|
@ -0,0 +1,20 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<ProjectGuid>{D3677DCF-098A-4398-9FA5-8E74AC37E0DF}</ProjectGuid>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<OutputName>freethreaded_d</OutputName>
|
||||
<OutputType>Package</OutputType>
|
||||
</PropertyGroup>
|
||||
<Import Project="..\msi.props" />
|
||||
<ItemGroup>
|
||||
<Compile Include="freethreaded_d.wxs" />
|
||||
<Compile Include="freethreaded_files.wxs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="*.wxl" />
|
||||
<WxlTemplate Include="*.wxl_template" />
|
||||
</ItemGroup>
|
||||
|
||||
<Import Project="..\msi.targets" />
|
||||
</Project>
|
|
@ -0,0 +1,16 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
|
||||
<Product Id="*" Language="!(loc.LCID)" Name="!(loc.Title_d)" Version="$(var.Version)" Manufacturer="!(loc.Manufacturer)" UpgradeCode="$(var.UpgradeCode)">
|
||||
<Package InstallerVersion="500" Compressed="yes" InstallScope="perUser" />
|
||||
<MediaTemplate EmbedCab="yes" CompressionLevel="high" />
|
||||
|
||||
<PropertyRef Id="UpgradeTable" />
|
||||
|
||||
<Feature Id="DebugBinaries" AllowAdvertise="no" Title="!(loc.Title_d)" Description="!(loc.Description_d)">
|
||||
<ComponentGroupRef Id="freethreaded_dll_d" />
|
||||
<ComponentGroupRef Id="freethreaded_exe_d" />
|
||||
<ComponentGroupRef Id="freethreaded_lib_extensions_d" />
|
||||
<ComponentRef Id="OptionalFeature" />
|
||||
</Feature>
|
||||
</Product>
|
||||
</Wix>
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<WixLocalization Culture="en-us" xmlns="http://schemas.microsoft.com/wix/2006/localization">
|
||||
<String Id="Descriptor">Freethreaded Interpreter</String>
|
||||
<String Id="ShortDescriptor">freethreaded</String>
|
||||
<String Id="ShortcutName">Python {{ShortVersion}} ({{Bitness}}, freethreaded)</String>
|
||||
<String Id="ShortcutDescription">Launches the !(loc.ProductName) freethreaded interpreter.</String>
|
||||
<String Id="SupportUrl">https://www.python.org/</String>
|
||||
</WixLocalization>
|
|
@ -0,0 +1,175 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
|
||||
<Fragment>
|
||||
<Property Id="FREETHREADED_REGISTRYKEY" Value="Software\Python\PythonCore\$(var.ShortVersion)t$(var.PyArchExt)$(var.PyTestExt)" />
|
||||
|
||||
<ComponentGroup Id="freethreaded_reg">
|
||||
<Component Id="PythonRegistration" Directory="InstallDirectory" Guid="$(var.PythonRegComponentGuid)">
|
||||
<RegistryKey Root="HKMU" Key="[FREETHREADED_REGISTRYKEY]">
|
||||
<RegistryValue Name="DisplayName" Type="string" Value="!(loc.ShortcutName)" KeyPath="yes" />
|
||||
<RegistryValue Name="SupportUrl" Type="string" Value="!(loc.SupportUrl)" KeyPath="no" />
|
||||
<RegistryValue Name="Version" Type="string" Value="$(var.LongVersion)" KeyPath="no" />
|
||||
<RegistryValue Name="SysVersion" Type="string" Value="$(var.ShortVersion)" KeyPath="no" />
|
||||
<RegistryValue Name="SysArchitecture" Type="string" Value="$(var.PlatformArchitecture)" KeyPath="no" />
|
||||
</RegistryKey>
|
||||
</Component>
|
||||
</ComponentGroup>
|
||||
</Fragment>
|
||||
<Fragment>
|
||||
<DirectoryRef Id="Lib">
|
||||
<Directory Id="Lib_venv__freethreaded" Name="venv">
|
||||
<Directory Id="Lib_venv_scripts__freethreaded" Name="scripts">
|
||||
<Directory Id="Lib_venv_scripts_nt__freethreaded" Name="nt" />
|
||||
</Directory>
|
||||
</Directory>
|
||||
</DirectoryRef>
|
||||
</Fragment>
|
||||
<Fragment>
|
||||
<PropertyRef Id="FREETHREADED_REGISTRYKEY" />
|
||||
|
||||
<ComponentGroup Id="freethreaded_exe">
|
||||
<Component Id="freethreaded_python.exe" Directory="InstallDirectory" Guid="$(var.FreethreadedPythonExeComponentGuid)">
|
||||
<File Name="python$(var.ShortVersion)t.exe" KeyPath="yes" />
|
||||
|
||||
<RegistryKey Root="HKMU" Key="[FREETHREADED_REGISTRYKEY]">
|
||||
<RegistryValue Key="InstallPath" Type="string" Value="[InstallDirectory]" KeyPath="no" />
|
||||
<RegistryValue Key="InstallPath" Name="ExecutablePath" Type="string" Value="[#python$(var.ShortVersion)t.exe]" KeyPath="no" />
|
||||
</RegistryKey>
|
||||
</Component>
|
||||
<Component Id="freethreaded_pythonw.exe" Directory="InstallDirectory" Guid="$(var.FreethreadedPythonwExeComponentGuid)">
|
||||
<File Name="pythonw$(var.ShortVersion)t.exe" KeyPath="yes" />
|
||||
<RegistryKey Root="HKMU" Key="[FREETHREADED_REGISTRYKEY]">
|
||||
<RegistryValue Key="InstallPath" Name="WindowedExecutablePath" Type="string" Value="[#pythonw$(var.ShortVersion)t.exe]" KeyPath="no" />
|
||||
</RegistryKey>
|
||||
</Component>
|
||||
<Component Id="freethreaded_python_stable.dll" Directory="InstallDirectory" Guid="*">
|
||||
<File Id="freethreaded_python_stable.dll" Name="python$(var.MajorVersionNumber)t.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="freethreaded_python.dll" Directory="InstallDirectory" Guid="*">
|
||||
<File Id="freethreaded_python.dll" Name="python$(var.MajorVersionNumber)$(var.MinorVersionNumber)t.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
</ComponentGroup>
|
||||
</Fragment>
|
||||
<Fragment>
|
||||
<ComponentGroup Id="freethreaded_symbols">
|
||||
<Component Id="freethreaded_python_dll.pdb" Directory="InstallDirectory" Guid="*">
|
||||
<File Name="python$(var.MajorVersionNumber)$(var.MinorVersionNumber)t.pdb" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="freethreaded_python.pdb" Directory="InstallDirectory" Guid="*">
|
||||
<File Name="python$(var.ShortVersion)t.pdb" />
|
||||
</Component>
|
||||
<Component Id="freethreaded_pythonw.pdb" Directory="InstallDirectory" Guid="*">
|
||||
<File Name="pythonw$(var.ShortVersion)t.pdb" />
|
||||
</Component>
|
||||
</ComponentGroup>
|
||||
</Fragment>
|
||||
<Fragment>
|
||||
<ComponentGroup Id="freethreaded_dll_d">
|
||||
<Component Id="freethreaded_python_stable_d.dll" Directory="InstallDirectory" Guid="*">
|
||||
<File Id="freethreaded_python_stable_d.dll" Name="python$(var.MajorVersionNumber)t_d.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="freethreaded_python_d.dll" Directory="InstallDirectory" Guid="*">
|
||||
<File Id="freethreaded_python_d.dll" Name="python$(var.MajorVersionNumber)$(var.MinorVersionNumber)_d.dll" KeyPath="yes" />
|
||||
<File Id="freethreaded_python_d.pdb" Name="python$(var.MajorVersionNumber)$(var.MinorVersionNumber)_d.pdb" KeyPath="no" />
|
||||
</Component>
|
||||
</ComponentGroup>
|
||||
</Fragment>
|
||||
<Fragment>
|
||||
<ComponentGroup Id="freethreaded_exe_d">
|
||||
<Component Id="freethreaded_python_d.exe" Directory="InstallDirectory" Guid="*">
|
||||
<File Name="python$(var.ShortVersion)t_d.exe" />
|
||||
</Component>
|
||||
<Component Id="freethreaded_python_d.pdb" Directory="InstallDirectory" Guid="*">
|
||||
<File Name="python$(var.ShortVersion)t_d.pdb" />
|
||||
</Component>
|
||||
<Component Id="freethreaded_pythonw_d.exe" Directory="InstallDirectory" Guid="*">
|
||||
<File Name="pythonw$(var.ShortVersion)t_d.exe" />
|
||||
</Component>
|
||||
<Component Id="freethreaded_pythonw_d.pdb" Directory="InstallDirectory" Guid="*">
|
||||
<File Name="pythonw$(var.ShortVersion)t_d.pdb" />
|
||||
</Component>
|
||||
</ComponentGroup>
|
||||
</Fragment>
|
||||
|
||||
<?define exts=pyexpat;select;unicodedata;winsound;_bz2;_elementtree;_socket;_ssl;_ctypes;_hashlib;_multiprocessing;_lzma;_decimal;_overlapped;_sqlite3;_asyncio;_queue;_uuid;_wmi;_zoneinfo;_testcapi;_ctypes_test;_testbuffer;_testimportmultiple;_testmultiphase;_testsinglephase;_testconsole;_testinternalcapi;_testclinic;_testclinic_limited ?>
|
||||
<Fragment>
|
||||
<DirectoryRef Id="Lib_venv_scripts_nt__freethreaded" />
|
||||
|
||||
<ComponentGroup Id="freethreaded_lib_extensions">
|
||||
<?foreach ext in $(var.exts)?>
|
||||
|
||||
<Component Id="freethreaded_$(var.ext).pyd" Directory="DLLs" Guid="*">
|
||||
<File Name="$(var.ext)$(var.FreethreadedPydTag).pyd" KeyPath="yes" />
|
||||
</Component>
|
||||
|
||||
<?endforeach ?>
|
||||
|
||||
<Component Id="venvlaunchert.exe" Directory="Lib_venv_scripts_nt__freethreaded" Guid="*">
|
||||
<File Name="venvlaunchert.exe" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="venvwlaunchert.exe" Directory="Lib_venv_scripts_nt__freethreaded" Guid="*">
|
||||
<File Name="venvwlaunchert.exe" KeyPath="yes" />
|
||||
</Component>
|
||||
</ComponentGroup>
|
||||
</Fragment>
|
||||
|
||||
<Fragment>
|
||||
<DirectoryRef Id="Lib_venv_scripts_nt__freethreaded" />
|
||||
|
||||
<ComponentGroup Id="freethreaded_lib_extensions_symbols">
|
||||
<?foreach ext in $(var.exts)?>
|
||||
|
||||
<Component Id="freethreaded_$(var.ext).pdb" Directory="DLLs" Guid="*">
|
||||
<File Name="$(var.ext)$(var.FreethreadedPydTag).pdb" />
|
||||
</Component>
|
||||
|
||||
<?endforeach ?>
|
||||
|
||||
<Component Id="venvlaunchert.pdb" Directory="Lib_venv_scripts_nt__freethreaded" Guid="*">
|
||||
<File Name="venvlaunchert.pdb" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="venvwlaunchert.pdb" Directory="Lib_venv_scripts_nt__freethreaded" Guid="*">
|
||||
<File Name="venvwlaunchert.pdb" KeyPath="yes" />
|
||||
</Component>
|
||||
</ComponentGroup>
|
||||
</Fragment>
|
||||
|
||||
<Fragment>
|
||||
<ComponentGroup Id="freethreaded_lib_extensions_d">
|
||||
<?foreach ext in $(var.exts)?>
|
||||
|
||||
<Component Id="freethreaded_$(var.ext)_d.pyd" Directory="DLLs" Guid="*">
|
||||
<File Name="$(var.ext)_d$(var.FreethreadedPydTag).pyd" />
|
||||
</Component>
|
||||
<Component Id="freethreaded_$(var.ext)_d.pdb" Directory="DLLs" Guid="*">
|
||||
<File Name="$(var.ext)_d$(var.FreethreadedPydTag).pdb" />
|
||||
</Component>
|
||||
|
||||
<?endforeach ?>
|
||||
|
||||
<Component Id="venvlauncher_d.exe" Directory="Lib_venv_scripts_nt__freethreaded" Guid="*">
|
||||
<File Name="python_d.exe" Source="venvlauncher_d.exe" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="venvwlauncher_d.exe" Directory="Lib_venv_scripts_nt__freethreaded" Guid="*">
|
||||
<File Name="pythonw_d.exe" Source="venvwlauncher_d.exe" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="venvlaunchert_d.pdb" Directory="Lib_venv_scripts_nt__freethreaded" Guid="*">
|
||||
<File Name="venvlaunchert_d.pdb" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="venvwlaunchert_d.pdb" Directory="Lib_venv_scripts_nt__freethreaded" Guid="*">
|
||||
<File Name="venvwlaunchert_d.pdb" KeyPath="yes" />
|
||||
</Component>
|
||||
</ComponentGroup>
|
||||
</Fragment>
|
||||
<Fragment>
|
||||
<PropertyRef Id="FREETHREADED_REGISTRYKEY" />
|
||||
|
||||
<ComponentGroup Id="freethreaded_lib_files">
|
||||
<Component Id="PythonPathRegistry" Directory="Lib" Guid="*">
|
||||
<RegistryKey Root="HKMU" Key="[FREETHREADED_REGISTRYKEY]">
|
||||
<RegistryValue Key="PythonPath" Type="string" Value="[Lib];[DLLs]" />
|
||||
</RegistryKey>
|
||||
</Component>
|
||||
</ComponentGroup>
|
||||
</Fragment>
|
||||
</Wix>
|
|
@ -0,0 +1,20 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<ProjectGuid>{E98E7539-64E7-4DCE-AACD-01E3ADE40EFD}</ProjectGuid>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<OutputName>freethreaded_pdb</OutputName>
|
||||
<OutputType>Package</OutputType>
|
||||
</PropertyGroup>
|
||||
<Import Project="..\msi.props" />
|
||||
<ItemGroup>
|
||||
<Compile Include="freethreaded_pdb.wxs" />
|
||||
<Compile Include="freethreaded_files.wxs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="*.wxl" />
|
||||
<WxlTemplate Include="*.wxl_template" />
|
||||
</ItemGroup>
|
||||
|
||||
<Import Project="..\msi.targets" />
|
||||
</Project>
|
|
@ -0,0 +1,15 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
|
||||
<Product Id="*" Language="!(loc.LCID)" Name="!(loc.TitlePdb)" Version="$(var.Version)" Manufacturer="!(loc.Manufacturer)" UpgradeCode="$(var.UpgradeCode)">
|
||||
<Package InstallerVersion="500" Compressed="yes" InstallScope="perUser" />
|
||||
<MediaTemplate EmbedCab="yes" CompressionLevel="high" />
|
||||
|
||||
<PropertyRef Id="UpgradeTable" />
|
||||
|
||||
<Feature Id="Symbols" AllowAdvertise="no" Title="!(loc.TitlePdb)" Description="!(loc.DescriptionPdb)">
|
||||
<ComponentGroupRef Id="freethreaded_symbols" />
|
||||
<ComponentGroupRef Id="freethreaded_lib_extensions_symbols" />
|
||||
<ComponentRef Id="OptionalFeature" />
|
||||
</Feature>
|
||||
</Product>
|
||||
</Wix>
|
|
@ -26,10 +26,10 @@
|
|||
<File Name="libffi-8.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="venvlauncher.exe" Directory="Lib_venv_scripts_nt" Guid="*">
|
||||
<File Name="python.exe" Source="venvlauncher.exe" KeyPath="yes" />
|
||||
<File Name="venvlauncher.exe" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="venvwlauncher.exe" Directory="Lib_venv_scripts_nt" Guid="*">
|
||||
<File Name="pythonw.exe" Source="venvwlauncher.exe" KeyPath="yes" />
|
||||
<File Name="venvwlauncher.exe" KeyPath="yes" />
|
||||
</Component>
|
||||
</ComponentGroup>
|
||||
</Fragment>
|
||||
|
@ -63,10 +63,10 @@
|
|||
<File Name="libssl$(var.ssltag).pdb" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="venvlauncher.pdb" Directory="Lib_venv_scripts_nt__pdbs" Guid="*">
|
||||
<File Name="python.pdb" Source="venvlauncher.pdb" KeyPath="yes" />
|
||||
<File Name="venvlauncher.pdb" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="venvwlauncher.pdb" Directory="Lib_venv_scripts_nt__pdbs" Guid="*">
|
||||
<File Name="pythonw.pdb" Source="venvwlauncher.pdb" KeyPath="yes" />
|
||||
<File Name="venvwlauncher.pdb" KeyPath="yes" />
|
||||
</Component>
|
||||
</ComponentGroup>
|
||||
</Fragment>
|
||||
|
@ -100,10 +100,10 @@
|
|||
<File Name="sqlite3_d.pdb" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="venvlauncher_d.exe" Directory="Lib_venv_scripts_nt__d" Guid="*">
|
||||
<File Name="python_d.exe" Source="venvlauncher_d.exe" KeyPath="yes" />
|
||||
<File Name="venvlauncher_d.exe" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="venvwlauncher_d.exe" Directory="Lib_venv_scripts_nt__d" Guid="*">
|
||||
<File Name="pythonw_d.exe" Source="venvwlauncher_d.exe" KeyPath="yes" />
|
||||
<File Name="venvwlauncher_d.exe" KeyPath="yes" />
|
||||
</Component>
|
||||
</ComponentGroup>
|
||||
</Fragment>
|
||||
|
|
|
@ -64,6 +64,10 @@
|
|||
<InstallerVersion>$(MajorVersionNumber).$(MinorVersionNumber).$(Field3Value).0</InstallerVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<IncludeFreethreaded Condition="$(IncludeFreethreaded) != 'true'">false</IncludeFreethreaded>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="!$(BuildForRelease)">
|
||||
<RevisionNumber Condition="'$(RevisionNumber)' == ''">$([System.Math]::Floor($([System.DateTime]::Now.Subtract($([System.DateTime]::new(2001, 1, 1))).TotalDays)))</RevisionNumber>
|
||||
<PythonVersion>$(MajorVersionNumber).$(MinorVersionNumber).$(MicroVersionNumber)dev$(RevisionNumber)</PythonVersion>
|
||||
|
@ -91,9 +95,12 @@
|
|||
PyDebugExt=$(PyDebugExt);
|
||||
PyArchExt=$(PyArchExt);
|
||||
PyTestExt=$(PyTestExt);
|
||||
PydTag=$(PydTag);
|
||||
FreethreadedPydTag=$(FreethreadedPydTag);
|
||||
OptionalFeatureName=$(OutputName);
|
||||
ssltag=$(OpenSSLDLLSuffix);
|
||||
Suffix32=$(PyArchExt);
|
||||
IncludeFreethreaded=$(IncludeFreethreaded);
|
||||
</DefineConstants>
|
||||
<DefineConstants Condition="'$(CRTRedist)' != ''">
|
||||
$(DefineConstants);CRTRedist=$(CRTRedist);
|
||||
|
@ -162,6 +169,12 @@
|
|||
<_Uuid Include="PythonRegComponentGuid">
|
||||
<Uri>registry/$(OutputName)</Uri>
|
||||
</_Uuid>
|
||||
<_Uuid Include="FreethreadedPythonExeComponentGuid" Condition="$(IncludeFreethreaded)">
|
||||
<Uri>freethreaded/python.exe</Uri>
|
||||
</_Uuid>
|
||||
<_Uuid Include="FreethreadedPythonwExeComponentGuid" Condition="$(IncludeFreethreaded)">
|
||||
<Uri>freethreaded/pythonw.exe</Uri>
|
||||
</_Uuid>
|
||||
</ItemGroup>
|
||||
<Target Name="_GenerateGuids"
|
||||
AfterTargets="PrepareForBuild"
|
||||
|
|
Loading…
Reference in New Issue