This is an automated email from the ASF dual-hosted git repository.

acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx-apps.git


The following commit(s) were added to refs/heads/master by this push:
     new efc1bf710 interpreters/python: Add Python's port to NuttX
efc1bf710 is described below

commit efc1bf710c8be1e0f0ae5e1bf2b292f8b57076a6
Author: Tiago Medicci <[email protected]>
AuthorDate: Wed Dec 4 16:48:38 2024 -0300

    interpreters/python: Add Python's port to NuttX
    
    This is the NuttX's port of Python (cpython)!
    
    Initial support of Python includes building the Python's static
    library and the `python` (Programs/python.c) application. Python's
    modules are stored in `pyc` (byte-code file) and loaded as needed
    from flash.
---
 interpreters/python/.gitignore                     |   6 +
 interpreters/python/Kconfig                        |  58 +++++++
 interpreters/python/Make.defs                      |  30 ++++
 interpreters/python/Makefile                       | 172 +++++++++++++++++++
 interpreters/python/Setup.local                    |  50 ++++++
 interpreters/python/config.site                    |  21 +++
 interpreters/python/mount_modules.c                | 132 ++++++++++++++
 ...-workaround-newlib-resource.h-limitations.patch |  29 ++++
 ...-uint32_t-unsigned-int-type-mismatch-issu.patch | 151 ++++++++++++++++
 ...assets.py-for-generating-an-archive-of-py.patch |  42 +++++
 .../0004-recognize-nuttx-as-a-supported-OS.patch   |  60 +++++++
 ...ix-Builds-Without-HAVE_DYNAMIC_LOADING-Se.patch | 189 +++++++++++++++++++++
 ...name-to-avoid-conflict-with-nuttx-unused_.patch | 168 ++++++++++++++++++
 .../python/patch/0007-undef-atexit_register.patch  |  29 ++++
 .../python/patch/0008-declare-struct-timeval.patch |  27 +++
 ...tx-sys-select-header-to-define-FD_SETSIZE.patch |  27 +++
 ...-the-d_ino-member-of-the-structure-dirent.patch | 173 +++++++++++++++++++
 17 files changed, 1364 insertions(+)

