Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

interpreters/python: Add Python's port to NuttX #2879

Merged
merged 2 commits into from
Dec 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions interpreters/python/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/*.zip
/build/
/install/
/Python/
/romfs_cpython_modules.h
/romfs_cpython_modules.img
58 changes: 58 additions & 0 deletions interpreters/python/Kconfig
Original file line number Diff line number Diff line change
@@ -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
30 changes: 30 additions & 0 deletions interpreters/python/Make.defs
Original file line number Diff line number Diff line change
@@ -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
172 changes: 172 additions & 0 deletions interpreters/python/Makefile
Original file line number Diff line number Diff line change
@@ -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

tmedicci marked this conversation as resolved.
Show resolved Hide resolved
# 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 //')" \
tmedicci marked this conversation as resolved.
Show resolved Hide resolved
CC="$(CC)" \
CXX="$(CXX)" \
AR="$(AR)" \
ARFLAGS=" " \
MACHDEP="$(MACHDEP)" \
OPT="-g -O0 -Wall" \
tmedicci marked this conversation as resolved.
Show resolved Hide resolved
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
50 changes: 50 additions & 0 deletions interpreters/python/Setup.local
Original file line number Diff line number Diff line change
@@ -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
21 changes: 21 additions & 0 deletions interpreters/python/config.site
Original file line number Diff line number Diff line change
@@ -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"
Loading
Loading