8000 BLD Add Meson support (#28040) · scikit-learn/scikit-learn@56625c9 · GitHub
[go: up one dir, main page]

Skip to content

Commit 56625c9

Browse files
lesteveadrinjalaliogriselglemaitrejjerphan
authored
BLD Add Meson support (#28040)
Co-authored-by: Adrin Jalali <adrin.jalali@gmail.com> Co-authored-by: Olivier Grisel <olivier.grisel@ensta.org> Co-authored-by: Guillaume Lemaitre <g.lemaitre58@gmail.com> Co-authored-by: Julien Jerphanion <git@jjerphan.xyz>
1 parent 07007b3 commit 56625c9

File tree

34 files changed

+1100
-3
lines changed

34 files changed

+1100
-3
lines changed

Makefile

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,14 @@ in: inplace # just a shortcut
2323
inplace:
2424
$(PYTHON) setup.py build_ext -i
2525

26+
dev-meson:
27+
# Temporary script to try the experimental meson build. Once meson is
28+
# accepted as the default build tool, this will go away.
29+
python build_tools/build-meson-editable-install.py
30+
31+
clean-meson:
32+
pip uninstall -y scikit-learn
33+
2634
test-code: in
2735
$(PYTEST) --showlocals -v sklearn --durations=20
2836
test-sphinxext:

azure-pipelines.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@ jobs:
171171
DISTRIB: 'conda'
172172
LOCK_FILE: './build_tools/azure/pylatest_conda_forge_mkl_linux-64_conda.lock'
173173
COVERAGE: 'true'
174+
BUILD_WITH_MESON: 'true'
174175
SKLEARN_TESTS_GLOBAL_RANDOM_SEED: '42' # default global random seed
175176

176177
# Check compilation with Ubuntu 22.04 LTS (Jammy Jellyfish) and scipy from conda-forge

build_tools/azure/install.sh

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,8 +126,10 @@ scikit_learn_install() {
126126
export LDFLAGS="$LDFLAGS -Wl,--sysroot=/"
127127
fi
128128

129+
if [[ "$BUILD_WITH_MESON" == "true" ]]; then
130+
make dev-meson
129131
# TODO use a specific variable for this rather than using a particular build ...
130-
if [[ "$DISTRIB" == "conda-pip-latest" ]]; then
132+
elif [[ "$DISTRIB" == "conda-pip-latest" ]]; then
131133
# Check that pip can automatically build scikit-learn with the build
132134
# dependencies specified in pyproject.toml using an isolated build
133135
# environment:

build_tools/azure/pylatest_conda_forge_mkl_linux-64_conda.lock

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Generated by conda-lock.
22
# platform: linux-64
3-
# input_hash: 0e751f4212c4e51710aad471314a8b385a5e12fe3536c2a766f949da61eabb88
3+
# input_hash: 0cee038efd0cc93a79f66b1cdbbc359ac52521c98df956b3e4042575e89711f5
44
@EXPLICIT
55
https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2#d7c89558ba9fa0495403155b64376d81
66
https://conda.anaconda.org/conda-forge/linux-64/ca-certificates-2023.11.17-hbcca054_0.conda#01ffc8d36f9eba0ce0b3c1955fa780ee
@@ -20,7 +20,7 @@ https://conda.anaconda.org/conda-forge/linux-64/alsa-lib-1.2.10-hd590300_0.conda
2020
https://conda.anaconda.org/conda-forge/linux-64/attr-2.5.1-h166bdaf_1.tar.bz2#d9c69a24ad678ffce24c6543a0176b00
2121
https://conda.anaconda.org/conda-forge/linux-64/aws-c-common-0.9.0-hd590300_0.conda#71b89db63b5b504e7afc8ad901172e1e
2222
https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hd590300_5.conda#69b8b6202a07720f448be700e300ccf4
23-
https://conda.anaconda.org/conda-forge/linux-64/c-ares-1.24.0-hd590300_0.conda#f5842b88e9cbfa177abfaeacd457a45d
23+
https://conda.anaconda.org/conda-forge/linux-64/c-ares-1.25.0-hd590300_0.conda#89e40af02dd3a0846c0c1131c5126706
2424
https://conda.anaconda.org/conda-forge/linux-64/gettext-0.21.1-h27087fc_0.tar.bz2#14947d8770185e5153fdd04d4673ed37
2525
https://conda.anaconda.org/conda-forge/linux-64/gflags-2.2.2-he1b5a44_1004.tar.bz2#cddaf2c63ea4a5901cf09524c490ecdc
2626
https://conda.anaconda.org/conda-forge/linux-64/graphite2-1.3.13-h58526e2_1001.tar.bz2#8c54672728e8ec6aa6db90cf2806d220
@@ -50,6 +50,7 @@ https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.2.13-hd590300_5.conda#
5050
https://conda.anaconda.org/conda-forge/linux-64/lz4-c-1.9.4-hcb278e6_0.conda#318b08df404f9c9be5712aaa5a6f0bb0
5151
https://conda.anaconda.org/conda-forge/linux-64/mpg123-1.32.3-h59595ed_0.conda#bdadff838d5437aea83607ced8b37f75
5252
https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.4-h59595ed_2.conda#7dbaa197d7ba6032caf7ae7f32c1efa0
53+
https://conda.anaconda.org/conda-forge/linux-64/ninja-1.11.1-h924138e_0.conda#73a4953a2d9c115bdc10ff30a52f675f
5354
https://conda.anaconda.org/conda-forge/linux-64/nspr-4.35-h27087fc_0.conda#da0ec11a6454ae19bff5b02ed881a2b1
5455
https://conda.anaconda.org/conda-forge/linux-64/openssl-3.2.0-hd590300_1.conda#603827b39ea2b835268adb8c821b8570
5556
https://conda.anaconda.org/conda-forge/linux-64/pixman-0.43.0-h59595ed_0.conda#6b4b43013628634b6cfdee6b74fd696b
@@ -159,6 +160,7 @@ https://conda.anaconda.org/conda-forge/noarch/toml-0.10.2-pyhd8ed1ab_0.tar.bz2#f
159160
https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2#5844808ffab9ebdb694585b50ba02a96
160161
https://conda.anaconda.org/conda-forge/linux-64/tornado-6.3.3-py311h459d7ec_1.conda#a700fcb5cedd3e72d0c75d095c7a6eda
161162
https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.9.0-pyha770c72_0.conda#a92a6440c3fe7052d63244f3aba2a4a7
163+
https://conda.anaconda.org/conda-forge/noarch/wheel-0.42.0-pyhd8ed1ab_0.conda#1cdea58981c5cbc17b51973bcaddcea7
162164
https://conda.anaconda.org/conda-forge/linux-64/xcb-util-image-0.4.0-h8ee46fc_1.conda#9d7bcddf49cbf727730af10e71022c73
163165
https://conda.anaconda.org/conda-forge/linux-64/xkeyboard-config-2.40-hd590300_0.conda#07c15d846a2e4d673da22cbd85fdb6d2
164166
https://conda.anaconda.org/conda-forge/linux-64/xorg-libxext-1.3.4-h0b41bf4_2.conda#82b6df12252e6f32402b96dacc656fec
@@ -173,9 +175,12 @@ https://conda.anaconda.org/conda-forge/noarch/joblib-1.3.2-pyhd8ed1ab_0.conda#4d
173175
https://conda.anaconda.org/conda-forge/linux-64/libclang-15.0.7-default_hb11cfb5_4.conda#c90f4cbb57839c98fef8f830e4b9972f
174176
https://conda.anaconda.org/conda-forge/linux-64/libgoogle-cloud-2.12.0-hac9eb74_1.conda#0dee716254497604762957076ac76540
175177
https://conda.anaconda.org/conda-forge/linux-64/libxkbcommon-1.6.0-h5d7e998_0.conda#d8edd0e29db6fb6b6988e1a28d35d994
178+
https://conda.anaconda.org/conda-forge/noarch/meson-1.3.1-pyhd8ed1ab_0.conda#54744574be599bff37ee4c3624ed02d2
176179
https://conda.anaconda.org/conda-forge/linux-64/mkl-2022.2.1-h84fe81f_16997.conda#a7ce56d5757f5b57e7daabe703ade5bb
177180
https://conda.anaconda.org/conda-forge/linux-64/pillow-10.2.0-py311ha6c5da5_0.conda#a5ccd7f2271f28b7d2de0b02b64e3796
181+
https://conda.anaconda.org/conda-forge/noarch/pip-23.3.2-pyhd8ed1ab_0.conda#8591c748f98dcc02253003533bc2e4b1
178182
https://conda.anaconda.org/conda-forge/linux-64/pulseaudio-client-16.1-hb77b528_5.conda#ac902ff3c1c6d750dd0dfc93a974ab74
183+
https://conda.anaconda.org/conda-forge/noarch/pyproject-metadata-0.7.1-pyhd8ed1ab_0.conda#dcb27826ffc94d5f04e241322239983b
179184
https://conda.anaconda.org/conda-forge/noarch/pytest-7.4.4-pyhd8ed1ab_0.conda#a9d145de8c5f064b5fa68fb34725d9f4
180185
https://conda.anaconda.org/conda-forge/noarch/python-dateutil-2.8.2-pyhd8ed1ab_0.tar.bz2#dd999d1cc9f79e67dbb855c8924c7984
181186
https://conda.anaconda.org/conda-forge/linux-64/sip-6.7.12-py311hb755f60_0.conda#02336abab4cb5dd794010ef53c54bd09
@@ -184,6 +189,7 @@ https://conda.anaconda.org/conda-forge/linux-64/blas-1.0-mkl.tar.bz2#349aef876b1
184189
https://conda.anaconda.org/conda-forge/linux-64/gstreamer-1.22.8-h98fc4e7_1.conda#1b52a89485ab573a5bb83a5225ff706e
185190
https://conda.anaconda.org/conda-forge/linux-64/harfbuzz-8.3.0-h3d44ed6_0.conda#5a6f6c00ef982a9bc83558d9ac8f64a0
186191
https://conda.anaconda.org/conda-forge/linux-64/libblas-3.9.0-16_linux64_mkl.tar.bz2#85f61af03fd291dae33150ffe89dc09a
192+
https://conda.anaconda.org/conda-forge/noarch/meson-python-0.15.0-pyh0c530f3_0.conda#3bc64565ca78ce3bb80248d09926d8f9
187193
https://conda.anaconda.org/conda-forge/linux-64/pyqt5-sip-12.12.2-py311hb755f60_5.conda#e4d262cc3600e70b505a6761d29f6207
188194
https://conda.anaconda.org/conda-forge/noarch/pytest-cov-4.1.0-pyhd8ed1ab_0.conda#06eb685a3a0b146347a58dda979485da
189195
https://conda.anaconda.org/conda-forge/noarch/pytest-xdist-3.5.0-pyhd8ed1ab_0.conda#d5f595da2daead898ca958ac62f0307b

build_tools/azure/pylatest_conda_forge_mkl_linux-64_environment.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ dependencies:
2121
- pytest-cov
2222
- coverage
2323
- ccache
24+
- meson-python
25+
- pip
2426
- pytorch=1.13
2527
- pytorch-cpu
2628
- polars
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import re
2+
import shlex
3+
import subprocess
4+
from pathlib import Path
5+
6+
7+
def main():
8+
pyproject_path = Path("pyproject.toml")
9+
10+
if not pyproject_path.exists():
11+
raise SystemExit(
12+
"Can not find pyproject.toml. You should run this script from the"
13+
" scikit-learn root folder."
14+
)
15+
16+
old_pyproject_content = pyproject_path.read_text(encoding="utf-8")
17+
if 'build-backend = "mesonpy"' not in old_pyproject_content:
18+
new_pyproject_content = re.sub(
19+
r"\[build-system\]",
20+
r'[build-system]\nbuild-backend = "mesonpy"',
21+
old_pyproject_content,
22+
)
23+
pyproject_path.write_text(new_pyproject_content, encoding="utf-8")
24+
25+
command = shlex.split(
26+
"pip install --editable . --verbose --no-build-isolation "
27+
"--config-settings editable-verbose=true"
28+
)
29+
30+
exception = None
31+
try:
32+
subprocess.check_call(command)
33+
except Exception as e:
34+
exception = e
35+
finally:
36+
pyproject_path.write_text(old_pyproject_content, encoding="utf-8")
37+
38+
if exception is not None:
39+
raise RuntimeError(
40+
"There was some error when running the script"
41+
) from exception
42+
43+
44+
if __name__ == "__main__":
45+
main()

build_tools/update_environments_and_lock_files.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,8 @@ def remove_from(alist, to_remove):
9797
"channel": "conda-forge",
9898
"conda_dependencies": common_dependencies + [
9999
"ccache",
100+
"meson-python",
101+
"pip",
100102
"pytorch",
101103
"pytorch-cpu",
102104
"polars",

doc/developers/advanced_installation.rst

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,88 @@ It is however preferred to use pip.
201201
On Unix-like systems, you can equivalently type ``make in`` from the top-level
202202
folder. Have a look at the ``Makefile`` for additional utilities.
203203

204+
.. _building_with_meson:
205+
206+
Building with Meson
207+
-------------------
208+
209+
Support for Meson is experimental, in scikit-learn 1.5.0.dev0.
210+
`Open an issue <https://github.com/scikit-learn/scikit-learn/issues/new>`__ if
211+
you encounter any problems!
212+
213+
Make sure you have `meson-python` and `ninja` installed, either with `conda`:
214+
215+
.. code-block:: bash
216+
217+
conda install -c conda-forge meson-python ninja -y
218+
219+
or with pip:
220+
221+
.. code-block:: bash
222+
223+
pip install meson-python ninja
224+
225+
Simplest way to build with Meson
226+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
227+
228+
To build scikit-learn, the simplest way is to run:
229+
230+
.. code-block:: bash
231+
232+
make dev-meson
233+
234+
You need to do it once after this you can run your code that imports `sklearn`
235+
and it will recompile as needed.
236+
237+
In case you want to go back to using setuptools:
238+
239+
.. code-block:: bash
240+
241+
make clean-meson
242+
243+
More advanced way to build with Meson
244+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
245+
246+
If you can not use `make`, want to do it yourself or understand what goes in
247+
behind the scenes, you can edit `pyproject.toml` and make sure `build-backend`
248+
is set to `"mesonpy"`
249+
250+
.. code-block:: toml
251+
252+
[build-system]
253+
build-backend = "mesonpy"
254+
255+
Build with the following `pip` command:
256+
257+
.. code-block:: bash
258+
259+
pip install --editable . \
260+
--verbose --no-build-isolation \
261+
--config-settings editable-verbose=true
262+
263+
If you want to go back to using `setuptools`:
264+
265+
.. code-block:: bash
266+
267+
pip uninstall -y scikit-learn
268+
269+
Note `--config-settings editable-verbose=true` is advised to avoid surprises.
270+
meson-python implements editable install by recompiling when doing `import
271+
sklearn`. Even changing python files involves copying files to the Meson build
272+
directory. You will see the meson output when that happens, rather than
273+
potentially waiting a while and wondering what is taking so long. Bonus: that
274+
means you only have to do the `pip install` once, after that your code will
275+
recompile when doing `import sklearn`.
276+
277+
Other places that may be worth looking at:
278+
279+
- `pandas setup doc
280+
<https://pandas.pydata.org/docs/development/contributing_environment.html#step-3-build-and-install-pandas>`_:
281+
pandas has a similar setup as ours (no spin or dev.py)
282+
- `scipy Meson doc
283+
<https://scipy.github.io/devdocs/building/understanding_meson.html>`_ gives
284+
more background about how Meson works behind the scenes
285+
204286
.. _platform_specific_instructions:
205287

206288
Platform-specific instructions

doc/whats_new/v1.5.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,16 @@ Version 1.5.0
1111

1212
.. include:: changelog_legend.inc
1313

14+
Support for building with Meson
15+
-------------------------------
16+
17+
Meson is now supported as a build backend, see :ref:`Building with Meson
18+
<building_with_meson>` for more details.
19+
20+
:pr:`28040` by :user:`Loïc Estève <lesteve>`
21+
22+
TODO Fill more details before the 1.5 release, when the Meson story has settled down.
23+
1424
Changelog
1525
---------
1626

meson.build

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
project(
2+
'scikit-learn',
3+
'c', 'cpp', 'cython',
4+
version: run_command('sklearn/_build_utils/version.py', check: true).stdout().strip(),
5+
license: 'BSD-3',
6+
meson_version: '>= 1.1.0',
7+
default_options: [
8+
'buildtype=debugoptimized',
9+
'c_std=c99',
10+
'cpp_std=c++14',
11+
],
12+
)
13+
14+
cc = meson.get_compiler('c')
15+
cpp = meson.get_compiler('cpp')
16+
17+
# Check compiler is recent enough (see "Toolchain Roadmap" for details)
18+
if cc.get_id() == 'gcc'
19+
if not cc.version().version_compare('>=8.0')
20+
error('scikit-learn requires GCC >= 8.0')
21+
endif
22+
elif cc.get_id() == 'msvc'
23+
if not cc.version().version_compare('>=19.20')
24+
error('scikit-learn requires at least vc142 (default with Visual Studio 2019) ' + \
25+
'when building with MSVC')
26+
endif
27+
endif
28+
29+
_global_c_args = cc.get_supported_arguments(
30+
'-Wno-unused-but-set-variable',
31+
'-Wno-unused-function',
32+
'-Wno-conversion',
33+
'-Wno-misleading-indentation',
34+
)
35+
add_project_arguments(_global_c_args, language : 'c')
36+
37+
# We need -lm for all C code (assuming it uses math functions, which is safe to
38+
# assume for scikit-learn). For C++ it isn't needed, because libstdc++/libc++ is
39+
# guaranteed to depend on it.
40+
m_dep = cc.find_library('m', required : false)
41+
if m_dep.found()
42+
add_project_link_arguments('-lm', language : 'c')
43+
endif
44+
45+
tempita = files('sklearn/_build_utils/tempita.py')
46+
47+
py = import('python').find_installation(pure: false)
48+
49+
# Copy all the .py files to the install dir, rather than using
50+
# py.install_sources and needing to list them explicitely one by one
51+
install_subdir('sklearn', install_dir: py.get_install_dir())
52+
53+
subdir('sklearn')

0 commit comments

Comments
 (0)
0