diff --git a/interpreters/python/.gitignore b/interpreters/python/.gitignore
new file mode 100644
index 000000000..ad58719cd
--- /dev/null
+++ b/interpreters/python/.gitignore
@@ -0,0 +1,6 @@
+/*.zip
+/build/
+/install/
+/Python/
+/romfs_cpython_modules.h
+/romfs_cpython_modules.img
diff --git a/interpreters/python/Kconfig b/interpreters/python/Kconfig
new file mode 100644
index 000000000..da20c8ec4
--- /dev/null
+++ b/interpreters/python/Kconfig
@@ -0,0 +1,58 @@
+#
+# For a description of the syntax of this configuration file,
+# see the file kconfig-language.txt in the NuttX tools repository.
+#
+
+config INTERPRETER_CPYTHON
+       tristate "CPython"
+       depends on LIB_ZLIB
+       depends on EXPERIMENTAL
+       default n
+       ---help---
+               Enable the CPython port to NuttX. This is a port of the Python
+               interpreter to NuttX. Initially, it is tweaked to work with the
+               RISC-V QEMU virtual board (`rv-virt`).
+
+if INTERPRETER_CPYTHON
+
+config INTERPRETER_CPYTHON_VERSION
+       string "Python Version"
+       default "3.13.0"
+
+config INTERPRETER_CPYTHON_STACKSIZE
+       int "CPython stack size"
+       default 307200
+       ---help---
+               This is the stack size allocated when the CPython task runs.
+
+config INTERPRETER_CPYTHON_PRIORITY
+       int "CPython task priority"
+       default 150
+       ---help---
+               This is the priority of the CPython task.
+
+config INTERPRETER_CPYTHON_PROGNAME
+       string "CPython name"
+       default "python"
+       ---help---
+               This is the name of the program that will be used from the nsh.
+
+config INTERPRETER_CPYTHON_MOUNT_MODULES_STACKSIZE
+       int "CPython's Modules Mount stack size"
+       default 4096
+       ---help---
+               This is the stack size allocated when the CPython's Modules 
Mount task runs.
+
+config INTERPRETER_CPYTHON_MOUNT_MODULES_PRIORITY
+       int "CPython's Modules Mount task priority"
+       default 150
+       ---help---
+               This is the priority of the CPython's Modules Mount task.
+
+config INTERPRETER_CPYTHON_MOUNT_MODULES_PROGNAME
+       string "CPython's Modules Mount app name"
+       default "python_mount_modules"
+       ---help---
+               This is the name of the program that will be used from the nsh.
+
+endif
diff --git a/interpreters/python/Make.defs b/interpreters/python/Make.defs
new file mode 100644
index 000000000..a1aecbdb4
--- /dev/null
+++ b/interpreters/python/Make.defs
@@ -0,0 +1,30 @@
+############################################################################
+# apps/interpreters/python/Make.defs
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+############################################################################
+
+ifneq ($(CONFIG_INTERPRETER_CPYTHON),)
+
+CPYTHON_VERSION = $(patsubst "%",%,$(strip 
$(CONFIG_INTERPRETER_CPYTHON_VERSION)))
+CPYTHON_VERSION_MINOR=$(basename $(CPYTHON_VERSION))
+
+EXTRA_LIBPATHS += -L$(APPDIR)/interpreters/python/install/target
+EXTRA_LIBS += -lpython$(CPYTHON_VERSION_MINOR)
+
+CONFIGURED_APPS += $(APPDIR)/interpreters/python
+endif
diff --git a/interpreters/python/Makefile b/interpreters/python/Makefile
new file mode 100644
index 000000000..80db1722e
--- /dev/null
+++ b/interpreters/python/Makefile
@@ -0,0 +1,172 @@
+############################################################################
+# apps/interpreters/python/Makefile
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+############################################################################
+
+include $(APPDIR)/Make.defs
+
+CPYTHON_URL ?= "https://github.com/python/cpython/archive";
+CPYTHON_VERSION = $(patsubst "%",%,$(strip 
$(CONFIG_INTERPRETER_CPYTHON_VERSION)))
+CPYTHON_VERSION_MINOR=$(basename $(CPYTHON_VERSION))
+CPYTHON_ZIP = v$(CPYTHON_VERSION).zip
+
+CPYTHON_UNPACKNAME = Python
+UNPACK ?= unzip -q -o
+
+MACHDEP=nuttx
+CONFIG_SITE=${CURDIR}/config.site
+CPYTHON_PATH=$(CURDIR)/$(CPYTHON_UNPACKNAME)
+
+BUILDIR=$(CURDIR)/build
+INSTALLDIR=$(CURDIR)/install
+HOSTBUILD=$(BUILDIR)/host
+HOSTINSTALL=$(INSTALLDIR)/host
+HOSTPYTHON=$(HOSTINSTALL)/bin/python3
+TARGETBUILD=$(BUILDIR)/target
+TARGETINSTALL=$(INSTALLDIR)/target
+TARGETLIBPYTHON=$(TARGETINSTALL)/libpython$(CPYTHON_VERSION_MINOR).a
+TARGETMODULESPACK=$(TARGETBUILD)/lib/python$(shell echo 
$(CPYTHON_VERSION_MINOR) | tr -d .).zip
+TARGETMODULES=$(TARGETINSTALL)/lib/
+
+DEPPATH += --dep-path $(CPYTHON_UNPACKNAME)$(DELIM)Programs
+VPATH   += :$(CPYTHON_UNPACKNAME)$(DELIM)Programs
+
+$(CPYTHON_ZIP):
+       @echo "Downloading: $(CPYTHON_URL)/$(CPYTHON_ZIP)"
+       $(Q) $(call DOWNLOAD,$(CPYTHON_URL),$(CPYTHON_ZIP))
+
+$(CPYTHON_UNPACKNAME): $(CPYTHON_ZIP)
+       @echo "Unpacking: $(CPYTHON_ZIP) -> $(CPYTHON_UNPACKNAME)"
+       $(Q) $(UNPACK) $(CPYTHON_ZIP)
+       $(Q) mv cpython-$(CPYTHON_VERSION) $(CPYTHON_UNPACKNAME)
+       @echo "Patching $(CPYTHON_UNPACKNAME)"
+       $(Q) patch -p1 -d $(CPYTHON_UNPACKNAME) < 
patch$(DELIM)0001-workaround-newlib-resource.h-limitations.patch
+       $(Q) patch -p1 -d $(CPYTHON_UNPACKNAME) < 
patch$(DELIM)0002-fix-various-uint32_t-unsigned-int-type-mismatch-issu.patch
+       $(Q) patch -p1 -d $(CPYTHON_UNPACKNAME) < 
patch$(DELIM)0003-reuse-wasm_assets.py-for-generating-an-archive-of-py.patch
+       $(Q) patch -p1 -d $(CPYTHON_UNPACKNAME) < 
patch$(DELIM)0004-recognize-nuttx-as-a-supported-OS.patch
+       $(Q) patch -p1 -d $(CPYTHON_UNPACKNAME) < 
patch$(DELIM)0005-gh-122907-Fix-Builds-Without-HAVE_DYNAMIC_LOADING-Se.patch
+       $(Q) patch -p1 -d $(CPYTHON_UNPACKNAME) < 
patch$(DELIM)0006-change-var-name-to-avoid-conflict-with-nuttx-unused_.patch
+       $(Q) patch -p1 -d $(CPYTHON_UNPACKNAME) < 
patch$(DELIM)0007-undef-atexit_register.patch
+       $(Q) patch -p1 -d $(CPYTHON_UNPACKNAME) < 
patch$(DELIM)0008-declare-struct-timeval.patch
+       $(Q) patch -p1 -d $(CPYTHON_UNPACKNAME) < 
patch$(DELIM)0009-include-nuttx-sys-select-header-to-define-FD_SETSIZE.patch
+       $(Q) patch -p1 -d $(CPYTHON_UNPACKNAME) < 
patch$(DELIM)0010-check-for-the-d_ino-member-of-the-structure-dirent.patch
+
+$(HOSTPYTHON):
+       mkdir -p $(HOSTBUILD)
+       mkdir -p $(HOSTINSTALL)
+       $(Q) ( \
+                       cd $(HOSTBUILD) && $(CPYTHON_PATH)/configure \
+                        --with-pydebug \
+                        --prefix=$(HOSTINSTALL) \
+                )
+       $(MAKE) -C $(HOSTBUILD) install
+
+# For the Python's `configure` script, please consider the following
+# when building for NuttX:
+#
+# Use sed to remove optimization flags from NuttX's CFLAGS because
+# Python's configure script requires them in OPT. Having the flags in
+# both places causes a conflict.
+#
+# Also, use -O0 for OPT because -Os is causing problems in
+# Python/Modules/getpath.c (issue will be filed soon to track this
+# problem).
+
+$(TARGETBUILD)/Makefile: $(HOSTPYTHON)
+       $(Q) mkdir -p $(TARGETBUILD)/Modules
+       $(Q) mkdir -p $(TARGETMODULES)/python$(CPYTHON_VERSION_MINOR)
+       $(Q) ( cp Setup.local $(TARGETBUILD)/Modules/Setup.local )
+       $(Q) ( \
+                       cd $(TARGETBUILD); \
+                       CFLAGS="$(CFLAGS)"; \
+                       ARCH=$(CONFIG_ARCH); \
+                       ARCH_CHIP=$(CONFIG_ARCH_CHIP); \
+                       ARCH="$${ARCH//-/}"; \
+                       ARCH_CHIP="$${ARCH_CHIP//-/}"; \
+                       CFLAGS="$$(echo "$${CFLAGS}" | sed 's/-Os //')" \
+                       CC="$(CC)" \
+                       CXX="$(CXX)" \
+                       AR="$(AR)" \
+                       ARFLAGS=" " \
+                       MACHDEP="$(MACHDEP)" \
+                       OPT="-g -O0 -Wall" \
+                       CONFIG_SITE="$(CONFIG_SITE)" \
+                       $(CPYTHON_PATH)/configure \
+                        --prefix=${TARGETINSTALL} \
+                        --disable-shared \
+                        --host=$${ARCH}-$${ARCH_CHIP}-nuttx \
+                        --build=$(shell $(CPYTHON_PATH)/config.guess) \
+                        --with-build-python=${HOSTPYTHON} \
+                        --without-mimalloc \
+                        --without-pymalloc \
+                        --disable-test-modules \
+               )
+
+$(TARGETLIBPYTHON): $(TARGETBUILD)/Makefile
+       $(MAKE) -C $(TARGETBUILD) regen-frozen
+       $(MAKE) -C $(TARGETBUILD) libpython$(CPYTHON_VERSION_MINOR).a 
wasm_stdlib
+       $(Q) ( cp $(TARGETBUILD)/libpython$(CPYTHON_VERSION_MINOR).a 
$(TARGETLIBPYTHON) )
+       $(Q) $(UNPACK) $(TARGETMODULESPACK) -d 
$(TARGETMODULES)/python$(CPYTHON_VERSION_MINOR)
+
+CFLAGS += ${INCDIR_PREFIX}$(CPYTHON_PATH)$(DELIM)Include
+CFLAGS += ${INCDIR_PREFIX}$(CPYTHON_PATH)$(DELIM)Test
+CFLAGS += ${INCDIR_PREFIX}$(CPYTHON_PATH)$(DELIM)Include$(DELIM)internal
+CFLAGS += ${INCDIR_PREFIX}$(APPDIR)$(DELIM)system
+CFLAGS += ${INCDIR_PREFIX}$(APPDIR)$(DELIM)system$(DELIM)zlib$(DELIM)zlib
+CFLAGS += ${INCDIR_PREFIX}$(TARGETBUILD)
+
+MODULE    = $(CONFIG_INTERPRETER_CPYTHON)
+
+PROGNAME  += $(CONFIG_INTERPRETER_CPYTHON_PROGNAME)
+PRIORITY  += $(CONFIG_INTERPRETER_CPYTHON_PRIORITY)
+STACKSIZE += $(CONFIG_INTERPRETER_CPYTHON_STACKSIZE)
+
+MAINSRC += python.c
+
+PROGNAME  += $(CONFIG_INTERPRETER_CPYTHON_MOUNT_MODULES_PROGNAME)
+PRIORITY  += $(CONFIG_INTERPRETER_CPYTHON_MOUNT_MODULES_PRIORITY)
+STACKSIZE += $(CONFIG_INTERPRETER_CPYTHON_MOUNT_MODULES_STACKSIZE)
+
+MAINSRC += mount_modules.c
+
+checkgenromfs:
+       @genromfs -h 1>/dev/null 2>&1 || { \
+ echo "Host executable genromfs not available in PATH"; \
+ echo "You may need to download in from https://romfs.sourceforge.net/";; \
+ exit 1; \
+       }
+
+romfs_cpython_modules.img : $(TARGETLIBPYTHON) checkgenromfs
+       @genromfs -f $@ -d $(TARGETMODULES) -V "ROMFS_Test" || { echo "genromfs 
failed" ; exit 1 ; }
+
+romfs_cpython_modules.h : romfs_cpython_modules.img
+       @xxd -i $< >$@ || { echo "xxd of $< failed" ; exit 1 ; }
+
+context:: $(CPYTHON_UNPACKNAME)
+
+depend:: romfs_cpython_modules.h
+
+distclean::
+       $(call DELDIR, $(BUILDIR))
+       $(call DELDIR, $(INSTALLDIR))
+       $(call DELDIR, $(CPYTHON_UNPACKNAME))
+       $(call DELFILE, $(CPYTHON_ZIP))
+       $(call DELFILE, romfs_cpython_modules.img)
+       $(call DELFILE, romfs_cpython_modules.h)
+
+include $(APPDIR)/Application.mk
diff --git a/interpreters/python/Setup.local b/interpreters/python/Setup.local
new file mode 100644
index 000000000..beca9d666
--- /dev/null
+++ b/interpreters/python/Setup.local
@@ -0,0 +1,50 @@
+# This file gets copied into the Modules/ folder when building
+# newlib configurations which do not support dynamic library
+# loading.
+
+*disabled*
+_asyncio
+_blake2
+_bz2
+_codecs_cn
+_codecs_hk
+_codecs_iso2022
+_codecs_jp
+_codecs_kr
+_codecs_tw
+_ctypes
+_decimal
+_elementtree
+_hashlib
+_heapq
+_interpchannels
+_interpqueues
+_lsprof
+_lzma
+_md5
+_multibytecodec
+_sha1
+_sha2
+_sha2
+_sha3
+_sha3
+_socket
+_sqlite3
+_ssl
+_statistics
+_testbuffer
+_testcapi
+_testclinic
+_testclinic_limited
+_testexternalinspection
+_testinternalcapi
+_testlimitedcapi
+_uuid
+_xxtestfuzz
+_zoneinfo
+mmap
+pwd
+pyexpat
+readline
+resource
+xxsubtype
diff --git a/interpreters/python/config.site b/interpreters/python/config.site
new file mode 100644
index 000000000..d806ba564
--- /dev/null
+++ b/interpreters/python/config.site
@@ -0,0 +1,21 @@
+export ac_cv_file__dev_ptmx="no"
+export ac_cv_file__dev_ptc="no"
+export ac_cv_buggy_getaddrinfo="no"
+export ac_cv_func_getaddrinfo="yes"
+export ac_cv_pthread_is_default="yes"
+export ac_cv_func_acosh="yes"
+export ac_cv_func_asinh="yes"
+export ac_cv_func_atanh="yes"
+export ac_cv_func_erf="yes"
+export ac_cv_func_erfc="yes"
+export ac_cv_func_expm1="yes"
+export ac_cv_func_log1p="yes"
+export ac_cv_func_log2="yes"
+export ac_cv_func_clock_gettime="yes"
+export ac_cv_header_sys_syscall_h="no"
+export ac_cv_func_timegm="yes"
+export ac_cv_func_clock="yes"
+export ac_cv_func_fork="yes"
+export ac_cv_func_waitpid="yes"
+export ac_cv_func_pipe="yes"
+export MODULE_BUILDTYPE="static"
diff --git a/interpreters/python/mount_modules.c 
b/interpreters/python/mount_modules.c
new file mode 100644
index 000000000..89a7bc377
--- /dev/null
+++ b/interpreters/python/mount_modules.c
@@ -0,0 +1,132 @@
+/****************************************************************************
+ * apps/interpreters/python/mount_modules.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sys/types.h>
+#include <sys/mount.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <sys/boardctl.h>
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <errno.h>
+
+#include <nuttx/drivers/ramdisk.h>
+
+#include "romfs_cpython_modules.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Configuration settings */
+
+#ifndef CONFIG_CPYTHON_ROMFS_RAMDEVNO
+#  define CONFIG_CPYTHON_ROMFS_RAMDEVNO 1
+#endif
+
+#ifndef CONFIG_CPYTHON_ROMFS_SECTORSIZE
+#  define CONFIG_CPYTHON_ROMFS_SECTORSIZE 64
+#endif
+
+#ifndef CONFIG_CPYTHON_ROMFS_MOUNTPOINT
+#  define CONFIG_CPYTHON_ROMFS_MOUNTPOINT "/usr/local/lib/"
+#endif
+
+#ifdef CONFIG_DISABLE_MOUNTPOINT
+#  error "Mountpoint support is disabled"
+#endif
+
+#ifndef CONFIG_FS_ROMFS
+#  error "ROMFS support not enabled"
+#endif
+
+#define NSECTORS(b)        
(((b)+CONFIG_CPYTHON_ROMFS_SECTORSIZE-1)/CONFIG_CPYTHON_ROMFS_SECTORSIZE)
+#define STR_RAMDEVNO(m)    #m
+#define MKMOUNT_DEVNAME(m) "/dev/ram" STR_RAMDEVNO(m)
+#define MOUNT_DEVNAME      MKMOUNT_DEVNAME(CONFIG_CPYTHON_ROMFS_RAMDEVNO)
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: mount_modules
+ ****************************************************************************/
+
+int main(int argc, FAR char *argv[])
+{
+  int ret;
+  struct boardioc_romdisk_s desc;
+
+  /* Create a RAM disk for the test */
+
+  desc.minor    = CONFIG_CPYTHON_ROMFS_RAMDEVNO;            /* Minor device 
number of the ROM disk. */
+  desc.nsectors = NSECTORS(romfs_cpython_modules_img_len);  /* The number of 
sectors in the ROM disk */
+  desc.sectsize = CONFIG_CPYTHON_ROMFS_SECTORSIZE;          /* The size of one 
sector in bytes */
+  desc.image    = (FAR uint8_t *)romfs_cpython_modules_img; /* File system 
image */
+
+  ret = boardctl(BOARDIOC_ROMDISK, (uintptr_t)&desc);
+
+  if (ret < 0)
+    {
+      printf("ERROR: Failed to create RAM disk: %s\n", strerror(errno));
+      return 1;
+    }
+
+  /* Mount the test file system */
+
+  printf("Mounting ROMFS filesystem at target=%s with source=%s\n",
+         CONFIG_CPYTHON_ROMFS_MOUNTPOINT, MOUNT_DEVNAME);
+
+  ret = mount(MOUNT_DEVNAME, CONFIG_CPYTHON_ROMFS_MOUNTPOINT, "romfs",
+              MS_RDONLY, NULL);
+  if (ret < 0)
+    {
+      printf("ERROR: Mount failed: %s\n", strerror(errno));
+      return 1;
+    }
+
+  return 0;
+}
diff --git 
a/interpreters/python/patch/0001-workaround-newlib-resource.h-limitations.patch 
b/interpreters/python/patch/0001-workaround-newlib-resource.h-limitations.patch
new file mode 100644
index 000000000..dfb9d437a
--- /dev/null
+++ 
b/interpreters/python/patch/0001-workaround-newlib-resource.h-limitations.patch
@@ -0,0 +1,29 @@
+From b2ac42cefa3747c7f7a9066fceed834286e829af Mon Sep 17 00:00:00 2001
+From: Ivan Grokhotkov <[email protected]>
+Date: Tue, 22 Oct 2024 23:58:17 +0200
+Subject: [PATCH 01/10] workaround newlib resource.h limitations
+
+configure script checks if resource.h is available but doesn't check
+if it defines all the necessary functions.
+
+Temporary workaround until these functions are added to IDF.
+---
+ Modules/faulthandler.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/Modules/faulthandler.c b/Modules/faulthandler.c
+index b62362f2777..327d883f94e 100644
+--- a/Modules/faulthandler.c
++++ b/Modules/faulthandler.c
+@@ -968,7 +968,7 @@ faulthandler_suppress_crash_report(void)
+     SetErrorMode(mode | SEM_NOGPFAULTERRORBOX);
+ #endif
+ 
+-#ifdef HAVE_SYS_RESOURCE_H
++#if 0 && defined(HAVE_SYS_RESOURCE_H)
+     struct rlimit rl;
+ 
+     /* Disable creation of core dump */
+-- 
+2.46.1
+
diff --git 
a/interpreters/python/patch/0002-fix-various-uint32_t-unsigned-int-type-mismatch-issu.patch
 
