Fix python3 installed from the Windows Store

When meson is currently being run with a python that seems to have been
installed from the Windows Store, replace the general WindowsApps
directory in search paths with dirname(sys.executable), and also handle
failures with pathlib.resolve on WindowsApps exe files.
This commit is contained in:
D Scott Phillips 2020-06-02 21:20:52 -07:00 committed by Jussi Pakkanen
parent 5663b4a3e8
commit f6a842821b
2 changed files with 26 additions and 4 deletions

View File

@ -22,6 +22,7 @@ import json
import shlex
import shutil
import stat
import sys
import textwrap
import platform
import typing as T
@ -1845,14 +1846,22 @@ class ExternalProgram:
# Ensure that we use USERPROFILE even when inside MSYS, MSYS2, Cygwin, etc.
if 'USERPROFILE' not in os.environ:
return path
# Ignore executables in the WindowsApps directory which are
# zero-sized wrappers that magically open the Windows Store to
# install the application.
# The WindowsApps directory is a bit of a problem. It contains
# some zero-sized .exe files which have "reparse points", that
# might either launch an installed application, or might open
# a page in the Windows Store to download the application.
#
# To handle the case where the python interpreter we're
# running on came from the Windows Store, if we see the
# WindowsApps path in the search path, replace it with
# dirname(sys.executable).
appstore_dir = Path(os.environ['USERPROFILE']) / 'AppData' / 'Local' / 'Microsoft' / 'WindowsApps'
paths = []
for each in path.split(os.pathsep):
if Path(each) != appstore_dir:
paths.append(each)
elif 'WindowsApps' in sys.executable:
paths.append(os.path.dirname(sys.executable))
return os.pathsep.join(paths)
@staticmethod

View File

@ -41,6 +41,7 @@ import shutil
import uuid
import re
import shlex
import stat
import subprocess
import collections
import functools
@ -2512,7 +2513,19 @@ class Interpreter(InterpreterBase):
elif os.path.isfile(f) and not f.startswith('/dev'):
srcdir = Path(self.environment.get_source_dir())
builddir = Path(self.environment.get_build_dir())
f = Path(f).resolve()
try:
f = Path(f).resolve()
except OSError:
f = Path(f)
s = f.stat()
if (hasattr(s, 'st_file_attributes') and
s.st_file_attributes & stat.FILE_ATTRIBUTE_REPARSE_POINT != 0 and
s.st_reparse_tag == stat.IO_REPARSE_TAG_APPEXECLINK):
# This is a Windows Store link which we can't
# resolve, so just do our best otherwise.
f = f.parent.resolve() / f.name
else:
raise
if builddir in f.parents:
return
if srcdir in f.parents: