Skip to content

Commit

Permalink
Add support for detecting free-threaded Python on Windows
Browse files Browse the repository at this point in the history
This does a couple of things:
1. Scrape the `Py_GIL_DISABLED` sysconfig var, which is the best way as of today
   to determine whether the target interpreter was built with `--disable-gil`
2. link against the correct libpython
3. On Windows, work around a known issue in the python.org installer with a
   missing define in `pyconfig.h`, which the CPython devs have said is unlikely
   to be fixed since headers are shared between the regular and free-threaded
   builds in a single NSIS installer.
  • Loading branch information
rgommers authored and jpakkane committed Jun 23, 2024
1 parent c0ca35c commit a111c28
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 1 deletion.
14 changes: 13 additions & 1 deletion mesonbuild/dependencies/python.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ class PythonIntrospectionDict(TypedDict):
install_paths: T.Dict[str, str]
is_pypy: bool
is_venv: bool
is_freethreaded: bool
link_libpython: bool
sysconfig_paths: T.Dict[str, str]
paths: T.Dict[str, str]
Expand Down Expand Up @@ -91,6 +92,7 @@ def __init__(self, name: str, command: T.Optional[T.List[str]] = None,
'install_paths': {},
'is_pypy': False,
'is_venv': False,
'is_freethreaded': False,
'link_libpython': False,
'sysconfig_paths': {},
'paths': {},
Expand Down Expand Up @@ -146,6 +148,7 @@ def __init__(self, python_holder: 'BasicPythonExternalProgram', embed: bool):
self.variables = python_holder.info['variables']
self.paths = python_holder.info['paths']
self.is_pypy = python_holder.info['is_pypy']
self.is_freethreaded = python_holder.info['is_freethreaded']
# The "-embed" version of python.pc / python-config was introduced in 3.8,
# and distutils extension linking was changed to be considered a non embed
# usage. Before then, this dependency always uses the embed=True handling
Expand All @@ -161,6 +164,12 @@ def __init__(self, python_holder: 'BasicPythonExternalProgram', embed: bool):
else:
self.major_version = 2

# pyconfig.h is shared between regular and free-threaded builds in the
# Windows installer from python.org, and hence does not define
# Py_GIL_DISABLED correctly. So do it here:
if mesonlib.is_windows() and self.is_freethreaded:
self.compile_args += ['-DPy_GIL_DISABLED']

def find_libpy(self, environment: 'Environment') -> None:
if self.is_pypy:
if self.major_version == 3:
Expand Down Expand Up @@ -220,7 +229,10 @@ def get_windows_link_args(self, limited_api: bool) -> T.Optional[T.List[str]]:
else:
if limited_api:
vernum = vernum[0]
libpath = Path('libs') / f'python{vernum}.lib'
if self.is_freethreaded:
libpath = Path('libs') / f'python{vernum}t.lib'
else:
libpath = Path('libs') / f'python{vernum}.lib'
# For a debug build, pyconfig.h may force linking with
# pythonX_d.lib (see meson#10776). This cannot be avoided
# and won't work unless we also have a debug build of
Expand Down
4 changes: 4 additions & 0 deletions mesonbuild/scripts/python_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,9 @@ def links_against_libpython():
if is_pypy:
limited_api_suffix = suffix

# Whether we're targeting a free-threaded CPython interpreter
is_freethreaded = bool(variables.get('Py_GIL_DISABLED', False))

print(json.dumps({
'variables': variables,
'paths': paths,
Expand All @@ -118,4 +121,5 @@ def links_against_libpython():
'link_libpython': links_against_libpython(),
'suffix': suffix,
'limited_api_suffix': limited_api_suffix,
'is_freethreaded': is_freethreaded,
}))

0 comments on commit a111c28

Please sign in to comment.