b/interpreters/python/patch/0002-fix-various-uint32_t-unsigned-int-type-mismatch-issu.patch
new file mode 100644
index 000000000..0bf12755a
--- /dev/null
+++ 
b/interpreters/python/patch/0002-fix-various-uint32_t-unsigned-int-type-mismatch-issu.patch
@@ -0,0 +1,151 @@
+From 036b39478c2419af1e0a64763b9ac741cf886387 Mon Sep 17 00:00:00 2001
+From: Ivan Grokhotkov <[email protected]>
+Date: Wed, 23 Oct 2024 16:48:49 +0200
+Subject: [PATCH 02/10] fix various uint32_t/'unsigned int' type mismatch
+ issues
+
+In a few places existing code assumes that uint32_t == unsigned int.
+Since in Xtensa and RISC-V bare metal toolchains uint32_t is instead
+'unsigned long', the original code fails to build.
+---
+ Modules/zlibmodule.c | 28 ++++++++++++++--------------
+ Objects/typeobject.c |  2 +-
+ 2 files changed, 15 insertions(+), 15 deletions(-)
+
+diff --git a/Modules/zlibmodule.c b/Modules/zlibmodule.c
+index b115f67f228..034a9420b16 100644
+--- a/Modules/zlibmodule.c
++++ b/Modules/zlibmodule.c
+@@ -28,13 +28,13 @@
+    On failure, return -1 */
+ static inline Py_ssize_t
+ OutputBuffer_InitAndGrow(_BlocksOutputBuffer *buffer, Py_ssize_t max_length,
+-                         Bytef **next_out, uint32_t *avail_out)
++                         Bytef **next_out, unsigned int *avail_out)
+ {
+     Py_ssize_t allocated;
+ 
+     allocated = _BlocksOutputBuffer_InitAndGrow(
+                     buffer, max_length, (void**) next_out);
+-    *avail_out = (uint32_t) allocated;
++    *avail_out = (unsigned) allocated;
+     return allocated;
+ }
+ 
+@@ -42,24 +42,24 @@ OutputBuffer_InitAndGrow(_BlocksOutputBuffer *buffer, 
Py_ssize_t max_length,
+    On failure, return -1 */
+ static inline Py_ssize_t
+ OutputBuffer_Grow(_BlocksOutputBuffer *buffer,
+-                  Bytef **next_out, uint32_t *avail_out)
++                  Bytef **next_out, unsigned int *avail_out)
+ {
+     Py_ssize_t allocated;
+ 
+     allocated = _BlocksOutputBuffer_Grow(
+                     buffer, (void**) next_out, (Py_ssize_t) *avail_out);
+-    *avail_out = (uint32_t) allocated;
++    *avail_out = (unsigned int) allocated;
+     return allocated;
+ }
+ 
+ static inline Py_ssize_t
+-OutputBuffer_GetDataSize(_BlocksOutputBuffer *buffer, uint32_t avail_out)
++OutputBuffer_GetDataSize(_BlocksOutputBuffer *buffer, unsigned int avail_out)
+ {
+     return _BlocksOutputBuffer_GetDataSize(buffer, (Py_ssize_t) avail_out);
+ }
+ 
+ static inline PyObject *
+-OutputBuffer_Finish(_BlocksOutputBuffer *buffer, uint32_t avail_out)
++OutputBuffer_Finish(_BlocksOutputBuffer *buffer, unsigned int avail_out)
+ {
+     return _BlocksOutputBuffer_Finish(buffer, (Py_ssize_t) avail_out);
+ }
+@@ -97,7 +97,7 @@ typedef struct {
+ static inline Py_ssize_t
+ OutputBuffer_WindowInitWithSize(_BlocksOutputBuffer *buffer, _Uint32Window 
*window,
+                                 Py_ssize_t init_size,
+-                                Bytef **next_out, uint32_t *avail_out)
++                                Bytef **next_out, unsigned int *avail_out)
+ {
+     Py_ssize_t allocated = _BlocksOutputBuffer_InitWithSize(
+                                buffer, init_size, (void**) next_out);
+@@ -105,7 +105,7 @@ OutputBuffer_WindowInitWithSize(_BlocksOutputBuffer 
*buffer, _Uint32Window *wind
+     if (allocated >= 0) {
+         // the UINT32_MAX sliding window
+         Py_ssize_t window_size = Py_MIN((size_t)allocated, UINT32_MAX);
+-        *avail_out = (uint32_t) window_size;
++        *avail_out = (unsigned int) window_size;
+ 
+         window->left_bytes = allocated - window_size;
+         window->next_posi = *next_out + window_size;
+@@ -119,7 +119,7 @@ OutputBuffer_WindowInitWithSize(_BlocksOutputBuffer 
*buffer, _Uint32Window *wind
+    On failure, return value < 0 */
+ static inline Py_ssize_t
+ OutputBuffer_WindowGrow(_BlocksOutputBuffer *buffer, _Uint32Window *window,
+-                        Bytef **next_out, uint32_t *avail_out)
++                        Bytef **next_out, unsigned int *avail_out)
+ {
+     Py_ssize_t allocated;
+ 
+@@ -136,7 +136,7 @@ OutputBuffer_WindowGrow(_BlocksOutputBuffer *buffer, 
_Uint32Window *window,
+         Py_ssize_t window_size = Py_MIN((size_t)window->left_bytes, 
UINT32_MAX);
+ 
+         *next_out = window->next_posi;
+-        *avail_out = (uint32_t) window_size;
++        *avail_out = (unsigned int) window_size;
+ 
+         window->left_bytes -= window_size;
+         window->next_posi += window_size;
+@@ -148,7 +148,7 @@ OutputBuffer_WindowGrow(_BlocksOutputBuffer *buffer, 
_Uint32Window *window,
+     // only the first block may > UINT32_MAX
+     allocated = _BlocksOutputBuffer_Grow(
+                     buffer, (void**) next_out, (Py_ssize_t) *avail_out);
+-    *avail_out = (uint32_t) allocated;
++    *avail_out = (unsigned int) allocated;
+     return allocated;
+ }
+ 
+@@ -158,7 +158,7 @@ OutputBuffer_WindowGrow(_BlocksOutputBuffer *buffer, 
_Uint32Window *window,
+    On failure, return NULL */
+ static inline PyObject *
+ OutputBuffer_WindowFinish(_BlocksOutputBuffer *buffer, _Uint32Window *window,
+-                          uint32_t avail_out)
++                          unsigned avail_out)
+ {
+     Py_ssize_t real_avail_out = (Py_ssize_t) avail_out + window->left_bytes;
+     return _BlocksOutputBuffer_Finish(buffer, real_avail_out);
+@@ -1398,7 +1398,7 @@ set_inflate_zdict_ZlibDecompressor(zlibstate *state, 
ZlibDecompressor *self)
+ }
+ 
+ static Py_ssize_t
+-arrange_output_buffer_with_maximum(uint32_t *avail_out,
++arrange_output_buffer_with_maximum(unsigned int *avail_out,
+                                    uint8_t **next_out,
+                                    PyObject **buffer,
+                                    Py_ssize_t length,
+@@ -1430,7 +1430,7 @@ arrange_output_buffer_with_maximum(uint32_t *avail_out,
+         }
+     }
+ 
+-    *avail_out = (uint32_t)Py_MIN((size_t)(length - occupied), UINT32_MAX);
++    *avail_out = (unsigned)Py_MIN((size_t)(length - occupied), UINT32_MAX);
+     *next_out = (uint8_t *)PyBytes_AS_STRING(*buffer) + occupied;
+ 
+     return length;
+diff --git a/Objects/typeobject.c b/Objects/typeobject.c
+index c911c302003..9c640e0ab65 100644
+--- a/Objects/typeobject.c
++++ b/Objects/typeobject.c
+@@ -5140,7 +5140,7 @@ is_dunder_name(PyObject *name)
+ static PyObject *
+ update_cache(struct type_cache_entry *entry, PyObject *name, unsigned int 
version_tag, PyObject *value)
+ {
+-    _Py_atomic_store_uint32_relaxed(&entry->version, version_tag);
++    _Py_atomic_store_uint32_relaxed((uint32_t*) &entry->version, version_tag);
+     _Py_atomic_store_ptr_relaxed(&entry->value, value); /* borrowed */
+     assert(_PyASCIIObject_CAST(name)->hash != -1);
+     OBJECT_STAT_INC_COND(type_cache_collisions, entry->name != Py_None && 
entry->name != name);
+-- 
+2.46.1
+
diff --git 
a/interpreters/python/patch/0003-reuse-wasm_assets.py-for-generating-an-archive-of-py.patch
 
b/interpreters/python/patch/0003-reuse-wasm_assets.py-for-generating-an-archive-of-py.patch
new file mode 100644
index 000000000..f8e03a2cf
--- /dev/null
+++ 
b/interpreters/python/patch/0003-reuse-wasm_assets.py-for-generating-an-archive-of-py.patch
@@ -0,0 +1,42 @@
+From 4af7a9b726ca2c8ac330b51f98acf0a103f6fa71 Mon Sep 17 00:00:00 2001
+From: Ivan Grokhotkov <[email protected]>
+Date: Wed, 23 Oct 2024 16:54:39 +0200
+Subject: [PATCH 03/10] reuse wasm_assets.py for generating an archive of
+ python lib dir
+
+wasm_assets.py is a useful script to prepare the smallest possible
+package of pre-compiled python stdlib modules. There is very little
+wasm-specific there.
+
+This patch adds nuttx to the supported OS list in the script, as well
+as fixes what I think is a bug in path calculation.
+
+Co-authored-by: Tiago Medicci Serrano <[email protected]>
+---
+ Tools/wasm/wasm_assets.py | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/Tools/wasm/wasm_assets.py b/Tools/wasm/wasm_assets.py
+index ffa5e303412..381d4819c39 100755
+--- a/Tools/wasm/wasm_assets.py
++++ b/Tools/wasm/wasm_assets.py
+@@ -99,6 +99,7 @@
+     "_sysconfigdata__emscripten_wasm32-emscripten",
+     "_sysconfigdata__wasi_wasm32-wasi",
+     "_sysconfigdata__wasi_wasm64-wasi",
++    "_sysconfigdata__nuttx_"
+ )
+ 
+ 
+@@ -203,7 +204,7 @@ def main() -> None:
+     relative_prefix = args.prefix.relative_to(pathlib.Path("/"))
+     args.srcdir = SRCDIR
+     args.srcdir_lib = SRCDIR_LIB
+-    args.wasm_root = args.buildroot / relative_prefix
++    args.wasm_root = args.buildroot #/ relative_prefix
+     args.wasm_stdlib_zip = args.wasm_root / WASM_STDLIB_ZIP
+     args.wasm_stdlib = args.wasm_root / WASM_STDLIB
+     args.wasm_dynload = args.wasm_root / WASM_DYNLOAD
+-- 
+2.46.1
+
diff --git 
a/interpreters/python/patch/0004-recognize-nuttx-as-a-supported-OS.patch 
b/interpreters/python/patch/0004-recognize-nuttx-as-a-supported-OS.patch
new file mode 100644
index 000000000..6d8531ce6
--- /dev/null
+++ b/interpreters/python/patch/0004-recognize-nuttx-as-a-supported-OS.patch
@@ -0,0 +1,60 @@
+From 1bb8d824a4b4e4b38c3541b7c26c5d71f0970266 Mon Sep 17 00:00:00 2001
+From: Ivan Grokhotkov <[email protected]>
+Date: Wed, 23 Oct 2024 16:55:53 +0200
+Subject: [PATCH 04/10] recognize *-*-nuttx as a supported OS
+
+cpython's configure script bails out when cross-compiling for an
+unknown OS, so we have to add "nuttx" to the list, even though it
+is not used almost anywhere else.
+
+Co-authored-by: Tiago Medicci Serrano <[email protected]>
+---
+ config.sub   | 2 +-
+ configure    | 3 +++
+ configure.ac | 3 +++
+ 3 files changed, 7 insertions(+), 1 deletion(-)
+
+diff --git a/config.sub b/config.sub
+index 1bb6a05dc11..2a87d3e0ddb 100755
+--- a/config.sub
++++ b/config.sub
+@@ -1769,7 +1769,7 @@ case $os in
+            | onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \
+            | midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi* \
+            | nsk* | powerunix* | genode* | zvmoe* | qnx* | emx* | zephyr* \
+-           | fiwix* | mlibc* | cos* | mbr* | ironclad* )
++           | fiwix* | mlibc* | cos* | mbr* | ironclad* | nuttx* )
+               ;;
+       # This one is extra strict with allowed versions
+       sco3.2v2 | sco3.2v[4-9]* | sco5v6*)
+diff --git a/configure b/configure
+index 7cdd386c387..6da5e9f3832 100755
+--- a/configure
++++ b/configure
+@@ -4527,6 +4527,9 @@ printf "%s\n" "$IPHONEOS_DEPLOYMENT_TARGET" >&6; }
+       wasm32-*-* | wasm64-*-*)
+               _host_ident=$host_cpu
+               ;;
++  *-*-nuttx*)
++    _host_ident=$host_cpu
++    ;;
+       *)
+               # for now, limit cross builds to known configurations
+               MACHDEP="unknown"
+diff --git a/configure.ac b/configure.ac
+index 24e28a1e2de..80d6738fab5 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -777,6 +777,9 @@ if test "$cross_compiling" = yes; then
+       wasm32-*-* | wasm64-*-*)
+               _host_ident=$host_cpu
+               ;;
++  *-*-nuttx*)
++    _host_ident=$host_cpu
++    ;;
+       *)
+               # for now, limit cross builds to known configurations
+               MACHDEP="unknown"
+-- 
+2.46.1
+
diff --git 
a/interpreters/python/patch/0005-gh-122907-Fix-Builds-Without-HAVE_DYNAMIC_LOADING-Se.patch
 
