-
-
Notifications
You must be signed in to change notification settings - Fork 25.8k
BLD Check build dependencies in meson.build #28721
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
Conversation
sklearn/meson.build
Outdated
if not py.version().version_compare('>=3.9') | ||
error('scikit-learn requires Python>=3.9, got ' + py.version() + ' instead') | ||
endif |
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 don't think this one is necessary since we have the requirement in pyproject.toml
. meson is already aware of the lower bound
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 tested and meson raises an error in that case
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 could remove it, but I like the fact that you have an early error if you have a too old Python.
I tested it locally and for now you need to install numpy and scipy to be told "actually you know what your Python is too old, sorry".
It seems it is meson-python
that raises the error according to the error:
('\x1b[31m',)meson-python: error: Package requires Python version >=3.9, running on 3.8.18
As noted in #28721 (comment) it would be nice if you can get the error without going through pip
, e.g. spin build
(if we use it one day) will call Meson directly.
sklearn/meson.build
Outdated
cython_min_version = run_command(py, ['_min_dependencies.py', 'cython'], check: true).stdout().strip() | ||
if not cython.version().version_compare('>=' + cython_min_version) | ||
error('scikit-learn requires Cython>=' + cython_min_version + ', got ' + cython.version() + ' instead') | ||
endif |
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 was indeed able to build with cython 3.0.8 without any complain. Since the min dependencies are listed in pyproject.toml
, is there no automated way to make meson aware of them ?
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 haven't found anything, pyproject.toml is Python-specific and Meson is a generic build tool. You can run a command from meson.build
and check its exit code, see https://mesonbuild.com/External-commands.html for more details.
I think there are a few options:
- do what is currently done in this PR,
_min_dependencies.py
for getting minimum versions + Meson-native version comparison. I am not saying this is great, but to me this seems a reasonable trade-off. I spent a bit of time trying to find something that I found significantly better and I was not able to, but better suggestions welcome! - write an external Python script but we need
packaging
to compare versions.packaging
is vendored inside pip, maybe we could assume that in most cases you have pip when you are trying to build scikit-learn ... - use our vendored
packaging
but we need__SKLEARN_SETUP__
hack +sys.path
manipulations to import fromsklearn
beforesklearn
is built - maybe better suggestions?
Note: we could give a more complicated pip
install command with --check-build-dependencies
but that would only work when building with Meson through pip. If one day we use spin
, spin build
will call meson directly (i.e. not going through pip) and as such will not error in there are some build dependencies missing.
One thing I had some hope for would be to use run_command
+ right pip
incantation to check build-dependencies in a light-weight manner (assuming pip is installed which is the most common case I think). I thought maybe
pip install . --dry-run --no-build-isolation --check-build-dependencies`
may work, but no it does not, causing an error because scikit-learn is already being built
LookupError: file:///home/lesteve/dev/scikit-learn is already being built: file:///home/lesteve/dev/scikit-learn
Side-comment: actually even pip
does not check build-dependencies are satisfied unless you use --check-build-dependencies
. See pypa/pip#11116 if you are curious why.
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.
do what is currently done in this PR, _min_dependencies.py for getting minimum versions + Meson-native version comparison. I am not saying this is great, but to me this seems a reasonable trade-off. I spent a bit of time trying to find something that I found significantly better and I was not able to, but better suggestions welcome!
I think that this approach is reasonable in that the benefit outweighs the complexity, however I'm unfamiliar with the meson build system so, similarly, I can't say for sure that there isn't a better way of doing it. Thanks for looking into this!
Another thing I am not too sure about is the cross-compiling case which is why I only check numpy and scipy when building natively (i.e. not cross-compiling). It seems like when cross-compiling the build machine can not necessarily call the host machine Python interpreter, maybe more details can be found in scipy/scipy#16783, scipy/scipy#14812 and https://mesonbuild.com/Cross-compilation.html. There is a comment that mentions this in # For cross-compilation it is often not possible to run the Python interpreter
# in order to retrieve numpy's include directory. It can be specified in the
# cross file instead:
# [properties]
# numpy-include-dir = /abspath/to/host-pythons/site-packages/numpy/core/include
#
# This uses the path as is, and avoids running the interpreter. |
Hmmm I forgot about this PR, maybe it should be considered for 1.5? Not checking versions when going via Meson may cause late confusing build errors rather than early easily understandable errors (e.g. your Cython version is too old). |
Found this PR right as I myself ran into mysterious build errors from an outdated Cython version. Indeed an explicit check to compliment the meson build system would be wonderful. |
@Micky774 after we merged #29132, for now it is up to the user to add I may have a another look at this PR at one point, but I have to admit this is not at the top of my priorities right now 😅. |
I just pushed a new commit with the correct tag to trigger the wheel builder :) |
|
||
# Only check numpy and scipy versions when not cross-compiling, as numpy and | ||
# scipy are not installed in the build machine | ||
if not meson.is_cross_build() |
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.
Note to myself: I think this one should be removed, there are other places in the code where we execute Python script without protection.
I have to say I don't remember all the details about this and need to have a closer look.
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.
So I looked a little bit more at this and I moved all the build dependency version checks inside the if not meson.is_cross_build()
clause, because I think this is safer. If I am wrong, I guess we may hear from some of this people relying on cross-compilation or they will do patches without telling us ...
It looks like conda-forge does not care about whether there is the protection if not meson.is_cross_build()
, I tested this in conda-forge/scikit-learn-feedstock#268.
On the other hand, other cross-compilation settings may care more, so I would still leave this.
For example the scipy Nix package is using numpy-include-dir
which is also meant to be used for tricky cross-compilation settings (basically you can not run the Python interpreter or the wrong numpy include dir gets picked): https://github.com/NixOS/nixpkgs/blob/81c768e223876ce8ff5120934c5d8f485731c6ed/pkgs/development/python-modules/scipy/default.nix#L61
The scikit-learn Nix package has a patch to get the version directly rather than running a Python script:
https://github.com/NixOS/nixpkgs/blob/fcf65eb2954fc78232b038ceef5d6a5390a734ec/pkgs/development/python-modules/scikit-learn/default.nix#L42-L44
We were wondering about this with @jeremiedbb, from build log, the wheels are built with
That means that build dependencies are installed in a new separate environment which will use The Wheels CI was green on this commit: e32e4c2 |
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.
LGTM.
check-build-dependencies
was causing issues in the 1.5.1 release branch because we have numpy>=2
there in the pyproject.toml, so I'm +1 for this alternative.
Side question: do you know what's the role of this section of pyproject.toml ?
[project.optional-dependencies]
build = ["numpy>=1.19.5", "scipy>=1.6.0", "cython>=3.0.10", "meson-python>=0.16.0"]
Should we set numpy>=2
here as well ?
[project.optional-dependencies]
build = ["numpy>=1.19.5", "scipy>=1.6.0", "cython>=3.0.10", "meson-python>=0.16.0"] This section are the equivalent of extra_requires, in other words it allows you to do I don't think anyone is using this, but this was in |
…as this will go away with scikit-learn#28721
I am going to merge this even if there is only one approval (thanks @jeremiedbb!). I feel nobody has had the time or courage to look at this which is perfectly understandable. I feel this is something internal and we can always adapt it when needed. |
Co-authored-by: Jérémie du Boisberranger <jeremie@probabl.ai>
Co-authored-by: Jérémie du Boisberranger <jeremie@probabl.ai>
I recently realised that we don't check build dependencies version when building with Meson. I was getting some weird Cython errors until I realised that I had 3.0.8 in my env.
I added the necessary logic in
sklearn/meson.build
to do something similar as what we do insetup.py
.This is a bit unfortunate that the logic is a bit duplicated between
meson.build
andsetup.py
but I think it is acceptable. I reused thesklearn/_min_dependencies.py
script to avoid hard-coding minimum versions in yet another place.I originally thought we could run the same Python script file from
meson.build
andsetup.py
, except that there are some complications:sklearn.external._packaging.parse
and for this you need thebuiltins.__SETUP__SKLEARN__
hack to allow partial import ofsklearn
beforesklearn
is actually builtsklearn
, or you need to dosys.path
manipulationsFull disclosure: version comparison in
meson.build
only takes into accountX.Y.Z
versions i.e. not full PEP440. I think this is OK, since for minimum dependencies it is very rare that you want a dev version that is close to a min dependency.