* [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-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-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-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
* [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 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 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
* 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
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).