b/interpreters/python/patch/0005-gh-122907-Fix-Builds-Without-HAVE_DYNAMIC_LOADING-Se.patch
new file mode 100644
index 000000000..cf25d88c2
--- /dev/null
+++ 
b/interpreters/python/patch/0005-gh-122907-Fix-Builds-Without-HAVE_DYNAMIC_LOADING-Se.patch
@@ -0,0 +1,189 @@
+From cd8af3cbc9881e5a4a7c0644c8844478c8d0245d Mon Sep 17 00:00:00 2001
+From: Eric Snow <[email protected]>
+Date: Tue, 13 Aug 2024 14:44:57 -0600
+Subject: [PATCH 05/10] gh-122907: Fix Builds Without HAVE_DYNAMIC_LOADING Set
+ (gh-122952)
+
+As of 529a160 (gh-118204), building with HAVE_DYNAMIC_LOADING stopped working. 
 This is a minimal fix just to get builds working again.  There are actually a 
number of long-standing deficiencies with HAVE_DYNAMIC_LOADING builds that need 
to be resolved separately.
+(cherry picked from commit ee1b8ce26e700350e47a5f65201097121c41912e)
+
+Co-authored-by: Eric Snow <[email protected]>
+---
+ Include/internal/pycore_importdl.h               |  4 ++++
+ Lib/importlib/_bootstrap_external.py             | 16 ++++++++--------
+ ...024-08-12-11-19-37.gh-issue-122907.q68096.rst |  3 +++
+ Python/importdl.c                                | 12 ++++++++----
+ Tools/build/check_extension_modules.py           |  9 +++++++++
+ 5 files changed, 32 insertions(+), 12 deletions(-)
+ create mode 100644 
Misc/NEWS.d/next/Core_and_Builtins/2024-08-12-11-19-37.gh-issue-122907.q68096.rst
+
+diff --git a/Include/internal/pycore_importdl.h 
b/Include/internal/pycore_importdl.h
+index e5f222b371a..525a16f6b97 100644
+--- a/Include/internal/pycore_importdl.h
++++ b/Include/internal/pycore_importdl.h
+@@ -56,9 +56,11 @@ extern int _Py_ext_module_loader_info_init_for_core(
+ extern int _Py_ext_module_loader_info_init_for_builtin(
+     struct _Py_ext_module_loader_info *p_info,
+     PyObject *name);
++#ifdef HAVE_DYNAMIC_LOADING
+ extern int _Py_ext_module_loader_info_init_from_spec(
+     struct _Py_ext_module_loader_info *info,
+     PyObject *spec);
++#endif
+ 
+ /* The result from running an extension module's init function. */
+ struct _Py_ext_module_loader_result {
+@@ -87,9 +89,11 @@ extern void _Py_ext_module_loader_result_apply_error(
+ 
+ /* The module init function. */
+ typedef PyObject *(*PyModInitFunction)(void);
++#ifdef HAVE_DYNAMIC_LOADING
+ extern PyModInitFunction _PyImport_GetModInitFunc(
+     struct _Py_ext_module_loader_info *info,
+     FILE *fp);
++#endif
+ extern int _PyImport_RunModInitFunc(
+     PyModInitFunction p0,
+     struct _Py_ext_module_loader_info *info,
+diff --git a/Lib/importlib/_bootstrap_external.py 
b/Lib/importlib/_bootstrap_external.py
+index 7742855e8b2..d8c61c92558 100644
+--- a/Lib/importlib/_bootstrap_external.py
++++ b/Lib/importlib/_bootstrap_external.py
+@@ -1793,14 +1793,14 @@ def _get_supported_file_loaders():
+ 
+     Each item is a tuple (loader, suffixes).
+     """
+-    if sys.platform in {"ios", "tvos", "watchos"}:
+-        extension_loaders = [(AppleFrameworkLoader, [
+-            suffix.replace(".so", ".fwork")
+-            for suffix in _imp.extension_suffixes()
+-        ])]
+-    else:
+-        extension_loaders = []
+-    extension_loaders.append((ExtensionFileLoader, _imp.extension_suffixes()))
++    extension_loaders = []
++    if hasattr(_imp, 'create_dynamic'):
++        if sys.platform in {"ios", "tvos", "watchos"}:
++            extension_loaders = [(AppleFrameworkLoader, [
++                suffix.replace(".so", ".fwork")
++                for suffix in _imp.extension_suffixes()
++            ])]
++        extension_loaders.append((ExtensionFileLoader, 
_imp.extension_suffixes()))
+     source = SourceFileLoader, SOURCE_SUFFIXES
+     bytecode = SourcelessFileLoader, BYTECODE_SUFFIXES
+     return extension_loaders + [source, bytecode]
+diff --git 
a/Misc/NEWS.d/next/Core_and_Builtins/2024-08-12-11-19-37.gh-issue-122907.q68096.rst
 
b/Misc/NEWS.d/next/Core_and_Builtins/2024-08-12-11-19-37.gh-issue-122907.q68096.rst
+new file mode 100644
+index 00000000000..88c872f4ef4
+--- /dev/null
++++ 
b/Misc/NEWS.d/next/Core_and_Builtins/2024-08-12-11-19-37.gh-issue-122907.q68096.rst
+@@ -0,0 +1,3 @@
++Building with ``HAVE_DYNAMIC_LOADING`` now works as well as it did in 3.12.
++Existing deficiences will be addressed separately.
++(See https://github.com/python/cpython/issues/122950.)
+diff --git a/Python/importdl.c b/Python/importdl.c
+index 7c42d37283c..b1a6fcc8223 100644
+--- a/Python/importdl.c
++++ b/Python/importdl.c
+@@ -8,6 +8,8 @@
+ #include "pycore_pystate.h"
+ #include "pycore_runtime.h"
+ 
++#include "pycore_importdl.h"
++
+ /* ./configure sets HAVE_DYNAMIC_LOADING if dynamic loading of modules is
+    supported on this platform. configure will then compile and link in one
+    of the dynload_*.c files, as appropriate. We will call a function in
+@@ -15,8 +17,6 @@
+ */
+ #ifdef HAVE_DYNAMIC_LOADING
+ 
+-#include "pycore_importdl.h"
+-
+ #ifdef MS_WINDOWS
+ extern dl_funcptr _PyImport_FindSharedFuncptrWindows(const char *prefix,
+                                                      const char *shortname,
+@@ -28,6 +28,8 @@ extern dl_funcptr _PyImport_FindSharedFuncptr(const char 
*prefix,
+                                               const char *pathname, FILE *fp);
+ #endif
+ 
++#endif /* HAVE_DYNAMIC_LOADING */
++
+ 
+ /***********************************/
+ /* module info to use when loading */
+@@ -205,6 +207,7 @@ _Py_ext_module_loader_info_init_for_core(
+     return 0;
+ }
+ 
++#ifdef HAVE_DYNAMIC_LOADING
+ int
+ _Py_ext_module_loader_info_init_from_spec(
+                             struct _Py_ext_module_loader_info *p_info,
+@@ -226,6 +229,7 @@ _Py_ext_module_loader_info_init_from_spec(
+     Py_DECREF(filename);
+     return err;
+ }
++#endif /* HAVE_DYNAMIC_LOADING */
+ 
+ 
+ /********************************/
+@@ -372,6 +376,7 @@ _Py_ext_module_loader_result_apply_error(
+ /* getting/running the module init function */
+ /********************************************/
+ 
++#ifdef HAVE_DYNAMIC_LOADING
+ PyModInitFunction
+ _PyImport_GetModInitFunc(struct _Py_ext_module_loader_info *info,
+                          FILE *fp)
+@@ -406,6 +411,7 @@ _PyImport_GetModInitFunc(struct _Py_ext_module_loader_info 
*info,
+ 
+     return (PyModInitFunction)exportfunc;
+ }
++#endif /* HAVE_DYNAMIC_LOADING */
+ 
+ int
+ _PyImport_RunModInitFunc(PyModInitFunction p0,
+@@ -513,5 +519,3 @@ _PyImport_RunModInitFunc(PyModInitFunction p0,
+     p_res->err = &p_res->_err;
+     return -1;
+ }
+-
+-#endif /* HAVE_DYNAMIC_LOADING */
+diff --git a/Tools/build/check_extension_modules.py 
b/Tools/build/check_extension_modules.py
+index 7de35b499da..66b2a262e11 100644
+--- a/Tools/build/check_extension_modules.py
++++ b/Tools/build/check_extension_modules.py
+@@ -27,6 +27,7 @@
+ import sys
+ import sysconfig
+ import warnings
++import _imp
+ 
+ from importlib._bootstrap import _load as bootstrap_load
+ from importlib.machinery import BuiltinImporter, ExtensionFileLoader, 
ModuleSpec
+@@ -154,6 +155,11 @@ def __init__(self, cross_compiling: bool = False, strict: 
bool = False):
+         self.notavailable = []
+ 
+     def check(self):
++        if not hasattr(_imp, 'create_dynamic'):
++            logger.warning(
++                ('Dynamic extensions not supported '
++                 '(HAVE_DYNAMIC_LOADING not defined)'),
++            )
+         for modinfo in self.modules:
+             logger.debug("Checking '%s' (%s)", modinfo.name, 
self.get_location(modinfo))
+             if modinfo.state == ModuleState.DISABLED:
+@@ -415,6 +421,9 @@ def check_module_import(self, modinfo: ModuleInfo):
+             logger.error("%s failed to import: %s", modinfo.name, e)
+             raise
+         except Exception as e:
++            if not hasattr(_imp, 'create_dynamic'):
++                logger.warning("Dynamic extension '%s' ignored", modinfo.name)
++                return
+             logger.exception("Importing extension '%s' failed!", modinfo.name)
+             raise
+ 
+-- 
+2.46.1
+
diff --git 
a/interpreters/python/patch/0006-change-var-name-to-avoid-conflict-with-nuttx-unused_.patch
 
b/interpreters/python/patch/0006-change-var-name-to-avoid-conflict-with-nuttx-unused_.patch
new file mode 100644
index 000000000..641233bf4
--- /dev/null
+++ 
b/interpreters/python/patch/0006-change-var-name-to-avoid-conflict-with-nuttx-unused_.patch
@@ -0,0 +1,168 @@
+From d424766bff74fb34a80a09c6e2ed8d9b40350bb8 Mon Sep 17 00:00:00 2001
+From: Tiago Medicci <[email protected]>
+Date: Wed, 13 Nov 2024 14:20:36 -0300
+Subject: [PATCH 06/10] change var name to avoid conflict with nuttx
+ unused_data macro
+
+---
+ Modules/zlibmodule.c | 42 +++++++++++++++++++++---------------------
+ 1 file changed, 21 insertions(+), 21 deletions(-)
+
+diff --git a/Modules/zlibmodule.c b/Modules/zlibmodule.c
+index 034a9420b16..595d4ad32e9 100644
+--- a/Modules/zlibmodule.c
++++ b/Modules/zlibmodule.c
+@@ -213,7 +213,7 @@ typedef struct
+ {
+     PyObject_HEAD
+     z_stream zst;
+-    PyObject *unused_data;
++    PyObject *unused_data_var;
+     PyObject *unconsumed_tail;
+     char eof;
+     bool is_initialised;
+@@ -267,8 +267,8 @@ newcompobject(PyTypeObject *type)
+     self->eof = 0;
+     self->is_initialised = 0;
+     self->zdict = NULL;
+-    self->unused_data = PyBytes_FromStringAndSize("", 0);
+-    if (self->unused_data == NULL) {
++    self->unused_data_var = PyBytes_FromStringAndSize("", 0);
++    if (self->unused_data_var == NULL) {
+         Py_DECREF(self);
+         return NULL;
+     }
+@@ -708,7 +708,7 @@ Dealloc(compobject *self)
+ {
+     PyObject *type = (PyObject *)Py_TYPE(self);
+     PyThread_free_lock(self->lock);
+-    Py_XDECREF(self->unused_data);
++    Py_XDECREF(self->unused_data_var);
+     Py_XDECREF(self->unconsumed_tail);
+     Py_XDECREF(self->zdict);
+     PyObject_Free(self);
+@@ -803,15 +803,15 @@ zlib_Compress_compress_impl(compobject *self, 
PyTypeObject *cls,
+ }
+ 
+ /* Helper for objdecompress() and flush(). Saves any unconsumed input data in
+-   self->unused_data or self->unconsumed_tail, as appropriate. */
++   self->unused_data_var or self->unconsumed_tail, as appropriate. */
+ static int
+ save_unconsumed_input(compobject *self, Py_buffer *data, int err)
+ {
+     if (err == Z_STREAM_END) {
+         /* The end of the compressed data has been reached. Store the leftover
+-           input data in self->unused_data. */
++           input data in self->unused_data_var. */
+         if (self->zst.avail_in > 0) {
+-            Py_ssize_t old_size = PyBytes_GET_SIZE(self->unused_data);
++            Py_ssize_t old_size = PyBytes_GET_SIZE(self->unused_data_var);
+             Py_ssize_t new_size, left_size;
+             PyObject *new_data;
+             left_size = (Byte *)data->buf + data->len - self->zst.next_in;
+@@ -824,10 +824,10 @@ save_unconsumed_input(compobject *self, Py_buffer *data, 
int err)
+             if (new_data == NULL)
+                 return -1;
+             memcpy(PyBytes_AS_STRING(new_data),
+-                      PyBytes_AS_STRING(self->unused_data), old_size);
++                      PyBytes_AS_STRING(self->unused_data_var), old_size);
+             memcpy(PyBytes_AS_STRING(new_data) + old_size,
+                       self->zst.next_in, left_size);
+-            Py_SETREF(self->unused_data, new_data);
++            Py_SETREF(self->unused_data_var, new_data);
+             self->zst.avail_in = 0;
+         }
+     }
+@@ -1091,7 +1091,7 @@ zlib_Compress_copy_impl(compobject *self, PyTypeObject 
*cls)
+         zlib_error(state, self->zst, err, "while copying compression object");
+         goto error;
+     }
+-    Py_XSETREF(return_value->unused_data, Py_NewRef(self->unused_data));
++    Py_XSETREF(return_value->unused_data_var, 
Py_NewRef(self->unused_data_var));
+     Py_XSETREF(return_value->unconsumed_tail, 
Py_NewRef(self->unconsumed_tail));
+     Py_XSETREF(return_value->zdict, Py_XNewRef(self->zdict));
+     return_value->eof = self->eof;
+@@ -1176,7 +1176,7 @@ zlib_Decompress_copy_impl(compobject *self, PyTypeObject 
*cls)
+         goto error;
+     }
+ 
+-    Py_XSETREF(return_value->unused_data, Py_NewRef(self->unused_data));
++    Py_XSETREF(return_value->unused_data_var, 
Py_NewRef(self->unused_data_var));
+     Py_XSETREF(return_value->unconsumed_tail, 
Py_NewRef(self->unconsumed_tail));
+     Py_XSETREF(return_value->zdict, Py_XNewRef(self->zdict));
+     return_value->eof = self->eof;
+@@ -1341,7 +1341,7 @@ typedef struct {
+     z_stream zst;
+     PyObject *zdict;
+     PyThread_type_lock lock;
+-    PyObject *unused_data;
++    PyObject *unused_data_var;
+     uint8_t *input_buffer;
+     Py_ssize_t input_buffer_size;
+     /* zst>avail_in is only 32 bit, so we store the true length
+@@ -1367,7 +1367,7 @@ ZlibDecompressor_dealloc(ZlibDecompressor *self)
+         inflateEnd(&self->zst);
+     }
+     PyMem_Free(self->input_buffer);
+-    Py_CLEAR(self->unused_data);
++    Py_CLEAR(self->unused_data_var);
+     Py_CLEAR(self->zdict);
+     PyObject_Free(self);
+     Py_DECREF(type);
+@@ -1602,12 +1602,12 @@ decompress(ZlibDecompressor *self, uint8_t *data,
+         self->needs_input = 0;
+ 
+         if (self->avail_in_real > 0) {
+-            PyObject *unused_data = PyBytes_FromStringAndSize(
++            PyObject *unused_data_var = PyBytes_FromStringAndSize(
+                 (char *)self->zst.next_in, self->avail_in_real);
+-            if (unused_data == NULL) {
++            if (unused_data_var == NULL) {
+                 goto error;
+             }
+-            Py_XSETREF(self->unused_data, unused_data);
++            Py_XSETREF(self->unused_data_var, unused_data_var);
+         }
+     }
+     else if (self->avail_in_real == 0) {
+@@ -1671,7 +1671,7 @@ was less than *max_length* bytes, or because 
*max_length* was negative),
+ 
+ Attempting to decompress data after the end of stream is reached raises an
+ EOFError.  Any data found after the end of the stream is ignored and saved in
+-the unused_data attribute.
++the unused_data_var attribute.
+ [clinic start generated code]*/
+ 
+ static PyObject *
+@@ -1739,8 +1739,8 @@ ZlibDecompressor__new__(PyTypeObject *cls,
+     self->zst.zfree = PyZlib_Free;
+     self->zst.next_in = NULL;
+     self->zst.avail_in = 0;
+-    self->unused_data = PyBytes_FromStringAndSize(NULL, 0);
+-    if (self->unused_data == NULL) {
++    self->unused_data_var = PyBytes_FromStringAndSize(NULL, 0);
++    if (self->unused_data_var == NULL) {
+         Py_CLEAR(self);
+         return NULL;
+     }
+@@ -1806,7 +1806,7 @@ static PyMethodDef ZlibDecompressor_methods[] = {
+ 
+ #define COMP_OFF(x) offsetof(compobject, x)
+ static PyMemberDef Decomp_members[] = {
+-    {"unused_data",     _Py_T_OBJECT, COMP_OFF(unused_data), Py_READONLY},
++    {"unused_data_var",     _Py_T_OBJECT, COMP_OFF(unused_data_var), 
Py_READONLY},
+     {"unconsumed_tail", _Py_T_OBJECT, COMP_OFF(unconsumed_tail), Py_READONLY},
+     {"eof",             Py_T_BOOL,   COMP_OFF(eof), Py_READONLY},
+     {NULL},
+@@ -1824,7 +1824,7 @@ PyDoc_STRVAR(ZlibDecompressor_needs_input_doc,
+ static PyMemberDef ZlibDecompressor_members[] = {
+     {"eof", Py_T_BOOL, offsetof(ZlibDecompressor, eof),
+      Py_READONLY, ZlibDecompressor_eof__doc__},
+-    {"unused_data", Py_T_OBJECT_EX, offsetof(ZlibDecompressor, unused_data),
++    {"unused_data_var", Py_T_OBJECT_EX, offsetof(ZlibDecompressor, 
unused_data_var),
+      Py_READONLY, ZlibDecompressor_unused_data__doc__},
+     {"needs_input", Py_T_BOOL, offsetof(ZlibDecompressor, needs_input), 
Py_READONLY,
+      ZlibDecompressor_needs_input_doc},
+-- 
+2.46.1
+
diff --git a/interpreters/python/patch/0007-undef-atexit_register.patch 
b/interpreters/python/patch/0007-undef-atexit_register.patch
new file mode 100644
index 000000000..266f704a9
--- /dev/null
+++ b/interpreters/python/patch/0007-undef-atexit_register.patch
@@ -0,0 +1,29 @@
+From 1b802bfd159a6a9766ca5834af90f55d54285b4b Mon Sep 17 00:00:00 2001
+From: Tiago Medicci <[email protected]>
+Date: Wed, 13 Nov 2024 14:22:04 -0300
+Subject: [PATCH 07/10] undef atexit_register
+
+Even if not built, nuttx/include/nuttx/atexit.h defines it and this
+causes conflicts.
+---
+ Modules/atexitmodule.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/Modules/atexitmodule.c b/Modules/atexitmodule.c
+index 297a8d74ba3..1fea72fbc99 100644
+--- a/Modules/atexitmodule.c
++++ b/Modules/atexitmodule.c
+@@ -175,6 +175,10 @@ Register a function to be executed upon normal program 
termination\n\
+ \n\
+     func is returned to facilitate usage as a decorator.");
+ 
++#ifdef atexit_register
++#  undef atexit_register
++#endif
++
+ static PyObject *
+ atexit_register(PyObject *module, PyObject *args, PyObject *kwargs)
+ {
+-- 
+2.46.1
+
diff --git a/interpreters/python/patch/0008-declare-struct-timeval.patch 
b/interpreters/python/patch/0008-declare-struct-timeval.patch
new file mode 100644
index 000000000..bb8d3cb43
--- /dev/null
+++ b/interpreters/python/patch/0008-declare-struct-timeval.patch
@@ -0,0 +1,27 @@
+From b40e89c190ec7c6b3b0116a3f7025ab13854398f Mon Sep 17 00:00:00 2001
+From: Tiago Medicci <[email protected]>
+Date: Wed, 13 Nov 2024 14:23:34 -0300
+Subject: [PATCH 08/10] declare struct timeval
+
+Otherwise, build will fail due to redefinition of _PyTime_FromTimeval
+---
+ Include/internal/pycore_time.h | 2 --
+ 1 file changed, 2 deletions(-)
+
+diff --git a/Include/internal/pycore_time.h b/Include/internal/pycore_time.h
+index 205ac5d3781..c30e07f4b4a 100644
+--- a/Include/internal/pycore_time.h
++++ b/Include/internal/pycore_time.h
+@@ -58,9 +58,7 @@ extern "C" {
+ #endif
+ 
+ 
+-#ifdef __clang__
+ struct timeval;
+-#endif
+ 
+ #define _SIZEOF_PYTIME_T 8
+ 
+-- 
+2.46.1
+
diff --git 
a/interpreters/python/patch/0009-include-nuttx-sys-select-header-to-define-FD_SETSIZE.patch
 
b/interpreters/python/patch/0009-include-nuttx-sys-select-header-to-define-FD_SETSIZE.patch
new file mode 100644
index 000000000..b52b76be1
--- /dev/null
+++ 
b/interpreters/python/patch/0009-include-nuttx-sys-select-header-to-define-FD_SETSIZE.patch
@@ -0,0 +1,27 @@
+From 9a32a300c95e0061220d2608a014c7fa39dedab3 Mon Sep 17 00:00:00 2001
+From: Tiago Medicci <[email protected]>
+Date: Thu, 14 Nov 2024 13:44:49 -0300
+Subject: [PATCH 09/10] include nuttx sys/select header to define FD_SETSIZE
+
+---
+ Modules/selectmodule.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/Modules/selectmodule.c b/Modules/selectmodule.c
+index 5bd9b7732a4..e9fab839122 100644
+--- a/Modules/selectmodule.c
++++ b/Modules/selectmodule.c
+@@ -63,6 +63,10 @@ extern void bzero(void *, int);
+ #include <sys/types.h>
+ #endif
+ 
++#ifdef HAVE_SYS_SELECT_H
++#include <sys/select.h>
++#endif
++
+ #ifdef MS_WINDOWS
+ #  ifndef WIN32_LEAN_AND_MEAN
+ #    define WIN32_LEAN_AND_MEAN
+-- 
+2.46.1
+
diff --git 
a/interpreters/python/patch/0010-check-for-the-d_ino-member-of-the-structure-dirent.patch
 
b/interpreters/python/patch/0010-check-for-the-d_ino-member-of-the-structure-dirent.patch
new file mode 100644
index 000000000..d65b1f287
--- /dev/null
+++ 
b/interpreters/python/patch/0010-check-for-the-d_ino-member-of-the-structure-dirent.patch
@@ -0,0 +1,173 @@
+From 4f6a1db85c56df378dc3856ed95a0a7342f44d89 Mon Sep 17 00:00:00 2001
+From: Tiago Medicci <[email protected]>
+Date: Tue, 3 Dec 2024 17:18:50 -0300
+Subject: [PATCH 10/10] check for the d_ino member of the structure dirent
+
+---
+ Modules/posixmodule.c | 18 ++++++++++++++++--
+ configure             | 43 +++++++++++++++++++++++++++++++++++++++++++
+ configure.ac          |  5 +++++
+ pyconfig.h.in         |  3 +++
+ 4 files changed, 67 insertions(+), 2 deletions(-)
+
+diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c
+index 51e34b5f4b7..2aa507aa942 100644
+--- a/Modules/posixmodule.c
++++ b/Modules/posixmodule.c
+@@ -15522,7 +15522,9 @@ typedef struct {
+ #ifdef HAVE_DIRENT_D_TYPE
+     unsigned char d_type;
+ #endif
++#ifdef HAVE_DIRENT_D_INO
+     ino_t d_ino;
++#endif
+     int dir_fd;
+ #endif
+ } DirEntry;
+@@ -15821,6 +15823,7 @@ os.DirEntry.inode
+ Return inode of the entry; cached per entry.
+ [clinic start generated code]*/
+ 
++#ifdef HAVE_DIRENT_D_INO
+ static PyObject *
+ os_DirEntry_inode_impl(DirEntry *self)
+ /*[clinic end generated code: output=156bb3a72162440e 
input=3ee7b872ae8649f0]*/
+@@ -15856,6 +15859,7 @@ os_DirEntry_inode_impl(DirEntry *self)
+     return PyLong_FromUnsignedLongLong(self->d_ino);
+ #endif
+ }
++#endif
+ 
+ static PyObject *
+ DirEntry_repr(DirEntry *self)
+@@ -15892,7 +15896,9 @@ static PyMethodDef DirEntry_methods[] = {
+     OS_DIRENTRY_IS_SYMLINK_METHODDEF
+     OS_DIRENTRY_IS_JUNCTION_METHODDEF
+     OS_DIRENTRY_STAT_METHODDEF
++#ifdef HAVE_DIRENT_D_INO
+     OS_DIRENTRY_INODE_METHODDEF
++#endif
+     OS_DIRENTRY___FSPATH___METHODDEF
+     {"__class_getitem__",       Py_GenericAlias,
+     METH_O|METH_CLASS,          PyDoc_STR("See PEP 585")},
+@@ -16043,7 +16049,10 @@ join_path_filename(const char *path_narrow, const 
char* filename, Py_ssize_t fil
+ 
+ static PyObject *
+ DirEntry_from_posix_info(PyObject *module, path_t *path, const char *name,
+-                         Py_ssize_t name_len, ino_t d_ino
++                         Py_ssize_t name_len
++#ifdef HAVE_DIRENT_D_INO
++                         , ino_t d_ino
++#endif
+ #ifdef HAVE_DIRENT_D_TYPE
+                          , unsigned char d_type
+ #endif
+@@ -16095,7 +16104,9 @@ DirEntry_from_posix_info(PyObject *module, path_t 
*path, const char *name,
+ #ifdef HAVE_DIRENT_D_TYPE
+     entry->d_type = d_type;
+ #endif
++#ifdef HAVE_DIRENT_D_INO
+     entry->d_ino = d_ino;
++#endif
+ 
+     return (PyObject *)entry;
+ 
+@@ -16248,7 +16259,10 @@ ScandirIterator_iternext(ScandirIterator *iterator)
+             PyObject *module = PyType_GetModule(Py_TYPE(iterator));
+             entry = DirEntry_from_posix_info(module,
+                                              &iterator->path, direntp->d_name,
+-                                             name_len, direntp->d_ino
++                                             name_len
++#ifdef HAVE_DIRENT_D_INO
++                                             , direntp->d_ino
++#endif
+ #ifdef HAVE_DIRENT_D_TYPE
+                                              , direntp->d_type
+ #endif
+diff --git a/configure b/configure
+index 6da5e9f3832..c89beb7ef6a 100755
+--- a/configure
++++ b/configure
+@@ -27746,6 +27746,49 @@ then :
+ printf "%s\n" "#define HAVE_DIRENT_D_TYPE 1" >>confdefs.h
+ 
+ 
++fi
++
++# check if the dirent structure of a d_ino is defined
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if the dirent 
structure of a d_ino field" >&5
++printf %s "checking if the dirent structure of a d_ino field... " >&6; }
++if test ${ac_cv_dirent_d_ino+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++
++cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h.  */
++
++
++    #include <dirent.h>
++
++    int main(void) {
++      struct dirent entry;
++      return entry.d_ino == 0;
++    }
++
++
++_ACEOF
++if ac_fn_c_try_link "$LINENO"
++then :
++  ac_cv_dirent_d_ino=yes
++else $as_nop
++  ac_cv_dirent_d_ino=no
++fi
++rm -f core conftest.err conftest.$ac_objext conftest.beam \
++    conftest$ac_exeext conftest.$ac_ext
++
++fi
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_dirent_d_ino" >&5
++printf "%s\n" "$ac_cv_dirent_d_ino" >&6; }
++
++if test "x$ac_cv_dirent_d_ino" = xyes
++then :
++
++
++printf "%s\n" "#define HAVE_DIRENT_D_INO 1" >>confdefs.h
++
++
+ fi
+ 
+ # check if the Linux getrandom() syscall is available
+diff --git a/configure.ac b/configure.ac
+index 80d6738fab5..40f2f950b36 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -7084,6 +7084,11 @@ AS_VAR_IF([ac_cv_dirent_d_type], [yes], [
+               [Define to 1 if the dirent structure has a d_type field])
+ ])
+ 
++AS_VAR_IF([ac_cv_dirent_d_ino], [yes], [
++    AC_DEFINE([HAVE_DIRENT_D_INO], [1],
++              [Define to 1 if the dirent structure has a d_ino field])
++])
++
+ # check if the Linux getrandom() syscall is available
+ AC_CACHE_CHECK([for the Linux getrandom() syscall], 
[ac_cv_getrandom_syscall], [
+ AC_LINK_IFELSE(
+diff --git a/pyconfig.h.in b/pyconfig.h.in
+index 4d8b1d4f254..4a2ba83a872 100644
+--- a/pyconfig.h.in
++++ b/pyconfig.h.in
+@@ -277,6 +277,9 @@
+ /* Define to 1 if the dirent structure has a d_type field */
+ #undef HAVE_DIRENT_D_TYPE
+ 
++/* Define to 1 if the dirent structure has a d_ino field */
++#undef HAVE_DIRENT_D_INO
++
+ /* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.
+    */
+ #undef HAVE_DIRENT_H
+-- 
+2.46.1
+

Reply via email to