-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Prototype support for PEP 739 #13945
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
ea9aed7
to
697e20c
Compare
Rebased on |
64f9781
to
e9deda3
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is starting to look quite nice! \o/ How close are we to getting the PEP approved and deployed (e.g. in a cpython alpha)?
Thanks! I have requested a review for the PEP, so hopefully we should hear something soon. If it gets accepted, I'll add the file to CPython as soon as possible, so it should be available on the following release. I'll also publish a package to generate the build config file to PyPI, so that we can use it on older Python versions, or Python implementations that do not ship it, as long as you are able to run code on the target. Afterwards, in a followup to PEP 739, I also want to standardize a file for the installation environment, which will provide the installation paths. We'll ship a file for the default environment, and unless we run into some issue, I'll also get |
43fcae5
to
f30406d
Compare
The PEP has been accepted. https://peps.python.org/pep-0739/ I'll add support for it in Python 3.14, and then come back to this PR. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fantastic news! Looking forward to local testing as soon as the backportable version exists. Some more quick comments.
mesonbuild/dependencies/pkgconfig.py
Outdated
extra_paths: T.List[str] = self.env.coredata.optstore.get_value(key)[:] | ||
extra_paths: T.List[str] = self.env.coredata.optstore.get_value(key)[:] + self.extra_paths |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, I see what you're doing here. You allow a PkgConfigDependency to take an additional PKG_CONFIG_PATH which is joined to the one in the cross file, which also means we don't need to push/pop os.environ.
On the flip side, the way we previously used it was via PKG_CONFIG_LIBDIR which was more narrowly scoped. I suspect this change means we can accidentally fall back to a different python than the one we were searching for (but still the same major.minor version at least)...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah hold on, we anyways fall back to checking for pkg-config without the internal LIBPC which means this is actually doing exactly what we want with one less check. Heh. :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, and without modifying os.environ
😊
Signed-off-by: Filipe Laíns <lains@riseup.net>
Signed-off-by: Filipe Laíns <lains@riseup.net>
bc6ef41
to
b5e8baa
Compare
…figDependency Signed-off-by: Filipe Laíns <lains@riseup.net>
Signed-off-by: Filipe Laíns <lains@riseup.net>
Have you done any work for generating the build configuration for older python interpreters? If not, I can probably spend some time on that. |
Yes. It might not handle every quirk and doesn't have tests, but it's here: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall, great work. Thanks!
That said, from the initial eyeball review it seems that some of the code assumes that non-required values will be present, and they look especially incorrect for PyPy.
I'm going to actually run the code tomorrow and try to experiment a bit with it.
value = self._data | ||
for part in key.split('.'): | ||
value = value[part] | ||
return value |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's a reduce()
pattern you could use here:
value = self._data | |
for part in key.split('.'): | |
value = value[part] | |
return value | |
return functools.reduce(lambda d, k: d[k], key.split('.'), self._data) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure. If we are simplifying it that way, we can also use operator.getitem
to replace the lambda.
value = self._data | |
for part in key.split('.'): | |
value = value[part] | |
return value | |
return functools.reduce(operator.getitem, key.split('.'), self._data) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, yes, I swear I have looked for one and couldn't find it. But now I see it, I must have made some silly mistake.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Included in my fork now.
if not self.build_config['libpython']: | ||
mlog.debug('This Python installation does not provide a libpython') | ||
return False |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm sorry if I'm missing something but I think this assertion is incorrect. Per PEP 739, libpython
is optional, and at least on Gentoo PyPy is installed without a shared library. Given that C extensions can be built without linking to it explicitly, and Meson has no problem building such extensions for PyPy, I don't think we should enforce libpython
being present here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, The build-detail.json
file semantics changed a bit during the PEP's lifetime, this is a leftover of that.
Taking your feedback into account, I think this error should be tied to libpython.link_extensions
, but unfortunately, the spec doesn't permit libpython.link_extensions
when libpython.dynamic
is missing.
I have opened pypa/packaging.python.org#1862 to track changes we'd like to make for a new spec version, and added this as one of them.
Thanks for noticing this shortcoming!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, that's an interesting point. I'll reply to the PyPA bug with my thoughts.
@property | ||
def version(self) -> str: | ||
if self.build_config: | ||
value = self.build_config['language']['version'] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a reason that we aren't using the dotted key support that seems to be provided by BuildConfig
?
self.version = self.build_config['language']['version'] | ||
self.platform = self.build_config['platform'] | ||
self.is_freethreaded = 't' in self.build_config['abi']['flags'] | ||
self.link_libpython = self.build_config['libpython']['link_extensions'] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Per my note above, I suppose this should be:
self.link_libpython = self.build_config['libpython']['link_extensions'] | |
self.link_libpython = self.build_config.get('libpython.link_extensions', False) |
Hmm, another thought: should we disable/skip pkg-config detection if |
if not path: | ||
raise DependencyException('Python does not provide a dynamic libpython library') | ||
libdirs = [os.path.dirname(path)] | ||
libname = os.path.basename(path) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems to be incorrect. FWICS find_library()
can't handle the full filename (e.g. libpython3.14.so
, but needs the bare python3.14
.
Sorry for the delay getting back to you! No worries at all from me! In fact, that would make me very happy 😊. I have been suffering from burnout and haven't been able to make productive progress on my own in this project, so having someone pick it back up would make me feel a lot better. While I don't think I am in a position where I can productively drive the development, I am more than happy to collaborate and help navigate the complexity around this feature. |
Thanks! I've opened #14657 to continue the work — unless you have a better idea how to proceed. |
pkg_libdir = installation.info['variables'].get('LIBPC') | ||
pkg_libdir_origin = 'LIBPC' if pkg_libdir else 'the default paths' | ||
mlog.debug(f'Searching for {pkg_libdir!r} via pkgconfig lookup in {pkg_libdir_origin}') | ||
pkgconfig_paths = [pkg_libdir] if pkg_libdir else [] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, the assumption that we check default pkg-config dirs when LIBPC
is not set introduced a regression — now we end up taking python-3.11.pc
on PyPy, so effectively PyPy extensions start being built against the headers from CPython.
The way I see it, we have two options here: either we restore the previous logic that pkg-config is not used when LIBPC
is not set, or we unconditionally skip pkg-config when not targeting CPython (in the end, the pkg_name
assumption is CPython-only).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd lean towards restoring the previous logic with a descriptive code comment, so it's easier to understand for whoever looks at this next. I'm thinking either change is reasonable; restoring the logic may be better just in case something like crossenv
, GraalPython or Pyodide relies on this logic.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be good to make sure all of this works with crossenv
. Even if meson can get all of the python information via PEP 739 support, when using pkgconf-pypi
there isn't yet a way for a package that depends on pkg-config information published by another wheel to retrieve it without using crossenv
.
I should probably add a crossenv testcase to pkgconf-pypi.
Reference: pypackaging-native/pkgconf-pypi#74
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm sorry but I'm thoroughly confused by what you're saying. Meson here looks up the .pc
files for Python itself. I don't think there is a case where this logic would be used for any other package or any other purpose.
Also, the discussion is about PyPy, not PyPI.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My apologies for the confusion. It wasn't directly related to your comment, but rgommers mention of crossenv -- the TL;DR of my comment is "It would be good to make sure all of this works with crossenv.". The rest of the comment explains a situation where one might still need crossenv after this PR is merged.
See mesonbuild#13945 (comment) Signed-off-by: Michał Górny <mgorny@quansight.com>
See mesonbuild#13945 (comment) Signed-off-by: Michał Górny <mgorny@quansight.com>
See mesonbuild#13945 (comment) Signed-off-by: Michał Górny <mgorny@quansight.com>
See mesonbuild#13945 (comment) Signed-off-by: Michał Górny <mgorny@quansight.com>
The overall goal is to support targeting Python installations without need for introspection, given all necessary information is given externally.
This is built upon:
_sysconfigdata
to a JSON file python/cpython#127178, forpy_installation.get_variable
/py_installation.has_variable
supportThis PR is just a prototype, as I work to get all necessary pieces finalized.