* [PATCH] meson: port python bindings to build natively via meson and meson-python @ 2025-03-17 0:40 Eli Schwartz 2025-03-18 14:15 ` Rob Herring 2025-03-19 5:55 ` David Gibson 0 siblings, 2 replies; 20+ messages in thread From: Eli Schwartz @ 2025-03-17 0:40 UTC (permalink / raw) To: devicetree-compiler We get full build parallelism and fewer confusing ancient distutils paths. The python wheels build fully standalone, including linking libfdt as a static library. For convenience, when running pip install a meson option is passed that prevents building tools or installing headers/pkgconfig files. meson-python would otherwise include them in the wheel itself, in case they are needed, but this is essentially a bit useless so don't bother. Signed-off-by: Eli Schwartz <eschwartz@gentoo.org> --- MANIFEST.in | 12 ------ libfdt/meson.build | 32 ++++++++------- meson.build | 3 +- meson_options.txt | 2 + pylibfdt/meson.build | 28 ++++++++----- pyproject.toml | 25 ++++++++++++ setup.py | 97 -------------------------------------------- 7 files changed, 64 insertions(+), 135 deletions(-) delete mode 100644 MANIFEST.in create mode 100644 pyproject.toml delete mode 100755 setup.py diff --git a/MANIFEST.in b/MANIFEST.in deleted file mode 100644 index 904d124..0000000 --- a/MANIFEST.in +++ /dev/null @@ -1,12 +0,0 @@ -# SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) - -global-exclude * -include README.md -include GPL -include BSD-2-Clause -include setup.py -include pylibfdt/libfdt.i -include libfdt/libfdt.h -include libfdt/fdt.h -include libfdt/libfdt_env.h -include VERSION.txt diff --git a/libfdt/meson.build b/libfdt/meson.build index c2f4bd6..9c6ef54 100644 --- a/libfdt/meson.build +++ b/libfdt/meson.build @@ -31,7 +31,7 @@ libfdt = library( version: meson.project_version(), link_args: link_args, link_depends: 'version.lds', - install: true, + install: get_option('default_library') != 'static' or not wheel_only, ) libfdt_inc = include_directories('.') @@ -41,20 +41,22 @@ libfdt_dep = declare_dependency( link_with: libfdt, ) -install_headers( - files( - 'fdt.h', - 'libfdt.h', - 'libfdt_env.h', +if not wheel_only + install_headers( + files( + 'fdt.h', + 'libfdt.h', + 'libfdt_env.h', + ) ) -) -pkgconfig = import('pkgconfig') + pkgconfig = import('pkgconfig') -pkgconfig.generate( - libraries: libfdt, - version: meson.project_version(), - filebase: 'libfdt', - name: 'libfdt', - description: 'Flat Device Tree manipulation', -) + pkgconfig.generate( + libraries: libfdt, + version: meson.project_version(), + filebase: 'libfdt', + name: 'libfdt', + description: 'Flat Device Tree manipulation', + ) +endif diff --git a/meson.build b/meson.build index 3026f88..ed4a39d 100644 --- a/meson.build +++ b/meson.build @@ -43,6 +43,7 @@ py = import('python') py = py.find_installation(required: get_option('python')) swig = find_program('swig', required: get_option('python')) pylibfdt_enabled = not meson.is_cross_build() and py.found() and swig.found() ? true : false +wheel_only = get_option('wheel-only') version_gen_h = vcs_tag( command: ['git', 'describe', '--dirty=+'], @@ -59,7 +60,7 @@ util_dep = declare_dependency( dependencies: libfdt_dep ) -if get_option('tools') +if get_option('tools') and not wheel_only flex = find_program('flex', required: true) bison = find_program('bison', required: true) diff --git a/meson_options.txt b/meson_options.txt index 62b31b3..a866b17 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -10,3 +10,5 @@ option('python', type: 'feature', value: 'auto', description: 'Build pylibfdt Python library') option('tests', type: 'boolean', value: true, description: 'Build tests') +option('wheel-only', type: 'boolean', value: false, + description: 'building from meson-python') diff --git a/pylibfdt/meson.build b/pylibfdt/meson.build index 6157f8d..b13d802 100644 --- a/pylibfdt/meson.build +++ b/pylibfdt/meson.build @@ -1,13 +1,21 @@ -setup_py = find_program('../setup.py') -setup_py = [setup_py, '--quiet', '--top-builddir', meson.project_build_root()] - -pylibfdt = custom_target( - 'pylibfdt', +libfdt_c = custom_target( + 'swig', input: 'libfdt.i', - depends: libfdt, - output: '_libfdt.so', - command: [setup_py, 'build_ext'], - build_by_default: true, + output: ['libfdt.c', 'libfdt.py'], + install: true, + install_dir: [false, py.get_install_dir(pure: false)], + command: [swig, '-python', '-I'+meson.current_source_dir() / '../libfdt', '-o', '@OUTPUT0@', '@INPUT@'] ) -meson.add_install_script(setup_py, 'install', '--prefix=' + get_option('prefix'), '--root=$DESTDIR') +nowarn_gen = cc.get_supported_arguments( + '-Wno-cast-qual', + '-Wno-missing-prototypes', + '-Wno-redundant-decls', +) +pylibfdt = py.extension_module( + '_libfdt', + libfdt_c, + c_args: ['-DPY_SSIZE_T_CLEAN'] + nowarn_gen, + dependencies: [libfdt_dep, py.dependency()], + install: true, +) diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..0929bd0 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,25 @@ +[build-system] +build-backend = 'mesonpy' +requires = ['meson-python'] + +[project] +name = 'libfdt' +authors = [ + {name = 'Simon Glass', email = 'sjg@chromium.org'}, +] +classifiers = [ + 'Programming Language :: Python :: 3', + 'License :: OSI Approved :: BSD License', + 'License :: OSI Approved :: GNU General Public License v2 or later (GPLv2+)', + 'Operating System :: OS Independent', +] +description = 'Pthon binding for libfdt' +readme = 'README.md' +requires-python = '>=3.8' +dynamic = ['version'] + +[project.urls] +'homepage' = 'https://git.kernel.org/pub/scm/utils/dtc/dtc.git' + +[tool.meson-python.args] +'setup' = ['-Ddefault_library=static', '-Dwheel-only=true'] diff --git a/setup.py b/setup.py deleted file mode 100755 index 52844ce..0000000 --- a/setup.py +++ /dev/null @@ -1,97 +0,0 @@ -#!/usr/bin/env python3 -# SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) - -""" -setup.py file for SWIG libfdt -Copyright (C) 2017 Google, Inc. -Written by Simon Glass <sjg@chromium.org> -""" - -import os -import sys - -from setuptools import setup, Extension -from setuptools.command.build_py import build_py as _build_py - - -def scan_for_info(srcdir): - """Scan for the version and long_description fields - - Args: - srcdir (str): Source-directory path - - Returns: tuple - str: Full description (contents of README.md) - str: Version string - """ - with open(os.path.join(srcdir, "VERSION.txt"), "r", encoding='utf-8') as fh: - version = fh.readline().strip() - - with open(os.path.join(srcdir, "README.md"), "r", encoding='utf-8') as fh: - long_description = fh.read() - - return version, long_description - - -def get_top_builddir(srcdir): - """Figure out the top-level directory containing the source code - - Args: - srcdir (str): Source-directory path - - Returns: - str: Directory to build in - """ - if '--top-builddir' in sys.argv: - index = sys.argv.index('--top-builddir') - sys.argv.pop(index) - return sys.argv.pop(index) - return srcdir - - -class BuildPy(_build_py): - """Small class to run the build_ext command""" - def run(self): - self.run_command("build_ext") - return super().run() - - -srcdir = os.path.dirname(__file__) -version, long_description = scan_for_info(srcdir) - -libfdt_module = Extension( - '_libfdt', - sources=[os.path.join(srcdir, 'pylibfdt/libfdt.i')], - define_macros=[('PY_SSIZE_T_CLEAN', None)], - include_dirs=[os.path.join(srcdir, 'libfdt')], - libraries=['fdt'], - library_dirs=[os.path.join(get_top_builddir(srcdir), 'libfdt')], - swig_opts=['-I' + os.path.join(srcdir, 'libfdt')], -) - - -setup( - name='libfdt', - version=version, - cmdclass = {'build_py' : BuildPy}, - author='Simon Glass', - author_email='sjg@chromium.org', - description='Python binding for libfdt', - ext_modules=[libfdt_module], - package_dir={'': os.path.join(srcdir, 'pylibfdt')}, - py_modules=['libfdt'], - python_requires=">=3.8", - - long_description=long_description, - long_description_content_type="text/plain", - url="https://git.kernel.org/pub/scm/utils/dtc/dtc.git", - license="BSD", - license_files=["GPL", "BSD-2-Clause"], - - classifiers=[ - "Programming Language :: Python :: 3", - "License :: OSI Approved :: BSD License", - "License :: OSI Approved :: GNU General Public License v2 or later (GPLv2+)", - "Operating System :: OS Independent", - ], -) -- 2.48.1 ^ permalink raw reply related [flat|nested] 20+ messages in thread
* Re: [PATCH] meson: port python bindings to build natively via meson and meson-python 2025-03-17 0:40 [PATCH] meson: port python bindings to build natively via meson and meson-python Eli Schwartz @ 2025-03-18 14:15 ` Rob Herring 2025-03-18 14:36 ` Eli Schwartz 2025-03-19 5:55 ` David Gibson 1 sibling, 1 reply; 20+ messages in thread From: Rob Herring @ 2025-03-18 14:15 UTC (permalink / raw) To: Eli Schwartz; +Cc: devicetree-compiler On Sun, Mar 16, 2025 at 7:42 PM Eli Schwartz <eschwartz@gentoo.org> wrote: > > We get full build parallelism and fewer confusing ancient distutils > paths. The python wheels build fully standalone, including linking > libfdt as a static library. > > For convenience, when running pip install a meson option is passed that g > prevents building tools or installing headers/pkgconfig files. > meson-python would otherwise include them in the wheel itself, in case > they are needed, but this is essentially a bit useless so don't bother. This is great as building a sdist that can be uploaded to pypi works. I've been maintaining a separate repo solely for that purpose. > > Signed-off-by: Eli Schwartz <eschwartz@gentoo.org> > --- > MANIFEST.in | 12 ------ > libfdt/meson.build | 32 ++++++++------- > meson.build | 3 +- > meson_options.txt | 2 + > pylibfdt/meson.build | 28 ++++++++----- > pyproject.toml | 25 ++++++++++++ > setup.py | 97 -------------------------------------------- Isn't removing this going to break make based builds as that calls setup.py directly? Personally, I think that's fine because I think python things should be built "the Python way", rather than trying to wrap them in make or meson. David didn't agree though. I think the only somewhat sane path is making the make support purely a wrapper to call meson so we're not maintaining 2 parallel build systems. > 7 files changed, 64 insertions(+), 135 deletions(-) > delete mode 100644 MANIFEST.in > create mode 100644 pyproject.toml > delete mode 100755 setup.py > > diff --git a/MANIFEST.in b/MANIFEST.in > deleted file mode 100644 > index 904d124..0000000 > --- a/MANIFEST.in > +++ /dev/null > @@ -1,12 +0,0 @@ > -# SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) > - > -global-exclude * > -include README.md > -include GPL > -include BSD-2-Clause > -include setup.py > -include pylibfdt/libfdt.i > -include libfdt/libfdt.h > -include libfdt/fdt.h > -include libfdt/libfdt_env.h > -include VERSION.txt > diff --git a/libfdt/meson.build b/libfdt/meson.build > index c2f4bd6..9c6ef54 100644 > --- a/libfdt/meson.build > +++ b/libfdt/meson.build > @@ -31,7 +31,7 @@ libfdt = library( > version: meson.project_version(), > link_args: link_args, > link_depends: 'version.lds', > - install: true, > + install: get_option('default_library') != 'static' or not wheel_only, > ) > > libfdt_inc = include_directories('.') > @@ -41,20 +41,22 @@ libfdt_dep = declare_dependency( > link_with: libfdt, > ) > > -install_headers( > - files( > - 'fdt.h', > - 'libfdt.h', > - 'libfdt_env.h', > +if not wheel_only > + install_headers( > + files( > + 'fdt.h', > + 'libfdt.h', > + 'libfdt_env.h', > + ) > ) > -) > > -pkgconfig = import('pkgconfig') > + pkgconfig = import('pkgconfig') > > -pkgconfig.generate( > - libraries: libfdt, > - version: meson.project_version(), > - filebase: 'libfdt', > - name: 'libfdt', > - description: 'Flat Device Tree manipulation', > -) > + pkgconfig.generate( > + libraries: libfdt, > + version: meson.project_version(), > + filebase: 'libfdt', > + name: 'libfdt', > + description: 'Flat Device Tree manipulation', > + ) > +endif > diff --git a/meson.build b/meson.build > index 3026f88..ed4a39d 100644 > --- a/meson.build > +++ b/meson.build > @@ -43,6 +43,7 @@ py = import('python') > py = py.find_installation(required: get_option('python')) > swig = find_program('swig', required: get_option('python')) > pylibfdt_enabled = not meson.is_cross_build() and py.found() and swig.found() ? true : false > +wheel_only = get_option('wheel-only') > > version_gen_h = vcs_tag( > command: ['git', 'describe', '--dirty=+'], > @@ -59,7 +60,7 @@ util_dep = declare_dependency( > dependencies: libfdt_dep > ) > > -if get_option('tools') > +if get_option('tools') and not wheel_only > flex = find_program('flex', required: true) > bison = find_program('bison', required: true) > > diff --git a/meson_options.txt b/meson_options.txt > index 62b31b3..a866b17 100644 > --- a/meson_options.txt > +++ b/meson_options.txt > @@ -10,3 +10,5 @@ option('python', type: 'feature', value: 'auto', > description: 'Build pylibfdt Python library') > option('tests', type: 'boolean', value: true, > description: 'Build tests') > +option('wheel-only', type: 'boolean', value: false, > + description: 'building from meson-python') > diff --git a/pylibfdt/meson.build b/pylibfdt/meson.build > index 6157f8d..b13d802 100644 > --- a/pylibfdt/meson.build > +++ b/pylibfdt/meson.build > @@ -1,13 +1,21 @@ > -setup_py = find_program('../setup.py') > -setup_py = [setup_py, '--quiet', '--top-builddir', meson.project_build_root()] > - > -pylibfdt = custom_target( > - 'pylibfdt', > +libfdt_c = custom_target( > + 'swig', > input: 'libfdt.i', > - depends: libfdt, > - output: '_libfdt.so', > - command: [setup_py, 'build_ext'], > - build_by_default: true, > + output: ['libfdt.c', 'libfdt.py'], > + install: true, > + install_dir: [false, py.get_install_dir(pure: false)], > + command: [swig, '-python', '-I'+meson.current_source_dir() / '../libfdt', '-o', '@OUTPUT0@', '@INPUT@'] > ) > > -meson.add_install_script(setup_py, 'install', '--prefix=' + get_option('prefix'), '--root=$DESTDIR') > +nowarn_gen = cc.get_supported_arguments( > + '-Wno-cast-qual', > + '-Wno-missing-prototypes', > + '-Wno-redundant-decls', > +) > +pylibfdt = py.extension_module( > + '_libfdt', > + libfdt_c, > + c_args: ['-DPY_SSIZE_T_CLEAN'] + nowarn_gen, > + dependencies: [libfdt_dep, py.dependency()], > + install: true, > +) > diff --git a/pyproject.toml b/pyproject.toml > new file mode 100644 > index 0000000..0929bd0 > --- /dev/null > +++ b/pyproject.toml > @@ -0,0 +1,25 @@ > +[build-system] > +build-backend = 'mesonpy' > +requires = ['meson-python'] > + > +[project] > +name = 'libfdt' > +authors = [ > + {name = 'Simon Glass', email = 'sjg@chromium.org'}, > +] > +classifiers = [ > + 'Programming Language :: Python :: 3', > + 'License :: OSI Approved :: BSD License', > + 'License :: OSI Approved :: GNU General Public License v2 or later (GPLv2+)', > + 'Operating System :: OS Independent', > +] > +description = 'Pthon binding for libfdt' typo ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH] meson: port python bindings to build natively via meson and meson-python 2025-03-18 14:15 ` Rob Herring @ 2025-03-18 14:36 ` Eli Schwartz 2025-03-18 17:02 ` Rob Herring 0 siblings, 1 reply; 20+ messages in thread From: Eli Schwartz @ 2025-03-18 14:36 UTC (permalink / raw) To: Rob Herring; +Cc: devicetree-compiler [-- Attachment #1.1: Type: text/plain, Size: 2369 bytes --] On 3/18/25 10:15 AM, Rob Herring wrote: > On Sun, Mar 16, 2025 at 7:42 PM Eli Schwartz <eschwartz@gentoo.org> wrote: >> >> We get full build parallelism and fewer confusing ancient distutils >> paths. The python wheels build fully standalone, including linking >> libfdt as a static library. >> >> For convenience, when running pip install a meson option is passed that g >> prevents building tools or installing headers/pkgconfig files. >> meson-python would otherwise include them in the wheel itself, in case >> they are needed, but this is essentially a bit useless so don't bother. > > This is great as building a sdist that can be uploaded to pypi works. > I've been maintaining a separate repo solely for that purpose. Interestingly, the one you uploaded to PyPI seems to be called something different from the name in setup.py and which I reused for pyproject.toml :) >> Signed-off-by: Eli Schwartz <eschwartz@gentoo.org> >> --- >> MANIFEST.in | 12 ------ >> libfdt/meson.build | 32 ++++++++------- >> meson.build | 3 +- >> meson_options.txt | 2 + >> pylibfdt/meson.build | 28 ++++++++----- >> pyproject.toml | 25 ++++++++++++ >> setup.py | 97 -------------------------------------------- > > Isn't removing this going to break make based builds as that calls > setup.py directly? Personally, I think that's fine because I think > python things should be built "the Python way", rather than trying to > wrap them in make or meson. David didn't agree though. I think the > only somewhat sane path is making the make support purely a wrapper to > call meson so we're not maintaining 2 parallel build systems. Ah yes, that's true. Meson *is* "the python way", for what it's worth, as it's a genuine python build system, no wrapper :) but I do think it's not worth supporting make as a route for the python bindings since Make can't actually build the python code at all. Also, if you're interested in python bindings you can afford to have python installed, and consequently, to invoke a build system (meson) written in python. I have no strong opinions about whether to maintain Makefile rules for building pure C code. I'm not really sure that people building python bindings will need a Make rule that just runs meson... -- Eli Schwartz [-- Attachment #2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 236 bytes --] ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH] meson: port python bindings to build natively via meson and meson-python 2025-03-18 14:36 ` Eli Schwartz @ 2025-03-18 17:02 ` Rob Herring 2025-03-19 6:51 ` Eli Schwartz 0 siblings, 1 reply; 20+ messages in thread From: Rob Herring @ 2025-03-18 17:02 UTC (permalink / raw) To: Eli Schwartz; +Cc: devicetree-compiler On Tue, Mar 18, 2025 at 9:37 AM Eli Schwartz <eschwartz@gentoo.org> wrote: > > On 3/18/25 10:15 AM, Rob Herring wrote: > > On Sun, Mar 16, 2025 at 7:42 PM Eli Schwartz <eschwartz@gentoo.org> wrote: > >> > >> We get full build parallelism and fewer confusing ancient distutils > >> paths. The python wheels build fully standalone, including linking > >> libfdt as a static library. > >> > >> For convenience, when running pip install a meson option is passed that g > >> prevents building tools or installing headers/pkgconfig files. > >> meson-python would otherwise include them in the wheel itself, in case > >> they are needed, but this is essentially a bit useless so don't bother. > > > > This is great as building a sdist that can be uploaded to pypi works. > > I've been maintaining a separate repo solely for that purpose. > > > Interestingly, the one you uploaded to PyPI seems to be called something > different from the name in setup.py and which I reused for pyproject.toml :) At the time I added it, there was a name collision with just "libfdt" which was something else, so I went with "pylibfdt". Now I don't see the libfdt one... FWIW, this is used to build the pypi package: https://github.com/devicetree-org/pylibfdt > >> Signed-off-by: Eli Schwartz <eschwartz@gentoo.org> > >> --- > >> MANIFEST.in | 12 ------ > >> libfdt/meson.build | 32 ++++++++------- > >> meson.build | 3 +- > >> meson_options.txt | 2 + > >> pylibfdt/meson.build | 28 ++++++++----- > >> pyproject.toml | 25 ++++++++++++ > >> setup.py | 97 -------------------------------------------- > > > > Isn't removing this going to break make based builds as that calls > > setup.py directly? Personally, I think that's fine because I think > > python things should be built "the Python way", rather than trying to > > wrap them in make or meson. David didn't agree though. I think the > > only somewhat sane path is making the make support purely a wrapper to > > call meson so we're not maintaining 2 parallel build systems. > > > Ah yes, that's true. > > Meson *is* "the python way", for what it's worth, as it's a genuine As a backend, yes it seems so, but I meant as a front-end where users run pip (or historically setup.py) rather than running ninja to run pip or setup.py. But looks like with this patch meson works as both the front-end and back-end. All news to me really, as pretty much nothing I've read on how to create and/or install python projects mentions meson, but it's certainly a moving target with setup.py, setup.cfg, pyproject.toml... > python build system, no wrapper :) but I do think it's not worth > supporting make as a route for the python bindings since Make can't > actually build the python code at all. Also, if you're interested in > python bindings you can afford to have python installed, and > consequently, to invoke a build system (meson) written in python. I don't think anyone is arguing that we need to keep the make build because the host doesn't have python. > I have no strong opinions about whether to maintain Makefile rules for > building pure C code. > > I'm not really sure that people building python bindings will need a > Make rule that just runs meson... I agree, but not my call. If that is all make is, then it's not a big deal to support. The problem is meson build is missing some features that make build supports, and no one has cared enough to address that so the make build can be dropped (to be just a wrapper of meson/ninja commands). Rob ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH] meson: port python bindings to build natively via meson and meson-python 2025-03-18 17:02 ` Rob Herring @ 2025-03-19 6:51 ` Eli Schwartz 0 siblings, 0 replies; 20+ messages in thread From: Eli Schwartz @ 2025-03-19 6:51 UTC (permalink / raw) To: Rob Herring; +Cc: devicetree-compiler [-- Attachment #1.1: Type: text/plain, Size: 3910 bytes --] On 3/18/25 1:02 PM, Rob Herring wrote: >> Meson *is* "the python way", for what it's worth, as it's a genuine > > As a backend, yes it seems so, but I meant as a front-end where users > run pip (or historically setup.py) rather than running ninja to run > pip or setup.py. But looks like with this patch meson works as both > the front-end and back-end. All news to me really, as pretty much > nothing I've read on how to create and/or install python projects > mentions meson, but it's certainly a moving target with setup.py, > setup.cfg, pyproject.toml... It is a bit confusing, but I think that's mostly a PR thing. For a bit of context here: Way back in the old day, setup.py was a second-stage cross platform "basically a Makefile" for cpython itself. The cpython standard library bootstrapped itself far enough to run a script called setup.py which built the rest of the standard library C modules, in part because writing this logic in python meant they didn't have to do it twice, once in a unix makefile and once in a Windows VS solution file. Naturally, shipping "basically a Makefile" in the standard library so you could build the standard library, was an attractive idea to others who wanted to build third-party python modules. Free build system! Runs on Windows without GNU Make! So people used it, and the PyPI ecosystem grew up around it, and setuptools was created to add some extra commands for `setup.py`, especially since not all functionality was needed by the standard library but was needed by third-party modules. Along the way, setup.cfg was invented. It's an ini file that you can use instead of passing most arguments to setup() because it's easier to configure metadata arguments via a config file rather than a python program. "declarative config" is the big appeal. At a certain point they also decided that ini files were too 2010s and wanted to shift to the hot new thing, TOML. (Tom's non-obvious maximalist language) Around the same time, people were feeling a bit let down by this glorious hack of unintended functionality (a stdlib portable Makefile retrofitted as a packaging standard) and especially setuptools was relatively very slow if all you had was pure *.py scripts, so they invented some alternative wheel builders (flit and poetry) and eventually decided to make a formal spec that would allow "pip install" to stop assuming everything is a setup.py Basically, they tried to reinvent linux distro build recipes I guess? So, pyproject.toml fulfills two roles: - it has the metadata-only parts of setup.py, all declarative - it tells pip what the python module contains a "build_wheel" function that knows how to build this particular package For us, that latter one is meson-python. It's a tiny python script that knows how to run the "meson" program, invoke ninja as needed, and tar up the results in a wheel file. All the real work aside for packaging is done by meson. Setuptools, naturally, provides its own "build_wheel" function (and you will no doubt be shocked to learn it executes `python3 setup.py bdist_wheel`). The moving target was years ago. These days the confusion is all about everyone inventing their own "build_wheel" functions now that they are allowed to. Most of them do exactly the same thing as each other, but rewritten from scratch with slightly different spelling (or in some cases their explanation is that they needed to create a new fork because they "need to be able to control the quality of the error messages") rather than rely on existing, proven tools such as meson, autotools, or cmake. It is what it is. For us, meson-python is only just enough of a thin wrapper to convert the results of "meson install" into a wheel file, which is simply format shifting. >> python build system, no wrapper :) -- Eli Schwartz [-- Attachment #2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 236 bytes --] ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH] meson: port python bindings to build natively via meson and meson-python 2025-03-17 0:40 [PATCH] meson: port python bindings to build natively via meson and meson-python Eli Schwartz 2025-03-18 14:15 ` Rob Herring @ 2025-03-19 5:55 ` David Gibson 2025-03-19 6:30 ` Eli Schwartz 1 sibling, 1 reply; 20+ messages in thread From: David Gibson @ 2025-03-19 5:55 UTC (permalink / raw) To: Eli Schwartz; +Cc: devicetree-compiler [-- Attachment #1: Type: text/plain, Size: 10361 bytes --] I find the setuptools / distutils stuff immensely confusing, so I really like this idea. However, there are a few issues in this draft. On Sun, Mar 16, 2025 at 08:40:56PM -0400, Eli Schwartz wrote: > We get full build parallelism and fewer confusing ancient distutils > paths. The python wheels build fully standalone, including linking > libfdt as a static library. First, this description assumes that you're at least broadly familiar with the distinction between distutils and meson-python. As it happens, I am, but the commit message is for posterity, so it would really help to give a bit more background here. > For convenience, when running pip install a meson option is passed that > prevents building tools or installing headers/pkgconfig files. > meson-python would otherwise include them in the wheel itself, in case > they are needed, but this is essentially a bit useless so don't bother. > > Signed-off-by: Eli Schwartz <eschwartz@gentoo.org> > --- > MANIFEST.in | 12 ------ > libfdt/meson.build | 32 ++++++++------- > meson.build | 3 +- > meson_options.txt | 2 + > pylibfdt/meson.build | 28 ++++++++----- > pyproject.toml | 25 ++++++++++++ > setup.py | 97 -------------------------------------------- > 7 files changed, 64 insertions(+), 135 deletions(-) > delete mode 100644 MANIFEST.in > create mode 100644 pyproject.toml > delete mode 100755 setup.py > > diff --git a/MANIFEST.in b/MANIFEST.in > deleted file mode 100644 > index 904d124..0000000 > --- a/MANIFEST.in > +++ /dev/null > @@ -1,12 +0,0 @@ > -# SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) > - > -global-exclude * > -include README.md > -include GPL > -include BSD-2-Clause > -include setup.py > -include pylibfdt/libfdt.i > -include libfdt/libfdt.h > -include libfdt/fdt.h > -include libfdt/libfdt_env.h > -include VERSION.txt We can't just delete the MANIFEST.in and setup.py, for now, because they're still needed for the Makefile build. I'm certainly considering dropping support for make, but we're not there yet. > diff --git a/libfdt/meson.build b/libfdt/meson.build > index c2f4bd6..9c6ef54 100644 > --- a/libfdt/meson.build > +++ b/libfdt/meson.build > @@ -31,7 +31,7 @@ libfdt = library( > version: meson.project_version(), > link_args: link_args, > link_depends: 'version.lds', > - install: true, > + install: get_option('default_library') != 'static' or not wheel_only, The first clause doesn't quite make sense to me. Why would we not install a static library? > ) > > libfdt_inc = include_directories('.') > @@ -41,20 +41,22 @@ libfdt_dep = declare_dependency( > link_with: libfdt, > ) > > -install_headers( > - files( > - 'fdt.h', > - 'libfdt.h', > - 'libfdt_env.h', > +if not wheel_only > + install_headers( > + files( > + 'fdt.h', > + 'libfdt.h', > + 'libfdt_env.h', > + ) > ) > -) > > -pkgconfig = import('pkgconfig') > + pkgconfig = import('pkgconfig') > > -pkgconfig.generate( > - libraries: libfdt, > - version: meson.project_version(), > - filebase: 'libfdt', > - name: 'libfdt', > - description: 'Flat Device Tree manipulation', > -) > + pkgconfig.generate( > + libraries: libfdt, > + version: meson.project_version(), > + filebase: 'libfdt', > + name: 'libfdt', > + description: 'Flat Device Tree manipulation', > + ) > +endif > diff --git a/meson.build b/meson.build > index 3026f88..ed4a39d 100644 > --- a/meson.build > +++ b/meson.build > @@ -43,6 +43,7 @@ py = import('python') > py = py.find_installation(required: get_option('python')) > swig = find_program('swig', required: get_option('python')) > pylibfdt_enabled = not meson.is_cross_build() and py.found() and swig.found() ? true : false > +wheel_only = get_option('wheel-only') > > version_gen_h = vcs_tag( > command: ['git', 'describe', '--dirty=+'], > @@ -59,7 +60,7 @@ util_dep = declare_dependency( > dependencies: libfdt_dep > ) > > -if get_option('tools') > +if get_option('tools') and not wheel_only > flex = find_program('flex', required: true) > bison = find_program('bison', required: true) > > diff --git a/meson_options.txt b/meson_options.txt > index 62b31b3..a866b17 100644 > --- a/meson_options.txt > +++ b/meson_options.txt > @@ -10,3 +10,5 @@ option('python', type: 'feature', value: 'auto', > description: 'Build pylibfdt Python library') > option('tests', type: 'boolean', value: true, > description: 'Build tests') > +option('wheel-only', type: 'boolean', value: false, > + description: 'building from meson-python') > diff --git a/pylibfdt/meson.build b/pylibfdt/meson.build > index 6157f8d..b13d802 100644 > --- a/pylibfdt/meson.build > +++ b/pylibfdt/meson.build > @@ -1,13 +1,21 @@ > -setup_py = find_program('../setup.py') > -setup_py = [setup_py, '--quiet', '--top-builddir', meson.project_build_root()] > - > -pylibfdt = custom_target( > - 'pylibfdt', > +libfdt_c = custom_target( > + 'swig', > input: 'libfdt.i', > - depends: libfdt, > - output: '_libfdt.so', > - command: [setup_py, 'build_ext'], > - build_by_default: true, > + output: ['libfdt.c', 'libfdt.py'], > + install: true, > + install_dir: [false, py.get_install_dir(pure: false)], > + command: [swig, '-python', '-I'+meson.current_source_dir() / '../libfdt', '-o', '@OUTPUT0@', '@INPUT@'] > ) > > -meson.add_install_script(setup_py, 'install', '--prefix=' + get_option('prefix'), '--root=$DESTDIR') > +nowarn_gen = cc.get_supported_arguments( > + '-Wno-cast-qual', > + '-Wno-missing-prototypes', > + '-Wno-redundant-decls', > +) > +pylibfdt = py.extension_module( > + '_libfdt', > + libfdt_c, > + c_args: ['-DPY_SSIZE_T_CLEAN'] + nowarn_gen, > + dependencies: [libfdt_dep, py.dependency()], > + install: true, > +) > diff --git a/pyproject.toml b/pyproject.toml > new file mode 100644 > index 0000000..0929bd0 > --- /dev/null > +++ b/pyproject.toml > @@ -0,0 +1,25 @@ > +[build-system] > +build-backend = 'mesonpy' > +requires = ['meson-python'] > + > +[project] > +name = 'libfdt' > +authors = [ > + {name = 'Simon Glass', email = 'sjg@chromium.org'}, > +] > +classifiers = [ > + 'Programming Language :: Python :: 3', > + 'License :: OSI Approved :: BSD License', > + 'License :: OSI Approved :: GNU General Public License v2 or later (GPLv2+)', > + 'Operating System :: OS Independent', > +] > +description = 'Pthon binding for libfdt' > +readme = 'README.md' > +requires-python = '>=3.8' > +dynamic = ['version'] > + > +[project.urls] > +'homepage' = 'https://git.kernel.org/pub/scm/utils/dtc/dtc.git' > + > +[tool.meson-python.args] > +'setup' = ['-Ddefault_library=static', '-Dwheel-only=true'] Shouldn't the python library use the shared library, at least by default? > diff --git a/setup.py b/setup.py > deleted file mode 100755 > index 52844ce..0000000 > --- a/setup.py > +++ /dev/null > @@ -1,97 +0,0 @@ > -#!/usr/bin/env python3 > -# SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) > - > -""" > -setup.py file for SWIG libfdt > -Copyright (C) 2017 Google, Inc. > -Written by Simon Glass <sjg@chromium.org> > -""" > - > -import os > -import sys > - > -from setuptools import setup, Extension > -from setuptools.command.build_py import build_py as _build_py > - > - > -def scan_for_info(srcdir): > - """Scan for the version and long_description fields > - > - Args: > - srcdir (str): Source-directory path > - > - Returns: tuple > - str: Full description (contents of README.md) > - str: Version string > - """ > - with open(os.path.join(srcdir, "VERSION.txt"), "r", encoding='utf-8') as fh: > - version = fh.readline().strip() > - > - with open(os.path.join(srcdir, "README.md"), "r", encoding='utf-8') as fh: > - long_description = fh.read() > - > - return version, long_description > - > - > -def get_top_builddir(srcdir): > - """Figure out the top-level directory containing the source code > - > - Args: > - srcdir (str): Source-directory path > - > - Returns: > - str: Directory to build in > - """ > - if '--top-builddir' in sys.argv: > - index = sys.argv.index('--top-builddir') > - sys.argv.pop(index) > - return sys.argv.pop(index) > - return srcdir > - > - > -class BuildPy(_build_py): > - """Small class to run the build_ext command""" > - def run(self): > - self.run_command("build_ext") > - return super().run() > - > - > -srcdir = os.path.dirname(__file__) > -version, long_description = scan_for_info(srcdir) > - > -libfdt_module = Extension( > - '_libfdt', > - sources=[os.path.join(srcdir, 'pylibfdt/libfdt.i')], > - define_macros=[('PY_SSIZE_T_CLEAN', None)], > - include_dirs=[os.path.join(srcdir, 'libfdt')], > - libraries=['fdt'], > - library_dirs=[os.path.join(get_top_builddir(srcdir), 'libfdt')], > - swig_opts=['-I' + os.path.join(srcdir, 'libfdt')], > -) > - > - > -setup( > - name='libfdt', > - version=version, > - cmdclass = {'build_py' : BuildPy}, > - author='Simon Glass', > - author_email='sjg@chromium.org', > - description='Python binding for libfdt', > - ext_modules=[libfdt_module], > - package_dir={'': os.path.join(srcdir, 'pylibfdt')}, > - py_modules=['libfdt'], > - python_requires=">=3.8", > - > - long_description=long_description, > - long_description_content_type="text/plain", > - url="https://git.kernel.org/pub/scm/utils/dtc/dtc.git", > - license="BSD", > - license_files=["GPL", "BSD-2-Clause"], > - > - classifiers=[ > - "Programming Language :: Python :: 3", > - "License :: OSI Approved :: BSD License", > - "License :: OSI Approved :: GNU General Public License v2 or later (GPLv2+)", > - "Operating System :: OS Independent", > - ], > -) -- David Gibson (he or they) | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you, not the other way | around. http://www.ozlabs.org/~dgibson [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 833 bytes --] ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH] meson: port python bindings to build natively via meson and meson-python 2025-03-19 5:55 ` David Gibson @ 2025-03-19 6:30 ` Eli Schwartz 2025-04-25 7:56 ` David Gibson 0 siblings, 1 reply; 20+ messages in thread From: Eli Schwartz @ 2025-03-19 6:30 UTC (permalink / raw) To: David Gibson; +Cc: devicetree-compiler [-- Attachment #1.1: Type: text/plain, Size: 6367 bytes --] On 3/19/25 1:55 AM, David Gibson wrote: >> diff --git a/MANIFEST.in b/MANIFEST.in >> deleted file mode 100644 >> index 904d124..0000000 >> --- a/MANIFEST.in >> +++ /dev/null >> @@ -1,12 +0,0 @@ >> -# SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) >> - >> -global-exclude * >> -include README.md >> -include GPL >> -include BSD-2-Clause >> -include setup.py >> -include pylibfdt/libfdt.i >> -include libfdt/libfdt.h >> -include libfdt/fdt.h >> -include libfdt/libfdt_env.h >> -include VERSION.txt > > We can't just delete the MANIFEST.in and setup.py, for now, because > they're still needed for the Makefile build. I'm certainly > considering dropping support for make, but we're not there yet. If, as discussed in the previous emails, we drop support for *building python from Make* but don't drop Make for C, is that acceptable? >> diff --git a/libfdt/meson.build b/libfdt/meson.build >> index c2f4bd6..9c6ef54 100644 >> --- a/libfdt/meson.build >> +++ b/libfdt/meson.build >> @@ -31,7 +31,7 @@ libfdt = library( >> version: meson.project_version(), >> link_args: link_args, >> link_depends: 'version.lds', >> - install: true, >> + install: get_option('default_library') != 'static' or not wheel_only, > > The first clause doesn't quite make sense to me. Why would we not > install a static library? Read this the other way around. We *do* install, if either (or both) conditions are true: - we are building a non-static library, so we certainly need it at runtime (thus it has to be installed at runtime) - we are NOT building a special wheel-specific build, which is to say, we assume we need this installed if we aren't running from pip install i.e. the purpose of this is that we assume the end goal for python wheels is as I'm going to describe in the latter half of this email, and this specific conditional over here is just trying to detect "PyPI mode". >> +[tool.meson-python.args] >> +'setup' = ['-Ddefault_library=static', '-Dwheel-only=true'] > > Shouldn't the python library use the shared library, at least by > default? This isn't about building the python library. If I'm building the python library, I just use "meson setup" like normal, and it builds the full dtc stack, including tools, library, python bindings and all. meson-python is *specifically* about building a python wheel. Python wheels have two choices: - the shared library is copied into the wheel - don't use the shared library Without setting these options, a wheel uploaded to PyPI ends up looking like this: $ bsdtar -tf dist/libfdt-1.7.2-cp312-cp312-linux_x86_64.whl libfdt-1.7.2.dist-info/METADATA libfdt-1.7.2.dist-info/WHEEL .libfdt.mesonpy.libs/libfdt.so.1.7.2 .libfdt.mesonpy.libs/pkgconfig/libfdt.pc libfdt-1.7.2.data/scripts/convert-dtsv0 libfdt-1.7.2.data/scripts/dtc libfdt-1.7.2.data/scripts/fdtdump libfdt-1.7.2.data/scripts/fdtget libfdt-1.7.2.data/scripts/fdtput libfdt-1.7.2.data/scripts/fdtoverlay libfdt-1.7.2.data/scripts/dtdiff libfdt.py _libfdt.cpython-312-x86_64-linux-gnu.so libfdt-1.7.2.data/headers/fdt.h libfdt-1.7.2.data/headers/libfdt.h libfdt-1.7.2.data/headers/libfdt_env.h libfdt-1.7.2.dist-info/RECORD And, $ readelf -d _libfdt.cpython-312-x86_64-linux-gnu.so Library runpath: [$ORIGIN/.libfdt.mesonpy.libs] This is all necessary since pip install can't know that libfdt is already installed via a package manager (dpkg, rpm, portage, pacman, xbps, apk, etc), so it has to ship its own just in case. Building statically simplifies distribution as a PyPI wheel. If you really want to build bloated wheels, you can still do it: python -m build --wheel \ -Csetup-args=-Ddefault_library=static \ -Csetup-args=wheel-only=false By the way, the locations that the files get installed to when building via pip aren't great either. The *.data/headers/ gets installed to /usr/include/python3.12/libfdt/ and the library and pkg-config files end up in /usr/lib/python3.12/site-packages/.libfdt.mesonpy.libs/libfdt.so.1.7.2 /usr/lib/python3.12/site-packages/.libfdt.mesonpy.libs/pkgconfig/libfdt.pc The pkg-config file doesn't even get remapped, it still says -I/usr/include and -L/usr/lib64 If you install with pip install --user (default when not running with sudo), then you even end up with this: /home/eschwartz/.local/bin/convert-dtsv0 /home/eschwartz/.local/bin/dtc /home/eschwartz/.local/bin/dtdiff /home/eschwartz/.local/bin/fdtdump /home/eschwartz/.local/bin/fdtget /home/eschwartz/.local/bin/fdtoverlay /home/eschwartz/.local/bin/fdtput /home/eschwartz/.local/include/python3.12/libfdt/fdt.h /home/eschwartz/.local/include/python3.12/libfdt/libfdt.h /home/eschwartz/.local/include/python3.12/libfdt/libfdt_env.h /home/eschwartz/.local/lib/python3.12/site-packages/.libfdt.mesonpy.libs/libfdt.so.1.7.2 /home/eschwartz/.local/lib/python3.12/site-packages/.libfdt.mesonpy.libs/pkgconfig/libfdt.pc /home/eschwartz/.local/lib/python3.12/site-packages/_libfdt.cpython-312-x86_64-linux-gnu.so /home/eschwartz/.local/lib/python3.12/site-packages/libfdt.py So yeah, IMO all of this cruft is out of place for pypi.org / pip. Python packaging *cannot*, in any way shape or form be used outside of its closed-in silo. They literally forbid, via their standards body, the possibility of installing outside of the locations I described. The only way to install to arbitrary locations the way Make or Meson can, is to use what they describe as "the legacy install route" of running ``` python setup.py install ``` and then having the equivalent of Makefile `cp XXXX ${DESTDIR}${PREFIX}/bin` i.e. completely disrespecting the pip install approach. The point of distributing on PyPI is so that people can get a python-specific copy of the bindings easily, with a minimum of fuss, and nothing else. You can always get the complete set using a real build system and installing with "meson install" instead of pip, and usually using a distro package manager even. But people installing via pip install aren't necessarily interested in that. They just want to download a binary package which their python scripts depend on. -- Eli Schwartz [-- Attachment #2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 236 bytes --] ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH] meson: port python bindings to build natively via meson and meson-python 2025-03-19 6:30 ` Eli Schwartz @ 2025-04-25 7:56 ` David Gibson 2025-04-29 1:34 ` Eli Schwartz 0 siblings, 1 reply; 20+ messages in thread From: David Gibson @ 2025-04-25 7:56 UTC (permalink / raw) To: Eli Schwartz; +Cc: devicetree-compiler [-- Attachment #1: Type: text/plain, Size: 7964 bytes --] Sorry, I haven't replied to this for ages. I've had a lot of stuff going on, both at work and otherwise. On Wed, Mar 19, 2025 at 02:30:17AM -0400, Eli Schwartz wrote: > On 3/19/25 1:55 AM, David Gibson wrote: > > >> diff --git a/MANIFEST.in b/MANIFEST.in > >> deleted file mode 100644 > >> index 904d124..0000000 > >> --- a/MANIFEST.in > >> +++ /dev/null > >> @@ -1,12 +0,0 @@ > >> -# SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) > >> - > >> -global-exclude * > >> -include README.md > >> -include GPL > >> -include BSD-2-Clause > >> -include setup.py > >> -include pylibfdt/libfdt.i > >> -include libfdt/libfdt.h > >> -include libfdt/fdt.h > >> -include libfdt/libfdt_env.h > >> -include VERSION.txt > > > > We can't just delete the MANIFEST.in and setup.py, for now, because > > they're still needed for the Makefile build. I'm certainly > > considering dropping support for make, but we're not there yet. > > If, as discussed in the previous emails, we drop support for *building > python from Make* but don't drop Make for C, is that acceptable? I'm conflicted. I don't really like the idea of making make work for only some things, without just removing it completely, or at least having a concrete plan to do so. On the other hand, I'd really like to get rid of the confusing setuptools gunk. How about this: could you author a patch deprecating make, which prints a message saying so if you build with make (anything, not just the Python pieces). It should say that meson is preferred and give example meson commands to use instead. If we start with that, then I'd be ok making the Python build meson only, followed by the changes you're suggesting here. > >> diff --git a/libfdt/meson.build b/libfdt/meson.build > >> index c2f4bd6..9c6ef54 100644 > >> --- a/libfdt/meson.build > >> +++ b/libfdt/meson.build > >> @@ -31,7 +31,7 @@ libfdt = library( > >> version: meson.project_version(), > >> link_args: link_args, > >> link_depends: 'version.lds', > >> - install: true, > >> + install: get_option('default_library') != 'static' or not wheel_only, > > > > The first clause doesn't quite make sense to me. Why would we not > > install a static library? > > > Read this the other way around. > > We *do* install, if either (or both) conditions are true: > > - we are building a non-static library, so we certainly need it at > runtime (thus it has to be installed at runtime) > > - we are NOT building a special wheel-specific build, which is to say, > we assume we need this installed if we aren't running from pip install > > > i.e. the purpose of this is that we assume the end goal for python > wheels is as I'm going to describe in the latter half of this email, and > this specific conditional over here is just trying to detect "PyPI mode". > > > >> +[tool.meson-python.args] > >> +'setup' = ['-Ddefault_library=static', '-Dwheel-only=true'] > > > > Shouldn't the python library use the shared library, at least by > > default? > > > This isn't about building the python library. If I'm building the python > library, I just use "meson setup" like normal, and it builds the full > dtc stack, including tools, library, python bindings and all. > > meson-python is *specifically* about building a python wheel. Python > wheels have two choices: > > - the shared library is copied into the wheel > - don't use the shared library > > Without setting these options, a wheel uploaded to PyPI ends up looking > like this: > > $ bsdtar -tf dist/libfdt-1.7.2-cp312-cp312-linux_x86_64.whl > libfdt-1.7.2.dist-info/METADATA > libfdt-1.7.2.dist-info/WHEEL > .libfdt.mesonpy.libs/libfdt.so.1.7.2 > .libfdt.mesonpy.libs/pkgconfig/libfdt.pc > libfdt-1.7.2.data/scripts/convert-dtsv0 > libfdt-1.7.2.data/scripts/dtc > libfdt-1.7.2.data/scripts/fdtdump > libfdt-1.7.2.data/scripts/fdtget > libfdt-1.7.2.data/scripts/fdtput > libfdt-1.7.2.data/scripts/fdtoverlay > libfdt-1.7.2.data/scripts/dtdiff > libfdt.py > _libfdt.cpython-312-x86_64-linux-gnu.so > libfdt-1.7.2.data/headers/fdt.h > libfdt-1.7.2.data/headers/libfdt.h > libfdt-1.7.2.data/headers/libfdt_env.h > libfdt-1.7.2.dist-info/RECORD > > And, > > $ readelf -d _libfdt.cpython-312-x86_64-linux-gnu.so > > Library runpath: [$ORIGIN/.libfdt.mesonpy.libs] > > This is all necessary since pip install can't know that libfdt is > already installed via a package manager (dpkg, rpm, portage, pacman, > xbps, apk, etc), so it has to ship its own just in case. > > Building statically simplifies distribution as a PyPI wheel. Ah, thanks for the explanation. Thank makes sense. If you can word something sufficiently succinct, a comment for posterity explaining that reasoning would be nice. But if you can't find a way to explain that briefly, I won't insist. > If you really want to build bloated wheels, you can still do it: > > > python -m build --wheel \ > -Csetup-args=-Ddefault_library=static \ > -Csetup-args=wheel-only=false > > > > By the way, the locations that the files get installed to when building > via pip aren't great either. The *.data/headers/ gets installed to > > /usr/include/python3.12/libfdt/ > > and the library and pkg-config files end up in > > /usr/lib/python3.12/site-packages/.libfdt.mesonpy.libs/libfdt.so.1.7.2 > /usr/lib/python3.12/site-packages/.libfdt.mesonpy.libs/pkgconfig/libfdt.pc > > The pkg-config file doesn't even get remapped, it still says > -I/usr/include and -L/usr/lib64 > > If you install with pip install --user (default when not running with > sudo), then you even end up with this: > > > /home/eschwartz/.local/bin/convert-dtsv0 > /home/eschwartz/.local/bin/dtc > /home/eschwartz/.local/bin/dtdiff > /home/eschwartz/.local/bin/fdtdump > /home/eschwartz/.local/bin/fdtget > /home/eschwartz/.local/bin/fdtoverlay > /home/eschwartz/.local/bin/fdtput > /home/eschwartz/.local/include/python3.12/libfdt/fdt.h > /home/eschwartz/.local/include/python3.12/libfdt/libfdt.h > /home/eschwartz/.local/include/python3.12/libfdt/libfdt_env.h > > /home/eschwartz/.local/lib/python3.12/site-packages/.libfdt.mesonpy.libs/libfdt.so.1.7.2 > > /home/eschwartz/.local/lib/python3.12/site-packages/.libfdt.mesonpy.libs/pkgconfig/libfdt.pc > > /home/eschwartz/.local/lib/python3.12/site-packages/_libfdt.cpython-312-x86_64-linux-gnu.so > /home/eschwartz/.local/lib/python3.12/site-packages/libfdt.py > > > So yeah, IMO all of this cruft is out of place for pypi.org / pip. > > > Python packaging *cannot*, in any way shape or form be used outside of > its closed-in silo. They literally forbid, via their standards body, the > possibility of installing outside of the locations I described. The only > way to install to arbitrary locations the way Make or Meson can, is to > use what they describe as "the legacy install route" of running > > ``` > python setup.py install > ``` > > and then having the equivalent of Makefile > > `cp XXXX ${DESTDIR}${PREFIX}/bin` > > i.e. completely disrespecting the pip install approach. > > > The point of distributing on PyPI is so that people can get a > python-specific copy of the bindings easily, with a minimum of fuss, and > nothing else. You can always get the complete set using a real build > system and installing with "meson install" instead of pip, and usually > using a distro package manager even. But people installing via pip > install aren't necessarily interested in that. They just want to > download a binary package which their python scripts depend on. Ok, understood. -- David Gibson (he or they) | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you, not the other way | around. http://www.ozlabs.org/~dgibson [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 833 bytes --] ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH] meson: port python bindings to build natively via meson and meson-python 2025-04-25 7:56 ` David Gibson @ 2025-04-29 1:34 ` Eli Schwartz 2025-04-29 1:41 ` [PATCH v2 0/2] port python bindings to native Meson Eli Schwartz 0 siblings, 1 reply; 20+ messages in thread From: Eli Schwartz @ 2025-04-29 1:34 UTC (permalink / raw) To: David Gibson; +Cc: devicetree-compiler [-- Attachment #1.1: Type: text/plain, Size: 2461 bytes --] On 4/25/25 3:56 AM, David Gibson wrote: > Sorry, I haven't replied to this for ages. I've had a lot of stuff > going on, both at work and otherwise. No problem. I myself had low availability because your message came in at the tail end of my holidays. :) > On Wed, Mar 19, 2025 at 02:30:17AM -0400, Eli Schwartz wrote: >> On 3/19/25 1:55 AM, David Gibson wrote: >> >>>> diff --git a/MANIFEST.in b/MANIFEST.in >>>> deleted file mode 100644 >>>> index 904d124..0000000 >>>> --- a/MANIFEST.in >>>> +++ /dev/null >>>> @@ -1,12 +0,0 @@ >>>> -# SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) >>>> - >>>> -global-exclude * >>>> -include README.md >>>> -include GPL >>>> -include BSD-2-Clause >>>> -include setup.py >>>> -include pylibfdt/libfdt.i >>>> -include libfdt/libfdt.h >>>> -include libfdt/fdt.h >>>> -include libfdt/libfdt_env.h >>>> -include VERSION.txt >>> >>> We can't just delete the MANIFEST.in and setup.py, for now, because >>> they're still needed for the Makefile build. I'm certainly >>> considering dropping support for make, but we're not there yet. >> >> If, as discussed in the previous emails, we drop support for *building >> python from Make* but don't drop Make for C, is that acceptable? > > I'm conflicted. I don't really like the idea of making make work for > only some things, without just removing it completely, or at least > having a concrete plan to do so. On the other hand, I'd really like > to get rid of the confusing setuptools gunk. > > How about this: could you author a patch deprecating make, which > prints a message saying so if you build with make (anything, not just > the Python pieces). It should say that meson is preferred and give > example meson commands to use instead. > > If we start with that, then I'd be ok making the Python build meson > only, followed by the changes you're suggesting here. I can do this, yes. In order to avoid the situation where a phony target is used as a dependency of all targets, leading to one or the other of: - it is never "up to date", so every target depending on it is continually rebuilt - add "stamp files" which clutter up the source tree to record that a warning was issued I can use GNU Make's $(warning), which emits output as a side effect of executing the Makefile. Not perfectly ideal as it prints on every build, not just the first one, but... -- Eli Schwartz [-- Attachment #2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 236 bytes --] ^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH v2 0/2] port python bindings to native Meson 2025-04-29 1:34 ` Eli Schwartz @ 2025-04-29 1:41 ` Eli Schwartz 2025-04-29 1:41 ` [PATCH v2 1/2] Makefile: deprecate in favor of Meson Eli Schwartz 2025-04-29 1:41 ` [PATCH v2 2/2] meson: port python bindings to build natively via meson and meson-python Eli Schwartz 0 siblings, 2 replies; 20+ messages in thread From: Eli Schwartz @ 2025-04-29 1:41 UTC (permalink / raw) To: devicetree-compiler Eli Schwartz (2): Makefile: deprecate in favor of Meson meson: port python bindings to build natively via meson and meson-python MANIFEST.in | 12 ----- Makefile | 55 +++------------------ libfdt/meson.build | 32 +++++++------ meson.build | 3 +- meson_options.txt | 2 + pylibfdt/Makefile.pylibfdt | 30 ------------ pylibfdt/meson.build | 28 +++++++---- pyproject.toml | 33 +++++++++++++ setup.py | 97 -------------------------------------- 9 files changed, 79 insertions(+), 213 deletions(-) delete mode 100644 MANIFEST.in delete mode 100644 pylibfdt/Makefile.pylibfdt create mode 100644 pyproject.toml delete mode 100755 setup.py Range-diff against v1: -: ------- > 1: 142d7e4 Makefile: deprecate in favor of Meson 1: f23b5eb ! 2: 5d0590f meson: port python bindings to build natively via meson and meson-python @@ Commit message meson-python would otherwise include them in the wheel itself, in case they are needed, but this is essentially a bit useless so don't bother. + The old setuptools-based build is now redundant and goes away. + ## MANIFEST.in (deleted) ## @@ -# SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) @@ MANIFEST.in (deleted) -include libfdt/libfdt_env.h -include VERSION.txt - ## libfdt/meson.build ## -@@ libfdt/meson.build: else - endif + ## Makefile ## +@@ Makefile: BISON = bison + LEX = flex + SWIG = swig + PKG_CONFIG ?= pkg-config +-PYTHON ?= python3 + + INSTALL = install + INSTALL_PROGRAM = $(INSTALL) +@@ Makefile: INCLUDEDIR = $(PREFIX)/include + HOSTOS := $(shell uname -s | tr '[:upper:]' '[:lower:]' | \ + sed -e 's/\(cygwin\|msys\).*/\1/') + +-NO_PYTHON ?= 0 +- + NO_VALGRIND := $(shell $(PKG_CONFIG) --exists valgrind; echo $$?) + ifeq ($(NO_VALGRIND),1) + CPPFLAGS += -DNO_VALGRIND +@@ Makefile: SCRIPTS = dtdiff + + all: $(BIN) libfdt + +-# We need both Python and swig to build/install pylibfdt. +-# This builds the given make ${target} if those deps are found. +-check_python_deps = \ +- if $(PKG_CONFIG) --cflags $(PYTHON) >/dev/null 2>&1; then \ +- if which swig >/dev/null 2>&1; then \ +- can_build=yes; \ +- fi; \ +- fi; \ +- if [ "$${can_build}" = "yes" ]; then \ +- $(MAKE) $${target}; \ +- else \ +- echo "\#\# Skipping pylibfdt (install python dev and swig to build)"; \ +- fi ; +- +-.PHONY: maybe_pylibfdt +-maybe_pylibfdt: FORCE +- target=pylibfdt; $(check_python_deps) +- +-ifeq ($(NO_PYTHON),0) +-all: maybe_pylibfdt +-endif +- +- + ifneq ($(DEPTARGETS),) + ifneq ($(MAKECMDGOALS),libfdt) + -include $(DTC_OBJS:%.o=%.d) +@@ Makefile: install-includes: + + install: install-bin install-lib install-includes + +-.PHONY: maybe_install_pylibfdt +-maybe_install_pylibfdt: FORCE +- target=install_pylibfdt; $(check_python_deps) +- +-ifeq ($(NO_PYTHON),0) +-install: maybe_install_pylibfdt +-endif +- + $(VERSION_FILE): Makefile FORCE + $(call filechk,version) + +@@ Makefile: dist: + gzip -9 > ../dtc-$(dtc_version).tar.gz + - link_args += version_script --libfdt = both_libraries( -+libfdt = library( - 'fdt', sources, +-# +-# Rules for pylibfdt +-# +-PYLIBFDT_dir = pylibfdt +- +-include $(PYLIBFDT_dir)/Makefile.pylibfdt +- +-.PHONY: pylibfdt +-pylibfdt: $(PYLIBFDT_dir)/_libfdt.so +- + # + # Release signing and uploading + # This is for maintainer convenience, don't try this at home. +@@ Makefile: TESTS_BIN += fdtput + TESTS_BIN += fdtget + TESTS_BIN += fdtdump + TESTS_BIN += fdtoverlay +-ifeq ($(NO_PYTHON),0) +-TESTS_PYLIBFDT += maybe_pylibfdt +-endif + + ifneq ($(MAKECMDGOALS),libfdt) + include tests/Makefile.tests +@@ Makefile: endif + STD_CLEANFILES = *~ *.o *.$(SHAREDLIB_EXT) *.d *.a *.i *.s core a.out vgcore.* \ + *.tab.[ch] *.lex.c *.output + +-clean: libfdt_clean pylibfdt_clean tests_clean ++clean: libfdt_clean tests_clean + @$(VECHO) CLEAN + rm -f $(STD_CLEANFILES) + rm -f $(VERSION_FILE) + + ## libfdt/meson.build ## +@@ libfdt/meson.build: libfdt = library( version: meson.project_version(), link_args: link_args, link_depends: 'version.lds', @@ libfdt/meson.build: else + install: get_option('default_library') != 'static' or not wheel_only, ) - if static_build -- link_with = libfdt.get_static_lib() -+ link_with = libfdt - else -- link_with = libfdt.get_shared_lib() -+ link_with = libfdt - endif - libfdt_inc = include_directories('.') @@ libfdt/meson.build: libfdt_dep = declare_dependency( - link_with: link_with, + link_with: libfdt, ) -install_headers( @@ meson.build: util_dep = declare_dependency( ## meson_options.txt ## -@@ meson_options.txt: option('static-build', type: 'boolean', value: false, - description: 'Build static binaries') +@@ meson_options.txt: option('python', type: 'feature', value: 'auto', + description: 'Build pylibfdt Python library') option('tests', type: 'boolean', value: true, description: 'Build tests') +option('wheel-only', type: 'boolean', value: false, + description: 'building from meson-python') + ## pylibfdt/Makefile.pylibfdt (deleted) ## +@@ +-# SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) +-# Makefile.pylibfdt +-# +- +-PYLIBFDT_srcs = $(PYLIBFDT_dir)/libfdt.i +-PYMODULE = $(PYLIBFDT_dir)/_libfdt.so +-PYLIBFDT_CLEANFILES_L = libfdt_wrap.c libfdt.py *.pyc *.so +-PYLIBFDT_CLEANFILES = $(PYLIBFDT_CLEANFILES_L:%=$(PYLIBFDT_dir)/%) +-PYLIBFDT_CLEANDIRS_L = __pycache__ libfdt.egg-info +-PYLIBFDT_CLEANDIRS = build $(PYLIBFDT_CLEANDIRS_L:%=$(PYLIBFDT_dir)/%) +- +-SETUP = ./setup.py +- +-ifndef V +-SETUPFLAGS += --quiet +-endif +- +-$(PYMODULE): WARNINGS = # suppress warnings from generated code +-$(PYMODULE): $(PYLIBFDT_srcs) $(LIBFDT_archive) $(SETUP) +- @$(VECHO) PYMOD $@ +- CFLAGS="$(CFLAGS) -Wno-error" $(PYTHON) $(SETUP) $(SETUPFLAGS) build_ext +- +-install_pylibfdt: $(PYMODULE) +- @$(VECHO) INSTALL-PYLIB +- $(PYTHON) $(SETUP) $(SETUPFLAGS) install --prefix=$(PREFIX) +- +-pylibfdt_clean: +- @$(VECHO) CLEAN "(pylibfdt)" +- rm -f $(PYLIBFDT_CLEANFILES) +- rm -rf $(PYLIBFDT_CLEANDIRS) + ## pylibfdt/meson.build ## @@ -setup_py = find_program('../setup.py') @@ pyproject.toml (new) +[project.urls] +'homepage' = 'https://git.kernel.org/pub/scm/utils/dtc/dtc.git' + ++# These arguments are applied only when building a redistributable binary wheel ++# for uploading to PyPI. We don't want to install libraries (or headers / ++# pkgconfig files / executables) that clash with system C installs, so we ++# disable everything other than the python bindings themselves, and build the ++# python C-API extension using static linkage to avoid juggling "libdir" / ++# LD_LIBRARY_PATH / RPATH around. When building both the C library and the ++# python bindings for a distro, `meson setup` will still default to shared ++# libraries. +[tool.meson-python.args] -+'setup' = ['-Ddefault_library=static', '-Dwheel-only=true'] ++setup = ['-Ddefault_library=static', '-Dwheel-only=true'] ## setup.py (deleted) ## @@ -- 2.49.0 ^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH v2 1/2] Makefile: deprecate in favor of Meson 2025-04-29 1:41 ` [PATCH v2 0/2] port python bindings to native Meson Eli Schwartz @ 2025-04-29 1:41 ` Eli Schwartz 2025-04-30 14:56 ` David Gibson 2025-04-29 1:41 ` [PATCH v2 2/2] meson: port python bindings to build natively via meson and meson-python Eli Schwartz 1 sibling, 1 reply; 20+ messages in thread From: Eli Schwartz @ 2025-04-29 1:41 UTC (permalink / raw) To: devicetree-compiler Building the python bindings is complicated and not very practical to do in a Makefile. The setuptools invocations previously used are confusing and don't work very well compared to Meson. Having two build systems that do different things is also confusing though. Since Meson can do everything that Make can do, but the reverse is not true, we deprecate the latter and warn when you use it. GNU Make can emit a $(warning) on every Makefile run, which is a bit noisly but means we don't need to have every target depend on a PHONY target (preventing built targets from being seen as up to date). Signed-off-by: Eli Schwartz <eschwartz@gentoo.org> --- Makefile | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Makefile b/Makefile index a00123d..000dd85 100644 --- a/Makefile +++ b/Makefile @@ -3,6 +3,12 @@ # Device Tree Compiler # +$(warning WARNING: Building dtc using the Makefile is deprecated, in favor of using the Meson build system instead.) +$(warning ) +$(warning https://mesonbuild.com) +$(warning ) +$(warning Use `meson setup builddir/ && ninja -C builddir/` to build, or `meson configure` to see build options.) + # # Version information will be constructed in this order: # DTC_VERSION release version as MAJOR.MINOR.PATCH -- 2.49.0 ^ permalink raw reply related [flat|nested] 20+ messages in thread
* Re: [PATCH v2 1/2] Makefile: deprecate in favor of Meson 2025-04-29 1:41 ` [PATCH v2 1/2] Makefile: deprecate in favor of Meson Eli Schwartz @ 2025-04-30 14:56 ` David Gibson 2025-04-30 15:10 ` Eli Schwartz 0 siblings, 1 reply; 20+ messages in thread From: David Gibson @ 2025-04-30 14:56 UTC (permalink / raw) To: Eli Schwartz; +Cc: devicetree-compiler [-- Attachment #1: Type: text/plain, Size: 2126 bytes --] On Mon, Apr 28, 2025 at 09:41:42PM -0400, Eli Schwartz wrote: > Building the python bindings is complicated and not very practical to do > in a Makefile. The setuptools invocations previously used are confusing > and don't work very well compared to Meson. Having two build systems > that do different things is also confusing though. > > Since Meson can do everything that Make can do, but the reverse is not > true, we deprecate the latter and warn when you use it. > > GNU Make can emit a $(warning) on every Makefile run, which is a bit > noisly but means we don't need to have every target depend on a PHONY > target (preventing built targets from being seen as up to date). s/noisly/noisy/ I'm pretty ok with it being noisy. Some minor nits in wording noted below. > Signed-off-by: Eli Schwartz <eschwartz@gentoo.org> > --- > Makefile | 6 ++++++ > 1 file changed, 6 insertions(+) > > diff --git a/Makefile b/Makefile > index a00123d..000dd85 100644 > --- a/Makefile > +++ b/Makefile > @@ -3,6 +3,12 @@ > # Device Tree Compiler > # > > +$(warning WARNING: Building dtc using the Makefile is deprecated, in favor of using the Meson build system instead.) > +$(warning ) > +$(warning https://mesonbuild.com) For succinctness, I suggest: WARNING: Building dtc using make is deprecated in favour of using Meson (https://mesonbuild.com) Note that British/Australian spelling is preferred for this project, hence "favour". > +$(warning ) > +$(warning Use `meson setup builddir/ && ninja -C builddir/` to build, or `meson configure` to see build options.) I'd prefer to suggest "meson compile -C builddir" here, rather than directly invoking ninja, and I'd also like to list "meson test -C builddir" as the replacement for "make check". > + > # > # Version information will be constructed in this order: > # DTC_VERSION release version as MAJOR.MINOR.PATCH -- David Gibson (he or they) | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you, not the other way | around. http://www.ozlabs.org/~dgibson [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 833 bytes --] ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v2 1/2] Makefile: deprecate in favor of Meson 2025-04-30 14:56 ` David Gibson @ 2025-04-30 15:10 ` Eli Schwartz 2025-04-30 15:20 ` David Gibson 0 siblings, 1 reply; 20+ messages in thread From: Eli Schwartz @ 2025-04-30 15:10 UTC (permalink / raw) To: David Gibson; +Cc: devicetree-compiler [-- Attachment #1.1: Type: text/plain, Size: 1491 bytes --] On 4/30/25 10:56 AM, David Gibson wrote: >> +$(warning WARNING: Building dtc using the Makefile is deprecated, in favor of using the Meson build system instead.) >> +$(warning ) >> +$(warning https://mesonbuild.com) > > For succinctness, I suggest: > > WARNING: Building dtc using make is deprecated in favour of using Meson (https://mesonbuild.com) > > Note that British/Australian spelling is preferred for this project, hence "favour". Yup, sounds reasonable. :) >> +$(warning ) >> +$(warning Use `meson setup builddir/ && ninja -C builddir/` to build, or `meson configure` to see build options.) > > I'd prefer to suggest "meson compile -C builddir" here, rather than > directly invoking ninja, and I'd also like to list "meson test -C > builddir" as the replacement for "make check". As you wish, of course. But note that "meson compile" is a dispatching command that first checks whether the build has been setup using a non-default --backend option instead of the default ninja: - Microsoft msbuild - Apple xcode and then determines which of the three to run. So if you decide to run "meson compile -C builddir/" it will just in turn run, on your behalf, "ninja -C builddir/". It also has the side effect of, if your compiler is MSVC cl.exe, loading vcvarsall.bat before dispatching to ninja, as a workaround for https://github.com/ninja-build/ninja/issues/1610 None of that matters for dtc, I guess. :) -- Eli Schwartz [-- Attachment #2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 963 bytes --] ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v2 1/2] Makefile: deprecate in favor of Meson 2025-04-30 15:10 ` Eli Schwartz @ 2025-04-30 15:20 ` David Gibson 2025-04-30 15:25 ` [PATCH v3 0/2] port python bindings to native Meson Eli Schwartz 0 siblings, 1 reply; 20+ messages in thread From: David Gibson @ 2025-04-30 15:20 UTC (permalink / raw) To: Eli Schwartz; +Cc: devicetree-compiler [-- Attachment #1: Type: text/plain, Size: 2031 bytes --] On Wed, Apr 30, 2025 at 11:10:20AM -0400, Eli Schwartz wrote: > On 4/30/25 10:56 AM, David Gibson wrote: > >> +$(warning WARNING: Building dtc using the Makefile is deprecated, in favor of using the Meson build system instead.) > >> +$(warning ) > >> +$(warning https://mesonbuild.com) > > > > For succinctness, I suggest: > > > > WARNING: Building dtc using make is deprecated in favour of using Meson (https://mesonbuild.com) > > > > Note that British/Australian spelling is preferred for this project, hence "favour". > > > Yup, sounds reasonable. :) > > > >> +$(warning ) > >> +$(warning Use `meson setup builddir/ && ninja -C builddir/` to build, or `meson configure` to see build options.) > > > > I'd prefer to suggest "meson compile -C builddir" here, rather than > > directly invoking ninja, and I'd also like to list "meson test -C > > builddir" as the replacement for "make check". > > > As you wish, of course. But note that "meson compile" is a dispatching > command that first checks whether the build has been setup using a > non-default --backend option instead of the default ninja: > > - Microsoft msbuild > - Apple xcode > > and then determines which of the three to run. So if you decide to run > "meson compile -C builddir/" it will just in turn run, on your behalf, > "ninja -C builddir/". I'm aware. > It also has the side effect of, if your compiler is MSVC cl.exe, loading > vcvarsall.bat before dispatching to ninja, as a workaround for > > https://github.com/ninja-build/ninja/issues/1610 > > None of that matters for dtc, I guess. :) Well.. maybe. Since it's not tested, it probably doesn't work, but AFAIK there's no inherent reason dtc couldn't be built on MSVC or xcode. That's why I'd prefer to list the more broadly correct command. -- David Gibson (he or they) | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you, not the other way | around. http://www.ozlabs.org/~dgibson [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 833 bytes --] ^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH v3 0/2] port python bindings to native Meson 2025-04-30 15:20 ` David Gibson @ 2025-04-30 15:25 ` Eli Schwartz 2025-04-30 15:25 ` [PATCH v3 1/2] Makefile: deprecate in favor of Meson Eli Schwartz ` (2 more replies) 0 siblings, 3 replies; 20+ messages in thread From: Eli Schwartz @ 2025-04-30 15:25 UTC (permalink / raw) To: devicetree-compiler Eli Schwartz (2): Makefile: deprecate in favor of Meson meson: port python bindings to build natively via meson and meson-python MANIFEST.in | 12 ----- Makefile | 53 ++------------------- libfdt/meson.build | 32 +++++++------ meson.build | 3 +- meson_options.txt | 2 + pylibfdt/Makefile.pylibfdt | 30 ------------ pylibfdt/meson.build | 28 +++++++---- pyproject.toml | 33 +++++++++++++ setup.py | 97 -------------------------------------- 9 files changed, 77 insertions(+), 213 deletions(-) delete mode 100644 MANIFEST.in delete mode 100644 pylibfdt/Makefile.pylibfdt create mode 100644 pyproject.toml delete mode 100755 setup.py Range-diff against v2: 1: 142d7e4 ! 1: e5220b1 Makefile: deprecate in favor of Meson @@ Commit message true, we deprecate the latter and warn when you use it. GNU Make can emit a $(warning) on every Makefile run, which is a bit - noisly but means we don't need to have every target depend on a PHONY + noisy but means we don't need to have every target depend on a PHONY target (preventing built targets from being seen as up to date). ## Makefile ## @@ Makefile # Device Tree Compiler # -+$(warning WARNING: Building dtc using the Makefile is deprecated, in favor of using the Meson build system instead.) ++$(warning WARNING: Building dtc using make is deprecated, in favour of using Meson (https://mesonbuild.com)) +$(warning ) -+$(warning https://mesonbuild.com) -+$(warning ) -+$(warning Use `meson setup builddir/ && ninja -C builddir/` to build, or `meson configure` to see build options.) ++$(warning Use `meson setup builddir/ && meson compile -C builddir/` to build, `meson test -C builddir/` to test, or `meson configure` to see build options.) + # # Version information will be constructed in this order: 2: 5d0590f ! 2: 3490690 meson: port python bindings to build natively via meson and meson-python @@ pyproject.toml (new) + 'License :: OSI Approved :: GNU General Public License v2 or later (GPLv2+)', + 'Operating System :: OS Independent', +] -+description = 'Pthon binding for libfdt' ++description = 'Python binding for libfdt' +readme = 'README.md' +requires-python = '>=3.8' +dynamic = ['version'] -- 2.49.0 ^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH v3 1/2] Makefile: deprecate in favor of Meson 2025-04-30 15:25 ` [PATCH v3 0/2] port python bindings to native Meson Eli Schwartz @ 2025-04-30 15:25 ` Eli Schwartz 2025-04-30 15:25 ` [PATCH v3 2/2] meson: port python bindings to build natively via meson and meson-python Eli Schwartz 2025-05-01 12:33 ` [PATCH v3 0/2] port python bindings to native Meson David Gibson 2 siblings, 0 replies; 20+ messages in thread From: Eli Schwartz @ 2025-04-30 15:25 UTC (permalink / raw) To: devicetree-compiler Building the python bindings is complicated and not very practical to do in a Makefile. The setuptools invocations previously used are confusing and don't work very well compared to Meson. Having two build systems that do different things is also confusing though. Since Meson can do everything that Make can do, but the reverse is not true, we deprecate the latter and warn when you use it. GNU Make can emit a $(warning) on every Makefile run, which is a bit noisy but means we don't need to have every target depend on a PHONY target (preventing built targets from being seen as up to date). Signed-off-by: Eli Schwartz <eschwartz@gentoo.org> --- Makefile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Makefile b/Makefile index a00123d..6ab5f97 100644 --- a/Makefile +++ b/Makefile @@ -3,6 +3,10 @@ # Device Tree Compiler # +$(warning WARNING: Building dtc using make is deprecated, in favour of using Meson (https://mesonbuild.com)) +$(warning ) +$(warning Use `meson setup builddir/ && meson compile -C builddir/` to build, `meson test -C builddir/` to test, or `meson configure` to see build options.) + # # Version information will be constructed in this order: # DTC_VERSION release version as MAJOR.MINOR.PATCH -- 2.49.0 ^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v3 2/2] meson: port python bindings to build natively via meson and meson-python 2025-04-30 15:25 ` [PATCH v3 0/2] port python bindings to native Meson Eli Schwartz 2025-04-30 15:25 ` [PATCH v3 1/2] Makefile: deprecate in favor of Meson Eli Schwartz @ 2025-04-30 15:25 ` Eli Schwartz 2025-05-01 12:33 ` [PATCH v3 0/2] port python bindings to native Meson David Gibson 2 siblings, 0 replies; 20+ messages in thread From: Eli Schwartz @ 2025-04-30 15:25 UTC (permalink / raw) To: devicetree-compiler We get full build parallelism and fewer confusing ancient distutils paths. The python wheels build fully standalone, including linking libfdt as a static library. For convenience, when running pip install a meson option is passed that prevents building tools or installing headers/pkgconfig files. meson-python would otherwise include them in the wheel itself, in case they are needed, but this is essentially a bit useless so don't bother. The old setuptools-based build is now redundant and goes away. Signed-off-by: Eli Schwartz <eschwartz@gentoo.org> --- MANIFEST.in | 12 ----- Makefile | 49 +------------------ libfdt/meson.build | 32 +++++++------ meson.build | 3 +- meson_options.txt | 2 + pylibfdt/Makefile.pylibfdt | 30 ------------ pylibfdt/meson.build | 28 +++++++---- pyproject.toml | 33 +++++++++++++ setup.py | 97 -------------------------------------- 9 files changed, 73 insertions(+), 213 deletions(-) delete mode 100644 MANIFEST.in delete mode 100644 pylibfdt/Makefile.pylibfdt create mode 100644 pyproject.toml delete mode 100755 setup.py diff --git a/MANIFEST.in b/MANIFEST.in deleted file mode 100644 index 904d124..0000000 --- a/MANIFEST.in +++ /dev/null @@ -1,12 +0,0 @@ -# SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) - -global-exclude * -include README.md -include GPL -include BSD-2-Clause -include setup.py -include pylibfdt/libfdt.i -include libfdt/libfdt.h -include libfdt/fdt.h -include libfdt/libfdt_env.h -include VERSION.txt diff --git a/Makefile b/Makefile index 6ab5f97..b1815c3 100644 --- a/Makefile +++ b/Makefile @@ -31,7 +31,6 @@ BISON = bison LEX = flex SWIG = swig PKG_CONFIG ?= pkg-config -PYTHON ?= python3 INSTALL = install INSTALL_PROGRAM = $(INSTALL) @@ -47,8 +46,6 @@ INCLUDEDIR = $(PREFIX)/include HOSTOS := $(shell uname -s | tr '[:upper:]' '[:lower:]' | \ sed -e 's/\(cygwin\|msys\).*/\1/') -NO_PYTHON ?= 0 - NO_VALGRIND := $(shell $(PKG_CONFIG) --exists valgrind; echo $$?) ifeq ($(NO_VALGRIND),1) CPPFLAGS += -DNO_VALGRIND @@ -158,29 +155,6 @@ SCRIPTS = dtdiff all: $(BIN) libfdt -# We need both Python and swig to build/install pylibfdt. -# This builds the given make ${target} if those deps are found. -check_python_deps = \ - if $(PKG_CONFIG) --cflags $(PYTHON) >/dev/null 2>&1; then \ - if which swig >/dev/null 2>&1; then \ - can_build=yes; \ - fi; \ - fi; \ - if [ "$${can_build}" = "yes" ]; then \ - $(MAKE) $${target}; \ - else \ - echo "\#\# Skipping pylibfdt (install python dev and swig to build)"; \ - fi ; - -.PHONY: maybe_pylibfdt -maybe_pylibfdt: FORCE - target=pylibfdt; $(check_python_deps) - -ifeq ($(NO_PYTHON),0) -all: maybe_pylibfdt -endif - - ifneq ($(DEPTARGETS),) ifneq ($(MAKECMDGOALS),libfdt) -include $(DTC_OBJS:%.o=%.d) @@ -254,14 +228,6 @@ install-includes: install: install-bin install-lib install-includes -.PHONY: maybe_install_pylibfdt -maybe_install_pylibfdt: FORCE - target=install_pylibfdt; $(check_python_deps) - -ifeq ($(NO_PYTHON),0) -install: maybe_install_pylibfdt -endif - $(VERSION_FILE): Makefile FORCE $(call filechk,version) @@ -287,16 +253,6 @@ dist: gzip -9 > ../dtc-$(dtc_version).tar.gz -# -# Rules for pylibfdt -# -PYLIBFDT_dir = pylibfdt - -include $(PYLIBFDT_dir)/Makefile.pylibfdt - -.PHONY: pylibfdt -pylibfdt: $(PYLIBFDT_dir)/_libfdt.so - # # Release signing and uploading # This is for maintainer convenience, don't try this at home. @@ -330,9 +286,6 @@ TESTS_BIN += fdtput TESTS_BIN += fdtget TESTS_BIN += fdtdump TESTS_BIN += fdtoverlay -ifeq ($(NO_PYTHON),0) -TESTS_PYLIBFDT += maybe_pylibfdt -endif ifneq ($(MAKECMDGOALS),libfdt) include tests/Makefile.tests @@ -344,7 +297,7 @@ endif STD_CLEANFILES = *~ *.o *.$(SHAREDLIB_EXT) *.d *.a *.i *.s core a.out vgcore.* \ *.tab.[ch] *.lex.c *.output -clean: libfdt_clean pylibfdt_clean tests_clean +clean: libfdt_clean tests_clean @$(VECHO) CLEAN rm -f $(STD_CLEANFILES) rm -f $(VERSION_FILE) diff --git a/libfdt/meson.build b/libfdt/meson.build index c2f4bd6..9c6ef54 100644 --- a/libfdt/meson.build +++ b/libfdt/meson.build @@ -31,7 +31,7 @@ libfdt = library( version: meson.project_version(), link_args: link_args, link_depends: 'version.lds', - install: true, + install: get_option('default_library') != 'static' or not wheel_only, ) libfdt_inc = include_directories('.') @@ -41,20 +41,22 @@ libfdt_dep = declare_dependency( link_with: libfdt, ) -install_headers( - files( - 'fdt.h', - 'libfdt.h', - 'libfdt_env.h', +if not wheel_only + install_headers( + files( + 'fdt.h', + 'libfdt.h', + 'libfdt_env.h', + ) ) -) -pkgconfig = import('pkgconfig') + pkgconfig = import('pkgconfig') -pkgconfig.generate( - libraries: libfdt, - version: meson.project_version(), - filebase: 'libfdt', - name: 'libfdt', - description: 'Flat Device Tree manipulation', -) + pkgconfig.generate( + libraries: libfdt, + version: meson.project_version(), + filebase: 'libfdt', + name: 'libfdt', + description: 'Flat Device Tree manipulation', + ) +endif diff --git a/meson.build b/meson.build index 3026f88..ed4a39d 100644 --- a/meson.build +++ b/meson.build @@ -43,6 +43,7 @@ py = import('python') py = py.find_installation(required: get_option('python')) swig = find_program('swig', required: get_option('python')) pylibfdt_enabled = not meson.is_cross_build() and py.found() and swig.found() ? true : false +wheel_only = get_option('wheel-only') version_gen_h = vcs_tag( command: ['git', 'describe', '--dirty=+'], @@ -59,7 +60,7 @@ util_dep = declare_dependency( dependencies: libfdt_dep ) -if get_option('tools') +if get_option('tools') and not wheel_only flex = find_program('flex', required: true) bison = find_program('bison', required: true) diff --git a/meson_options.txt b/meson_options.txt index 62b31b3..a866b17 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -10,3 +10,5 @@ option('python', type: 'feature', value: 'auto', description: 'Build pylibfdt Python library') option('tests', type: 'boolean', value: true, description: 'Build tests') +option('wheel-only', type: 'boolean', value: false, + description: 'building from meson-python') diff --git a/pylibfdt/Makefile.pylibfdt b/pylibfdt/Makefile.pylibfdt deleted file mode 100644 index 647203f..0000000 --- a/pylibfdt/Makefile.pylibfdt +++ /dev/null @@ -1,30 +0,0 @@ -# SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) -# Makefile.pylibfdt -# - -PYLIBFDT_srcs = $(PYLIBFDT_dir)/libfdt.i -PYMODULE = $(PYLIBFDT_dir)/_libfdt.so -PYLIBFDT_CLEANFILES_L = libfdt_wrap.c libfdt.py *.pyc *.so -PYLIBFDT_CLEANFILES = $(PYLIBFDT_CLEANFILES_L:%=$(PYLIBFDT_dir)/%) -PYLIBFDT_CLEANDIRS_L = __pycache__ libfdt.egg-info -PYLIBFDT_CLEANDIRS = build $(PYLIBFDT_CLEANDIRS_L:%=$(PYLIBFDT_dir)/%) - -SETUP = ./setup.py - -ifndef V -SETUPFLAGS += --quiet -endif - -$(PYMODULE): WARNINGS = # suppress warnings from generated code -$(PYMODULE): $(PYLIBFDT_srcs) $(LIBFDT_archive) $(SETUP) - @$(VECHO) PYMOD $@ - CFLAGS="$(CFLAGS) -Wno-error" $(PYTHON) $(SETUP) $(SETUPFLAGS) build_ext - -install_pylibfdt: $(PYMODULE) - @$(VECHO) INSTALL-PYLIB - $(PYTHON) $(SETUP) $(SETUPFLAGS) install --prefix=$(PREFIX) - -pylibfdt_clean: - @$(VECHO) CLEAN "(pylibfdt)" - rm -f $(PYLIBFDT_CLEANFILES) - rm -rf $(PYLIBFDT_CLEANDIRS) diff --git a/pylibfdt/meson.build b/pylibfdt/meson.build index 6157f8d..b13d802 100644 --- a/pylibfdt/meson.build +++ b/pylibfdt/meson.build @@ -1,13 +1,21 @@ -setup_py = find_program('../setup.py') -setup_py = [setup_py, '--quiet', '--top-builddir', meson.project_build_root()] - -pylibfdt = custom_target( - 'pylibfdt', +libfdt_c = custom_target( + 'swig', input: 'libfdt.i', - depends: libfdt, - output: '_libfdt.so', - command: [setup_py, 'build_ext'], - build_by_default: true, + output: ['libfdt.c', 'libfdt.py'], + install: true, + install_dir: [false, py.get_install_dir(pure: false)], + command: [swig, '-python', '-I'+meson.current_source_dir() / '../libfdt', '-o', '@OUTPUT0@', '@INPUT@'] ) -meson.add_install_script(setup_py, 'install', '--prefix=' + get_option('prefix'), '--root=$DESTDIR') +nowarn_gen = cc.get_supported_arguments( + '-Wno-cast-qual', + '-Wno-missing-prototypes', + '-Wno-redundant-decls', +) +pylibfdt = py.extension_module( + '_libfdt', + libfdt_c, + c_args: ['-DPY_SSIZE_T_CLEAN'] + nowarn_gen, + dependencies: [libfdt_dep, py.dependency()], + install: true, +) diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..853d13e --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,33 @@ +[build-system] +build-backend = 'mesonpy' +requires = ['meson-python'] + +[project] +name = 'libfdt' +authors = [ + {name = 'Simon Glass', email = 'sjg@chromium.org'}, +] +classifiers = [ + 'Programming Language :: Python :: 3', + 'License :: OSI Approved :: BSD License', + 'License :: OSI Approved :: GNU General Public License v2 or later (GPLv2+)', + 'Operating System :: OS Independent', +] +description = 'Python binding for libfdt' +readme = 'README.md' +requires-python = '>=3.8' +dynamic = ['version'] + +[project.urls] +'homepage' = 'https://git.kernel.org/pub/scm/utils/dtc/dtc.git' + +# These arguments are applied only when building a redistributable binary wheel +# for uploading to PyPI. We don't want to install libraries (or headers / +# pkgconfig files / executables) that clash with system C installs, so we +# disable everything other than the python bindings themselves, and build the +# python C-API extension using static linkage to avoid juggling "libdir" / +# LD_LIBRARY_PATH / RPATH around. When building both the C library and the +# python bindings for a distro, `meson setup` will still default to shared +# libraries. +[tool.meson-python.args] +setup = ['-Ddefault_library=static', '-Dwheel-only=true'] diff --git a/setup.py b/setup.py deleted file mode 100755 index 52844ce..0000000 --- a/setup.py +++ /dev/null @@ -1,97 +0,0 @@ -#!/usr/bin/env python3 -# SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) - -""" -setup.py file for SWIG libfdt -Copyright (C) 2017 Google, Inc. -Written by Simon Glass <sjg@chromium.org> -""" - -import os -import sys - -from setuptools import setup, Extension -from setuptools.command.build_py import build_py as _build_py - - -def scan_for_info(srcdir): - """Scan for the version and long_description fields - - Args: - srcdir (str): Source-directory path - - Returns: tuple - str: Full description (contents of README.md) - str: Version string - """ - with open(os.path.join(srcdir, "VERSION.txt"), "r", encoding='utf-8') as fh: - version = fh.readline().strip() - - with open(os.path.join(srcdir, "README.md"), "r", encoding='utf-8') as fh: - long_description = fh.read() - - return version, long_description - - -def get_top_builddir(srcdir): - """Figure out the top-level directory containing the source code - - Args: - srcdir (str): Source-directory path - - Returns: - str: Directory to build in - """ - if '--top-builddir' in sys.argv: - index = sys.argv.index('--top-builddir') - sys.argv.pop(index) - return sys.argv.pop(index) - return srcdir - - -class BuildPy(_build_py): - """Small class to run the build_ext command""" - def run(self): - self.run_command("build_ext") - return super().run() - - -srcdir = os.path.dirname(__file__) -version, long_description = scan_for_info(srcdir) - -libfdt_module = Extension( - '_libfdt', - sources=[os.path.join(srcdir, 'pylibfdt/libfdt.i')], - define_macros=[('PY_SSIZE_T_CLEAN', None)], - include_dirs=[os.path.join(srcdir, 'libfdt')], - libraries=['fdt'], - library_dirs=[os.path.join(get_top_builddir(srcdir), 'libfdt')], - swig_opts=['-I' + os.path.join(srcdir, 'libfdt')], -) - - -setup( - name='libfdt', - version=version, - cmdclass = {'build_py' : BuildPy}, - author='Simon Glass', - author_email='sjg@chromium.org', - description='Python binding for libfdt', - ext_modules=[libfdt_module], - package_dir={'': os.path.join(srcdir, 'pylibfdt')}, - py_modules=['libfdt'], - python_requires=">=3.8", - - long_description=long_description, - long_description_content_type="text/plain", - url="https://git.kernel.org/pub/scm/utils/dtc/dtc.git", - license="BSD", - license_files=["GPL", "BSD-2-Clause"], - - classifiers=[ - "Programming Language :: Python :: 3", - "License :: OSI Approved :: BSD License", - "License :: OSI Approved :: GNU General Public License v2 or later (GPLv2+)", - "Operating System :: OS Independent", - ], -) -- 2.49.0 ^ permalink raw reply related [flat|nested] 20+ messages in thread
* Re: [PATCH v3 0/2] port python bindings to native Meson 2025-04-30 15:25 ` [PATCH v3 0/2] port python bindings to native Meson Eli Schwartz 2025-04-30 15:25 ` [PATCH v3 1/2] Makefile: deprecate in favor of Meson Eli Schwartz 2025-04-30 15:25 ` [PATCH v3 2/2] meson: port python bindings to build natively via meson and meson-python Eli Schwartz @ 2025-05-01 12:33 ` David Gibson 2 siblings, 0 replies; 20+ messages in thread From: David Gibson @ 2025-05-01 12:33 UTC (permalink / raw) To: Eli Schwartz; +Cc: devicetree-compiler [-- Attachment #1: Type: text/plain, Size: 2908 bytes --] On Wed, Apr 30, 2025 at 11:25:24AM -0400, Eli Schwartz wrote: > Eli Schwartz (2): > Makefile: deprecate in favor of Meson > meson: port python bindings to build natively via meson and > meson-python Merged, thanks. > > MANIFEST.in | 12 ----- > Makefile | 53 ++------------------- > libfdt/meson.build | 32 +++++++------ > meson.build | 3 +- > meson_options.txt | 2 + > pylibfdt/Makefile.pylibfdt | 30 ------------ > pylibfdt/meson.build | 28 +++++++---- > pyproject.toml | 33 +++++++++++++ > setup.py | 97 -------------------------------------- > 9 files changed, 77 insertions(+), 213 deletions(-) > delete mode 100644 MANIFEST.in > delete mode 100644 pylibfdt/Makefile.pylibfdt > create mode 100644 pyproject.toml > delete mode 100755 setup.py > > Range-diff against v2: > 1: 142d7e4 ! 1: e5220b1 Makefile: deprecate in favor of Meson > @@ Commit message > true, we deprecate the latter and warn when you use it. > > GNU Make can emit a $(warning) on every Makefile run, which is a bit > - noisly but means we don't need to have every target depend on a PHONY > + noisy but means we don't need to have every target depend on a PHONY > target (preventing built targets from being seen as up to date). > > ## Makefile ## > @@ Makefile > # Device Tree Compiler > # > > -+$(warning WARNING: Building dtc using the Makefile is deprecated, in favor of using the Meson build system instead.) > ++$(warning WARNING: Building dtc using make is deprecated, in favour of using Meson (https://mesonbuild.com)) > +$(warning ) > -+$(warning https://mesonbuild.com) > -+$(warning ) > -+$(warning Use `meson setup builddir/ && ninja -C builddir/` to build, or `meson configure` to see build options.) > ++$(warning Use `meson setup builddir/ && meson compile -C builddir/` to build, `meson test -C builddir/` to test, or `meson configure` to see build options.) > + > # > # Version information will be constructed in this order: > 2: 5d0590f ! 2: 3490690 meson: port python bindings to build natively via meson and meson-python > @@ pyproject.toml (new) > + 'License :: OSI Approved :: GNU General Public License v2 or later (GPLv2+)', > + 'Operating System :: OS Independent', > +] > -+description = 'Pthon binding for libfdt' > ++description = 'Python binding for libfdt' > +readme = 'README.md' > +requires-python = '>=3.8' > +dynamic = ['version'] -- David Gibson (he or they) | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you, not the other way | around. http://www.ozlabs.org/~dgibson [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 833 bytes --] ^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH v2 2/2] meson: port python bindings to build natively via meson and meson-python 2025-04-29 1:41 ` [PATCH v2 0/2] port python bindings to native Meson Eli Schwartz 2025-04-29 1:41 ` [PATCH v2 1/2] Makefile: deprecate in favor of Meson Eli Schwartz @ 2025-04-29 1:41 ` Eli Schwartz 2025-04-30 14:59 ` David Gibson 1 sibling, 1 reply; 20+ messages in thread From: Eli Schwartz @ 2025-04-29 1:41 UTC (permalink / raw) To: devicetree-compiler We get full build parallelism and fewer confusing ancient distutils paths. The python wheels build fully standalone, including linking libfdt as a static library. For convenience, when running pip install a meson option is passed that prevents building tools or installing headers/pkgconfig files. meson-python would otherwise include them in the wheel itself, in case they are needed, but this is essentially a bit useless so don't bother. The old setuptools-based build is now redundant and goes away. Signed-off-by: Eli Schwartz <eschwartz@gentoo.org> --- MANIFEST.in | 12 ----- Makefile | 49 +------------------ libfdt/meson.build | 32 +++++++------ meson.build | 3 +- meson_options.txt | 2 + pylibfdt/Makefile.pylibfdt | 30 ------------ pylibfdt/meson.build | 28 +++++++---- pyproject.toml | 33 +++++++++++++ setup.py | 97 -------------------------------------- 9 files changed, 73 insertions(+), 213 deletions(-) delete mode 100644 MANIFEST.in delete mode 100644 pylibfdt/Makefile.pylibfdt create mode 100644 pyproject.toml delete mode 100755 setup.py diff --git a/MANIFEST.in b/MANIFEST.in deleted file mode 100644 index 904d124..0000000 --- a/MANIFEST.in +++ /dev/null @@ -1,12 +0,0 @@ -# SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) - -global-exclude * -include README.md -include GPL -include BSD-2-Clause -include setup.py -include pylibfdt/libfdt.i -include libfdt/libfdt.h -include libfdt/fdt.h -include libfdt/libfdt_env.h -include VERSION.txt diff --git a/Makefile b/Makefile index 000dd85..9fc8b14 100644 --- a/Makefile +++ b/Makefile @@ -33,7 +33,6 @@ BISON = bison LEX = flex SWIG = swig PKG_CONFIG ?= pkg-config -PYTHON ?= python3 INSTALL = install INSTALL_PROGRAM = $(INSTALL) @@ -49,8 +48,6 @@ INCLUDEDIR = $(PREFIX)/include HOSTOS := $(shell uname -s | tr '[:upper:]' '[:lower:]' | \ sed -e 's/\(cygwin\|msys\).*/\1/') -NO_PYTHON ?= 0 - NO_VALGRIND := $(shell $(PKG_CONFIG) --exists valgrind; echo $$?) ifeq ($(NO_VALGRIND),1) CPPFLAGS += -DNO_VALGRIND @@ -160,29 +157,6 @@ SCRIPTS = dtdiff all: $(BIN) libfdt -# We need both Python and swig to build/install pylibfdt. -# This builds the given make ${target} if those deps are found. -check_python_deps = \ - if $(PKG_CONFIG) --cflags $(PYTHON) >/dev/null 2>&1; then \ - if which swig >/dev/null 2>&1; then \ - can_build=yes; \ - fi; \ - fi; \ - if [ "$${can_build}" = "yes" ]; then \ - $(MAKE) $${target}; \ - else \ - echo "\#\# Skipping pylibfdt (install python dev and swig to build)"; \ - fi ; - -.PHONY: maybe_pylibfdt -maybe_pylibfdt: FORCE - target=pylibfdt; $(check_python_deps) - -ifeq ($(NO_PYTHON),0) -all: maybe_pylibfdt -endif - - ifneq ($(DEPTARGETS),) ifneq ($(MAKECMDGOALS),libfdt) -include $(DTC_OBJS:%.o=%.d) @@ -256,14 +230,6 @@ install-includes: install: install-bin install-lib install-includes -.PHONY: maybe_install_pylibfdt -maybe_install_pylibfdt: FORCE - target=install_pylibfdt; $(check_python_deps) - -ifeq ($(NO_PYTHON),0) -install: maybe_install_pylibfdt -endif - $(VERSION_FILE): Makefile FORCE $(call filechk,version) @@ -289,16 +255,6 @@ dist: gzip -9 > ../dtc-$(dtc_version).tar.gz -# -# Rules for pylibfdt -# -PYLIBFDT_dir = pylibfdt - -include $(PYLIBFDT_dir)/Makefile.pylibfdt - -.PHONY: pylibfdt -pylibfdt: $(PYLIBFDT_dir)/_libfdt.so - # # Release signing and uploading # This is for maintainer convenience, don't try this at home. @@ -332,9 +288,6 @@ TESTS_BIN += fdtput TESTS_BIN += fdtget TESTS_BIN += fdtdump TESTS_BIN += fdtoverlay -ifeq ($(NO_PYTHON),0) -TESTS_PYLIBFDT += maybe_pylibfdt -endif ifneq ($(MAKECMDGOALS),libfdt) include tests/Makefile.tests @@ -346,7 +299,7 @@ endif STD_CLEANFILES = *~ *.o *.$(SHAREDLIB_EXT) *.d *.a *.i *.s core a.out vgcore.* \ *.tab.[ch] *.lex.c *.output -clean: libfdt_clean pylibfdt_clean tests_clean +clean: libfdt_clean tests_clean @$(VECHO) CLEAN rm -f $(STD_CLEANFILES) rm -f $(VERSION_FILE) diff --git a/libfdt/meson.build b/libfdt/meson.build index c2f4bd6..9c6ef54 100644 --- a/libfdt/meson.build +++ b/libfdt/meson.build @@ -31,7 +31,7 @@ libfdt = library( version: meson.project_version(), link_args: link_args, link_depends: 'version.lds', - install: true, + install: get_option('default_library') != 'static' or not wheel_only, ) libfdt_inc = include_directories('.') @@ -41,20 +41,22 @@ libfdt_dep = declare_dependency( link_with: libfdt, ) -install_headers( - files( - 'fdt.h', - 'libfdt.h', - 'libfdt_env.h', +if not wheel_only + install_headers( + files( + 'fdt.h', + 'libfdt.h', + 'libfdt_env.h', + ) ) -) -pkgconfig = import('pkgconfig') + pkgconfig = import('pkgconfig') -pkgconfig.generate( - libraries: libfdt, - version: meson.project_version(), - filebase: 'libfdt', - name: 'libfdt', - description: 'Flat Device Tree manipulation', -) + pkgconfig.generate( + libraries: libfdt, + version: meson.project_version(), + filebase: 'libfdt', + name: 'libfdt', + description: 'Flat Device Tree manipulation', + ) +endif diff --git a/meson.build b/meson.build index 3026f88..ed4a39d 100644 --- a/meson.build +++ b/meson.build @@ -43,6 +43,7 @@ py = import('python') py = py.find_installation(required: get_option('python')) swig = find_program('swig', required: get_option('python')) pylibfdt_enabled = not meson.is_cross_build() and py.found() and swig.found() ? true : false +wheel_only = get_option('wheel-only') version_gen_h = vcs_tag( command: ['git', 'describe', '--dirty=+'], @@ -59,7 +60,7 @@ util_dep = declare_dependency( dependencies: libfdt_dep ) -if get_option('tools') +if get_option('tools') and not wheel_only flex = find_program('flex', required: true) bison = find_program('bison', required: true) diff --git a/meson_options.txt b/meson_options.txt index 62b31b3..a866b17 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -10,3 +10,5 @@ option('python', type: 'feature', value: 'auto', description: 'Build pylibfdt Python library') option('tests', type: 'boolean', value: true, description: 'Build tests') +option('wheel-only', type: 'boolean', value: false, + description: 'building from meson-python') diff --git a/pylibfdt/Makefile.pylibfdt b/pylibfdt/Makefile.pylibfdt deleted file mode 100644 index 647203f..0000000 --- a/pylibfdt/Makefile.pylibfdt +++ /dev/null @@ -1,30 +0,0 @@ -# SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) -# Makefile.pylibfdt -# - -PYLIBFDT_srcs = $(PYLIBFDT_dir)/libfdt.i -PYMODULE = $(PYLIBFDT_dir)/_libfdt.so -PYLIBFDT_CLEANFILES_L = libfdt_wrap.c libfdt.py *.pyc *.so -PYLIBFDT_CLEANFILES = $(PYLIBFDT_CLEANFILES_L:%=$(PYLIBFDT_dir)/%) -PYLIBFDT_CLEANDIRS_L = __pycache__ libfdt.egg-info -PYLIBFDT_CLEANDIRS = build $(PYLIBFDT_CLEANDIRS_L:%=$(PYLIBFDT_dir)/%) - -SETUP = ./setup.py - -ifndef V -SETUPFLAGS += --quiet -endif - -$(PYMODULE): WARNINGS = # suppress warnings from generated code -$(PYMODULE): $(PYLIBFDT_srcs) $(LIBFDT_archive) $(SETUP) - @$(VECHO) PYMOD $@ - CFLAGS="$(CFLAGS) -Wno-error" $(PYTHON) $(SETUP) $(SETUPFLAGS) build_ext - -install_pylibfdt: $(PYMODULE) - @$(VECHO) INSTALL-PYLIB - $(PYTHON) $(SETUP) $(SETUPFLAGS) install --prefix=$(PREFIX) - -pylibfdt_clean: - @$(VECHO) CLEAN "(pylibfdt)" - rm -f $(PYLIBFDT_CLEANFILES) - rm -rf $(PYLIBFDT_CLEANDIRS) diff --git a/pylibfdt/meson.build b/pylibfdt/meson.build index 6157f8d..b13d802 100644 --- a/pylibfdt/meson.build +++ b/pylibfdt/meson.build @@ -1,13 +1,21 @@ -setup_py = find_program('../setup.py') -setup_py = [setup_py, '--quiet', '--top-builddir', meson.project_build_root()] - -pylibfdt = custom_target( - 'pylibfdt', +libfdt_c = custom_target( + 'swig', input: 'libfdt.i', - depends: libfdt, - output: '_libfdt.so', - command: [setup_py, 'build_ext'], - build_by_default: true, + output: ['libfdt.c', 'libfdt.py'], + install: true, + install_dir: [false, py.get_install_dir(pure: false)], + command: [swig, '-python', '-I'+meson.current_source_dir() / '../libfdt', '-o', '@OUTPUT0@', '@INPUT@'] ) -meson.add_install_script(setup_py, 'install', '--prefix=' + get_option('prefix'), '--root=$DESTDIR') +nowarn_gen = cc.get_supported_arguments( + '-Wno-cast-qual', + '-Wno-missing-prototypes', + '-Wno-redundant-decls', +) +pylibfdt = py.extension_module( + '_libfdt', + libfdt_c, + c_args: ['-DPY_SSIZE_T_CLEAN'] + nowarn_gen, + dependencies: [libfdt_dep, py.dependency()], + install: true, +) diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..8682026 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,33 @@ +[build-system] +build-backend = 'mesonpy' +requires = ['meson-python'] + +[project] +name = 'libfdt' +authors = [ + {name = 'Simon Glass', email = 'sjg@chromium.org'}, +] +classifiers = [ + 'Programming Language :: Python :: 3', + 'License :: OSI Approved :: BSD License', + 'License :: OSI Approved :: GNU General Public License v2 or later (GPLv2+)', + 'Operating System :: OS Independent', +] +description = 'Pthon binding for libfdt' +readme = 'README.md' +requires-python = '>=3.8' +dynamic = ['version'] + +[project.urls] +'homepage' = 'https://git.kernel.org/pub/scm/utils/dtc/dtc.git' + +# These arguments are applied only when building a redistributable binary wheel +# for uploading to PyPI. We don't want to install libraries (or headers / +# pkgconfig files / executables) that clash with system C installs, so we +# disable everything other than the python bindings themselves, and build the +# python C-API extension using static linkage to avoid juggling "libdir" / +# LD_LIBRARY_PATH / RPATH around. When building both the C library and the +# python bindings for a distro, `meson setup` will still default to shared +# libraries. +[tool.meson-python.args] +setup = ['-Ddefault_library=static', '-Dwheel-only=true'] diff --git a/setup.py b/setup.py deleted file mode 100755 index 52844ce..0000000 --- a/setup.py +++ /dev/null @@ -1,97 +0,0 @@ -#!/usr/bin/env python3 -# SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) - -""" -setup.py file for SWIG libfdt -Copyright (C) 2017 Google, Inc. -Written by Simon Glass <sjg@chromium.org> -""" - -import os -import sys - -from setuptools import setup, Extension -from setuptools.command.build_py import build_py as _build_py - - -def scan_for_info(srcdir): - """Scan for the version and long_description fields - - Args: - srcdir (str): Source-directory path - - Returns: tuple - str: Full description (contents of README.md) - str: Version string - """ - with open(os.path.join(srcdir, "VERSION.txt"), "r", encoding='utf-8') as fh: - version = fh.readline().strip() - - with open(os.path.join(srcdir, "README.md"), "r", encoding='utf-8') as fh: - long_description = fh.read() - - return version, long_description - - -def get_top_builddir(srcdir): - """Figure out the top-level directory containing the source code - - Args: - srcdir (str): Source-directory path - - Returns: - str: Directory to build in - """ - if '--top-builddir' in sys.argv: - index = sys.argv.index('--top-builddir') - sys.argv.pop(index) - return sys.argv.pop(index) - return srcdir - - -class BuildPy(_build_py): - """Small class to run the build_ext command""" - def run(self): - self.run_command("build_ext") - return super().run() - - -srcdir = os.path.dirname(__file__) -version, long_description = scan_for_info(srcdir) - -libfdt_module = Extension( - '_libfdt', - sources=[os.path.join(srcdir, 'pylibfdt/libfdt.i')], - define_macros=[('PY_SSIZE_T_CLEAN', None)], - include_dirs=[os.path.join(srcdir, 'libfdt')], - libraries=['fdt'], - library_dirs=[os.path.join(get_top_builddir(srcdir), 'libfdt')], - swig_opts=['-I' + os.path.join(srcdir, 'libfdt')], -) - - -setup( - name='libfdt', - version=version, - cmdclass = {'build_py' : BuildPy}, - author='Simon Glass', - author_email='sjg@chromium.org', - description='Python binding for libfdt', - ext_modules=[libfdt_module], - package_dir={'': os.path.join(srcdir, 'pylibfdt')}, - py_modules=['libfdt'], - python_requires=">=3.8", - - long_description=long_description, - long_description_content_type="text/plain", - url="https://git.kernel.org/pub/scm/utils/dtc/dtc.git", - license="BSD", - license_files=["GPL", "BSD-2-Clause"], - - classifiers=[ - "Programming Language :: Python :: 3", - "License :: OSI Approved :: BSD License", - "License :: OSI Approved :: GNU General Public License v2 or later (GPLv2+)", - "Operating System :: OS Independent", - ], -) -- 2.49.0 ^ permalink raw reply related [flat|nested] 20+ messages in thread
* Re: [PATCH v2 2/2] meson: port python bindings to build natively via meson and meson-python 2025-04-29 1:41 ` [PATCH v2 2/2] meson: port python bindings to build natively via meson and meson-python Eli Schwartz @ 2025-04-30 14:59 ` David Gibson 0 siblings, 0 replies; 20+ messages in thread From: David Gibson @ 2025-04-30 14:59 UTC (permalink / raw) To: Eli Schwartz; +Cc: devicetree-compiler [-- Attachment #1: Type: text/plain, Size: 1570 bytes --] On Mon, Apr 28, 2025 at 09:41:43PM -0400, Eli Schwartz wrote: > We get full build parallelism and fewer confusing ancient distutils > paths. The python wheels build fully standalone, including linking > libfdt as a static library. > > For convenience, when running pip install a meson option is passed that > prevents building tools or installing headers/pkgconfig files. > meson-python would otherwise include them in the wheel itself, in case > they are needed, but this is essentially a bit useless so don't bother. > > The old setuptools-based build is now redundant and goes away. > > Signed-off-by: Eli Schwartz <eschwartz@gentoo.org> LGTM, excepting one tiny typo [snip] > diff --git a/pyproject.toml b/pyproject.toml > new file mode 100644 > index 0000000..8682026 > --- /dev/null > +++ b/pyproject.toml > @@ -0,0 +1,33 @@ > +[build-system] > +build-backend = 'mesonpy' > +requires = ['meson-python'] > + > +[project] > +name = 'libfdt' > +authors = [ > + {name = 'Simon Glass', email = 'sjg@chromium.org'}, > +] > +classifiers = [ > + 'Programming Language :: Python :: 3', > + 'License :: OSI Approved :: BSD License', > + 'License :: OSI Approved :: GNU General Public License v2 or later (GPLv2+)', > + 'Operating System :: OS Independent', > +] > +description = 'Pthon binding for libfdt' "Pthon" -- David Gibson (he or they) | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you, not the other way | around. http://www.ozlabs.org/~dgibson [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 833 bytes --] ^ permalink raw reply [flat|nested] 20+ messages in thread
end of thread, other threads:[~2025-05-01 12:33 UTC | newest] Thread overview: 20+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2025-03-17 0:40 [PATCH] meson: port python bindings to build natively via meson and meson-python Eli Schwartz 2025-03-18 14:15 ` Rob Herring 2025-03-18 14:36 ` Eli Schwartz 2025-03-18 17:02 ` Rob Herring 2025-03-19 6:51 ` Eli Schwartz 2025-03-19 5:55 ` David Gibson 2025-03-19 6:30 ` Eli Schwartz 2025-04-25 7:56 ` David Gibson 2025-04-29 1:34 ` Eli Schwartz 2025-04-29 1:41 ` [PATCH v2 0/2] port python bindings to native Meson Eli Schwartz 2025-04-29 1:41 ` [PATCH v2 1/2] Makefile: deprecate in favor of Meson Eli Schwartz 2025-04-30 14:56 ` David Gibson 2025-04-30 15:10 ` Eli Schwartz 2025-04-30 15:20 ` David Gibson 2025-04-30 15:25 ` [PATCH v3 0/2] port python bindings to native Meson Eli Schwartz 2025-04-30 15:25 ` [PATCH v3 1/2] Makefile: deprecate in favor of Meson Eli Schwartz 2025-04-30 15:25 ` [PATCH v3 2/2] meson: port python bindings to build natively via meson and meson-python Eli Schwartz 2025-05-01 12:33 ` [PATCH v3 0/2] port python bindings to native Meson David Gibson 2025-04-29 1:41 ` [PATCH v2 2/2] meson: port python bindings to build natively via meson and meson-python Eli Schwartz 2025-04-30 14:59 ` David Gibson
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).