From 88fff697d96c8f65c9b40792a066526c8dcac467 Mon Sep 17 00:00:00 2001
From: Bastian Germann <bage@debian.org>
Date: Fri, 20 May 2022 17:01:09 +0200
Subject: [PATCH] Enable pylibfdt build (Closes: #877125)

Include two post-1.6.1 upstream commits to allow building with Python 3.10
and setuptools. The patch also introduces setuptools_scm, which is why this
needs to be included in the Build-Dependencies.

Fix d/rules' CFLAGS handling. The upstream Makefile overrides the passed
CFLAGS but it contains EXTRA_CFLAGS to add more. The previously contained
CFLAGS amount to the default on Linux.
---
 debian/control                                |   4 +
 .../02_Move_setup.py_to_the_top_level.patch   | 132 ++++++++++++++++++
 debian/patches/03_fix_with_Python_3.10.patch  |  55 ++++++++
 debian/patches/series                         |   2 +
 debian/rules                                  |  13 +-
 5 files changed, 198 insertions(+), 8 deletions(-)
 create mode 100644 debian/patches/02_Move_setup.py_to_the_top_level.patch
 create mode 100644 debian/patches/03_fix_with_Python_3.10.patch

diff --git a/debian/control b/debian/control
index d60b092..f82e53c 100644
--- a/debian/control
+++ b/debian/control
@@ -9,6 +9,10 @@ Build-Depends: debhelper-compat (= 13),
  bison,
  libyaml-dev,
  pkg-config,
+ python3-dev,
+ python3-setuptools,
+ python3-setuptools-scm,
+ swig,
  texlive <!nodoc>,
  texlive-latex-extra <!nodoc>,
  valgrind [amd64 arm64 armhf i386 mips mips64el mipsel powerpc ppc64 ppc64el s390x],
diff --git a/debian/patches/02_Move_setup.py_to_the_top_level.patch b/debian/patches/02_Move_setup.py_to_the_top_level.patch
new file mode 100644
index 0000000..372242a
--- /dev/null
+++ b/debian/patches/02_Move_setup.py_to_the_top_level.patch
@@ -0,0 +1,132 @@
+Origin: backport, 23b56cb7e18992650c79a04c9e4e3f2740bc1fbd
+From: Rob Herring <robh@kernel.org>
+Date: Wed, 10 Nov 2021 19:11:35 -0600
+Subject: pylibfdt: Move setup.py to the top level
+
+Using 'pip' and several setup.py sub-commands currently don't work with
+pylibfdt. The primary reason is Python packaging has opinions on the
+directory structure of repositories and one of those appears to be the
+inability to reference source files outside of setup.py's subtree. This
+means a sdist cannot be created with all necessary source components
+(i.e. libfdt headers). Moving setup.py to the top-level solves these
+problems.
+
+With this change. the following commands now work:
+
+Creating packages for pypi.org:
+./setup.py sdist bdist_wheel
+
+Using pip for installs:
+pip install .
+pip install git+http://github.com/robherring/dtc.git@pypi-v2
+
+Signed-off-by: Rob Herring <robh@kernel.org>
+Message-Id: <20211111011135.2386773-5-robh@kernel.org>
+Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
+---
+ MANIFEST.in                |  9 ++++++++
+ pylibfdt/Makefile.pylibfdt |  3 +--
+ pylibfdt/meson.build       |  4 ++--
+ setup.py                   | 51 ++++++++++++++++++++++++++++++++++++++++++++++
+ 6 files changed, 67 insertions(+), 54 deletions(-)
+ create mode 100644 MANIFEST.in
+ create mode 100755 setup.py
+
+diff --git a/MANIFEST.in b/MANIFEST.in
+new file mode 100644
+index 0000000..9e6c4ac
+--- /dev/null
++++ b/MANIFEST.in
+@@ -0,0 +1,9 @@
++# SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
++
++global-exclude *
++include setup.py
++include pylibfdt/libfdt.i
++include pylibfdt/*.py
++include libfdt/libfdt.h
++include libfdt/fdt.h
++include libfdt/libfdt_env.h
+diff --git a/pylibfdt/Makefile.pylibfdt b/pylibfdt/Makefile.pylibfdt
+index 015a05e..82f565e 100644
+--- a/pylibfdt/Makefile.pylibfdt
++++ b/pylibfdt/Makefile.pylibfdt
+@@ -9,8 +9,7 @@ PYLIBFDT_CLEANFILES = $(PYLIBFDT_CLEANFILES_L:%=$(PYLIBFDT_dir)/%)
+ PYLIBFDT_CLEANDIRS_L = build __pycache__
+ PYLIBFDT_CLEANDIRS = $(PYLIBFDT_CLEANDIRS_L:%=$(PYLIBFDT_dir)/%)
+ 
+-SETUP = $(PYLIBFDT_dir)/setup.py
+-SETUPFLAGS = --top-builddir .
++SETUP = ./setup.py
+ 
+ ifndef V
+ SETUPFLAGS += --quiet
+diff --git a/pylibfdt/meson.build b/pylibfdt/meson.build
+index fad5aa1..f684cbb 100644
+--- a/pylibfdt/meson.build
++++ b/pylibfdt/meson.build
+@@ -1,5 +1,5 @@
+-setup_py = find_program('setup.py')
+-setup_py = [setup_py.path(), '--quiet', '--top-builddir', meson.current_build_dir() / '..']
++setup_py = find_program('../setup.py')
++setup_py = [setup_py.path(), '--quiet', '--top-builddir', meson.project_build_root()]
+ 
+ custom_target(
+   'pylibfdt',
+diff --git a/setup.py b/setup.py
+new file mode 100755
+index 0000000..4b07be9
+--- /dev/null
++++ b/setup.py
+@@ -0,0 +1,51 @@
++#!/usr/bin/env python3
++# SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
++
++# While Python 3 is the default, it's also possible to invoke
++# this setup.py script with Python 2.
++
++"""
++setup.py file for SWIG libfdt
++Copyright (C) 2017 Google, Inc.
++Written by Simon Glass <sjg@chromium.org>
++"""
++
++from setuptools import setup, Extension
++import os
++import re
++import sys
++
++srcdir = os.path.dirname(__file__)
++
++def get_top_builddir():
++    if '--top-builddir' in sys.argv:
++        index = sys.argv.index('--top-builddir')
++        sys.argv.pop(index)
++        return sys.argv.pop(index)
++    else:
++        return srcdir
++
++top_builddir = get_top_builddir()
++
++libfdt_module = Extension(
++    '_libfdt',
++    sources=[os.path.join(srcdir, 'pylibfdt/libfdt.i')],
++    include_dirs=[os.path.join(srcdir, 'libfdt')],
++    libraries=['fdt'],
++    library_dirs=[os.path.join(top_builddir, 'libfdt')],
++    swig_opts=['-I' + os.path.join(srcdir, 'libfdt')],
++)
++
++setup(
++    name='libfdt',
++    use_scm_version={
++        "root": srcdir,
++    },
++    setup_requires = ['setuptools_scm'],
++    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'],
++)
diff --git a/debian/patches/03_fix_with_Python_3.10.patch b/debian/patches/03_fix_with_Python_3.10.patch
new file mode 100644
index 0000000..3b7fc32
--- /dev/null
+++ b/debian/patches/03_fix_with_Python_3.10.patch
@@ -0,0 +1,55 @@
+Origin: upstream, 383e148b70a47ab15f97a19bb999d54f9c3e810f
+From: Ross Burton <ross.burton@arm.com>
+Date: Thu, 11 Nov 2021 16:05:36 +0000
+Subject: pylibfdt: fix with Python 3.10
+
+Since Python 2.5 the argument parsing functions when parsing expressions
+such as s# (string plus length) expect the length to be an int or a
+ssize_t, depending on whether PY_SSIZE_T_CLEAN is defined or not.
+
+Python 3.8 deprecated the use of int, and with Python 3.10 this symbol
+must be defined and ssize_t used[1].
+
+Define the magic symbol when building the extension, and cast the ints
+from the libfdt API to ssize_t as appropriate.
+
+[1] https://docs.python.org/3.10/whatsnew/3.10.html#id2
+
+Signed-off-by: Ross Burton <ross.burton@arm.com>
+Message-Id: <20211111160536.2516573-1-ross.burton@arm.com>
+[dwg: Adjust for new location of setup.py]
+Tested-by: Rob Herring <robh@kernel.org>
+Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
+---
+ pylibfdt/libfdt.i | 4 ++--
+ setup.py          | 1 +
+ 2 files changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/pylibfdt/libfdt.i b/pylibfdt/libfdt.i
+index 51ee801..075ef70 100644
+--- a/pylibfdt/libfdt.i
++++ b/pylibfdt/libfdt.i
+@@ -1044,9 +1044,9 @@ typedef uint32_t fdt32_t;
+ 		$result = Py_None;
+ 	else
+         %#if PY_VERSION_HEX >= 0x03000000
+-            $result = Py_BuildValue("y#", $1, *arg4);
++            $result = Py_BuildValue("y#", $1, (Py_ssize_t)*arg4);
+         %#else
+-            $result = Py_BuildValue("s#", $1, *arg4);
++            $result = Py_BuildValue("s#", $1, (Py_ssize_t)*arg4);
+         %#endif
+ }
+ 
+diff --git a/setup.py b/setup.py
+index 4b07be9..0a0daf1 100755
+--- a/setup.py
++++ b/setup.py
+@@ -30,6 +30,7 @@ top_builddir = get_top_builddir()
+ 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(top_builddir, 'libfdt')],
diff --git a/debian/patches/series b/debian/patches/series
index 7f8f39e..3b4e70f 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -1 +1,3 @@
 01_build_doc.patch
+02_Move_setup.py_to_the_top_level.patch
+03_fix_with_Python_3.10.patch
diff --git a/debian/rules b/debian/rules
index 3274b59..01a4155 100755
--- a/debian/rules
+++ b/debian/rules
@@ -5,33 +5,30 @@
 # respect SOURCE_DATE_EPOCH.
 export FORCE_SOURCE_DATE=1
 
+export SETUPTOOLS_SCM_PRETEND_VERSION=$(DEB_VERSION_UPSTREAM)
 export DEB_BUILD_MAINT_OPTIONS=hardening=+all
 
-# python library builds with warnings, temporarily disabled.
-export NO_PYTHON = 1
-
 include /usr/share/dpkg/architecture.mk
 ifeq ($(origin CC),default)
 export CC = $(DEB_HOST_GNU_TYPE)-gcc
 endif
 
 include /usr/share/dpkg/buildflags.mk
-CFLAGS += -fPIC -Werror -Wall -Wpointer-arith -Wcast-qual	\
-	-Wnested-externs -Wstrict-prototypes -Wmissing-prototypes	\
-	-Wredundant-decls -Wshadow
+EXTRA_CFLAGS = -Wno-error
 CPPFLAGS += -I libfdt -I .
 
 %:
 	dh $@
 
 override_dh_auto_build:
-	dh_auto_build -- V=1 CFLAGS="$(CFLAGS)" CPPFLAGS="$(CPPFLAGS)"
+	dh_auto_build -- V=1 EXTRA_CFLAGS="$(EXTRA_CFLAGS)" CPPFLAGS="$(CPPFLAGS)"
 ifeq (,$(findstring nodoc,$(DEB_BUILD_OPTIONS)))
 	$(MAKE) -C Documentation
 endif
 
 override_dh_auto_install:
-	$(MAKE) install DESTDIR=$(CURDIR)/debian/tmp PREFIX=/usr LIBDIR=/usr/lib/$(DEB_HOST_MULTIARCH)
+	NO_PYTHON=1 $(MAKE) install DESTDIR=$(CURDIR)/debian/tmp PREFIX=/usr LIBDIR=/usr/lib/$(DEB_HOST_MULTIARCH)
+	$(MAKE) maybe_install_pylibfdt EXTRA_CFLAGS="$(EXTRA_CFLAGS)" PREFIX=$(CURDIR)/debian/tmp/usr
 
 override_dh_auto_clean:
 	dh_auto_clean
