From 0da1c31b61a918de51a8910724eaa2ed32bb3d6e Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Tue, 10 Sep 2024 14:28:29 -0700 Subject: [PATCH 001/142] bcrypt, cffi, argon2, freetype, pillow are working --- .appveyor.yml | 20 ++-- make_dep_wheels.py | 46 +++++----- pyproject.toml | 3 +- recipes/argon2-cffi-bindings/meta.yaml | 2 +- recipes/bcrypt/meta.yaml | 4 +- recipes/cffi/meta.yaml | 4 +- recipes/cryptography/meta.yaml | 8 +- recipes/freetype/meta.yaml | 4 +- recipes/freetype/patches/config.patch | 55 +++++------ recipes/pillow/meta.yaml | 12 ++- recipes/pillow/patches/setup.patch | 49 +++++----- setup.sh | 121 ++++++++++++------------- src/forge/build.py | 64 +++++++++---- src/forge/cross.py | 80 ++++++++++------ 14 files changed, 258 insertions(+), 214 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index 509fdc0b..6c5a7612 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -65,11 +65,11 @@ environment: job_group: build_android FORGE_ARCH: android FORGE_PACKAGES: >- - cffi:1.16.0 + cffi:1.17.1 libjpeg:3.0.3 libpng:1.6.43 - freetype:2.13.2 - pillow:10.3.0 + freetype:2.13.3 + pillow:10.4.0 lru-dict:1.3.0 yarl:1.9.4 contourpy:1.2.1 @@ -77,8 +77,8 @@ environment: aiohttp:3.9.5 bitarray:2.9.2 argon2-cffi-bindings:21.2.0 - bcrypt:4.1.3 - cryptography:42.0.7 + bcrypt:4.2.0 + cryptography:43.0.1 brotli:1.1.0 pydantic-core:2.18.4 websockets:12.0 @@ -99,8 +99,8 @@ environment: FORGE_PACKAGES: >- libjpeg:3.0.3 libpng:1.6.43 - freetype:2.13.2 - pillow:10.3.0 + freetype:2.13.3 + pillow:10.4.0 lru-dict:1.3.0 yarl:1.9.4 contourpy:1.2.1 @@ -113,10 +113,10 @@ environment: job_group: build_ios FORGE_ARCH: iOS FORGE_PACKAGES: >- - cffi:1.16.0 + cffi:1.17.1 argon2-cffi-bindings:21.2.0 - bcrypt:4.1.3 - cryptography:42.0.7 + bcrypt:4.2.0 + cryptography:43.0.1 brotli:1.1.0 - job_name: 'iOS: pydantic-core' diff --git a/make_dep_wheels.py b/make_dep_wheels.py index c862b82a..742e6696 100644 --- a/make_dep_wheels.py +++ b/make_dep_wheels.py @@ -26,7 +26,15 @@ def make_wheel(package, os_name, target): :param os_name: The OS name to target (e.g., "iOS") :param target: The target specifier (e.g., "iphoneos.arm64") """ - support = Path(os.environ["PYTHON_ANDROID_SUPPORT" if os_name == "android" else "PYTHON_APPLE_SUPPORT"]) + support = Path( + os.environ[ + ( + "MOBILE_FORGE_ANDROID_SUPPORT_PATH" + if os_name == "android" + else "MOBILE_FORGE_IOS_SUPPORT_PATH" + ) + ] + ) versions_file = ( support @@ -43,10 +51,15 @@ def make_wheel(package, os_name, target): package_version, package_build = package_version_build.split("-") - target_parts = target.split(".") - target_parts.reverse() - wheel_target = "_".join(target_parts) - wheel_tag = f"py3-none-{os_name}_{min_version}_{wheel_target.replace('-', '_')}".lower().replace(".", "_") + target_parts = target.split("-") + wheel_target = ( + f"{target_parts[0]}_iphoneos" + if len(target_parts) == 3 + else f"{target_parts[0]}_iphonesimulator" + ) + wheel_tag = f"py3-none-{os_name}_{min_version}_{wheel_target}".lower().replace( + ".", "_" + ) wheel_file = ( Path("dist") / f"{package.lower()}-{package_version_build}-{wheel_tag}.whl" @@ -125,26 +138,11 @@ def make_wheel(package, os_name, target): if __name__ == "__main__": os_name = sys.argv[1] for target in { - "android": [ - "arm64-v8a", - "armeabi-v7a", - "x86_64", - "x86" - ], + "android": ["arm64-v8a", "armeabi-v7a", "x86_64", "x86"], "iOS": [ - "iphoneos.arm64", - "iphonesimulator.arm64", - "iphonesimulator.x86_64", - ], - "tvOS": [ - "appletvos.arm64", - "appletvsimulator.arm64", - "appletvsimulator.x86_64", - ], - "watchOS": [ - "watchos.arm64_32", - "watchsimulator.arm64", - "watchsimulator.x86_64", + "arm64-apple-ios", + "arm64-apple-ios-simulator", + "x86_64-apple-ios-simulator", ], }[os_name]: for dep in ["BZip2", "XZ", "libFFI", "OpenSSL"]: diff --git a/pyproject.toml b/pyproject.toml index 884131d5..eea2c3ef 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -31,7 +31,8 @@ classifiers = [ dependencies = [ # Currently using a fork of crossenv to get iOS fixes. # Replace when/if these are merged and released. - "crossenv @ git+https://github.com/flet-dev/crossenv@ios-support", + #"crossenv @ git+https://github.com/flet-dev/crossenv@ios-support", + "crossenv @ git+https://github.com/freakboy3742/crossenv@f0f07129eb06ea16d180650a26a02df2b948b888", "httpx == 0.27.0", "Jinja2 == 3.1.3", "jsonschema == 4.21.1", diff --git a/recipes/argon2-cffi-bindings/meta.yaml b/recipes/argon2-cffi-bindings/meta.yaml index 52bf786e..04780dc4 100644 --- a/recipes/argon2-cffi-bindings/meta.yaml +++ b/recipes/argon2-cffi-bindings/meta.yaml @@ -4,4 +4,4 @@ package: requirements: build: - - cffi 1.16.0 + - cffi diff --git a/recipes/bcrypt/meta.yaml b/recipes/bcrypt/meta.yaml index 17ce120a..50a8f3af 100644 --- a/recipes/bcrypt/meta.yaml +++ b/recipes/bcrypt/meta.yaml @@ -1,8 +1,8 @@ package: name: bcrypt - version: 4.1.3 + version: 4.2.0 requirements: build: - setuptools_rust @ git+https://github.com/flet-dev/setuptools-rust@ios-support - - cffi 1.16.0 + - cffi diff --git a/recipes/cffi/meta.yaml b/recipes/cffi/meta.yaml index c29eccfe..caad2724 100644 --- a/recipes/cffi/meta.yaml +++ b/recipes/cffi/meta.yaml @@ -1,10 +1,10 @@ package: name: cffi - version: 1.16.0 + version: 1.17.1 patches: - mobile.patch requirements: host: - - libffi 3.4.4 + - libffi diff --git a/recipes/cryptography/meta.yaml b/recipes/cryptography/meta.yaml index 86f4274e..40e77fd8 100644 --- a/recipes/cryptography/meta.yaml +++ b/recipes/cryptography/meta.yaml @@ -1,16 +1,18 @@ package: name: cryptography - version: 42.0.7 + version: 43.0.1 build: script_env: - OPENSSL_STATIC: 1 + #OPENSSL_STATIC: 1 OPENSSL_DIR: '{platlib}/opt' + #PYO3_USE_ABI3_FORWARD_COMPATIBILITY: 1 requirements: build: - setuptools_rust @ git+https://github.com/flet-dev/setuptools-rust@ios-support host: - - cffi 1.16.0 + - cffi - openssl ^3.0.12 + - maturin @ git+https://github.com/PyO3/maturin \ No newline at end of file diff --git a/recipes/freetype/meta.yaml b/recipes/freetype/meta.yaml index 893e31c4..fbc9cadc 100644 --- a/recipes/freetype/meta.yaml +++ b/recipes/freetype/meta.yaml @@ -1,12 +1,12 @@ package: name: freetype - version: 2.13.2 + version: 2.13.3 build: number: 1 source: - url: https://download.flet.dev/freetype/freetype-2.13.2.tar.gz + url: https://download.savannah.gnu.org/releases/freetype/freetype-2.13.3.tar.gz patches: - config.patch diff --git a/recipes/freetype/patches/config.patch b/recipes/freetype/patches/config.patch index 7458d301..115801bb 100644 --- a/recipes/freetype/patches/config.patch +++ b/recipes/freetype/patches/config.patch @@ -1,29 +1,30 @@ -index 6ae2502..ab90b57 100755 +diff --git a/builds/unix/config.sub b/builds/unix/config.sub +index 4aaae46..526f2d4 100755 --- a/builds/unix/config.sub +++ b/builds/unix/config.sub -@@ -146,6 +146,7 @@ case $1 in - | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* \ - | netbsd*-eabi* | kopensolaris*-gnu* | cloudabi*-eabi* \ - | storm-chaos* | os2-emx* | rtmk-nova* | managarm-* \ -+ | ios*-simulator | tvos*-simulator | watchos*-simulator \ - | windows-* ) - basic_machine=$field1 - basic_os=$maybe_os -@@ -1492,6 +1493,8 @@ case $os in - ;; - esac - ;; -+ ios | ios-simulator) -+ ;; - *) - # No normalization, but not necessarily accepted, that comes below. - ;; -@@ -1797,6 +1800,8 @@ case $kernel-$os in - # None (no kernel, i.e. freestanding / bare metal), - # can be paired with an output format "OS" - ;; -+ ios-simulator) -+ ;; - -*) - # Blank kernel with real OS is always fine. - ;; \ No newline at end of file +@@ -155,6 +155,7 @@ case $1 in + | storm-chaos* \ + | uclinux-gnu* \ + | uclinux-uclibc* \ ++ | ios*-simulator \ + | windows-* ) + basic_machine=$field1 + basic_os=$maybe_os +@@ -1727,6 +1728,8 @@ case $os in + obj=$os + os= + ;; ++ ios | ios-simulator) ++ ;; + *) + # No normalization, but not necessarily accepted, that comes below. + ;; +@@ -2253,6 +2256,8 @@ case $kernel-$os-$obj in + # None (no kernel, i.e. freestanding / bare metal), + # can be paired with an machine code file format + ;; ++ ios-simulator) ++ ;; + -*-) + # Blank kernel with real OS is always fine. + ;; diff --git a/recipes/pillow/meta.yaml b/recipes/pillow/meta.yaml index b69db90f..cd1e9c71 100644 --- a/recipes/pillow/meta.yaml +++ b/recipes/pillow/meta.yaml @@ -1,12 +1,18 @@ package: name: Pillow - version: 10.3.0 + version: 10.4.0 patches: - setup.patch +build: + script_env: + # libfreetype references both libz and libbz2 + # but doesn't link them into the static library + LDFLAGS: -lz -lbz2 + requirements: host: # PNG support is internal: libpng is not used. - - libjpeg 3.0.3 - - freetype 2.13.2 + - libjpeg + - freetype diff --git a/recipes/pillow/patches/setup.patch b/recipes/pillow/patches/setup.patch index 80b29b02..659e12b1 100644 --- a/recipes/pillow/patches/setup.patch +++ b/recipes/pillow/patches/setup.patch @@ -1,55 +1,48 @@ -diff --git a/setup.py b/setup.py -index ac401dd..a5a9938 100644 ---- a/setup.py -+++ b/setup.py -@@ -341,9 +341,7 @@ class pil_build_ext(build_ext): - return True if value in configuration.get(option, []) else None - - def initialize_options(self): -- self.disable_platform_guessing = self.check_configuration( -- "platform-guessing", "disable" -- ) -+ self.disable_platform_guessing = True - self.add_imaging_libs = "" - build_ext.initialize_options(self) - for x in self.feature: -@@ -421,10 +419,19 @@ class pil_build_ext(build_ext): +diff -ur pillow-10.4.0-orig/setup.py pillow-10.4.0/setup.py +--- pillow-10.4.0-orig/setup.py 2024-07-01 14:02:01 ++++ pillow-10.4.0/setup.py 2024-09-05 14:20:16 +@@ -422,10 +422,22 @@ self.extensions.remove(extension) break - + - def get_macos_sdk_path(self): + def get_apple_sdk_path(self): try: + sdk = { + ("ios", False): ["--sdk", "iphoneos"], + ("ios", True): ["--sdk", "iphonesimulator"], -+ ("tvs", False): ["--sdk", "appletvos"], -+ ("tvs", True): ["--sdk", "appletvsimulator"], ++ ("tvos", False): ["--sdk", "appletvos"], ++ ("tvos", True): ["--sdk", "appletvsimulator"], + ("watchos", False): ["--sdk", "watchos"], + ("watchos", True): ["--sdk", "watchsimulator"], + ("darwin", False): [], -+ }[sys.platform, getattr(sys.implementation, "_simulator", False)] ++ }[ ++ sys.platform, ++ getattr(sys.implementation, "_multiarch", "").endswith("simulator"), ++ ] sdk_path = ( - subprocess.check_output(["xcrun", "--show-sdk-path"]) + subprocess.check_output(["xcrun", "--show-sdk-path"] + sdk) .strip() .decode("latin1") ) -@@ -577,11 +584,15 @@ class pil_build_ext(build_ext): +@@ -580,13 +592,18 @@ _add_directory(library_dirs, "/usr/X11/lib") _add_directory(include_dirs, "/usr/X11/include") - + - sdk_path = self.get_macos_sdk_path() -+ sdk_path = self.get_apple_sdk_path() -+ if sdk_path: -+ _add_directory(library_dirs, os.path.join(sdk_path, "usr", "lib")) -+ _add_directory(include_dirs, os.path.join(sdk_path, "usr", "include")) -+ elif sys.platform in ("ios", "tvos", "watchos"): + sdk_path = self.get_apple_sdk_path() if sdk_path: _add_directory(library_dirs, os.path.join(sdk_path, "usr", "lib")) _add_directory(include_dirs, os.path.join(sdk_path, "usr", "include")) -- + for extension in self.extensions: extension.extra_compile_args = ["-Wno-nullability-completeness"] ++ elif sys.platform in {"ios", "tvos", "watchos"}: ++ sdk_path = self.get_apple_sdk_path() ++ if sdk_path: ++ _add_directory(library_dirs, os.path.join(sdk_path, "usr", "lib")) ++ _add_directory(include_dirs, os.path.join(sdk_path, "usr", "include")) elif ( + sys.platform.startswith("linux") + or sys.platform.startswith("gnu") \ No newline at end of file diff --git a/setup.sh b/setup.sh index a4c87f6f..4a936081 100755 --- a/setup.sh +++ b/setup.sh @@ -5,7 +5,7 @@ usage() { echo echo "for example:" echo - echo " source $1 3.12" + echo " source $1 3.13" echo } @@ -34,8 +34,8 @@ CMAKE_VERSION="3.27.4" echo "Python version: $PYTHON_VERSION" echo "Python short version: $PYTHON_VER" -if [[ -z "$PYTHON_APPLE_SUPPORT" && -z "$PYTHON_ANDROID_SUPPORT" ]]; then - echo "Neither PYTHON_APPLE_SUPPORT nor PYTHON_ANDROID_SUPPORT are defined." +if [[ -z "$MOBILE_FORGE_IOS_SUPPORT_PATH" && -z "$MOBILE_FORGE_ANDROID_SUPPORT_PATH" ]]; then + echo "Neither MOBILE_FORGE_IOS_SUPPORT_PATH nor MOBILE_FORGE_ANDROID_SUPPORT_PATH are defined." return fi @@ -48,48 +48,56 @@ venv_dir="$(pwd)/venv$PYTHON_VER" if [ ! -d $venv_dir ]; then echo "Creating Python $PYTHON_VER virtual environment for build in $venv_dir..." - if ! [ -d "tools/python" ]; then - if [ $(uname) = "Darwin" ]; then - # macOS - if [ $(uname -m) = "arm64" ]; then - PYTHON_SUFFIX="aarch64-apple-darwin-install_only.tar.gz" - else - PYTHON_SUFFIX="x86_64-apple-darwin-install_only.tar.gz" - fi - else - # Linux - if [ $(uname -m) = "arm64" ]; then - PYTHON_SUFFIX="aarch64-unknown-linux-gnu-install_only.tar.gz" - else - PYTHON_SUFFIX="x86_64_v3-unknown-linux-gnu-install_only.tar.gz" - fi - fi - - if ! [ -f "downloads/python-${PYTHON_VERSION}-${PYTHON_SUFFIX}" ]; then - echo "Downloading Python ${PYTHON_VERSION}" - mkdir -p downloads - curl --location --progress-bar "${PYTHON_URL_PREFIX}-${PYTHON_SUFFIX}" --output "downloads/python-${PYTHON_VERSION}-${PYTHON_SUFFIX}" - fi - - mkdir -p tools - tar -xzf "downloads/python-${PYTHON_VERSION}-${PYTHON_SUFFIX}" -C tools + # if ! [ -d "tools/python" ]; then + # if [ $(uname) = "Darwin" ]; then + # # macOS + # if [ $(uname -m) = "arm64" ]; then + # PYTHON_SUFFIX="aarch64-apple-darwin-install_only.tar.gz" + # else + # PYTHON_SUFFIX="x86_64-apple-darwin-install_only.tar.gz" + # fi + # else + # # Linux + # if [ $(uname -m) = "arm64" ]; then + # PYTHON_SUFFIX="aarch64-unknown-linux-gnu-install_only.tar.gz" + # else + # PYTHON_SUFFIX="x86_64_v3-unknown-linux-gnu-install_only.tar.gz" + # fi + # fi + + # if ! [ -f "downloads/python-${PYTHON_VERSION}-${PYTHON_SUFFIX}" ]; then + # echo "Downloading Python ${PYTHON_VERSION}" + # mkdir -p downloads + # curl --location --progress-bar "${PYTHON_URL_PREFIX}-${PYTHON_SUFFIX}" --output "downloads/python-${PYTHON_VERSION}-${PYTHON_SUFFIX}" + # fi + + # mkdir -p tools + # tar -xzf "downloads/python-${PYTHON_VERSION}-${PYTHON_SUFFIX}" -C tools + # fi + + BUILD_PYTHON=$(which python$PYTHON_VER) + if [ $? -ne 0 ]; then + echo "Can't find a Python $PYTHON_VER binary on the path." + return fi - tools/python/bin/python -m venv $venv_dir + # tools/python/bin/python -m venv $venv_dir + echo "Using $BUILD_PYTHON as the build python" + $BUILD_PYTHON -m venv $venv_dir source $venv_dir/bin/activate pip install -U pip pip install -e . wheel echo "Building platform dependency wheels..." - if [ ! -z "$PYTHON_APPLE_SUPPORT" ]; then + if [ ! -z "$MOBILE_FORGE_IOS_SUPPORT_PATH" ]; then python -m make_dep_wheels iOS if [ $? -ne 0 ]; then return fi fi - if [ ! -z "$PYTHON_ANDROID_SUPPORT" ]; then + if [ ! -z "$MOBILE_FORGE_ANDROID_SUPPORT_PATH" ]; then python -m make_dep_wheels android if [ $? -ne 0 ]; then return @@ -104,65 +112,54 @@ else fi # configure iOS paths -if [ ! -z "$PYTHON_APPLE_SUPPORT" ]; then +if [ ! -z "$MOBILE_FORGE_IOS_SUPPORT_PATH" ]; then - if [ ! -d $PYTHON_APPLE_SUPPORT/install ]; then - echo "PYTHON_APPLE_SUPPORT does not point at a valid location." + if [ ! -d $MOBILE_FORGE_IOS_SUPPORT_PATH/install ]; then + echo "MOBILE_FORGE_IOS_SUPPORT_PATH does not point at a valid location." return fi - if [ ! -e $PYTHON_APPLE_SUPPORT/install/iOS/iphoneos.arm64/python-$PYTHON_VERSION/bin/python$PYTHON_VER ]; then - echo "PYTHON_APPLE_SUPPORT does not appear to contain a Python $PYTHON_VERSION iOS ARM64 device binary." + if [ ! -e $MOBILE_FORGE_IOS_SUPPORT_PATH/install/iOS/arm64-apple-ios/python-$PYTHON_VERSION/bin/python$PYTHON_VER ]; then + echo "MOBILE_FORGE_IOS_SUPPORT_PATH does not appear to contain a Python $PYTHON_VERSION iOS ARM64 device binary." return fi - if [ ! -e $PYTHON_APPLE_SUPPORT/install/iOS/iphonesimulator.arm64/python-$PYTHON_VERSION/bin/python$PYTHON_VER ]; then - echo "PYTHON_APPLE_SUPPORT does not appear to contain a Python $PYTHON_VERSION iOS ARM64 simulator binary." + if [ ! -e $MOBILE_FORGE_IOS_SUPPORT_PATH/install/iOS/arm64-apple-ios-simulator/python-$PYTHON_VERSION/bin/python$PYTHON_VER ]; then + echo "MOBILE_FORGE_IOS_SUPPORT_PATH does not appear to contain a Python $PYTHON_VERSION iOS ARM64 simulator binary." return fi - if [ ! -e $PYTHON_APPLE_SUPPORT/install/iOS/iphonesimulator.x86_64/python-$PYTHON_VERSION/bin/python$PYTHON_VER ]; then - echo "PYTHON_APPLE_SUPPORT does not appear to contain a Python $PYTHON_VERSION iOS x86-64 simulator binary." + if [ ! -e $MOBILE_FORGE_IOS_SUPPORT_PATH/install/iOS/x86_64-apple-ios-simulator/python-$PYTHON_VERSION/bin/python$PYTHON_VER ]; then + echo "MOBILE_FORGE_IOS_SUPPORT_PATH does not appear to contain a Python $PYTHON_VERSION iOS x86-64 simulator binary." return fi - echo "PYTHON_APPLE_SUPPORT: $PYTHON_APPLE_SUPPORT" - - export MOBILE_FORGE_IPHONEOS_ARM64=$PYTHON_APPLE_SUPPORT/install/iOS/iphoneos.arm64/python-$PYTHON_VERSION/bin/python$PYTHON_VER - export MOBILE_FORGE_IPHONESIMULATOR_ARM64=$PYTHON_APPLE_SUPPORT/install/iOS/iphonesimulator.arm64/python-$PYTHON_VERSION/bin/python$PYTHON_VER - export MOBILE_FORGE_IPHONESIMULATOR_X86_64=$PYTHON_APPLE_SUPPORT/install/iOS/iphonesimulator.x86_64/python-$PYTHON_VERSION/bin/python$PYTHON_VER - - export PATH="$PATH:$PYTHON_APPLE_SUPPORT/support/$PYTHON_VER/iOS/bin" + echo "MOBILE_FORGE_IOS_SUPPORT_PATH: $MOBILE_FORGE_IOS_SUPPORT_PATH" fi # configure Android paths -if [ ! -z "$PYTHON_ANDROID_SUPPORT" ]; then - if [ ! -e $PYTHON_ANDROID_SUPPORT/install/android/arm64-v8a/python-$PYTHON_VERSION/bin/python$PYTHON_VER ]; then - echo "PYTHON_ANDROID_SUPPORT does not appear to contain a Python $PYTHON_VERSION Android arm64-v8a device binary." +if [ ! -z "$MOBILE_FORGE_ANDROID_SUPPORT_PATH" ]; then + if [ ! -e $MOBILE_FORGE_ANDROID_SUPPORT_PATH/install/android/arm64-v8a/python-$PYTHON_VERSION/bin/python$PYTHON_VER ]; then + echo "MOBILE_FORGE_ANDROID_SUPPORT_PATH does not appear to contain a Python $PYTHON_VERSION Android arm64-v8a device binary." return fi - if [ ! -e $PYTHON_ANDROID_SUPPORT/install/android/armeabi-v7a/python-$PYTHON_VERSION/bin/python$PYTHON_VER ]; then - echo "PYTHON_ANDROID_SUPPORT does not appear to contain a Python $PYTHON_VERSION Android armeabi-v7a device binary." + if [ ! -e $MOBILE_FORGE_ANDROID_SUPPORT_PATH/install/android/armeabi-v7a/python-$PYTHON_VERSION/bin/python$PYTHON_VER ]; then + echo "MOBILE_FORGE_ANDROID_SUPPORT_PATH does not appear to contain a Python $PYTHON_VERSION Android armeabi-v7a device binary." return fi - if [ ! -e $PYTHON_ANDROID_SUPPORT/install/android/x86_64/python-$PYTHON_VERSION/bin/python$PYTHON_VER ]; then - echo "PYTHON_ANDROID_SUPPORT does not appear to contain a Python $PYTHON_VERSION Android x86_64 device binary." + if [ ! -e $MOBILE_FORGE_ANDROID_SUPPORT_PATH/install/android/x86_64/python-$PYTHON_VERSION/bin/python$PYTHON_VER ]; then + echo "MOBILE_FORGE_ANDROID_SUPPORT_PATH does not appear to contain a Python $PYTHON_VERSION Android x86_64 device binary." return fi - if [ ! -e $PYTHON_ANDROID_SUPPORT/install/android/x86/python-$PYTHON_VERSION/bin/python$PYTHON_VER ]; then - echo "PYTHON_ANDROID_SUPPORT does not appear to contain a Python $PYTHON_VERSION Android x86 device binary." + if [ ! -e $MOBILE_FORGE_ANDROID_SUPPORT_PATH/install/android/x86/python-$PYTHON_VERSION/bin/python$PYTHON_VER ]; then + echo "MOBILE_FORGE_ANDROID_SUPPORT_PATH does not appear to contain a Python $PYTHON_VERSION Android x86 device binary." return fi - echo "PYTHON_ANDROID_SUPPORT: $PYTHON_ANDROID_SUPPORT" - - export MOBILE_FORGE_ANDROID_ARM64_V8A=$PYTHON_ANDROID_SUPPORT/install/android/arm64-v8a/python-$PYTHON_VERSION/bin/python$PYTHON_VER - export MOBILE_FORGE_ANDROID_ARMEABI_V7A=$PYTHON_ANDROID_SUPPORT/install/android/armeabi-v7a/python-$PYTHON_VERSION/bin/python$PYTHON_VER - export MOBILE_FORGE_ANDROID_X86_64=$PYTHON_ANDROID_SUPPORT/install/android/x86_64/python-$PYTHON_VERSION/bin/python$PYTHON_VER - export MOBILE_FORGE_ANDROID_X86=$PYTHON_ANDROID_SUPPORT/install/android/x86/python-$PYTHON_VERSION/bin/python$PYTHON_VER + echo "MOBILE_FORGE_ANDROID_SUPPORT_PATH: $MOBILE_FORGE_ANDROID_SUPPORT_PATH" fi # Ensure CMake is installed diff --git a/src/forge/build.py b/src/forge/build.py index db9b32ae..1beaab4c 100644 --- a/src/forge/build.py +++ b/src/forge/build.py @@ -7,7 +7,7 @@ import sys import tarfile import zipfile -from abc import ABC, abstractmethod +from abc import ABC, abstractmethod, abstractproperty from email import generator, message from pathlib import Path from typing import TYPE_CHECKING @@ -36,15 +36,13 @@ def __init__(self, cross_venv: CrossVEnv, package: Package): self.cross_venv = cross_venv self.package = package - @property - @abstractmethod + @abstractproperty def build_path(self) -> Path: """The path in which all environment and sources for the build will be created.""" ... - @property - @abstractmethod + @abstractproperty def log_file_path(self) -> Path: """The path where build logs should be written.""" ... @@ -54,8 +52,7 @@ def error_log_file_path(self) -> Path: """The path for the log file if a build error occurs.""" return self.log_file_path.parent.parent / "errors" / self.log_file_path.name - @property - @abstractmethod + @abstractproperty def source_archive_path(self) -> Path: """The source archive file for the package.""" ... @@ -79,7 +76,7 @@ def install_requirements(self, target): self.cross_venv.pip_install( self.log_file, requirements, - wheels_path=Path.cwd() / "dist", + paths=[Path.cwd() / "dist"], build=target == "build", ) else: @@ -106,6 +103,13 @@ def unpack_source(self): self.log_file, f"Unpacking {self.source_archive_path.relative_to(Path.cwd())}...", ) + # Determine the stripping level. By default, this is 1; + # but some source types can override. + try: + strip = self.package.meta["source"]["strip"] + except (TypeError, KeyError): + strip = 1 + # Some packages (e.g., brotli) have uploaded a .tar.gz file... that is # actually a zipfile (!). if tarfile.is_tarfile(self.source_archive_path): @@ -123,7 +127,7 @@ def members(tf: tarfile.TarFile, strip=1): with tarfile.open(self.source_archive_path) as tf: tf.extractall( path=self.build_path, - members=members(tf, strip=1), + members=members(tf, strip=strip) if strip else None, ) elif zipfile.is_zipfile(self.source_archive_path): # Strip the top level folder. @@ -141,7 +145,7 @@ def members(zf, strip=1): zf.extractall( path=self.build_path, - members=members(zf, strip=1), + members=members(zf, strip=strip) if strip else None, ) else: raise RuntimeError( @@ -160,7 +164,14 @@ def patch_source(self): # not anything dependent on the Python environment. subprocess.run( self.log_file, - ["patch", "-p1", "--ignore-whitespace", "--input", str(patchfile)], + [ + "patch", + "-p1", + "--ignore-whitespace", + "--quiet", + "--input", + str(patchfile), + ], cwd=self.build_path, ) patched = True @@ -245,7 +256,7 @@ def compile_env(self, **kwargs) -> dict[str, str]: # cargo_ldflags = re.sub(r"-march=[\w-]+", "", ldflags) cargo_ldflags = " -L{}/lib".format(self.cross_venv.sysconfig_data["prefix"]) - cargo_ldflags += " -C link-arg=-undefined -C link-arg=dynamic_lookup" + # cargo_ldflags += " -C link-arg=-undefined -C link-arg=dynamic_lookup" if self.cross_venv.sdk != "android": @@ -258,6 +269,9 @@ def compile_env(self, **kwargs) -> dict[str, str]: if (self.cross_venv.sdk_root / "usr" / "lib").is_dir(): ldflags += f" -L{self.cross_venv.sdk_root}/usr/lib" + # Add the framework path + ldflags += f' -F "{self.cross_venv.host_python_home}"' + cargo_build_target = ( { "arm64-apple-ios": "aarch64-apple-ios", @@ -361,7 +375,7 @@ class SimplePackageBuilder(Builder): @property def source_archive_path(self) -> Path: - url = self.package.meta["source"]["url"] + url = self.download_source_url() filename = url.split("/")[-1] return Path.cwd() / "downloads" / filename @@ -389,7 +403,12 @@ def log_file_path(self) -> Path: ) def download_source_url(self): - return self.package.meta["source"]["url"] + return self.package.meta["source"]["url"].format( + version=self.package.meta["package"]["version"], + build=self.package.meta["build"]["number"], + sdk=self.cross_venv.sdk, + arch=self.cross_venv.arch, + ) def prepare(self, clean=True): # Always clean a non-Python build. @@ -414,7 +433,7 @@ def make_wheel(self): info_path = self.build_path / "wheel" / f"{name}-{version}.dist-info" log(self.log_file, f"\n[{self.cross_venv}] Writing wheel metadata") - info_path.mkdir() + info_path.mkdir(exist_ok=True) # Write the packaging metadata self.write_message_file( @@ -537,14 +556,14 @@ def prepare(self, clean=True): self.cross_venv.pip_install( self.log_file, ["build", "wheel"] + pyproject["build-system"]["requires"], - wheels_path=Path.cwd() / "dist", + paths=[Path.cwd() / "dist"], ) # Install the build requirements in the build environment self.cross_venv.pip_install( self.log_file, ["build", "wheel"] + pyproject["build-system"]["requires"], - wheels_path=Path.cwd() / "dist", + paths=[Path.cwd() / "dist"], build=True, ) else: @@ -624,11 +643,18 @@ def _build(self): env = self.compile_env() - script_vars = {**env, **self.cross_venv.scheme_paths, **self.cross_venv.sysconfig_data} + script_vars = { + **env, + **self.cross_venv.scheme_paths, + **self.cross_venv.sysconfig_data, + } # Set up any additional environment variables needed in the script environment. for key, value in self.package.meta["build"]["script_env"].items(): - env[key] = str(value).format(**script_vars) + if key == "LDFLAGS": + env[key] += " " + value + else: + env[key] = str(value).format(**script_vars) # Set the cross host platform in the environment env["_PYTHON_HOST_PLATFORM"] = self.cross_venv.platform_identifier diff --git a/src/forge/cross.py b/src/forge/cross.py index 34e3f8a3..18d9b603 100644 --- a/src/forge/cross.py +++ b/src/forge/cross.py @@ -1,6 +1,7 @@ from __future__ import annotations import argparse +import itertools import os import shutil import sys @@ -14,8 +15,8 @@ class CrossVEnv: BASE_VERSION = { "android": "24", - "iOS": "12.0", - "tvOS": "7.0", + "iOS": "13.0", + "tvOS": "12.0", "watchOS": "4.0", } @@ -65,6 +66,9 @@ def __init__(self, sdk, sdk_version, arch): self.sdk_version = sdk_version self.arch = arch + self.host_os = { + sdk: host_os for host_os, sdks in self.HOST_SDKS.items() for sdk, _ in sdks + }[self.sdk] self.platform_identifier = self._platform_identifier(sdk, sdk_version, arch) self.tag = ( self._platform_identifier(sdk, sdk_version, arch) @@ -90,6 +94,19 @@ def exists(self) -> bool: """Does the cross environment exist?""" return self.venv_path.is_dir() + @property + def host_python_home(self): + support_path = Path( + os.getenv(f"MOBILE_FORGE_{self.host_os.upper()}_SUPPORT_PATH") + ) + return ( + support_path + / "install" + / self.host_os + / self.platform_triplet + / f"python-3.{sys.version_info.minor}.{sys.version_info.micro}" + ) + @property def venv_path(self) -> Path: """The location of the cross environment on disk.""" @@ -187,18 +204,18 @@ def sdk_root(self) -> Path: return self._sdk_root @classmethod - def _platform_identifier(cls, sdk, version, arch): + def _platform_identifier(self, sdk, version, arch): if sdk == "android": if version is None: version = 21 identifier = f"{sdk}-{version}-{arch}" elif sdk in {"iphoneos", "iphonesimulator"}: if version is None: - version = "12.0" + version = "13.0" identifier = f"ios-{version}-{arch}-{sdk}" elif sdk in {"appletvos", "appletvsimulator"}: if version is None: - version = "7.0" + version = "12.0" identifier = f"tvos-{version}-{arch}-{sdk}" elif sdk in {"watchos", "watchsimulator"}: if version is None: @@ -222,17 +239,17 @@ def create( :raises: ``RuntimeError`` if an environment matching the requested host already exists, and ``clean=False``. """ - env_key = ( - f"MOBILE_FORGE_{self.sdk.upper()}_{self.arch.upper().replace('-', '_')}" + host_python = self.host_python_home / f"bin/python3.{sys.version_info.minor}" + if not host_python.is_file(): + raise RuntimeError(f"Can't find host python {host_python}") + + host_sysconfig = ( + self.host_python_home + / f"lib/python3.{sys.version_info.minor}" + / f"_sysconfigdata__{self.host_os.lower()}_{self.arch}-{self.sdk}.py" ) - host_python = os.getenv(env_key) - if host_python is None: - raise RuntimeError( - f"Host Python not defined. Set the {env_key} environment variable with " - "the location of the host Python's binary." - ) - elif not Path(host_python).is_file(): - raise RuntimeError(f"Environment {self} already exists.") + if not host_sysconfig.is_file(): + raise RuntimeError(f"Can't find host sysconfig {host_sysconfig}") self.location = Path(location).resolve() if location else Path.cwd() if self.exists(): @@ -250,9 +267,12 @@ def create( sys.executable, "-m", "crossenv", + "--sysconfigdata-file", + str(host_sysconfig), str(host_python), self.venv_path, ], + **self.cross_kwargs({}), ) except subprocess.CalledProcessError: raise RuntimeError(f"Unable to create cross platform environment {self}.") @@ -348,8 +368,10 @@ def cross_kwargs(self, kwargs): ) ] + # Ensure the path is clean, and doesn't include any non-iOS paths. env["PATH"] = os.pathsep.join( [ + str(self.host_python_home / "bin"), str(self.venv_path / "bin"), str(self.venv_path / self.venv_path.name / "bin"), ] @@ -402,7 +424,7 @@ def pip_install( packages, update=False, build=False, - wheels_path=None, + paths=None, ): """Install packages into the cross environment. @@ -410,14 +432,17 @@ def pip_install( :param update: Should the package be updated ("-U") :param build: Should the package be installed in the build environment? Defaults to installing in the host environment. - :param wheels_path: A path to search for additional wheels ("--find-links"). + :param paths: The paths to search for additional wheels ("--find-links"). """ # build-pip is a script; pip is a shim with a hashbang that points # at a python interpreter, which we can't invoke with subprocess. self.run( logfile, (["build-pip"] if build else ["python", "-m", "pip"]) - + ["install", "--disable-pip-version-check"] + + [ + "install", + "--disable-pip-version-check", + ] # If we're doing a host build, require binary packages. # build environment can use non-binary packages. + ( @@ -430,8 +455,12 @@ def pip_install( ) # Update packages if requested + (["-U"] if update else []) - # Include the local wheels path if provided. - + (["--find-links", str(wheels_path)] if wheels_path else []) + # Include the local wheels paths if provided. + + ( + list(itertools.chain(*(["--find-links", str(path)] for path in paths))) + if paths + else [] + ) # Finally, the list of packages to install. + packages, ) @@ -463,12 +492,6 @@ def main(): parser.add_argument( "--arch", required=True, help="The CPU architecture for the host." ) - parser.add_argument( - "host_python", - metavar="DIR", - type=abspath, - help="Path to the python executable of the Python built for the host platform.", - ) args = parser.parse_args() @@ -478,10 +501,7 @@ def main(): sdk_version=args.sdk_version, arch=args.arch, ) - cross_venv.create( - host_python=Path(args.host_python), - clean=args.clean, - ) + cross_venv.create(clean=args.clean) except RuntimeError as e: print() print(f"ERROR: {e}") From 4626a079c50b4e5d8075fb8b55b26fa702b3b729 Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Wed, 11 Sep 2024 10:47:36 -0700 Subject: [PATCH 002/142] Try Python 3.12 with beeware layout --- make_dep_wheels.py | 17 +++++++---------- pyproject.toml | 3 ++- recipes/cryptography/meta.yaml | 6 ++---- setup.sh | 16 ++++++++-------- src/forge/cross.py | 19 ++++++++++++++++--- 5 files changed, 35 insertions(+), 26 deletions(-) diff --git a/make_dep_wheels.py b/make_dep_wheels.py index 742e6696..72657018 100644 --- a/make_dep_wheels.py +++ b/make_dep_wheels.py @@ -51,13 +51,10 @@ def make_wheel(package, os_name, target): package_version, package_build = package_version_build.split("-") - target_parts = target.split("-") - wheel_target = ( - f"{target_parts[0]}_iphoneos" - if len(target_parts) == 3 - else f"{target_parts[0]}_iphonesimulator" - ) - wheel_tag = f"py3-none-{os_name}_{min_version}_{wheel_target}".lower().replace( + target_parts = target.split(".") + target_parts.reverse() + wheel_target = "_".join(target_parts) + wheel_tag = f"py3-none-{os_name}_{min_version}_{wheel_target.replace('-', '_')}".lower().replace( ".", "_" ) @@ -140,9 +137,9 @@ def make_wheel(package, os_name, target): for target in { "android": ["arm64-v8a", "armeabi-v7a", "x86_64", "x86"], "iOS": [ - "arm64-apple-ios", - "arm64-apple-ios-simulator", - "x86_64-apple-ios-simulator", + "iphoneos.arm64", + "iphonesimulator.arm64", + "iphonesimulator.x86_64", ], }[os_name]: for dep in ["BZip2", "XZ", "libFFI", "OpenSSL"]: diff --git a/pyproject.toml b/pyproject.toml index eea2c3ef..59bae745 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -32,7 +32,8 @@ dependencies = [ # Currently using a fork of crossenv to get iOS fixes. # Replace when/if these are merged and released. #"crossenv @ git+https://github.com/flet-dev/crossenv@ios-support", - "crossenv @ git+https://github.com/freakboy3742/crossenv@f0f07129eb06ea16d180650a26a02df2b948b888", + #"crossenv @ git+https://github.com/freakboy3742/crossenv@f0f07129eb06ea16d180650a26a02df2b948b888", + "crossenv @ git+https://github.com/freakboy3742/crossenv@iOS-support", "httpx == 0.27.0", "Jinja2 == 3.1.3", "jsonschema == 4.21.1", diff --git a/recipes/cryptography/meta.yaml b/recipes/cryptography/meta.yaml index 40e77fd8..bfef6a7e 100644 --- a/recipes/cryptography/meta.yaml +++ b/recipes/cryptography/meta.yaml @@ -1,12 +1,11 @@ package: name: cryptography - version: 43.0.1 + version: 42.0.7 build: script_env: - #OPENSSL_STATIC: 1 + OPENSSL_STATIC: 1 OPENSSL_DIR: '{platlib}/opt' - #PYO3_USE_ABI3_FORWARD_COMPATIBILITY: 1 requirements: build: @@ -15,4 +14,3 @@ requirements: host: - cffi - openssl ^3.0.12 - - maturin @ git+https://github.com/PyO3/maturin \ No newline at end of file diff --git a/setup.sh b/setup.sh index 4a936081..5e63d4f0 100755 --- a/setup.sh +++ b/setup.sh @@ -114,25 +114,25 @@ fi # configure iOS paths if [ ! -z "$MOBILE_FORGE_IOS_SUPPORT_PATH" ]; then - if [ ! -d $MOBILE_FORGE_IOS_SUPPORT_PATH/install ]; then + if [ ! -d $MOBILE_FORGE_IOS_SUPPORT_PATH/support/$PYTHON_VER/iOS/Python.xcframework ]; then echo "MOBILE_FORGE_IOS_SUPPORT_PATH does not point at a valid location." return fi - if [ ! -e $MOBILE_FORGE_IOS_SUPPORT_PATH/install/iOS/arm64-apple-ios/python-$PYTHON_VERSION/bin/python$PYTHON_VER ]; then + if [ ! -e $MOBILE_FORGE_IOS_SUPPORT_PATH/support/$PYTHON_VER/iOS/Python.xcframework/ios-arm64/bin/python$PYTHON_VER ]; then echo "MOBILE_FORGE_IOS_SUPPORT_PATH does not appear to contain a Python $PYTHON_VERSION iOS ARM64 device binary." return fi - if [ ! -e $MOBILE_FORGE_IOS_SUPPORT_PATH/install/iOS/arm64-apple-ios-simulator/python-$PYTHON_VERSION/bin/python$PYTHON_VER ]; then - echo "MOBILE_FORGE_IOS_SUPPORT_PATH does not appear to contain a Python $PYTHON_VERSION iOS ARM64 simulator binary." + if [ ! -e $MOBILE_FORGE_IOS_SUPPORT_PATH/support/$PYTHON_VER/iOS/Python.xcframework/ios-arm64_x86_64-simulator/bin/python$PYTHON_VER ]; then + echo "MOBILE_FORGE_IOS_SUPPORT_PATH does not appear to contain a Python $PYTHON_VERSION iOS ARM64/x86_64 simulator binaries." return fi - if [ ! -e $MOBILE_FORGE_IOS_SUPPORT_PATH/install/iOS/x86_64-apple-ios-simulator/python-$PYTHON_VERSION/bin/python$PYTHON_VER ]; then - echo "MOBILE_FORGE_IOS_SUPPORT_PATH does not appear to contain a Python $PYTHON_VERSION iOS x86-64 simulator binary." - return - fi + # if [ ! -e $MOBILE_FORGE_IOS_SUPPORT_PATH/install/iOS/x86_64-apple-ios-simulator/python-$PYTHON_VERSION/bin/python$PYTHON_VER ]; then + # echo "MOBILE_FORGE_IOS_SUPPORT_PATH does not appear to contain a Python $PYTHON_VERSION iOS x86-64 simulator binary." + # return + # fi echo "MOBILE_FORGE_IOS_SUPPORT_PATH: $MOBILE_FORGE_IOS_SUPPORT_PATH" fi diff --git a/src/forge/cross.py b/src/forge/cross.py index 18d9b603..f6b5b6ea 100644 --- a/src/forge/cross.py +++ b/src/forge/cross.py @@ -54,6 +54,18 @@ class CrossVEnv: "watchsimulator": "apple-watchos-simulator", } + XCFRAMEWORK_SLICES = { + ("iphonesimulator", "arm64"): "ios-arm64_x86_64-simulator", + ("iphonesimulator", "x86_64"): "ios-arm64_x86_64-simulator", + ("iphoneos", "arm64"): "ios-arm64", + ("appletvsimulator", "arm64"): "tvos-arm64_x86_64-simulator", + ("appletvsimulator", "x86_64"): "tvos-arm64_x86_64-simulator", + ("appletvos", "arm64"): "tvos-arm64", + ("watchsimulator", "arm64"): "watchos-arm64_x86_64-simulator", + ("watchsimulator", "x86_64"): "watchos-arm64_x86_64-simulator", + ("watchos", "arm64_32"): "watchos-arm64_32", + } + ANDROID_PLATFORM_TRIPLET = { "arm64-v8a": "aarch64-linux-android", "armeabi-v7a": "arm-linux-androideabi", @@ -101,10 +113,11 @@ def host_python_home(self): ) return ( support_path - / "install" + / "support" + / f"3.{sys.version_info.minor}" / self.host_os - / self.platform_triplet - / f"python-3.{sys.version_info.minor}.{sys.version_info.micro}" + / "Python.xcframework" + / self.XCFRAMEWORK_SLICES[(self.sdk, self.arch)] ) @property From 7dcb8f757ad4e0d0fe3b8bc75bec23d17c4af53b Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Wed, 11 Sep 2024 11:50:43 -0700 Subject: [PATCH 003/142] Add Python framework to cargo linker args --- src/forge/build.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/forge/build.py b/src/forge/build.py index 1beaab4c..1a28a2d3 100644 --- a/src/forge/build.py +++ b/src/forge/build.py @@ -271,6 +271,7 @@ def compile_env(self, **kwargs) -> dict[str, str]: # Add the framework path ldflags += f' -F "{self.cross_venv.host_python_home}"' + cargo_ldflags += f" -C link-arg=-F{self.cross_venv.host_python_home} -C link-arg=-framework -C link-arg=Python" cargo_build_target = ( { From 4d43a16565eb3683314f95845ec32dc58f1546c3 Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Wed, 11 Sep 2024 14:01:32 -0700 Subject: [PATCH 004/142] All packages can be built for iOS, except "blis" --- recipes/blis/meta.yaml | 2 -- recipes/cryptography/meta.yaml | 2 +- recipes/libjpeg/meta.yaml | 6 +++- recipes/matplotlib/meta.yaml | 3 +- recipes/numpy/meta.yaml | 6 ++-- recipes/opencv-python/meta.yaml | 2 ++ recipes/pandas/meta.yaml | 4 +-- recipes/pydantic-core/meta.yaml | 4 +-- setup.sh | 52 --------------------------------- src/forge/build.py | 15 ++++++---- src/forge/cross.py | 28 +++++------------- src/forge/package.py | 13 ++------- 12 files changed, 37 insertions(+), 100 deletions(-) diff --git a/recipes/blis/meta.yaml b/recipes/blis/meta.yaml index 76b02d3c..91252e0a 100644 --- a/recipes/blis/meta.yaml +++ b/recipes/blis/meta.yaml @@ -6,7 +6,5 @@ patches: - mobile.patch requirements: - build: - - numpy 1.26.4 host: - numpy 1.26.4 \ No newline at end of file diff --git a/recipes/cryptography/meta.yaml b/recipes/cryptography/meta.yaml index bfef6a7e..1e2bacd1 100644 --- a/recipes/cryptography/meta.yaml +++ b/recipes/cryptography/meta.yaml @@ -4,7 +4,7 @@ package: build: script_env: - OPENSSL_STATIC: 1 + #OPENSSL_STATIC: 1 OPENSSL_DIR: '{platlib}/opt' requirements: diff --git a/recipes/libjpeg/meta.yaml b/recipes/libjpeg/meta.yaml index abfbec17..49a7f0ae 100644 --- a/recipes/libjpeg/meta.yaml +++ b/recipes/libjpeg/meta.yaml @@ -6,4 +6,8 @@ source: url: https://github.com/libjpeg-turbo/libjpeg-turbo/releases/download/3.0.3/libjpeg-turbo-3.0.3.tar.gz build: - number: 1 \ No newline at end of file + number: 1 + +requirements: + build: + - cmake \ No newline at end of file diff --git a/recipes/matplotlib/meta.yaml b/recipes/matplotlib/meta.yaml index 2f33fc2d..97eda173 100644 --- a/recipes/matplotlib/meta.yaml +++ b/recipes/matplotlib/meta.yaml @@ -3,9 +3,10 @@ package: version: 3.9.0 requirements: - host: + build: - meson - ninja + host: - numpy 2.0.0 build: diff --git a/recipes/numpy/meta.yaml b/recipes/numpy/meta.yaml index 5d28cb9f..969053d8 100644 --- a/recipes/numpy/meta.yaml +++ b/recipes/numpy/meta.yaml @@ -6,8 +6,8 @@ package: version: 1.26.4 requirements: - host: -# - chaquopy-openblas 0.2.20 + build: + - cython - ninja - meson @@ -23,7 +23,7 @@ build: meson: properties: -# {% if sdk == 'android' and arch in ['arm64-v8a', 'x86_64'] %} +# {% if sdk == 'iOS' or (sdk == 'android' and arch in ['arm64-v8a', 'x86_64']) %} longdouble_format: IEEE_QUAD_LE # {% else %} longdouble_format: IEEE_DOUBLE_LE diff --git a/recipes/opencv-python/meta.yaml b/recipes/opencv-python/meta.yaml index 8881b1dc..d3b16e75 100644 --- a/recipes/opencv-python/meta.yaml +++ b/recipes/opencv-python/meta.yaml @@ -50,6 +50,8 @@ build: # {% endif %} requirements: + host: + - numpy 2.0.0 build: - cmake - scikit-build @ git+https://github.com/flet-dev/scikit-build@ios-android-support diff --git a/recipes/pandas/meta.yaml b/recipes/pandas/meta.yaml index 5eac73f0..1a7b6711 100644 --- a/recipes/pandas/meta.yaml +++ b/recipes/pandas/meta.yaml @@ -4,10 +4,10 @@ package: requirements: build: - - numpy 2.0.0 - host: - meson - ninja + host: + - numpy 2.0.0 build: backend-args: diff --git a/recipes/pydantic-core/meta.yaml b/recipes/pydantic-core/meta.yaml index bda176e1..14ce49ca 100644 --- a/recipes/pydantic-core/meta.yaml +++ b/recipes/pydantic-core/meta.yaml @@ -3,5 +3,5 @@ package: version: 2.18.4 requirements: - host: - - maturin @ git+https://github.com/flet-dev/maturin@python-host-platform-var \ No newline at end of file + build: + - maturin \ No newline at end of file diff --git a/setup.sh b/setup.sh index 5e63d4f0..ace10612 100755 --- a/setup.sh +++ b/setup.sh @@ -129,11 +129,6 @@ if [ ! -z "$MOBILE_FORGE_IOS_SUPPORT_PATH" ]; then return fi - # if [ ! -e $MOBILE_FORGE_IOS_SUPPORT_PATH/install/iOS/x86_64-apple-ios-simulator/python-$PYTHON_VERSION/bin/python$PYTHON_VER ]; then - # echo "MOBILE_FORGE_IOS_SUPPORT_PATH does not appear to contain a Python $PYTHON_VERSION iOS x86-64 simulator binary." - # return - # fi - echo "MOBILE_FORGE_IOS_SUPPORT_PATH: $MOBILE_FORGE_IOS_SUPPORT_PATH" fi @@ -162,53 +157,6 @@ if [ ! -z "$MOBILE_FORGE_ANDROID_SUPPORT_PATH" ]; then echo "MOBILE_FORGE_ANDROID_SUPPORT_PATH: $MOBILE_FORGE_ANDROID_SUPPORT_PATH" fi -# Ensure CMake is installed -if [ $(uname) = "Darwin" ]; then - if ! [ -d "tools/CMake.app" ]; then - if ! [ -f "downloads/cmake-${CMAKE_VERSION}-macos-universal.tar.gz" ]; then - echo "Downloading CMake" - mkdir -p downloads - curl --location --progress-bar "https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}/cmake-${CMAKE_VERSION}-macos-universal.tar.gz" --output downloads/cmake-${CMAKE_VERSION}-macos-universal.tar.gz - fi - - echo "Installing CMake" - mkdir -p tools - tar -xzf downloads/cmake-${CMAKE_VERSION}-macos-universal.tar.gz - mv cmake-${CMAKE_VERSION}-macos-universal/CMake.app tools - rm -rf cmake-${CMAKE_VERSION}-macos-universal - fi - export PATH="$PATH:$(pwd)/tools/CMake.app/Contents/bin" -else - if ! [ -d "tools/cmake" ]; then - if ! [ -f "downloads/cmake-${CMAKE_VERSION}-linux-x86_64.tar.gz" ]; then - echo "Downloading CMake" - mkdir -p downloads - curl --location --progress-bar "https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}/cmake-${CMAKE_VERSION}-linux-x86_64.tar.gz" --output downloads/cmake-${CMAKE_VERSION}-linux-x86_64.tar.gz - fi - - echo "Installing CMake" - mkdir -p tools - tar -xzf downloads/cmake-${CMAKE_VERSION}-linux-x86_64.tar.gz - mv cmake-${CMAKE_VERSION}-linux-x86_64/bin tools/cmake - rm -rf cmake-${CMAKE_VERSION}-linux-x86_64 - fi - export PATH="$PATH:$(pwd)/tools/cmake" -fi - -# Create wheels for ninja that can be installed in the host environment -if ! [ -f "dist/ninja-1.11.1-py3-none-any.whl" ]; then - echo "Downloading Ninja" - python -m pip wheel --no-deps -w dist ninja==1.11.1 - mv dist/ninja-1.11.1-*.whl dist/ninja-1.11.1-py3-none-any.whl -fi - -# Create wheels for cmake that can be installed in the host environment -if ! [ -f "dist/cmake-3.29.6-py3-none-any.whl" ]; then - echo "Downloading CMake" - python -m pip wheel --no-deps -w dist cmake==3.29.6 - mv dist/cmake-3.29.6-*.whl dist/cmake-3.29.6-py3-none-any.whl -fi - echo echo "You can now build packages with forge; e.g.:" echo diff --git a/src/forge/build.py b/src/forge/build.py index 1a28a2d3..af899dae 100644 --- a/src/forge/build.py +++ b/src/forge/build.py @@ -245,6 +245,8 @@ def compile_env(self, **kwargs) -> dict[str, str]: if (self.cross_venv.sdk_root / "usr" / "include").is_dir(): cflags += f" -I{self.cross_venv.sdk_root}/usr/include" + cppflags += f" -mios-version-min={self.cross_venv.sdk_version}" + ldflags = self.cross_venv.sysconfig_data["LDFLAGS"] # -lpython3.x @@ -554,11 +556,11 @@ def prepare(self, clean=True): pyproject = tomllib.load(f) # Install the build requirements in the cross environment - self.cross_venv.pip_install( - self.log_file, - ["build", "wheel"] + pyproject["build-system"]["requires"], - paths=[Path.cwd() / "dist"], - ) + # self.cross_venv.pip_install( + # self.log_file, + # ["build", "wheel"] + pyproject["build-system"]["requires"], + # paths=[Path.cwd() / "dist"], + # ) # Install the build requirements in the build environment self.cross_venv.pip_install( @@ -659,6 +661,9 @@ def _build(self): # Set the cross host platform in the environment env["_PYTHON_HOST_PLATFORM"] = self.cross_venv.platform_identifier + env["_PYTHON_SYSCONFIGDATA_NAME"] = ( + f"_sysconfigdata__{self.cross_venv.host_os.lower()}_{self.cross_venv.arch}-{self.cross_venv.sdk}" + ) meson_cross_file = self._create_meson_cross(env) diff --git a/src/forge/cross.py b/src/forge/cross.py index f6b5b6ea..4a7a2e40 100644 --- a/src/forge/cross.py +++ b/src/forge/cross.py @@ -362,33 +362,21 @@ def cross_kwargs(self, kwargs): venv_kwargs = kwargs.copy() env = venv_kwargs.get("env", {}) - # Remove the current venv from the path, and add the cross-env and the - # build-env, and clean out any other problematic paths. - clean_path = [ - p - for p in os.getenv("PATH").split(os.pathsep)[1:] - if not ( - # Exclude rbenv, npm, and other language environments - p.startswith(f"{Path.home()}/.") - and not p.startswith(f"{Path.home()}/.cargo") - # Exclude homebrew - or p.startswith("/opt") - # Exclude local python installs - or p.startswith("/Library/Frameworks") - # Exclude cryptexd - or p.startswith("/var") - or p.startswith("/System") - ) - ] - # Ensure the path is clean, and doesn't include any non-iOS paths. env["PATH"] = os.pathsep.join( [ str(self.host_python_home / "bin"), + str(self.venv_path / "cross" / "bin"), + str(self.venv_path / "build" / "bin"), str(self.venv_path / "bin"), str(self.venv_path / self.venv_path.name / "bin"), + str(Path.home() / ".cargo/bin"), + "/usr/bin", + "/bin", + "/usr/sbin", + "/sbin", + "/Library/Apple/usr/bin", ] - + clean_path ) # Set VIRTUALENV to the active venv diff --git a/src/forge/package.py b/src/forge/package.py index 58317590..9e56aa6e 100644 --- a/src/forge/package.py +++ b/src/forge/package.py @@ -8,12 +8,7 @@ import jsonschema import yaml -from forge.build import ( - Builder, - CMakePackageBuilder, - PythonPackageBuilder, - SimplePackageBuilder, -) +from forge.build import Builder, PythonPackageBuilder, SimplePackageBuilder from forge.cross import CrossVEnv @@ -121,8 +116,4 @@ def builder(self, cross_venv: CrossVEnv) -> Builder: if self.meta["source"] == "pypi": return PythonPackageBuilder(cross_venv=cross_venv, package=self) else: - if "cmake" in self.meta["requirements"]["build"]: - self.meta["requirements"]["build"].remove("cmake") - return CMakePackageBuilder(cross_venv=cross_venv, package=self) - else: - return SimplePackageBuilder(cross_venv=cross_venv, package=self) + return SimplePackageBuilder(cross_venv=cross_venv, package=self) From 51b07e7527815b9abbf7e9e0f22a825664f8bd8b Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Wed, 11 Sep 2024 14:56:03 -0700 Subject: [PATCH 005/142] Explicit _PYTHON_SYSCONFIGDATA_NAME, cleanup --- recipes/argon2-cffi-bindings/meta.yaml | 4 ---- recipes/bcrypt/meta.yaml | 7 +------ recipes/contourpy/meta.yaml | 6 +++--- recipes/cryptography/meta.yaml | 5 +---- recipes/pydantic-core/meta.yaml | 6 +++--- src/forge/build.py | 4 +--- src/forge/cross.py | 6 +++++- 7 files changed, 14 insertions(+), 24 deletions(-) diff --git a/recipes/argon2-cffi-bindings/meta.yaml b/recipes/argon2-cffi-bindings/meta.yaml index 04780dc4..236b2240 100644 --- a/recipes/argon2-cffi-bindings/meta.yaml +++ b/recipes/argon2-cffi-bindings/meta.yaml @@ -1,7 +1,3 @@ package: name: argon2-cffi-bindings version: 21.2.0 - -requirements: - build: - - cffi diff --git a/recipes/bcrypt/meta.yaml b/recipes/bcrypt/meta.yaml index 50a8f3af..b38e2dbd 100644 --- a/recipes/bcrypt/meta.yaml +++ b/recipes/bcrypt/meta.yaml @@ -1,8 +1,3 @@ package: name: bcrypt - version: 4.2.0 - -requirements: - build: - - setuptools_rust @ git+https://github.com/flet-dev/setuptools-rust@ios-support - - cffi + version: 4.2.0 \ No newline at end of file diff --git a/recipes/contourpy/meta.yaml b/recipes/contourpy/meta.yaml index 9190a767..f042ca45 100644 --- a/recipes/contourpy/meta.yaml +++ b/recipes/contourpy/meta.yaml @@ -8,6 +8,6 @@ build: - -Csetup-args={MESON_CROSS_FILE} requirements: - host: - - meson - - ninja \ No newline at end of file + build: + - ninja + - cmake \ No newline at end of file diff --git a/recipes/cryptography/meta.yaml b/recipes/cryptography/meta.yaml index 1e2bacd1..1e873552 100644 --- a/recipes/cryptography/meta.yaml +++ b/recipes/cryptography/meta.yaml @@ -6,11 +6,8 @@ build: script_env: #OPENSSL_STATIC: 1 OPENSSL_DIR: '{platlib}/opt' + _PYTHON_SYSCONFIGDATA_NAME: '{sysconfigdata_name}' requirements: - build: - - setuptools_rust @ git+https://github.com/flet-dev/setuptools-rust@ios-support - host: - - cffi - openssl ^3.0.12 diff --git a/recipes/pydantic-core/meta.yaml b/recipes/pydantic-core/meta.yaml index 14ce49ca..981269f2 100644 --- a/recipes/pydantic-core/meta.yaml +++ b/recipes/pydantic-core/meta.yaml @@ -2,6 +2,6 @@ package: name: pydantic-core version: 2.18.4 -requirements: - build: - - maturin \ No newline at end of file +build: + script_env: + _PYTHON_SYSCONFIGDATA_NAME: '{sysconfigdata_name}' \ No newline at end of file diff --git a/src/forge/build.py b/src/forge/build.py index af899dae..f211630a 100644 --- a/src/forge/build.py +++ b/src/forge/build.py @@ -650,6 +650,7 @@ def _build(self): **env, **self.cross_venv.scheme_paths, **self.cross_venv.sysconfig_data, + "sysconfigdata_name": self.cross_venv.sysconfigdata_name, } # Set up any additional environment variables needed in the script environment. @@ -661,9 +662,6 @@ def _build(self): # Set the cross host platform in the environment env["_PYTHON_HOST_PLATFORM"] = self.cross_venv.platform_identifier - env["_PYTHON_SYSCONFIGDATA_NAME"] = ( - f"_sysconfigdata__{self.cross_venv.host_os.lower()}_{self.cross_venv.arch}-{self.cross_venv.sdk}" - ) meson_cross_file = self._create_meson_cross(env) diff --git a/src/forge/cross.py b/src/forge/cross.py index 4a7a2e40..57f4de8f 100644 --- a/src/forge/cross.py +++ b/src/forge/cross.py @@ -256,10 +256,14 @@ def create( if not host_python.is_file(): raise RuntimeError(f"Can't find host python {host_python}") + self.sysconfigdata_name = ( + f"_sysconfigdata__{self.host_os.lower()}_{self.arch}-{self.sdk}" + ) + host_sysconfig = ( self.host_python_home / f"lib/python3.{sys.version_info.minor}" - / f"_sysconfigdata__{self.host_os.lower()}_{self.arch}-{self.sdk}.py" + / f"{self.sysconfigdata_name}.py" ) if not host_sysconfig.is_file(): raise RuntimeError(f"Can't find host sysconfig {host_sysconfig}") From 018045324a50eedfd7694b4a011f2b7acfba5e33 Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Thu, 12 Sep 2024 10:16:32 -0700 Subject: [PATCH 006/142] Blis 1.0.0, numpy 2.1.1 --- .appveyor.yml | 22 ++++++++--------- recipes/blis/meta.yaml | 4 ++-- recipes/blis/patches/mobile.patch | 39 +++++++++++++++++++++++++++---- recipes/matplotlib/meta.yaml | 2 +- recipes/numpy/meta.yaml | 2 +- recipes/pandas/meta.yaml | 2 +- 6 files changed, 51 insertions(+), 20 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index 6c5a7612..f56b8745 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -29,37 +29,37 @@ environment: - job_name: 'Android arm64-v8a: opencv-python' job_group: build_android FORGE_ARCH: 'android:arm64-v8a' - FORGE_PACKAGES: numpy:2.0.0 opencv-python:4.10.0.84 + FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 - job_name: 'Android armeabi-v7a: opencv-python' job_group: build_android FORGE_ARCH: 'android:armeabi-v7a' - FORGE_PACKAGES: numpy:2.0.0 opencv-python:4.10.0.84 + FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 - job_name: 'Android x86_64: opencv-python' job_group: build_android FORGE_ARCH: 'android:x86_64' - FORGE_PACKAGES: numpy:2.0.0 opencv-python:4.10.0.84 + FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 - job_name: 'Android x86: opencv-python' job_group: build_android FORGE_ARCH: 'android:x86' - FORGE_PACKAGES: numpy:2.0.0 opencv-python:4.10.0.84 + FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 - job_name: 'iOS iphone arm64: opencv-python' job_group: build_ios FORGE_ARCH: 'iphoneos:arm64' - FORGE_PACKAGES: numpy:2.0.0 opencv-python:4.10.0.84 + FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 - job_name: 'iOS simulator arm64: opencv-python' job_group: build_ios FORGE_ARCH: 'iphonesimulator:arm64' - FORGE_PACKAGES: numpy:2.0.0 opencv-python:4.10.0.84 + FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 - job_name: 'iOS simulator x86_64: opencv-python' job_group: build_ios FORGE_ARCH: 'iphonesimulator:x86_64' - FORGE_PACKAGES: numpy:2.0.0 opencv-python:4.10.0.84 + FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 - job_name: 'Android: pydantic-core, pillow, lru-dict, contourpy, kiwisolver, aiohttp, bitarray, argon2-cffi-binding, bcrypt, cryptography, brotli, websockets' job_group: build_android @@ -88,10 +88,10 @@ environment: FORGE_ARCH: android FORGE_PACKAGES: >- numpy:1.26.4 - numpy:2.0.0 + numpy:2.1.1 matplotlib:3.9.0 pandas:2.2.2 - blis:0.9.1 + blis:1.0.0 - job_name: 'iOS: pillow, lru-dict, yarl, contourpy, kiwisolver, aiohttp, bitarray, websockets' job_group: build_ios @@ -130,10 +130,10 @@ environment: FORGE_ARCH: iOS FORGE_PACKAGES: >- numpy:1.26.4 - numpy:2.0.0 + numpy:2.1.1 matplotlib:3.9.0 pandas:2.2.2 - blis:0.9.1 + blis:1.0.0 - job_name: Re-build Simple index job_group: rebuild_index diff --git a/recipes/blis/meta.yaml b/recipes/blis/meta.yaml index 91252e0a..faebf519 100644 --- a/recipes/blis/meta.yaml +++ b/recipes/blis/meta.yaml @@ -1,10 +1,10 @@ package: name: blis - version: 0.9.1 + version: 1.0.0 patches: - mobile.patch requirements: host: - - numpy 1.26.4 \ No newline at end of file + - numpy ^2.0.0 \ No newline at end of file diff --git a/recipes/blis/patches/mobile.patch b/recipes/blis/patches/mobile.patch index 28559404..479017ad 100644 --- a/recipes/blis/patches/mobile.patch +++ b/recipes/blis/patches/mobile.patch @@ -1,7 +1,9 @@ +diff --git a/blis/_src/frame/thread/bli_pthread.c b/blis/_src/frame/thread/bli_pthread.c +index a099356..6d5fe03 100644 --- a/blis/_src/frame/thread/bli_pthread.c +++ b/blis/_src/frame/thread/bli_pthread.c @@ -594,7 +594,7 @@ int bli_pthread_barrier_wait - return 0; + return 0; } -#elif defined(__APPLE__) || defined(_MSC_VER) // !defined(BLIS_DISABLE_SYSTEM) @@ -23,10 +25,18 @@ index d5158ff..bf3fbe5 100644 // For OS X, we must define the barrier types ourselves since Apple does // not implement barriers in their variant of pthreads. diff --git a/setup.py b/setup.py -index 332cab3..bdd673e 100644 +index d0944c9..6b3c19e 100644 --- a/setup.py +++ b/setup.py -@@ -37,6 +37,10 @@ PLATFORM_TO_ARCH = { +@@ -21,6 +21,7 @@ import subprocess + import sys + import platform + import numpy ++import sysconfig + + + PLATFORM_TO_ARCH = { +@@ -36,6 +37,10 @@ PLATFORM_TO_ARCH = { MOD_NAMES = ["blis.cy", "blis.py"] @@ -34,4 +44,25 @@ index 332cab3..bdd673e 100644 +os.environ["BLIS_ARCH"] = "generic" +os.environ["BLIS_COMPILER"] = os.environ["CC"] + - print("BLIS_COMPILER?", os.environ.get("BLIS_COMPILER", "None")) \ No newline at end of file + print("BLIS_COMPILER?", os.environ.get("BLIS_COMPILER", "None")) + + +@@ -220,6 +225,9 @@ class ExtensionBuilder(build_ext, build_ext_options): + objects = [] + platform_arch = platform + "-" + py_arch + compiler = self.get_compiler_name() ++ host_triplet = sysconfig.get_platform().split("-") ++ print("Host triplet:", host_triplet) ++ + with open(os.path.join(BLIS_DIR, "make", "%s.jsonl" % platform_arch)) as file_: + env = {} + for line in file_: +@@ -255,6 +263,8 @@ class ExtensionBuilder(build_ext, build_ext_options): + spec["flags"] = [ + f for f in spec["flags"] if "visibility=hidden" not in f + ] ++ if len(host_triplet) == 4 and host_triplet[0] == "ios": ++ spec["flags"].append(f"-mios-version-min={host_triplet[1]}") + objects.append(self.build_object(env=env, **spec)) + return objects + diff --git a/recipes/matplotlib/meta.yaml b/recipes/matplotlib/meta.yaml index 97eda173..8717df79 100644 --- a/recipes/matplotlib/meta.yaml +++ b/recipes/matplotlib/meta.yaml @@ -7,7 +7,7 @@ requirements: - meson - ninja host: - - numpy 2.0.0 + - numpy ^2.0.0 build: backend-args: diff --git a/recipes/numpy/meta.yaml b/recipes/numpy/meta.yaml index 969053d8..563f11c7 100644 --- a/recipes/numpy/meta.yaml +++ b/recipes/numpy/meta.yaml @@ -3,7 +3,7 @@ package: name: numpy - version: 1.26.4 + version: 2.1.1 requirements: build: diff --git a/recipes/pandas/meta.yaml b/recipes/pandas/meta.yaml index 1a7b6711..3385206e 100644 --- a/recipes/pandas/meta.yaml +++ b/recipes/pandas/meta.yaml @@ -7,7 +7,7 @@ requirements: - meson - ninja host: - - numpy 2.0.0 + - numpy ^2.0.0 build: backend-args: From ba1188553290e1b8c4a47202fab5b7f500efab83 Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Thu, 12 Sep 2024 10:55:16 -0700 Subject: [PATCH 007/142] websockets 13.0.1 --- .appveyor.yml | 80 ++++++++++++++++++------------------ recipes/websockets/meta.yaml | 2 +- src/forge/build.py | 2 + 3 files changed, 43 insertions(+), 41 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index f56b8745..5b764498 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -18,33 +18,33 @@ environment: # job_group: build_android # FORGE_ARCH: android # FORGE_PACKAGES: >- - # websockets:12.0 + # websockets:13.0.1 # - job_name: 'iOS: websockets' # job_group: build_ios # FORGE_ARCH: iOS # FORGE_PACKAGES: >- - # websockets:12.0 + # websockets:13.0.1 - - job_name: 'Android arm64-v8a: opencv-python' - job_group: build_android - FORGE_ARCH: 'android:arm64-v8a' - FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 + # - job_name: 'Android arm64-v8a: opencv-python' + # job_group: build_android + # FORGE_ARCH: 'android:arm64-v8a' + # FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 - - job_name: 'Android armeabi-v7a: opencv-python' - job_group: build_android - FORGE_ARCH: 'android:armeabi-v7a' - FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 + # - job_name: 'Android armeabi-v7a: opencv-python' + # job_group: build_android + # FORGE_ARCH: 'android:armeabi-v7a' + # FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 - - job_name: 'Android x86_64: opencv-python' - job_group: build_android - FORGE_ARCH: 'android:x86_64' - FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 + # - job_name: 'Android x86_64: opencv-python' + # job_group: build_android + # FORGE_ARCH: 'android:x86_64' + # FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 - - job_name: 'Android x86: opencv-python' - job_group: build_android - FORGE_ARCH: 'android:x86' - FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 + # - job_name: 'Android x86: opencv-python' + # job_group: build_android + # FORGE_ARCH: 'android:x86' + # FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 - job_name: 'iOS iphone arm64: opencv-python' job_group: build_ios @@ -61,27 +61,27 @@ environment: FORGE_ARCH: 'iphonesimulator:x86_64' FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 - - job_name: 'Android: pydantic-core, pillow, lru-dict, contourpy, kiwisolver, aiohttp, bitarray, argon2-cffi-binding, bcrypt, cryptography, brotli, websockets' - job_group: build_android - FORGE_ARCH: android - FORGE_PACKAGES: >- - cffi:1.17.1 - libjpeg:3.0.3 - libpng:1.6.43 - freetype:2.13.3 - pillow:10.4.0 - lru-dict:1.3.0 - yarl:1.9.4 - contourpy:1.2.1 - kiwisolver:1.4.5 - aiohttp:3.9.5 - bitarray:2.9.2 - argon2-cffi-bindings:21.2.0 - bcrypt:4.2.0 - cryptography:43.0.1 - brotli:1.1.0 - pydantic-core:2.18.4 - websockets:12.0 + # - job_name: 'Android: pydantic-core, pillow, lru-dict, contourpy, kiwisolver, aiohttp, bitarray, argon2-cffi-binding, bcrypt, cryptography, brotli, websockets' + # job_group: build_android + # FORGE_ARCH: android + # FORGE_PACKAGES: >- + # cffi:1.17.1 + # libjpeg:3.0.3 + # libpng:1.6.43 + # freetype:2.13.3 + # pillow:10.4.0 + # lru-dict:1.3.0 + # yarl:1.9.4 + # contourpy:1.2.1 + # kiwisolver:1.4.5 + # aiohttp:3.9.5 + # bitarray:2.9.2 + # argon2-cffi-bindings:21.2.0 + # bcrypt:4.2.0 + # cryptography:43.0.1 + # brotli:1.1.0 + # pydantic-core:2.18.4 + # websockets:13.0.1 - job_name: 'Android: numpy, matplotlib, pandas, blis' job_group: build_android @@ -107,7 +107,7 @@ environment: kiwisolver:1.4.5 aiohttp:3.9.5 bitarray:2.9.2 - websockets:12.0 + websockets:13.0.1 - job_name: 'iOS: cffi, argon2-cffi-bindings, bcrypt, cryptography, brotli' job_group: build_ios diff --git a/recipes/websockets/meta.yaml b/recipes/websockets/meta.yaml index 7e331d03..a4f7c61f 100644 --- a/recipes/websockets/meta.yaml +++ b/recipes/websockets/meta.yaml @@ -1,3 +1,3 @@ package: name: websockets - version: '12.0' \ No newline at end of file + version: 13.0.1 \ No newline at end of file diff --git a/src/forge/build.py b/src/forge/build.py index f211630a..55bb79f6 100644 --- a/src/forge/build.py +++ b/src/forge/build.py @@ -275,6 +275,8 @@ def compile_env(self, **kwargs) -> dict[str, str]: ldflags += f' -F "{self.cross_venv.host_python_home}"' cargo_ldflags += f" -C link-arg=-F{self.cross_venv.host_python_home} -C link-arg=-framework -C link-arg=Python" + cargo_ldflags += f" -C link-arg=-L -C link-arg=/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS17.5.sdk" + cargo_build_target = ( { "arm64-apple-ios": "aarch64-apple-ios", From 6157eaf23b0a9874be6704781ca849a77dfd304d Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Thu, 12 Sep 2024 12:56:19 -0700 Subject: [PATCH 008/142] cryptography 43.0.1 --- recipes/cryptography/meta.yaml | 3 +-- src/forge/build.py | 4 +--- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/recipes/cryptography/meta.yaml b/recipes/cryptography/meta.yaml index 1e873552..a5e27a89 100644 --- a/recipes/cryptography/meta.yaml +++ b/recipes/cryptography/meta.yaml @@ -1,10 +1,9 @@ package: name: cryptography - version: 42.0.7 + version: 43.0.1 build: script_env: - #OPENSSL_STATIC: 1 OPENSSL_DIR: '{platlib}/opt' _PYTHON_SYSCONFIGDATA_NAME: '{sysconfigdata_name}' diff --git a/src/forge/build.py b/src/forge/build.py index 55bb79f6..5c9a039c 100644 --- a/src/forge/build.py +++ b/src/forge/build.py @@ -258,7 +258,7 @@ def compile_env(self, **kwargs) -> dict[str, str]: # cargo_ldflags = re.sub(r"-march=[\w-]+", "", ldflags) cargo_ldflags = " -L{}/lib".format(self.cross_venv.sysconfig_data["prefix"]) - # cargo_ldflags += " -C link-arg=-undefined -C link-arg=dynamic_lookup" + cargo_ldflags += " -C link-arg=-undefined -C link-arg=dynamic_lookup" if self.cross_venv.sdk != "android": @@ -275,8 +275,6 @@ def compile_env(self, **kwargs) -> dict[str, str]: ldflags += f' -F "{self.cross_venv.host_python_home}"' cargo_ldflags += f" -C link-arg=-F{self.cross_venv.host_python_home} -C link-arg=-framework -C link-arg=Python" - cargo_ldflags += f" -C link-arg=-L -C link-arg=/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS17.5.sdk" - cargo_build_target = ( { "arm64-apple-ios": "aarch64-apple-ios", From 33f00c6529a23e33098c8ef7a1e753844543d911 Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Thu, 12 Sep 2024 13:00:48 -0700 Subject: [PATCH 009/142] pydantic-core 2.23.3 --- .appveyor.yml | 4 ++-- recipes/pydantic-core/meta.yaml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index 5b764498..1d334bee 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -80,7 +80,7 @@ environment: # bcrypt:4.2.0 # cryptography:43.0.1 # brotli:1.1.0 - # pydantic-core:2.18.4 + # pydantic-core:2.23.3 # websockets:13.0.1 - job_name: 'Android: numpy, matplotlib, pandas, blis' @@ -123,7 +123,7 @@ environment: job_group: build_ios FORGE_ARCH: iOS FORGE_PACKAGES: >- - pydantic-core:2.18.4 + pydantic-core:2.23.3 - job_name: 'iOS: numpy, matplotlib, pandas, blis' job_group: build_ios diff --git a/recipes/pydantic-core/meta.yaml b/recipes/pydantic-core/meta.yaml index 981269f2..7081779d 100644 --- a/recipes/pydantic-core/meta.yaml +++ b/recipes/pydantic-core/meta.yaml @@ -1,6 +1,6 @@ package: name: pydantic-core - version: 2.18.4 + version: 2.23.3 build: script_env: From 864952b85e4bece42cdce18a028d33960c2ffc6e Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Thu, 12 Sep 2024 13:05:43 -0700 Subject: [PATCH 010/142] contourpy 1.3.0, matplotlib 3.9.2, yarl 1.11.1 --- .appveyor.yml | 12 ++++++------ recipes/contourpy/meta.yaml | 2 +- recipes/matplotlib/meta.yaml | 2 +- recipes/yarl/meta.yaml | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index 1d334bee..74b736fe 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -71,8 +71,8 @@ environment: # freetype:2.13.3 # pillow:10.4.0 # lru-dict:1.3.0 - # yarl:1.9.4 - # contourpy:1.2.1 + # yarl:1.11.1 + # contourpy:1.3.0 # kiwisolver:1.4.5 # aiohttp:3.9.5 # bitarray:2.9.2 @@ -89,7 +89,7 @@ environment: FORGE_PACKAGES: >- numpy:1.26.4 numpy:2.1.1 - matplotlib:3.9.0 + matplotlib:3.9.2 pandas:2.2.2 blis:1.0.0 @@ -102,8 +102,8 @@ environment: freetype:2.13.3 pillow:10.4.0 lru-dict:1.3.0 - yarl:1.9.4 - contourpy:1.2.1 + yarl:1.11.1 + contourpy:1.3.0 kiwisolver:1.4.5 aiohttp:3.9.5 bitarray:2.9.2 @@ -131,7 +131,7 @@ environment: FORGE_PACKAGES: >- numpy:1.26.4 numpy:2.1.1 - matplotlib:3.9.0 + matplotlib:3.9.2 pandas:2.2.2 blis:1.0.0 diff --git a/recipes/contourpy/meta.yaml b/recipes/contourpy/meta.yaml index f042ca45..537c8280 100644 --- a/recipes/contourpy/meta.yaml +++ b/recipes/contourpy/meta.yaml @@ -1,6 +1,6 @@ package: name: contourpy - version: 1.2.1 + version: 1.3.0 build: backend-args: diff --git a/recipes/matplotlib/meta.yaml b/recipes/matplotlib/meta.yaml index 8717df79..b7fdb95d 100644 --- a/recipes/matplotlib/meta.yaml +++ b/recipes/matplotlib/meta.yaml @@ -1,6 +1,6 @@ package: name: matplotlib - version: 3.9.0 + version: 3.9.2 requirements: build: diff --git a/recipes/yarl/meta.yaml b/recipes/yarl/meta.yaml index ed7d6881..f543372b 100644 --- a/recipes/yarl/meta.yaml +++ b/recipes/yarl/meta.yaml @@ -1,6 +1,6 @@ package: name: yarl - version: 1.9.4 + version: 1.11.1 requirements: build: From 234628003c5e880b3fc74f9113158a69952f23ee Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Thu, 12 Sep 2024 19:50:13 -0700 Subject: [PATCH 011/142] Try building iOS packages --- .appveyor.yml | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index 74b736fe..0772f869 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -224,8 +224,8 @@ for: install: # download Python for iOS - - python_ios_dir=$HOME/projects/python-ios - - curl -#OL https://github.com/flet-dev/python-ios/releases/download/v${PYTHON_VERSION}/python-ios-install-${PYTHON_VERSION}.tar.gz + - python_ios_dir=$HOME/projects/python-darwin/Python-Apple-support + - curl -#OL https://github.com/flet-dev/python-ios/releases/download/v${PYTHON_SHORT_VERSION}/python-ios-install-${PYTHON_SHORT_VERSION}.tar.gz - mkdir -p $python_ios_dir - tar -xzf python-ios-install-${PYTHON_VERSION}.tar.gz -C $python_ios_dir @@ -238,7 +238,7 @@ for: - rustup target add x86_64-apple-ios # configure forge - - export PYTHON_APPLE_SUPPORT=$python_ios_dir + - export MOBILE_FORGE_IOS_SUPPORT_PATH=$python_ios_dir - source ./setup.sh $PYTHON_VERSION # refresh PATH @@ -252,8 +252,6 @@ for: done # cleanup - - rm dist/ninja-* - - rm dist/cmake-* - rm dist/bzip2-* - rm dist/xz-* - rm dist/libffi-* From d9f671cce97bfdc336ee3f7ffee7cad4a619ad48 Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Thu, 12 Sep 2024 19:52:05 -0700 Subject: [PATCH 012/142] Build a few iOS packages only --- .appveyor.yml | 138 +++++++++++++++++++++++++------------------------- 1 file changed, 69 insertions(+), 69 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index 0772f869..e9208b75 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -20,11 +20,11 @@ environment: # FORGE_PACKAGES: >- # websockets:13.0.1 - # - job_name: 'iOS: websockets' - # job_group: build_ios - # FORGE_ARCH: iOS - # FORGE_PACKAGES: >- - # websockets:13.0.1 + - job_name: 'iOS: websockets' + job_group: build_ios + FORGE_ARCH: iOS + FORGE_PACKAGES: >- + websockets:13.0.1 # - job_name: 'Android arm64-v8a: opencv-python' # job_group: build_android @@ -46,20 +46,20 @@ environment: # FORGE_ARCH: 'android:x86' # FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 - - job_name: 'iOS iphone arm64: opencv-python' - job_group: build_ios - FORGE_ARCH: 'iphoneos:arm64' - FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 + # - job_name: 'iOS iphone arm64: opencv-python' + # job_group: build_ios + # FORGE_ARCH: 'iphoneos:arm64' + # FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 - - job_name: 'iOS simulator arm64: opencv-python' - job_group: build_ios - FORGE_ARCH: 'iphonesimulator:arm64' - FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 + # - job_name: 'iOS simulator arm64: opencv-python' + # job_group: build_ios + # FORGE_ARCH: 'iphonesimulator:arm64' + # FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 - - job_name: 'iOS simulator x86_64: opencv-python' - job_group: build_ios - FORGE_ARCH: 'iphonesimulator:x86_64' - FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 + # - job_name: 'iOS simulator x86_64: opencv-python' + # job_group: build_ios + # FORGE_ARCH: 'iphonesimulator:x86_64' + # FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 # - job_name: 'Android: pydantic-core, pillow, lru-dict, contourpy, kiwisolver, aiohttp, bitarray, argon2-cffi-binding, bcrypt, cryptography, brotli, websockets' # job_group: build_android @@ -83,61 +83,61 @@ environment: # pydantic-core:2.23.3 # websockets:13.0.1 - - job_name: 'Android: numpy, matplotlib, pandas, blis' - job_group: build_android - FORGE_ARCH: android - FORGE_PACKAGES: >- - numpy:1.26.4 - numpy:2.1.1 - matplotlib:3.9.2 - pandas:2.2.2 - blis:1.0.0 + # - job_name: 'Android: numpy, matplotlib, pandas, blis' + # job_group: build_android + # FORGE_ARCH: android + # FORGE_PACKAGES: >- + # numpy:1.26.4 + # numpy:2.1.1 + # matplotlib:3.9.2 + # pandas:2.2.2 + # blis:1.0.0 - - job_name: 'iOS: pillow, lru-dict, yarl, contourpy, kiwisolver, aiohttp, bitarray, websockets' - job_group: build_ios - FORGE_ARCH: iOS - FORGE_PACKAGES: >- - libjpeg:3.0.3 - libpng:1.6.43 - freetype:2.13.3 - pillow:10.4.0 - lru-dict:1.3.0 - yarl:1.11.1 - contourpy:1.3.0 - kiwisolver:1.4.5 - aiohttp:3.9.5 - bitarray:2.9.2 - websockets:13.0.1 + # - job_name: 'iOS: pillow, lru-dict, yarl, contourpy, kiwisolver, aiohttp, bitarray, websockets' + # job_group: build_ios + # FORGE_ARCH: iOS + # FORGE_PACKAGES: >- + # libjpeg:3.0.3 + # libpng:1.6.43 + # freetype:2.13.3 + # pillow:10.4.0 + # lru-dict:1.3.0 + # yarl:1.11.1 + # contourpy:1.3.0 + # kiwisolver:1.4.5 + # aiohttp:3.9.5 + # bitarray:2.9.2 + # websockets:13.0.1 - - job_name: 'iOS: cffi, argon2-cffi-bindings, bcrypt, cryptography, brotli' - job_group: build_ios - FORGE_ARCH: iOS - FORGE_PACKAGES: >- - cffi:1.17.1 - argon2-cffi-bindings:21.2.0 - bcrypt:4.2.0 - cryptography:43.0.1 - brotli:1.1.0 - - - job_name: 'iOS: pydantic-core' - job_group: build_ios - FORGE_ARCH: iOS - FORGE_PACKAGES: >- - pydantic-core:2.23.3 + # - job_name: 'iOS: cffi, argon2-cffi-bindings, bcrypt, cryptography, brotli' + # job_group: build_ios + # FORGE_ARCH: iOS + # FORGE_PACKAGES: >- + # cffi:1.17.1 + # argon2-cffi-bindings:21.2.0 + # bcrypt:4.2.0 + # cryptography:43.0.1 + # brotli:1.1.0 - - job_name: 'iOS: numpy, matplotlib, pandas, blis' - job_group: build_ios - FORGE_ARCH: iOS - FORGE_PACKAGES: >- - numpy:1.26.4 - numpy:2.1.1 - matplotlib:3.9.2 - pandas:2.2.2 - blis:1.0.0 - - - job_name: Re-build Simple index - job_group: rebuild_index - job_depends_on: build_android, build_ios + # - job_name: 'iOS: pydantic-core' + # job_group: build_ios + # FORGE_ARCH: iOS + # FORGE_PACKAGES: >- + # pydantic-core:2.23.3 + + # - job_name: 'iOS: numpy, matplotlib, pandas, blis' + # job_group: build_ios + # FORGE_ARCH: iOS + # FORGE_PACKAGES: >- + # numpy:1.26.4 + # numpy:2.1.1 + # matplotlib:3.9.2 + # pandas:2.2.2 + # blis:1.0.0 + + # - job_name: Re-build Simple index + # job_group: rebuild_index + # job_depends_on: build_android, build_ios stack: - python $PYTHON_SHORT_VERSION From b99f03e42fdfaabd368c3e8cd96669ed3a279334 Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Thu, 12 Sep 2024 19:55:52 -0700 Subject: [PATCH 013/142] Fix archive path --- .appveyor.yml | 2 +- setup.sh | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index e9208b75..c774805c 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -227,7 +227,7 @@ for: - python_ios_dir=$HOME/projects/python-darwin/Python-Apple-support - curl -#OL https://github.com/flet-dev/python-ios/releases/download/v${PYTHON_SHORT_VERSION}/python-ios-install-${PYTHON_SHORT_VERSION}.tar.gz - mkdir -p $python_ios_dir - - tar -xzf python-ios-install-${PYTHON_VERSION}.tar.gz -C $python_ios_dir + - tar -xzf python-ios-install-${PYTHON_SHORT_VERSION}.tar.gz -C $python_ios_dir # install Rust - curl https://sh.rustup.rs -sSf | sh -s -- -y diff --git a/setup.sh b/setup.sh index ace10612..4c32151f 100755 --- a/setup.sh +++ b/setup.sh @@ -29,7 +29,6 @@ PYTHON_URL_PREFIX=https://github.com/indygreg/python-build-standalone/releases/d PYTHON_VERSION=$1 read python_version_major python_version_minor < <(echo $PYTHON_VERSION | sed -E 's/^([0-9]+)\.([0-9]+).*/\1 \2/') PYTHON_VER=$python_version_major.$python_version_minor -CMAKE_VERSION="3.27.4" echo "Python version: $PYTHON_VERSION" echo "Python short version: $PYTHON_VER" From 6fcc4ae316331b740bfb7becc8b85aad69bf367d Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Thu, 12 Sep 2024 20:02:24 -0700 Subject: [PATCH 014/142] Build more iOS packages --- .appveyor.yml | 74 +++++++++++++++++++++++++-------------------------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index c774805c..b0262305 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -20,11 +20,11 @@ environment: # FORGE_PACKAGES: >- # websockets:13.0.1 - - job_name: 'iOS: websockets' - job_group: build_ios - FORGE_ARCH: iOS - FORGE_PACKAGES: >- - websockets:13.0.1 + # - job_name: 'iOS: websockets' + # job_group: build_ios + # FORGE_ARCH: iOS + # FORGE_PACKAGES: >- + # websockets:13.0.1 # - job_name: 'Android arm64-v8a: opencv-python' # job_group: build_android @@ -46,10 +46,10 @@ environment: # FORGE_ARCH: 'android:x86' # FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 - # - job_name: 'iOS iphone arm64: opencv-python' - # job_group: build_ios - # FORGE_ARCH: 'iphoneos:arm64' - # FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 + - job_name: 'iOS iphone arm64: opencv-python' + job_group: build_ios + FORGE_ARCH: 'iphoneos:arm64' + FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 # - job_name: 'iOS simulator arm64: opencv-python' # job_group: build_ios @@ -109,35 +109,35 @@ environment: # bitarray:2.9.2 # websockets:13.0.1 - # - job_name: 'iOS: cffi, argon2-cffi-bindings, bcrypt, cryptography, brotli' - # job_group: build_ios - # FORGE_ARCH: iOS - # FORGE_PACKAGES: >- - # cffi:1.17.1 - # argon2-cffi-bindings:21.2.0 - # bcrypt:4.2.0 - # cryptography:43.0.1 - # brotli:1.1.0 - - # - job_name: 'iOS: pydantic-core' - # job_group: build_ios - # FORGE_ARCH: iOS - # FORGE_PACKAGES: >- - # pydantic-core:2.23.3 - - # - job_name: 'iOS: numpy, matplotlib, pandas, blis' - # job_group: build_ios - # FORGE_ARCH: iOS - # FORGE_PACKAGES: >- - # numpy:1.26.4 - # numpy:2.1.1 - # matplotlib:3.9.2 - # pandas:2.2.2 - # blis:1.0.0 + - job_name: 'iOS: cffi, argon2-cffi-bindings, bcrypt, cryptography, brotli' + job_group: build_ios + FORGE_ARCH: iOS + FORGE_PACKAGES: >- + cffi:1.17.1 + argon2-cffi-bindings:21.2.0 + bcrypt:4.2.0 + cryptography:43.0.1 + brotli:1.1.0 + + - job_name: 'iOS: pydantic-core' + job_group: build_ios + FORGE_ARCH: iOS + FORGE_PACKAGES: >- + pydantic-core:2.23.3 - # - job_name: Re-build Simple index - # job_group: rebuild_index - # job_depends_on: build_android, build_ios + - job_name: 'iOS: numpy, matplotlib, pandas, blis' + job_group: build_ios + FORGE_ARCH: iOS + FORGE_PACKAGES: >- + numpy:1.26.4 + numpy:2.1.1 + matplotlib:3.9.2 + pandas:2.2.2 + blis:1.0.0 + + - job_name: Re-build Simple index + job_group: rebuild_index + job_depends_on: build_android, build_ios stack: - python $PYTHON_SHORT_VERSION From 554869c6b6b33e67cd18bbb543ceb1f20d641917 Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Thu, 12 Sep 2024 20:16:22 -0700 Subject: [PATCH 015/142] Fix bcrypt build --- recipes/bcrypt/meta.yaml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/recipes/bcrypt/meta.yaml b/recipes/bcrypt/meta.yaml index b38e2dbd..f249fd43 100644 --- a/recipes/bcrypt/meta.yaml +++ b/recipes/bcrypt/meta.yaml @@ -1,3 +1,7 @@ package: name: bcrypt - version: 4.2.0 \ No newline at end of file + version: 4.2.0 + +build: + script_env: + _PYTHON_SYSCONFIGDATA_NAME: '{sysconfigdata_name}' \ No newline at end of file From 4406cdb7b147e1da13f859d2ddf45f4cd3e3b496 Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Thu, 12 Sep 2024 20:51:06 -0700 Subject: [PATCH 016/142] Fix numpy build --- recipes/opencv-python/meta.yaml | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/recipes/opencv-python/meta.yaml b/recipes/opencv-python/meta.yaml index d3b16e75..394a5438 100644 --- a/recipes/opencv-python/meta.yaml +++ b/recipes/opencv-python/meta.yaml @@ -35,6 +35,7 @@ build: -DCMAKE_SYSTEM_NAME=iOS -DCMAKE_SYSTEM_PROCESSOR=aarch64 -DCMAKE_OSX_SYSROOT={{ sdk }} + -DCMAKE_OSX_DEPLOYMENT_TARGET={{ sdk_version }} -DCMAKE_OSX_ARCHITECTURES={{ arch }} -DWITH_IPP=OFF -DWITH_ITT=OFF @@ -51,8 +52,4 @@ build: requirements: host: - - numpy 2.0.0 - build: - - cmake - - scikit-build @ git+https://github.com/flet-dev/scikit-build@ios-android-support - - numpy 2.0.0 + - numpy ^2.0.0 \ No newline at end of file From dba4122d7f2c1ae92eada716a6e263468738537e Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Thu, 12 Sep 2024 20:53:14 -0700 Subject: [PATCH 017/142] kiwisolver 1.4.7 --- .appveyor.yml | 4 ++-- recipes/kiwisolver/meta.yaml | 6 +----- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index b0262305..414b2d3b 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -73,7 +73,7 @@ environment: # lru-dict:1.3.0 # yarl:1.11.1 # contourpy:1.3.0 - # kiwisolver:1.4.5 + # kiwisolver:1.4.7 # aiohttp:3.9.5 # bitarray:2.9.2 # argon2-cffi-bindings:21.2.0 @@ -104,7 +104,7 @@ environment: # lru-dict:1.3.0 # yarl:1.11.1 # contourpy:1.3.0 - # kiwisolver:1.4.5 + # kiwisolver:1.4.7 # aiohttp:3.9.5 # bitarray:2.9.2 # websockets:13.0.1 diff --git a/recipes/kiwisolver/meta.yaml b/recipes/kiwisolver/meta.yaml index 913230cf..a690af34 100644 --- a/recipes/kiwisolver/meta.yaml +++ b/recipes/kiwisolver/meta.yaml @@ -1,7 +1,3 @@ package: name: kiwisolver - version: 1.4.5 - -requirements: - build: - - cppy 1.2.1 + version: 1.4.7 \ No newline at end of file From 584e289082d77c47a685433c34d488f7f9f505c5 Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Fri, 13 Sep 2024 09:06:25 -0700 Subject: [PATCH 018/142] Meta cleanup, build all iOS packages --- .appveyor.yml | 46 ++++++++++++++++----------------- recipes/bitarray/LICENSE | 46 --------------------------------- recipes/blis/meta.yaml | 8 +++--- recipes/cffi/meta.yaml | 6 ++--- recipes/contourpy/meta.yaml | 12 ++++----- recipes/cryptography/meta.yaml | 10 +++---- recipes/matplotlib/meta.yaml | 1 - recipes/numpy/meta.yaml | 2 -- recipes/opencv-python/meta.yaml | 10 +++---- recipes/pandas/meta.yaml | 1 - recipes/pillow/meta.yaml | 14 +++++----- recipes/yarl/meta.yaml | 2 +- 12 files changed, 54 insertions(+), 104 deletions(-) delete mode 100644 recipes/bitarray/LICENSE diff --git a/.appveyor.yml b/.appveyor.yml index 414b2d3b..f408d5c2 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -51,15 +51,15 @@ environment: FORGE_ARCH: 'iphoneos:arm64' FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 - # - job_name: 'iOS simulator arm64: opencv-python' - # job_group: build_ios - # FORGE_ARCH: 'iphonesimulator:arm64' - # FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 + - job_name: 'iOS simulator arm64: opencv-python' + job_group: build_ios + FORGE_ARCH: 'iphonesimulator:arm64' + FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 - # - job_name: 'iOS simulator x86_64: opencv-python' - # job_group: build_ios - # FORGE_ARCH: 'iphonesimulator:x86_64' - # FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 + - job_name: 'iOS simulator x86_64: opencv-python' + job_group: build_ios + FORGE_ARCH: 'iphonesimulator:x86_64' + FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 # - job_name: 'Android: pydantic-core, pillow, lru-dict, contourpy, kiwisolver, aiohttp, bitarray, argon2-cffi-binding, bcrypt, cryptography, brotli, websockets' # job_group: build_android @@ -93,21 +93,21 @@ environment: # pandas:2.2.2 # blis:1.0.0 - # - job_name: 'iOS: pillow, lru-dict, yarl, contourpy, kiwisolver, aiohttp, bitarray, websockets' - # job_group: build_ios - # FORGE_ARCH: iOS - # FORGE_PACKAGES: >- - # libjpeg:3.0.3 - # libpng:1.6.43 - # freetype:2.13.3 - # pillow:10.4.0 - # lru-dict:1.3.0 - # yarl:1.11.1 - # contourpy:1.3.0 - # kiwisolver:1.4.7 - # aiohttp:3.9.5 - # bitarray:2.9.2 - # websockets:13.0.1 + - job_name: 'iOS: pillow, lru-dict, yarl, contourpy, kiwisolver, aiohttp, bitarray, websockets' + job_group: build_ios + FORGE_ARCH: iOS + FORGE_PACKAGES: >- + libjpeg:3.0.3 + libpng:1.6.43 + freetype:2.13.3 + pillow:10.4.0 + lru-dict:1.3.0 + yarl:1.11.1 + contourpy:1.3.0 + kiwisolver:1.4.7 + aiohttp:3.9.5 + bitarray:2.9.2 + websockets:13.0.1 - job_name: 'iOS: cffi, argon2-cffi-bindings, bcrypt, cryptography, brotli' job_group: build_ios diff --git a/recipes/bitarray/LICENSE b/recipes/bitarray/LICENSE deleted file mode 100644 index a82526bf..00000000 --- a/recipes/bitarray/LICENSE +++ /dev/null @@ -1,46 +0,0 @@ -PYTHON SOFTWARE FOUNDATION LICENSE ----------------------------------- - -1. This LICENSE AGREEMENT is between Ilan Schnell, and the Individual or -Organization ("Licensee") accessing and otherwise using this software -("bitarray") in source or binary form and its associated documentation. - -2. Subject to the terms and conditions of this License Agreement, Ilan Schnell -hereby grants Licensee a nonexclusive, royalty-free, world-wide -license to reproduce, analyze, test, perform and/or display publicly, -prepare derivative works, distribute, and otherwise use bitarray -alone or in any derivative version, provided, however, that Ilan Schnell's -License Agreement and Ilan Schnell's notice of copyright, i.e., "Copyright (c) -2008 - 2021 Ilan Schnell; All Rights Reserved" are retained in bitarray -alone or in any derivative version prepared by Licensee. - -3. In the event Licensee prepares a derivative work that is based on -or incorporates bitarray or any part thereof, and wants to make -the derivative work available to others as provided herein, then -Licensee hereby agrees to include in any such work a brief summary of -the changes made to bitarray. - -4. Ilan Schnell is making bitarray available to Licensee on an "AS IS" -basis. ILAN SCHNELL MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR -IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, ILAN SCHNELL MAKES NO AND -DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS -FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF BITARRAY WILL NOT -INFRINGE ANY THIRD PARTY RIGHTS. - -5. ILAN SCHNELL SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF BITARRAY -FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS -A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING BITARRAY, -OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. - -6. This License Agreement will automatically terminate upon a material -breach of its terms and conditions. - -7. Nothing in this License Agreement shall be deemed to create any -relationship of agency, partnership, or joint venture between Ilan Schnell -and Licensee. This License Agreement does not grant permission to use Ilan -Schnell trademarks or trade name in a trademark sense to endorse or promote -products or services of Licensee, or any third party. - -8. By copying, installing or otherwise using bitarray, Licensee -agrees to be bound by the terms and conditions of this License -Agreement. diff --git a/recipes/blis/meta.yaml b/recipes/blis/meta.yaml index faebf519..d395e142 100644 --- a/recipes/blis/meta.yaml +++ b/recipes/blis/meta.yaml @@ -2,9 +2,9 @@ package: name: blis version: 1.0.0 -patches: - - mobile.patch - requirements: host: - - numpy ^2.0.0 \ No newline at end of file + - numpy ^2.0.0 + +patches: + - mobile.patch \ No newline at end of file diff --git a/recipes/cffi/meta.yaml b/recipes/cffi/meta.yaml index caad2724..25b39bbc 100644 --- a/recipes/cffi/meta.yaml +++ b/recipes/cffi/meta.yaml @@ -2,9 +2,9 @@ package: name: cffi version: 1.17.1 -patches: - - mobile.patch - requirements: host: - libffi + +patches: + - mobile.patch \ No newline at end of file diff --git a/recipes/contourpy/meta.yaml b/recipes/contourpy/meta.yaml index 537c8280..65f507ef 100644 --- a/recipes/contourpy/meta.yaml +++ b/recipes/contourpy/meta.yaml @@ -2,12 +2,12 @@ package: name: contourpy version: 1.3.0 -build: - backend-args: - - -Csetup-args=--cross-file - - -Csetup-args={MESON_CROSS_FILE} - requirements: build: - ninja - - cmake \ No newline at end of file + - cmake + +build: + backend-args: + - -Csetup-args=--cross-file + - -Csetup-args={MESON_CROSS_FILE} \ No newline at end of file diff --git a/recipes/cryptography/meta.yaml b/recipes/cryptography/meta.yaml index a5e27a89..1ab42e92 100644 --- a/recipes/cryptography/meta.yaml +++ b/recipes/cryptography/meta.yaml @@ -2,11 +2,11 @@ package: name: cryptography version: 43.0.1 -build: - script_env: - OPENSSL_DIR: '{platlib}/opt' - _PYTHON_SYSCONFIGDATA_NAME: '{sysconfigdata_name}' - requirements: host: - openssl ^3.0.12 + +build: + script_env: + OPENSSL_DIR: '{platlib}/opt' + _PYTHON_SYSCONFIGDATA_NAME: '{sysconfigdata_name}' \ No newline at end of file diff --git a/recipes/matplotlib/meta.yaml b/recipes/matplotlib/meta.yaml index b7fdb95d..fb17fcb9 100644 --- a/recipes/matplotlib/meta.yaml +++ b/recipes/matplotlib/meta.yaml @@ -4,7 +4,6 @@ package: requirements: build: - - meson - ninja host: - numpy ^2.0.0 diff --git a/recipes/numpy/meta.yaml b/recipes/numpy/meta.yaml index 563f11c7..b7e30824 100644 --- a/recipes/numpy/meta.yaml +++ b/recipes/numpy/meta.yaml @@ -7,9 +7,7 @@ package: requirements: build: - - cython - ninja - - meson build: script_env: diff --git a/recipes/opencv-python/meta.yaml b/recipes/opencv-python/meta.yaml index 394a5438..639906a2 100644 --- a/recipes/opencv-python/meta.yaml +++ b/recipes/opencv-python/meta.yaml @@ -2,6 +2,10 @@ package: name: opencv-python version: 4.10.0.84 +requirements: + host: + - numpy ^2.0.0 + patches: - mobile.patch @@ -48,8 +52,4 @@ build: -DPYTHON3_INCLUDE_PATH={prefix}/include/python{py_version_short} -DPYTHON3_LIBRARIES={prefix}/lib/libpython{py_version_short}.so -DPYTHON3_NUMPY_INCLUDE_DIRS={platlib}/numpy/_core/include -# {% endif %} - -requirements: - host: - - numpy ^2.0.0 \ No newline at end of file +# {% endif %} \ No newline at end of file diff --git a/recipes/pandas/meta.yaml b/recipes/pandas/meta.yaml index 3385206e..f330eddb 100644 --- a/recipes/pandas/meta.yaml +++ b/recipes/pandas/meta.yaml @@ -4,7 +4,6 @@ package: requirements: build: - - meson - ninja host: - numpy ^2.0.0 diff --git a/recipes/pillow/meta.yaml b/recipes/pillow/meta.yaml index cd1e9c71..825d255e 100644 --- a/recipes/pillow/meta.yaml +++ b/recipes/pillow/meta.yaml @@ -2,6 +2,12 @@ package: name: Pillow version: 10.4.0 +requirements: + host: + # PNG support is internal: libpng is not used. + - libjpeg + - freetype + patches: - setup.patch @@ -9,10 +15,4 @@ build: script_env: # libfreetype references both libz and libbz2 # but doesn't link them into the static library - LDFLAGS: -lz -lbz2 - -requirements: - host: - # PNG support is internal: libpng is not used. - - libjpeg - - freetype + LDFLAGS: -lz -lbz2 \ No newline at end of file diff --git a/recipes/yarl/meta.yaml b/recipes/yarl/meta.yaml index f543372b..b87129db 100644 --- a/recipes/yarl/meta.yaml +++ b/recipes/yarl/meta.yaml @@ -4,4 +4,4 @@ package: requirements: build: - - cython 3.0.7 \ No newline at end of file + - cython \ No newline at end of file From b9e6b66dbd15c6c58d21788056e4e1b701cdb2cd Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Fri, 13 Sep 2024 09:37:51 -0700 Subject: [PATCH 019/142] Fix pillow recipe --- .appveyor.yml | 74 ++++++++++++++------------- recipes/freetype/patches/config.patch | 2 +- 2 files changed, 39 insertions(+), 37 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index f408d5c2..eaf48894 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -26,6 +26,8 @@ environment: # FORGE_PACKAGES: >- # websockets:13.0.1 + # ================================================== + # - job_name: 'Android arm64-v8a: opencv-python' # job_group: build_android # FORGE_ARCH: 'android:arm64-v8a' @@ -46,20 +48,20 @@ environment: # FORGE_ARCH: 'android:x86' # FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 - - job_name: 'iOS iphone arm64: opencv-python' - job_group: build_ios - FORGE_ARCH: 'iphoneos:arm64' - FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 + # - job_name: 'iOS iphone arm64: opencv-python' + # job_group: build_ios + # FORGE_ARCH: 'iphoneos:arm64' + # FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 - - job_name: 'iOS simulator arm64: opencv-python' - job_group: build_ios - FORGE_ARCH: 'iphonesimulator:arm64' - FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 + # - job_name: 'iOS simulator arm64: opencv-python' + # job_group: build_ios + # FORGE_ARCH: 'iphonesimulator:arm64' + # FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 - - job_name: 'iOS simulator x86_64: opencv-python' - job_group: build_ios - FORGE_ARCH: 'iphonesimulator:x86_64' - FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 + # - job_name: 'iOS simulator x86_64: opencv-python' + # job_group: build_ios + # FORGE_ARCH: 'iphonesimulator:x86_64' + # FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 # - job_name: 'Android: pydantic-core, pillow, lru-dict, contourpy, kiwisolver, aiohttp, bitarray, argon2-cffi-binding, bcrypt, cryptography, brotli, websockets' # job_group: build_android @@ -109,31 +111,31 @@ environment: bitarray:2.9.2 websockets:13.0.1 - - job_name: 'iOS: cffi, argon2-cffi-bindings, bcrypt, cryptography, brotli' - job_group: build_ios - FORGE_ARCH: iOS - FORGE_PACKAGES: >- - cffi:1.17.1 - argon2-cffi-bindings:21.2.0 - bcrypt:4.2.0 - cryptography:43.0.1 - brotli:1.1.0 - - - job_name: 'iOS: pydantic-core' - job_group: build_ios - FORGE_ARCH: iOS - FORGE_PACKAGES: >- - pydantic-core:2.23.3 + # - job_name: 'iOS: cffi, argon2-cffi-bindings, bcrypt, cryptography, brotli' + # job_group: build_ios + # FORGE_ARCH: iOS + # FORGE_PACKAGES: >- + # cffi:1.17.1 + # argon2-cffi-bindings:21.2.0 + # bcrypt:4.2.0 + # cryptography:43.0.1 + # brotli:1.1.0 - - job_name: 'iOS: numpy, matplotlib, pandas, blis' - job_group: build_ios - FORGE_ARCH: iOS - FORGE_PACKAGES: >- - numpy:1.26.4 - numpy:2.1.1 - matplotlib:3.9.2 - pandas:2.2.2 - blis:1.0.0 + # - job_name: 'iOS: pydantic-core' + # job_group: build_ios + # FORGE_ARCH: iOS + # FORGE_PACKAGES: >- + # pydantic-core:2.23.3 + + # - job_name: 'iOS: numpy, matplotlib, pandas, blis' + # job_group: build_ios + # FORGE_ARCH: iOS + # FORGE_PACKAGES: >- + # numpy:1.26.4 + # numpy:2.1.1 + # matplotlib:3.9.2 + # pandas:2.2.2 + # blis:1.0.0 - job_name: Re-build Simple index job_group: rebuild_index diff --git a/recipes/freetype/patches/config.patch b/recipes/freetype/patches/config.patch index 115801bb..7b355451 100644 --- a/recipes/freetype/patches/config.patch +++ b/recipes/freetype/patches/config.patch @@ -23,7 +23,7 @@ index 4aaae46..526f2d4 100755 # None (no kernel, i.e. freestanding / bare metal), # can be paired with an machine code file format ;; -+ ios-simulator) ++ ios-simulator-) + ;; -*-) # Blank kernel with real OS is always fine. From 5a980d81c51e4822d39652ed9a64b4015d28087b Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Mon, 16 Sep 2024 12:07:36 -0700 Subject: [PATCH 020/142] Python3.12 with Android (#7) * Added Android support * Fixed pillow, pandas and other Meson-baked packages * Try building a simple android package * Check python location--upgrade setuptools * re-build index * display python path * ensurepip --upgrade * Fix python * which python$PYTHON_SHORT_VERSION * which python in different place * Try again * echo $PATH * configure rust before * don't use source command * configure forge first * echo $PATH * cat source * Remove deactivate * Remove junk * Test android * Fix python in setup.sh * Re-build all Android packages * Trying to fix pillow for android * Pillow - disable platform guessing * Re-run all Android jobs * Trying to fix contourpy * Fix host tool shims. Build contourpy, matplotlib and pandas on Android * Try iOS-like shim script template * Fix path to pybind config * Build pandas and contourpy on all android abis * Re-build all android packages --- .appveyor.yml | 131 +++++++++++++++------------- recipes/contourpy/meta.yaml | 2 + recipes/matplotlib/meta.yaml | 1 + recipes/pandas/meta.yaml | 3 + recipes/pandas/patches/mobile.patch | 15 ++++ recipes/pillow/meta.yaml | 4 +- recipes/pillow/patches/setup.patch | 30 +++++-- setup.sh | 6 +- src/forge/build.py | 42 +++++++-- src/forge/cross.py | 47 ++++++---- 10 files changed, 186 insertions(+), 95 deletions(-) create mode 100644 recipes/pandas/patches/mobile.patch diff --git a/.appveyor.yml b/.appveyor.yml index eaf48894..08937ea2 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -20,6 +20,15 @@ environment: # FORGE_PACKAGES: >- # websockets:13.0.1 + # - job_name: 'Android: contourpy' + # job_group: build_android + # FORGE_ARCH: 'android' + # FORGE_PACKAGES: >- + # contourpy:1.3.0 + # numpy:2.1.1 + # matplotlib:3.9.2 + # pandas:2.2.2 + # - job_name: 'iOS: websockets' # job_group: build_ios # FORGE_ARCH: iOS @@ -28,25 +37,25 @@ environment: # ================================================== - # - job_name: 'Android arm64-v8a: opencv-python' - # job_group: build_android - # FORGE_ARCH: 'android:arm64-v8a' - # FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 + - job_name: 'Android arm64-v8a: opencv-python' + job_group: build_android + FORGE_ARCH: 'android:arm64-v8a' + FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 - # - job_name: 'Android armeabi-v7a: opencv-python' - # job_group: build_android - # FORGE_ARCH: 'android:armeabi-v7a' - # FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 + - job_name: 'Android armeabi-v7a: opencv-python' + job_group: build_android + FORGE_ARCH: 'android:armeabi-v7a' + FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 - # - job_name: 'Android x86_64: opencv-python' - # job_group: build_android - # FORGE_ARCH: 'android:x86_64' - # FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 + - job_name: 'Android x86_64: opencv-python' + job_group: build_android + FORGE_ARCH: 'android:x86_64' + FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 - # - job_name: 'Android x86: opencv-python' - # job_group: build_android - # FORGE_ARCH: 'android:x86' - # FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 + - job_name: 'Android x86: opencv-python' + job_group: build_android + FORGE_ARCH: 'android:x86' + FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 # - job_name: 'iOS iphone arm64: opencv-python' # job_group: build_ios @@ -63,42 +72,11 @@ environment: # FORGE_ARCH: 'iphonesimulator:x86_64' # FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 - # - job_name: 'Android: pydantic-core, pillow, lru-dict, contourpy, kiwisolver, aiohttp, bitarray, argon2-cffi-binding, bcrypt, cryptography, brotli, websockets' - # job_group: build_android - # FORGE_ARCH: android - # FORGE_PACKAGES: >- - # cffi:1.17.1 - # libjpeg:3.0.3 - # libpng:1.6.43 - # freetype:2.13.3 - # pillow:10.4.0 - # lru-dict:1.3.0 - # yarl:1.11.1 - # contourpy:1.3.0 - # kiwisolver:1.4.7 - # aiohttp:3.9.5 - # bitarray:2.9.2 - # argon2-cffi-bindings:21.2.0 - # bcrypt:4.2.0 - # cryptography:43.0.1 - # brotli:1.1.0 - # pydantic-core:2.23.3 - # websockets:13.0.1 - - # - job_name: 'Android: numpy, matplotlib, pandas, blis' - # job_group: build_android - # FORGE_ARCH: android - # FORGE_PACKAGES: >- - # numpy:1.26.4 - # numpy:2.1.1 - # matplotlib:3.9.2 - # pandas:2.2.2 - # blis:1.0.0 - - - job_name: 'iOS: pillow, lru-dict, yarl, contourpy, kiwisolver, aiohttp, bitarray, websockets' - job_group: build_ios - FORGE_ARCH: iOS + - job_name: 'Android: pydantic-core, pillow, lru-dict, contourpy, kiwisolver, aiohttp, bitarray, argon2-cffi-binding, bcrypt, cryptography, brotli, websockets' + job_group: build_android + FORGE_ARCH: android FORGE_PACKAGES: >- + cffi:1.17.1 libjpeg:3.0.3 libpng:1.6.43 freetype:2.13.3 @@ -109,8 +87,39 @@ environment: kiwisolver:1.4.7 aiohttp:3.9.5 bitarray:2.9.2 + argon2-cffi-bindings:21.2.0 + bcrypt:4.2.0 + cryptography:43.0.1 + brotli:1.1.0 + pydantic-core:2.23.3 websockets:13.0.1 + - job_name: 'Android: numpy, matplotlib, pandas, blis' + job_group: build_android + FORGE_ARCH: android + FORGE_PACKAGES: >- + numpy:1.26.4 + numpy:2.1.1 + matplotlib:3.9.2 + pandas:2.2.2 + blis:1.0.0 + + # - job_name: 'iOS: pillow, lru-dict, yarl, contourpy, kiwisolver, aiohttp, bitarray, websockets' + # job_group: build_ios + # FORGE_ARCH: iOS + # FORGE_PACKAGES: >- + # libjpeg:3.0.3 + # libpng:1.6.43 + # freetype:2.13.3 + # pillow:10.4.0 + # lru-dict:1.3.0 + # yarl:1.11.1 + # contourpy:1.3.0 + # kiwisolver:1.4.7 + # aiohttp:3.9.5 + # bitarray:2.9.2 + # websockets:13.0.1 + # - job_name: 'iOS: cffi, argon2-cffi-bindings, bcrypt, cryptography, brotli' # job_group: build_ios # FORGE_ARCH: iOS @@ -167,22 +176,18 @@ for: environment: APPVEYOR_BUILD_WORKER_IMAGE: ubuntu-gce-c - NDK_VERSION: r27-beta2 + NDK_VERSION: r27 install: # download Python for Android - python_android_dir=$HOME/projects/python-android - - curl -#OL https://github.com/flet-dev/python-android/releases/download/v${PYTHON_VERSION}/python-android-install-${PYTHON_VERSION}.tar.gz + - curl -#OL https://github.com/flet-dev/python-android/releases/download/v${PYTHON_SHORT_VERSION}/python-android-install-${PYTHON_SHORT_VERSION}.tar.gz - mkdir -p $python_android_dir - - tar -xzf python-android-install-${PYTHON_VERSION}.tar.gz -C $python_android_dir - + - tar -xzf python-android-install-${PYTHON_SHORT_VERSION}.tar.gz -C $python_android_dir + # install Android NDK - .ci/install_ndk.sh - # configure forge - - export PYTHON_ANDROID_SUPPORT=$python_android_dir - - source ./setup.sh $PYTHON_VERSION - # install Rust - curl https://sh.rustup.rs -sSf | sh -s -- -y - . "$HOME/.cargo/env" @@ -191,6 +196,10 @@ for: - rustup target add arm-linux-androideabi - rustup target add x86_64-linux-android - rustup target add i686-linux-android + + # configure forge + - export MOBILE_FORGE_ANDROID_SUPPORT_PATH=$python_android_dir + - source ./setup.sh $PYTHON_VERSION build_script: - sh: | @@ -200,8 +209,6 @@ for: done # cleanup - - rm dist/ninja-* - - rm dist/cmake-* - rm dist/bzip2-* - rm dist/xz-* - rm dist/libffi-* @@ -277,6 +284,8 @@ for: APPVEYOR_BUILD_WORKER_IMAGE: ubuntu deploy_script: + - python -m ensurepip --upgrade + - pip3 install --upgrade setuptools - pip3 install boto3 - python .ci/rebuild-simple-index.py diff --git a/recipes/contourpy/meta.yaml b/recipes/contourpy/meta.yaml index 65f507ef..4ad619ad 100644 --- a/recipes/contourpy/meta.yaml +++ b/recipes/contourpy/meta.yaml @@ -6,6 +6,8 @@ requirements: build: - ninja - cmake + host: + - pybind11 build: backend-args: diff --git a/recipes/matplotlib/meta.yaml b/recipes/matplotlib/meta.yaml index fb17fcb9..814d1aea 100644 --- a/recipes/matplotlib/meta.yaml +++ b/recipes/matplotlib/meta.yaml @@ -7,6 +7,7 @@ requirements: - ninja host: - numpy ^2.0.0 + - pybind11 build: backend-args: diff --git a/recipes/pandas/meta.yaml b/recipes/pandas/meta.yaml index f330eddb..a9d1022f 100644 --- a/recipes/pandas/meta.yaml +++ b/recipes/pandas/meta.yaml @@ -8,6 +8,9 @@ requirements: host: - numpy ^2.0.0 +patches: + - mobile.patch + build: backend-args: - -Csetup-args=--cross-file diff --git a/recipes/pandas/patches/mobile.patch b/recipes/pandas/patches/mobile.patch new file mode 100644 index 00000000..74959289 --- /dev/null +++ b/recipes/pandas/patches/mobile.patch @@ -0,0 +1,15 @@ +diff --git a/pyproject.toml b/pyproject.toml +index db9f055..3e3d399 100644 +--- a/pyproject.toml ++++ b/pyproject.toml +@@ -2,8 +2,8 @@ + # Minimum requirements for the build system to execute. + # See https://github.com/scipy/scipy/pull/12940 for the AIX issue. + requires = [ +- "meson-python==0.13.1", +- "meson==1.2.1", ++ "meson-python>=0.15.0", ++ #"meson==1.2.1", + "wheel", + "Cython==3.0.5", # Note: sync with setup.py, environment.yml and asv.conf.json + # Force numpy higher than 2.0rc1, so that built wheels are compatible diff --git a/recipes/pillow/meta.yaml b/recipes/pillow/meta.yaml index 825d255e..28b1c576 100644 --- a/recipes/pillow/meta.yaml +++ b/recipes/pillow/meta.yaml @@ -11,8 +11,10 @@ requirements: patches: - setup.patch +# {% if sdk != 'android' %} build: script_env: # libfreetype references both libz and libbz2 # but doesn't link them into the static library - LDFLAGS: -lz -lbz2 \ No newline at end of file + LDFLAGS: -lz -lbz2 +# {% endif %} \ No newline at end of file diff --git a/recipes/pillow/patches/setup.patch b/recipes/pillow/patches/setup.patch index 659e12b1..21bff57e 100644 --- a/recipes/pillow/patches/setup.patch +++ b/recipes/pillow/patches/setup.patch @@ -1,10 +1,22 @@ -diff -ur pillow-10.4.0-orig/setup.py pillow-10.4.0/setup.py ---- pillow-10.4.0-orig/setup.py 2024-07-01 14:02:01 -+++ pillow-10.4.0/setup.py 2024-09-05 14:20:16 -@@ -422,10 +422,22 @@ +diff --git a/setup.py b/setup.py +index 0abfaad..7b077d4 100644 +--- a/setup.py ++++ b/setup.py +@@ -342,9 +342,7 @@ class pil_build_ext(build_ext): + return True if value in configuration.get(option, []) else None + + def initialize_options(self): +- self.disable_platform_guessing = self.check_configuration( +- "platform-guessing", "disable" +- ) ++ self.disable_platform_guessing = True + self.add_imaging_libs = "" + build_ext.initialize_options(self) + for x in self.feature: +@@ -422,10 +420,22 @@ class pil_build_ext(build_ext): self.extensions.remove(extension) break - + - def get_macos_sdk_path(self): + def get_apple_sdk_path(self): try: @@ -26,16 +38,16 @@ diff -ur pillow-10.4.0-orig/setup.py pillow-10.4.0/setup.py .strip() .decode("latin1") ) -@@ -580,13 +592,18 @@ +@@ -580,13 +590,18 @@ class pil_build_ext(build_ext): _add_directory(library_dirs, "/usr/X11/lib") _add_directory(include_dirs, "/usr/X11/include") - + - sdk_path = self.get_macos_sdk_path() + sdk_path = self.get_apple_sdk_path() if sdk_path: _add_directory(library_dirs, os.path.join(sdk_path, "usr", "lib")) _add_directory(include_dirs, os.path.join(sdk_path, "usr", "include")) - + for extension in self.extensions: extension.extra_compile_args = ["-Wno-nullability-completeness"] + elif sys.platform in {"ios", "tvos", "watchos"}: @@ -45,4 +57,4 @@ diff -ur pillow-10.4.0-orig/setup.py pillow-10.4.0/setup.py + _add_directory(include_dirs, os.path.join(sdk_path, "usr", "include")) elif ( sys.platform.startswith("linux") - or sys.platform.startswith("gnu") \ No newline at end of file + or sys.platform.startswith("gnu") diff --git a/setup.sh b/setup.sh index 4c32151f..d053354e 100755 --- a/setup.sh +++ b/setup.sh @@ -38,10 +38,6 @@ if [[ -z "$MOBILE_FORGE_IOS_SUPPORT_PATH" && -z "$MOBILE_FORGE_ANDROID_SUPPORT_P return fi -if [ ! -z "$VIRTUAL_ENV" ]; then - deactivate -fi - venv_dir="$(pwd)/venv$PYTHON_VER" if [ ! -d $venv_dir ]; then @@ -74,6 +70,8 @@ if [ ! -d $venv_dir ]; then # tar -xzf "downloads/python-${PYTHON_VERSION}-${PYTHON_SUFFIX}" -C tools # fi + echo $PATH + BUILD_PYTHON=$(which python$PYTHON_VER) if [ $? -ne 0 ]; then echo "Can't find a Python $PYTHON_VER binary on the path." diff --git a/src/forge/build.py b/src/forge/build.py index 5c9a039c..d5a025b1 100644 --- a/src/forge/build.py +++ b/src/forge/build.py @@ -36,13 +36,15 @@ def __init__(self, cross_venv: CrossVEnv, package: Package): self.cross_venv = cross_venv self.package = package - @abstractproperty + @property + @abstractmethod def build_path(self) -> Path: """The path in which all environment and sources for the build will be created.""" ... - @abstractproperty + @property + @abstractmethod def log_file_path(self) -> Path: """The path where build logs should be written.""" ... @@ -52,7 +54,8 @@ def error_log_file_path(self) -> Path: """The path for the log file if a build error occurs.""" return self.log_file_path.parent.parent / "errors" / self.log_file_path.name - @abstractproperty + @property + @abstractmethod def source_archive_path(self) -> Path: """The source archive file for the package.""" ... @@ -82,6 +85,28 @@ def install_requirements(self, target): else: log(self.log_file, f"No {target} requirements.") + def fix_host_tool_shims(self): + python_path = ( + self.cross_venv.venv_path + / "cross" + / "bin" + / f"python3.{sys.version_info.minor}" + ) + for shim in (self.cross_venv.venv_path / "cross" / "bin").iterdir(): + with open(shim, "r") as f: + lines = f.readlines() + if len(lines) > 0 and lines[0].strip() == f"#!{python_path}": + log(self.log_file, f"Fixing host shim: {shim}") + with open(shim, "w") as f: + f.writelines( + [ + "#!/bin/sh\n", + "'''exec' {} \"$0\" \"$@\"\n".format(python_path), + "' '''\n", + ] + + lines[1:] + ) + @abstractmethod def download_source_url(self): ... @@ -206,6 +231,7 @@ def prepare(self, clean=True): log(self.log_file, f"\n[{self.cross_venv}] Install forge host requirements") self.install_requirements("host") + self.fix_host_tool_shims() log(self.log_file, f"\n[{self.cross_venv}] Install forge build requirements") self.install_requirements("build") @@ -606,6 +632,12 @@ def _create_meson_cross(self, env: dict[str, str]): "cpp": env["CXX"], "ar": env["AR"], "strip": env["STRIP"], + "python": str( + self.cross_venv.venv_path + / "cross" + / "bin" + / f"python3.{sys.version_info.minor}" + ), }, "built-in options": { "c_args": env["CFLAGS"], @@ -613,7 +645,7 @@ def _create_meson_cross(self, env: dict[str, str]): "c_links_args": env["LDFLAGS"], "cpp_links_args": env["LDFLAGS"], }, - "properties": {"needs_exe_wrapper": True}, + "properties": {"needs_exe_wrapper": False}, "host_machine": { "cpu_family": cpu_family, "cpu": cpu, @@ -655,7 +687,7 @@ def _build(self): # Set up any additional environment variables needed in the script environment. for key, value in self.package.meta["build"]["script_env"].items(): - if key == "LDFLAGS": + if key in ["LDFLAGS", "CFLAGS", "CPPFLAGS"]: env[key] += " " + value else: env[key] = str(value).format(**script_vars) diff --git a/src/forge/cross.py b/src/forge/cross.py index 57f4de8f..0bd77b29 100644 --- a/src/forge/cross.py +++ b/src/forge/cross.py @@ -112,12 +112,20 @@ def host_python_home(self): os.getenv(f"MOBILE_FORGE_{self.host_os.upper()}_SUPPORT_PATH") ) return ( - support_path - / "support" - / f"3.{sys.version_info.minor}" - / self.host_os - / "Python.xcframework" - / self.XCFRAMEWORK_SLICES[(self.sdk, self.arch)] + ( + support_path + / "support" + / f"3.{sys.version_info.minor}" + / self.host_os + / "Python.xcframework" + / self.XCFRAMEWORK_SLICES[(self.sdk, self.arch)] + ) + if self.host_os == "iOS" + else next( + (support_path / "install" / self.host_os / self.arch).glob( + f"python-3.{sys.version_info.minor}.*" + ) + ) ) @property @@ -256,15 +264,24 @@ def create( if not host_python.is_file(): raise RuntimeError(f"Can't find host python {host_python}") - self.sysconfigdata_name = ( - f"_sysconfigdata__{self.host_os.lower()}_{self.arch}-{self.sdk}" - ) + if self.host_os == "iOS": + self.sysconfigdata_name = ( + f"_sysconfigdata__{self.host_os.lower()}_{self.arch}-{self.sdk}" + ) + + host_sysconfig = ( + self.host_python_home + / f"lib/python3.{sys.version_info.minor}" + / f"{self.sysconfigdata_name}.py" + ) + else: + host_sysconfig = next( + (self.host_python_home / f"lib/python3.{sys.version_info.minor}").glob( + "_sysconfigdata__*.py" + ) + ) + self.sysconfigdata_name = host_sysconfig.stem - host_sysconfig = ( - self.host_python_home - / f"lib/python3.{sys.version_info.minor}" - / f"{self.sysconfigdata_name}.py" - ) if not host_sysconfig.is_file(): raise RuntimeError(f"Can't find host sysconfig {host_sysconfig}") @@ -380,7 +397,7 @@ def cross_kwargs(self, kwargs): "/usr/sbin", "/sbin", "/Library/Apple/usr/bin", - ] + ][1 if self.host_os == "android" else 0 :] ) # Set VIRTUALENV to the active venv From 4d1f80bc73cf65f5af96189f2fa618829bf5e780 Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Mon, 16 Sep 2024 12:48:55 -0700 Subject: [PATCH 021/142] Re-build iOS and Android on Python 3.12.6 --- .appveyor.yml | 104 +++++++++++++++++++++++++------------------------- setup.sh | 74 +++++++++++++++++++---------------- 2 files changed, 94 insertions(+), 84 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index 08937ea2..cb4824a1 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -3,7 +3,7 @@ image: macos-monterey skip_branch_with_pr: true environment: - PYTHON_VERSION: 3.12.4 + PYTHON_VERSION: 3.12.6 PYTHON_SHORT_VERSION: 3.12 CF_ACCESS_KEY_ID: secure: +m1fzbrEPRecXKCCMn4uA781PAASzJSWAxuJj1c7ctLfWbi5oW4PMnowPK96XtQ5 @@ -57,20 +57,20 @@ environment: FORGE_ARCH: 'android:x86' FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 - # - job_name: 'iOS iphone arm64: opencv-python' - # job_group: build_ios - # FORGE_ARCH: 'iphoneos:arm64' - # FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 + - job_name: 'iOS iphone arm64: opencv-python' + job_group: build_ios + FORGE_ARCH: 'iphoneos:arm64' + FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 - # - job_name: 'iOS simulator arm64: opencv-python' - # job_group: build_ios - # FORGE_ARCH: 'iphonesimulator:arm64' - # FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 + - job_name: 'iOS simulator arm64: opencv-python' + job_group: build_ios + FORGE_ARCH: 'iphonesimulator:arm64' + FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 - # - job_name: 'iOS simulator x86_64: opencv-python' - # job_group: build_ios - # FORGE_ARCH: 'iphonesimulator:x86_64' - # FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 + - job_name: 'iOS simulator x86_64: opencv-python' + job_group: build_ios + FORGE_ARCH: 'iphonesimulator:x86_64' + FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 - job_name: 'Android: pydantic-core, pillow, lru-dict, contourpy, kiwisolver, aiohttp, bitarray, argon2-cffi-binding, bcrypt, cryptography, brotli, websockets' job_group: build_android @@ -104,47 +104,47 @@ environment: pandas:2.2.2 blis:1.0.0 - # - job_name: 'iOS: pillow, lru-dict, yarl, contourpy, kiwisolver, aiohttp, bitarray, websockets' - # job_group: build_ios - # FORGE_ARCH: iOS - # FORGE_PACKAGES: >- - # libjpeg:3.0.3 - # libpng:1.6.43 - # freetype:2.13.3 - # pillow:10.4.0 - # lru-dict:1.3.0 - # yarl:1.11.1 - # contourpy:1.3.0 - # kiwisolver:1.4.7 - # aiohttp:3.9.5 - # bitarray:2.9.2 - # websockets:13.0.1 + - job_name: 'iOS: pillow, lru-dict, yarl, contourpy, kiwisolver, aiohttp, bitarray, websockets' + job_group: build_ios + FORGE_ARCH: iOS + FORGE_PACKAGES: >- + libjpeg:3.0.3 + libpng:1.6.43 + freetype:2.13.3 + pillow:10.4.0 + lru-dict:1.3.0 + yarl:1.11.1 + contourpy:1.3.0 + kiwisolver:1.4.7 + aiohttp:3.9.5 + bitarray:2.9.2 + websockets:13.0.1 - # - job_name: 'iOS: cffi, argon2-cffi-bindings, bcrypt, cryptography, brotli' - # job_group: build_ios - # FORGE_ARCH: iOS - # FORGE_PACKAGES: >- - # cffi:1.17.1 - # argon2-cffi-bindings:21.2.0 - # bcrypt:4.2.0 - # cryptography:43.0.1 - # brotli:1.1.0 - - # - job_name: 'iOS: pydantic-core' - # job_group: build_ios - # FORGE_ARCH: iOS - # FORGE_PACKAGES: >- - # pydantic-core:2.23.3 + - job_name: 'iOS: cffi, argon2-cffi-bindings, bcrypt, cryptography, brotli' + job_group: build_ios + FORGE_ARCH: iOS + FORGE_PACKAGES: >- + cffi:1.17.1 + argon2-cffi-bindings:21.2.0 + bcrypt:4.2.0 + cryptography:43.0.1 + brotli:1.1.0 - # - job_name: 'iOS: numpy, matplotlib, pandas, blis' - # job_group: build_ios - # FORGE_ARCH: iOS - # FORGE_PACKAGES: >- - # numpy:1.26.4 - # numpy:2.1.1 - # matplotlib:3.9.2 - # pandas:2.2.2 - # blis:1.0.0 + - job_name: 'iOS: pydantic-core' + job_group: build_ios + FORGE_ARCH: iOS + FORGE_PACKAGES: >- + pydantic-core:2.23.3 + + - job_name: 'iOS: numpy, matplotlib, pandas, blis' + job_group: build_ios + FORGE_ARCH: iOS + FORGE_PACKAGES: >- + numpy:1.26.4 + numpy:2.1.1 + matplotlib:3.9.2 + pandas:2.2.2 + blis:1.0.0 - job_name: Re-build Simple index job_group: rebuild_index diff --git a/setup.sh b/setup.sh index d053354e..522f809e 100755 --- a/setup.sh +++ b/setup.sh @@ -24,12 +24,12 @@ if [ -z "$1" ]; then return fi -PYTHON_URL_PREFIX=https://github.com/indygreg/python-build-standalone/releases/download/20240415/cpython-3.12.3+20240415 - PYTHON_VERSION=$1 read python_version_major python_version_minor < <(echo $PYTHON_VERSION | sed -E 's/^([0-9]+)\.([0-9]+).*/\1 \2/') PYTHON_VER=$python_version_major.$python_version_minor +PYTHON_URL_PREFIX=https://github.com/indygreg/python-build-standalone/releases/download/20240909/cpython-$PYTHON_VERSION+20240909 + echo "Python version: $PYTHON_VERSION" echo "Python short version: $PYTHON_VER" @@ -43,42 +43,52 @@ venv_dir="$(pwd)/venv$PYTHON_VER" if [ ! -d $venv_dir ]; then echo "Creating Python $PYTHON_VER virtual environment for build in $venv_dir..." - # if ! [ -d "tools/python" ]; then - # if [ $(uname) = "Darwin" ]; then - # # macOS - # if [ $(uname -m) = "arm64" ]; then - # PYTHON_SUFFIX="aarch64-apple-darwin-install_only.tar.gz" - # else - # PYTHON_SUFFIX="x86_64-apple-darwin-install_only.tar.gz" - # fi - # else - # # Linux - # if [ $(uname -m) = "arm64" ]; then - # PYTHON_SUFFIX="aarch64-unknown-linux-gnu-install_only.tar.gz" - # else - # PYTHON_SUFFIX="x86_64_v3-unknown-linux-gnu-install_only.tar.gz" - # fi - # fi - - # if ! [ -f "downloads/python-${PYTHON_VERSION}-${PYTHON_SUFFIX}" ]; then - # echo "Downloading Python ${PYTHON_VERSION}" - # mkdir -p downloads - # curl --location --progress-bar "${PYTHON_URL_PREFIX}-${PYTHON_SUFFIX}" --output "downloads/python-${PYTHON_VERSION}-${PYTHON_SUFFIX}" - # fi - - # mkdir -p tools - # tar -xzf "downloads/python-${PYTHON_VERSION}-${PYTHON_SUFFIX}" -C tools + if ! [ -d "tools/python" ]; then + if [ $(uname) = "Darwin" ]; then + # macOS + if [ $(uname -m) = "arm64" ]; then + PYTHON_SUFFIX="aarch64-apple-darwin-install_only.tar.gz" + else + PYTHON_SUFFIX="x86_64-apple-darwin-install_only.tar.gz" + fi + else + # Linux + if [ $(uname -m) = "arm64" ]; then + PYTHON_SUFFIX="aarch64-unknown-linux-gnu-install_only.tar.gz" + else + PYTHON_SUFFIX="x86_64_v3-unknown-linux-gnu-install_only.tar.gz" + fi + fi + + if ! [ -f "downloads/python-${PYTHON_VERSION}-${PYTHON_SUFFIX}" ]; then + echo "Downloading Python ${PYTHON_VERSION}" + python_dist_filename="downloads/python-${PYTHON_VERSION}-${PYTHON_SUFFIX}" + mkdir -p downloads + rm -rf $python_dist_filename + curl --location --progress-bar --fail "${PYTHON_URL_PREFIX}-${PYTHON_SUFFIX}" --output $python_dist_filename + if [ $? -ne 0 ]; then + echo "Can't download a Python from ${PYTHON_URL_PREFIX}-${PYTHON_SUFFIX}" + return + fi + fi + + mkdir -p tools + tar -xzf "downloads/python-${PYTHON_VERSION}-${PYTHON_SUFFIX}" -C tools + fi + + # BUILD_PYTHON=$(which python$PYTHON_VER) + # if [ $? -ne 0 ]; then + # echo "Can't find a Python $PYTHON_VER binary on the path." + # return # fi - echo $PATH + BUILD_PYTHON=tools/python/bin/python - BUILD_PYTHON=$(which python$PYTHON_VER) - if [ $? -ne 0 ]; then - echo "Can't find a Python $PYTHON_VER binary on the path." + if ! [ -f $BUILD_PYTHON ]; then + echo "Can't find a Python $BUILD_PYTHON binary on the path." return fi - # tools/python/bin/python -m venv $venv_dir echo "Using $BUILD_PYTHON as the build python" $BUILD_PYTHON -m venv $venv_dir source $venv_dir/bin/activate From ae123ff059b6abb6815b20371dde78b84a318b19 Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Wed, 25 Sep 2024 15:56:48 -0700 Subject: [PATCH 022/142] Try publishing something simple --- .appveyor.yml | 230 ++++++++++++++++++++++++++------------------------ .ci/common.sh | 7 ++ 2 files changed, 126 insertions(+), 111 deletions(-) create mode 100644 .ci/common.sh diff --git a/.appveyor.yml b/.appveyor.yml index cb4824a1..a94f83af 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -12,13 +12,15 @@ environment: CF_ENDPOINT_URL: secure: lSQBfrqIXIOAYhA0NGej7Pfll1wOSKTTFwQCl8N8lvI22uI5CA/UjRKaqw6KlIZMcXvqTP1w11CVqC2CWnyM3hK857X2tAe8nkO8KT0DCzw= CF_BUCKET_NAME: flet-simple + GEMFURY_TOKEN: + secure: trYGM65OQ1+HYnOYOe/NOHrofLpP3bz64nHwVWPJhiUIYll3MrrQd7ilFNp+zSkI matrix: - # - job_name: 'Android: websockets' - # job_group: build_android - # FORGE_ARCH: android - # FORGE_PACKAGES: >- - # websockets:13.0.1 + - job_name: 'Android: websockets' + job_group: build_android + FORGE_ARCH: android + FORGE_PACKAGES: >- + websockets:13.0.1 # - job_name: 'Android: contourpy' # job_group: build_android @@ -37,118 +39,118 @@ environment: # ================================================== - - job_name: 'Android arm64-v8a: opencv-python' - job_group: build_android - FORGE_ARCH: 'android:arm64-v8a' - FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 + # - job_name: 'Android arm64-v8a: opencv-python' + # job_group: build_android + # FORGE_ARCH: 'android:arm64-v8a' + # FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 - - job_name: 'Android armeabi-v7a: opencv-python' - job_group: build_android - FORGE_ARCH: 'android:armeabi-v7a' - FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 + # - job_name: 'Android armeabi-v7a: opencv-python' + # job_group: build_android + # FORGE_ARCH: 'android:armeabi-v7a' + # FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 - - job_name: 'Android x86_64: opencv-python' - job_group: build_android - FORGE_ARCH: 'android:x86_64' - FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 + # - job_name: 'Android x86_64: opencv-python' + # job_group: build_android + # FORGE_ARCH: 'android:x86_64' + # FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 - - job_name: 'Android x86: opencv-python' - job_group: build_android - FORGE_ARCH: 'android:x86' - FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 + # - job_name: 'Android x86: opencv-python' + # job_group: build_android + # FORGE_ARCH: 'android:x86' + # FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 - - job_name: 'iOS iphone arm64: opencv-python' - job_group: build_ios - FORGE_ARCH: 'iphoneos:arm64' - FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 + # - job_name: 'iOS iphone arm64: opencv-python' + # job_group: build_ios + # FORGE_ARCH: 'iphoneos:arm64' + # FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 - - job_name: 'iOS simulator arm64: opencv-python' - job_group: build_ios - FORGE_ARCH: 'iphonesimulator:arm64' - FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 + # - job_name: 'iOS simulator arm64: opencv-python' + # job_group: build_ios + # FORGE_ARCH: 'iphonesimulator:arm64' + # FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 - - job_name: 'iOS simulator x86_64: opencv-python' - job_group: build_ios - FORGE_ARCH: 'iphonesimulator:x86_64' - FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 + # - job_name: 'iOS simulator x86_64: opencv-python' + # job_group: build_ios + # FORGE_ARCH: 'iphonesimulator:x86_64' + # FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 - - job_name: 'Android: pydantic-core, pillow, lru-dict, contourpy, kiwisolver, aiohttp, bitarray, argon2-cffi-binding, bcrypt, cryptography, brotli, websockets' - job_group: build_android - FORGE_ARCH: android - FORGE_PACKAGES: >- - cffi:1.17.1 - libjpeg:3.0.3 - libpng:1.6.43 - freetype:2.13.3 - pillow:10.4.0 - lru-dict:1.3.0 - yarl:1.11.1 - contourpy:1.3.0 - kiwisolver:1.4.7 - aiohttp:3.9.5 - bitarray:2.9.2 - argon2-cffi-bindings:21.2.0 - bcrypt:4.2.0 - cryptography:43.0.1 - brotli:1.1.0 - pydantic-core:2.23.3 - websockets:13.0.1 + # - job_name: 'Android: pydantic-core, pillow, lru-dict, contourpy, kiwisolver, aiohttp, bitarray, argon2-cffi-binding, bcrypt, cryptography, brotli, websockets' + # job_group: build_android + # FORGE_ARCH: android + # FORGE_PACKAGES: >- + # cffi:1.17.1 + # libjpeg:3.0.3 + # libpng:1.6.43 + # freetype:2.13.3 + # pillow:10.4.0 + # lru-dict:1.3.0 + # yarl:1.11.1 + # contourpy:1.3.0 + # kiwisolver:1.4.7 + # aiohttp:3.9.5 + # bitarray:2.9.2 + # argon2-cffi-bindings:21.2.0 + # bcrypt:4.2.0 + # cryptography:43.0.1 + # brotli:1.1.0 + # pydantic-core:2.23.3 + # websockets:13.0.1 - - job_name: 'Android: numpy, matplotlib, pandas, blis' - job_group: build_android - FORGE_ARCH: android - FORGE_PACKAGES: >- - numpy:1.26.4 - numpy:2.1.1 - matplotlib:3.9.2 - pandas:2.2.2 - blis:1.0.0 - - - job_name: 'iOS: pillow, lru-dict, yarl, contourpy, kiwisolver, aiohttp, bitarray, websockets' - job_group: build_ios - FORGE_ARCH: iOS - FORGE_PACKAGES: >- - libjpeg:3.0.3 - libpng:1.6.43 - freetype:2.13.3 - pillow:10.4.0 - lru-dict:1.3.0 - yarl:1.11.1 - contourpy:1.3.0 - kiwisolver:1.4.7 - aiohttp:3.9.5 - bitarray:2.9.2 - websockets:13.0.1 + # - job_name: 'Android: numpy, matplotlib, pandas, blis' + # job_group: build_android + # FORGE_ARCH: android + # FORGE_PACKAGES: >- + # numpy:1.26.4 + # numpy:2.1.1 + # matplotlib:3.9.2 + # pandas:2.2.2 + # blis:1.0.0 - - job_name: 'iOS: cffi, argon2-cffi-bindings, bcrypt, cryptography, brotli' - job_group: build_ios - FORGE_ARCH: iOS - FORGE_PACKAGES: >- - cffi:1.17.1 - argon2-cffi-bindings:21.2.0 - bcrypt:4.2.0 - cryptography:43.0.1 - brotli:1.1.0 - - - job_name: 'iOS: pydantic-core' - job_group: build_ios - FORGE_ARCH: iOS - FORGE_PACKAGES: >- - pydantic-core:2.23.3 + # - job_name: 'iOS: pillow, lru-dict, yarl, contourpy, kiwisolver, aiohttp, bitarray, websockets' + # job_group: build_ios + # FORGE_ARCH: iOS + # FORGE_PACKAGES: >- + # libjpeg:3.0.3 + # libpng:1.6.43 + # freetype:2.13.3 + # pillow:10.4.0 + # lru-dict:1.3.0 + # yarl:1.11.1 + # contourpy:1.3.0 + # kiwisolver:1.4.7 + # aiohttp:3.9.5 + # bitarray:2.9.2 + # websockets:13.0.1 - - job_name: 'iOS: numpy, matplotlib, pandas, blis' - job_group: build_ios - FORGE_ARCH: iOS - FORGE_PACKAGES: >- - numpy:1.26.4 - numpy:2.1.1 - matplotlib:3.9.2 - pandas:2.2.2 - blis:1.0.0 + # - job_name: 'iOS: cffi, argon2-cffi-bindings, bcrypt, cryptography, brotli' + # job_group: build_ios + # FORGE_ARCH: iOS + # FORGE_PACKAGES: >- + # cffi:1.17.1 + # argon2-cffi-bindings:21.2.0 + # bcrypt:4.2.0 + # cryptography:43.0.1 + # brotli:1.1.0 + + # - job_name: 'iOS: pydantic-core' + # job_group: build_ios + # FORGE_ARCH: iOS + # FORGE_PACKAGES: >- + # pydantic-core:2.23.3 - - job_name: Re-build Simple index - job_group: rebuild_index - job_depends_on: build_android, build_ios + # - job_name: 'iOS: numpy, matplotlib, pandas, blis' + # job_group: build_ios + # FORGE_ARCH: iOS + # FORGE_PACKAGES: >- + # numpy:1.26.4 + # numpy:2.1.1 + # matplotlib:3.9.2 + # pandas:2.2.2 + # blis:1.0.0 + + # - job_name: Re-build Simple index + # job_group: rebuild_index + # job_depends_on: build_android, build_ios stack: - python $PYTHON_SHORT_VERSION @@ -179,9 +181,11 @@ for: NDK_VERSION: r27 install: + - . .ci/common.sh + # download Python for Android - python_android_dir=$HOME/projects/python-android - - curl -#OL https://github.com/flet-dev/python-android/releases/download/v${PYTHON_SHORT_VERSION}/python-android-install-${PYTHON_SHORT_VERSION}.tar.gz + - curl -#OL https://github.com/flet-dev/python-android/releases/download/v${PYTHON_SHORT_VERSION}/python-android-mobile-forge-${PYTHON_SHORT_VERSION}.tar.gz - mkdir -p $python_android_dir - tar -xzf python-android-install-${PYTHON_SHORT_VERSION}.tar.gz -C $python_android_dir @@ -215,8 +219,9 @@ for: - rm dist/openssl-* deploy_script: - - pip install boto3 - - python .ci/publish-wheels.py dist + # - pip install boto3 + # - python .ci/publish-wheels.py dist + - publish_to_pypi dist/*.whl test: off @@ -232,6 +237,8 @@ for: APPVEYOR_BUILD_WORKER_IMAGE: macos-sonoma install: + - . .ci/common.sh + # download Python for iOS - python_ios_dir=$HOME/projects/python-darwin/Python-Apple-support - curl -#OL https://github.com/flet-dev/python-ios/releases/download/v${PYTHON_SHORT_VERSION}/python-ios-install-${PYTHON_SHORT_VERSION}.tar.gz @@ -267,8 +274,9 @@ for: - rm dist/openssl-* deploy_script: - - pip install boto3 - - python .ci/publish-wheels.py dist + # - pip install boto3 + # - python .ci/publish-wheels.py dist + - publish_to_pypi dist/*.whl test: off diff --git a/.ci/common.sh b/.ci/common.sh new file mode 100644 index 00000000..0e724950 --- /dev/null +++ b/.ci/common.sh @@ -0,0 +1,7 @@ +function publish_to_pypi() { + if [[ "$APPVEYOR_PULL_REQUEST_NUMBER" == "" ]]; then + for wheel in "$@"; do + curl -F package=@$wheel https://$GEMFURY_TOKEN@push.fury.io/flet/ + done + fi +} \ No newline at end of file From f961e88c1b018878453ba0c3c47b69a82f1b9ad1 Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Wed, 25 Sep 2024 16:02:05 -0700 Subject: [PATCH 023/142] Fix install archives --- .appveyor.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index a94f83af..2bd0ee78 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -31,11 +31,11 @@ environment: # matplotlib:3.9.2 # pandas:2.2.2 - # - job_name: 'iOS: websockets' - # job_group: build_ios - # FORGE_ARCH: iOS - # FORGE_PACKAGES: >- - # websockets:13.0.1 + - job_name: 'iOS: websockets' + job_group: build_ios + FORGE_ARCH: iOS + FORGE_PACKAGES: >- + websockets:13.0.1 # ================================================== @@ -187,7 +187,7 @@ for: - python_android_dir=$HOME/projects/python-android - curl -#OL https://github.com/flet-dev/python-android/releases/download/v${PYTHON_SHORT_VERSION}/python-android-mobile-forge-${PYTHON_SHORT_VERSION}.tar.gz - mkdir -p $python_android_dir - - tar -xzf python-android-install-${PYTHON_SHORT_VERSION}.tar.gz -C $python_android_dir + - tar -xzf python-android-mobile-forge-${PYTHON_SHORT_VERSION}.tar.gz -C $python_android_dir # install Android NDK - .ci/install_ndk.sh @@ -241,9 +241,9 @@ for: # download Python for iOS - python_ios_dir=$HOME/projects/python-darwin/Python-Apple-support - - curl -#OL https://github.com/flet-dev/python-ios/releases/download/v${PYTHON_SHORT_VERSION}/python-ios-install-${PYTHON_SHORT_VERSION}.tar.gz + - curl -#OL https://github.com/flet-dev/python-darwin/releases/download/v${PYTHON_SHORT_VERSION}/python-ios-mobile-forge-${PYTHON_SHORT_VERSION}.tar.gz - mkdir -p $python_ios_dir - - tar -xzf python-ios-install-${PYTHON_SHORT_VERSION}.tar.gz -C $python_ios_dir + - tar -xzf python-ios-mobile-forge-${PYTHON_SHORT_VERSION}.tar.gz -C $python_ios_dir # install Rust - curl https://sh.rustup.rs -sSf | sh -s -- -y From 680cc47a53c79b05e341d49dbddb67216f33c10d Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Wed, 25 Sep 2024 16:13:42 -0700 Subject: [PATCH 024/142] Re-build/re-publish all packages to a new feed --- .appveyor.yml | 214 +++++++++++++++++++++++++------------------------- 1 file changed, 107 insertions(+), 107 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index 2bd0ee78..5887ebe8 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -16,11 +16,11 @@ environment: secure: trYGM65OQ1+HYnOYOe/NOHrofLpP3bz64nHwVWPJhiUIYll3MrrQd7ilFNp+zSkI matrix: - - job_name: 'Android: websockets' - job_group: build_android - FORGE_ARCH: android - FORGE_PACKAGES: >- - websockets:13.0.1 + # - job_name: 'Android: websockets' + # job_group: build_android + # FORGE_ARCH: android + # FORGE_PACKAGES: >- + # websockets:13.0.1 # - job_name: 'Android: contourpy' # job_group: build_android @@ -31,122 +31,122 @@ environment: # matplotlib:3.9.2 # pandas:2.2.2 - - job_name: 'iOS: websockets' - job_group: build_ios - FORGE_ARCH: iOS - FORGE_PACKAGES: >- - websockets:13.0.1 + # - job_name: 'iOS: websockets' + # job_group: build_ios + # FORGE_ARCH: iOS + # FORGE_PACKAGES: >- + # websockets:13.0.1 # ================================================== - # - job_name: 'Android arm64-v8a: opencv-python' - # job_group: build_android - # FORGE_ARCH: 'android:arm64-v8a' - # FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 + - job_name: 'Android arm64-v8a: opencv-python' + job_group: build_android + FORGE_ARCH: 'android:arm64-v8a' + FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 - # - job_name: 'Android armeabi-v7a: opencv-python' - # job_group: build_android - # FORGE_ARCH: 'android:armeabi-v7a' - # FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 + - job_name: 'Android armeabi-v7a: opencv-python' + job_group: build_android + FORGE_ARCH: 'android:armeabi-v7a' + FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 - # - job_name: 'Android x86_64: opencv-python' - # job_group: build_android - # FORGE_ARCH: 'android:x86_64' - # FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 + - job_name: 'Android x86_64: opencv-python' + job_group: build_android + FORGE_ARCH: 'android:x86_64' + FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 - # - job_name: 'Android x86: opencv-python' - # job_group: build_android - # FORGE_ARCH: 'android:x86' - # FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 + - job_name: 'Android x86: opencv-python' + job_group: build_android + FORGE_ARCH: 'android:x86' + FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 - # - job_name: 'iOS iphone arm64: opencv-python' - # job_group: build_ios - # FORGE_ARCH: 'iphoneos:arm64' - # FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 + - job_name: 'iOS iphone arm64: opencv-python' + job_group: build_ios + FORGE_ARCH: 'iphoneos:arm64' + FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 - # - job_name: 'iOS simulator arm64: opencv-python' - # job_group: build_ios - # FORGE_ARCH: 'iphonesimulator:arm64' - # FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 + - job_name: 'iOS simulator arm64: opencv-python' + job_group: build_ios + FORGE_ARCH: 'iphonesimulator:arm64' + FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 - # - job_name: 'iOS simulator x86_64: opencv-python' - # job_group: build_ios - # FORGE_ARCH: 'iphonesimulator:x86_64' - # FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 + - job_name: 'iOS simulator x86_64: opencv-python' + job_group: build_ios + FORGE_ARCH: 'iphonesimulator:x86_64' + FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 - # - job_name: 'Android: pydantic-core, pillow, lru-dict, contourpy, kiwisolver, aiohttp, bitarray, argon2-cffi-binding, bcrypt, cryptography, brotli, websockets' - # job_group: build_android - # FORGE_ARCH: android - # FORGE_PACKAGES: >- - # cffi:1.17.1 - # libjpeg:3.0.3 - # libpng:1.6.43 - # freetype:2.13.3 - # pillow:10.4.0 - # lru-dict:1.3.0 - # yarl:1.11.1 - # contourpy:1.3.0 - # kiwisolver:1.4.7 - # aiohttp:3.9.5 - # bitarray:2.9.2 - # argon2-cffi-bindings:21.2.0 - # bcrypt:4.2.0 - # cryptography:43.0.1 - # brotli:1.1.0 - # pydantic-core:2.23.3 - # websockets:13.0.1 + - job_name: 'Android: pydantic-core, pillow, lru-dict, contourpy, kiwisolver, aiohttp, bitarray, argon2-cffi-binding, bcrypt, cryptography, brotli, websockets' + job_group: build_android + FORGE_ARCH: android + FORGE_PACKAGES: >- + cffi:1.17.1 + libjpeg:3.0.3 + libpng:1.6.43 + freetype:2.13.3 + pillow:10.4.0 + lru-dict:1.3.0 + yarl:1.11.1 + contourpy:1.3.0 + kiwisolver:1.4.7 + aiohttp:3.9.5 + bitarray:2.9.2 + argon2-cffi-bindings:21.2.0 + bcrypt:4.2.0 + cryptography:43.0.1 + brotli:1.1.0 + pydantic-core:2.23.3 + websockets:13.0.1 - # - job_name: 'Android: numpy, matplotlib, pandas, blis' - # job_group: build_android - # FORGE_ARCH: android - # FORGE_PACKAGES: >- - # numpy:1.26.4 - # numpy:2.1.1 - # matplotlib:3.9.2 - # pandas:2.2.2 - # blis:1.0.0 + - job_name: 'Android: numpy, matplotlib, pandas, blis' + job_group: build_android + FORGE_ARCH: android + FORGE_PACKAGES: >- + numpy:1.26.4 + numpy:2.1.1 + matplotlib:3.9.2 + pandas:2.2.2 + blis:1.0.0 - # - job_name: 'iOS: pillow, lru-dict, yarl, contourpy, kiwisolver, aiohttp, bitarray, websockets' - # job_group: build_ios - # FORGE_ARCH: iOS - # FORGE_PACKAGES: >- - # libjpeg:3.0.3 - # libpng:1.6.43 - # freetype:2.13.3 - # pillow:10.4.0 - # lru-dict:1.3.0 - # yarl:1.11.1 - # contourpy:1.3.0 - # kiwisolver:1.4.7 - # aiohttp:3.9.5 - # bitarray:2.9.2 - # websockets:13.0.1 + - job_name: 'iOS: pillow, lru-dict, yarl, contourpy, kiwisolver, aiohttp, bitarray, websockets' + job_group: build_ios + FORGE_ARCH: iOS + FORGE_PACKAGES: >- + libjpeg:3.0.3 + libpng:1.6.43 + freetype:2.13.3 + pillow:10.4.0 + lru-dict:1.3.0 + yarl:1.11.1 + contourpy:1.3.0 + kiwisolver:1.4.7 + aiohttp:3.9.5 + bitarray:2.9.2 + websockets:13.0.1 - # - job_name: 'iOS: cffi, argon2-cffi-bindings, bcrypt, cryptography, brotli' - # job_group: build_ios - # FORGE_ARCH: iOS - # FORGE_PACKAGES: >- - # cffi:1.17.1 - # argon2-cffi-bindings:21.2.0 - # bcrypt:4.2.0 - # cryptography:43.0.1 - # brotli:1.1.0 - - # - job_name: 'iOS: pydantic-core' - # job_group: build_ios - # FORGE_ARCH: iOS - # FORGE_PACKAGES: >- - # pydantic-core:2.23.3 + - job_name: 'iOS: cffi, argon2-cffi-bindings, bcrypt, cryptography, brotli' + job_group: build_ios + FORGE_ARCH: iOS + FORGE_PACKAGES: >- + cffi:1.17.1 + argon2-cffi-bindings:21.2.0 + bcrypt:4.2.0 + cryptography:43.0.1 + brotli:1.1.0 + + - job_name: 'iOS: pydantic-core' + job_group: build_ios + FORGE_ARCH: iOS + FORGE_PACKAGES: >- + pydantic-core:2.23.3 - # - job_name: 'iOS: numpy, matplotlib, pandas, blis' - # job_group: build_ios - # FORGE_ARCH: iOS - # FORGE_PACKAGES: >- - # numpy:1.26.4 - # numpy:2.1.1 - # matplotlib:3.9.2 - # pandas:2.2.2 - # blis:1.0.0 + - job_name: 'iOS: numpy, matplotlib, pandas, blis' + job_group: build_ios + FORGE_ARCH: iOS + FORGE_PACKAGES: >- + numpy:1.26.4 + numpy:2.1.1 + matplotlib:3.9.2 + pandas:2.2.2 + blis:1.0.0 # - job_name: Re-build Simple index # job_group: rebuild_index From 7c9cbbf15aa2c62636477bd7a0025334e135d3e3 Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Fri, 27 Sep 2024 13:01:58 -0700 Subject: [PATCH 025/142] Use flet-build repo --- .appveyor.yml | 222 +++++++++++++++++++++++++------------------------- 1 file changed, 111 insertions(+), 111 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index 5887ebe8..8ec2c98f 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -16,11 +16,11 @@ environment: secure: trYGM65OQ1+HYnOYOe/NOHrofLpP3bz64nHwVWPJhiUIYll3MrrQd7ilFNp+zSkI matrix: - # - job_name: 'Android: websockets' - # job_group: build_android - # FORGE_ARCH: android - # FORGE_PACKAGES: >- - # websockets:13.0.1 + - job_name: 'Android: websockets' + job_group: build_android + FORGE_ARCH: android + FORGE_PACKAGES: >- + websockets:13.0.1 # - job_name: 'Android: contourpy' # job_group: build_android @@ -31,122 +31,122 @@ environment: # matplotlib:3.9.2 # pandas:2.2.2 - # - job_name: 'iOS: websockets' - # job_group: build_ios - # FORGE_ARCH: iOS - # FORGE_PACKAGES: >- - # websockets:13.0.1 + - job_name: 'iOS: websockets' + job_group: build_ios + FORGE_ARCH: iOS + FORGE_PACKAGES: >- + websockets:13.0.1 # ================================================== - - job_name: 'Android arm64-v8a: opencv-python' - job_group: build_android - FORGE_ARCH: 'android:arm64-v8a' - FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 + # - job_name: 'Android arm64-v8a: opencv-python' + # job_group: build_android + # FORGE_ARCH: 'android:arm64-v8a' + # FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 - - job_name: 'Android armeabi-v7a: opencv-python' - job_group: build_android - FORGE_ARCH: 'android:armeabi-v7a' - FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 + # - job_name: 'Android armeabi-v7a: opencv-python' + # job_group: build_android + # FORGE_ARCH: 'android:armeabi-v7a' + # FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 - - job_name: 'Android x86_64: opencv-python' - job_group: build_android - FORGE_ARCH: 'android:x86_64' - FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 + # - job_name: 'Android x86_64: opencv-python' + # job_group: build_android + # FORGE_ARCH: 'android:x86_64' + # FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 - - job_name: 'Android x86: opencv-python' - job_group: build_android - FORGE_ARCH: 'android:x86' - FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 + # - job_name: 'Android x86: opencv-python' + # job_group: build_android + # FORGE_ARCH: 'android:x86' + # FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 - - job_name: 'iOS iphone arm64: opencv-python' - job_group: build_ios - FORGE_ARCH: 'iphoneos:arm64' - FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 + # - job_name: 'iOS iphone arm64: opencv-python' + # job_group: build_ios + # FORGE_ARCH: 'iphoneos:arm64' + # FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 - - job_name: 'iOS simulator arm64: opencv-python' - job_group: build_ios - FORGE_ARCH: 'iphonesimulator:arm64' - FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 + # - job_name: 'iOS simulator arm64: opencv-python' + # job_group: build_ios + # FORGE_ARCH: 'iphonesimulator:arm64' + # FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 - - job_name: 'iOS simulator x86_64: opencv-python' - job_group: build_ios - FORGE_ARCH: 'iphonesimulator:x86_64' - FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 + # - job_name: 'iOS simulator x86_64: opencv-python' + # job_group: build_ios + # FORGE_ARCH: 'iphonesimulator:x86_64' + # FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 - - job_name: 'Android: pydantic-core, pillow, lru-dict, contourpy, kiwisolver, aiohttp, bitarray, argon2-cffi-binding, bcrypt, cryptography, brotli, websockets' - job_group: build_android - FORGE_ARCH: android - FORGE_PACKAGES: >- - cffi:1.17.1 - libjpeg:3.0.3 - libpng:1.6.43 - freetype:2.13.3 - pillow:10.4.0 - lru-dict:1.3.0 - yarl:1.11.1 - contourpy:1.3.0 - kiwisolver:1.4.7 - aiohttp:3.9.5 - bitarray:2.9.2 - argon2-cffi-bindings:21.2.0 - bcrypt:4.2.0 - cryptography:43.0.1 - brotli:1.1.0 - pydantic-core:2.23.3 - websockets:13.0.1 + # - job_name: 'Android: pydantic-core, pillow, lru-dict, contourpy, kiwisolver, aiohttp, bitarray, argon2-cffi-binding, bcrypt, cryptography, brotli, websockets' + # job_group: build_android + # FORGE_ARCH: android + # FORGE_PACKAGES: >- + # cffi:1.17.1 + # libjpeg:3.0.3 + # libpng:1.6.43 + # freetype:2.13.3 + # pillow:10.4.0 + # lru-dict:1.3.0 + # yarl:1.11.1 + # contourpy:1.3.0 + # kiwisolver:1.4.7 + # aiohttp:3.9.5 + # bitarray:2.9.2 + # argon2-cffi-bindings:21.2.0 + # bcrypt:4.2.0 + # cryptography:43.0.1 + # brotli:1.1.0 + # pydantic-core:2.23.3 + # websockets:13.0.1 - - job_name: 'Android: numpy, matplotlib, pandas, blis' - job_group: build_android - FORGE_ARCH: android - FORGE_PACKAGES: >- - numpy:1.26.4 - numpy:2.1.1 - matplotlib:3.9.2 - pandas:2.2.2 - blis:1.0.0 + # - job_name: 'Android: numpy, matplotlib, pandas, blis' + # job_group: build_android + # FORGE_ARCH: android + # FORGE_PACKAGES: >- + # numpy:1.26.4 + # numpy:2.1.1 + # matplotlib:3.9.2 + # pandas:2.2.2 + # blis:1.0.0 - - job_name: 'iOS: pillow, lru-dict, yarl, contourpy, kiwisolver, aiohttp, bitarray, websockets' - job_group: build_ios - FORGE_ARCH: iOS - FORGE_PACKAGES: >- - libjpeg:3.0.3 - libpng:1.6.43 - freetype:2.13.3 - pillow:10.4.0 - lru-dict:1.3.0 - yarl:1.11.1 - contourpy:1.3.0 - kiwisolver:1.4.7 - aiohttp:3.9.5 - bitarray:2.9.2 - websockets:13.0.1 + # - job_name: 'iOS: pillow, lru-dict, yarl, contourpy, kiwisolver, aiohttp, bitarray, websockets' + # job_group: build_ios + # FORGE_ARCH: iOS + # FORGE_PACKAGES: >- + # libjpeg:3.0.3 + # libpng:1.6.43 + # freetype:2.13.3 + # pillow:10.4.0 + # lru-dict:1.3.0 + # yarl:1.11.1 + # contourpy:1.3.0 + # kiwisolver:1.4.7 + # aiohttp:3.9.5 + # bitarray:2.9.2 + # websockets:13.0.1 - - job_name: 'iOS: cffi, argon2-cffi-bindings, bcrypt, cryptography, brotli' - job_group: build_ios - FORGE_ARCH: iOS - FORGE_PACKAGES: >- - cffi:1.17.1 - argon2-cffi-bindings:21.2.0 - bcrypt:4.2.0 - cryptography:43.0.1 - brotli:1.1.0 - - - job_name: 'iOS: pydantic-core' - job_group: build_ios - FORGE_ARCH: iOS - FORGE_PACKAGES: >- - pydantic-core:2.23.3 + # - job_name: 'iOS: cffi, argon2-cffi-bindings, bcrypt, cryptography, brotli' + # job_group: build_ios + # FORGE_ARCH: iOS + # FORGE_PACKAGES: >- + # cffi:1.17.1 + # argon2-cffi-bindings:21.2.0 + # bcrypt:4.2.0 + # cryptography:43.0.1 + # brotli:1.1.0 + + # - job_name: 'iOS: pydantic-core' + # job_group: build_ios + # FORGE_ARCH: iOS + # FORGE_PACKAGES: >- + # pydantic-core:2.23.3 - - job_name: 'iOS: numpy, matplotlib, pandas, blis' - job_group: build_ios - FORGE_ARCH: iOS - FORGE_PACKAGES: >- - numpy:1.26.4 - numpy:2.1.1 - matplotlib:3.9.2 - pandas:2.2.2 - blis:1.0.0 + # - job_name: 'iOS: numpy, matplotlib, pandas, blis' + # job_group: build_ios + # FORGE_ARCH: iOS + # FORGE_PACKAGES: >- + # numpy:1.26.4 + # numpy:2.1.1 + # matplotlib:3.9.2 + # pandas:2.2.2 + # blis:1.0.0 # - job_name: Re-build Simple index # job_group: rebuild_index @@ -184,8 +184,8 @@ for: - . .ci/common.sh # download Python for Android - - python_android_dir=$HOME/projects/python-android - - curl -#OL https://github.com/flet-dev/python-android/releases/download/v${PYTHON_SHORT_VERSION}/python-android-mobile-forge-${PYTHON_SHORT_VERSION}.tar.gz + - python_android_dir=$HOME/projects/python-build/android + - curl -#OL https://github.com/flet-dev/python-build/releases/download/v${PYTHON_SHORT_VERSION}/python-android-mobile-forge-${PYTHON_SHORT_VERSION}.tar.gz - mkdir -p $python_android_dir - tar -xzf python-android-mobile-forge-${PYTHON_SHORT_VERSION}.tar.gz -C $python_android_dir @@ -240,8 +240,8 @@ for: - . .ci/common.sh # download Python for iOS - - python_ios_dir=$HOME/projects/python-darwin/Python-Apple-support - - curl -#OL https://github.com/flet-dev/python-darwin/releases/download/v${PYTHON_SHORT_VERSION}/python-ios-mobile-forge-${PYTHON_SHORT_VERSION}.tar.gz + - python_ios_dir=$HOME/projects/python-build/darwin/Python-Apple-support + - curl -#OL https://github.com/flet-dev/python-build/releases/download/v${PYTHON_SHORT_VERSION}/python-ios-mobile-forge-${PYTHON_SHORT_VERSION}.tar.gz - mkdir -p $python_ios_dir - tar -xzf python-ios-mobile-forge-${PYTHON_SHORT_VERSION}.tar.gz -C $python_ios_dir From aada3c0caad62dc33a2fad773dd2643e0a965e73 Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Fri, 27 Sep 2024 13:20:40 -0700 Subject: [PATCH 026/142] build Android: contourpy --- .appveyor.yml | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index 8ec2c98f..ad6e59b8 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -16,26 +16,26 @@ environment: secure: trYGM65OQ1+HYnOYOe/NOHrofLpP3bz64nHwVWPJhiUIYll3MrrQd7ilFNp+zSkI matrix: - - job_name: 'Android: websockets' - job_group: build_android - FORGE_ARCH: android - FORGE_PACKAGES: >- - websockets:13.0.1 - - # - job_name: 'Android: contourpy' + # - job_name: 'Android: websockets' # job_group: build_android - # FORGE_ARCH: 'android' + # FORGE_ARCH: android # FORGE_PACKAGES: >- - # contourpy:1.3.0 - # numpy:2.1.1 - # matplotlib:3.9.2 - # pandas:2.2.2 + # websockets:13.0.1 - - job_name: 'iOS: websockets' - job_group: build_ios - FORGE_ARCH: iOS + - job_name: 'Android: contourpy' + job_group: build_android + FORGE_ARCH: 'android' FORGE_PACKAGES: >- - websockets:13.0.1 + contourpy:1.3.0 + numpy:2.1.1 + matplotlib:3.9.2 + pandas:2.2.2 + + # - job_name: 'iOS: websockets' + # job_group: build_ios + # FORGE_ARCH: iOS + # FORGE_PACKAGES: >- + # websockets:13.0.1 # ================================================== From d6e03ad2388fa941be11c8d56eac121fb1cb1493 Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Mon, 7 Oct 2024 12:46:36 -0700 Subject: [PATCH 027/142] Build MarkupSafe --- .appveyor.yml | 32 ++++++++++++++++---------------- pyproject.toml | 20 ++++++-------------- recipes/markupsafe/meta.yaml | 3 +++ 3 files changed, 25 insertions(+), 30 deletions(-) create mode 100644 recipes/markupsafe/meta.yaml diff --git a/.appveyor.yml b/.appveyor.yml index ad6e59b8..cb2140b3 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -16,26 +16,26 @@ environment: secure: trYGM65OQ1+HYnOYOe/NOHrofLpP3bz64nHwVWPJhiUIYll3MrrQd7ilFNp+zSkI matrix: - # - job_name: 'Android: websockets' - # job_group: build_android - # FORGE_ARCH: android - # FORGE_PACKAGES: >- - # websockets:13.0.1 - - - job_name: 'Android: contourpy' + - job_name: 'Android: markupsafe' job_group: build_android - FORGE_ARCH: 'android' + FORGE_ARCH: android FORGE_PACKAGES: >- - contourpy:1.3.0 - numpy:2.1.1 - matplotlib:3.9.2 - pandas:2.2.2 + markupsafe - # - job_name: 'iOS: websockets' - # job_group: build_ios - # FORGE_ARCH: iOS + - job_name: 'iOS: markupsafe' + job_group: build_ios + FORGE_ARCH: iOS + FORGE_PACKAGES: >- + markupsafe + + # - job_name: 'Android: contourpy' + # job_group: build_android + # FORGE_ARCH: 'android' # FORGE_PACKAGES: >- - # websockets:13.0.1 + # contourpy:1.3.0 + # numpy:2.1.1 + # matplotlib:3.9.2 + # pandas:2.2.2 # ================================================== diff --git a/pyproject.toml b/pyproject.toml index 59bae745..ea7b5410 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,14 +6,12 @@ build-backend = "setuptools.build_meta" name = "mobile-forge" version = "2023.0.0" description = "A tool to manage building cross-platform binary wheels for mobile devices" -readme = { file = "README.md", content-type = "text/x-rst"} +readme = { file = "README.md", content-type = "text/x-rst" } requires-python = ">=3.8" license = { file = "LICENSE" } -authors = [ - {name = "Russell Keith-Magee", email = "russell@keith-magee.com"} -] +authors = [{ name = "Russell Keith-Magee", email = "russell@keith-magee.com" }] maintainers = [ - {name = "Russell Keith-Magee", email = "russell@keith-magee.com"} + { name = "Russell Keith-Magee", email = "russell@keith-magee.com" }, ] classifiers = [ "Development Status :: 3 - Alpha", @@ -33,7 +31,7 @@ dependencies = [ # Replace when/if these are merged and released. #"crossenv @ git+https://github.com/flet-dev/crossenv@ios-support", #"crossenv @ git+https://github.com/freakboy3742/crossenv@f0f07129eb06ea16d180650a26a02df2b948b888", - "crossenv @ git+https://github.com/freakboy3742/crossenv@iOS-support", + "crossenv @ git+https://github.com/benfogle/crossenv@c801a526403a06f653939a0c45534d7703f9066f", "httpx == 0.27.0", "Jinja2 == 3.1.3", "jsonschema == 4.21.1", @@ -44,9 +42,7 @@ dependencies = [ ] [project.optional-dependencies] -dev = [ - "pre-commit==3.7.0", -] +dev = ["pre-commit==3.7.0"] [project.urls] Homepage = "https://beeware.org" @@ -60,11 +56,7 @@ forge-env = "forge.cross:main" [tool.isort] profile = "black" -skip_glob = [ - "docs/conf.py", - "venv*", - "local", -] +skip_glob = ["docs/conf.py", "venv*", "local"] multi_line_output = 3 [tool.codespell] diff --git a/recipes/markupsafe/meta.yaml b/recipes/markupsafe/meta.yaml new file mode 100644 index 00000000..8a10f7a1 --- /dev/null +++ b/recipes/markupsafe/meta.yaml @@ -0,0 +1,3 @@ +package: + name: MarkupSafe + version: 2.1.5 From 6d25e739910c010eaea6815fe2a1596ed3d81c3e Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Tue, 29 Oct 2024 13:51:54 -0700 Subject: [PATCH 028/142] Android fixes and new packages (#9) * time-machine package added * Always build as simple package if `build.sh` found * flet-libcpp-shared recipe * flet-libjpeg recipe * Strip libraries in wheels - draft * Strip .so in built wheels * Build flet-libjpeg * PYTHON_VERSION: 3.12.7 * flet-libjpeg 3.0.90 * NDK_VERSION: r27c * Re-build android packages * Fix yaml * Re-build android packages * Fix recipes * Re-build numpy * re-built wheel in a temp dir * ls -al dist * Re-build matplotlib * flet-libcpp-shared * Add build number to a wheel * Re-build android packages * Fix kiwisolver --- .appveyor.yml | 66 ++++++---- make_dep_wheels.py | 4 +- recipes/{freetype => flet-freetype}/build.sh | 0 recipes/{freetype => flet-freetype}/meta.yaml | 2 +- .../patches/config.patch | 0 recipes/flet-libcpp-shared/build.sh | 13 ++ recipes/flet-libcpp-shared/meta.yaml | 6 + recipes/{libjpeg => flet-libjpeg}/build.sh | 3 +- recipes/{libjpeg => flet-libjpeg}/meta.yaml | 6 +- recipes/{libpng => flet-libpng}/build.sh | 0 recipes/{libpng => flet-libpng}/meta.yaml | 2 +- .../patches/config.patch | 0 recipes/kiwisolver/meta.yaml | 6 +- recipes/matplotlib/meta.yaml | 1 + recipes/pandas/meta.yaml | 1 + recipes/pillow/meta.yaml | 4 +- recipes/time-machine/meta.yaml | 3 + setup.sh | 2 +- src/forge/__main__.py | 84 +------------ src/forge/build.py | 117 +++++++++++++++--- src/forge/package.py | 8 +- 21 files changed, 190 insertions(+), 138 deletions(-) rename recipes/{freetype => flet-freetype}/build.sh (100%) rename recipes/{freetype => flet-freetype}/meta.yaml (90%) rename recipes/{freetype => flet-freetype}/patches/config.patch (100%) create mode 100755 recipes/flet-libcpp-shared/build.sh create mode 100644 recipes/flet-libcpp-shared/meta.yaml rename recipes/{libjpeg => flet-libjpeg}/build.sh (88%) rename recipes/{libjpeg => flet-libjpeg}/meta.yaml (62%) rename recipes/{libpng => flet-libpng}/build.sh (100%) rename recipes/{libpng => flet-libpng}/meta.yaml (88%) rename recipes/{libpng => flet-libpng}/patches/config.patch (100%) create mode 100644 recipes/time-machine/meta.yaml diff --git a/.appveyor.yml b/.appveyor.yml index cb2140b3..d2d519bb 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -3,7 +3,7 @@ image: macos-monterey skip_branch_with_pr: true environment: - PYTHON_VERSION: 3.12.6 + PYTHON_VERSION: 3.12.7 PYTHON_SHORT_VERSION: 3.12 CF_ACCESS_KEY_ID: secure: +m1fzbrEPRecXKCCMn4uA781PAASzJSWAxuJj1c7ctLfWbi5oW4PMnowPK96XtQ5 @@ -16,26 +16,19 @@ environment: secure: trYGM65OQ1+HYnOYOe/NOHrofLpP3bz64nHwVWPJhiUIYll3MrrQd7ilFNp+zSkI matrix: - - job_name: 'Android: markupsafe' + - job_name: 'Android: kiwisolver' job_group: build_android FORGE_ARCH: android FORGE_PACKAGES: >- - markupsafe + flet-libcpp-shared:27.2.12479018 + kiwisolver:1.4.7 + BUILD_NUMBER: 1 - - job_name: 'iOS: markupsafe' - job_group: build_ios - FORGE_ARCH: iOS - FORGE_PACKAGES: >- - markupsafe - - # - job_name: 'Android: contourpy' - # job_group: build_android - # FORGE_ARCH: 'android' + # - job_name: 'iOS: flet-libjpeg' + # job_group: build_ios + # FORGE_ARCH: iOS # FORGE_PACKAGES: >- - # contourpy:1.3.0 - # numpy:2.1.1 - # matplotlib:3.9.2 - # pandas:2.2.2 + # flet-libjpeg # ================================================== @@ -43,45 +36,53 @@ environment: # job_group: build_android # FORGE_ARCH: 'android:arm64-v8a' # FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 + # BUILD_NUMBER: 1 # - job_name: 'Android armeabi-v7a: opencv-python' # job_group: build_android # FORGE_ARCH: 'android:armeabi-v7a' # FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 + # BUILD_NUMBER: 1 # - job_name: 'Android x86_64: opencv-python' # job_group: build_android # FORGE_ARCH: 'android:x86_64' # FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 + # BUILD_NUMBER: 1 # - job_name: 'Android x86: opencv-python' # job_group: build_android # FORGE_ARCH: 'android:x86' # FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 + # BUILD_NUMBER: 1 # - job_name: 'iOS iphone arm64: opencv-python' # job_group: build_ios # FORGE_ARCH: 'iphoneos:arm64' # FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 + # BUILD_NUMBER: 1 # - job_name: 'iOS simulator arm64: opencv-python' # job_group: build_ios # FORGE_ARCH: 'iphonesimulator:arm64' # FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 + # BUILD_NUMBER: 1 # - job_name: 'iOS simulator x86_64: opencv-python' # job_group: build_ios # FORGE_ARCH: 'iphonesimulator:x86_64' # FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 + # BUILD_NUMBER: 1 # - job_name: 'Android: pydantic-core, pillow, lru-dict, contourpy, kiwisolver, aiohttp, bitarray, argon2-cffi-binding, bcrypt, cryptography, brotli, websockets' # job_group: build_android # FORGE_ARCH: android # FORGE_PACKAGES: >- # cffi:1.17.1 - # libjpeg:3.0.3 - # libpng:1.6.43 - # freetype:2.13.3 + # flet-libcpp-shared:27.2.12479018 + # flet-libjpeg:3.0.90 + # flet-libpng:1.6.43 + # flet-freetype:2.13.3 # pillow:10.4.0 # lru-dict:1.3.0 # yarl:1.11.1 @@ -95,24 +96,30 @@ environment: # brotli:1.1.0 # pydantic-core:2.23.3 # websockets:13.0.1 + # time-machine:2.16.0 + # markupsafe:2.1.5 + # BUILD_NUMBER: 1 # - job_name: 'Android: numpy, matplotlib, pandas, blis' # job_group: build_android # FORGE_ARCH: android # FORGE_PACKAGES: >- + # flet-libcpp-shared:27.2.12479018 # numpy:1.26.4 # numpy:2.1.1 + # flet-libjpeg:3.0.90 # matplotlib:3.9.2 # pandas:2.2.2 # blis:1.0.0 + # BUILD_NUMBER: 1 # - job_name: 'iOS: pillow, lru-dict, yarl, contourpy, kiwisolver, aiohttp, bitarray, websockets' # job_group: build_ios # FORGE_ARCH: iOS # FORGE_PACKAGES: >- - # libjpeg:3.0.3 - # libpng:1.6.43 - # freetype:2.13.3 + # flet-libjpeg:3.0.90 + # flet-libpng:1.6.43 + # flet-freetype:2.13.3 # pillow:10.4.0 # lru-dict:1.3.0 # yarl:1.11.1 @@ -121,6 +128,9 @@ environment: # aiohttp:3.9.5 # bitarray:2.9.2 # websockets:13.0.1 + # time-machine:2.16.0 + # markupsafe:2.1.5 + # BUILD_NUMBER: 1 # - job_name: 'iOS: cffi, argon2-cffi-bindings, bcrypt, cryptography, brotli' # job_group: build_ios @@ -131,12 +141,14 @@ environment: # bcrypt:4.2.0 # cryptography:43.0.1 # brotli:1.1.0 + # BUILD_NUMBER: 1 # - job_name: 'iOS: pydantic-core' # job_group: build_ios # FORGE_ARCH: iOS # FORGE_PACKAGES: >- # pydantic-core:2.23.3 + # BUILD_NUMBER: 1 # - job_name: 'iOS: numpy, matplotlib, pandas, blis' # job_group: build_ios @@ -144,9 +156,11 @@ environment: # FORGE_PACKAGES: >- # numpy:1.26.4 # numpy:2.1.1 + # flet-libjpeg:3.0.90 # matplotlib:3.9.2 # pandas:2.2.2 # blis:1.0.0 + # BUILD_NUMBER: 1 # - job_name: Re-build Simple index # job_group: rebuild_index @@ -178,7 +192,7 @@ for: environment: APPVEYOR_BUILD_WORKER_IMAGE: ubuntu-gce-c - NDK_VERSION: r27 + NDK_VERSION: r27c install: - . .ci/common.sh @@ -209,14 +223,14 @@ for: - sh: | IFS=' ' read -r -a packages <<< "$FORGE_PACKAGES" for package in "${packages[@]}"; do - forge $FORGE_ARCH $package || exit 1 + forge $FORGE_ARCH $package:$BUILD_NUMBER || exit 1 done # cleanup - rm dist/bzip2-* - rm dist/xz-* - - rm dist/libffi-* - rm dist/openssl-* + - rm dist/libffi-* deploy_script: # - pip install boto3 @@ -264,7 +278,7 @@ for: - sh: | IFS=' ' read -r -a packages <<< "$FORGE_PACKAGES" for package in "${packages[@]}"; do - forge $FORGE_ARCH $package || exit 1 + forge $FORGE_ARCH $package:$BUILD_NUMBER || exit 1 done # cleanup diff --git a/make_dep_wheels.py b/make_dep_wheels.py index 72657018..5c685d61 100644 --- a/make_dep_wheels.py +++ b/make_dep_wheels.py @@ -46,7 +46,9 @@ def make_wheel(package, os_name, target): with versions_file.open(encoding="utf-8") as f: versions = f.read() - package_version_build = re.search(rf"^{package}: (.*)", versions, re.MULTILINE)[1] + package_version_build = re.search( + rf"^{package}: (.*)", versions, re.MULTILINE | re.IGNORECASE + )[1] min_version = re.search(rf"^Min {os_name} version: (.*)", versions, re.MULTILINE)[1] package_version, package_build = package_version_build.split("-") diff --git a/recipes/freetype/build.sh b/recipes/flet-freetype/build.sh similarity index 100% rename from recipes/freetype/build.sh rename to recipes/flet-freetype/build.sh diff --git a/recipes/freetype/meta.yaml b/recipes/flet-freetype/meta.yaml similarity index 90% rename from recipes/freetype/meta.yaml rename to recipes/flet-freetype/meta.yaml index fbc9cadc..b09f7a01 100644 --- a/recipes/freetype/meta.yaml +++ b/recipes/flet-freetype/meta.yaml @@ -1,5 +1,5 @@ package: - name: freetype + name: flet-freetype version: 2.13.3 build: diff --git a/recipes/freetype/patches/config.patch b/recipes/flet-freetype/patches/config.patch similarity index 100% rename from recipes/freetype/patches/config.patch rename to recipes/flet-freetype/patches/config.patch diff --git a/recipes/flet-libcpp-shared/build.sh b/recipes/flet-libcpp-shared/build.sh new file mode 100755 index 00000000..3ffec39c --- /dev/null +++ b/recipes/flet-libcpp-shared/build.sh @@ -0,0 +1,13 @@ +#!/bin/bash +set -eu + +if [[ "$CROSS_VENV_SDK" != "android" ]]; then + echo "This package can be built for Android only." + exit 1 +fi + +toolchain=$(echo $NDK_ROOT/toolchains/llvm/prebuilt/*) +export LIBC_SHARED_SO="$toolchain/sysroot/usr/lib/${HOST_TRIPLET}/libc++_shared.so" + +mkdir -p $PREFIX/lib +cp $LIBC_SHARED_SO $PREFIX/lib diff --git a/recipes/flet-libcpp-shared/meta.yaml b/recipes/flet-libcpp-shared/meta.yaml new file mode 100644 index 00000000..12184be3 --- /dev/null +++ b/recipes/flet-libcpp-shared/meta.yaml @@ -0,0 +1,6 @@ +package: + name: flet-libcpp-shared + version: 27.2.12479018 + +source: + url: https://github.com/flet-dev/awesome-flet/archive/refs/heads/main.zip \ No newline at end of file diff --git a/recipes/libjpeg/build.sh b/recipes/flet-libjpeg/build.sh similarity index 88% rename from recipes/libjpeg/build.sh rename to recipes/flet-libjpeg/build.sh index 85e14b8e..37e50c19 100755 --- a/recipes/libjpeg/build.sh +++ b/recipes/flet-libjpeg/build.sh @@ -8,10 +8,11 @@ if [ $CROSS_VENV_SDK == "android" ]; then -DANDROID_PLATFORM=24 \ -DANDROID_ABI=$ANDROID_ABI \ -DCMAKE_TOOLCHAIN_FILE=$NDK_ROOT/build/cmake/android.toolchain.cmake \ - -DWITH_SIMD=OFF \ -DCMAKE_INSTALL_PREFIX=$PREFIX . else cmake -G"Unix Makefiles" \ + -DCMAKE_SYSTEM_NAME=iOS \ + -DCMAKE_SYSTEM_PROCESSOR=$HOST_ARCH \ -DCMAKE_INSTALL_PREFIX=$PREFIX . fi diff --git a/recipes/libjpeg/meta.yaml b/recipes/flet-libjpeg/meta.yaml similarity index 62% rename from recipes/libjpeg/meta.yaml rename to recipes/flet-libjpeg/meta.yaml index 49a7f0ae..c3ad9580 100644 --- a/recipes/libjpeg/meta.yaml +++ b/recipes/flet-libjpeg/meta.yaml @@ -1,9 +1,9 @@ package: - name: libjpeg - version: 3.0.3 + name: flet-libjpeg + version: 3.0.90 source: - url: https://github.com/libjpeg-turbo/libjpeg-turbo/releases/download/3.0.3/libjpeg-turbo-3.0.3.tar.gz + url: https://github.com/libjpeg-turbo/libjpeg-turbo/releases/download/3.0.90/libjpeg-turbo-3.0.90.tar.gz build: number: 1 diff --git a/recipes/libpng/build.sh b/recipes/flet-libpng/build.sh similarity index 100% rename from recipes/libpng/build.sh rename to recipes/flet-libpng/build.sh diff --git a/recipes/libpng/meta.yaml b/recipes/flet-libpng/meta.yaml similarity index 88% rename from recipes/libpng/meta.yaml rename to recipes/flet-libpng/meta.yaml index a3d00a75..21eaa2c4 100644 --- a/recipes/libpng/meta.yaml +++ b/recipes/flet-libpng/meta.yaml @@ -1,5 +1,5 @@ package: - name: libpng + name: flet-libpng version: 1.6.43 build: diff --git a/recipes/libpng/patches/config.patch b/recipes/flet-libpng/patches/config.patch similarity index 100% rename from recipes/libpng/patches/config.patch rename to recipes/flet-libpng/patches/config.patch diff --git a/recipes/kiwisolver/meta.yaml b/recipes/kiwisolver/meta.yaml index a690af34..ef5fb92c 100644 --- a/recipes/kiwisolver/meta.yaml +++ b/recipes/kiwisolver/meta.yaml @@ -1,3 +1,7 @@ package: name: kiwisolver - version: 1.4.7 \ No newline at end of file + version: 1.4.7 + +requirements: + host: + - flet-libcpp-shared 27.2.12479018 \ No newline at end of file diff --git a/recipes/matplotlib/meta.yaml b/recipes/matplotlib/meta.yaml index 814d1aea..cb1ff1ee 100644 --- a/recipes/matplotlib/meta.yaml +++ b/recipes/matplotlib/meta.yaml @@ -8,6 +8,7 @@ requirements: host: - numpy ^2.0.0 - pybind11 + - flet-libjpeg 3.0.90 build: backend-args: diff --git a/recipes/pandas/meta.yaml b/recipes/pandas/meta.yaml index a9d1022f..e06f7153 100644 --- a/recipes/pandas/meta.yaml +++ b/recipes/pandas/meta.yaml @@ -7,6 +7,7 @@ requirements: - ninja host: - numpy ^2.0.0 + - flet-libcpp-shared 27.2.12479018 patches: - mobile.patch diff --git a/recipes/pillow/meta.yaml b/recipes/pillow/meta.yaml index 28b1c576..3ca0085e 100644 --- a/recipes/pillow/meta.yaml +++ b/recipes/pillow/meta.yaml @@ -5,8 +5,8 @@ package: requirements: host: # PNG support is internal: libpng is not used. - - libjpeg - - freetype + - flet-libjpeg 3.0.90 + - flet-freetype 2.13.3 patches: - setup.patch diff --git a/recipes/time-machine/meta.yaml b/recipes/time-machine/meta.yaml new file mode 100644 index 00000000..8f8c5a59 --- /dev/null +++ b/recipes/time-machine/meta.yaml @@ -0,0 +1,3 @@ +package: + name: time-machine + version: 2.16.0 \ No newline at end of file diff --git a/setup.sh b/setup.sh index 522f809e..bb0408a2 100755 --- a/setup.sh +++ b/setup.sh @@ -28,7 +28,7 @@ PYTHON_VERSION=$1 read python_version_major python_version_minor < <(echo $PYTHON_VERSION | sed -E 's/^([0-9]+)\.([0-9]+).*/\1 \2/') PYTHON_VER=$python_version_major.$python_version_minor -PYTHON_URL_PREFIX=https://github.com/indygreg/python-build-standalone/releases/download/20240909/cpython-$PYTHON_VERSION+20240909 +PYTHON_URL_PREFIX=https://github.com/indygreg/python-build-standalone/releases/download/20241016/cpython-$PYTHON_VERSION+20241016 echo "Python version: $PYTHON_VERSION" echo "Python short version: $PYTHON_VER" diff --git a/src/forge/__main__.py b/src/forge/__main__.py index 7a4678c5..17ed8f14 100644 --- a/src/forge/__main__.py +++ b/src/forge/__main__.py @@ -99,83 +99,7 @@ def main(): print() sys.exit(1) - # Targets that generate py3-none-any wheels only need to be built on a single - # platform. - py_any_targets = [ - "oldest-supported-numpy", - ] - - if not args.build_targets: - build_targets = [] - - if args.subset in {"all", "py-any", "smoke"}: - build_targets.extend(py_any_targets) - - if args.subset in {"all", "non-py", "smoke", "smoke-non-py"}: - build_targets.extend( - [ - "libjpeg", - "freetype", - ] - ) - - if args.subset in {"all", "non-py", "non-smoke"}: - build_targets.extend( - [ - "libpng", - ] - ) - - # Pandas uses a meta-package called "oldest-supported-numpy" which installs, - # predictably, the oldest version of numpy known to work on a given Python - # version. This is done for Python ABI compatibility. - oldest_supported_numpy = { - 8: "numpy:1.17.3", - 9: "numpy:1.19.3", - 10: "numpy:1.21.6", - 11: "numpy:1.23.2", - 12: "numpy:1.26.0", - 13: "numpy:1.26.0", - }[sys.version_info.minor] - - if args.subset in {"all", "py", "smoke", "smoke-py"}: - build_targets.extend( - [ - "lru-dict", - "pillow", - "numpy", - ] - # On Python 3.12 and 3.13, the oldest supported numpy *is* the only version of - # numpy that is supported. - + ( - [ - oldest_supported_numpy, - ] - if sys.version_info.minor in {12, 13} - else [] - ) - + [ - "pandas", - "cffi", - "cryptography", - ] - ) - - if args.subset in {"all", "py", "non-smoke"}: - build_targets.extend( - [ - "aiohttp", - "argon2-cffi", - "bcrypt", - "bitarray", - "blis", - "brotli", - "typed-ast", - "yarl", - ] - ) - else: - build_targets = args.build_targets + build_targets = args.build_targets or [] successes = [] failures = [] @@ -218,11 +142,7 @@ def main(): # subsequent builds will be isolated by first = True - # Packages that generate -py3-none-any wheels only need to be built on a single platform. - if package_name_or_recipe in py_any_targets: - build_platforms = platforms[:1] - else: - build_platforms = platforms + build_platforms = platforms # Build the package for each required platform. for sdk, sdk_version, arch in build_platforms: diff --git a/src/forge/build.py b/src/forge/build.py index d5a025b1..7dbcea63 100644 --- a/src/forge/build.py +++ b/src/forge/build.py @@ -8,7 +8,7 @@ import tarfile import zipfile from abc import ABC, abstractmethod, abstractproperty -from email import generator, message +from email import generator, message, parser from pathlib import Path from typing import TYPE_CHECKING @@ -257,7 +257,6 @@ def compile_env(self, **kwargs) -> dict[str, str]: cflags += f" -I{install_root}/include" if self.cross_venv.sdk != "android": - # Pre Python 3.11 versions included BZip2 and XZ includes in CFLAGS. Remove them. cflags = re.sub(r"-I.*/merge/iOS/.*/bzip2-.*/include", "", cflags) cflags = re.sub(r"-I.*/merge/iOS/.*/xs-.*/include", "", cflags) @@ -287,7 +286,6 @@ def compile_env(self, **kwargs) -> dict[str, str]: cargo_ldflags += " -C link-arg=-undefined -C link-arg=dynamic_lookup" if self.cross_venv.sdk != "android": - # Replace any hard-coded reference to -isysroot with the actual reference ldflags = re.sub( r"-isysroot \w+", f"-isysroot={self.cross_venv.sdk_root}", ldflags @@ -342,6 +340,7 @@ def compile_env(self, **kwargs) -> dict[str, str]: cc_parts = cc.split("/") env["NDK_ROOT"] = "/".join(cc_parts[: cc_parts.index("toolchains")]) env["ANDROID_ABI"] = self.cross_venv.arch + env["HOST_TRIPLET"] = self.cross_venv.platform_triplet # Add in some user environment keys that are useful for key in [ @@ -398,6 +397,46 @@ def _build(self): """Build the package.""" ... + def read_message_file(self, filename: Path): + return parser.Parser().parse(filename.open("r")) + + def write_message_file(self, filename: Path, data): + msg = message.Message() + for key, value in data.items(): + msg[key] = value + + # I don't know whether maxheaderlen is required, but it's used by bdist_wheel. + with filename.open("w", encoding="utf-8") as f: + generator.Generator(f, maxheaderlen=0).flatten(msg) + + def fix_wheel(self, wheel_dir: Path): + if self.cross_venv.sdk != "android": + return + + log(self.log_file, f"[{self.cross_venv}] Fixing wheel contents") + env = self.compile_env() + + for so in wheel_dir.glob("**/*.so"): + log(self.log_file, f"[{self.cross_venv}] Stripping {so}") + self.cross_venv.run( + self.log_file, + [env["STRIP"], "--strip-unneeded", str(so)], + ) + + # add missing requirements from "host" + if len(self.package.meta["requirements"]["host"]): + metadata_path = next(wheel_dir.glob("*.dist-info")) / "METADATA" + metadata = self.read_message_file(metadata_path) + for req in self.package.meta["requirements"]["host"]: + if req.startswith("flet-"): + log( + self.log_file, + f"[{self.cross_venv}] Adding {req} requirement to METADATA", + ) + req_name, req_ver = req.split(" ") + metadata["Requires-Dist"] = f"{req_name} (>={req_ver})" + self.write_message_file(metadata_path, metadata) + class SimplePackageBuilder(Builder): """A builder for projects that have a build.sh entry point.""" @@ -446,20 +485,13 @@ def prepare(self, clean=True): log(self.log_file, f"\n[{self.cross_venv}] Installing wheel-building tools") self.cross_venv.pip_install(self.log_file, ["wheel"], build=True) - def write_message_file(self, filename, data): - msg = message.Message() - for key, value in data.items(): - msg[key] = value - - # I don't know whether maxheaderlen is required, but it's used by bdist_wheel. - with filename.open("w", encoding="utf-8") as f: - generator.Generator(f, maxheaderlen=0).flatten(msg) - def make_wheel(self): build_num = str(self.package.meta["build"]["number"]) name = canonicalize_name(self.package.name) version = canonicalize_version(self.package.version) - info_path = self.build_path / "wheel" / f"{name}-{version}.dist-info" + info_path = ( + self.build_path / "wheel" / f"{name.replace('-', '_')}-{version}.dist-info" + ) log(self.log_file, f"\n[{self.cross_venv}] Writing wheel metadata") info_path.mkdir(exist_ok=True) @@ -486,6 +518,9 @@ def make_wheel(self): }, ) + # fix wheel before packaging + self.fix_wheel(self.build_path / "wheel") + # Re-pack the wheel file log(self.log_file, f"\n[{self.cross_venv}] Packing wheel") self.cross_venv.run( @@ -513,6 +548,7 @@ def compile(self): env=self.compile_env( **{ "HOST_TRIPLET": self.cross_venv.platform_triplet, + "HOST_ARCH": self.cross_venv.arch, "BUILD_TRIPLET": f"{os.uname().machine}-apple-darwin", "CPU_COUNT": str(multiprocessing.cpu_count()), "PREFIX": str(self.build_path / "wheel" / "opt"), @@ -675,7 +711,6 @@ def _create_meson_cross(self, env: dict[str, str]): return meson_cross def _build(self): - env = self.compile_env() script_vars = { @@ -715,6 +750,12 @@ def _build(self): else [] ) + # build wheel to a temp dir + tmp_dist = self.build_path / "tmp_dist" + if tmp_dist.exists(): + shutil.rmtree(tmp_dist) + tmp_dist.mkdir(parents=True, exist_ok=True) + self.cross_venv.run( self.log_file, [ @@ -724,9 +765,55 @@ def _build(self): "--no-isolation", "--wheel", "--outdir", - str(Path.cwd() / "dist"), + str(tmp_dist), ] + backend_args, cwd=self.build_path, env=env, ) + tmp_wheel = next(tmp_dist.glob("*.whl")) + + # unpack wheel to a temp directory + tmp_wheel_dir = self.build_path / "tmp_wheel" + if tmp_wheel_dir.exists(): + shutil.rmtree(tmp_wheel_dir) + tmp_wheel_dir.mkdir(parents=True, exist_ok=True) + + log(self.log_file, f"\n[{self.cross_venv}] Unpacking wheel to temp directory") + self.cross_venv.run( + self.log_file, + [ + "build-python", + "-m", + "wheel", + "unpack", + "--dest", + str(tmp_wheel_dir), + str(tmp_wheel), + ], + ) + + tmp_wheel_dir = next(tmp_wheel_dir.iterdir()) + + # fix wheel + self.fix_wheel(tmp_wheel_dir) + + # re-pack the wheel to "dist" + log(self.log_file, f"\n[{self.cross_venv}] Packing wheel to dist") + pack_args = [ + "build-python", + "-m", + "wheel", + "pack", + str(tmp_wheel_dir), + "--dest-dir", + str(Path.cwd() / "dist"), + ] + if self.package.meta["build"]["number"]: + pack_args.extend( + ["--build-number", str(self.package.meta["build"]["number"])] + ) + self.cross_venv.run( + self.log_file, + pack_args, + ) diff --git a/src/forge/package.py b/src/forge/package.py index 9e56aa6e..c3200111 100644 --- a/src/forge/package.py +++ b/src/forge/package.py @@ -17,7 +17,7 @@ def __init__( self, package_name_or_recipe: str, version: str | None, - build_number: str | None, + build_number: int | None, sdk: str, sdk_version: str, arch: str, @@ -113,7 +113,7 @@ def builder(self, cross_venv: CrossVEnv) -> Builder: :param cross_venv: The cross-platform environment to use for the build :returns: A builder for the package. """ - if self.meta["source"] == "pypi": - return PythonPackageBuilder(cross_venv=cross_venv, package=self) - else: + if (self.recipe_path / "build.sh").exists(): return SimplePackageBuilder(cross_venv=cross_venv, package=self) + else: + return PythonPackageBuilder(cross_venv=cross_venv, package=self) From 47cfc11d5f69d27d19a7a126d79106360e8758af Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Tue, 29 Oct 2024 14:07:30 -0700 Subject: [PATCH 029/142] Re-build all packages for iOS and Android --- .appveyor.yml | 248 +++++++++++++++++------------------ recipes/kiwisolver/meta.yaml | 4 +- recipes/pandas/meta.yaml | 2 + 3 files changed, 129 insertions(+), 125 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index d2d519bb..c654fe53 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -16,13 +16,13 @@ environment: secure: trYGM65OQ1+HYnOYOe/NOHrofLpP3bz64nHwVWPJhiUIYll3MrrQd7ilFNp+zSkI matrix: - - job_name: 'Android: kiwisolver' - job_group: build_android - FORGE_ARCH: android - FORGE_PACKAGES: >- - flet-libcpp-shared:27.2.12479018 - kiwisolver:1.4.7 - BUILD_NUMBER: 1 + # - job_name: 'Android: kiwisolver' + # job_group: build_android + # FORGE_ARCH: android + # FORGE_PACKAGES: >- + # flet-libcpp-shared:27.2.12479018 + # kiwisolver:1.4.7 + # BUILD_NUMBER: 1 # - job_name: 'iOS: flet-libjpeg' # job_group: build_ios @@ -32,135 +32,135 @@ environment: # ================================================== - # - job_name: 'Android arm64-v8a: opencv-python' - # job_group: build_android - # FORGE_ARCH: 'android:arm64-v8a' - # FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 - # BUILD_NUMBER: 1 + - job_name: 'Android arm64-v8a: opencv-python' + job_group: build_android + FORGE_ARCH: 'android:arm64-v8a' + FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 + BUILD_NUMBER: 1 - # - job_name: 'Android armeabi-v7a: opencv-python' - # job_group: build_android - # FORGE_ARCH: 'android:armeabi-v7a' - # FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 - # BUILD_NUMBER: 1 + - job_name: 'Android armeabi-v7a: opencv-python' + job_group: build_android + FORGE_ARCH: 'android:armeabi-v7a' + FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 + BUILD_NUMBER: 1 - # - job_name: 'Android x86_64: opencv-python' - # job_group: build_android - # FORGE_ARCH: 'android:x86_64' - # FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 - # BUILD_NUMBER: 1 + - job_name: 'Android x86_64: opencv-python' + job_group: build_android + FORGE_ARCH: 'android:x86_64' + FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 + BUILD_NUMBER: 1 - # - job_name: 'Android x86: opencv-python' - # job_group: build_android - # FORGE_ARCH: 'android:x86' - # FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 - # BUILD_NUMBER: 1 + - job_name: 'Android x86: opencv-python' + job_group: build_android + FORGE_ARCH: 'android:x86' + FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 + BUILD_NUMBER: 1 - # - job_name: 'iOS iphone arm64: opencv-python' - # job_group: build_ios - # FORGE_ARCH: 'iphoneos:arm64' - # FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 - # BUILD_NUMBER: 1 + - job_name: 'iOS iphone arm64: opencv-python' + job_group: build_ios + FORGE_ARCH: 'iphoneos:arm64' + FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 + BUILD_NUMBER: 1 - # - job_name: 'iOS simulator arm64: opencv-python' - # job_group: build_ios - # FORGE_ARCH: 'iphonesimulator:arm64' - # FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 - # BUILD_NUMBER: 1 + - job_name: 'iOS simulator arm64: opencv-python' + job_group: build_ios + FORGE_ARCH: 'iphonesimulator:arm64' + FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 + BUILD_NUMBER: 1 - # - job_name: 'iOS simulator x86_64: opencv-python' - # job_group: build_ios - # FORGE_ARCH: 'iphonesimulator:x86_64' - # FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 - # BUILD_NUMBER: 1 + - job_name: 'iOS simulator x86_64: opencv-python' + job_group: build_ios + FORGE_ARCH: 'iphonesimulator:x86_64' + FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 + BUILD_NUMBER: 1 - # - job_name: 'Android: pydantic-core, pillow, lru-dict, contourpy, kiwisolver, aiohttp, bitarray, argon2-cffi-binding, bcrypt, cryptography, brotli, websockets' - # job_group: build_android - # FORGE_ARCH: android - # FORGE_PACKAGES: >- - # cffi:1.17.1 - # flet-libcpp-shared:27.2.12479018 - # flet-libjpeg:3.0.90 - # flet-libpng:1.6.43 - # flet-freetype:2.13.3 - # pillow:10.4.0 - # lru-dict:1.3.0 - # yarl:1.11.1 - # contourpy:1.3.0 - # kiwisolver:1.4.7 - # aiohttp:3.9.5 - # bitarray:2.9.2 - # argon2-cffi-bindings:21.2.0 - # bcrypt:4.2.0 - # cryptography:43.0.1 - # brotli:1.1.0 - # pydantic-core:2.23.3 - # websockets:13.0.1 - # time-machine:2.16.0 - # markupsafe:2.1.5 - # BUILD_NUMBER: 1 + - job_name: 'Android: pydantic-core, pillow, lru-dict, contourpy, kiwisolver, aiohttp, bitarray, argon2-cffi-binding, bcrypt, cryptography, brotli, websockets' + job_group: build_android + FORGE_ARCH: android + FORGE_PACKAGES: >- + cffi:1.17.1 + flet-libcpp-shared:27.2.12479018 + flet-libjpeg:3.0.90 + flet-libpng:1.6.43 + flet-freetype:2.13.3 + pillow:10.4.0 + lru-dict:1.3.0 + yarl:1.11.1 + contourpy:1.3.0 + kiwisolver:1.4.7 + aiohttp:3.9.5 + bitarray:2.9.2 + argon2-cffi-bindings:21.2.0 + bcrypt:4.2.0 + cryptography:43.0.1 + brotli:1.1.0 + pydantic-core:2.23.3 + websockets:13.0.1 + time-machine:2.16.0 + markupsafe:2.1.5 + BUILD_NUMBER: 1 - # - job_name: 'Android: numpy, matplotlib, pandas, blis' - # job_group: build_android - # FORGE_ARCH: android - # FORGE_PACKAGES: >- - # flet-libcpp-shared:27.2.12479018 - # numpy:1.26.4 - # numpy:2.1.1 - # flet-libjpeg:3.0.90 - # matplotlib:3.9.2 - # pandas:2.2.2 - # blis:1.0.0 - # BUILD_NUMBER: 1 + - job_name: 'Android: numpy, matplotlib, pandas, blis' + job_group: build_android + FORGE_ARCH: android + FORGE_PACKAGES: >- + flet-libcpp-shared:27.2.12479018 + numpy:1.26.4 + numpy:2.1.1 + flet-libjpeg:3.0.90 + matplotlib:3.9.2 + pandas:2.2.2 + blis:1.0.0 + BUILD_NUMBER: 1 - # - job_name: 'iOS: pillow, lru-dict, yarl, contourpy, kiwisolver, aiohttp, bitarray, websockets' - # job_group: build_ios - # FORGE_ARCH: iOS - # FORGE_PACKAGES: >- - # flet-libjpeg:3.0.90 - # flet-libpng:1.6.43 - # flet-freetype:2.13.3 - # pillow:10.4.0 - # lru-dict:1.3.0 - # yarl:1.11.1 - # contourpy:1.3.0 - # kiwisolver:1.4.7 - # aiohttp:3.9.5 - # bitarray:2.9.2 - # websockets:13.0.1 - # time-machine:2.16.0 - # markupsafe:2.1.5 - # BUILD_NUMBER: 1 + - job_name: 'iOS: pillow, lru-dict, yarl, contourpy, kiwisolver, aiohttp, bitarray, websockets' + job_group: build_ios + FORGE_ARCH: iOS + FORGE_PACKAGES: >- + flet-libjpeg:3.0.90 + flet-libpng:1.6.43 + flet-freetype:2.13.3 + pillow:10.4.0 + lru-dict:1.3.0 + yarl:1.11.1 + contourpy:1.3.0 + kiwisolver:1.4.7 + aiohttp:3.9.5 + bitarray:2.9.2 + websockets:13.0.1 + time-machine:2.16.0 + markupsafe:2.1.5 + BUILD_NUMBER: 1 - # - job_name: 'iOS: cffi, argon2-cffi-bindings, bcrypt, cryptography, brotli' - # job_group: build_ios - # FORGE_ARCH: iOS - # FORGE_PACKAGES: >- - # cffi:1.17.1 - # argon2-cffi-bindings:21.2.0 - # bcrypt:4.2.0 - # cryptography:43.0.1 - # brotli:1.1.0 - # BUILD_NUMBER: 1 + - job_name: 'iOS: cffi, argon2-cffi-bindings, bcrypt, cryptography, brotli' + job_group: build_ios + FORGE_ARCH: iOS + FORGE_PACKAGES: >- + cffi:1.17.1 + argon2-cffi-bindings:21.2.0 + bcrypt:4.2.0 + cryptography:43.0.1 + brotli:1.1.0 + BUILD_NUMBER: 1 - # - job_name: 'iOS: pydantic-core' - # job_group: build_ios - # FORGE_ARCH: iOS - # FORGE_PACKAGES: >- - # pydantic-core:2.23.3 - # BUILD_NUMBER: 1 + - job_name: 'iOS: pydantic-core' + job_group: build_ios + FORGE_ARCH: iOS + FORGE_PACKAGES: >- + pydantic-core:2.23.3 + BUILD_NUMBER: 1 - # - job_name: 'iOS: numpy, matplotlib, pandas, blis' - # job_group: build_ios - # FORGE_ARCH: iOS - # FORGE_PACKAGES: >- - # numpy:1.26.4 - # numpy:2.1.1 - # flet-libjpeg:3.0.90 - # matplotlib:3.9.2 - # pandas:2.2.2 - # blis:1.0.0 - # BUILD_NUMBER: 1 + - job_name: 'iOS: numpy, matplotlib, pandas, blis' + job_group: build_ios + FORGE_ARCH: iOS + FORGE_PACKAGES: >- + numpy:1.26.4 + numpy:2.1.1 + flet-libjpeg:3.0.90 + matplotlib:3.9.2 + pandas:2.2.2 + blis:1.0.0 + BUILD_NUMBER: 1 # - job_name: Re-build Simple index # job_group: rebuild_index diff --git a/recipes/kiwisolver/meta.yaml b/recipes/kiwisolver/meta.yaml index ef5fb92c..482075ca 100644 --- a/recipes/kiwisolver/meta.yaml +++ b/recipes/kiwisolver/meta.yaml @@ -2,6 +2,8 @@ package: name: kiwisolver version: 1.4.7 +# {% if sdk == 'android' %} requirements: host: - - flet-libcpp-shared 27.2.12479018 \ No newline at end of file + - flet-libcpp-shared 27.2.12479018 +# {% endif %} \ No newline at end of file diff --git a/recipes/pandas/meta.yaml b/recipes/pandas/meta.yaml index e06f7153..1cf6b707 100644 --- a/recipes/pandas/meta.yaml +++ b/recipes/pandas/meta.yaml @@ -7,7 +7,9 @@ requirements: - ninja host: - numpy ^2.0.0 +# {% if sdk == 'android' %} - flet-libcpp-shared 27.2.12479018 +# {% endif %} patches: - mobile.patch From 4e5338a7c7282a3ae2359d6a0e011dbcf142d058 Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Tue, 5 Nov 2024 12:25:20 -0800 Subject: [PATCH 030/142] Add flet-libcpp-shared to contourpy deps --- .appveyor.yml | 248 ++++++++++++++++++------------------ recipes/contourpy/meta.yaml | 1 + 2 files changed, 125 insertions(+), 124 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index c654fe53..e7c94e79 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -16,13 +16,13 @@ environment: secure: trYGM65OQ1+HYnOYOe/NOHrofLpP3bz64nHwVWPJhiUIYll3MrrQd7ilFNp+zSkI matrix: - # - job_name: 'Android: kiwisolver' - # job_group: build_android - # FORGE_ARCH: android - # FORGE_PACKAGES: >- - # flet-libcpp-shared:27.2.12479018 - # kiwisolver:1.4.7 - # BUILD_NUMBER: 1 + - job_name: 'Android: contourpy' + job_group: build_android + FORGE_ARCH: android + FORGE_PACKAGES: >- + flet-libcpp-shared:27.2.12479018 + contourpy:1.3.0 + BUILD_NUMBER: 1 # - job_name: 'iOS: flet-libjpeg' # job_group: build_ios @@ -32,135 +32,135 @@ environment: # ================================================== - - job_name: 'Android arm64-v8a: opencv-python' - job_group: build_android - FORGE_ARCH: 'android:arm64-v8a' - FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 - BUILD_NUMBER: 1 + # - job_name: 'Android arm64-v8a: opencv-python' + # job_group: build_android + # FORGE_ARCH: 'android:arm64-v8a' + # FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 + # BUILD_NUMBER: 1 - - job_name: 'Android armeabi-v7a: opencv-python' - job_group: build_android - FORGE_ARCH: 'android:armeabi-v7a' - FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 - BUILD_NUMBER: 1 + # - job_name: 'Android armeabi-v7a: opencv-python' + # job_group: build_android + # FORGE_ARCH: 'android:armeabi-v7a' + # FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 + # BUILD_NUMBER: 1 - - job_name: 'Android x86_64: opencv-python' - job_group: build_android - FORGE_ARCH: 'android:x86_64' - FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 - BUILD_NUMBER: 1 + # - job_name: 'Android x86_64: opencv-python' + # job_group: build_android + # FORGE_ARCH: 'android:x86_64' + # FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 + # BUILD_NUMBER: 1 - - job_name: 'Android x86: opencv-python' - job_group: build_android - FORGE_ARCH: 'android:x86' - FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 - BUILD_NUMBER: 1 + # - job_name: 'Android x86: opencv-python' + # job_group: build_android + # FORGE_ARCH: 'android:x86' + # FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 + # BUILD_NUMBER: 1 - - job_name: 'iOS iphone arm64: opencv-python' - job_group: build_ios - FORGE_ARCH: 'iphoneos:arm64' - FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 - BUILD_NUMBER: 1 + # - job_name: 'iOS iphone arm64: opencv-python' + # job_group: build_ios + # FORGE_ARCH: 'iphoneos:arm64' + # FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 + # BUILD_NUMBER: 1 - - job_name: 'iOS simulator arm64: opencv-python' - job_group: build_ios - FORGE_ARCH: 'iphonesimulator:arm64' - FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 - BUILD_NUMBER: 1 + # - job_name: 'iOS simulator arm64: opencv-python' + # job_group: build_ios + # FORGE_ARCH: 'iphonesimulator:arm64' + # FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 + # BUILD_NUMBER: 1 - - job_name: 'iOS simulator x86_64: opencv-python' - job_group: build_ios - FORGE_ARCH: 'iphonesimulator:x86_64' - FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 - BUILD_NUMBER: 1 + # - job_name: 'iOS simulator x86_64: opencv-python' + # job_group: build_ios + # FORGE_ARCH: 'iphonesimulator:x86_64' + # FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 + # BUILD_NUMBER: 1 - - job_name: 'Android: pydantic-core, pillow, lru-dict, contourpy, kiwisolver, aiohttp, bitarray, argon2-cffi-binding, bcrypt, cryptography, brotli, websockets' - job_group: build_android - FORGE_ARCH: android - FORGE_PACKAGES: >- - cffi:1.17.1 - flet-libcpp-shared:27.2.12479018 - flet-libjpeg:3.0.90 - flet-libpng:1.6.43 - flet-freetype:2.13.3 - pillow:10.4.0 - lru-dict:1.3.0 - yarl:1.11.1 - contourpy:1.3.0 - kiwisolver:1.4.7 - aiohttp:3.9.5 - bitarray:2.9.2 - argon2-cffi-bindings:21.2.0 - bcrypt:4.2.0 - cryptography:43.0.1 - brotli:1.1.0 - pydantic-core:2.23.3 - websockets:13.0.1 - time-machine:2.16.0 - markupsafe:2.1.5 - BUILD_NUMBER: 1 + # - job_name: 'Android: pydantic-core, pillow, lru-dict, contourpy, kiwisolver, aiohttp, bitarray, argon2-cffi-binding, bcrypt, cryptography, brotli, websockets' + # job_group: build_android + # FORGE_ARCH: android + # FORGE_PACKAGES: >- + # cffi:1.17.1 + # flet-libcpp-shared:27.2.12479018 + # flet-libjpeg:3.0.90 + # flet-libpng:1.6.43 + # flet-freetype:2.13.3 + # pillow:10.4.0 + # lru-dict:1.3.0 + # yarl:1.11.1 + # contourpy:1.3.0 + # kiwisolver:1.4.7 + # aiohttp:3.9.5 + # bitarray:2.9.2 + # argon2-cffi-bindings:21.2.0 + # bcrypt:4.2.0 + # cryptography:43.0.1 + # brotli:1.1.0 + # pydantic-core:2.23.3 + # websockets:13.0.1 + # time-machine:2.16.0 + # markupsafe:2.1.5 + # BUILD_NUMBER: 1 - - job_name: 'Android: numpy, matplotlib, pandas, blis' - job_group: build_android - FORGE_ARCH: android - FORGE_PACKAGES: >- - flet-libcpp-shared:27.2.12479018 - numpy:1.26.4 - numpy:2.1.1 - flet-libjpeg:3.0.90 - matplotlib:3.9.2 - pandas:2.2.2 - blis:1.0.0 - BUILD_NUMBER: 1 + # - job_name: 'Android: numpy, matplotlib, pandas, blis' + # job_group: build_android + # FORGE_ARCH: android + # FORGE_PACKAGES: >- + # flet-libcpp-shared:27.2.12479018 + # numpy:1.26.4 + # numpy:2.1.1 + # flet-libjpeg:3.0.90 + # matplotlib:3.9.2 + # pandas:2.2.2 + # blis:1.0.0 + # BUILD_NUMBER: 1 - - job_name: 'iOS: pillow, lru-dict, yarl, contourpy, kiwisolver, aiohttp, bitarray, websockets' - job_group: build_ios - FORGE_ARCH: iOS - FORGE_PACKAGES: >- - flet-libjpeg:3.0.90 - flet-libpng:1.6.43 - flet-freetype:2.13.3 - pillow:10.4.0 - lru-dict:1.3.0 - yarl:1.11.1 - contourpy:1.3.0 - kiwisolver:1.4.7 - aiohttp:3.9.5 - bitarray:2.9.2 - websockets:13.0.1 - time-machine:2.16.0 - markupsafe:2.1.5 - BUILD_NUMBER: 1 + # - job_name: 'iOS: pillow, lru-dict, yarl, contourpy, kiwisolver, aiohttp, bitarray, websockets' + # job_group: build_ios + # FORGE_ARCH: iOS + # FORGE_PACKAGES: >- + # flet-libjpeg:3.0.90 + # flet-libpng:1.6.43 + # flet-freetype:2.13.3 + # pillow:10.4.0 + # lru-dict:1.3.0 + # yarl:1.11.1 + # contourpy:1.3.0 + # kiwisolver:1.4.7 + # aiohttp:3.9.5 + # bitarray:2.9.2 + # websockets:13.0.1 + # time-machine:2.16.0 + # markupsafe:2.1.5 + # BUILD_NUMBER: 1 - - job_name: 'iOS: cffi, argon2-cffi-bindings, bcrypt, cryptography, brotli' - job_group: build_ios - FORGE_ARCH: iOS - FORGE_PACKAGES: >- - cffi:1.17.1 - argon2-cffi-bindings:21.2.0 - bcrypt:4.2.0 - cryptography:43.0.1 - brotli:1.1.0 - BUILD_NUMBER: 1 + # - job_name: 'iOS: cffi, argon2-cffi-bindings, bcrypt, cryptography, brotli' + # job_group: build_ios + # FORGE_ARCH: iOS + # FORGE_PACKAGES: >- + # cffi:1.17.1 + # argon2-cffi-bindings:21.2.0 + # bcrypt:4.2.0 + # cryptography:43.0.1 + # brotli:1.1.0 + # BUILD_NUMBER: 1 - - job_name: 'iOS: pydantic-core' - job_group: build_ios - FORGE_ARCH: iOS - FORGE_PACKAGES: >- - pydantic-core:2.23.3 - BUILD_NUMBER: 1 + # - job_name: 'iOS: pydantic-core' + # job_group: build_ios + # FORGE_ARCH: iOS + # FORGE_PACKAGES: >- + # pydantic-core:2.23.3 + # BUILD_NUMBER: 1 - - job_name: 'iOS: numpy, matplotlib, pandas, blis' - job_group: build_ios - FORGE_ARCH: iOS - FORGE_PACKAGES: >- - numpy:1.26.4 - numpy:2.1.1 - flet-libjpeg:3.0.90 - matplotlib:3.9.2 - pandas:2.2.2 - blis:1.0.0 - BUILD_NUMBER: 1 + # - job_name: 'iOS: numpy, matplotlib, pandas, blis' + # job_group: build_ios + # FORGE_ARCH: iOS + # FORGE_PACKAGES: >- + # numpy:1.26.4 + # numpy:2.1.1 + # flet-libjpeg:3.0.90 + # matplotlib:3.9.2 + # pandas:2.2.2 + # blis:1.0.0 + # BUILD_NUMBER: 1 # - job_name: Re-build Simple index # job_group: rebuild_index diff --git a/recipes/contourpy/meta.yaml b/recipes/contourpy/meta.yaml index 4ad619ad..456a7c34 100644 --- a/recipes/contourpy/meta.yaml +++ b/recipes/contourpy/meta.yaml @@ -8,6 +8,7 @@ requirements: - cmake host: - pybind11 + - flet-libcpp-shared 27.2.12479018 build: backend-args: From c5b4c32e22c26634f0c80cf096386d00e2099fb6 Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Tue, 5 Nov 2024 12:29:03 -0800 Subject: [PATCH 031/142] Build contourpy for iOS --- .appveyor.yml | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index e7c94e79..a0d63546 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -16,20 +16,21 @@ environment: secure: trYGM65OQ1+HYnOYOe/NOHrofLpP3bz64nHwVWPJhiUIYll3MrrQd7ilFNp+zSkI matrix: - - job_name: 'Android: contourpy' - job_group: build_android - FORGE_ARCH: android + # - job_name: 'Android: contourpy' + # job_group: build_android + # FORGE_ARCH: android + # FORGE_PACKAGES: >- + # flet-libcpp-shared:27.2.12479018 + # contourpy:1.3.0 + # BUILD_NUMBER: 1 + + - job_name: 'iOS: contourpy' + job_group: build_ios + FORGE_ARCH: iOS FORGE_PACKAGES: >- - flet-libcpp-shared:27.2.12479018 - contourpy:1.3.0 + contourpy BUILD_NUMBER: 1 - # - job_name: 'iOS: flet-libjpeg' - # job_group: build_ios - # FORGE_ARCH: iOS - # FORGE_PACKAGES: >- - # flet-libjpeg - # ================================================== # - job_name: 'Android arm64-v8a: opencv-python' From fe4ede3eee8d2ee68b6df34770bea0e56c4c3826 Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Tue, 5 Nov 2024 12:34:40 -0800 Subject: [PATCH 032/142] Re-build contourpy for iOS --- .appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.appveyor.yml b/.appveyor.yml index a0d63546..5446a716 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -28,7 +28,7 @@ environment: job_group: build_ios FORGE_ARCH: iOS FORGE_PACKAGES: >- - contourpy + contourpy:1.3.0 BUILD_NUMBER: 1 # ================================================== From b7089a506d30b9c5eac46e522d18cb762fe43a42 Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Tue, 5 Nov 2024 12:39:30 -0800 Subject: [PATCH 033/142] Re-build contourpy for iOS, again --- .appveyor.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.appveyor.yml b/.appveyor.yml index 5446a716..cd4c5277 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -28,6 +28,7 @@ environment: job_group: build_ios FORGE_ARCH: iOS FORGE_PACKAGES: >- + flet-libcpp-shared:27.2.12479018 contourpy:1.3.0 BUILD_NUMBER: 1 From 4f3dc1a60606af3c0426bdc09ea561992daf142a Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Tue, 5 Nov 2024 12:45:09 -0800 Subject: [PATCH 034/142] contourpy: do not refer flet-libcpp-shared for iOS --- recipes/contourpy/meta.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/recipes/contourpy/meta.yaml b/recipes/contourpy/meta.yaml index 456a7c34..6c21d367 100644 --- a/recipes/contourpy/meta.yaml +++ b/recipes/contourpy/meta.yaml @@ -8,7 +8,9 @@ requirements: - cmake host: - pybind11 +# {% if sdk == 'android' %} - flet-libcpp-shared 27.2.12479018 +# {% endif %} build: backend-args: From a83cd39a3b26c72cf44f1e0160b1f65fc24564b3 Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Tue, 5 Nov 2024 12:50:14 -0800 Subject: [PATCH 035/142] Do not build flet-libcpp-shared for iOS --- .appveyor.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.appveyor.yml b/.appveyor.yml index cd4c5277..5446a716 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -28,7 +28,6 @@ environment: job_group: build_ios FORGE_ARCH: iOS FORGE_PACKAGES: >- - flet-libcpp-shared:27.2.12479018 contourpy:1.3.0 BUILD_NUMBER: 1 From 4da9f099a5a1dec4c3ac40e20fd1a8d4004a6b70 Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Wed, 6 Nov 2024 13:12:57 -0800 Subject: [PATCH 036/142] Fix libjpeg. Re-build pillow and matplotlib --- .appveyor.yml | 7 +++++-- recipes/flet-libjpeg/build.sh | 1 + 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index 5446a716..9cd9549b 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -24,11 +24,14 @@ environment: # contourpy:1.3.0 # BUILD_NUMBER: 1 - - job_name: 'iOS: contourpy' + - job_name: 'iOS: matplotlib, pillow' job_group: build_ios FORGE_ARCH: iOS FORGE_PACKAGES: >- - contourpy:1.3.0 + flet-libjpeg:3.0.90 + flet-freetype:2.13.3 + pillow:10.4.0 + matplotlib:3.9.2 BUILD_NUMBER: 1 # ================================================== diff --git a/recipes/flet-libjpeg/build.sh b/recipes/flet-libjpeg/build.sh index 37e50c19..ad561a1f 100755 --- a/recipes/flet-libjpeg/build.sh +++ b/recipes/flet-libjpeg/build.sh @@ -21,3 +21,4 @@ make install rm -r $PREFIX/{bin,share} rm -r $PREFIX/lib/{pkgconfig,cmake} +find "$PREFIX/lib/" -name "*.dylib" -exec rm -rf {} \; \ No newline at end of file From c21f8ada063776616d82868715a372a427352349 Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Wed, 6 Nov 2024 13:31:30 -0800 Subject: [PATCH 037/142] matplotlib requires numpy --- .appveyor.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.appveyor.yml b/.appveyor.yml index 9cd9549b..04db1a08 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -31,6 +31,7 @@ environment: flet-libjpeg:3.0.90 flet-freetype:2.13.3 pillow:10.4.0 + numpy:2.1.1 matplotlib:3.9.2 BUILD_NUMBER: 1 From 6a4c0f39a25d771f2d10aa91aacf09a13cdc6d64 Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Mon, 11 Nov 2024 08:19:55 -0800 Subject: [PATCH 038/142] Lxml (#11) * Android: flet-libxml2, flet-libxslt, lxml * iOS: lxml --- .appveyor.yml | 25 +++++------ recipes/flet-libxml2/build.sh | 12 +++++ recipes/flet-libxml2/meta.yaml | 9 ++++ recipes/flet-libxml2/patches/mobile.patch | 55 +++++++++++++++++++++++ recipes/flet-libxslt/build.sh | 14 ++++++ recipes/flet-libxslt/meta.yaml | 13 ++++++ recipes/flet-libxslt/patches/mobile.patch | 23 ++++++++++ recipes/lxml/meta.yaml | 16 +++++++ recipes/lxml/patches/mobile.patch | 30 +++++++++++++ recipes/lxml/test_lxml.py | 15 +++++++ src/forge/build.py | 1 + 11 files changed, 200 insertions(+), 13 deletions(-) create mode 100755 recipes/flet-libxml2/build.sh create mode 100755 recipes/flet-libxml2/meta.yaml create mode 100644 recipes/flet-libxml2/patches/mobile.patch create mode 100755 recipes/flet-libxslt/build.sh create mode 100755 recipes/flet-libxslt/meta.yaml create mode 100644 recipes/flet-libxslt/patches/mobile.patch create mode 100644 recipes/lxml/meta.yaml create mode 100644 recipes/lxml/patches/mobile.patch create mode 100644 recipes/lxml/test_lxml.py diff --git a/.appveyor.yml b/.appveyor.yml index 04db1a08..e257abc5 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -16,23 +16,22 @@ environment: secure: trYGM65OQ1+HYnOYOe/NOHrofLpP3bz64nHwVWPJhiUIYll3MrrQd7ilFNp+zSkI matrix: - # - job_name: 'Android: contourpy' - # job_group: build_android - # FORGE_ARCH: android - # FORGE_PACKAGES: >- - # flet-libcpp-shared:27.2.12479018 - # contourpy:1.3.0 - # BUILD_NUMBER: 1 + - job_name: 'Android: flet-libxml2, flet-libxslt, lxml' + job_group: build_android + FORGE_ARCH: android + FORGE_PACKAGES: >- + flet-libxml2:2.9.8 + flet-libxslt:1.1.32 + lxml:5.3.0 + BUILD_NUMBER: 1 - - job_name: 'iOS: matplotlib, pillow' + - job_name: 'iOS: flet-libxml2, flet-libxslt, lxml' job_group: build_ios FORGE_ARCH: iOS FORGE_PACKAGES: >- - flet-libjpeg:3.0.90 - flet-freetype:2.13.3 - pillow:10.4.0 - numpy:2.1.1 - matplotlib:3.9.2 + flet-libxml2:2.9.8 + flet-libxslt:1.1.32 + lxml:5.3.0 BUILD_NUMBER: 1 # ================================================== diff --git a/recipes/flet-libxml2/build.sh b/recipes/flet-libxml2/build.sh new file mode 100755 index 00000000..fd4f9f82 --- /dev/null +++ b/recipes/flet-libxml2/build.sh @@ -0,0 +1,12 @@ +#!/bin/bash +set -eu + +./configure --host=$HOST_TRIPLET --prefix=$PREFIX --without-python +make -j $CPU_COUNT +make install + +mv $PREFIX/include/libxml2/libxml $PREFIX/include +rm -r $PREFIX/include/libxml2 + +rm -r $PREFIX/share +rm -r $PREFIX/lib/{cmake,pkgconfig,*.a,*.la,*.sh} \ No newline at end of file diff --git a/recipes/flet-libxml2/meta.yaml b/recipes/flet-libxml2/meta.yaml new file mode 100755 index 00000000..6d9f7375 --- /dev/null +++ b/recipes/flet-libxml2/meta.yaml @@ -0,0 +1,9 @@ +package: + name: flet-libxml2 + version: 2.9.8 + +source: + url: http://xmlsoft.org/download/libxml2-2.9.8.tar.gz + +patches: + - mobile.patch \ No newline at end of file diff --git a/recipes/flet-libxml2/patches/mobile.patch b/recipes/flet-libxml2/patches/mobile.patch new file mode 100644 index 00000000..b4dd4a1b --- /dev/null +++ b/recipes/flet-libxml2/patches/mobile.patch @@ -0,0 +1,55 @@ +diff --git a/config.sub b/config.sub +index 7b334f9..cdb35e9 100755 +--- a/config.sub ++++ b/config.sub +@@ -355,6 +355,10 @@ case $basic_machine in + xscaleel) + basic_machine=armel-unknown + ;; ++ arm64-apple | *-ios) ++ basic_machine=$basic_machine-unknown ++ os=-none ++ ;; + + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and +diff --git a/libxml2.syms b/libxml2.syms +index 370dcf1..3c4a3dc 100644 +--- a/libxml2.syms ++++ b/libxml2.syms +@@ -453,16 +453,16 @@ LIBXML2_2.4.30 { + xmlNanoFTPUpdateURL; + + # DOCBparser +- docbCreateFileParserCtxt; +- docbCreatePushParserCtxt; +- docbEncodeEntities; +- docbFreeParserCtxt; +- docbParseChunk; +- docbParseDoc; +- docbParseDocument; +- docbParseFile; +- docbSAXParseDoc; +- docbSAXParseFile; ++# docbCreateFileParserCtxt; ++# docbCreatePushParserCtxt; ++# docbEncodeEntities; ++# docbFreeParserCtxt; ++# docbParseChunk; ++# docbParseDoc; ++# docbParseDocument; ++# docbParseFile; ++# docbSAXParseDoc; ++# docbSAXParseFile; + + # xpath + xmlXPathCastBooleanToNumber; +@@ -2187,7 +2187,7 @@ LIBXML2_2.6.29 { + global: + + # threads +- xmlDllMain; ++ # xmlDllMain; + } LIBXML2_2.6.28; + + LIBXML2_2.6.32 { diff --git a/recipes/flet-libxslt/build.sh b/recipes/flet-libxslt/build.sh new file mode 100755 index 00000000..5f8572d8 --- /dev/null +++ b/recipes/flet-libxslt/build.sh @@ -0,0 +1,14 @@ +#!/bin/bash +set -eu + +export CFLAGS="-Wno-error=incompatible-function-pointer-types" +export LIBS="-lxml2" + +./configure --host=$HOST_TRIPLET --prefix=$PREFIX --without-crypto --without-python \ + --with-libxml-include-prefix=$PLATLIB/opt/include \ + --with-libxml-libs-prefix=$PLATLIB/opt/lib +make -j $CPU_COUNT V=1 +make install + +rm -r $PREFIX/share +rm -r $PREFIX/lib/{libxslt-*,pkgconfig,*.a,*.la,*.sh} \ No newline at end of file diff --git a/recipes/flet-libxslt/meta.yaml b/recipes/flet-libxslt/meta.yaml new file mode 100755 index 00000000..1702c79d --- /dev/null +++ b/recipes/flet-libxslt/meta.yaml @@ -0,0 +1,13 @@ +package: + name: flet-libxslt + version: 1.1.32 + +source: + url: http://xmlsoft.org/download/libxslt-1.1.32.tar.gz + +requirements: + host: + - flet-libxml2 2.9.8 + +patches: + - mobile.patch \ No newline at end of file diff --git a/recipes/flet-libxslt/patches/mobile.patch b/recipes/flet-libxslt/patches/mobile.patch new file mode 100644 index 00000000..cdb9fe6b --- /dev/null +++ b/recipes/flet-libxslt/patches/mobile.patch @@ -0,0 +1,23 @@ +diff --git a/config.sub b/config.sub +index 7b334f9..a32642c 100755 +--- a/config.sub ++++ b/config.sub +@@ -316,7 +316,8 @@ case $basic_machine in + | visium \ + | we32k \ + | x86 | xc16x | xstormy16 | xtensa \ +- | z8k | z80) ++ | z8k | z80 \ ++ | arm64-apple | *-ios) + basic_machine=$basic_machine-unknown + ;; + c54x) +@@ -1539,7 +1540,7 @@ case $os in + ;; + -nacl*) + ;; +- -ios) ++ -ios | -simulator) + ;; + -none) + ;; diff --git a/recipes/lxml/meta.yaml b/recipes/lxml/meta.yaml new file mode 100644 index 00000000..ef28a048 --- /dev/null +++ b/recipes/lxml/meta.yaml @@ -0,0 +1,16 @@ +package: + name: lxml + version: 5.3.0 + +build: + script_env: + WITH_XML2_CONFIG: '{platlib}/opt/bin/xml2-config' + WITH_XSLT_CONFIG: '{platlib}/opt/bin/xslt-config' + +patches: + - mobile.patch + +requirements: + host: + - flet-libxslt 1.1.32 + - flet-libxml2 2.9.8 \ No newline at end of file diff --git a/recipes/lxml/patches/mobile.patch b/recipes/lxml/patches/mobile.patch new file mode 100644 index 00000000..171be5ba --- /dev/null +++ b/recipes/lxml/patches/mobile.patch @@ -0,0 +1,30 @@ +diff --git a/setupinfo.py b/setupinfo.py +index 97e3399..634183a 100644 +--- a/setupinfo.py ++++ b/setupinfo.py +@@ -1,12 +1,13 @@ +-import sys + import io + import os + import os.path + import subprocess +- +-from setuptools.command.build_ext import build_ext as _build_ext ++import sys + from distutils.core import Extension + from distutils.errors import CompileError, DistutilsOptionError ++ ++from setuptools.command.build_ext import build_ext as _build_ext ++ + from versioninfo import get_base_dir + + try: +@@ -330,7 +331,7 @@ def include_dirs(static_include_dirs): + result = [] + possible_include_dirs = flags('cflags') + for possible_include_dir in possible_include_dirs: +- if possible_include_dir.startswith('-I'): ++ if possible_include_dir.startswith('-I') and not possible_include_dir.endswith('/MacOSX.sdk/usr/include'): + result.append(possible_include_dir[2:]) + return result + diff --git a/recipes/lxml/test_lxml.py b/recipes/lxml/test_lxml.py new file mode 100644 index 00000000..ace631a2 --- /dev/null +++ b/recipes/lxml/test_lxml.py @@ -0,0 +1,15 @@ +import unittest + + +class TestLxml(unittest.TestCase): + + def test_basic(self): + from lxml import etree + + parent = etree.fromstring( + "" + ) + self.assertEqual("parent", parent.tag) + self.assertEqual(2, len(parent)) + self.assertEqual("one", parent[0].get("name")) + self.assertEqual("two", parent[1].get("name")) diff --git a/src/forge/build.py b/src/forge/build.py index 7dbcea63..adeeadde 100644 --- a/src/forge/build.py +++ b/src/forge/build.py @@ -552,6 +552,7 @@ def compile(self): "BUILD_TRIPLET": f"{os.uname().machine}-apple-darwin", "CPU_COUNT": str(multiprocessing.cpu_count()), "PREFIX": str(self.build_path / "wheel" / "opt"), + "PLATLIB": self.cross_venv.scheme_paths["platlib"], } ), ) From fe8c710f23f7cb755021bdc57c9a0f0798c9a288 Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Wed, 13 Nov 2024 14:57:15 -0800 Subject: [PATCH 039/142] Grpcio for iOS and Android (#12) * Grpcio for Android * grpcio for iOS --- .appveyor.yml | 21 +++++++--------- recipes/grpcio/meta.yaml | 26 +++++++++++++++++++ recipes/grpcio/patches/mobile.patch | 39 +++++++++++++++++++++++++++++ recipes/grpcio/test_grpcio.py | 1 + 4 files changed, 75 insertions(+), 12 deletions(-) create mode 100644 recipes/grpcio/meta.yaml create mode 100644 recipes/grpcio/patches/mobile.patch create mode 100644 recipes/grpcio/test_grpcio.py diff --git a/.appveyor.yml b/.appveyor.yml index e257abc5..db6cee53 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -16,22 +16,19 @@ environment: secure: trYGM65OQ1+HYnOYOe/NOHrofLpP3bz64nHwVWPJhiUIYll3MrrQd7ilFNp+zSkI matrix: - - job_name: 'Android: flet-libxml2, flet-libxslt, lxml' - job_group: build_android - FORGE_ARCH: android - FORGE_PACKAGES: >- - flet-libxml2:2.9.8 - flet-libxslt:1.1.32 - lxml:5.3.0 - BUILD_NUMBER: 1 + # - job_name: 'Android: grpcio' + # job_group: build_android + # FORGE_ARCH: android + # FORGE_PACKAGES: >- + # flet-libcpp-shared:27.2.12479018 + # grpcio:1.67.1 + # BUILD_NUMBER: 1 - - job_name: 'iOS: flet-libxml2, flet-libxslt, lxml' + - job_name: 'iOS: grpcio' job_group: build_ios FORGE_ARCH: iOS FORGE_PACKAGES: >- - flet-libxml2:2.9.8 - flet-libxslt:1.1.32 - lxml:5.3.0 + grpcio:1.67.1 BUILD_NUMBER: 1 # ================================================== diff --git a/recipes/grpcio/meta.yaml b/recipes/grpcio/meta.yaml new file mode 100644 index 00000000..aa6e54d9 --- /dev/null +++ b/recipes/grpcio/meta.yaml @@ -0,0 +1,26 @@ +package: + name: grpcio + version: 1.67.1 + +build: + script_env: +# {% if sdk == 'android' %} + GRPC_PYTHON_BUILD_SYSTEM_OPENSSL: '1' + GRPC_PYTHON_BUILD_SYSTEM_ZLIB: '1' + PLATFORM: android + CFLAGS: '-U__ANDROID_API__ -D__ANDROID_API__={{ sdk_version }} -Wno-reserved-user-defined-literal' + LDFLAGS: '-llog' +# {% else %} + CXXFLAGS: -std=c++14 -Wno-c++11-narrowing + LDFLAGS: '-framework CoreFoundation' +# {% endif %} + +patches: + - mobile.patch + +# {% if sdk == 'android' %} +requirements: + host: + - openssl 3.0.15 + - flet-libcpp-shared 27.2.12479018 +# {% endif %} \ No newline at end of file diff --git a/recipes/grpcio/patches/mobile.patch b/recipes/grpcio/patches/mobile.patch new file mode 100644 index 00000000..418c12a1 --- /dev/null +++ b/recipes/grpcio/patches/mobile.patch @@ -0,0 +1,39 @@ +diff --git a/setup.py b/setup.py +index 48bfefe..ff21bc5 100644 +--- a/setup.py ++++ b/setup.py +@@ -58,12 +58,14 @@ CARES_INCLUDE = ( + os.path.join("third_party", "cares"), + os.path.join("third_party", "cares", "cares"), + ) +-if "darwin" in sys.platform: ++if "darwin" in sys.platform or "ios" in sys.platform: + CARES_INCLUDE += (os.path.join("third_party", "cares", "config_darwin"),) + if "freebsd" in sys.platform: + CARES_INCLUDE += (os.path.join("third_party", "cares", "config_freebsd"),) + if "linux" in sys.platform: + CARES_INCLUDE += (os.path.join("third_party", "cares", "config_linux"),) ++if "android" in sys.platform: ++ CARES_INCLUDE += (os.path.join("third_party", "cares", "config_android"),) + if "openbsd" in sys.platform: + CARES_INCLUDE += (os.path.join("third_party", "cares", "config_openbsd"),) + RE2_INCLUDE = (os.path.join("third_party", "re2"),) +@@ -329,15 +331,16 @@ EXTENSION_INCLUDE_DIRECTORIES = ( + + ADDRESS_SORTING_INCLUDE + + CARES_INCLUDE + + RE2_INCLUDE +- + SSL_INCLUDE + + UPB_INCLUDE + + UPB_GRPC_GENERATED_INCLUDE + + UPBDEFS_GRPC_GENERATED_INCLUDE + + UTF8_RANGE_INCLUDE + + XXHASH_INCLUDE +- + ZLIB_INCLUDE + ) + ++if "android" not in sys.platform: ++ EXTENSION_INCLUDE_DIRECTORIES += SSL_INCLUDE + ZLIB_INCLUDE ++ + EXTENSION_LIBRARIES = () + if "linux" in sys.platform: + EXTENSION_LIBRARIES += ("rt",) diff --git a/recipes/grpcio/test_grpcio.py b/recipes/grpcio/test_grpcio.py new file mode 100644 index 00000000..6b81d9cd --- /dev/null +++ b/recipes/grpcio/test_grpcio.py @@ -0,0 +1 @@ +# TBD \ No newline at end of file From 73ae9f6e68130813bd994eb8a4e60974f1e62ba3 Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Mon, 25 Nov 2024 08:47:35 -0800 Subject: [PATCH 040/142] google-crc32c for iOS and Android (#13) --- .appveyor.yml | 19 ++++++++++--------- recipes/flet-crc32c/build.sh | 32 ++++++++++++++++++++++++++++++++ recipes/flet-crc32c/meta.yaml | 13 +++++++++++++ recipes/flet-libjpeg/build.sh | 2 +- recipes/google-crc32c/meta.yaml | 13 +++++++++++++ recipes/google-crc32c/test.py | 15 +++++++++++++++ src/forge/build.py | 2 ++ 7 files changed, 86 insertions(+), 10 deletions(-) create mode 100755 recipes/flet-crc32c/build.sh create mode 100644 recipes/flet-crc32c/meta.yaml create mode 100644 recipes/google-crc32c/meta.yaml create mode 100644 recipes/google-crc32c/test.py diff --git a/.appveyor.yml b/.appveyor.yml index db6cee53..795526c6 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -16,19 +16,20 @@ environment: secure: trYGM65OQ1+HYnOYOe/NOHrofLpP3bz64nHwVWPJhiUIYll3MrrQd7ilFNp+zSkI matrix: - # - job_name: 'Android: grpcio' - # job_group: build_android - # FORGE_ARCH: android - # FORGE_PACKAGES: >- - # flet-libcpp-shared:27.2.12479018 - # grpcio:1.67.1 - # BUILD_NUMBER: 1 + - job_name: 'Android: google-crc32c' + job_group: build_android + FORGE_ARCH: android + FORGE_PACKAGES: >- + flet-crc32c:1.1.2 + google-crc32c:1.6.0 + BUILD_NUMBER: 1 - - job_name: 'iOS: grpcio' + - job_name: 'iOS: google-crc32c' job_group: build_ios FORGE_ARCH: iOS FORGE_PACKAGES: >- - grpcio:1.67.1 + flet-crc32c:1.1.2 + google-crc32c:1.6.0 BUILD_NUMBER: 1 # ================================================== diff --git a/recipes/flet-crc32c/build.sh b/recipes/flet-crc32c/build.sh new file mode 100755 index 00000000..2767996e --- /dev/null +++ b/recipes/flet-crc32c/build.sh @@ -0,0 +1,32 @@ +#!/bin/bash +set -eu + +if [ $CROSS_VENV_SDK == "android" ]; then + cmake \ + -DCMAKE_SYSTEM_NAME=Android \ + -DANDROID_PLATFORM=$SDK_VERSION \ + -DANDROID_ABI=$ANDROID_ABI \ + -DCMAKE_TOOLCHAIN_FILE=$NDK_ROOT/build/cmake/android.toolchain.cmake \ + -DCRC32C_BUILD_TESTS=0 \ + -DCRC32C_BUILD_BENCHMARKS=0 \ + -DCRC32C_USE_GLOG=0 \ + -DCMAKE_BUILD_TYPE=Release \ + -DBUILD_SHARED_LIBS=1 \ + -DCMAKE_INSTALL_PREFIX="$PREFIX" +else + cmake \ + -DCMAKE_SYSTEM_NAME=iOS \ + -DCMAKE_OSX_SYSROOT=$SDK \ + -DCMAKE_OSX_ARCHITECTURES=$HOST_ARCH \ + -DCRC32C_BUILD_TESTS=0 \ + -DCRC32C_BUILD_BENCHMARKS=0 \ + -DCRC32C_USE_GLOG=0 \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_INSTALL_PREFIX=$PREFIX +fi + +make -j $CPU_COUNT +make install + +# cleanup +rm -r $PREFIX/lib/cmake \ No newline at end of file diff --git a/recipes/flet-crc32c/meta.yaml b/recipes/flet-crc32c/meta.yaml new file mode 100644 index 00000000..f477090c --- /dev/null +++ b/recipes/flet-crc32c/meta.yaml @@ -0,0 +1,13 @@ +package: + name: flet-crc32c + version: 1.1.2 + +build: + number: 1 + +source: + url: https://github.com/google/crc32c/archive/refs/tags/1.1.2.tar.gz + +requirements: + build: + - cmake \ No newline at end of file diff --git a/recipes/flet-libjpeg/build.sh b/recipes/flet-libjpeg/build.sh index ad561a1f..936a0add 100755 --- a/recipes/flet-libjpeg/build.sh +++ b/recipes/flet-libjpeg/build.sh @@ -5,7 +5,7 @@ set -eu if [ $CROSS_VENV_SDK == "android" ]; then cmake -G"Unix Makefiles" \ -DCMAKE_SYSTEM_NAME=Android \ - -DANDROID_PLATFORM=24 \ + -DANDROID_PLATFORM=$SDK_VERSION \ -DANDROID_ABI=$ANDROID_ABI \ -DCMAKE_TOOLCHAIN_FILE=$NDK_ROOT/build/cmake/android.toolchain.cmake \ -DCMAKE_INSTALL_PREFIX=$PREFIX . diff --git a/recipes/google-crc32c/meta.yaml b/recipes/google-crc32c/meta.yaml new file mode 100644 index 00000000..903bfa11 --- /dev/null +++ b/recipes/google-crc32c/meta.yaml @@ -0,0 +1,13 @@ +package: + name: google-crc32c + version: 1.6.0 + +requirements: + host: + - flet-crc32c 1.1.2 + +# {% if sdk != 'android' %} +build: + script_env: + LDFLAGS: '-lc++' +# {% endif %} \ No newline at end of file diff --git a/recipes/google-crc32c/test.py b/recipes/google-crc32c/test.py new file mode 100644 index 00000000..7e761bf6 --- /dev/null +++ b/recipes/google-crc32c/test.py @@ -0,0 +1,15 @@ +import unittest + + +class TestGoogleCrc32c(unittest.TestCase): + + # Based on https://github.com/googleapis/python-crc32c/blob/main/tests/test___init__.py + def test_basic(self): + import google_crc32c + + self.assertEqual("c", google_crc32c.implementation) + for data, expected in [(b"", 0x00000000), + (b"\x00" * 32, 0x8A9136AA), + (bytes(range(32)), 0x46DD794E)]: + with self.subTest(data=data): + self.assertEqual(expected, google_crc32c.value(data)) diff --git a/src/forge/build.py b/src/forge/build.py index adeeadde..25871390 100644 --- a/src/forge/build.py +++ b/src/forge/build.py @@ -549,6 +549,8 @@ def compile(self): **{ "HOST_TRIPLET": self.cross_venv.platform_triplet, "HOST_ARCH": self.cross_venv.arch, + "SDK": self.cross_venv.sdk, + "SDK_VERSION": self.cross_venv.sdk_version, "BUILD_TRIPLET": f"{os.uname().machine}-apple-darwin", "CPU_COUNT": str(multiprocessing.cpu_count()), "PREFIX": str(self.build_path / "wheel" / "opt"), From 96c97a57e267d63562d10defeaefa7eaf1e7a594 Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Mon, 25 Nov 2024 13:45:44 -0800 Subject: [PATCH 041/142] protobuf for iOS and Android (#14) * fiona package draft * protobuf for iOS and Android --- .appveyor.yml | 10 ++++------ recipes/fiona/meta.yaml | 3 +++ recipes/fiona/test_fiona.py | 1 + recipes/protobuf/meta.yaml | 3 +++ recipes/protobuf/test_protobuf.py | 1 + 5 files changed, 12 insertions(+), 6 deletions(-) create mode 100644 recipes/fiona/meta.yaml create mode 100644 recipes/fiona/test_fiona.py create mode 100644 recipes/protobuf/meta.yaml create mode 100644 recipes/protobuf/test_protobuf.py diff --git a/.appveyor.yml b/.appveyor.yml index 795526c6..199130ed 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -16,20 +16,18 @@ environment: secure: trYGM65OQ1+HYnOYOe/NOHrofLpP3bz64nHwVWPJhiUIYll3MrrQd7ilFNp+zSkI matrix: - - job_name: 'Android: google-crc32c' + - job_name: 'Android: protobuf' job_group: build_android FORGE_ARCH: android FORGE_PACKAGES: >- - flet-crc32c:1.1.2 - google-crc32c:1.6.0 + protobuf:5.28.3 BUILD_NUMBER: 1 - - job_name: 'iOS: google-crc32c' + - job_name: 'iOS: protobuf' job_group: build_ios FORGE_ARCH: iOS FORGE_PACKAGES: >- - flet-crc32c:1.1.2 - google-crc32c:1.6.0 + protobuf:5.28.3 BUILD_NUMBER: 1 # ================================================== diff --git a/recipes/fiona/meta.yaml b/recipes/fiona/meta.yaml new file mode 100644 index 00000000..2b8ea81c --- /dev/null +++ b/recipes/fiona/meta.yaml @@ -0,0 +1,3 @@ +package: + name: fiona + version: 1.10.1 diff --git a/recipes/fiona/test_fiona.py b/recipes/fiona/test_fiona.py new file mode 100644 index 00000000..6b81d9cd --- /dev/null +++ b/recipes/fiona/test_fiona.py @@ -0,0 +1 @@ +# TBD \ No newline at end of file diff --git a/recipes/protobuf/meta.yaml b/recipes/protobuf/meta.yaml new file mode 100644 index 00000000..1846a408 --- /dev/null +++ b/recipes/protobuf/meta.yaml @@ -0,0 +1,3 @@ +package: + name: protobuf + version: 5.28.3 diff --git a/recipes/protobuf/test_protobuf.py b/recipes/protobuf/test_protobuf.py new file mode 100644 index 00000000..6b81d9cd --- /dev/null +++ b/recipes/protobuf/test_protobuf.py @@ -0,0 +1 @@ +# TBD \ No newline at end of file From 36837f5071d1374acebf7308351d1bbec5ce5ffc Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Thu, 28 Nov 2024 08:52:25 -0800 Subject: [PATCH 042/142] shapely, fiona, pyogrio, GDAL, geopandas (#15) * flet-geos for iOS and Android * shapely for iOS and Android * Shapely for iOS and Android * flet-libcurl, flet-libpsl, flet-libtiff, flet-libproj for Android * flet-geos renamed to flet-libgeos * pyproj for iOS and Android * Trying to fix libpsl * libpsl - disable runtime * build flet-libjpeg for libtiff * Fix path to libsqlite3_python.so * install sqlite3, fix libcurl on iOS * Fix flet-libcurl for iOS * Build pyproj for iOS * flet-libgdal for Android * Fix flet-libtiff for iOS simulator * flet-libgdal, fiona for iOS and Android * pyogrio for iOS and Android * Fix libgdal, GDAL for iOS and Android * rebuild flet-libcrc32c, google-crc32c, flet-libfreetype, pillow * flet-libjpeg:3.0.90 required for pillow * Re-build flet-libgdal on Android * GDAL_USE_LIBXML2=OFF for Android --- .appveyor.yml | 38 +++++++--- recipes/fiona/meta.yaml | 17 +++++ recipes/fiona/patches/mobile.patch | 26 +++++++ .../{flet-crc32c => flet-libcrc32c}/build.sh | 0 .../{flet-crc32c => flet-libcrc32c}/meta.yaml | 2 +- recipes/flet-libcurl/build.sh | 13 ++++ recipes/flet-libcurl/meta.yaml | 19 +++++ recipes/flet-libcurl/patches/config.patch | 13 ++++ .../build.sh | 5 +- .../meta.yaml | 2 +- .../patches/config.patch | 0 recipes/flet-libgdal/build.sh | 57 ++++++++++++++ recipes/flet-libgdal/meta.yaml | 17 +++++ recipes/flet-libgeos/build.sh | 32 ++++++++ recipes/flet-libgeos/meta.yaml | 13 ++++ recipes/flet-libproj/build.sh | 40 ++++++++++ recipes/flet-libproj/meta.yaml | 24 ++++++ recipes/flet-libpsl/build.sh | 13 ++++ recipes/flet-libpsl/meta.yaml | 14 ++++ recipes/flet-libpsl/patches/config.patch | 13 ++++ recipes/flet-libtiff/build.sh | 13 ++++ recipes/flet-libtiff/meta.yaml | 18 +++++ recipes/flet-libtiff/patches/config.patch | 13 ++++ recipes/gdal/meta.yaml | 19 +++++ recipes/gdal/patches/config.patch | 14 ++++ recipes/gdal/test_gdal.py | 1 + recipes/google-crc32c/meta.yaml | 2 +- recipes/pillow/meta.yaml | 2 +- recipes/pyogrio/meta.yaml | 16 ++++ recipes/pyogrio/test_pyogrio.py | 1 + recipes/pyproj/meta.yaml | 18 +++++ recipes/pyproj/patches/mobile.patch | 15 ++++ recipes/shapely/meta.yaml | 11 +++ recipes/shapely/patches/mobile.patch | 75 +++++++++++++++++++ src/forge/build.py | 36 +++++---- 35 files changed, 582 insertions(+), 30 deletions(-) create mode 100644 recipes/fiona/patches/mobile.patch rename recipes/{flet-crc32c => flet-libcrc32c}/build.sh (100%) rename recipes/{flet-crc32c => flet-libcrc32c}/meta.yaml (87%) create mode 100755 recipes/flet-libcurl/build.sh create mode 100644 recipes/flet-libcurl/meta.yaml create mode 100644 recipes/flet-libcurl/patches/config.patch rename recipes/{flet-freetype => flet-libfreetype}/build.sh (87%) rename recipes/{flet-freetype => flet-libfreetype}/meta.yaml (88%) rename recipes/{flet-freetype => flet-libfreetype}/patches/config.patch (100%) create mode 100755 recipes/flet-libgdal/build.sh create mode 100644 recipes/flet-libgdal/meta.yaml create mode 100755 recipes/flet-libgeos/build.sh create mode 100644 recipes/flet-libgeos/meta.yaml create mode 100755 recipes/flet-libproj/build.sh create mode 100644 recipes/flet-libproj/meta.yaml create mode 100755 recipes/flet-libpsl/build.sh create mode 100644 recipes/flet-libpsl/meta.yaml create mode 100644 recipes/flet-libpsl/patches/config.patch create mode 100755 recipes/flet-libtiff/build.sh create mode 100644 recipes/flet-libtiff/meta.yaml create mode 100644 recipes/flet-libtiff/patches/config.patch create mode 100644 recipes/gdal/meta.yaml create mode 100644 recipes/gdal/patches/config.patch create mode 100644 recipes/gdal/test_gdal.py create mode 100644 recipes/pyogrio/meta.yaml create mode 100644 recipes/pyogrio/test_pyogrio.py create mode 100644 recipes/pyproj/meta.yaml create mode 100644 recipes/pyproj/patches/mobile.patch create mode 100644 recipes/shapely/meta.yaml create mode 100644 recipes/shapely/patches/mobile.patch diff --git a/.appveyor.yml b/.appveyor.yml index 199130ed..b4715722 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -14,21 +14,38 @@ environment: CF_BUCKET_NAME: flet-simple GEMFURY_TOKEN: secure: trYGM65OQ1+HYnOYOe/NOHrofLpP3bz64nHwVWPJhiUIYll3MrrQd7ilFNp+zSkI + MOBILE_FORGE_CACHE_DOWNLOADS_OFF: 1 matrix: - - job_name: 'Android: protobuf' + - job_name: 'Android: flet-libgdal, fiona' job_group: build_android FORGE_ARCH: android FORGE_PACKAGES: >- - protobuf:5.28.3 + flet-libpsl:0.21.5 + flet-libcurl:8.11.0 + flet-libjpeg:3.0.90 + flet-libtiff:4.7.0 + flet-libproj:9.5.0 + flet-libgdal:3.10.0 + fiona:1.10.1 + pyogrio:0.10.0 + gdal:3.10.0 BUILD_NUMBER: 1 - - job_name: 'iOS: protobuf' - job_group: build_ios - FORGE_ARCH: iOS - FORGE_PACKAGES: >- - protobuf:5.28.3 - BUILD_NUMBER: 1 + # - job_name: 'iOS: flet-libgdal, fiona' + # job_group: build_ios + # FORGE_ARCH: iOS + # FORGE_PACKAGES: >- + # flet-libpsl:0.21.5 + # flet-libcurl:8.11.0 + # flet-libjpeg:3.0.90 + # flet-libtiff:4.7.0 + # flet-libproj:9.5.0 + # flet-libgdal:3.10.0 + # fiona:1.10.1 + # pyogrio:0.10.0 + # gdal:3.10.0 + # BUILD_NUMBER: 1 # ================================================== @@ -82,7 +99,7 @@ environment: # flet-libcpp-shared:27.2.12479018 # flet-libjpeg:3.0.90 # flet-libpng:1.6.43 - # flet-freetype:2.13.3 + # flet-libfreetype:2.13.3 # pillow:10.4.0 # lru-dict:1.3.0 # yarl:1.11.1 @@ -119,7 +136,7 @@ environment: # FORGE_PACKAGES: >- # flet-libjpeg:3.0.90 # flet-libpng:1.6.43 - # flet-freetype:2.13.3 + # flet-libfreetype:2.13.3 # pillow:10.4.0 # lru-dict:1.3.0 # yarl:1.11.1 @@ -195,6 +212,7 @@ for: NDK_VERSION: r27c install: + - sudo apt install sqlite3 - . .ci/common.sh # download Python for Android diff --git a/recipes/fiona/meta.yaml b/recipes/fiona/meta.yaml index 2b8ea81c..a966ad5e 100644 --- a/recipes/fiona/meta.yaml +++ b/recipes/fiona/meta.yaml @@ -1,3 +1,20 @@ package: name: fiona version: 1.10.1 + +requirements: + host: + - flet-libgdal 3.10.0 + +build: + script_env: + GDAL_VERSION: 3.10.0 + GDAL_LIB_PATH: '{platlib}/opt/lib' + GDAL_INCLUDE_PATH: '{platlib}/opt/include' + GDAL_LIBS: gdal +# {% if sdk != 'android' %} + LDFLAGS: '-undefined dynamic_lookup' +# {% endif %} + +patches: + - mobile.patch \ No newline at end of file diff --git a/recipes/fiona/patches/mobile.patch b/recipes/fiona/patches/mobile.patch new file mode 100644 index 00000000..6b6d0b5b --- /dev/null +++ b/recipes/fiona/patches/mobile.patch @@ -0,0 +1,26 @@ +diff --git a/setup.py b/setup.py +index e1f48a6..6c04d39 100644 +--- a/setup.py ++++ b/setup.py +@@ -9,7 +9,6 @@ import sys + from setuptools import setup + from setuptools.extension import Extension + +- + # Ensure minimum version of Python is running + if sys.version_info[0:2] < (3, 6): + raise RuntimeError('Fiona requires Python>=3.6') +@@ -85,6 +84,13 @@ if 'clean' not in sys.argv: + else: + logging.warning("Failed to get options via gdal-config: %s", str(e)) + ++ if 'GDAL_LIB_PATH' in os.environ: ++ library_dirs.extend(os.environ['GDAL_LIB_PATH'].split(":")) ++ if 'GDAL_INCLUDE_PATH' in os.environ: ++ include_dirs.extend(os.environ['GDAL_INCLUDE_PATH'].split(":")) ++ if 'GDAL_LIBS' in os.environ: ++ libraries.extend(os.environ['GDAL_LIBS'].split(",")) ++ + # Get GDAL API version from environment variable. + if 'GDAL_VERSION' in os.environ: + gdalversion = os.environ['GDAL_VERSION'] diff --git a/recipes/flet-crc32c/build.sh b/recipes/flet-libcrc32c/build.sh similarity index 100% rename from recipes/flet-crc32c/build.sh rename to recipes/flet-libcrc32c/build.sh diff --git a/recipes/flet-crc32c/meta.yaml b/recipes/flet-libcrc32c/meta.yaml similarity index 87% rename from recipes/flet-crc32c/meta.yaml rename to recipes/flet-libcrc32c/meta.yaml index f477090c..7d9b942e 100644 --- a/recipes/flet-crc32c/meta.yaml +++ b/recipes/flet-libcrc32c/meta.yaml @@ -1,5 +1,5 @@ package: - name: flet-crc32c + name: flet-libcrc32c version: 1.1.2 build: diff --git a/recipes/flet-libcurl/build.sh b/recipes/flet-libcurl/build.sh new file mode 100755 index 00000000..f0b69969 --- /dev/null +++ b/recipes/flet-libcurl/build.sh @@ -0,0 +1,13 @@ +#!/bin/bash +set -eu + +./configure --host=$HOST_TRIPLET --prefix=$PREFIX --with-openssl=$PLATLIB/opt +make -j $CPU_COUNT +make install + +rm -r $PREFIX/{bin,share} +rm -r $PREFIX/lib/{*.la,pkgconfig} + +if [ $CROSS_VENV_SDK == "android" ]; then + rm -r $PREFIX/lib/*.a +fi \ No newline at end of file diff --git a/recipes/flet-libcurl/meta.yaml b/recipes/flet-libcurl/meta.yaml new file mode 100644 index 00000000..39d732b3 --- /dev/null +++ b/recipes/flet-libcurl/meta.yaml @@ -0,0 +1,19 @@ +{% set version = "8.11.0" %} + +package: + name: flet-libcurl + version: '{{ version }}' + +source: + url: https://curl.se/download/curl-{{ version }}.tar.gz + +build: + number: 1 + +requirements: + host: + - openssl 3.0.15 + - flet-libpsl 0.21.5 + +patches: + - config.patch \ No newline at end of file diff --git a/recipes/flet-libcurl/patches/config.patch b/recipes/flet-libcurl/patches/config.patch new file mode 100644 index 00000000..7eecc34f --- /dev/null +++ b/recipes/flet-libcurl/patches/config.patch @@ -0,0 +1,13 @@ +diff --git a/config.sub b/config.sub +index dba16e8..215b8e2 100755 +--- a/config.sub ++++ b/config.sub +@@ -1792,6 +1792,8 @@ case $kernel-$os in + ;; + *-eabi* | *-gnueabi*) + ;; ++ ios-simulator) ++ ;; + -*) + # Blank kernel with real OS is always fine. + ;; diff --git a/recipes/flet-freetype/build.sh b/recipes/flet-libfreetype/build.sh similarity index 87% rename from recipes/flet-freetype/build.sh rename to recipes/flet-libfreetype/build.sh index 2c7ad0f9..53ccf720 100755 --- a/recipes/flet-freetype/build.sh +++ b/recipes/flet-libfreetype/build.sh @@ -12,5 +12,8 @@ rmdir $PREFIX/include/freetype2 # has an SONAME of libfreetype.so, so there's no conflict. # rm -r $PREFIX/lib/{*.a,*.la,pkgconfig} rm -r $PREFIX/lib/{*.la,pkgconfig} - rm -r $PREFIX/share + +if [ $CROSS_VENV_SDK == "android" ]; then + rm -r $PREFIX/lib/*.a +fi \ No newline at end of file diff --git a/recipes/flet-freetype/meta.yaml b/recipes/flet-libfreetype/meta.yaml similarity index 88% rename from recipes/flet-freetype/meta.yaml rename to recipes/flet-libfreetype/meta.yaml index b09f7a01..139a8bb9 100644 --- a/recipes/flet-freetype/meta.yaml +++ b/recipes/flet-libfreetype/meta.yaml @@ -1,5 +1,5 @@ package: - name: flet-freetype + name: flet-libfreetype version: 2.13.3 build: diff --git a/recipes/flet-freetype/patches/config.patch b/recipes/flet-libfreetype/patches/config.patch similarity index 100% rename from recipes/flet-freetype/patches/config.patch rename to recipes/flet-libfreetype/patches/config.patch diff --git a/recipes/flet-libgdal/build.sh b/recipes/flet-libgdal/build.sh new file mode 100755 index 00000000..774bbc93 --- /dev/null +++ b/recipes/flet-libgdal/build.sh @@ -0,0 +1,57 @@ +#!/bin/bash +set -eu + +mkdir build +cd build + +if [ $CROSS_VENV_SDK == "android" ]; then + cmake .. \ + -DCMAKE_SYSTEM_NAME=Android \ + -DANDROID_PLATFORM=$SDK_VERSION \ + -DANDROID_ABI=$ANDROID_ABI \ + -DCMAKE_TOOLCHAIN_FILE=$NDK_ROOT/build/cmake/android.toolchain.cmake \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_INSTALL_PREFIX="$PREFIX" \ + -DCMAKE_FIND_ROOT_PATH_MODE_INCLUDE=NEVER \ + -DCMAKE_FIND_ROOT_PATH_MODE_LIBRARY=NEVER \ + -DCMAKE_FIND_USE_CMAKE_SYSTEM_PATH=NO \ + -DPROJ_LIBRARY=$PLATLIB/opt/lib/libproj.so \ + -DPROJ_INCLUDE_DIR=$PLATLIB/opt/include \ + -DSQLite3_LIBRARY=$PYTHON_PREFIX/lib/libsqlite3_python.so \ + -DSQLite3_INCLUDE_DIR=$PYTHON_PREFIX/include \ + -DGDAL_BUILD_OPTIONAL_DRIVERS=OFF \ + -DOGR_BUILD_OPTIONAL_DRIVERS=OFF \ + -DGDAL_USE_EXPAT=OFF \ + -DGDAL_USE_OPENSSL=OFF \ + -DGDAL_USE_CURL=OFF \ + -DGDAL_USE_LIBXML2=OFF \ + -DBUILD_APPS=OFF \ + -DBUILD_TESTING=OFF +else + cmake .. \ + -DCMAKE_SYSTEM_NAME=iOS \ + -DCMAKE_OSX_SYSROOT=$SDK \ + -DCMAKE_OSX_ARCHITECTURES=$HOST_ARCH \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_INSTALL_PREFIX=$PREFIX \ + -DBUILD_SHARED_LIBS=OFF \ + -DCMAKE_FIND_ROOT_PATH_MODE_INCLUDE=NEVER \ + -DCMAKE_FIND_ROOT_PATH_MODE_LIBRARY=NEVER \ + -DCMAKE_FIND_USE_CMAKE_SYSTEM_PATH=NO \ + -DCMAKE_CXX_FLAGS="$CFLAGS" \ + -DGDAL_USE_EXTERNAL_LIBS=OFF \ + -DPROJ_LIBRARY=$PLATLIB/opt/lib/libproj.a \ + -DPROJ_INCLUDE_DIR=$PLATLIB/opt/include \ + -DSQLite3_LIBRARY=$SDK_ROOT/usr/lib/libsqlite3.tbd \ + -DSQLite3_INCLUDE_DIR=$SDK_ROOT/usr/include \ + -DGDAL_BUILD_OPTIONAL_DRIVERS=OFF \ + -DOGR_BUILD_OPTIONAL_DRIVERS=OFF \ + -DBUILD_APPS=OFF \ + -DBUILD_TESTING=OFF +fi + +cmake --build . -j $CPU_COUNT +cmake --build . --target install + +rm -rf $PREFIX/{bin,share} +rm -rf $PREFIX/lib/{cmake,pkgconfig} \ No newline at end of file diff --git a/recipes/flet-libgdal/meta.yaml b/recipes/flet-libgdal/meta.yaml new file mode 100644 index 00000000..17c9e612 --- /dev/null +++ b/recipes/flet-libgdal/meta.yaml @@ -0,0 +1,17 @@ +{% set version = "3.10.0" %} + +package: + name: flet-libgdal + version: '{{ version }}' + +source: + url: https://github.com/OSGeo/gdal/releases/download/v{{ version }}/gdal-{{ version }}.tar.gz + +build: + number: 1 + +requirements: + build: + - cmake + host: + - flet-libproj 9.5.0 \ No newline at end of file diff --git a/recipes/flet-libgeos/build.sh b/recipes/flet-libgeos/build.sh new file mode 100755 index 00000000..12573ad8 --- /dev/null +++ b/recipes/flet-libgeos/build.sh @@ -0,0 +1,32 @@ +#!/bin/bash +set -eu + +if [ $CROSS_VENV_SDK == "android" ]; then + cmake \ + -DCMAKE_SYSTEM_NAME=Android \ + -DANDROID_PLATFORM=$SDK_VERSION \ + -DANDROID_ABI=$ANDROID_ABI \ + -DCMAKE_TOOLCHAIN_FILE=$NDK_ROOT/build/cmake/android.toolchain.cmake \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_INSTALL_PREFIX="$PREFIX" \ + -DBUILD_TESTING=0 +else + cmake \ + -DCMAKE_SYSTEM_NAME=iOS \ + -DCMAKE_OSX_SYSROOT=$SDK \ + -DCMAKE_OSX_ARCHITECTURES=$HOST_ARCH \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_INSTALL_PREFIX=$PREFIX \ + -DBUILD_SHARED_LIBS=OFF \ + -DBUILD_TESTING=0 +fi + +make -j $CPU_COUNT +make install + +rm -rf $PREFIX/bin +rm -rf $PREFIX/lib/{cmake,pkgconfig} + +# As recommended by the documentation, most users of this library link against libgeos_c, which +# has a copy of libgeos built into it. +rm $PREFIX/lib/libgeos.* diff --git a/recipes/flet-libgeos/meta.yaml b/recipes/flet-libgeos/meta.yaml new file mode 100644 index 00000000..5acb7e7e --- /dev/null +++ b/recipes/flet-libgeos/meta.yaml @@ -0,0 +1,13 @@ +package: + name: flet-libgeos + version: 3.13.0 + +build: + number: 1 + +source: + url: http://download.osgeo.org/geos/geos-3.13.0.tar.bz2 + +requirements: + build: + - cmake \ No newline at end of file diff --git a/recipes/flet-libproj/build.sh b/recipes/flet-libproj/build.sh new file mode 100755 index 00000000..f19a8424 --- /dev/null +++ b/recipes/flet-libproj/build.sh @@ -0,0 +1,40 @@ +#!/bin/bash +set -eu + +if [ $CROSS_VENV_SDK == "android" ]; then + cmake \ + -DCMAKE_SYSTEM_NAME=Android \ + -DANDROID_PLATFORM=$SDK_VERSION \ + -DANDROID_ABI=$ANDROID_ABI \ + -DCMAKE_TOOLCHAIN_FILE=$NDK_ROOT/build/cmake/android.toolchain.cmake \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_INSTALL_PREFIX="$PREFIX" \ + -DBUILD_TESTING=0 \ + -DTIFF_LIBRARY="$PLATLIB/opt/lib/libtiff.so" \ + -DTIFF_INCLUDE_DIR="$PLATLIB/opt/include" \ + -DCURL_LIBRARY="$PLATLIB/opt/lib/libcurl.so" \ + -DCURL_INCLUDE_DIR="$PLATLIB/opt/include" \ + -DSQLite3_LIBRARY=$PYTHON_PREFIX/lib/libsqlite3_python.so \ + -DSQLite3_INCLUDE_DIR=$PYTHON_PREFIX/include +else + cmake \ + -DCMAKE_SYSTEM_NAME=iOS \ + -DCMAKE_OSX_SYSROOT=$SDK \ + -DCMAKE_OSX_ARCHITECTURES=$HOST_ARCH \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_INSTALL_PREFIX=$PREFIX \ + -DBUILD_SHARED_LIBS=OFF \ + -DBUILD_TESTING=0 \ + -DTIFF_LIBRARY="$PLATLIB/opt/lib/libtiff.a" \ + -DTIFF_INCLUDE_DIR="$PLATLIB/opt/include" \ + -DCURL_LIBRARY="$PLATLIB/opt/lib/libcurl.a" \ + -DCURL_INCLUDE_DIR="$PLATLIB/opt/include" \ + -DSQLite3_LIBRARY=$SDK_ROOT/usr/lib/libsqlite3.tbd \ + -DSQLite3_INCLUDE_DIR=$SDK_ROOT/usr/include +fi + +cmake --build . -j $CPU_COUNT +cmake --build . --target install + +rm -rf $PREFIX/{bin,share} +rm -rf $PREFIX/lib/{cmake,pkgconfig} \ No newline at end of file diff --git a/recipes/flet-libproj/meta.yaml b/recipes/flet-libproj/meta.yaml new file mode 100644 index 00000000..76134754 --- /dev/null +++ b/recipes/flet-libproj/meta.yaml @@ -0,0 +1,24 @@ +{% set version = "9.5.0" %} + +package: + name: flet-libproj + version: '{{ version }}' + +source: + url: https://download.osgeo.org/proj/proj-{{ version }}.tar.gz + +build: + number: 1 + +requirements: + build: + - cmake + host: + - flet-libtiff 4.7.0 + - flet-libcurl 8.11.0 + +# {% if sdk != 'android' %} +build: + script_env: + LDFLAGS: '-undefined dynamic_lookup' +# {% endif %} \ No newline at end of file diff --git a/recipes/flet-libpsl/build.sh b/recipes/flet-libpsl/build.sh new file mode 100755 index 00000000..93734586 --- /dev/null +++ b/recipes/flet-libpsl/build.sh @@ -0,0 +1,13 @@ +#!/bin/bash +set -eu + +./configure --host=$HOST_TRIPLET --build=$BUILD_TRIPLET --prefix=$PREFIX --disable-runtime +make -j $CPU_COUNT +make install + +rm -r $PREFIX/{bin,share} +rm -r $PREFIX/lib/{*.la,pkgconfig} + +if [ $CROSS_VENV_SDK == "android" ]; then + rm -r $PREFIX/lib/*.a +fi \ No newline at end of file diff --git a/recipes/flet-libpsl/meta.yaml b/recipes/flet-libpsl/meta.yaml new file mode 100644 index 00000000..d8da3832 --- /dev/null +++ b/recipes/flet-libpsl/meta.yaml @@ -0,0 +1,14 @@ +{% set version = "0.21.5" %} + +package: + name: flet-libpsl + version: '{{ version }}' + +source: + url: https://github.com/rockdaboot/libpsl/releases/download/{{ version }}/libpsl-{{ version }}.tar.gz + +build: + number: 1 + +patches: + - config.patch \ No newline at end of file diff --git a/recipes/flet-libpsl/patches/config.patch b/recipes/flet-libpsl/patches/config.patch new file mode 100644 index 00000000..3000a67f --- /dev/null +++ b/recipes/flet-libpsl/patches/config.patch @@ -0,0 +1,13 @@ +diff --git a/build-aux/config.sub b/build-aux/config.sub +index dba16e8..215b8e2 100755 +--- a/build-aux/config.sub ++++ b/build-aux/config.sub +@@ -1792,6 +1792,8 @@ case $kernel-$os in + ;; + *-eabi* | *-gnueabi*) + ;; ++ ios-simulator) ++ ;; + -*) + # Blank kernel with real OS is always fine. + ;; diff --git a/recipes/flet-libtiff/build.sh b/recipes/flet-libtiff/build.sh new file mode 100755 index 00000000..948c279f --- /dev/null +++ b/recipes/flet-libtiff/build.sh @@ -0,0 +1,13 @@ +#!/bin/bash +set -eu + +./configure --host=$HOST_TRIPLET --prefix=$PREFIX --disable-docs +make -j $CPU_COUNT +make install + +rm -r $PREFIX/bin +rm -rf $PREFIX/lib/{*.la,*xx.*,pkgconfig} + +if [ $CROSS_VENV_SDK == "android" ]; then + rm -r $PREFIX/lib/*.a +fi \ No newline at end of file diff --git a/recipes/flet-libtiff/meta.yaml b/recipes/flet-libtiff/meta.yaml new file mode 100644 index 00000000..7380bfb5 --- /dev/null +++ b/recipes/flet-libtiff/meta.yaml @@ -0,0 +1,18 @@ +{% set version = "4.7.0" %} + +package: + name: flet-libtiff + version: '{{ version }}' + +source: + url: https://download.osgeo.org/libtiff/tiff-{{ version }}.tar.gz + +build: + number: 1 + +requirements: + host: + - flet-libjpeg 3.0.90 + +patches: + - config.patch \ No newline at end of file diff --git a/recipes/flet-libtiff/patches/config.patch b/recipes/flet-libtiff/patches/config.patch new file mode 100644 index 00000000..a853b1e5 --- /dev/null +++ b/recipes/flet-libtiff/patches/config.patch @@ -0,0 +1,13 @@ +diff --git a/config/config.sub b/config/config.sub +index 4aaae46..1692095 100755 +--- a/config/config.sub ++++ b/config/config.sub +@@ -2259,6 +2259,8 @@ case $kernel-$os-$obj in + --*) + # Blank kernel and OS with real machine code file format is always fine. + ;; ++ ios-simulator*-) ++ ;; + *-*-*) + echo "Invalid configuration '$1': Kernel '$kernel' not known to work with OS '$os'." 1>&2 + exit 1 diff --git a/recipes/gdal/meta.yaml b/recipes/gdal/meta.yaml new file mode 100644 index 00000000..877f2bf8 --- /dev/null +++ b/recipes/gdal/meta.yaml @@ -0,0 +1,19 @@ +package: + name: gdal + version: 3.10.0 + +requirements: + host: + - flet-libgdal 3.10.0 + +build: + script_env: + GDAL_VERSION: 3.10.0 + GDAL_PREFIX: '{platlib}/opt' + GDAL_CFLAGS: '' +# {% if sdk != 'android' %} + LDFLAGS: '-undefined dynamic_lookup' +# {% endif %} + +patches: + - config.patch \ No newline at end of file diff --git a/recipes/gdal/patches/config.patch b/recipes/gdal/patches/config.patch new file mode 100644 index 00000000..58f84d8d --- /dev/null +++ b/recipes/gdal/patches/config.patch @@ -0,0 +1,14 @@ +diff --git a/setup.py b/setup.py +index 5c6ac95..26bb5fa 100644 +--- a/setup.py ++++ b/setup.py +@@ -228,6 +228,9 @@ class gdal_ext(build_ext): + + def get_gdal_config(self, option): + try: ++ var_name = f"GDAL_{option.upper()}" ++ if var_name in os.environ: ++ return os.environ[var_name] + return fetch_config(option, gdal_config=self.gdal_config) + except gdal_config_error: + msg = 'Could not find gdal-config. Make sure you have installed the GDAL native library and development headers.' diff --git a/recipes/gdal/test_gdal.py b/recipes/gdal/test_gdal.py new file mode 100644 index 00000000..6b81d9cd --- /dev/null +++ b/recipes/gdal/test_gdal.py @@ -0,0 +1 @@ +# TBD \ No newline at end of file diff --git a/recipes/google-crc32c/meta.yaml b/recipes/google-crc32c/meta.yaml index 903bfa11..83512090 100644 --- a/recipes/google-crc32c/meta.yaml +++ b/recipes/google-crc32c/meta.yaml @@ -4,7 +4,7 @@ package: requirements: host: - - flet-crc32c 1.1.2 + - flet-libcrc32c 1.1.2 # {% if sdk != 'android' %} build: diff --git a/recipes/pillow/meta.yaml b/recipes/pillow/meta.yaml index 3ca0085e..91686fff 100644 --- a/recipes/pillow/meta.yaml +++ b/recipes/pillow/meta.yaml @@ -6,7 +6,7 @@ requirements: host: # PNG support is internal: libpng is not used. - flet-libjpeg 3.0.90 - - flet-freetype 2.13.3 + - flet-libfreetype 2.13.3 patches: - setup.patch diff --git a/recipes/pyogrio/meta.yaml b/recipes/pyogrio/meta.yaml new file mode 100644 index 00000000..104bb531 --- /dev/null +++ b/recipes/pyogrio/meta.yaml @@ -0,0 +1,16 @@ +package: + name: pyogrio + version: 0.10.0 + +requirements: + host: + - flet-libgdal 3.10.0 + +build: + script_env: + GDAL_VERSION: 3.10.0 + GDAL_LIBRARY_PATH: '{platlib}/opt/lib' + GDAL_INCLUDE_PATH: '{platlib}/opt/include' +# {% if sdk != 'android' %} + LDFLAGS: '-undefined dynamic_lookup' +# {% endif %} \ No newline at end of file diff --git a/recipes/pyogrio/test_pyogrio.py b/recipes/pyogrio/test_pyogrio.py new file mode 100644 index 00000000..6b81d9cd --- /dev/null +++ b/recipes/pyogrio/test_pyogrio.py @@ -0,0 +1 @@ +# TBD \ No newline at end of file diff --git a/recipes/pyproj/meta.yaml b/recipes/pyproj/meta.yaml new file mode 100644 index 00000000..50408874 --- /dev/null +++ b/recipes/pyproj/meta.yaml @@ -0,0 +1,18 @@ +package: + name: pyproj + version: 3.7.0 + +build: + script_env: + PROJ_VERSION: 9.5.0 + PROJ_DIR: '{platlib}/opt' +# {% if sdk != 'android' %} + LDFLAGS: '-undefined dynamic_lookup' +# {% endif %} + +requirements: + host: + - flet-libproj 9.5.0 + +patches: + - mobile.patch \ No newline at end of file diff --git a/recipes/pyproj/patches/mobile.patch b/recipes/pyproj/patches/mobile.patch new file mode 100644 index 00000000..aa542c16 --- /dev/null +++ b/recipes/pyproj/patches/mobile.patch @@ -0,0 +1,15 @@ +diff --git a/setup.py b/setup.py +index 9987cff..b56a0fc 100644 +--- a/setup.py ++++ b/setup.py +@@ -194,7 +194,9 @@ def get_extension_modules(): + "include_dirs": include_dirs, + "library_dirs": library_dirs, + "runtime_library_dirs": ( +- library_dirs if os.name != "nt" and sys.platform != "cygwin" else None ++ library_dirs ++ if os.name != "nt" and sys.platform != "cygwin" and sys.platform != "ios" ++ else None + ), + "libraries": get_libraries(library_dirs), + } diff --git a/recipes/shapely/meta.yaml b/recipes/shapely/meta.yaml new file mode 100644 index 00000000..22d9884d --- /dev/null +++ b/recipes/shapely/meta.yaml @@ -0,0 +1,11 @@ +package: + name: shapely + version: 2.0.6 + +requirements: + host: + - flet-libgeos 3.13.0 + - numpy ^2.0.0 + +patches: + - mobile.patch \ No newline at end of file diff --git a/recipes/shapely/patches/mobile.patch b/recipes/shapely/patches/mobile.patch new file mode 100644 index 00000000..010c0235 --- /dev/null +++ b/recipes/shapely/patches/mobile.patch @@ -0,0 +1,75 @@ +diff --git a/setup.py b/setup.py +index d49d722..ca3c433 100644 +--- a/setup.py ++++ b/setup.py +@@ -73,39 +73,39 @@ def get_geos_paths(): + "libraries": ["geos_c"], + } + +- geos_version = get_geos_config("--version") +- if not geos_version: +- log.warning( +- "Could not find geos-config executable. Either append the path to geos-config" +- " to PATH or manually provide the include_dirs, library_dirs, libraries and " +- "other link args for compiling against a GEOS version >=%s.", +- MIN_GEOS_VERSION, +- ) +- return {} +- +- def version_tuple(ver): +- return tuple(int(itm) if itm.isnumeric() else itm for itm in ver.split(".")) +- +- if version_tuple(geos_version) < version_tuple(MIN_GEOS_VERSION): +- raise ImportError( +- f"GEOS version should be >={MIN_GEOS_VERSION}, found {geos_version}" +- ) +- +- libraries = [] ++ # geos_version = get_geos_config("--version") ++ # if not geos_version: ++ # log.warning( ++ # "Could not find geos-config executable. Either append the path to geos-config" ++ # " to PATH or manually provide the include_dirs, library_dirs, libraries and " ++ # "other link args for compiling against a GEOS version >=%s.", ++ # MIN_GEOS_VERSION, ++ # ) ++ # return {} ++ ++ # def version_tuple(ver): ++ # return tuple(int(itm) if itm.isnumeric() else itm for itm in ver.split(".")) ++ ++ # if version_tuple(geos_version) < version_tuple(MIN_GEOS_VERSION): ++ # raise ImportError( ++ # f"GEOS version should be >={MIN_GEOS_VERSION}, found {geos_version}" ++ # ) ++ ++ libraries = ["geos_c"] + library_dirs = [] + include_dirs = ["./src"] +- extra_link_args = [] +- for item in get_geos_config("--cflags").split(): +- if item.startswith("-I"): +- include_dirs.extend(item[2:].split(":")) +- +- for item in get_geos_config("--clibs").split(): +- if item.startswith("-L"): +- library_dirs.extend(item[2:].split(":")) +- elif item.startswith("-l"): +- libraries.append(item[2:]) +- else: +- extra_link_args.append(item) ++ extra_link_args = ["-undefined", "dynamic_lookup"] if sys.platform == "ios" else [] ++ # for item in get_geos_config("--cflags").split(): ++ # if item.startswith("-I"): ++ # include_dirs.extend(item[2:].split(":")) ++ ++ # for item in get_geos_config("--clibs").split(): ++ # if item.startswith("-L"): ++ # library_dirs.extend(item[2:].split(":")) ++ # elif item.startswith("-l"): ++ # libraries.append(item[2:]) ++ # else: ++ # extra_link_args.append(item) + + return { + "include_dirs": include_dirs, diff --git a/src/forge/build.py b/src/forge/build.py index 25871390..5c935f82 100644 --- a/src/forge/build.py +++ b/src/forge/build.py @@ -214,7 +214,7 @@ def prepare(self, clean=True): ) shutil.rmtree(self.build_path) - if not self.source_archive_path.is_file(): + if os.getenv(f"MOBILE_FORGE_CACHE_DOWNLOADS_OFF") or not self.source_archive_path.is_file(): log(self.log_file, f"\n[{self.cross_venv}] Download package sources") self.download_source() @@ -336,6 +336,20 @@ def compile_env(self, **kwargs) -> dict[str, str]: } env.update(kwargs) + script_vars = { + **env, + **self.cross_venv.scheme_paths, + **self.cross_venv.sysconfig_data, + "sysconfigdata_name": self.cross_venv.sysconfigdata_name, + } + + # Set up any additional environment variables needed in the script environment. + for key, value in self.package.meta["build"]["script_env"].items(): + if key in ["LDFLAGS", "CFLAGS", "CPPFLAGS"]: + env[key] += " " + value + else: + env[key] = str(value).format(**script_vars) + if self.cross_venv.sdk == "android": cc_parts = cc.split("/") env["NDK_ROOT"] = "/".join(cc_parts[: cc_parts.index("toolchains")]) @@ -551,9 +565,15 @@ def compile(self): "HOST_ARCH": self.cross_venv.arch, "SDK": self.cross_venv.sdk, "SDK_VERSION": self.cross_venv.sdk_version, + "SDK_ROOT": ( + str(self.cross_venv.sdk_root) + if self.cross_venv.sdk != "android" + else "" + ), "BUILD_TRIPLET": f"{os.uname().machine}-apple-darwin", "CPU_COUNT": str(multiprocessing.cpu_count()), "PREFIX": str(self.build_path / "wheel" / "opt"), + "PYTHON_PREFIX": self.cross_venv.sysconfig_data["prefix"], "PLATLIB": self.cross_venv.scheme_paths["platlib"], } ), @@ -716,20 +736,6 @@ def _create_meson_cross(self, env: dict[str, str]): def _build(self): env = self.compile_env() - script_vars = { - **env, - **self.cross_venv.scheme_paths, - **self.cross_venv.sysconfig_data, - "sysconfigdata_name": self.cross_venv.sysconfigdata_name, - } - - # Set up any additional environment variables needed in the script environment. - for key, value in self.package.meta["build"]["script_env"].items(): - if key in ["LDFLAGS", "CFLAGS", "CPPFLAGS"]: - env[key] += " " + value - else: - env[key] = str(value).format(**script_vars) - # Set the cross host platform in the environment env["_PYTHON_HOST_PLATFORM"] = self.cross_venv.platform_identifier From c062d221e633ceb11b2deb230a0c96ef6b6cb918 Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Thu, 28 Nov 2024 10:12:37 -0800 Subject: [PATCH 043/142] pendulum (#16) * pendulum for iOS and Android * Build pendulum for x64 archs only * Fix pendulum for 32-bit androids --- .appveyor.yml | 32 +++++++-------------------- recipes/pendulum/meta.yaml | 13 +++++++++++ recipes/pendulum/patches/mobile.patch | 12 ++++++++++ 3 files changed, 33 insertions(+), 24 deletions(-) create mode 100644 recipes/pendulum/meta.yaml create mode 100644 recipes/pendulum/patches/mobile.patch diff --git a/.appveyor.yml b/.appveyor.yml index b4715722..7fafd141 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -17,35 +17,19 @@ environment: MOBILE_FORGE_CACHE_DOWNLOADS_OFF: 1 matrix: - - job_name: 'Android: flet-libgdal, fiona' + - job_name: 'Android: pendulum' job_group: build_android FORGE_ARCH: android FORGE_PACKAGES: >- - flet-libpsl:0.21.5 - flet-libcurl:8.11.0 - flet-libjpeg:3.0.90 - flet-libtiff:4.7.0 - flet-libproj:9.5.0 - flet-libgdal:3.10.0 - fiona:1.10.1 - pyogrio:0.10.0 - gdal:3.10.0 + pendulum:3.0.0 BUILD_NUMBER: 1 - # - job_name: 'iOS: flet-libgdal, fiona' - # job_group: build_ios - # FORGE_ARCH: iOS - # FORGE_PACKAGES: >- - # flet-libpsl:0.21.5 - # flet-libcurl:8.11.0 - # flet-libjpeg:3.0.90 - # flet-libtiff:4.7.0 - # flet-libproj:9.5.0 - # flet-libgdal:3.10.0 - # fiona:1.10.1 - # pyogrio:0.10.0 - # gdal:3.10.0 - # BUILD_NUMBER: 1 + - job_name: 'iOS: pendulum' + job_group: build_ios + FORGE_ARCH: iOS + FORGE_PACKAGES: >- + pendulum:3.0.0 + BUILD_NUMBER: 1 # ================================================== diff --git a/recipes/pendulum/meta.yaml b/recipes/pendulum/meta.yaml new file mode 100644 index 00000000..68c697f1 --- /dev/null +++ b/recipes/pendulum/meta.yaml @@ -0,0 +1,13 @@ +package: + name: pendulum + version: 3.0.0 + +build: + script_env: + _PYTHON_SYSCONFIGDATA_NAME: '{sysconfigdata_name}' +# {% if sdk == 'iphonesimulator' %} + CFLAGS_aarch64-apple-ios-sim: "--target=arm64-apple-ios13.0-simulator" +# {% endif %} + +patches: + - mobile.patch \ No newline at end of file diff --git a/recipes/pendulum/patches/mobile.patch b/recipes/pendulum/patches/mobile.patch new file mode 100644 index 00000000..8d410b4c --- /dev/null +++ b/recipes/pendulum/patches/mobile.patch @@ -0,0 +1,12 @@ +diff --git a/rust/src/helpers.rs b/rust/src/helpers.rs +index 364075a..8c5fbe8 100644 +--- a/rust/src/helpers.rs ++++ b/rust/src/helpers.rs +@@ -56,7 +56,7 @@ pub fn local_time( + seconds -= (10957 * SECS_PER_DAY as usize) as isize; + year += 30; // == 2000 + } else { +- seconds += ((146_097 - 10957) * SECS_PER_DAY as usize) as isize; ++ seconds += ((146_097 - 10957) as u64 * SECS_PER_DAY as u64) as isize; + year -= 370; // == 1600 + } From 5619a2ff584e26c10cf149d1facabd373002f9ec Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Thu, 28 Nov 2024 10:14:19 -0800 Subject: [PATCH 044/142] pycryptodome, pycryptodomex (#17) * pycryptodome * pycryptodome for iOS and Android --- .appveyor.yml | 10 ++++++---- recipes/pycryptodome/meta.yaml | 6 ++++++ recipes/pycryptodome/patches/mobile.patch | 21 +++++++++++++++++++++ recipes/pycryptodomex/meta.yaml | 6 ++++++ recipes/pycryptodomex/patches/mobile.patch | 21 +++++++++++++++++++++ 5 files changed, 60 insertions(+), 4 deletions(-) create mode 100644 recipes/pycryptodome/meta.yaml create mode 100644 recipes/pycryptodome/patches/mobile.patch create mode 100644 recipes/pycryptodomex/meta.yaml create mode 100644 recipes/pycryptodomex/patches/mobile.patch diff --git a/.appveyor.yml b/.appveyor.yml index 7fafd141..98acbade 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -17,18 +17,20 @@ environment: MOBILE_FORGE_CACHE_DOWNLOADS_OFF: 1 matrix: - - job_name: 'Android: pendulum' + - job_name: 'Android: pycryptodome, pycryptodomex' job_group: build_android FORGE_ARCH: android FORGE_PACKAGES: >- - pendulum:3.0.0 + pycryptodome:3.21.0 + pycryptodomex:3.21.0 BUILD_NUMBER: 1 - - job_name: 'iOS: pendulum' + - job_name: 'iOS: pycryptodome, pycryptodomex' job_group: build_ios FORGE_ARCH: iOS FORGE_PACKAGES: >- - pendulum:3.0.0 + pycryptodome:3.21.0 + pycryptodomex:3.21.0 BUILD_NUMBER: 1 # ================================================== diff --git a/recipes/pycryptodome/meta.yaml b/recipes/pycryptodome/meta.yaml new file mode 100644 index 00000000..116bd62e --- /dev/null +++ b/recipes/pycryptodome/meta.yaml @@ -0,0 +1,6 @@ +package: + name: pycryptodome + version: 3.21.0 + +# patches: +# - mobile.patch \ No newline at end of file diff --git a/recipes/pycryptodome/patches/mobile.patch b/recipes/pycryptodome/patches/mobile.patch new file mode 100644 index 00000000..1a171b4c --- /dev/null +++ b/recipes/pycryptodome/patches/mobile.patch @@ -0,0 +1,21 @@ +--- aaa/lib/Crypto/Util/_raw_api.py 2024-09-30 18:09:41.000000000 +0000 ++++ src/lib/Crypto/Util/_raw_api.py 2024-10-23 16:10:01.744278766 +0000 +@@ -312,6 +312,18 @@ + return load_lib(full_name, cdecl) + except OSError as exp: + attempts.append("Cannot load '%s': %s" % (filename, str(exp))) ++ ++ # This technique will work both before and after the importer redesign in Chaquopy 6.3. ++ import pkgutil ++ import Crypto ++ for entry in Crypto.__path__: ++ importer = pkgutil.get_importer(entry) ++ try: ++ filename = importer.extract_if_changed(name.replace(".", "/") + ".so") ++ return load_lib(filename, cdecl) ++ except KeyError: ++ attempts.append("Trying importer for '%s'" % entry) ++ + raise OSError("Cannot load native module '%s': %s" % (name, ", ".join(attempts))) + + diff --git a/recipes/pycryptodomex/meta.yaml b/recipes/pycryptodomex/meta.yaml new file mode 100644 index 00000000..7c6f97a6 --- /dev/null +++ b/recipes/pycryptodomex/meta.yaml @@ -0,0 +1,6 @@ +package: + name: pycryptodomex + version: 3.21.0 + +# patches: +# - mobile.patch \ No newline at end of file diff --git a/recipes/pycryptodomex/patches/mobile.patch b/recipes/pycryptodomex/patches/mobile.patch new file mode 100644 index 00000000..bc24fd23 --- /dev/null +++ b/recipes/pycryptodomex/patches/mobile.patch @@ -0,0 +1,21 @@ +--- aaa/lib/Cryptodome/Util/_raw_api.py 2024-09-30 18:09:41.000000000 +0000 ++++ src/lib/Cryptodome/Util/_raw_api.py 2024-10-23 16:10:01.744278766 +0000 +@@ -312,6 +312,18 @@ + return load_lib(full_name, cdecl) + except OSError as exp: + attempts.append("Cannot load '%s': %s" % (filename, str(exp))) ++ ++ # This technique will work both before and after the importer redesign in Chaquopy 6.3. ++ import pkgutil ++ import Cryptodome ++ for entry in Cryptodome.__path__: ++ importer = pkgutil.get_importer(entry) ++ try: ++ filename = importer.extract_if_changed(name.replace(".", "/") + ".so") ++ return load_lib(filename, cdecl) ++ except KeyError: ++ attempts.append("Trying importer for '%s'" % entry) ++ + raise OSError("Cannot load native module '%s': %s" % (name, ", ".join(attempts))) + + From 594bc1b111c6ffa396c285ae5c604b186fc53545 Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Thu, 28 Nov 2024 10:58:41 -0800 Subject: [PATCH 045/142] msgspec, msgpack for iOS and Android (#18) --- .appveyor.yml | 12 ++++++------ recipes/msgpack/meta.yaml | 3 +++ recipes/msgspec/meta.yaml | 7 +++++++ src/forge/build.py | 2 +- 4 files changed, 17 insertions(+), 7 deletions(-) create mode 100644 recipes/msgpack/meta.yaml create mode 100644 recipes/msgspec/meta.yaml diff --git a/.appveyor.yml b/.appveyor.yml index 98acbade..8eb7c46f 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -17,20 +17,20 @@ environment: MOBILE_FORGE_CACHE_DOWNLOADS_OFF: 1 matrix: - - job_name: 'Android: pycryptodome, pycryptodomex' + - job_name: 'Android: msgspec, msgpack' job_group: build_android FORGE_ARCH: android FORGE_PACKAGES: >- - pycryptodome:3.21.0 - pycryptodomex:3.21.0 + msgspec:0.18.6 + msgpack:1.1.0 BUILD_NUMBER: 1 - - job_name: 'iOS: pycryptodome, pycryptodomex' + - job_name: 'iOS: msgspec, msgpack' job_group: build_ios FORGE_ARCH: iOS FORGE_PACKAGES: >- - pycryptodome:3.21.0 - pycryptodomex:3.21.0 + msgspec:0.18.6 + msgpack:1.1.0 BUILD_NUMBER: 1 # ================================================== diff --git a/recipes/msgpack/meta.yaml b/recipes/msgpack/meta.yaml new file mode 100644 index 00000000..4e00554c --- /dev/null +++ b/recipes/msgpack/meta.yaml @@ -0,0 +1,3 @@ +package: + name: msgpack + version: 1.1.0 diff --git a/recipes/msgspec/meta.yaml b/recipes/msgspec/meta.yaml new file mode 100644 index 00000000..3b52e5b4 --- /dev/null +++ b/recipes/msgspec/meta.yaml @@ -0,0 +1,7 @@ +package: + name: msgspec + version: 0.18.6 + +requirements: + build: + - setuptools ^69.5.1 \ No newline at end of file diff --git a/src/forge/build.py b/src/forge/build.py index 5c935f82..c7de6b4b 100644 --- a/src/forge/build.py +++ b/src/forge/build.py @@ -650,7 +650,7 @@ def prepare(self, clean=True): # Install the build requirements in the build environment self.cross_venv.pip_install( self.log_file, - ["build", "wheel"] + pyproject["build-system"]["requires"], + ["build", "wheel"] + (pyproject["build-system"]["requires"] if "build-system" in pyproject else []), paths=[Path.cwd() / "dist"], build=True, ) From 377f925f8918bf55aa1b1d081967a623836b41f1 Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Thu, 28 Nov 2024 11:17:01 -0800 Subject: [PATCH 046/142] PyYAML for iOS and Android (#19) --- .appveyor.yml | 10 ++++------ recipes/pyyaml/meta.yaml | 3 +++ 2 files changed, 7 insertions(+), 6 deletions(-) create mode 100644 recipes/pyyaml/meta.yaml diff --git a/.appveyor.yml b/.appveyor.yml index 8eb7c46f..e6951152 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -17,20 +17,18 @@ environment: MOBILE_FORGE_CACHE_DOWNLOADS_OFF: 1 matrix: - - job_name: 'Android: msgspec, msgpack' + - job_name: 'Android: PyYAML' job_group: build_android FORGE_ARCH: android FORGE_PACKAGES: >- - msgspec:0.18.6 - msgpack:1.1.0 + pyyaml:6.0.2 BUILD_NUMBER: 1 - - job_name: 'iOS: msgspec, msgpack' + - job_name: 'iOS: PyYAML' job_group: build_ios FORGE_ARCH: iOS FORGE_PACKAGES: >- - msgspec:0.18.6 - msgpack:1.1.0 + pyyaml:6.0.2 BUILD_NUMBER: 1 # ================================================== diff --git a/recipes/pyyaml/meta.yaml b/recipes/pyyaml/meta.yaml new file mode 100644 index 00000000..5ada0c05 --- /dev/null +++ b/recipes/pyyaml/meta.yaml @@ -0,0 +1,3 @@ +package: + name: PyYAML + version: 6.0.2 From ada198df099b77c13d50f6c460560481cc1bd674 Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Thu, 28 Nov 2024 12:08:11 -0800 Subject: [PATCH 047/142] re-build shapely --- .appveyor.yml | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index e6951152..7d58de83 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -17,18 +17,22 @@ environment: MOBILE_FORGE_CACHE_DOWNLOADS_OFF: 1 matrix: - - job_name: 'Android: PyYAML' + - job_name: 'Android: shapely' job_group: build_android FORGE_ARCH: android FORGE_PACKAGES: >- - pyyaml:6.0.2 + flet-libgeos:3.13.0 + numpy:2.1.1 + shapely:2.0.6 BUILD_NUMBER: 1 - - job_name: 'iOS: PyYAML' + - job_name: 'iOS: shapely' job_group: build_ios FORGE_ARCH: iOS FORGE_PACKAGES: >- - pyyaml:6.0.2 + flet-libgeos:3.13.0 + numpy:2.1.1 + shapely:2.0.6 BUILD_NUMBER: 1 # ================================================== From d2b92278d8497e95fadeeeac90f8c32057d8d78e Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Thu, 28 Nov 2024 13:07:30 -0800 Subject: [PATCH 048/142] Re-build flet-libgeos with libgeos.so --- .appveyor.yml | 8 ++------ recipes/flet-libgeos/build.sh | 6 +----- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index 7d58de83..988c1e83 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -22,18 +22,14 @@ environment: FORGE_ARCH: android FORGE_PACKAGES: >- flet-libgeos:3.13.0 - numpy:2.1.1 - shapely:2.0.6 - BUILD_NUMBER: 1 + BUILD_NUMBER: 2 - job_name: 'iOS: shapely' job_group: build_ios FORGE_ARCH: iOS FORGE_PACKAGES: >- flet-libgeos:3.13.0 - numpy:2.1.1 - shapely:2.0.6 - BUILD_NUMBER: 1 + BUILD_NUMBER: 2 # ================================================== diff --git a/recipes/flet-libgeos/build.sh b/recipes/flet-libgeos/build.sh index 12573ad8..0572db12 100755 --- a/recipes/flet-libgeos/build.sh +++ b/recipes/flet-libgeos/build.sh @@ -25,8 +25,4 @@ make -j $CPU_COUNT make install rm -rf $PREFIX/bin -rm -rf $PREFIX/lib/{cmake,pkgconfig} - -# As recommended by the documentation, most users of this library link against libgeos_c, which -# has a copy of libgeos built into it. -rm $PREFIX/lib/libgeos.* +rm -rf $PREFIX/lib/{cmake,pkgconfig} \ No newline at end of file From ac4c2dbaebaf24c099dc8b80c7c933589f9b0dc7 Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Fri, 29 Nov 2024 11:15:43 -0800 Subject: [PATCH 049/142] Fix shapely for iOS. Re-publish. (#20) --- .appveyor.yml | 8 ++++++-- recipes/shapely/patches/mobile.patch | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index 988c1e83..7d58de83 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -22,14 +22,18 @@ environment: FORGE_ARCH: android FORGE_PACKAGES: >- flet-libgeos:3.13.0 - BUILD_NUMBER: 2 + numpy:2.1.1 + shapely:2.0.6 + BUILD_NUMBER: 1 - job_name: 'iOS: shapely' job_group: build_ios FORGE_ARCH: iOS FORGE_PACKAGES: >- flet-libgeos:3.13.0 - BUILD_NUMBER: 2 + numpy:2.1.1 + shapely:2.0.6 + BUILD_NUMBER: 1 # ================================================== diff --git a/recipes/shapely/patches/mobile.patch b/recipes/shapely/patches/mobile.patch index 010c0235..43aa6df8 100644 --- a/recipes/shapely/patches/mobile.patch +++ b/recipes/shapely/patches/mobile.patch @@ -43,7 +43,7 @@ index d49d722..ca3c433 100644 + # f"GEOS version should be >={MIN_GEOS_VERSION}, found {geos_version}" + # ) + -+ libraries = ["geos_c"] ++ libraries = ["geos", "geos_c"] library_dirs = [] include_dirs = ["./src"] - extra_link_args = [] From 93b4e15da91f230bbc7873711941d51c0d585411 Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Thu, 19 Dec 2024 12:40:26 -0800 Subject: [PATCH 050/142] Jq for iOS and Android (#21) * flet-libjq * jq for iOS and Android --- .appveyor.yml | 14 ++++++------- recipes/flet-libjq/build.sh | 13 +++++++++++++ recipes/flet-libjq/meta.yaml | 18 +++++++++++++++++ recipes/flet-libjq/patches/config.patch | 26 +++++++++++++++++++++++++ recipes/jq/meta.yaml | 11 +++++++++++ 5 files changed, 74 insertions(+), 8 deletions(-) create mode 100755 recipes/flet-libjq/build.sh create mode 100644 recipes/flet-libjq/meta.yaml create mode 100644 recipes/flet-libjq/patches/config.patch create mode 100644 recipes/jq/meta.yaml diff --git a/.appveyor.yml b/.appveyor.yml index 7d58de83..285de3c3 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -17,22 +17,20 @@ environment: MOBILE_FORGE_CACHE_DOWNLOADS_OFF: 1 matrix: - - job_name: 'Android: shapely' + - job_name: 'Android: jq' job_group: build_android FORGE_ARCH: android FORGE_PACKAGES: >- - flet-libgeos:3.13.0 - numpy:2.1.1 - shapely:2.0.6 + flet-libjq:1.7.1 + jq:1.8.0 BUILD_NUMBER: 1 - - job_name: 'iOS: shapely' + - job_name: 'iOS: jq' job_group: build_ios FORGE_ARCH: iOS FORGE_PACKAGES: >- - flet-libgeos:3.13.0 - numpy:2.1.1 - shapely:2.0.6 + flet-libjq:1.7.1 + jq:1.8.0 BUILD_NUMBER: 1 # ================================================== diff --git a/recipes/flet-libjq/build.sh b/recipes/flet-libjq/build.sh new file mode 100755 index 00000000..a546dbc4 --- /dev/null +++ b/recipes/flet-libjq/build.sh @@ -0,0 +1,13 @@ +#!/bin/bash +set -eu + +./configure --host=$HOST_TRIPLET --prefix=$PREFIX --with-oniguruma=builtin +make -j $CPU_COUNT +make install + +rm -r $PREFIX/{bin,share} +rm -r $PREFIX/lib/{*.la,pkgconfig} + +if [ $CROSS_VENV_SDK == "android" ]; then + rm -r $PREFIX/lib/*.a +fi \ No newline at end of file diff --git a/recipes/flet-libjq/meta.yaml b/recipes/flet-libjq/meta.yaml new file mode 100644 index 00000000..948eee21 --- /dev/null +++ b/recipes/flet-libjq/meta.yaml @@ -0,0 +1,18 @@ +{% set version = "1.7.1" %} + +package: + name: flet-libjq + version: '{{ version }}' + +source: + url: https://github.com/jqlang/jq/releases/download/jq-{{ version }}/jq-{{ version }}.tar.gz + +build: + number: 1 + +requirements: + build: + - cmake + +patches: + - config.patch \ No newline at end of file diff --git a/recipes/flet-libjq/patches/config.patch b/recipes/flet-libjq/patches/config.patch new file mode 100644 index 00000000..d4a35e70 --- /dev/null +++ b/recipes/flet-libjq/patches/config.patch @@ -0,0 +1,26 @@ +diff --git a/config/config.sub b/config/config.sub +index dba16e8..215b8e2 100755 +--- a/config/config.sub ++++ b/config/config.sub +@@ -1792,6 +1792,8 @@ case $kernel-$os in + ;; + *-eabi* | *-gnueabi*) + ;; ++ ios-simulator) ++ ;; + -*) + # Blank kernel with real OS is always fine. + ;; +diff --git a/modules/oniguruma/config.sub b/modules/oniguruma/config.sub +index 0753e30..fe182ac 100755 +--- a/modules/oniguruma/config.sub ++++ b/modules/oniguruma/config.sub +@@ -1753,6 +1753,8 @@ case $kernel-$os in + ;; + *-eabi* | *-gnueabi*) + ;; ++ ios-simulator) ++ ;; + -*) + # Blank kernel with real OS is always fine. + ;; diff --git a/recipes/jq/meta.yaml b/recipes/jq/meta.yaml new file mode 100644 index 00000000..5249ea96 --- /dev/null +++ b/recipes/jq/meta.yaml @@ -0,0 +1,11 @@ +package: + name: jq + version: 1.8.0 + +requirements: + host: + - flet-libjq 1.7.1 + +build: + script_env: + JQPY_USE_SYSTEM_LIBS: 1 \ No newline at end of file From 3a22935d5baeabfbcbc1608d9c897118e7174719 Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Sat, 28 Dec 2024 10:17:30 -0800 Subject: [PATCH 051/142] `pyjnius` and `pyobjus` (#22) * pyjnius for Android (draft) * pyobjus for iOS (draft) * pyjnius for Android, pyobjus for iOS * Added flet-libpyjni, re-build pyjnius * Build flet-libpyjni * Re-build flet-libpyjni, pyjnius * Cleanup --- .appveyor.yml | 19 ++-- recipes/flet-libpyjni/build.sh | 22 +++++ recipes/flet-libpyjni/meta.yaml | 13 +++ recipes/pyjnius/meta.yaml | 10 ++ recipes/pyjnius/patches/mobile.patch | 140 +++++++++++++++++++++++++++ recipes/pyobjus/meta.yaml | 10 ++ recipes/pyobjus/patches/mobile.patch | 86 ++++++++++++++++ 7 files changed, 290 insertions(+), 10 deletions(-) create mode 100755 recipes/flet-libpyjni/build.sh create mode 100644 recipes/flet-libpyjni/meta.yaml create mode 100644 recipes/pyjnius/meta.yaml create mode 100644 recipes/pyjnius/patches/mobile.patch create mode 100644 recipes/pyobjus/meta.yaml create mode 100644 recipes/pyobjus/patches/mobile.patch diff --git a/.appveyor.yml b/.appveyor.yml index 285de3c3..31a1ad42 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -17,21 +17,20 @@ environment: MOBILE_FORGE_CACHE_DOWNLOADS_OFF: 1 matrix: - - job_name: 'Android: jq' + - job_name: 'Android: pyjnius' job_group: build_android FORGE_ARCH: android FORGE_PACKAGES: >- - flet-libjq:1.7.1 - jq:1.8.0 + flet-libpyjni:1.0.1 + pyjnius:1.6.1 BUILD_NUMBER: 1 - - job_name: 'iOS: jq' - job_group: build_ios - FORGE_ARCH: iOS - FORGE_PACKAGES: >- - flet-libjq:1.7.1 - jq:1.8.0 - BUILD_NUMBER: 1 + # - job_name: 'iOS: pyobjus' + # job_group: build_ios + # FORGE_ARCH: iOS + # FORGE_PACKAGES: >- + # pyobjus:1.2.3 + # BUILD_NUMBER: 1 # ================================================== diff --git a/recipes/flet-libpyjni/build.sh b/recipes/flet-libpyjni/build.sh new file mode 100755 index 00000000..fb46ea3c --- /dev/null +++ b/recipes/flet-libpyjni/build.sh @@ -0,0 +1,22 @@ +#!/bin/bash +set -eu + +mkdir build +cd build + +if [ $CROSS_VENV_SDK == "android" ]; then + cmake .. \ + -DCMAKE_SYSTEM_NAME=Android \ + -DANDROID_PLATFORM=$SDK_VERSION \ + -DANDROID_ABI=$ANDROID_ABI \ + -DCMAKE_TOOLCHAIN_FILE=$NDK_ROOT/build/cmake/android.toolchain.cmake \ + -DCMAKE_BUILD_TYPE=Release \ + -DBUILD_SHARED_LIBS=1 \ + -DCMAKE_INSTALL_PREFIX="$PREFIX" +else + echo "flet-libpyjni library can be built for Android only." + exit 1 +fi + +make -j $CPU_COUNT +make install \ No newline at end of file diff --git a/recipes/flet-libpyjni/meta.yaml b/recipes/flet-libpyjni/meta.yaml new file mode 100644 index 00000000..aaf13d64 --- /dev/null +++ b/recipes/flet-libpyjni/meta.yaml @@ -0,0 +1,13 @@ +package: + name: flet-libpyjni + version: 1.0.1 + +build: + number: 1 + +source: + url: https://github.com/flet-dev/libpyjni/releases/download/v1.0.1/pyjni-1.0.1.tar.gz + +requirements: + build: + - cmake \ No newline at end of file diff --git a/recipes/pyjnius/meta.yaml b/recipes/pyjnius/meta.yaml new file mode 100644 index 00000000..26c42351 --- /dev/null +++ b/recipes/pyjnius/meta.yaml @@ -0,0 +1,10 @@ +package: + name: pyjnius + version: 1.6.1 + +patches: + - mobile.patch + +requirements: + host: + - flet-libpyjni 1.0.1 \ No newline at end of file diff --git a/recipes/pyjnius/patches/mobile.patch b/recipes/pyjnius/patches/mobile.patch new file mode 100644 index 00000000..2c3e83cd --- /dev/null +++ b/recipes/pyjnius/patches/mobile.patch @@ -0,0 +1,140 @@ +diff --git a/jnius/env.py b/jnius/env.py +index ea12d82..4111845 100644 +--- a/jnius/env.py ++++ b/jnius/env.py +@@ -288,7 +288,7 @@ class MacOsXJavaLocation(UnixJavaLocation): + + class AndroidJavaLocation(UnixJavaLocation): + def get_libraries(self): +- return ['SDL2', 'log'] ++ return ['log', 'pyjni'] + + def get_include_dirs(self): + # When cross-compiling for Android, we should not use the include dirs +diff --git a/jnius/jnius_conversion.pxi b/jnius/jnius_conversion.pxi +index 2e0b48d..e474445 100644 +--- a/jnius/jnius_conversion.pxi ++++ b/jnius/jnius_conversion.pxi +@@ -719,7 +719,7 @@ cdef jobject convert_pyarray_to_java(JNIEnv *j_env, definition, pyarray) except + + elif definition[0] == 'L': + defstr = str_for_c(definition[1:-1]) +- j_class = j_env[0].FindClass(j_env, defstr) ++ j_class = PyJni_FindClass(defstr) + + if j_class == NULL: + raise JavaException( +diff --git a/jnius/jnius_export_class.pxi b/jnius/jnius_export_class.pxi +index a688e2b..7018adf 100644 +--- a/jnius/jnius_export_class.pxi ++++ b/jnius/jnius_export_class.pxi +@@ -146,7 +146,7 @@ class MetaJavaClass(MetaJavaBase): + + if NULL == obj: + for interface in getattr(value, '__javainterfaces__', []): +- obj = j_env[0].FindClass(j_env, str_for_c(interface)) ++ obj = PyJni_FindClass(str_for_c(interface)) + if obj == NULL: + j_env[0].ExceptionClear(j_env) + elif 0 != j_env[0].IsAssignableFrom(j_env, obj, me.j_cls): +@@ -177,11 +177,11 @@ class MetaJavaClass(MetaJavaBase): + cdef JNIEnv *j_env = get_jnienv() + + if __javainterfaces__ and __javabaseclass__: +- baseclass = j_env[0].FindClass(j_env, __javabaseclass__) ++ baseclass = PyJni_FindClass(__javabaseclass__) + interfaces = malloc(sizeof(jclass) * len(__javainterfaces__)) + + for n, i in enumerate(__javainterfaces__): +- interfaces[n] = j_env[0].FindClass(j_env, i) ++ interfaces[n] = PyJni_FindClass(i) + + getProxyClass = j_env[0].GetStaticMethodID( + j_env, baseclass, "getProxyClass", +@@ -206,8 +206,7 @@ class MetaJavaClass(MetaJavaBase): + ' {0}'.format(__javaclass__)) + else: + class_name = str_for_c(__javaclass__) +- jcs.j_cls = j_env[0].FindClass(j_env, +- class_name) ++ jcs.j_cls = PyJni_FindClass(class_name) + if jcs.j_cls == NULL: + raise JavaException('Unable to find the class' + ' {0}'.format(__javaclass__)) +diff --git a/jnius/jnius_export_func.pxi b/jnius/jnius_export_func.pxi +index 3a76dd5..c3e1375 100644 +--- a/jnius/jnius_export_func.pxi ++++ b/jnius/jnius_export_func.pxi +@@ -18,7 +18,7 @@ def find_javaclass(namestr): + cdef jclass jc + cdef JNIEnv *j_env = get_jnienv() + +- jc = j_env[0].FindClass(j_env, name) ++ jc = PyJni_FindClass(name) + check_exception(j_env) + + cls = Class(noinstance=True) +diff --git a/jnius/jnius_jvm_android.pxi b/jnius/jnius_jvm_android.pxi +index dae6b31..17fe0e2 100644 +--- a/jnius/jnius_jvm_android.pxi ++++ b/jnius/jnius_jvm_android.pxi +@@ -1,6 +1,7 @@ + # on android, rely on SDL to get the JNI env +-cdef extern JNIEnv *SDL_AndroidGetJNIEnv() ++cdef extern JNIEnv *PyJni_AndroidGetJNIEnv() + ++cdef extern jclass *PyJni_FindClass(const char* className) + + cdef JNIEnv *get_platform_jnienv() except NULL: +- return SDL_AndroidGetJNIEnv() ++ return PyJni_AndroidGetJNIEnv() +diff --git a/jnius/jnius_utils.pxi b/jnius/jnius_utils.pxi +index ef5d6ab..a6edb0c 100644 +--- a/jnius/jnius_utils.pxi ++++ b/jnius/jnius_utils.pxi +@@ -164,14 +164,14 @@ cdef void check_assignable_from_str(JNIEnv *env, source, target) except *: + return + + s_source = str_for_c(source) +- cls_source = env[0].FindClass(env, s_source) ++ cls_source = PyJni_FindClass(s_source) + + if cls_source == NULL: + raise JavaException('Unable to find the class for {0!r}'.format( + source)) + + s_target = str_for_c(target) +- cls_target = env[0].FindClass(env, s_target) ++ cls_target = PyJni_FindClass(s_target) + + if cls_target == NULL: + raise JavaException('Unable to find the class for {0!r}'.format( +@@ -238,7 +238,7 @@ cdef void check_assignable_from(JNIEnv *env, JavaClass jc, signature) except *: + # we got an object that doesn't match with the signature + # check if we can use it. + s = str_for_c(signature) +- cls = env[0].FindClass(env, s) ++ cls = PyJni_FindClass(s) + if cls == NULL: + raise JavaException('Unable to found the class for {0!r}'.format( + signature)) +diff --git a/setup.py b/setup.py +index 3cca8c1..a7f40f0 100644 +--- a/setup.py ++++ b/setup.py +@@ -54,14 +54,7 @@ PXI_FILES = [ + EXTRA_LINK_ARGS = [] + + # detect Python for android +-PLATFORM = sys.platform +-NDKPLATFORM = getenv('NDKPLATFORM') +-if NDKPLATFORM is not None and getenv('LIBLINK'): +- PLATFORM = 'android' +- +-# detect platform +-if PLATFORM == 'android': +- PYX_FILES = [fn[:-3] + 'c' for fn in PYX_FILES] ++PLATFORM = 'android' + + JAVA=get_java_setup(PLATFORM) + diff --git a/recipes/pyobjus/meta.yaml b/recipes/pyobjus/meta.yaml new file mode 100644 index 00000000..7ac0dc55 --- /dev/null +++ b/recipes/pyobjus/meta.yaml @@ -0,0 +1,10 @@ +package: + name: pyobjus + version: 1.2.3 + +patches: + - mobile.patch + +requirements: + host: + - libffi \ No newline at end of file diff --git a/recipes/pyobjus/patches/mobile.patch b/recipes/pyobjus/patches/mobile.patch new file mode 100644 index 00000000..ba16e9f0 --- /dev/null +++ b/recipes/pyobjus/patches/mobile.patch @@ -0,0 +1,86 @@ +diff --git a/pyobjus/_runtime.h b/pyobjus/_runtime.h +index c31b7ba..6d0cf85 100644 +--- a/pyobjus/_runtime.h ++++ b/pyobjus/_runtime.h +@@ -1,6 +1,6 @@ + #include + #include +-#include ++#include + #include + #include + #include +diff --git a/pyobjus/common.pxi b/pyobjus/common.pxi +index 3a17bbb..4f43c6a 100644 +--- a/pyobjus/common.pxi ++++ b/pyobjus/common.pxi +@@ -109,7 +109,7 @@ cdef extern from "objc/runtime.h": + objc_method_description* protocol_copyMethodDescriptionList(Protocol *p, BOOL isRequiredMethod, BOOL isInstanceMethod, unsigned int *outCount) + + +-cdef extern from "ffi/ffi.h": ++cdef extern from "ffi.h": + ctypedef unsigned long ffi_arg + ctypedef signed long ffi_sarg + ctypedef enum: FFI_TYPE_STRUCT +diff --git a/setup.py b/setup.py +index 0de7708..c8deb36 100644 +--- a/setup.py ++++ b/setup.py +@@ -20,13 +20,7 @@ if kivy_ios_root is not None: + print("Pyobjus platform is {}".format(dev_platform)) + + # OSX +-files = [] +-if dev_platform == 'darwin': +- files = ['pyobjus.pyx'] +-# iOS +-elif dev_platform == 'ios': +- files = ['pyobjus.c'] +- ++files = ['pyobjus.pyx'] + + class PyObjusBuildExt(build_ext, object): + +@@ -43,13 +37,10 @@ class PyObjusBuildExt(build_ext, object): + # The following essentially supply a dynamically generated subclass + # that mix in the cython version of build_ext so that the + # functionality provided will also be executed. +- if dev_platform != 'ios': +- from Cython.Distutils import build_ext as cython_build_ext +- build_ext_cls = type( +- 'PyObjusBuildExt', (PyObjusBuildExt, cython_build_ext), {}) +- return super(PyObjusBuildExt, cls).__new__(build_ext_cls) +- else: +- return super(PyObjusBuildExt, cls).__new__(cls) ++ from Cython.Distutils import build_ext as cython_build_ext ++ build_ext_cls = type( ++ 'PyObjusBuildExt', (PyObjusBuildExt, cython_build_ext), {}) ++ return super(PyObjusBuildExt, cls).__new__(build_ext_cls) + + def build_extensions(self): + # create a configuration file for pyobjus (export the platform) +@@ -57,11 +48,9 @@ class PyObjusBuildExt(build_ext, object): + config_pxi_need_update = True + config_pxi = 'DEF PLATFORM = "{}"\n'.format(dev_platform) + config_pxi += 'DEF ARCH = "{}"\n'.format(arch) +- if dev_platform == 'ios': +- cython3 = False # Assume Cython 0.29, which is what we use for kivy-ios (ATM) +- else: +- import Cython +- cython3 = Cython.__version__.startswith('3.') ++ ++ import Cython ++ cython3 = Cython.__version__.startswith('3.') + config_pxi += f"DEF PYOBJUS_CYTHON_3 = {cython3}" + if exists(config_pxi_fn): + with open(config_pxi_fn) as fd: +@@ -73,7 +62,7 @@ class PyObjusBuildExt(build_ext, object): + super().build_extensions() + + +-libraries = ['ffi'] ++libraries = ['ffi', 'objc'] + library_dirs = [] + extra_compile_args = [] + extra_link_args = [] From 7065352aa699b1cbc054c5d7c3be6277b2e72b79 Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Sat, 28 Dec 2024 11:10:11 -0800 Subject: [PATCH 052/142] regex for iOS and Android (#23) --- .appveyor.yml | 17 ++++++++--------- recipes/regex/meta.yaml | 3 +++ 2 files changed, 11 insertions(+), 9 deletions(-) create mode 100644 recipes/regex/meta.yaml diff --git a/.appveyor.yml b/.appveyor.yml index 31a1ad42..1134aa41 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -17,20 +17,19 @@ environment: MOBILE_FORGE_CACHE_DOWNLOADS_OFF: 1 matrix: - - job_name: 'Android: pyjnius' + - job_name: 'Android: regex' job_group: build_android FORGE_ARCH: android FORGE_PACKAGES: >- - flet-libpyjni:1.0.1 - pyjnius:1.6.1 + regex:2024.11.6 BUILD_NUMBER: 1 - # - job_name: 'iOS: pyobjus' - # job_group: build_ios - # FORGE_ARCH: iOS - # FORGE_PACKAGES: >- - # pyobjus:1.2.3 - # BUILD_NUMBER: 1 + - job_name: 'iOS: regex' + job_group: build_ios + FORGE_ARCH: iOS + FORGE_PACKAGES: >- + regex:2024.11.6 + BUILD_NUMBER: 1 # ================================================== diff --git a/recipes/regex/meta.yaml b/recipes/regex/meta.yaml new file mode 100644 index 00000000..60ef895d --- /dev/null +++ b/recipes/regex/meta.yaml @@ -0,0 +1,3 @@ +package: + name: regex + version: 2024.11.6 \ No newline at end of file From daeaa405a67ed01ed6d1a143eb871c95fde0dee1 Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Sat, 28 Dec 2024 11:11:14 -0800 Subject: [PATCH 053/142] zstandard for iOS and Android (#24) --- .appveyor.yml | 8 ++++---- recipes/zstandard/meta.yaml | 3 +++ 2 files changed, 7 insertions(+), 4 deletions(-) create mode 100644 recipes/zstandard/meta.yaml diff --git a/.appveyor.yml b/.appveyor.yml index 1134aa41..b48ae845 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -17,18 +17,18 @@ environment: MOBILE_FORGE_CACHE_DOWNLOADS_OFF: 1 matrix: - - job_name: 'Android: regex' + - job_name: 'Android: zstandard' job_group: build_android FORGE_ARCH: android FORGE_PACKAGES: >- - regex:2024.11.6 + zstandard:0.23.0 BUILD_NUMBER: 1 - - job_name: 'iOS: regex' + - job_name: 'iOS: zstandard' job_group: build_ios FORGE_ARCH: iOS FORGE_PACKAGES: >- - regex:2024.11.6 + zstandard:0.23.0 BUILD_NUMBER: 1 # ================================================== diff --git a/recipes/zstandard/meta.yaml b/recipes/zstandard/meta.yaml new file mode 100644 index 00000000..ac640897 --- /dev/null +++ b/recipes/zstandard/meta.yaml @@ -0,0 +1,3 @@ +package: + name: zstandard + version: 0.23.0 \ No newline at end of file From af8b4c6c218f6969b52bf5521d0d3a719fcd942a Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Sat, 28 Dec 2024 13:49:13 -0800 Subject: [PATCH 054/142] ruamel.yaml.clib for iOS and Android (#25) --- .appveyor.yml | 8 ++++---- recipes/ruamel.yaml.clib/meta.yaml | 3 +++ 2 files changed, 7 insertions(+), 4 deletions(-) create mode 100644 recipes/ruamel.yaml.clib/meta.yaml diff --git a/.appveyor.yml b/.appveyor.yml index b48ae845..414c79ef 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -17,18 +17,18 @@ environment: MOBILE_FORGE_CACHE_DOWNLOADS_OFF: 1 matrix: - - job_name: 'Android: zstandard' + - job_name: 'Android: ruamel.yaml.clib' job_group: build_android FORGE_ARCH: android FORGE_PACKAGES: >- - zstandard:0.23.0 + ruamel.yaml.clib:0.2.12 BUILD_NUMBER: 1 - - job_name: 'iOS: zstandard' + - job_name: 'iOS: ruamel.yaml.clib' job_group: build_ios FORGE_ARCH: iOS FORGE_PACKAGES: >- - zstandard:0.23.0 + ruamel.yaml.clib:0.2.12 BUILD_NUMBER: 1 # ================================================== diff --git a/recipes/ruamel.yaml.clib/meta.yaml b/recipes/ruamel.yaml.clib/meta.yaml new file mode 100644 index 00000000..2caa1ed0 --- /dev/null +++ b/recipes/ruamel.yaml.clib/meta.yaml @@ -0,0 +1,3 @@ +package: + name: ruamel.yaml.clib + version: 0.2.12 \ No newline at end of file From 3dfdca1ffa77b29de01b42df4e8e0a9f1d28ec52 Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Sun, 29 Dec 2024 15:29:31 -0800 Subject: [PATCH 055/142] pyxirr for iOS and Android (#26) * pyxirr for iOS and Android * Publish pyxirr --- .appveyor.yml | 8 ++++---- recipes/pyxirr/meta.yaml | 6 ++++++ recipes/pyxirr/patches/mobile.patch | 10 ++++++++++ 3 files changed, 20 insertions(+), 4 deletions(-) create mode 100644 recipes/pyxirr/meta.yaml create mode 100644 recipes/pyxirr/patches/mobile.patch diff --git a/.appveyor.yml b/.appveyor.yml index 414c79ef..e96993ed 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -17,18 +17,18 @@ environment: MOBILE_FORGE_CACHE_DOWNLOADS_OFF: 1 matrix: - - job_name: 'Android: ruamel.yaml.clib' + - job_name: 'Android: pyxirr' job_group: build_android FORGE_ARCH: android FORGE_PACKAGES: >- - ruamel.yaml.clib:0.2.12 + pyxirr:0.10.6 BUILD_NUMBER: 1 - - job_name: 'iOS: ruamel.yaml.clib' + - job_name: 'iOS: pyxirr' job_group: build_ios FORGE_ARCH: iOS FORGE_PACKAGES: >- - ruamel.yaml.clib:0.2.12 + pyxirr:0.10.6 BUILD_NUMBER: 1 # ================================================== diff --git a/recipes/pyxirr/meta.yaml b/recipes/pyxirr/meta.yaml new file mode 100644 index 00000000..aed575fc --- /dev/null +++ b/recipes/pyxirr/meta.yaml @@ -0,0 +1,6 @@ +package: + name: pyxirr + version: 0.10.6 + +patches: + - mobile.patch \ No newline at end of file diff --git a/recipes/pyxirr/patches/mobile.patch b/recipes/pyxirr/patches/mobile.patch new file mode 100644 index 00000000..ff5bf54f --- /dev/null +++ b/recipes/pyxirr/patches/mobile.patch @@ -0,0 +1,10 @@ +diff --git a/pyproject.toml b/pyproject.toml +index be1a7b7..7bda5b8 100644 +--- a/pyproject.toml ++++ b/pyproject.toml +@@ -1,4 +1,5 @@ + [project] ++version = "0.10.6" + name = "pyxirr" + description-content-type = "text/markdown; charset=UTF-8; variant=GFM" + requires-python = ">=3.7,<3.14" From 3fa3887054a656ea080c97aa6f5c573edc4fdb99 Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Mon, 30 Dec 2024 17:49:02 -0800 Subject: [PATCH 056/142] Pycryptodome fix (#27) * Re-publish pycryptodome(x) with patch enabled * Create mobile_chaquopy.patch * Re-build pycryptodome, pycryptodomex for iOS and Android --- recipes/pycryptodome/meta.yaml | 4 +- recipes/pycryptodome/patches/mobile.patch | 46 +++++++++++++--------- recipes/pycryptodomex/meta.yaml | 4 +- recipes/pycryptodomex/patches/mobile.patch | 46 +++++++++++++--------- 4 files changed, 60 insertions(+), 40 deletions(-) diff --git a/recipes/pycryptodome/meta.yaml b/recipes/pycryptodome/meta.yaml index 116bd62e..bf322325 100644 --- a/recipes/pycryptodome/meta.yaml +++ b/recipes/pycryptodome/meta.yaml @@ -2,5 +2,5 @@ package: name: pycryptodome version: 3.21.0 -# patches: -# - mobile.patch \ No newline at end of file +patches: + - mobile.patch \ No newline at end of file diff --git a/recipes/pycryptodome/patches/mobile.patch b/recipes/pycryptodome/patches/mobile.patch index 1a171b4c..08e26fe8 100644 --- a/recipes/pycryptodome/patches/mobile.patch +++ b/recipes/pycryptodome/patches/mobile.patch @@ -1,21 +1,31 @@ ---- aaa/lib/Crypto/Util/_raw_api.py 2024-09-30 18:09:41.000000000 +0000 -+++ src/lib/Crypto/Util/_raw_api.py 2024-10-23 16:10:01.744278766 +0000 -@@ -312,6 +312,18 @@ +diff --git a/lib/Crypto/Util/_raw_api.py b/lib/Crypto/Util/_raw_api.py +index e0065c3..3b14e00 100644 +--- a/lib/Crypto/Util/_raw_api.py ++++ b/lib/Crypto/Util/_raw_api.py +@@ -30,6 +30,7 @@ + + import os + import abc ++import pathlib + import sys + from Crypto.Util.py3compat import byte_string + from Crypto.Util._file_system import pycryptodome_filename +@@ -302,13 +303,17 @@ def load_pycryptodome_raw_lib(name, cdecl): + split = name.split(".") + dir_comps, basename = split[:-1], split[-1] + attempts = [] +- for ext in extension_suffixes: ++ for ext in extension_suffixes + [".fwork"]: + try: + filename = basename + ext + full_name = pycryptodome_filename(dir_comps, filename) + if not os.path.isfile(full_name): + attempts.append("Not found '%s'" % filename) + continue ++ if full_name.endswith(".fwork"): ++ with open(full_name, 'r') as f: ++ framework_binary = f.read().strip() ++ full_name = str(pathlib.Path(sys.executable).parent.joinpath(framework_binary)) return load_lib(full_name, cdecl) except OSError as exp: attempts.append("Cannot load '%s': %s" % (filename, str(exp))) -+ -+ # This technique will work both before and after the importer redesign in Chaquopy 6.3. -+ import pkgutil -+ import Crypto -+ for entry in Crypto.__path__: -+ importer = pkgutil.get_importer(entry) -+ try: -+ filename = importer.extract_if_changed(name.replace(".", "/") + ".so") -+ return load_lib(filename, cdecl) -+ except KeyError: -+ attempts.append("Trying importer for '%s'" % entry) -+ - raise OSError("Cannot load native module '%s': %s" % (name, ", ".join(attempts))) - - diff --git a/recipes/pycryptodomex/meta.yaml b/recipes/pycryptodomex/meta.yaml index 7c6f97a6..f8c10a89 100644 --- a/recipes/pycryptodomex/meta.yaml +++ b/recipes/pycryptodomex/meta.yaml @@ -2,5 +2,5 @@ package: name: pycryptodomex version: 3.21.0 -# patches: -# - mobile.patch \ No newline at end of file +patches: + - mobile.patch \ No newline at end of file diff --git a/recipes/pycryptodomex/patches/mobile.patch b/recipes/pycryptodomex/patches/mobile.patch index bc24fd23..b9d5f9a7 100644 --- a/recipes/pycryptodomex/patches/mobile.patch +++ b/recipes/pycryptodomex/patches/mobile.patch @@ -1,21 +1,31 @@ ---- aaa/lib/Cryptodome/Util/_raw_api.py 2024-09-30 18:09:41.000000000 +0000 -+++ src/lib/Cryptodome/Util/_raw_api.py 2024-10-23 16:10:01.744278766 +0000 -@@ -312,6 +312,18 @@ +diff --git a/lib/Cryptodome/Util/_raw_api.py b/lib/Cryptodome/Util/_raw_api.py +index e0065c3..3b14e00 100644 +--- a/lib/Cryptodome/Util/_raw_api.py ++++ b/lib/Cryptodome/Util/_raw_api.py +@@ -30,6 +30,7 @@ + + import os + import abc ++import pathlib + import sys + from Cryptodome.Util.py3compat import byte_string + from Cryptodome.Util._file_system import pycryptodome_filename +@@ -302,13 +303,17 @@ def load_pycryptodome_raw_lib(name, cdecl): + split = name.split(".") + dir_comps, basename = split[:-1], split[-1] + attempts = [] +- for ext in extension_suffixes: ++ for ext in extension_suffixes + [".fwork"]: + try: + filename = basename + ext + full_name = pycryptodome_filename(dir_comps, filename) + if not os.path.isfile(full_name): + attempts.append("Not found '%s'" % filename) + continue ++ if full_name.endswith(".fwork"): ++ with open(full_name, 'r') as f: ++ framework_binary = f.read().strip() ++ full_name = str(pathlib.Path(sys.executable).parent.joinpath(framework_binary)) return load_lib(full_name, cdecl) except OSError as exp: attempts.append("Cannot load '%s': %s" % (filename, str(exp))) -+ -+ # This technique will work both before and after the importer redesign in Chaquopy 6.3. -+ import pkgutil -+ import Cryptodome -+ for entry in Cryptodome.__path__: -+ importer = pkgutil.get_importer(entry) -+ try: -+ filename = importer.extract_if_changed(name.replace(".", "/") + ".so") -+ return load_lib(filename, cdecl) -+ except KeyError: -+ attempts.append("Trying importer for '%s'" % entry) -+ - raise OSError("Cannot load native module '%s': %s" % (name, ", ".join(attempts))) - - From 08b2521df70573d97e34853a3d24f6252d8c5f72 Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Sun, 5 Jan 2025 14:37:38 -0800 Subject: [PATCH 057/142] libsodium, libopaque (#28) * Build libsodium * flet-libsodium for Android and iOS * Move libsodium.so to the root of site-packages for iOS * libsodium, libopaque, liboprf --- .appveyor.yml | 12 +- recipes/flet-libopaque/build.sh | 13 ++ recipes/flet-libopaque/meta.yaml | 20 +++ recipes/flet-libopaque/patches/mobile.patch | 81 ++++++++++ recipes/flet-liboprf/build.sh | 12 ++ recipes/flet-liboprf/meta.yaml | 19 +++ recipes/flet-liboprf/patches/mobile.patch | 167 ++++++++++++++++++++ recipes/flet-libsodium/build.sh | 32 ++++ recipes/flet-libsodium/meta.yaml | 8 + src/forge/build.py | 19 ++- 10 files changed, 376 insertions(+), 7 deletions(-) create mode 100755 recipes/flet-libopaque/build.sh create mode 100644 recipes/flet-libopaque/meta.yaml create mode 100644 recipes/flet-libopaque/patches/mobile.patch create mode 100755 recipes/flet-liboprf/build.sh create mode 100644 recipes/flet-liboprf/meta.yaml create mode 100644 recipes/flet-liboprf/patches/mobile.patch create mode 100755 recipes/flet-libsodium/build.sh create mode 100644 recipes/flet-libsodium/meta.yaml diff --git a/.appveyor.yml b/.appveyor.yml index e96993ed..250a6b24 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -17,18 +17,22 @@ environment: MOBILE_FORGE_CACHE_DOWNLOADS_OFF: 1 matrix: - - job_name: 'Android: pyxirr' + - job_name: 'Android: flet-libsodium, flet-liboprf, flet-libopaque' job_group: build_android FORGE_ARCH: android FORGE_PACKAGES: >- - pyxirr:0.10.6 + flet-libsodium:1.0.20 + flet-liboprf:0.5.0 + flet-libopaque:0.99.8 BUILD_NUMBER: 1 - - job_name: 'iOS: pyxirr' + - job_name: 'iOS: flet-libsodium, flet-liboprf, flet-libopaque' job_group: build_ios FORGE_ARCH: iOS FORGE_PACKAGES: >- - pyxirr:0.10.6 + flet-libsodium:1.0.20 + flet-liboprf:0.5.0 + flet-libopaque:0.99.8 BUILD_NUMBER: 1 # ================================================== diff --git a/recipes/flet-libopaque/build.sh b/recipes/flet-libopaque/build.sh new file mode 100755 index 00000000..9df7f940 --- /dev/null +++ b/recipes/flet-libopaque/build.sh @@ -0,0 +1,13 @@ +#!/bin/bash +set -eu + +cd src +make -j $CPU_COUNT +make install + +rm -r $PREFIX/bin +rm -r $PREFIX/lib/*.a + +if [ $CROSS_VENV_SDK != "android" ]; then + mv $PREFIX/lib/libopaque.so $PREFIX/../libopaque.so +fi \ No newline at end of file diff --git a/recipes/flet-libopaque/meta.yaml b/recipes/flet-libopaque/meta.yaml new file mode 100644 index 00000000..17475b3a --- /dev/null +++ b/recipes/flet-libopaque/meta.yaml @@ -0,0 +1,20 @@ +{% set version = "0.99.8" %} + +package: + name: flet-libopaque + version: '{{ version }}' + +source: + url: https://github.com/stef/libopaque/archive/refs/tags/v{{ version }}.tar.gz + +requirements: + host: + - flet-libsodium 1.0.20 + - flet-liboprf 0.5.0 + +# build: +# script_env: +# CFLAGS: '-Qunused-arguments -Wno-unreachable-code' + +patches: + - mobile.patch \ No newline at end of file diff --git a/recipes/flet-libopaque/patches/mobile.patch b/recipes/flet-libopaque/patches/mobile.patch new file mode 100644 index 00000000..309ba605 --- /dev/null +++ b/recipes/flet-libopaque/patches/mobile.patch @@ -0,0 +1,81 @@ +diff --git a/src/makefile b/src/makefile +index 42e70bb..d2759e5 100644 +--- a/src/makefile ++++ b/src/makefile +@@ -6,34 +6,35 @@ CFLAGS?=-march=native -Wall -O2 -g -fstack-protector-strong -D_FORTIFY_SOURCE=2 + -Warray-bounds -fsanitize=bounds -fsanitize-undefined-trap-on-error -ftrapv $(DEFINES) + #-fstrict-flex-arrays + CFLAGS+= -std=c99 -fpic +-LDFLAGS=-g $(LIBS) ++LDFLAGS+=-g $(LIBS) + CC?=gcc + AEXT=a + SOVER=0 ++SOEXT=so + + AR?=ar + +-UNAME := $(shell uname -s) +-ARCH := $(shell uname -m) +-ifeq ($(UNAME),Darwin) +- SOEXT=dylib +- SOFLAGS=-Wl,-install_name,$(DESTDIR)$(PREFIX)/lib/libopaque.$(SOEXT) +-else +- CFLAGS+=-Wl,-z,defs -Wl,-z,relro -Wl,-z,noexecstack -Wl,-z,now \ +- -fsanitize=signed-integer-overflow -fsanitize-undefined-trap-on-error +- # -mbranch-protection=standard -fstrict-flex-arrays=3 +- SOEXT=so +- SOFLAGS=-Wl,-soname,libopaque.$(SOEXT).$(SOVER) +- ifeq ($(ARCH),x86_64) +- CFLAGS+=-fcf-protection=full +- endif +- +- ifeq ($(ARCH),parisc64) +- else ifeq ($(ARCH),parisc64) +- else +- CFLAGS+=-fstack-clash-protection +- endif +-endif ++# UNAME := $(shell uname -s) ++# ARCH := $(shell uname -m) ++# ifeq ($(UNAME),Darwin) ++# SOEXT=dylib ++# SOFLAGS=-Wl,-install_name,$(DESTDIR)$(PREFIX)/lib/libopaque.$(SOEXT) ++# else ++# CFLAGS+=-Wl,-z,defs -Wl,-z,relro -Wl,-z,noexecstack -Wl,-z,now \ ++# -fsanitize=signed-integer-overflow -fsanitize-undefined-trap-on-error ++# # -mbranch-protection=standard -fstrict-flex-arrays=3 ++# SOEXT=so ++# SOFLAGS=-Wl,-soname,libopaque.$(SOEXT).$(SOVER) ++# ifeq ($(ARCH),x86_64) ++# CFLAGS+=-fcf-protection=full ++# endif ++ ++# ifeq ($(ARCH),parisc64) ++# else ifeq ($(ARCH),parisc64) ++# else ++# CFLAGS+=-fstack-clash-protection ++# endif ++# endif + + SODIUM_NEWER_THAN_1_0_18 := $(shell pkgconf --atleast-version=1.0.19 libsodium; echo $$?) + ifeq ($(SODIUM_NEWER_THAN_1_0_18),1) +@@ -58,7 +59,7 @@ ifneq (, $(shell which pandoc)) + endif + + +-all: libopaque.$(SOEXT) libopaque.$(AEXT) tests utils/opaque $(MANPAGES) ++all: libopaque.$(SOEXT) libopaque.$(AEXT) + + debug: DEFINES=-DTRACE -DNORANDOM + debug: all +@@ -154,8 +155,7 @@ man-uninstall: + + $(DESTDIR)$(PREFIX)/lib/libopaque.$(SOEXT): libopaque.$(SOEXT) + mkdir -p $(DESTDIR)$(PREFIX)/lib +- cp $< $@.$(SOVER) +- ln -fs $@.$(SOVER) $@ ++ cp $< $@ + + $(DESTDIR)$(PREFIX)/lib/libopaque.$(AEXT): libopaque.$(AEXT) + mkdir -p $(DESTDIR)$(PREFIX)/lib diff --git a/recipes/flet-liboprf/build.sh b/recipes/flet-liboprf/build.sh new file mode 100755 index 00000000..5674236b --- /dev/null +++ b/recipes/flet-liboprf/build.sh @@ -0,0 +1,12 @@ +#!/bin/bash +set -eu + +cd src +make -j $CPU_COUNT +make install + +if [ $CROSS_VENV_SDK == "android" ]; then + rm -r $PREFIX/lib/*.a +else + rm -r $PREFIX/lib/*.so +fi \ No newline at end of file diff --git a/recipes/flet-liboprf/meta.yaml b/recipes/flet-liboprf/meta.yaml new file mode 100644 index 00000000..b9389643 --- /dev/null +++ b/recipes/flet-liboprf/meta.yaml @@ -0,0 +1,19 @@ +{% set version = "0.5.0" %} + +package: + name: flet-liboprf + version: '{{ version }}' + +source: + url: https://github.com/stef/liboprf/archive/refs/tags/v{{ version }}.tar.gz + +requirements: + host: + - flet-libsodium 1.0.20 + +build: + script_env: + CFLAGS: '-Qunused-arguments -Wno-unreachable-code' + +patches: + - mobile.patch \ No newline at end of file diff --git a/recipes/flet-liboprf/patches/mobile.patch b/recipes/flet-liboprf/patches/mobile.patch new file mode 100644 index 00000000..129897eb --- /dev/null +++ b/recipes/flet-liboprf/patches/mobile.patch @@ -0,0 +1,167 @@ +diff --git a/src/makefile b/src/makefile +index f7819af..4d4ae06 100644 +--- a/src/makefile ++++ b/src/makefile +@@ -7,33 +7,33 @@ CFLAGS?=-march=native -Wall -O2 -g \ + -fstack-protector-strong -fasynchronous-unwind-tables -fpic \ + -ftrapv -D_GLIBCXX_ASSERTIONS $(DEFINES) + +-LDFLAGS?=-lsodium -loprf-noiseXK -Lnoise_xk ++LDFLAGS_PRIVATE=$(LDFLAGS) -lsodium -loprf-noiseXK -Lnoise_xk + CC?=gcc + SOEXT?=so + STATICEXT?=a + SOVER=0 + +-UNAME := $(shell uname -s) +-ARCH := $(shell uname -m) +-ifeq ($(UNAME),Darwin) +- SOEXT=dylib +- SOFLAGS=-Wl,-install_name,$(DESTDIR)$(PREFIX)/lib/liboprf.$(SOEXT) +-else +- CFLAGS+=-Wl,-z,defs -Wl,-z,relro -Wl,-z,noexecstack -Wl,-z,now -Wtrampolines \ +- -fsanitize=signed-integer-overflow -fsanitize-undefined-trap-on-error +- #-fstrict-flex-arrays=3 -mbranch-protection=standard +- SOEXT=so +- SOFLAGS=-Wl,-soname,liboprf.$(SOEXT).$(SOVER) +- ifeq ($(ARCH),x86_64) +- CFLAGS+=-fcf-protection=full +- endif +- +- ifeq ($(ARCH),parisc64) +- else ifeq ($(ARCH),parisc64) +- else +- CFLAGS+=-fstack-clash-protection +- endif +-endif ++# UNAME := $(shell uname -s) ++# ARCH := $(shell uname -m) ++# ifeq ($(UNAME),Darwin) ++# SOEXT=dylib ++# SOFLAGS=-Wl,-install_name,$(DESTDIR)$(PREFIX)/lib/liboprf.$(SOEXT) ++# else ++# CFLAGS+=-Wl,-z,defs -Wl,-z,relro -Wl,-z,noexecstack -Wl,-z,now -Wtrampolines \ ++# -fsanitize=signed-integer-overflow -fsanitize-undefined-trap-on-error ++# #-fstrict-flex-arrays=3 -mbranch-protection=standard ++# SOEXT=so ++# SOFLAGS=-Wl,-soname,liboprf.$(SOEXT).$(SOVER) ++# ifeq ($(ARCH),x86_64) ++# CFLAGS+=-fcf-protection=full ++# endif ++ ++# ifeq ($(ARCH),parisc64) ++# else ifeq ($(ARCH),parisc64) ++# else ++# CFLAGS+=-fstack-clash-protection ++# endif ++# endif + + CFLAGS+=$(INCLUDES) + +@@ -55,16 +55,16 @@ asan: + else + CFLAGS+=-fstack-clash-protection + endif +-asan: LDFLAGS+= -fsanitize=address -static-libasan ++asan: LDFLAGS_PRIVATE+= -fsanitize=address -static-libasan + asan: all + + AR ?= ar + + liboprf.$(SOEXT): $(SOURCES) noise_xk/liboprf-noiseXK.$(SOEXT) +- $(CC) $(CFLAGS) -fPIC -shared $(SOFLAGS) -o $@ $^ $(LDFLAGS) ++ $(CC) $(CFLAGS) -fPIC -shared $(SOFLAGS) -o $@ $^ $(LDFLAGS_PRIVATE) + + liboprf-corrupt-dkg.$(SOEXT): $(SOURCES) noise_xk/liboprf-noiseXK.$(SOEXT) +- $(CC) $(CFLAGS) -DUNITTEST -DUNITTEST_CORRUPT -fPIC -shared $(SOFLAGS) -o $@ $^ $(LDFLAGS) ++ $(CC) $(CFLAGS) -DUNITTEST -DUNITTEST_CORRUPT -fPIC -shared $(SOFLAGS) -o $@ $^ $(LDFLAGS_PRIVATE) + + liboprf.$(STATICEXT): $(OBJECTS) + $(AR) rcs $@ $^ +@@ -98,8 +98,7 @@ uninstall-noiseXK: + + $(DESTDIR)$(PREFIX)/lib/liboprf.$(SOEXT): liboprf.$(SOEXT) + mkdir -p $(DESTDIR)$(PREFIX)/lib +- cp $< $@.$(SOVER) +- ln -sf $@.$(SOVER) $@ ++ cp $< $@ + + $(DESTDIR)$(PREFIX)/lib/liboprf.$(STATICEXT): liboprf.$(STATICEXT) + mkdir -p $(DESTDIR)$(PREFIX)/lib +diff --git a/src/noise_xk/makefile b/src/noise_xk/makefile +index 8d69ae9..b8fc7b9 100644 +--- a/src/noise_xk/makefile ++++ b/src/noise_xk/makefile +@@ -1,5 +1,5 @@ + PREFIX?=/usr/local +-LDFLAGS=-lsodium ++LDFLAGS_PRIVATE=$(LDFLAGS) -lsodium + SOURCES=src/Noise_XK.c src/XK.c + + CFLAGS += -Iinclude -I include/karmel -I include/karmel/minimal \ +@@ -17,26 +17,26 @@ SOEXT?=so + STATICEXT?=a + SOVER=0 + +-UNAME := $(shell uname -s) +-ARCH := $(shell uname -m) +-ifeq ($(UNAME),Darwin) +- SOEXT=dylib +- SOFLAGS=-Wl,-install_name,$(DESTDIR)$(PREFIX)/lib/liboprf-noiseXK.$(SOEXT) +-else +- ifeq ($(shell uname),Linux) +- CFLAGS += -Wl,--error-unresolved-symbols -Wl,-z,defs -Wl,-z,relro -Wl,-z,noexecstack +- SOEXT=so +- SOFLAGS=-Wl,-soname,liboprf-noiseXK.$(SOEXT).$(SOVER) +- endif +- ifeq ($(ARCH),x86_64) +- CFLAGS+=-fcf-protection=full +- endif +- ifeq ($(ARCH),parisc64) +- else ifeq ($(ARCH),parisc64) +- else +- CFLAGS+=-fstack-clash-protection +- endif +-endif ++# UNAME := $(shell uname -s) ++# ARCH := $(shell uname -m) ++# ifeq ($(UNAME),Darwin) ++# SOEXT=dylib ++# SOFLAGS=-Wl,-install_name,$(DESTDIR)$(PREFIX)/lib/liboprf-noiseXK.$(SOEXT) ++# else ++# ifeq ($(shell uname),Linux) ++# CFLAGS += -Wl,--error-unresolved-symbols -Wl,-z,defs -Wl,-z,relro -Wl,-z,noexecstack ++# SOEXT=so ++# SOFLAGS=-Wl,-soname,liboprf-noiseXK.$(SOEXT).$(SOVER) ++# endif ++# ifeq ($(ARCH),x86_64) ++# CFLAGS+=-fcf-protection=full ++# endif ++# ifeq ($(ARCH),parisc64) ++# else ifeq ($(ARCH),parisc64) ++# else ++# CFLAGS+=-fstack-clash-protection ++# endif ++# endif + + OBJS += $(patsubst %.c,%.o,$(SOURCES)) + +@@ -48,7 +48,7 @@ AR ?= ar + $(AR) rcs $@ $^ + + %.$(SOEXT): $(OBJS) +- $(CC) $(CFLAGS) -fPIC -shared $(SOFLAGS) -o $@ $^ $(LDFLAGS) ++ $(CC) $(CFLAGS) -fPIC -shared $(SOFLAGS) -o $@ $^ $(LDFLAGS_PRIVATE) + + clean: + rm -rf *.so *.a src/*.o +@@ -64,8 +64,7 @@ uninstall: $(DESTDIR)$(PREFIX)/lib/liboprf-noiseXK.$(SOEXT) $(DESTDIR)$(PREFIX)/ + + $(DESTDIR)$(PREFIX)/lib/liboprf-noiseXK.$(SOEXT): liboprf-noiseXK.$(SOEXT) + mkdir -p $(DESTDIR)$(PREFIX)/lib/ +- cp $< $@.$(SOVER) +- ln -sf $@.$(SOVER) $@ ++ cp $< $@ + + $(DESTDIR)$(PREFIX)/lib/liboprf-noiseXK.$(STATICEXT): liboprf-noiseXK.$(STATICEXT) + mkdir -p $(DESTDIR)$(PREFIX)/lib/ diff --git a/recipes/flet-libsodium/build.sh b/recipes/flet-libsodium/build.sh new file mode 100755 index 00000000..d59a4e14 --- /dev/null +++ b/recipes/flet-libsodium/build.sh @@ -0,0 +1,32 @@ +#!/bin/bash +set -eu + +if [ $CROSS_VENV_SDK != "android" ]; then + case $HOST_TRIPLET in + arm64-apple-ios) + HOST_TRIPLET=arm-apple-darwin23 + ;; + arm64-apple-ios-simulator) + HOST_TRIPLET=aarch64-apple-darwin23 + ;; + x86_64-apple-ios-simulator) + HOST_TRIPLET=x86_64-apple-darwin23 + ;; + *) + echo "Unknown host triplet: '$HOST_TRIPLET'" + exit 1 + ;; + esac +fi + +./configure --host=$HOST_TRIPLET --prefix=$PREFIX --disable-soname-versions +make -j $CPU_COUNT +make install + +rm -r $PREFIX/lib/{*.la,pkgconfig} + +if [ $CROSS_VENV_SDK == "android" ]; then + rm -r $PREFIX/lib/*.a +else + mv $PREFIX/lib/libsodium.dylib $PREFIX/../libsodium.so +fi \ No newline at end of file diff --git a/recipes/flet-libsodium/meta.yaml b/recipes/flet-libsodium/meta.yaml new file mode 100644 index 00000000..0b37a42b --- /dev/null +++ b/recipes/flet-libsodium/meta.yaml @@ -0,0 +1,8 @@ +{% set version = "1.0.20" %} + +package: + name: flet-libsodium + version: '{{ version }}' + +source: + url: https://github.com/jedisct1/libsodium/releases/download/{{ version }}-RELEASE/libsodium-{{ version }}.tar.gz \ No newline at end of file diff --git a/src/forge/build.py b/src/forge/build.py index c7de6b4b..152ef9a9 100644 --- a/src/forge/build.py +++ b/src/forge/build.py @@ -214,7 +214,10 @@ def prepare(self, clean=True): ) shutil.rmtree(self.build_path) - if os.getenv(f"MOBILE_FORGE_CACHE_DOWNLOADS_OFF") or not self.source_archive_path.is_file(): + if ( + os.getenv(f"MOBILE_FORGE_CACHE_DOWNLOADS_OFF") + or not self.source_archive_path.is_file() + ): log(self.log_file, f"\n[{self.cross_venv}] Download package sources") self.download_source() @@ -248,7 +251,11 @@ def compile_env(self, **kwargs) -> dict[str, str]: if ar and self.cross_venv.sdk == "android" else "strip" ) - + ranlib = ( + str(Path(ar).parent.joinpath("llvm-ranlib")) + if ar and self.cross_venv.sdk == "android" + else "ranlib" + ) cflags = self.cross_venv.sysconfig_data["CFLAGS"] cppflags = self.cross_venv.sysconfig_data["CPPFLAGS"] @@ -316,6 +323,7 @@ def compile_env(self, **kwargs) -> dict[str, str]: "CC": cc, "CXX": cxx, "STRIP": strip, + "RANLIB": ranlib, "CFLAGS": cflags, "CPPFLAGS": cppflags, "LDFLAGS": ldflags, @@ -650,7 +658,12 @@ def prepare(self, clean=True): # Install the build requirements in the build environment self.cross_venv.pip_install( self.log_file, - ["build", "wheel"] + (pyproject["build-system"]["requires"] if "build-system" in pyproject else []), + ["build", "wheel"] + + ( + pyproject["build-system"]["requires"] + if "build-system" in pyproject + else [] + ), paths=[Path.cwd() / "dist"], build=True, ) From a40e869d4343f7126887b40cf30f45266a967e6b Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Mon, 6 Jan 2025 10:20:42 -0800 Subject: [PATCH 058/142] pynacl for iOS and Android (#29) --- .appveyor.yml | 12 ++++-------- recipes/flet-libopaque/meta.yaml | 4 ---- recipes/pynacl/meta.yaml | 10 ++++++++++ recipes/pynacl/patches/mobile.patch | 23 +++++++++++++++++++++++ src/forge/cross.py | 1 + 5 files changed, 38 insertions(+), 12 deletions(-) create mode 100644 recipes/pynacl/meta.yaml create mode 100644 recipes/pynacl/patches/mobile.patch diff --git a/.appveyor.yml b/.appveyor.yml index 250a6b24..43df83a4 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -17,22 +17,18 @@ environment: MOBILE_FORGE_CACHE_DOWNLOADS_OFF: 1 matrix: - - job_name: 'Android: flet-libsodium, flet-liboprf, flet-libopaque' + - job_name: 'Android: PyNaCl' job_group: build_android FORGE_ARCH: android FORGE_PACKAGES: >- - flet-libsodium:1.0.20 - flet-liboprf:0.5.0 - flet-libopaque:0.99.8 + pynacl:1.5.0 BUILD_NUMBER: 1 - - job_name: 'iOS: flet-libsodium, flet-liboprf, flet-libopaque' + - job_name: 'iOS: PyNaCl' job_group: build_ios FORGE_ARCH: iOS FORGE_PACKAGES: >- - flet-libsodium:1.0.20 - flet-liboprf:0.5.0 - flet-libopaque:0.99.8 + pynacl:1.5.0 BUILD_NUMBER: 1 # ================================================== diff --git a/recipes/flet-libopaque/meta.yaml b/recipes/flet-libopaque/meta.yaml index 17475b3a..3fe3c907 100644 --- a/recipes/flet-libopaque/meta.yaml +++ b/recipes/flet-libopaque/meta.yaml @@ -12,9 +12,5 @@ requirements: - flet-libsodium 1.0.20 - flet-liboprf 0.5.0 -# build: -# script_env: -# CFLAGS: '-Qunused-arguments -Wno-unreachable-code' - patches: - mobile.patch \ No newline at end of file diff --git a/recipes/pynacl/meta.yaml b/recipes/pynacl/meta.yaml new file mode 100644 index 00000000..b2df7a2f --- /dev/null +++ b/recipes/pynacl/meta.yaml @@ -0,0 +1,10 @@ +package: + name: PyNaCl + version: 1.5.0 + +requirements: + host: + - flet-libsodium 1.0.20 + +patches: + - mobile.patch \ No newline at end of file diff --git a/recipes/pynacl/patches/mobile.patch b/recipes/pynacl/patches/mobile.patch new file mode 100644 index 00000000..24d54087 --- /dev/null +++ b/recipes/pynacl/patches/mobile.patch @@ -0,0 +1,23 @@ +diff --git a/setup.py b/setup.py +index 96d4b32..045314f 100644 +--- a/setup.py ++++ b/setup.py +@@ -29,7 +29,6 @@ from setuptools import Distribution, setup + from setuptools.command.build_clib import build_clib as _build_clib + from setuptools.command.build_ext import build_ext as _build_ext + +- + requirements = [] + setup_requirements = ["setuptools"] + test_requirements = [ +@@ -218,8 +217,8 @@ setup( + package_data={"nacl": ["py.typed"]}, + ext_package="nacl", + cffi_modules=["src/bindings/build.py:ffi"], +- cmdclass={"build_clib": build_clib, "build_ext": build_ext}, +- distclass=Distribution, ++ # cmdclass={"build_ext": build_ext}, ++ # distclass=Distribution, + zip_safe=False, + classifiers=[ + "Programming Language :: Python :: Implementation :: CPython", diff --git a/src/forge/cross.py b/src/forge/cross.py index 0bd77b29..ab4361d6 100644 --- a/src/forge/cross.py +++ b/src/forge/cross.py @@ -483,6 +483,7 @@ def pip_install( if paths else [] ) + + (["--extra-index-url", "https://pypi.flet.dev"]) # Finally, the list of packages to install. + packages, ) From ee3fe3dfca8079f43e8244fcfb339eddcfc00ec9 Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Mon, 6 Jan 2025 11:03:15 -0800 Subject: [PATCH 059/142] sqlalchemy for iOS and Android (#30) --- .appveyor.yml | 8 ++++---- recipes/sqlalchemy/meta.yaml | 3 +++ 2 files changed, 7 insertions(+), 4 deletions(-) create mode 100644 recipes/sqlalchemy/meta.yaml diff --git a/.appveyor.yml b/.appveyor.yml index 43df83a4..95b9d64a 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -17,18 +17,18 @@ environment: MOBILE_FORGE_CACHE_DOWNLOADS_OFF: 1 matrix: - - job_name: 'Android: PyNaCl' + - job_name: 'Android: sqlalchemy' job_group: build_android FORGE_ARCH: android FORGE_PACKAGES: >- - pynacl:1.5.0 + sqlalchemy:2.0.36 BUILD_NUMBER: 1 - - job_name: 'iOS: PyNaCl' + - job_name: 'iOS: sqlalchemy' job_group: build_ios FORGE_ARCH: iOS FORGE_PACKAGES: >- - pynacl:1.5.0 + sqlalchemy:2.0.36 BUILD_NUMBER: 1 # ================================================== diff --git a/recipes/sqlalchemy/meta.yaml b/recipes/sqlalchemy/meta.yaml new file mode 100644 index 00000000..3b52fe59 --- /dev/null +++ b/recipes/sqlalchemy/meta.yaml @@ -0,0 +1,3 @@ +package: + name: sqlalchemy + version: 2.0.36 \ No newline at end of file From 97161787d97a097592b0ee81f6772c4eeb9f9403 Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Thu, 16 Jan 2025 16:28:54 -0800 Subject: [PATCH 060/142] pysodium, opaque (#31) * Publish pysodium, opaque * Fix flet-liboprf * Remove noise_xk/liboprf-noiseXK dep from a library --- .appveyor.yml | 8 ++++---- recipes/flet-liboprf/patches/mobile.patch | 6 +++--- recipes/opaque/meta.yaml | 7 +++++++ recipes/pysodium/meta.yaml | 7 +++++++ src/forge/build.py | 17 ++++++++--------- 5 files changed, 29 insertions(+), 16 deletions(-) create mode 100644 recipes/opaque/meta.yaml create mode 100644 recipes/pysodium/meta.yaml diff --git a/.appveyor.yml b/.appveyor.yml index 95b9d64a..30181733 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -17,18 +17,18 @@ environment: MOBILE_FORGE_CACHE_DOWNLOADS_OFF: 1 matrix: - - job_name: 'Android: sqlalchemy' + - job_name: 'Android: flet-liboprf' job_group: build_android FORGE_ARCH: android FORGE_PACKAGES: >- - sqlalchemy:2.0.36 + flet-liboprf:0.5.0 BUILD_NUMBER: 1 - - job_name: 'iOS: sqlalchemy' + - job_name: 'iOS: flet-liboprf' job_group: build_ios FORGE_ARCH: iOS FORGE_PACKAGES: >- - sqlalchemy:2.0.36 + flet-liboprf:0.5.0 BUILD_NUMBER: 1 # ================================================== diff --git a/recipes/flet-liboprf/patches/mobile.patch b/recipes/flet-liboprf/patches/mobile.patch index 129897eb..c11515ea 100644 --- a/recipes/flet-liboprf/patches/mobile.patch +++ b/recipes/flet-liboprf/patches/mobile.patch @@ -1,5 +1,5 @@ diff --git a/src/makefile b/src/makefile -index f7819af..4d4ae06 100644 +index f7819af..b76083f 100644 --- a/src/makefile +++ b/src/makefile @@ -7,33 +7,33 @@ CFLAGS?=-march=native -Wall -O2 -g \ @@ -70,11 +70,11 @@ index f7819af..4d4ae06 100644 liboprf.$(SOEXT): $(SOURCES) noise_xk/liboprf-noiseXK.$(SOEXT) - $(CC) $(CFLAGS) -fPIC -shared $(SOFLAGS) -o $@ $^ $(LDFLAGS) -+ $(CC) $(CFLAGS) -fPIC -shared $(SOFLAGS) -o $@ $^ $(LDFLAGS_PRIVATE) ++ $(CC) $(CFLAGS) -fPIC -shared $(SOFLAGS) -o $@ $(SOURCES) $(LDFLAGS_PRIVATE) liboprf-corrupt-dkg.$(SOEXT): $(SOURCES) noise_xk/liboprf-noiseXK.$(SOEXT) - $(CC) $(CFLAGS) -DUNITTEST -DUNITTEST_CORRUPT -fPIC -shared $(SOFLAGS) -o $@ $^ $(LDFLAGS) -+ $(CC) $(CFLAGS) -DUNITTEST -DUNITTEST_CORRUPT -fPIC -shared $(SOFLAGS) -o $@ $^ $(LDFLAGS_PRIVATE) ++ $(CC) $(CFLAGS) -DUNITTEST -DUNITTEST_CORRUPT -fPIC -shared $(SOFLAGS) -o $@ $(SOURCES) $(LDFLAGS_PRIVATE) liboprf.$(STATICEXT): $(OBJECTS) $(AR) rcs $@ $^ diff --git a/recipes/opaque/meta.yaml b/recipes/opaque/meta.yaml new file mode 100644 index 00000000..3e1b6f63 --- /dev/null +++ b/recipes/opaque/meta.yaml @@ -0,0 +1,7 @@ +package: + name: opaque + version: 0.2.0 + +requirements: + host: + - flet-libopaque 0.99.8 \ No newline at end of file diff --git a/recipes/pysodium/meta.yaml b/recipes/pysodium/meta.yaml new file mode 100644 index 00000000..823a2cab --- /dev/null +++ b/recipes/pysodium/meta.yaml @@ -0,0 +1,7 @@ +package: + name: pysodium + version: 0.7.18 + +requirements: + host: + - flet-libsodium 1.0.20 \ No newline at end of file diff --git a/src/forge/build.py b/src/forge/build.py index 152ef9a9..b356bb66 100644 --- a/src/forge/build.py +++ b/src/forge/build.py @@ -432,18 +432,17 @@ def write_message_file(self, filename: Path, data): generator.Generator(f, maxheaderlen=0).flatten(msg) def fix_wheel(self, wheel_dir: Path): - if self.cross_venv.sdk != "android": - return log(self.log_file, f"[{self.cross_venv}] Fixing wheel contents") - env = self.compile_env() + if self.cross_venv.sdk == "android": + env = self.compile_env() - for so in wheel_dir.glob("**/*.so"): - log(self.log_file, f"[{self.cross_venv}] Stripping {so}") - self.cross_venv.run( - self.log_file, - [env["STRIP"], "--strip-unneeded", str(so)], - ) + for so in wheel_dir.glob("**/*.so"): + log(self.log_file, f"[{self.cross_venv}] Stripping {so}") + self.cross_venv.run( + self.log_file, + [env["STRIP"], "--strip-unneeded", str(so)], + ) # add missing requirements from "host" if len(self.package.meta["requirements"]["host"]): From 1a0dad0e011d260dd3ae67bfb795a3d4552e09fa Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Mon, 17 Feb 2025 09:51:01 -0800 Subject: [PATCH 061/142] Numpy and other Meson-built packages fix for iOS (#32) * Fix Meson-built packages * Re-publish numpy 1.26.4 and 2.2.2 * contourpy:1.3.1 for iOS and Android * Update pandas, matplotlib * Fix matplotlib for Android --- .appveyor.yml | 10 ++++++---- recipes/contourpy/meta.yaml | 3 ++- recipes/matplotlib/meta.yaml | 12 ++++++++++-- recipes/numpy/meta.yaml | 9 ++++++++- recipes/numpy/patches/mobile-1.26.4.patch | 13 +++++++++++++ recipes/numpy/patches/mobile-2.2.2.patch | 13 +++++++++++++ recipes/pandas/meta.yaml | 3 ++- recipes/pandas/patches/mobile.patch | 8 ++++---- 8 files changed, 58 insertions(+), 13 deletions(-) create mode 100644 recipes/numpy/patches/mobile-1.26.4.patch create mode 100644 recipes/numpy/patches/mobile-2.2.2.patch diff --git a/.appveyor.yml b/.appveyor.yml index 30181733..1470a4b3 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -17,18 +17,20 @@ environment: MOBILE_FORGE_CACHE_DOWNLOADS_OFF: 1 matrix: - - job_name: 'Android: flet-liboprf' + - job_name: 'Android: pandas, matplotlib' job_group: build_android FORGE_ARCH: android FORGE_PACKAGES: >- - flet-liboprf:0.5.0 + pandas:2.2.3 + matplotlib:3.10.0 BUILD_NUMBER: 1 - - job_name: 'iOS: flet-liboprf' + - job_name: 'iOS: pandas, matplotlib' job_group: build_ios FORGE_ARCH: iOS FORGE_PACKAGES: >- - flet-liboprf:0.5.0 + pandas:2.2.3 + matplotlib:3.10.0 BUILD_NUMBER: 1 # ================================================== diff --git a/recipes/contourpy/meta.yaml b/recipes/contourpy/meta.yaml index 6c21d367..d00f6ec4 100644 --- a/recipes/contourpy/meta.yaml +++ b/recipes/contourpy/meta.yaml @@ -1,11 +1,12 @@ package: name: contourpy - version: 1.3.0 + version: 1.3.1 requirements: build: - ninja - cmake + - git+https://github.com/flet-dev/meson@ios-dynamiclib host: - pybind11 # {% if sdk == 'android' %} diff --git a/recipes/matplotlib/meta.yaml b/recipes/matplotlib/meta.yaml index cb1ff1ee..4df9c1cf 100644 --- a/recipes/matplotlib/meta.yaml +++ b/recipes/matplotlib/meta.yaml @@ -1,16 +1,24 @@ package: name: matplotlib - version: 3.9.2 + version: 3.10.0 requirements: build: - ninja + - git+https://github.com/flet-dev/meson@ios-dynamiclib host: - numpy ^2.0.0 - pybind11 - flet-libjpeg 3.0.90 build: +# {% if sdk == 'android' and arch in ['armeabi-v7a', 'x86'] %} + script_env: + CPPFLAGS: -Wno-c++11-narrowing +# {% endif %} backend-args: - -Csetup-args=--cross-file - - -Csetup-args={MESON_CROSS_FILE} \ No newline at end of file + - -Csetup-args={MESON_CROSS_FILE} + +# potential issues: +# https://github.com/godotengine/godot/pull/101036/files \ No newline at end of file diff --git a/recipes/numpy/meta.yaml b/recipes/numpy/meta.yaml index b7e30824..47bbde4f 100644 --- a/recipes/numpy/meta.yaml +++ b/recipes/numpy/meta.yaml @@ -3,12 +3,19 @@ package: name: numpy - version: 2.1.1 + version: 2.2.2 requirements: build: - ninja +patches: +{% if version and version < (2, 0) %} + - mobile-1.26.4.patch +{% else %} + - mobile-2.2.2.patch +{% endif %} + build: script_env: NPY_DISABLE_SVML: 1 diff --git a/recipes/numpy/patches/mobile-1.26.4.patch b/recipes/numpy/patches/mobile-1.26.4.patch new file mode 100644 index 00000000..12dde573 --- /dev/null +++ b/recipes/numpy/patches/mobile-1.26.4.patch @@ -0,0 +1,13 @@ +diff --git a/vendored-meson/meson/mesonbuild/linkers/linkers.py b/vendored-meson/meson/mesonbuild/linkers/linkers.py +index 7b3202c..2bf5e19 100644 +--- a/vendored-meson/meson/mesonbuild/linkers/linkers.py ++++ b/vendored-meson/meson/mesonbuild/linkers/linkers.py +@@ -767,7 +767,7 @@ def get_allow_undefined_args(self) -> T.List[str]: + return self._apply_prefix('-undefined,dynamic_lookup') + + def get_std_shared_module_args(self, options: 'KeyedOptionDictType') -> T.List[str]: +- return ['-bundle'] + self._apply_prefix('-undefined,dynamic_lookup') ++ return ['-dynamiclib'] + self._apply_prefix('-undefined,dynamic_lookup') + + def get_pie_args(self) -> T.List[str]: + return [] diff --git a/recipes/numpy/patches/mobile-2.2.2.patch b/recipes/numpy/patches/mobile-2.2.2.patch new file mode 100644 index 00000000..77e972a1 --- /dev/null +++ b/recipes/numpy/patches/mobile-2.2.2.patch @@ -0,0 +1,13 @@ +diff --git a/vendored-meson/meson/mesonbuild/linkers/linkers.py b/vendored-meson/meson/mesonbuild/linkers/linkers.py +index 4eec82e..ca4586f 100644 +--- a/vendored-meson/meson/mesonbuild/linkers/linkers.py ++++ b/vendored-meson/meson/mesonbuild/linkers/linkers.py +@@ -761,7 +761,7 @@ def get_allow_undefined_args(self) -> T.List[str]: + return self._apply_prefix('-undefined,dynamic_lookup') + + def get_std_shared_module_args(self, options: 'KeyedOptionDictType') -> T.List[str]: +- return ['-bundle'] + self._apply_prefix('-undefined,dynamic_lookup') ++ return ['-dynamiclib'] + self._apply_prefix('-undefined,dynamic_lookup') + + def get_pie_args(self) -> T.List[str]: + return [] diff --git a/recipes/pandas/meta.yaml b/recipes/pandas/meta.yaml index 1cf6b707..1ca19b30 100644 --- a/recipes/pandas/meta.yaml +++ b/recipes/pandas/meta.yaml @@ -1,10 +1,11 @@ package: name: pandas - version: 2.2.2 + version: 2.2.3 requirements: build: - ninja + - git+https://github.com/flet-dev/meson@ios-dynamiclib host: - numpy ^2.0.0 # {% if sdk == 'android' %} diff --git a/recipes/pandas/patches/mobile.patch b/recipes/pandas/patches/mobile.patch index 74959289..7160a732 100644 --- a/recipes/pandas/patches/mobile.patch +++ b/recipes/pandas/patches/mobile.patch @@ -1,5 +1,5 @@ diff --git a/pyproject.toml b/pyproject.toml -index db9f055..3e3d399 100644 +index 238abd8..37de5c7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,8 +2,8 @@ @@ -8,8 +8,8 @@ index db9f055..3e3d399 100644 requires = [ - "meson-python==0.13.1", - "meson==1.2.1", -+ "meson-python>=0.15.0", ++ "meson-python==0.15.0", + #"meson==1.2.1", "wheel", - "Cython==3.0.5", # Note: sync with setup.py, environment.yml and asv.conf.json - # Force numpy higher than 2.0rc1, so that built wheels are compatible + "Cython~=3.0.5", # Note: sync with setup.py, environment.yml and asv.conf.json + # Force numpy higher than 2.0, so that built wheels are compatible From 77a2a548cdb27073d9209e7d7d87a6a41f07b6e1 Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Mon, 17 Feb 2025 09:52:38 -0800 Subject: [PATCH 062/142] greenlet:3.1.1 for iOS and Android (#33) --- .appveyor.yml | 10 ++++------ recipes/greenlet/meta.yaml | 9 +++++++++ 2 files changed, 13 insertions(+), 6 deletions(-) create mode 100644 recipes/greenlet/meta.yaml diff --git a/.appveyor.yml b/.appveyor.yml index 1470a4b3..ffd65acb 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -17,20 +17,18 @@ environment: MOBILE_FORGE_CACHE_DOWNLOADS_OFF: 1 matrix: - - job_name: 'Android: pandas, matplotlib' + - job_name: 'Android: greenlet' job_group: build_android FORGE_ARCH: android FORGE_PACKAGES: >- - pandas:2.2.3 - matplotlib:3.10.0 + greenlet:3.1.1 BUILD_NUMBER: 1 - - job_name: 'iOS: pandas, matplotlib' + - job_name: 'iOS: greenlet' job_group: build_ios FORGE_ARCH: iOS FORGE_PACKAGES: >- - pandas:2.2.3 - matplotlib:3.10.0 + greenlet:3.1.1 BUILD_NUMBER: 1 # ================================================== diff --git a/recipes/greenlet/meta.yaml b/recipes/greenlet/meta.yaml new file mode 100644 index 00000000..bdcaa310 --- /dev/null +++ b/recipes/greenlet/meta.yaml @@ -0,0 +1,9 @@ +package: + name: greenlet + version: 3.1.1 + +# {% if sdk != 'android' %} +build: + script_env: + CXXFLAGS: -std=c++14 +# {% endif %} \ No newline at end of file From 54cc83a005798d4ea57fa997d6d54dccbb94cda8 Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Mon, 17 Feb 2025 10:14:49 -0800 Subject: [PATCH 063/142] pandas 2.0.3 for iOS and Android (#34) --- recipes/pandas/meta.yaml | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/recipes/pandas/meta.yaml b/recipes/pandas/meta.yaml index 1ca19b30..c106cef5 100644 --- a/recipes/pandas/meta.yaml +++ b/recipes/pandas/meta.yaml @@ -2,6 +2,9 @@ package: name: pandas version: 2.2.3 +# {% if not version or version >= (2,1) %} +# pandas >= 2.1.0 + requirements: build: - ninja @@ -18,4 +21,13 @@ patches: build: backend-args: - -Csetup-args=--cross-file - - -Csetup-args={MESON_CROSS_FILE} \ No newline at end of file + - -Csetup-args={MESON_CROSS_FILE} + +# {% else %} +# pandas < 2.1.0 + +requirements: + host: + - numpy 1.26.4 + +# {% endif %} \ No newline at end of file From fcefe6de33ad1f96acdabb76507fe11e08f8967a Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Mon, 17 Feb 2025 10:31:02 -0800 Subject: [PATCH 064/142] pydantic-core 2.29.0 --- .appveyor.yml | 8 ++++---- recipes/pydantic-core/meta.yaml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index ffd65acb..c1d7e479 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -17,18 +17,18 @@ environment: MOBILE_FORGE_CACHE_DOWNLOADS_OFF: 1 matrix: - - job_name: 'Android: greenlet' + - job_name: 'Android: pydantic-core' job_group: build_android FORGE_ARCH: android FORGE_PACKAGES: >- - greenlet:3.1.1 + pydantic-core:2.29.0 BUILD_NUMBER: 1 - - job_name: 'iOS: greenlet' + - job_name: 'iOS: pydantic-core' job_group: build_ios FORGE_ARCH: iOS FORGE_PACKAGES: >- - greenlet:3.1.1 + pydantic-core:2.29.0 BUILD_NUMBER: 1 # ================================================== diff --git a/recipes/pydantic-core/meta.yaml b/recipes/pydantic-core/meta.yaml index 7081779d..03d11f57 100644 --- a/recipes/pydantic-core/meta.yaml +++ b/recipes/pydantic-core/meta.yaml @@ -1,6 +1,6 @@ package: name: pydantic-core - version: 2.23.3 + version: 2.29.0 build: script_env: From e619c87c74390d7ab952785db26efb3a18570dab Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Tue, 18 Feb 2025 15:00:42 -0800 Subject: [PATCH 065/142] Pillow 11.1.0 (#35) * Pillow 11.1.0 for iOS and Android * Fix pillow 11 for android * Disable platform guessing * Re-build pillow:11.1.0 for iOS and Android --- .appveyor.yml | 8 ++++---- recipes/pillow/meta.yaml | 15 +++++++++++++-- .../patches/{setup.patch => setup-10.x.patch} | 0 recipes/pillow/patches/setup-11.x.patch | 15 +++++++++++++++ 4 files changed, 32 insertions(+), 6 deletions(-) rename recipes/pillow/patches/{setup.patch => setup-10.x.patch} (100%) create mode 100644 recipes/pillow/patches/setup-11.x.patch diff --git a/.appveyor.yml b/.appveyor.yml index c1d7e479..8df9e548 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -17,18 +17,18 @@ environment: MOBILE_FORGE_CACHE_DOWNLOADS_OFF: 1 matrix: - - job_name: 'Android: pydantic-core' + - job_name: 'Android: pillow 11.1.0' job_group: build_android FORGE_ARCH: android FORGE_PACKAGES: >- - pydantic-core:2.29.0 + pillow:11.1.0 BUILD_NUMBER: 1 - - job_name: 'iOS: pydantic-core' + - job_name: 'iOS: pillow 11.1.0' job_group: build_ios FORGE_ARCH: iOS FORGE_PACKAGES: >- - pydantic-core:2.29.0 + pillow:11.1.0 BUILD_NUMBER: 1 # ================================================== diff --git a/recipes/pillow/meta.yaml b/recipes/pillow/meta.yaml index 91686fff..8f7cfb6a 100644 --- a/recipes/pillow/meta.yaml +++ b/recipes/pillow/meta.yaml @@ -1,6 +1,6 @@ package: name: Pillow - version: 10.4.0 + version: 11.1.0 requirements: host: @@ -8,8 +8,19 @@ requirements: - flet-libjpeg 3.0.90 - flet-libfreetype 2.13.3 +# {% if version and version >= (11,0,0) %} +# pillow >= 11.x + patches: - - setup.patch + - setup-11.x.patch + +# {% else %} +# pillow <= 10.x + +patches: + - setup-10.x.patch + +# {% endif %} # {% if sdk != 'android' %} build: diff --git a/recipes/pillow/patches/setup.patch b/recipes/pillow/patches/setup-10.x.patch similarity index 100% rename from recipes/pillow/patches/setup.patch rename to recipes/pillow/patches/setup-10.x.patch diff --git a/recipes/pillow/patches/setup-11.x.patch b/recipes/pillow/patches/setup-11.x.patch new file mode 100644 index 00000000..640dc1b6 --- /dev/null +++ b/recipes/pillow/patches/setup-11.x.patch @@ -0,0 +1,15 @@ +diff --git a/setup.py b/setup.py +index a85731d..fbbb5b6 100644 +--- a/setup.py ++++ b/setup.py +@@ -355,9 +355,7 @@ class pil_build_ext(build_ext): + return True if value in configuration.get(option, []) else None + + def initialize_options(self) -> None: +- self.disable_platform_guessing = self.check_configuration( +- "platform-guessing", "disable" +- ) ++ self.disable_platform_guessing = True + self.add_imaging_libs = "" + build_ext.initialize_options(self) + for x in self.feature: From 1435c0df145d4cfda1d30f21ebb0677c2ed710f4 Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Wed, 19 Feb 2025 16:28:52 -0800 Subject: [PATCH 066/142] tiktoken:0.9.0 for iOS and Android (#36) --- .appveyor.yml | 8 ++++---- recipes/tiktoken/meta.yaml | 7 +++++++ 2 files changed, 11 insertions(+), 4 deletions(-) create mode 100644 recipes/tiktoken/meta.yaml diff --git a/.appveyor.yml b/.appveyor.yml index 8df9e548..69aff8a9 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -17,18 +17,18 @@ environment: MOBILE_FORGE_CACHE_DOWNLOADS_OFF: 1 matrix: - - job_name: 'Android: pillow 11.1.0' + - job_name: 'Android: tiktoken 0.9.0' job_group: build_android FORGE_ARCH: android FORGE_PACKAGES: >- - pillow:11.1.0 + tiktoken:0.9.0 BUILD_NUMBER: 1 - - job_name: 'iOS: pillow 11.1.0' + - job_name: 'iOS: tiktoken 0.9.0' job_group: build_ios FORGE_ARCH: iOS FORGE_PACKAGES: >- - pillow:11.1.0 + tiktoken:0.9.0 BUILD_NUMBER: 1 # ================================================== diff --git a/recipes/tiktoken/meta.yaml b/recipes/tiktoken/meta.yaml new file mode 100644 index 00000000..88290fa3 --- /dev/null +++ b/recipes/tiktoken/meta.yaml @@ -0,0 +1,7 @@ +package: + name: tiktoken + version: 0.9.0 + +build: + script_env: + _PYTHON_SYSCONFIGDATA_NAME: '{sysconfigdata_name}' \ No newline at end of file From 96ed169c2927da6e28d8c6fee558289bf9d94a72 Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Wed, 19 Feb 2025 17:26:07 -0800 Subject: [PATCH 067/142] Tokenizers for iOS and Android (#37) * tokenizers 0.21.0 for iOS and Android * Re-build tokenizers for iOS --- .appveyor.yml | 16 ++++++++-------- recipes/tokenizers/meta.yaml | 7 +++++++ 2 files changed, 15 insertions(+), 8 deletions(-) create mode 100644 recipes/tokenizers/meta.yaml diff --git a/.appveyor.yml b/.appveyor.yml index 69aff8a9..2b5b579b 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -17,18 +17,18 @@ environment: MOBILE_FORGE_CACHE_DOWNLOADS_OFF: 1 matrix: - - job_name: 'Android: tiktoken 0.9.0' - job_group: build_android - FORGE_ARCH: android - FORGE_PACKAGES: >- - tiktoken:0.9.0 - BUILD_NUMBER: 1 + # - job_name: 'Android: tokenizers 0.21.0' + # job_group: build_android + # FORGE_ARCH: android + # FORGE_PACKAGES: >- + # tokenizers:0.21.0 + # BUILD_NUMBER: 1 - - job_name: 'iOS: tiktoken 0.9.0' + - job_name: 'iOS: tokenizers 0.21.0' job_group: build_ios FORGE_ARCH: iOS FORGE_PACKAGES: >- - tiktoken:0.9.0 + tokenizers:0.21.0 BUILD_NUMBER: 1 # ================================================== diff --git a/recipes/tokenizers/meta.yaml b/recipes/tokenizers/meta.yaml new file mode 100644 index 00000000..85322cf1 --- /dev/null +++ b/recipes/tokenizers/meta.yaml @@ -0,0 +1,7 @@ +package: + name: tokenizers + version: 0.21.0 + +build: + script_env: + _PYTHON_SYSCONFIGDATA_NAME: '{sysconfigdata_name}' \ No newline at end of file From 3c92c34a66774436746a34f78511a40bfd3681a5 Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Sat, 22 Feb 2025 17:50:22 -0800 Subject: [PATCH 068/142] zope.interface 7.2 for iOS and Android (#38) --- .appveyor.yml | 16 ++++++++-------- recipes/zope.interface/meta.yaml | 3 +++ 2 files changed, 11 insertions(+), 8 deletions(-) create mode 100644 recipes/zope.interface/meta.yaml diff --git a/.appveyor.yml b/.appveyor.yml index 2b5b579b..92a8f062 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -17,18 +17,18 @@ environment: MOBILE_FORGE_CACHE_DOWNLOADS_OFF: 1 matrix: - # - job_name: 'Android: tokenizers 0.21.0' - # job_group: build_android - # FORGE_ARCH: android - # FORGE_PACKAGES: >- - # tokenizers:0.21.0 - # BUILD_NUMBER: 1 + - job_name: 'Android: zope.interface 7.2' + job_group: build_android + FORGE_ARCH: android + FORGE_PACKAGES: >- + zope.interface:7.2 + BUILD_NUMBER: 1 - - job_name: 'iOS: tokenizers 0.21.0' + - job_name: 'iOS: zope.interface 7.2' job_group: build_ios FORGE_ARCH: iOS FORGE_PACKAGES: >- - tokenizers:0.21.0 + zope.interface:7.2 BUILD_NUMBER: 1 # ================================================== diff --git a/recipes/zope.interface/meta.yaml b/recipes/zope.interface/meta.yaml new file mode 100644 index 00000000..60fc6735 --- /dev/null +++ b/recipes/zope.interface/meta.yaml @@ -0,0 +1,3 @@ +package: + name: zope.interface + version: '7.2' \ No newline at end of file From 1640a39168f8e67777d2b42aa7c19feb7f0c2c20 Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Mon, 18 Aug 2025 20:36:10 -0700 Subject: [PATCH 069/142] bitarray 3.6.1 --- .appveyor.yml | 15 ++++----------- pyproject.toml | 4 ++-- recipes/bitarray/meta.yaml | 2 +- 3 files changed, 7 insertions(+), 14 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index 92a8f062..24de29a5 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -5,30 +5,23 @@ skip_branch_with_pr: true environment: PYTHON_VERSION: 3.12.7 PYTHON_SHORT_VERSION: 3.12 - CF_ACCESS_KEY_ID: - secure: +m1fzbrEPRecXKCCMn4uA781PAASzJSWAxuJj1c7ctLfWbi5oW4PMnowPK96XtQ5 - CF_SECRET_ACCESS_KEY: - secure: siQTjK+IAmy+zcTSO0d/dnyU/SHC52+gaW8xOT3GFqW8dyRAWr7YXtCU0QvlIC5MFVnbEmgDcDKqINaWN1iD5Cuuw/QAFsF1L/zDnQSvAtE= - CF_ENDPOINT_URL: - secure: lSQBfrqIXIOAYhA0NGej7Pfll1wOSKTTFwQCl8N8lvI22uI5CA/UjRKaqw6KlIZMcXvqTP1w11CVqC2CWnyM3hK857X2tAe8nkO8KT0DCzw= - CF_BUCKET_NAME: flet-simple GEMFURY_TOKEN: secure: trYGM65OQ1+HYnOYOe/NOHrofLpP3bz64nHwVWPJhiUIYll3MrrQd7ilFNp+zSkI MOBILE_FORGE_CACHE_DOWNLOADS_OFF: 1 matrix: - - job_name: 'Android: zope.interface 7.2' + - job_name: 'Android: bitarray 3.6.1' job_group: build_android FORGE_ARCH: android FORGE_PACKAGES: >- - zope.interface:7.2 + bitarray:3.6.1 BUILD_NUMBER: 1 - - job_name: 'iOS: zope.interface 7.2' + - job_name: 'iOS: bitarray 3.6.1' job_group: build_ios FORGE_ARCH: iOS FORGE_PACKAGES: >- - zope.interface:7.2 + bitarray:3.6.1 BUILD_NUMBER: 1 # ================================================== diff --git a/pyproject.toml b/pyproject.toml index ea7b5410..6dd11818 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -29,9 +29,9 @@ classifiers = [ dependencies = [ # Currently using a fork of crossenv to get iOS fixes. # Replace when/if these are merged and released. - #"crossenv @ git+https://github.com/flet-dev/crossenv@ios-support", + "crossenv @ git+https://github.com/flet-dev/crossenv@flet", #"crossenv @ git+https://github.com/freakboy3742/crossenv@f0f07129eb06ea16d180650a26a02df2b948b888", - "crossenv @ git+https://github.com/benfogle/crossenv@c801a526403a06f653939a0c45534d7703f9066f", + #"crossenv @ git+https://github.com/benfogle/crossenv", "httpx == 0.27.0", "Jinja2 == 3.1.3", "jsonschema == 4.21.1", diff --git a/recipes/bitarray/meta.yaml b/recipes/bitarray/meta.yaml index d1bff373..8f29ceac 100644 --- a/recipes/bitarray/meta.yaml +++ b/recipes/bitarray/meta.yaml @@ -1,3 +1,3 @@ package: name: bitarray - version: 2.9.2 + version: 3.6.1 From 2b16b20dfef6f2f6cc46dc7a9ceba6535a639dba Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Mon, 18 Aug 2025 20:40:07 -0700 Subject: [PATCH 070/142] Add apt update step to AppVeyor install Added 'sudo apt update' before installing sqlite3 in the AppVeyor CI configuration to ensure package lists are up to date and prevent installation errors. --- .appveyor.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.appveyor.yml b/.appveyor.yml index 24de29a5..d379a95b 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -189,6 +189,7 @@ for: NDK_VERSION: r27c install: + - sudo apt update - sudo apt install sqlite3 - . .ci/common.sh From 562c2d41bff772937425ba03258d219445fa328d Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Sun, 8 Feb 2026 20:55:34 -0800 Subject: [PATCH 071/142] pydantic-core 2.33.2 (#41) * bitarray 3.6.1 * Add apt update step to AppVeyor install Added 'sudo apt update' before installing sqlite3 in the AppVeyor CI configuration to ensure package lists are up to date and prevent installation errors. * pydantic-core 2.33.2 --- .appveyor.yml | 16 +++++----------- pyproject.toml | 4 ++-- recipes/bitarray/meta.yaml | 2 +- recipes/pydantic-core/meta.yaml | 2 +- 4 files changed, 9 insertions(+), 15 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index 92a8f062..39e4d247 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -5,30 +5,23 @@ skip_branch_with_pr: true environment: PYTHON_VERSION: 3.12.7 PYTHON_SHORT_VERSION: 3.12 - CF_ACCESS_KEY_ID: - secure: +m1fzbrEPRecXKCCMn4uA781PAASzJSWAxuJj1c7ctLfWbi5oW4PMnowPK96XtQ5 - CF_SECRET_ACCESS_KEY: - secure: siQTjK+IAmy+zcTSO0d/dnyU/SHC52+gaW8xOT3GFqW8dyRAWr7YXtCU0QvlIC5MFVnbEmgDcDKqINaWN1iD5Cuuw/QAFsF1L/zDnQSvAtE= - CF_ENDPOINT_URL: - secure: lSQBfrqIXIOAYhA0NGej7Pfll1wOSKTTFwQCl8N8lvI22uI5CA/UjRKaqw6KlIZMcXvqTP1w11CVqC2CWnyM3hK857X2tAe8nkO8KT0DCzw= - CF_BUCKET_NAME: flet-simple GEMFURY_TOKEN: secure: trYGM65OQ1+HYnOYOe/NOHrofLpP3bz64nHwVWPJhiUIYll3MrrQd7ilFNp+zSkI MOBILE_FORGE_CACHE_DOWNLOADS_OFF: 1 matrix: - - job_name: 'Android: zope.interface 7.2' + - job_name: 'Android: pydantic-core 2.33.2' job_group: build_android FORGE_ARCH: android FORGE_PACKAGES: >- - zope.interface:7.2 + pydantic-core:2.33.2 BUILD_NUMBER: 1 - - job_name: 'iOS: zope.interface 7.2' + - job_name: 'iOS: pydantic-core 2.33.2' job_group: build_ios FORGE_ARCH: iOS FORGE_PACKAGES: >- - zope.interface:7.2 + pydantic-core:2.33.2 BUILD_NUMBER: 1 # ================================================== @@ -196,6 +189,7 @@ for: NDK_VERSION: r27c install: + - sudo apt update - sudo apt install sqlite3 - . .ci/common.sh diff --git a/pyproject.toml b/pyproject.toml index ea7b5410..6dd11818 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -29,9 +29,9 @@ classifiers = [ dependencies = [ # Currently using a fork of crossenv to get iOS fixes. # Replace when/if these are merged and released. - #"crossenv @ git+https://github.com/flet-dev/crossenv@ios-support", + "crossenv @ git+https://github.com/flet-dev/crossenv@flet", #"crossenv @ git+https://github.com/freakboy3742/crossenv@f0f07129eb06ea16d180650a26a02df2b948b888", - "crossenv @ git+https://github.com/benfogle/crossenv@c801a526403a06f653939a0c45534d7703f9066f", + #"crossenv @ git+https://github.com/benfogle/crossenv", "httpx == 0.27.0", "Jinja2 == 3.1.3", "jsonschema == 4.21.1", diff --git a/recipes/bitarray/meta.yaml b/recipes/bitarray/meta.yaml index d1bff373..8f29ceac 100644 --- a/recipes/bitarray/meta.yaml +++ b/recipes/bitarray/meta.yaml @@ -1,3 +1,3 @@ package: name: bitarray - version: 2.9.2 + version: 3.6.1 diff --git a/recipes/pydantic-core/meta.yaml b/recipes/pydantic-core/meta.yaml index 03d11f57..009c58da 100644 --- a/recipes/pydantic-core/meta.yaml +++ b/recipes/pydantic-core/meta.yaml @@ -1,6 +1,6 @@ package: name: pydantic-core - version: 2.29.0 + version: 2.33.2 build: script_env: From 3eec84c2cd37d2bc3e12bb83941784ca3a53a853 Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Sun, 8 Feb 2026 20:59:35 -0800 Subject: [PATCH 072/142] jiter, rpds-py for iOS and Android (#42) * jiter, rpds-py for iOS and Android * bitarray 3.6.1 * Add apt update step to AppVeyor install Added 'sudo apt update' before installing sqlite3 in the AppVeyor CI configuration to ensure package lists are up to date and prevent installation errors. --- recipes/jiter/meta.yaml | 7 +++++++ recipes/rpds-py/meta.yaml | 7 +++++++ 2 files changed, 14 insertions(+) create mode 100644 recipes/jiter/meta.yaml create mode 100644 recipes/rpds-py/meta.yaml diff --git a/recipes/jiter/meta.yaml b/recipes/jiter/meta.yaml new file mode 100644 index 00000000..27a817c9 --- /dev/null +++ b/recipes/jiter/meta.yaml @@ -0,0 +1,7 @@ +package: + name: jiter + version: 0.8.2 + +build: + script_env: + _PYTHON_SYSCONFIGDATA_NAME: '{sysconfigdata_name}' \ No newline at end of file diff --git a/recipes/rpds-py/meta.yaml b/recipes/rpds-py/meta.yaml new file mode 100644 index 00000000..907a6484 --- /dev/null +++ b/recipes/rpds-py/meta.yaml @@ -0,0 +1,7 @@ +package: + name: rpds-py + version: 0.23.1 + +build: + script_env: + _PYTHON_SYSCONFIGDATA_NAME: '{sysconfigdata_name}' \ No newline at end of file From de207980e03a3e87f191f28f49337e5f7938d209 Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Sun, 8 Feb 2026 21:04:02 -0800 Subject: [PATCH 073/142] pymongo for iOS and Android (#43) --- recipes/pymongo/meta.yaml | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 recipes/pymongo/meta.yaml diff --git a/recipes/pymongo/meta.yaml b/recipes/pymongo/meta.yaml new file mode 100644 index 00000000..53d1369c --- /dev/null +++ b/recipes/pymongo/meta.yaml @@ -0,0 +1,3 @@ +package: + name: pymongo + version: 4.10.1 \ No newline at end of file From 66915b9d25dd2deb48aff3217e4ea0791edec200 Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Tue, 10 Feb 2026 11:24:48 -0800 Subject: [PATCH 074/142] Add Android wheel workflow; update Python URL Add a new GitHub Actions workflow (build-wheels.yml) to build Android wheels using cibuildwheel. The workflow sets up Python 3.12, JDK 17, and the Android SDK, downloads websockets-16.0 source, builds cp313 Android wheels for arm64_v8a and x86_64, and uploads the resulting .whl artifacts. Also update setup.sh to use the indygreg python-build-standalone release tag 20260203 in PYTHON_URL_PREFIX. --- .github/workflows/build-wheels.yml | 44 ++++++++++++++++++++++++++++++ setup.sh | 2 +- 2 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/build-wheels.yml diff --git a/.github/workflows/build-wheels.yml b/.github/workflows/build-wheels.yml new file mode 100644 index 00000000..a284ed67 --- /dev/null +++ b/.github/workflows/build-wheels.yml @@ -0,0 +1,44 @@ +name: wheels-android + +on: + push: + pull_request: + +jobs: + build_android_wheels: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: "3.12" # cibuildwheel runner python; not the target + + - name: Set up JDK + uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: "17" + + - name: Set up Android SDK + uses: android-actions/setup-android@v3 + + - name: Build Android wheels + env: + CIBW_PLATFORM: android + CIBW_BUILD: "cp313-android_*" + CIBW_ARCHS_ANDROID: "arm64_v8a x86_64" + ANDROID_API_LEVEL: "24" + run: | + wget https://files.pythonhosted.org/packages/04/24/4b2031d72e840ce4c1ccb255f693b15c334757fc50023e4db9537080b8c4/websockets-16.0.tar.gz + tar xf websockets-16.0.tar.gz + cd websockets-16.0 + python -m pip install -U pip cibuildwheel + cibuildwheel --output-dir wheelhouse + + - uses: actions/upload-artifact@v4 + with: + name: wheels-android + path: websockets-16.0/wheelhouse/*.whl \ No newline at end of file diff --git a/setup.sh b/setup.sh index bb0408a2..1ae4317d 100755 --- a/setup.sh +++ b/setup.sh @@ -28,7 +28,7 @@ PYTHON_VERSION=$1 read python_version_major python_version_minor < <(echo $PYTHON_VERSION | sed -E 's/^([0-9]+)\.([0-9]+).*/\1 \2/') PYTHON_VER=$python_version_major.$python_version_minor -PYTHON_URL_PREFIX=https://github.com/indygreg/python-build-standalone/releases/download/20241016/cpython-$PYTHON_VERSION+20241016 +PYTHON_URL_PREFIX=https://github.com/indygreg/python-build-standalone/releases/download/20260203/cpython-$PYTHON_VERSION+20260203 echo "Python version: $PYTHON_VERSION" echo "Python short version: $PYTHON_VER" From 71ca0c76c323b8eee5087b1502ab27e2e9a335d6 Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Tue, 10 Feb 2026 11:53:19 -0800 Subject: [PATCH 075/142] Make target lists and deps dynamic for platforms Refactor make_dep_wheels.py to read the VERSIONS file and derive dependencies and targets dynamically: add get_versions_path, get_dependencies and get_targets helpers, and update make_wheel/main to iterate discovered deps and platform-specific targets (including a special-case for Android host archs). Update setup.sh to only check armeabi-v7a and x86 Android device binaries when PYTHON_VER is 3.12 (keep x86_64 check unconditional) and add a trailing newline. Adjust src/forge/cross.py to introduce ANDROID_HOST_ARCHS (varying by Python version) and construct HOST_SDKS['android'] from that list to keep host SDK targets in sync with the wheel generation logic. --- make_dep_wheels.py | 71 ++++++++++++++++++++++++++++++++-------------- setup.sh | 20 +++++++------ src/forge/cross.py | 13 +++++---- 3 files changed, 68 insertions(+), 36 deletions(-) diff --git a/make_dep_wheels.py b/make_dep_wheels.py index 5c685d61..d994c99b 100644 --- a/make_dep_wheels.py +++ b/make_dep_wheels.py @@ -16,16 +16,7 @@ from pathlib import Path -def make_wheel(package, os_name, target): - """Create a target-specific wheel for a given package. - - Requires that PYTHON_APPLE_SUPPORT is set in the environment, and that variable - points to a completed support build. - - :param package: The name of the package to build (e.g., "BZip2") - :param os_name: The OS name to target (e.g., "iOS") - :param target: The target specifier (e.g., "iphoneos.arm64") - """ +def get_versions_path(os_name): support = Path( os.environ[ ( @@ -35,14 +26,58 @@ def make_wheel(package, os_name, target): ) ] ) - - versions_file = ( + return ( support / "support" / ".".join(sys.version.split(".")[:2]) / os_name / "VERSIONS" ) + + +def get_dependencies(os_name): + versions_file = get_versions_path(os_name) + dependencies = [] + with versions_file.open(encoding="utf-8") as f: + for line in f: + match = re.match(r"^([^:]+):\s+(.+)$", line.strip()) + if not match: + continue + key = match[1] + if ( + key.lower() == "python version" + or key.lower() == "build" + or key.lower().startswith("min ") + ): + continue + dependencies.append(key) + return dependencies + + +def get_targets(os_name): + if os_name == "android": + if sys.version_info[:2] == (3, 13): + return ["arm64-v8a", "x86_64"] + return ["arm64-v8a", "armeabi-v7a", "x86_64", "x86"] + return [ + "iphoneos.arm64", + "iphonesimulator.arm64", + "iphonesimulator.x86_64", + ] + + +def make_wheel(package, os_name, target): + """Create a target-specific wheel for a given package. + + Requires that PYTHON_APPLE_SUPPORT is set in the environment, and that variable + points to a completed support build. + + :param package: The name of the package to build (e.g., "BZip2") + :param os_name: The OS name to target (e.g., "iOS") + :param target: The target specifier (e.g., "iphoneos.arm64") + """ + support = get_versions_path(os_name).parents[3] + versions_file = get_versions_path(os_name) with versions_file.open(encoding="utf-8") as f: versions = f.read() @@ -136,13 +171,7 @@ def make_wheel(package, os_name, target): if __name__ == "__main__": os_name = sys.argv[1] - for target in { - "android": ["arm64-v8a", "armeabi-v7a", "x86_64", "x86"], - "iOS": [ - "iphoneos.arm64", - "iphonesimulator.arm64", - "iphonesimulator.x86_64", - ], - }[os_name]: - for dep in ["BZip2", "XZ", "libFFI", "OpenSSL"]: + dependencies = get_dependencies(os_name) + for target in get_targets(os_name): + for dep in dependencies: make_wheel(dep, os_name, target) diff --git a/setup.sh b/setup.sh index 1ae4317d..6105bc74 100755 --- a/setup.sh +++ b/setup.sh @@ -146,19 +146,21 @@ if [ ! -z "$MOBILE_FORGE_ANDROID_SUPPORT_PATH" ]; then return fi - if [ ! -e $MOBILE_FORGE_ANDROID_SUPPORT_PATH/install/android/armeabi-v7a/python-$PYTHON_VERSION/bin/python$PYTHON_VER ]; then - echo "MOBILE_FORGE_ANDROID_SUPPORT_PATH does not appear to contain a Python $PYTHON_VERSION Android armeabi-v7a device binary." - return - fi - if [ ! -e $MOBILE_FORGE_ANDROID_SUPPORT_PATH/install/android/x86_64/python-$PYTHON_VERSION/bin/python$PYTHON_VER ]; then echo "MOBILE_FORGE_ANDROID_SUPPORT_PATH does not appear to contain a Python $PYTHON_VERSION Android x86_64 device binary." return fi - if [ ! -e $MOBILE_FORGE_ANDROID_SUPPORT_PATH/install/android/x86/python-$PYTHON_VERSION/bin/python$PYTHON_VER ]; then - echo "MOBILE_FORGE_ANDROID_SUPPORT_PATH does not appear to contain a Python $PYTHON_VERSION Android x86 device binary." - return + if [ "$PYTHON_VER" = "3.12" ]; then + if [ ! -e $MOBILE_FORGE_ANDROID_SUPPORT_PATH/install/android/armeabi-v7a/python-$PYTHON_VERSION/bin/python$PYTHON_VER ]; then + echo "MOBILE_FORGE_ANDROID_SUPPORT_PATH does not appear to contain a Python $PYTHON_VERSION Android armeabi-v7a device binary." + return + fi + + if [ ! -e $MOBILE_FORGE_ANDROID_SUPPORT_PATH/install/android/x86/python-$PYTHON_VERSION/bin/python$PYTHON_VER ]; then + echo "MOBILE_FORGE_ANDROID_SUPPORT_PATH does not appear to contain a Python $PYTHON_VERSION Android x86 device binary." + return + fi fi echo "MOBILE_FORGE_ANDROID_SUPPORT_PATH: $MOBILE_FORGE_ANDROID_SUPPORT_PATH" @@ -184,4 +186,4 @@ echo " forge iphoneos:arm64 lru-dict" echo echo "Build all applicable versions of lru-dict for all iOS targets:" echo " forge iOS --all-versions lru-dict" -echo \ No newline at end of file +echo diff --git a/src/forge/cross.py b/src/forge/cross.py index ab4361d6..58926937 100644 --- a/src/forge/cross.py +++ b/src/forge/cross.py @@ -20,13 +20,14 @@ class CrossVEnv: "watchOS": "4.0", } + ANDROID_HOST_ARCHS = ( + ("arm64-v8a", "x86_64") + if sys.version_info[:2] == (3, 13) + else ("arm64-v8a", "armeabi-v7a", "x86_64", "x86") + ) + HOST_SDKS = { - "android": [ - ("android", "arm64-v8a"), - ("android", "armeabi-v7a"), - ("android", "x86_64"), - ("android", "x86"), - ], + "android": [("android", arch) for arch in ANDROID_HOST_ARCHS], "iOS": [ ("iphoneos", "arm64"), ("iphonesimulator", "arm64"), From 1648b824da5ef0aed8a9dcc768af7fabd658f4e5 Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Tue, 10 Feb 2026 12:06:59 -0800 Subject: [PATCH 076/142] Support platform-config sysconfig & iOS Add detection for sysconfig files under a new platform-config/- path in addition to the legacy lib/python3.x location. Prefer the legacy path if present, otherwise use the platform-config path and raise a clear error listing both tried locations. Also exempt iOS from the later file-existence check to avoid incorrectly failing when host sysconfig handling differs. --- src/forge/cross.py | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/forge/cross.py b/src/forge/cross.py index 58926937..85cbe109 100644 --- a/src/forge/cross.py +++ b/src/forge/cross.py @@ -270,11 +270,26 @@ def create( f"_sysconfigdata__{self.host_os.lower()}_{self.arch}-{self.sdk}" ) - host_sysconfig = ( + legacy_host_sysconfig = ( self.host_python_home / f"lib/python3.{sys.version_info.minor}" / f"{self.sysconfigdata_name}.py" ) + platform_config_host_sysconfig = ( + self.host_python_home + / "platform-config" + / f"{self.arch}-{self.sdk}" + / f"{self.sysconfigdata_name}.py" + ) + if legacy_host_sysconfig.is_file(): + host_sysconfig = legacy_host_sysconfig + elif platform_config_host_sysconfig.is_file(): + host_sysconfig = platform_config_host_sysconfig + else: + raise RuntimeError( + "Can't find host sysconfig. Tried: " + f"{legacy_host_sysconfig} and {platform_config_host_sysconfig}" + ) else: host_sysconfig = next( (self.host_python_home / f"lib/python3.{sys.version_info.minor}").glob( @@ -283,7 +298,7 @@ def create( ) self.sysconfigdata_name = host_sysconfig.stem - if not host_sysconfig.is_file(): + if self.host_os != "iOS" and not host_sysconfig.is_file(): raise RuntimeError(f"Can't find host sysconfig {host_sysconfig}") self.location = Path(location).resolve() if location else Path.cwd() From 7ddcbf63bffa3b5e4d3dcf9e99ce13911d01de62 Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Tue, 10 Feb 2026 12:59:57 -0800 Subject: [PATCH 077/142] Adjust Android cross identifiers and NDK_SYSROOT Apply Android host/target selection for Python >= 3.13 (changed equality checks to >=). Add ANDROID_PLATFORM_MACHINE and make _platform_identifier emit machine-based identifiers for android on Python >=3.13, while adding a new _tag_identifier to preserve the legacy sdk-version-arch tag for wheel tags. Switch _PYTHON_HOST_PLATFORM to use the tag identifier. Also export NDK_SYSROOT in the build environment so the toolchain sysroot is available during cross builds. These changes align cross-compilation identifiers with Python 3.13+ tagging and ensure the NDK sysroot is provided to build steps. --- make_dep_wheels.py | 2 +- src/forge/build.py | 5 ++++- src/forge/cross.py | 27 ++++++++++++++++++++++----- 3 files changed, 27 insertions(+), 7 deletions(-) diff --git a/make_dep_wheels.py b/make_dep_wheels.py index d994c99b..880b12a6 100644 --- a/make_dep_wheels.py +++ b/make_dep_wheels.py @@ -56,7 +56,7 @@ def get_dependencies(os_name): def get_targets(os_name): if os_name == "android": - if sys.version_info[:2] == (3, 13): + if sys.version_info[:2] >= (3, 13): return ["arm64-v8a", "x86_64"] return ["arm64-v8a", "armeabi-v7a", "x86_64", "x86"] return [ diff --git a/src/forge/build.py b/src/forge/build.py index b356bb66..3dbfa6b0 100644 --- a/src/forge/build.py +++ b/src/forge/build.py @@ -361,6 +361,7 @@ def compile_env(self, **kwargs) -> dict[str, str]: if self.cross_venv.sdk == "android": cc_parts = cc.split("/") env["NDK_ROOT"] = "/".join(cc_parts[: cc_parts.index("toolchains")]) + env["NDK_SYSROOT"] = str(Path(cc).parent.parent / "sysroot") env["ANDROID_ABI"] = self.cross_venv.arch env["HOST_TRIPLET"] = self.cross_venv.platform_triplet @@ -749,7 +750,9 @@ def _build(self): env = self.compile_env() # Set the cross host platform in the environment - env["_PYTHON_HOST_PLATFORM"] = self.cross_venv.platform_identifier + env["_PYTHON_HOST_PLATFORM"] = self.cross_venv._tag_identifier( + self.cross_venv.sdk, self.cross_venv.sdk_version, self.cross_venv.arch + ) meson_cross_file = self._create_meson_cross(env) diff --git a/src/forge/cross.py b/src/forge/cross.py index 85cbe109..3f53c1ba 100644 --- a/src/forge/cross.py +++ b/src/forge/cross.py @@ -22,7 +22,7 @@ class CrossVEnv: ANDROID_HOST_ARCHS = ( ("arm64-v8a", "x86_64") - if sys.version_info[:2] == (3, 13) + if sys.version_info[:2] >= (3, 13) else ("arm64-v8a", "armeabi-v7a", "x86_64", "x86") ) @@ -73,6 +73,12 @@ class CrossVEnv: "x86_64": "x86_64-linux-android", "x86": "i686-linux-android", } + ANDROID_PLATFORM_MACHINE = { + "arm64-v8a": "aarch64", + "armeabi-v7a": "arm", + "x86_64": "x86_64", + "x86": "i686", + } def __init__(self, sdk, sdk_version, arch): self.sdk = sdk @@ -84,7 +90,7 @@ def __init__(self, sdk, sdk_version, arch): }[self.sdk] self.platform_identifier = self._platform_identifier(sdk, sdk_version, arch) self.tag = ( - self._platform_identifier(sdk, sdk_version, arch) + self._tag_identifier(sdk, sdk_version, arch) .replace("-", "_") .replace(".", "_") ) @@ -228,9 +234,12 @@ def sdk_root(self) -> Path: @classmethod def _platform_identifier(self, sdk, version, arch): if sdk == "android": - if version is None: - version = 21 - identifier = f"{sdk}-{version}-{arch}" + if sys.version_info[:2] >= (3, 13): + identifier = f"{sdk}-{self.ANDROID_PLATFORM_MACHINE[arch]}" + else: + if version is None: + version = 21 + identifier = f"{sdk}-{version}-{arch}" elif sdk in {"iphoneos", "iphonesimulator"}: if version is None: version = "13.0" @@ -247,6 +256,14 @@ def _platform_identifier(self, sdk, version, arch): raise ValueError(f"Don't know how to build wheels for {sdk}") return identifier + @classmethod + def _tag_identifier(self, sdk, version, arch): + if sdk == "android": + if version is None: + version = 21 + return f"{sdk}-{version}-{arch}" + return self._platform_identifier(sdk, version, arch) + def create( self, location=None, From bb7f0db2180dbec0576722987b77fdd7dfe380cc Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Tue, 10 Feb 2026 13:15:22 -0800 Subject: [PATCH 078/142] Add Android NDK sysroot handling Detect and use an Android NDK sysroot for cross builds. Introduces ndk_sysroot and adds its usr/include to CFLAGS when present, and appends -L flags for ndk sysroot lib paths (usr/lib// or usr/lib/). Also make NDK_SYSROOT env prefer the discovered ndk_sysroot. Ensures proper include and library search paths for Android targets. --- src/forge/build.py | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/src/forge/build.py b/src/forge/build.py index 3dbfa6b0..dbad0e7b 100644 --- a/src/forge/build.py +++ b/src/forge/build.py @@ -258,6 +258,7 @@ def compile_env(self, **kwargs) -> dict[str, str]: ) cflags = self.cross_venv.sysconfig_data["CFLAGS"] cppflags = self.cross_venv.sysconfig_data["CPPFLAGS"] + ndk_sysroot = None # Add install root include if (install_root / "include").is_dir(): @@ -278,6 +279,10 @@ def compile_env(self, **kwargs) -> dict[str, str]: cflags += f" -I{self.cross_venv.sdk_root}/usr/include" cppflags += f" -mios-version-min={self.cross_venv.sdk_version}" + else: + ndk_sysroot = Path(cc).parent.parent / "sysroot" + if (ndk_sysroot / "usr" / "include").is_dir(): + cflags += f" -I{ndk_sysroot}/usr/include" ldflags = self.cross_venv.sysconfig_data["LDFLAGS"] @@ -288,6 +293,22 @@ def compile_env(self, **kwargs) -> dict[str, str]: if (install_root / "lib").is_dir(): ldflags += f" -L{install_root}/lib" + if self.cross_venv.sdk == "android" and ndk_sysroot: + ndk_triplet_lib = ( + ndk_sysroot + / "usr" + / "lib" + / self.cross_venv.platform_triplet + / str(self.cross_venv.sdk_version) + ) + ndk_arch_lib = ( + ndk_sysroot / "usr" / "lib" / self.cross_venv.platform_triplet + ) + if ndk_triplet_lib.is_dir(): + ldflags += f" -L{ndk_triplet_lib}" + elif ndk_arch_lib.is_dir(): + ldflags += f" -L{ndk_arch_lib}" + # cargo_ldflags = re.sub(r"-march=[\w-]+", "", ldflags) cargo_ldflags = " -L{}/lib".format(self.cross_venv.sysconfig_data["prefix"]) cargo_ldflags += " -C link-arg=-undefined -C link-arg=dynamic_lookup" @@ -361,7 +382,9 @@ def compile_env(self, **kwargs) -> dict[str, str]: if self.cross_venv.sdk == "android": cc_parts = cc.split("/") env["NDK_ROOT"] = "/".join(cc_parts[: cc_parts.index("toolchains")]) - env["NDK_SYSROOT"] = str(Path(cc).parent.parent / "sysroot") + env["NDK_SYSROOT"] = str( + ndk_sysroot or (Path(cc).parent.parent / "sysroot") + ) env["ANDROID_ABI"] = self.cross_venv.arch env["HOST_TRIPLET"] = self.cross_venv.platform_triplet From 6207849ca23f75f2b1f8d6e465588ad7c1f5b89d Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Tue, 10 Feb 2026 13:18:05 -0800 Subject: [PATCH 079/142] Adjust Pillow recipe version conditional Modify recipes/pillow/meta.yaml to apply the pillow >= 11.x conditional when no version is provided or when version >= 11.0.0 by changing the Jinja condition to `{% if not version or version >= (11,0,0) %}`. Also ensure a trailing newline at end of file. --- recipes/pillow/meta.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/recipes/pillow/meta.yaml b/recipes/pillow/meta.yaml index 8f7cfb6a..46c9fa48 100644 --- a/recipes/pillow/meta.yaml +++ b/recipes/pillow/meta.yaml @@ -8,7 +8,7 @@ requirements: - flet-libjpeg 3.0.90 - flet-libfreetype 2.13.3 -# {% if version and version >= (11,0,0) %} +# {% if not version or version >= (11,0,0) %} # pillow >= 11.x patches: @@ -28,4 +28,4 @@ build: # libfreetype references both libz and libbz2 # but doesn't link them into the static library LDFLAGS: -lz -lbz2 -# {% endif %} \ No newline at end of file +# {% endif %} From 37eb7421275b12ee39d748ed40d6b72aba2dfb83 Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Tue, 10 Feb 2026 13:38:56 -0800 Subject: [PATCH 080/142] Improve OpenSSL detection and requirement parsing recipes/flet-libcurl: make build.sh detect a usable OpenSSL under PLATLIB/opt (checks for headers and libssl/libcrypto) and fall back to PYTHON_PREFIX if not found; pass the chosen prefix to configure. Update meta.yaml to use a conditional >= openssl host requirement (commented template lines) and fix trailing newline. src/forge/build.py: safer requirement splitting (split max 1) and support explicit version specifiers (>=, <=, !=, ==, ~=, >, <) while preserving ^ and ~ handling by translating them to >= and ~= semantics. --- recipes/flet-libcurl/build.sh | 11 +++++++++-- recipes/flet-libcurl/meta.yaml | 6 ++++-- src/forge/build.py | 6 ++++-- 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/recipes/flet-libcurl/build.sh b/recipes/flet-libcurl/build.sh index f0b69969..be944abb 100755 --- a/recipes/flet-libcurl/build.sh +++ b/recipes/flet-libcurl/build.sh @@ -1,7 +1,14 @@ #!/bin/bash set -eu -./configure --host=$HOST_TRIPLET --prefix=$PREFIX --with-openssl=$PLATLIB/opt +OPENSSL_PREFIX="$PLATLIB/opt" +if [ ! -f "$OPENSSL_PREFIX/include/openssl/ssl.h" ] || \ + { [ ! -f "$OPENSSL_PREFIX/lib/libssl.a" ] && [ ! -f "$OPENSSL_PREFIX/lib/libssl.so" ]; } || \ + { [ ! -f "$OPENSSL_PREFIX/lib/libcrypto.a" ] && [ ! -f "$OPENSSL_PREFIX/lib/libcrypto.so" ]; }; then + OPENSSL_PREFIX="$PYTHON_PREFIX" +fi + +./configure --host=$HOST_TRIPLET --prefix=$PREFIX --with-openssl="$OPENSSL_PREFIX" make -j $CPU_COUNT make install @@ -10,4 +17,4 @@ rm -r $PREFIX/lib/{*.la,pkgconfig} if [ $CROSS_VENV_SDK == "android" ]; then rm -r $PREFIX/lib/*.a -fi \ No newline at end of file +fi diff --git a/recipes/flet-libcurl/meta.yaml b/recipes/flet-libcurl/meta.yaml index 39d732b3..9dba6cc6 100644 --- a/recipes/flet-libcurl/meta.yaml +++ b/recipes/flet-libcurl/meta.yaml @@ -12,8 +12,10 @@ build: requirements: host: - - openssl 3.0.15 + # {% if sdk in ['iphoneos', 'iphonesimulator'] %} + - openssl >=3.0.15 + # {% endif %} - flet-libpsl 0.21.5 patches: - - config.patch \ No newline at end of file + - config.patch diff --git a/src/forge/build.py b/src/forge/build.py index dbad0e7b..fad90892 100644 --- a/src/forge/build.py +++ b/src/forge/build.py @@ -64,8 +64,10 @@ def install_requirements(self, target): requirements = [] for requirement in self.package.meta["requirements"][target]: try: - package, version = requirement.split() - if version.startswith("^"): + package, version = requirement.split(maxsplit=1) + if version.startswith((">=", "<=", "!=", "==", "~=", ">", "<")): + specifier = f"{package}{version}" + elif version.startswith("^"): specifier = f"{package}>={version[1:]}" elif version.startswith("~"): specifier = f"{package}~={version[1:]}" From ecfa8f9f6bbbee88a20e711cbba8defc16961a9c Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Tue, 10 Feb 2026 14:20:35 -0800 Subject: [PATCH 081/142] Normalize wheel tags and bump NDK/libcpp versions Normalize wheel tags used when repacking wheels and centralize tag logic. Builder.fix_wheel now updates the WHEEL metadata Tag to use a forge-style wheel tag (via a new wheel_tag property) so repacked wheels use platform tags like android_24_arm64_v8a / ios_13_0_arm64_iphoneos. SimplePackageBuilder now uses wheel_tag when writing metadata, and PythonPackageBuilder provides a py-specific wheel_tag (cp3X-cp3X-). Also: bump flet-libcpp-shared package version to 27.3.13750724, relax contourpy's host dependency to "flet-libcpp-shared >=27.2.12479018", and update AppVeyor NDK_VERSION from r27c to r27d. --- .appveyor.yml | 2 +- recipes/contourpy/meta.yaml | 2 +- recipes/flet-libcpp-shared/meta.yaml | 2 +- src/forge/build.py | 21 ++++++++++++++++++++- 4 files changed, 23 insertions(+), 4 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index 39e4d247..9f2b2da4 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -186,7 +186,7 @@ for: environment: APPVEYOR_BUILD_WORKER_IMAGE: ubuntu-gce-c - NDK_VERSION: r27c + NDK_VERSION: r27d install: - sudo apt update diff --git a/recipes/contourpy/meta.yaml b/recipes/contourpy/meta.yaml index d00f6ec4..90690a02 100644 --- a/recipes/contourpy/meta.yaml +++ b/recipes/contourpy/meta.yaml @@ -10,7 +10,7 @@ requirements: host: - pybind11 # {% if sdk == 'android' %} - - flet-libcpp-shared 27.2.12479018 + - flet-libcpp-shared >=27.2.12479018 # {% endif %} build: diff --git a/recipes/flet-libcpp-shared/meta.yaml b/recipes/flet-libcpp-shared/meta.yaml index 12184be3..18055a6c 100644 --- a/recipes/flet-libcpp-shared/meta.yaml +++ b/recipes/flet-libcpp-shared/meta.yaml @@ -1,6 +1,6 @@ package: name: flet-libcpp-shared - version: 27.2.12479018 + version: 27.3.13750724 source: url: https://github.com/flet-dev/awesome-flet/archive/refs/heads/main.zip \ No newline at end of file diff --git a/src/forge/build.py b/src/forge/build.py index fad90892..c7778212 100644 --- a/src/forge/build.py +++ b/src/forge/build.py @@ -457,9 +457,23 @@ def write_message_file(self, filename: Path, data): with filename.open("w", encoding="utf-8") as f: generator.Generator(f, maxheaderlen=0).flatten(msg) + @property + def wheel_tag(self) -> str: + return f"py3-none-{self.cross_venv.tag}" + def fix_wheel(self, wheel_dir: Path): log(self.log_file, f"[{self.cross_venv}] Fixing wheel contents") + + # Normalize wheel tags to forge platform tags so repacked wheels use + # android_24_arm64_v8a / ios_13_0_arm64_iphoneos style platform tags. + wheel_metadata_path = next(wheel_dir.glob("*.dist-info")) / "WHEEL" + wheel_metadata = self.read_message_file(wheel_metadata_path) + if "Tag" in wheel_metadata: + del wheel_metadata["Tag"] + wheel_metadata["Tag"] = self.wheel_tag + self.write_message_file(wheel_metadata_path, wheel_metadata) + if self.cross_venv.sdk == "android": env = self.compile_env() @@ -551,7 +565,7 @@ def make_wheel(self): "Root-Is-Purelib": "false", "Generator": "mobile-forge", "Build": build_num, - "Tag": f"py3-none-{self.cross_venv.tag}", + "Tag": self.wheel_tag, }, ) self.write_message_file( @@ -656,6 +670,11 @@ def log_file_path(self) -> Path: / f"{self.package.name}-{self.package.version}-cp3{sys.version_info.minor}-{self.cross_venv.tag}.log" ) + @property + def wheel_tag(self) -> str: + py_tag = f"cp3{sys.version_info.minor}" + return f"{py_tag}-{py_tag}-{self.cross_venv.tag}" + def download_source_url(self): return get_pypi_source_urls(self.package.name)[self.package.version] From 2e061329f672b0e91270f63f10452370c91bbe4f Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Tue, 10 Feb 2026 14:33:54 -0800 Subject: [PATCH 082/142] Use meson dep & repair malformed shims Replace direct git dependency on a meson fork with the standard meson package in contourpy and pandas recipes (recipes/contourpy/meta.yaml, recipes/pandas/meta.yaml). In src/forge/build.py add handling to detect and repair a legacy malformed shim where the separator line was accidentally merged with Python code (e.g. "' '''import sys"). The builder now logs the repair and rewrites the shim with a proper separator line (and preserves any trailing suffix). Also small formatting/newline adjustments to shim writing were made to ensure correct output. --- recipes/contourpy/meta.yaml | 4 ++-- recipes/pandas/meta.yaml | 2 +- src/forge/build.py | 19 ++++++++++++++++++- 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/recipes/contourpy/meta.yaml b/recipes/contourpy/meta.yaml index 90690a02..b05eb7b8 100644 --- a/recipes/contourpy/meta.yaml +++ b/recipes/contourpy/meta.yaml @@ -6,7 +6,7 @@ requirements: build: - ninja - cmake - - git+https://github.com/flet-dev/meson@ios-dynamiclib + - meson host: - pybind11 # {% if sdk == 'android' %} @@ -16,4 +16,4 @@ requirements: build: backend-args: - -Csetup-args=--cross-file - - -Csetup-args={MESON_CROSS_FILE} \ No newline at end of file + - -Csetup-args={MESON_CROSS_FILE} diff --git a/recipes/pandas/meta.yaml b/recipes/pandas/meta.yaml index c106cef5..a5acaf71 100644 --- a/recipes/pandas/meta.yaml +++ b/recipes/pandas/meta.yaml @@ -8,7 +8,7 @@ package: requirements: build: - ninja - - git+https://github.com/flet-dev/meson@ios-dynamiclib + - meson host: - numpy ^2.0.0 # {% if sdk == 'android' %} diff --git a/src/forge/build.py b/src/forge/build.py index c7778212..3b6dbe44 100644 --- a/src/forge/build.py +++ b/src/forge/build.py @@ -104,10 +104,27 @@ def fix_host_tool_shims(self): [ "#!/bin/sh\n", "'''exec' {} \"$0\" \"$@\"\n".format(python_path), - "' '''\n", + "' '''\n\n", ] + lines[1:] ) + elif ( + len(lines) > 2 + and lines[0].strip() == "#!/bin/sh" + and lines[1].startswith("'''exec' ") + and lines[2].startswith("' '''") + and lines[2].strip() != "' '''" + ): + # Repair legacy malformed shim output where the separator line was + # accidentally merged with Python code (e.g. "' '''import sys"). + log(self.log_file, f"Repairing malformed host shim: {shim}") + suffix = lines[2][len("' '''") :] + repaired = [lines[0], lines[1], "' '''\n"] + if suffix: + repaired.append(suffix) + repaired += lines[3:] + with open(shim, "w") as f: + f.writelines(repaired) @abstractmethod def download_source_url(self): ... From e0e6c96a14c7984355238a5d22288be5523bf98e Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Tue, 10 Feb 2026 15:46:25 -0800 Subject: [PATCH 083/142] Replace meson git URL with meson package Update recipes/matplotlib/meta.yaml to remove the external git dependency (git+https://github.com/flet-dev/meson@ios-dynamiclib) and use the packaged "meson" build requirement instead. This simplifies dependency management and avoids relying on an external repository for the Meson build system during the matplotlib build. --- recipes/matplotlib/meta.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/recipes/matplotlib/meta.yaml b/recipes/matplotlib/meta.yaml index 4df9c1cf..f097cec1 100644 --- a/recipes/matplotlib/meta.yaml +++ b/recipes/matplotlib/meta.yaml @@ -5,7 +5,7 @@ package: requirements: build: - ninja - - git+https://github.com/flet-dev/meson@ios-dynamiclib + - meson host: - numpy ^2.0.0 - pybind11 From 86c5b305db479ad89dcd41ca23b83058a7cbfaf3 Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Tue, 10 Feb 2026 15:53:43 -0800 Subject: [PATCH 084/142] Add Mobile Forge CI workflow Add a new GitHub Actions workflow (mobile-forge.yml) to build and publish mobile Python wheels for Android and iOS. The workflow uses Python 3.12.7, defines a matrix with Android and iOS jobs (currently targeting pydantic-core 2.33.2), downloads prebuilt python-build support archives, installs toolchains (NDK on Android, Rust targets on both platforms), runs forge to build wheels, and publishes resulting wheels to PyPI (using GEMFURY_TOKEN). It also uploads log artifacts on success or failure. Environment variables and build settings (PYTHON_SHORT_VERSION, NDK_VERSION, MOBILE_FORGE_* paths) are configured in the workflow. --- .github/workflows/mobile-forge.yml | 120 +++++++++++++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 .github/workflows/mobile-forge.yml diff --git a/.github/workflows/mobile-forge.yml b/.github/workflows/mobile-forge.yml new file mode 100644 index 00000000..63d040ef --- /dev/null +++ b/.github/workflows/mobile-forge.yml @@ -0,0 +1,120 @@ +name: Mobile Forge CI + +on: + push: + pull_request: + workflow_dispatch: + +env: + PYTHON_VERSION: "3.12.7" + PYTHON_SHORT_VERSION: "3.12" + MOBILE_FORGE_CACHE_DOWNLOADS_OFF: "1" + NDK_VERSION: r27c + +jobs: + build: + name: ${{ matrix.job_name }} + runs-on: ${{ matrix.runner }} + strategy: + fail-fast: false + matrix: + include: + - job_name: "Android: pydantic-core 2.33.2" + runner: ubuntu-latest + forge_arch: android + forge_packages: "pydantic-core:2.33.2" + build_number: "1" + platform: android + - job_name: "iOS: pydantic-core 2.33.2" + runner: macos-latest + forge_arch: iOS + forge_packages: "pydantic-core:2.33.2" + build_number: "1" + platform: ios + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: ${{ env.PYTHON_VERSION }} + + - name: Build and publish wheels + shell: bash + env: + GEMFURY_TOKEN: ${{ secrets.GEMFURY_TOKEN }} + APPVEYOR_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number || '' }} + FORGE_ARCH: ${{ matrix.forge_arch }} + FORGE_PACKAGES: ${{ matrix.forge_packages }} + BUILD_NUMBER: ${{ matrix.build_number }} + PLATFORM: ${{ matrix.platform }} + run: | + set -euxo pipefail + + . .ci/common.sh + + if [[ "$PLATFORM" == "android" ]]; then + sudo apt-get update + sudo apt-get install -y sqlite3 + + python_android_dir="$HOME/projects/python-build/android" + curl -#OL "https://github.com/flet-dev/python-build/releases/download/v${PYTHON_SHORT_VERSION}/python-android-mobile-forge-${PYTHON_SHORT_VERSION}.tar.gz" + mkdir -p "$python_android_dir" + tar -xzf "python-android-mobile-forge-${PYTHON_SHORT_VERSION}.tar.gz" -C "$python_android_dir" + + .ci/install_ndk.sh + + curl https://sh.rustup.rs -sSf | sh -s -- -y + . "$HOME/.cargo/env" + export PATH="$PATH:$HOME/.cargo/bin" + rustup target add aarch64-linux-android + rustup target add arm-linux-androideabi + rustup target add x86_64-linux-android + rustup target add i686-linux-android + + export MOBILE_FORGE_ANDROID_SUPPORT_PATH="$python_android_dir" + else + python_ios_dir="$HOME/projects/python-build/darwin/Python-Apple-support" + curl -#OL "https://github.com/flet-dev/python-build/releases/download/v${PYTHON_SHORT_VERSION}/python-ios-mobile-forge-${PYTHON_SHORT_VERSION}.tar.gz" + mkdir -p "$python_ios_dir" + tar -xzf "python-ios-mobile-forge-${PYTHON_SHORT_VERSION}.tar.gz" -C "$python_ios_dir" + + curl https://sh.rustup.rs -sSf | sh -s -- -y + . "$HOME/.cargo/env" + export PATH="$PATH:$HOME/.cargo/bin" + rustup target add aarch64-apple-ios + rustup target add aarch64-apple-ios-sim + rustup target add x86_64-apple-ios + + export MOBILE_FORGE_IOS_SUPPORT_PATH="$python_ios_dir" + fi + + source ./setup.sh "$PYTHON_VERSION" + export PATH="$PATH:$HOME/.cargo/bin" + + IFS=' ' read -r -a packages <<< "$FORGE_PACKAGES" + for package in "${packages[@]}"; do + forge "$FORGE_ARCH" "$package:$BUILD_NUMBER" + done + + rm -f dist/bzip2-* dist/xz-* dist/openssl-* dist/libffi-* + + if compgen -G "dist/*.whl" > /dev/null; then + publish_to_pypi dist/*.whl + fi + + - name: Upload logs on success + if: ${{ success() && hashFiles('logs/*.log') != '' }} + uses: actions/upload-artifact@v4 + with: + name: ${{ matrix.platform }}-logs-${{ github.run_id }}-${{ github.run_attempt }} + path: logs/*.log + + - name: Upload errors on failure + if: ${{ failure() && hashFiles('errors/*.log') != '' }} + uses: actions/upload-artifact@v4 + with: + name: ${{ matrix.platform }}-errors-${{ github.run_id }}-${{ github.run_attempt }} + path: errors/*.log From 0c807d3d86f328bd27aabaf5be439f9de5dc5300 Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Tue, 10 Feb 2026 15:56:20 -0800 Subject: [PATCH 085/142] Export MOBILE_FORGE support path env vars Define and export MOBILE_FORGE_ANDROID_SUPPORT_PATH and MOBILE_FORGE_IOS_SUPPORT_PATH as empty strings in the mobile-forge GitHub Actions workflow. This ensures the variables are explicitly set (overriding any inherited values) before the platform-specific logic runs. --- .github/workflows/mobile-forge.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/mobile-forge.yml b/.github/workflows/mobile-forge.yml index 63d040ef..f4d51594 100644 --- a/.github/workflows/mobile-forge.yml +++ b/.github/workflows/mobile-forge.yml @@ -54,6 +54,8 @@ jobs: set -euxo pipefail . .ci/common.sh + export MOBILE_FORGE_ANDROID_SUPPORT_PATH="" + export MOBILE_FORGE_IOS_SUPPORT_PATH="" if [[ "$PLATFORM" == "android" ]]; then sudo apt-get update From fdbfa32dbcae7e0b90eb821cff7b6392ad72bf82 Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Tue, 10 Feb 2026 16:06:40 -0800 Subject: [PATCH 086/142] Support platform-config sysconfig and iOS handling Add a fallback search for host sysconfig under a new platform-config/- directory while preserving the legacy lib/python3.x path. The code now selects the first existing sysconfig file or raises a RuntimeError listing both attempted paths. Also rename the old variable to legacy_host_sysconfig and skip the final existence check for iOS hosts. --- src/forge/cross.py | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/forge/cross.py b/src/forge/cross.py index ab4361d6..30d78f48 100644 --- a/src/forge/cross.py +++ b/src/forge/cross.py @@ -269,11 +269,26 @@ def create( f"_sysconfigdata__{self.host_os.lower()}_{self.arch}-{self.sdk}" ) - host_sysconfig = ( + legacy_host_sysconfig = ( self.host_python_home / f"lib/python3.{sys.version_info.minor}" / f"{self.sysconfigdata_name}.py" ) + platform_config_host_sysconfig = ( + self.host_python_home + / "platform-config" + / f"{self.arch}-{self.sdk}" + / f"{self.sysconfigdata_name}.py" + ) + if legacy_host_sysconfig.is_file(): + host_sysconfig = legacy_host_sysconfig + elif platform_config_host_sysconfig.is_file(): + host_sysconfig = platform_config_host_sysconfig + else: + raise RuntimeError( + "Can't find host sysconfig. Tried: " + f"{legacy_host_sysconfig} and {platform_config_host_sysconfig}" + ) else: host_sysconfig = next( (self.host_python_home / f"lib/python3.{sys.version_info.minor}").glob( @@ -282,7 +297,7 @@ def create( ) self.sysconfigdata_name = host_sysconfig.stem - if not host_sysconfig.is_file(): + if self.host_os != "iOS" and not host_sysconfig.is_file(): raise RuntimeError(f"Can't find host sysconfig {host_sysconfig}") self.location = Path(location).resolve() if location else Path.cwd() From 9d72351b29c3b9e87c737f10c2d8b9c35f88681e Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Tue, 10 Feb 2026 16:07:59 -0800 Subject: [PATCH 087/142] Bump Python version in mobile CI to 3.12.12 Update .github/workflows/mobile-forge.yml to use PYTHON_VERSION 3.12.12 (was 3.12.7). This applies a patch-level upgrade to the Python runtime used by the mobile CI workflow while keeping PYTHON_SHORT_VERSION at 3.12, ensuring CI picks up the latest bug and security fixes. --- .github/workflows/mobile-forge.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/mobile-forge.yml b/.github/workflows/mobile-forge.yml index f4d51594..3b1ec87c 100644 --- a/.github/workflows/mobile-forge.yml +++ b/.github/workflows/mobile-forge.yml @@ -6,7 +6,7 @@ on: workflow_dispatch: env: - PYTHON_VERSION: "3.12.7" + PYTHON_VERSION: "3.12.12" PYTHON_SHORT_VERSION: "3.12" MOBILE_FORGE_CACHE_DOWNLOADS_OFF: "1" NDK_VERSION: r27c From 8930fdfa0dbd1d04e9e736c83d3626f6bd4fa103 Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Tue, 10 Feb 2026 16:08:51 -0800 Subject: [PATCH 088/142] Use PYTHON_SHORT_VERSION for setup-python Switch setup-python input to use ${env.PYTHON_SHORT_VERSION} instead of the full PYTHON_VERSION to provide the short MAJOR.MINOR Python spec (e.g. 3.11) required by actions/setup-python and avoid pinning to a specific patch version. --- .github/workflows/mobile-forge.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/mobile-forge.yml b/.github/workflows/mobile-forge.yml index 3b1ec87c..e9f1c7cd 100644 --- a/.github/workflows/mobile-forge.yml +++ b/.github/workflows/mobile-forge.yml @@ -39,7 +39,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v5 with: - python-version: ${{ env.PYTHON_VERSION }} + python-version: ${{ env.PYTHON_SHORT_VERSION }} - name: Build and publish wheels shell: bash From 97c080361c6a62c9ad06670fc13a28d99d5f0933 Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Tue, 10 Feb 2026 16:09:54 -0800 Subject: [PATCH 089/142] Update python-build-standalone URL to 20260203 Bump PYTHON_URL_PREFIX in setup.sh to use the indygreg/python-build-standalone release tagged 20260203 (updates the suffix from +20241016 to +20260203), so the installer fetches the newer prebuilt CPython artifacts. --- setup.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.sh b/setup.sh index bb0408a2..1ae4317d 100755 --- a/setup.sh +++ b/setup.sh @@ -28,7 +28,7 @@ PYTHON_VERSION=$1 read python_version_major python_version_minor < <(echo $PYTHON_VERSION | sed -E 's/^([0-9]+)\.([0-9]+).*/\1 \2/') PYTHON_VER=$python_version_major.$python_version_minor -PYTHON_URL_PREFIX=https://github.com/indygreg/python-build-standalone/releases/download/20241016/cpython-$PYTHON_VERSION+20241016 +PYTHON_URL_PREFIX=https://github.com/indygreg/python-build-standalone/releases/download/20260203/cpython-$PYTHON_VERSION+20260203 echo "Python version: $PYTHON_VERSION" echo "Python short version: $PYTHON_VER" From cc97b830b11fce063d3f705cde08904c43717c10 Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Tue, 10 Feb 2026 16:36:31 -0800 Subject: [PATCH 090/142] Use host sysconfig for PYO3 cross lib dir Adjust cross-build sysconfig handling for pyo3 on Apple platforms. Add a host_sysconfig attribute to CrossVEnv and set PYO3_CROSS_LIB_DIR to the host_sysconfig.parent (the directory containing _sysconfigdata__*.py), falling back to /lib when host_sysconfig is unavailable. Also comment out the recipe-level _PYTHON_SYSCONFIGDATA_NAME script_env entry. These changes address newer Apple support layouts that place sysconfig data outside the venv prefix/lib. --- recipes/pydantic-core/meta.yaml | 6 +++--- src/forge/build.py | 10 ++++++++-- src/forge/cross.py | 3 +++ 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/recipes/pydantic-core/meta.yaml b/recipes/pydantic-core/meta.yaml index 009c58da..91208b69 100644 --- a/recipes/pydantic-core/meta.yaml +++ b/recipes/pydantic-core/meta.yaml @@ -2,6 +2,6 @@ package: name: pydantic-core version: 2.33.2 -build: - script_env: - _PYTHON_SYSCONFIGDATA_NAME: '{sysconfigdata_name}' \ No newline at end of file +# build: +# script_env: +# _PYTHON_SYSCONFIGDATA_NAME: '{sysconfigdata_name}' \ No newline at end of file diff --git a/src/forge/build.py b/src/forge/build.py index 3b6dbe44..3734ef94 100644 --- a/src/forge/build.py +++ b/src/forge/build.py @@ -378,8 +378,14 @@ def compile_env(self, **kwargs) -> dict[str, str]: "PYO3_CROSS_PYTHON_VERSION": self.cross_venv.sysconfig_data[ "py_version_short" ], - "PYO3_CROSS_LIB_DIR": "{}/lib".format( - self.cross_venv.sysconfig_data["prefix"] + # pyo3 expects a directory containing _sysconfigdata__*.py. + # Newer Apple support layouts place this outside prefix/lib. + "PYO3_CROSS_LIB_DIR": str( + ( + self.cross_venv.host_sysconfig.parent + if self.cross_venv.host_sysconfig is not None + else Path(self.cross_venv.sysconfig_data["prefix"]) / "lib" + ) ), } env.update(kwargs) diff --git a/src/forge/cross.py b/src/forge/cross.py index 3f53c1ba..33a96340 100644 --- a/src/forge/cross.py +++ b/src/forge/cross.py @@ -105,6 +105,7 @@ def __init__(self, sdk, sdk_version, arch): self._scheme_paths = None self._install_root = None self._sdk_root = None + self.host_sysconfig = None def __str__(self): return self.venv_name @@ -315,6 +316,8 @@ def create( ) self.sysconfigdata_name = host_sysconfig.stem + self.host_sysconfig = host_sysconfig + if self.host_os != "iOS" and not host_sysconfig.is_file(): raise RuntimeError(f"Can't find host sysconfig {host_sysconfig}") From 2a13e1af99f69cbf0a044d3c70f0c5b37bee707d Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Wed, 11 Feb 2026 09:20:34 -0800 Subject: [PATCH 091/142] Add cibuildwheel Android workflow and matrix build Add a new GitHub Actions workflow (build-wheels-with-cibuildwheel.yml) to build Android wheels using cibuildwheel. Revamp build-wheels.yml into a matrix-based job that supports Android and iOS builds, parameterizes Python versions and NDK, integrates mobile-forge artifacts, installs toolchains (Rust, NDK, iOS targets), runs forge packaging, and publishes built wheels. Also adds conditional artifact uploads for logs/errors and generalizes checkout and setup steps for multi-runner usage. --- .../build-wheels-with-cibuildwheel.yml | 44 ++++++ .github/workflows/build-wheels.yml | 132 ++++++++++++++---- 2 files changed, 149 insertions(+), 27 deletions(-) create mode 100644 .github/workflows/build-wheels-with-cibuildwheel.yml diff --git a/.github/workflows/build-wheels-with-cibuildwheel.yml b/.github/workflows/build-wheels-with-cibuildwheel.yml new file mode 100644 index 00000000..a284ed67 --- /dev/null +++ b/.github/workflows/build-wheels-with-cibuildwheel.yml @@ -0,0 +1,44 @@ +name: wheels-android + +on: + push: + pull_request: + +jobs: + build_android_wheels: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: "3.12" # cibuildwheel runner python; not the target + + - name: Set up JDK + uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: "17" + + - name: Set up Android SDK + uses: android-actions/setup-android@v3 + + - name: Build Android wheels + env: + CIBW_PLATFORM: android + CIBW_BUILD: "cp313-android_*" + CIBW_ARCHS_ANDROID: "arm64_v8a x86_64" + ANDROID_API_LEVEL: "24" + run: | + wget https://files.pythonhosted.org/packages/04/24/4b2031d72e840ce4c1ccb255f693b15c334757fc50023e4db9537080b8c4/websockets-16.0.tar.gz + tar xf websockets-16.0.tar.gz + cd websockets-16.0 + python -m pip install -U pip cibuildwheel + cibuildwheel --output-dir wheelhouse + + - uses: actions/upload-artifact@v4 + with: + name: wheels-android + path: websockets-16.0/wheelhouse/*.whl \ No newline at end of file diff --git a/.github/workflows/build-wheels.yml b/.github/workflows/build-wheels.yml index a284ed67..302f1948 100644 --- a/.github/workflows/build-wheels.yml +++ b/.github/workflows/build-wheels.yml @@ -1,44 +1,122 @@ -name: wheels-android +name: Build wheels on: push: pull_request: + workflow_dispatch: + +env: + PYTHON_VERSION: "3.13.12" + PYTHON_SHORT_VERSION: "3.13" + MOBILE_FORGE_CACHE_DOWNLOADS_OFF: "1" + NDK_VERSION: r27d jobs: - build_android_wheels: - runs-on: ubuntu-latest + build: + name: ${{ matrix.job_name }} + runs-on: ${{ matrix.runner }} + strategy: + fail-fast: false + matrix: + include: + - job_name: "Android: pydantic-core 2.33.2" + runner: ubuntu-latest + forge_arch: android + forge_packages: "pydantic-core:2.33.2" + build_number: "1" + platform: android + - job_name: "iOS: pydantic-core 2.33.2" + runner: macos-latest + forge_arch: iOS + forge_packages: "pydantic-core:2.33.2" + build_number: "1" + platform: ios steps: - - uses: actions/checkout@v4 + - name: Checkout + uses: actions/checkout@v4 - name: Set up Python uses: actions/setup-python@v5 with: - python-version: "3.12" # cibuildwheel runner python; not the target - - - name: Set up JDK - uses: actions/setup-java@v4 - with: - distribution: temurin - java-version: "17" + python-version: ${{ env.PYTHON_SHORT_VERSION }} - - name: Set up Android SDK - uses: android-actions/setup-android@v3 - - - name: Build Android wheels + - name: Build and publish wheels + shell: bash env: - CIBW_PLATFORM: android - CIBW_BUILD: "cp313-android_*" - CIBW_ARCHS_ANDROID: "arm64_v8a x86_64" - ANDROID_API_LEVEL: "24" + GEMFURY_TOKEN: ${{ secrets.GEMFURY_TOKEN }} + APPVEYOR_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number || '' }} + FORGE_ARCH: ${{ matrix.forge_arch }} + FORGE_PACKAGES: ${{ matrix.forge_packages }} + BUILD_NUMBER: ${{ matrix.build_number }} + PLATFORM: ${{ matrix.platform }} run: | - wget https://files.pythonhosted.org/packages/04/24/4b2031d72e840ce4c1ccb255f693b15c334757fc50023e4db9537080b8c4/websockets-16.0.tar.gz - tar xf websockets-16.0.tar.gz - cd websockets-16.0 - python -m pip install -U pip cibuildwheel - cibuildwheel --output-dir wheelhouse + set -euxo pipefail + + . .ci/common.sh + export MOBILE_FORGE_ANDROID_SUPPORT_PATH="" + export MOBILE_FORGE_IOS_SUPPORT_PATH="" + + if [[ "$PLATFORM" == "android" ]]; then + sudo apt-get update + sudo apt-get install -y sqlite3 + + python_android_dir="$HOME/projects/python-build/android" + curl -#OL "https://github.com/flet-dev/python-build/releases/download/v${PYTHON_SHORT_VERSION}/python-android-mobile-forge-${PYTHON_SHORT_VERSION}.tar.gz" + mkdir -p "$python_android_dir" + tar -xzf "python-android-mobile-forge-${PYTHON_SHORT_VERSION}.tar.gz" -C "$python_android_dir" + + .ci/install_ndk.sh + + curl https://sh.rustup.rs -sSf | sh -s -- -y + . "$HOME/.cargo/env" + export PATH="$PATH:$HOME/.cargo/bin" + rustup target add aarch64-linux-android + rustup target add arm-linux-androideabi + rustup target add x86_64-linux-android + rustup target add i686-linux-android + + export MOBILE_FORGE_ANDROID_SUPPORT_PATH="$python_android_dir" + else + python_ios_dir="$HOME/projects/python-build/darwin/Python-Apple-support" + curl -#OL "https://github.com/flet-dev/python-build/releases/download/v${PYTHON_SHORT_VERSION}/python-ios-mobile-forge-${PYTHON_SHORT_VERSION}.tar.gz" + mkdir -p "$python_ios_dir" + tar -xzf "python-ios-mobile-forge-${PYTHON_SHORT_VERSION}.tar.gz" -C "$python_ios_dir" + + curl https://sh.rustup.rs -sSf | sh -s -- -y + . "$HOME/.cargo/env" + export PATH="$PATH:$HOME/.cargo/bin" + rustup target add aarch64-apple-ios + rustup target add aarch64-apple-ios-sim + rustup target add x86_64-apple-ios + + export MOBILE_FORGE_IOS_SUPPORT_PATH="$python_ios_dir" + fi + + source ./setup.sh "$PYTHON_VERSION" + export PATH="$PATH:$HOME/.cargo/bin" + + IFS=' ' read -r -a packages <<< "$FORGE_PACKAGES" + for package in "${packages[@]}"; do + forge "$FORGE_ARCH" "$package:$BUILD_NUMBER" + done + + rm -f dist/bzip2-* dist/xz-* dist/openssl-* dist/libffi-* + + if compgen -G "dist/*.whl" > /dev/null; then + publish_to_pypi dist/*.whl + fi + + - name: Upload logs on success + if: ${{ success() && hashFiles('logs/*.log') != '' }} + uses: actions/upload-artifact@v4 + with: + name: ${{ matrix.platform }}-logs-${{ github.run_id }}-${{ github.run_attempt }} + path: logs/*.log - - uses: actions/upload-artifact@v4 + - name: Upload errors on failure + if: ${{ failure() && hashFiles('errors/*.log') != '' }} + uses: actions/upload-artifact@v4 with: - name: wheels-android - path: websockets-16.0/wheelhouse/*.whl \ No newline at end of file + name: ${{ matrix.platform }}-errors-${{ github.run_id }}-${{ github.run_attempt }} + path: errors/*.log \ No newline at end of file From 57f011446123b74aacc50033eb5ebb433334130c Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Wed, 11 Feb 2026 09:34:48 -0800 Subject: [PATCH 092/142] Source NDK installer and use NDK_HOME Source the NDK install script in CI (AppVeyor and GitHub Actions) so its environment is applied. .ci/install_ndk.sh now exports NDK_HOME and ensures a trailing newline. In src/forge/build.py, add logic to detect NDK_HOME and re-point missing compiler/binutils to the NDK toolchain prebuilt bin directory so Android build archives that reference embedded NDK paths work in CI. Also uncomment build.script_env in the pydantic-core recipe to set _PYTHON_SYSCONFIGDATA_NAME. --- .appveyor.yml | 2 +- .ci/install_ndk.sh | 4 +++- .github/workflows/build-wheels.yml | 4 ++-- recipes/pydantic-core/meta.yaml | 6 +++--- src/forge/build.py | 16 ++++++++++++++++ 5 files changed, 25 insertions(+), 7 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index 9f2b2da4..2a52e7c0 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -200,7 +200,7 @@ for: - tar -xzf python-android-mobile-forge-${PYTHON_SHORT_VERSION}.tar.gz -C $python_android_dir # install Android NDK - - .ci/install_ndk.sh + - . .ci/install_ndk.sh # install Rust - curl https://sh.rustup.rs -sSf | sh -s -- -y diff --git a/.ci/install_ndk.sh b/.ci/install_ndk.sh index 0193e155..cd4cea50 100755 --- a/.ci/install_ndk.sh +++ b/.ci/install_ndk.sh @@ -46,4 +46,6 @@ if [[ -z "${NDK_HOME-}" ]]; then fi else echo "NDK home: $NDK_HOME" -fi \ No newline at end of file +fi + +export NDK_HOME diff --git a/.github/workflows/build-wheels.yml b/.github/workflows/build-wheels.yml index 302f1948..3c46f5c0 100644 --- a/.github/workflows/build-wheels.yml +++ b/.github/workflows/build-wheels.yml @@ -66,7 +66,7 @@ jobs: mkdir -p "$python_android_dir" tar -xzf "python-android-mobile-forge-${PYTHON_SHORT_VERSION}.tar.gz" -C "$python_android_dir" - .ci/install_ndk.sh + . .ci/install_ndk.sh curl https://sh.rustup.rs -sSf | sh -s -- -y . "$HOME/.cargo/env" @@ -119,4 +119,4 @@ jobs: uses: actions/upload-artifact@v4 with: name: ${{ matrix.platform }}-errors-${{ github.run_id }}-${{ github.run_attempt }} - path: errors/*.log \ No newline at end of file + path: errors/*.log diff --git a/recipes/pydantic-core/meta.yaml b/recipes/pydantic-core/meta.yaml index 91208b69..009c58da 100644 --- a/recipes/pydantic-core/meta.yaml +++ b/recipes/pydantic-core/meta.yaml @@ -2,6 +2,6 @@ package: name: pydantic-core version: 2.33.2 -# build: -# script_env: -# _PYTHON_SYSCONFIGDATA_NAME: '{sysconfigdata_name}' \ No newline at end of file +build: + script_env: + _PYTHON_SYSCONFIGDATA_NAME: '{sysconfigdata_name}' \ No newline at end of file diff --git a/src/forge/build.py b/src/forge/build.py index 3734ef94..dc246ec2 100644 --- a/src/forge/build.py +++ b/src/forge/build.py @@ -299,6 +299,22 @@ def compile_env(self, **kwargs) -> dict[str, str]: cppflags += f" -mios-version-min={self.cross_venv.sdk_version}" else: + # Some Python Android support archives reference an embedded NDK path + # that isn't present in CI. If NDK_HOME is set, re-point missing + # compiler/binutils paths to that installed NDK toolchain. + ndk_home = os.environ.get("NDK_HOME") + if ndk_home: + prebuilt_dirs = list( + (Path(ndk_home) / "toolchains" / "llvm" / "prebuilt").glob("*") + ) + if prebuilt_dirs: + ndk_bin = prebuilt_dirs[0] / "bin" + if not Path(cc).is_file(): + cc = str(ndk_bin / Path(cc).name) + if not Path(cxx).is_file(): + cxx = str(ndk_bin / Path(cxx).name) + if not Path(ar).is_file(): + ar = str(ndk_bin / Path(ar).name) ndk_sysroot = Path(cc).parent.parent / "sysroot" if (ndk_sysroot / "usr" / "include").is_dir(): cflags += f" -I{ndk_sysroot}/usr/include" From 55a90f09f69994908d9822f698dcd304324db268 Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Wed, 11 Feb 2026 09:58:51 -0800 Subject: [PATCH 093/142] Fix strip/ranlib detection for Android cross builds Always default strip/ranlib to the host tools, then derive Android-specific llvm-strip/llvm-ranlib based on the detected NDK toolchain location. Moves detection after potential ndk_bin/AR adjustments, falling back to llvm-strip/llvm-ranlib next to the final AR when present, and ensures non-Android SDKs keep the host "strip"/"ranlib". This improves reliability of selecting the correct strip/ranlib for cross compiles with varying NDK layouts. --- src/forge/build.py | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/src/forge/build.py b/src/forge/build.py index dc246ec2..336399b8 100644 --- a/src/forge/build.py +++ b/src/forge/build.py @@ -265,16 +265,8 @@ def compile_env(self, **kwargs) -> dict[str, str]: ar = sysconfig_data["AR"] cc = sysconfig_data["CC"] cxx = sysconfig_data["CXX"] - strip = ( - str(Path(ar).parent.joinpath("llvm-strip")) - if ar and self.cross_venv.sdk == "android" - else "strip" - ) - ranlib = ( - str(Path(ar).parent.joinpath("llvm-ranlib")) - if ar and self.cross_venv.sdk == "android" - else "ranlib" - ) + strip = "strip" + ranlib = "ranlib" cflags = self.cross_venv.sysconfig_data["CFLAGS"] cppflags = self.cross_venv.sysconfig_data["CPPFLAGS"] ndk_sysroot = None @@ -315,9 +307,26 @@ def compile_env(self, **kwargs) -> dict[str, str]: cxx = str(ndk_bin / Path(cxx).name) if not Path(ar).is_file(): ar = str(ndk_bin / Path(ar).name) + if not Path(strip).is_file(): + strip = str(ndk_bin / "llvm-strip") + if not Path(ranlib).is_file(): + ranlib = str(ndk_bin / "llvm-ranlib") + + # Derive strip/ranlib from the final AR location when available. + if ar: + ar_parent = Path(ar).parent + derived_strip = ar_parent / "llvm-strip" + derived_ranlib = ar_parent / "llvm-ranlib" + if derived_strip.is_file(): + strip = str(derived_strip) + if derived_ranlib.is_file(): + ranlib = str(derived_ranlib) ndk_sysroot = Path(cc).parent.parent / "sysroot" if (ndk_sysroot / "usr" / "include").is_dir(): cflags += f" -I{ndk_sysroot}/usr/include" + if self.cross_venv.sdk != "android": + strip = "strip" + ranlib = "ranlib" ldflags = self.cross_venv.sysconfig_data["LDFLAGS"] From 52adafaf5d8a37d7655dc442c322fb0c88a4e67d Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Wed, 11 Feb 2026 10:11:48 -0800 Subject: [PATCH 094/142] Create dist dir before packing wheels Ensure the target dist directory exists before invoking the wheel packing step in SimplePackageBuilder and PythonPackageBuilder. Introduced a dist_dir variable (Path.cwd() / 'dist') and call dist_dir.mkdir(parents=True, exist_ok=True), then pass dist_dir to the pack command to avoid failures when the directory is missing and reduce repeated Path.cwd() calls. --- src/forge/build.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/forge/build.py b/src/forge/build.py index 336399b8..453172ff 100644 --- a/src/forge/build.py +++ b/src/forge/build.py @@ -632,6 +632,8 @@ def make_wheel(self): # Re-pack the wheel file log(self.log_file, f"\n[{self.cross_venv}] Packing wheel") + dist_dir = Path.cwd() / "dist" + dist_dir.mkdir(parents=True, exist_ok=True) self.cross_venv.run( self.log_file, [ @@ -641,7 +643,7 @@ def make_wheel(self): "pack", str(self.build_path / "wheel"), "--dest-dir", - str(Path.cwd() / "dist"), + str(dist_dir), "--build-number", str(build_num), ], @@ -916,6 +918,8 @@ def _build(self): # re-pack the wheel to "dist" log(self.log_file, f"\n[{self.cross_venv}] Packing wheel to dist") + dist_dir = Path.cwd() / "dist" + dist_dir.mkdir(parents=True, exist_ok=True) pack_args = [ "build-python", "-m", @@ -923,7 +927,7 @@ def _build(self): "pack", str(tmp_wheel_dir), "--dest-dir", - str(Path.cwd() / "dist"), + str(dist_dir), ] if self.package.meta["build"]["number"]: pack_args.extend( From 4cf1c1f65b31fcaaf9645dc51653301eb8c9198b Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Sun, 29 Mar 2026 14:39:52 -0700 Subject: [PATCH 095/142] GHA for Python 3.12 (#46) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add Android wheel workflow; update Python URL Add a new GitHub Actions workflow (build-wheels.yml) to build Android wheels using cibuildwheel. The workflow sets up Python 3.12, JDK 17, and the Android SDK, downloads websockets-16.0 source, builds cp313 Android wheels for arm64_v8a and x86_64, and uploads the resulting .whl artifacts. Also update setup.sh to use the indygreg python-build-standalone release tag 20260203 in PYTHON_URL_PREFIX. * Make target lists and deps dynamic for platforms Refactor make_dep_wheels.py to read the VERSIONS file and derive dependencies and targets dynamically: add get_versions_path, get_dependencies and get_targets helpers, and update make_wheel/main to iterate discovered deps and platform-specific targets (including a special-case for Android host archs). Update setup.sh to only check armeabi-v7a and x86 Android device binaries when PYTHON_VER is 3.12 (keep x86_64 check unconditional) and add a trailing newline. Adjust src/forge/cross.py to introduce ANDROID_HOST_ARCHS (varying by Python version) and construct HOST_SDKS['android'] from that list to keep host SDK targets in sync with the wheel generation logic. * Support platform-config sysconfig & iOS Add detection for sysconfig files under a new platform-config/- path in addition to the legacy lib/python3.x location. Prefer the legacy path if present, otherwise use the platform-config path and raise a clear error listing both tried locations. Also exempt iOS from the later file-existence check to avoid incorrectly failing when host sysconfig handling differs. * Adjust Android cross identifiers and NDK_SYSROOT Apply Android host/target selection for Python >= 3.13 (changed equality checks to >=). Add ANDROID_PLATFORM_MACHINE and make _platform_identifier emit machine-based identifiers for android on Python >=3.13, while adding a new _tag_identifier to preserve the legacy sdk-version-arch tag for wheel tags. Switch _PYTHON_HOST_PLATFORM to use the tag identifier. Also export NDK_SYSROOT in the build environment so the toolchain sysroot is available during cross builds. These changes align cross-compilation identifiers with Python 3.13+ tagging and ensure the NDK sysroot is provided to build steps. * Add Android NDK sysroot handling Detect and use an Android NDK sysroot for cross builds. Introduces ndk_sysroot and adds its usr/include to CFLAGS when present, and appends -L flags for ndk sysroot lib paths (usr/lib// or usr/lib/). Also make NDK_SYSROOT env prefer the discovered ndk_sysroot. Ensures proper include and library search paths for Android targets. * Adjust Pillow recipe version conditional Modify recipes/pillow/meta.yaml to apply the pillow >= 11.x conditional when no version is provided or when version >= 11.0.0 by changing the Jinja condition to `{% if not version or version >= (11,0,0) %}`. Also ensure a trailing newline at end of file. * Improve OpenSSL detection and requirement parsing recipes/flet-libcurl: make build.sh detect a usable OpenSSL under PLATLIB/opt (checks for headers and libssl/libcrypto) and fall back to PYTHON_PREFIX if not found; pass the chosen prefix to configure. Update meta.yaml to use a conditional >= openssl host requirement (commented template lines) and fix trailing newline. src/forge/build.py: safer requirement splitting (split max 1) and support explicit version specifiers (>=, <=, !=, ==, ~=, >, <) while preserving ^ and ~ handling by translating them to >= and ~= semantics. * Normalize wheel tags and bump NDK/libcpp versions Normalize wheel tags used when repacking wheels and centralize tag logic. Builder.fix_wheel now updates the WHEEL metadata Tag to use a forge-style wheel tag (via a new wheel_tag property) so repacked wheels use platform tags like android_24_arm64_v8a / ios_13_0_arm64_iphoneos. SimplePackageBuilder now uses wheel_tag when writing metadata, and PythonPackageBuilder provides a py-specific wheel_tag (cp3X-cp3X-). Also: bump flet-libcpp-shared package version to 27.3.13750724, relax contourpy's host dependency to "flet-libcpp-shared >=27.2.12479018", and update AppVeyor NDK_VERSION from r27c to r27d. * Use meson dep & repair malformed shims Replace direct git dependency on a meson fork with the standard meson package in contourpy and pandas recipes (recipes/contourpy/meta.yaml, recipes/pandas/meta.yaml). In src/forge/build.py add handling to detect and repair a legacy malformed shim where the separator line was accidentally merged with Python code (e.g. "' '''import sys"). The builder now logs the repair and rewrites the shim with a proper separator line (and preserves any trailing suffix). Also small formatting/newline adjustments to shim writing were made to ensure correct output. * Replace meson git URL with meson package Update recipes/matplotlib/meta.yaml to remove the external git dependency (git+https://github.com/flet-dev/meson@ios-dynamiclib) and use the packaged "meson" build requirement instead. This simplifies dependency management and avoids relying on an external repository for the Meson build system during the matplotlib build. * Use host sysconfig for PYO3 cross lib dir Adjust cross-build sysconfig handling for pyo3 on Apple platforms. Add a host_sysconfig attribute to CrossVEnv and set PYO3_CROSS_LIB_DIR to the host_sysconfig.parent (the directory containing _sysconfigdata__*.py), falling back to /lib when host_sysconfig is unavailable. Also comment out the recipe-level _PYTHON_SYSCONFIGDATA_NAME script_env entry. These changes address newer Apple support layouts that place sysconfig data outside the venv prefix/lib. * Add cibuildwheel Android workflow and matrix build Add a new GitHub Actions workflow (build-wheels-with-cibuildwheel.yml) to build Android wheels using cibuildwheel. Revamp build-wheels.yml into a matrix-based job that supports Android and iOS builds, parameterizes Python versions and NDK, integrates mobile-forge artifacts, installs toolchains (Rust, NDK, iOS targets), runs forge packaging, and publishes built wheels. Also adds conditional artifact uploads for logs/errors and generalizes checkout and setup steps for multi-runner usage. * Source NDK installer and use NDK_HOME Source the NDK install script in CI (AppVeyor and GitHub Actions) so its environment is applied. .ci/install_ndk.sh now exports NDK_HOME and ensures a trailing newline. In src/forge/build.py, add logic to detect NDK_HOME and re-point missing compiler/binutils to the NDK toolchain prebuilt bin directory so Android build archives that reference embedded NDK paths work in CI. Also uncomment build.script_env in the pydantic-core recipe to set _PYTHON_SYSCONFIGDATA_NAME. * Fix strip/ranlib detection for Android cross builds Always default strip/ranlib to the host tools, then derive Android-specific llvm-strip/llvm-ranlib based on the detected NDK toolchain location. Moves detection after potential ndk_bin/AR adjustments, falling back to llvm-strip/llvm-ranlib next to the final AR when present, and ensures non-Android SDKs keep the host "strip"/"ranlib". This improves reliability of selecting the correct strip/ranlib for cross compiles with varying NDK layouts. * Create dist dir before packing wheels Ensure the target dist directory exists before invoking the wheel packing step in SimplePackageBuilder and PythonPackageBuilder. Introduced a dist_dir variable (Path.cwd() / 'dist') and call dist_dir.mkdir(parents=True, exist_ok=True), then pass dist_dir to the pack command to avoid failures when the directory is missing and reduce repeated Path.cwd() calls. * Pin CI Python version to 3.12.12 Update .github/workflows/build-wheels.yml to set PYTHON_VERSION to 3.12.12 and PYTHON_SHORT_VERSION to 3.12 (previously 3.13.12 / 3.13). This changes the Python runtime used for building wheels in CI to the 3.12 series. * Android 16K support for Python 3.12 (#45) * Log build info and make regex case-insensitive Add a diagnostic print that logs the package, version/build target and OS when building wheels. Also update the regex that extracts the minimum OS version to use the IGNORECASE flag for more robust matching of varied casing in the versions file. * Add 16KB page alignment for Android shared libraries Google Play requires all .so files to be 16KB page-aligned (Android 15+). Add -z max-page-size=16384 to LDFLAGS for autotools, CMAKE_SHARED_LINKER_FLAGS for CMake recipes, and cargo rustflags for Rust-based builds. Fixes flet-dev/flet#6345 * Add workflow_dispatch inputs with dynamic matrix for build-wheels Support manual triggering with configurable archs, packages, and build_number inputs. A setup job generates the matrix from arch × package combinations. Disable push/PR triggers. * Run build-wheels on push and pull requests Add push and pull_request triggers to the build-wheels GitHub Actions workflow so wheel builds run automatically on pushes and PRs; keeps existing workflow_dispatch input-based manual trigger. * Fix artifact name containing invalid colon character Add artifact_name field without colons/spaces for upload-artifact, keep job_name with colon for job display only. --- .appveyor.yml | 4 +- .ci/install_ndk.sh | 4 +- .../build-wheels-with-cibuildwheel.yml | 44 +++++ .github/workflows/build-wheels.yml | 154 ++++++++++++++++++ make_dep_wheels.py | 73 ++++++--- recipes/contourpy/meta.yaml | 6 +- recipes/flet-libcpp-shared/meta.yaml | 2 +- recipes/flet-libcrc32c/build.sh | 1 + recipes/flet-libcurl/build.sh | 11 +- recipes/flet-libcurl/meta.yaml | 6 +- recipes/flet-libgdal/build.sh | 1 + recipes/flet-libgeos/build.sh | 1 + recipes/flet-libjpeg/build.sh | 1 + recipes/flet-libproj/build.sh | 1 + recipes/flet-libpyjni/build.sh | 1 + recipes/matplotlib/meta.yaml | 2 +- recipes/pandas/meta.yaml | 2 +- recipes/pillow/meta.yaml | 4 +- setup.sh | 20 ++- src/forge/build.py | 144 +++++++++++++--- src/forge/cross.py | 41 +++-- 21 files changed, 448 insertions(+), 75 deletions(-) create mode 100644 .github/workflows/build-wheels-with-cibuildwheel.yml create mode 100644 .github/workflows/build-wheels.yml diff --git a/.appveyor.yml b/.appveyor.yml index 39e4d247..2a52e7c0 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -186,7 +186,7 @@ for: environment: APPVEYOR_BUILD_WORKER_IMAGE: ubuntu-gce-c - NDK_VERSION: r27c + NDK_VERSION: r27d install: - sudo apt update @@ -200,7 +200,7 @@ for: - tar -xzf python-android-mobile-forge-${PYTHON_SHORT_VERSION}.tar.gz -C $python_android_dir # install Android NDK - - .ci/install_ndk.sh + - . .ci/install_ndk.sh # install Rust - curl https://sh.rustup.rs -sSf | sh -s -- -y diff --git a/.ci/install_ndk.sh b/.ci/install_ndk.sh index 0193e155..cd4cea50 100755 --- a/.ci/install_ndk.sh +++ b/.ci/install_ndk.sh @@ -46,4 +46,6 @@ if [[ -z "${NDK_HOME-}" ]]; then fi else echo "NDK home: $NDK_HOME" -fi \ No newline at end of file +fi + +export NDK_HOME diff --git a/.github/workflows/build-wheels-with-cibuildwheel.yml b/.github/workflows/build-wheels-with-cibuildwheel.yml new file mode 100644 index 00000000..a284ed67 --- /dev/null +++ b/.github/workflows/build-wheels-with-cibuildwheel.yml @@ -0,0 +1,44 @@ +name: wheels-android + +on: + push: + pull_request: + +jobs: + build_android_wheels: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: "3.12" # cibuildwheel runner python; not the target + + - name: Set up JDK + uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: "17" + + - name: Set up Android SDK + uses: android-actions/setup-android@v3 + + - name: Build Android wheels + env: + CIBW_PLATFORM: android + CIBW_BUILD: "cp313-android_*" + CIBW_ARCHS_ANDROID: "arm64_v8a x86_64" + ANDROID_API_LEVEL: "24" + run: | + wget https://files.pythonhosted.org/packages/04/24/4b2031d72e840ce4c1ccb255f693b15c334757fc50023e4db9537080b8c4/websockets-16.0.tar.gz + tar xf websockets-16.0.tar.gz + cd websockets-16.0 + python -m pip install -U pip cibuildwheel + cibuildwheel --output-dir wheelhouse + + - uses: actions/upload-artifact@v4 + with: + name: wheels-android + path: websockets-16.0/wheelhouse/*.whl \ No newline at end of file diff --git a/.github/workflows/build-wheels.yml b/.github/workflows/build-wheels.yml new file mode 100644 index 00000000..ae24a63e --- /dev/null +++ b/.github/workflows/build-wheels.yml @@ -0,0 +1,154 @@ +name: Build wheels + +on: + push: + pull_request: + workflow_dispatch: + inputs: + archs: + description: "Architectures (comma-separated, e.g. android,iOS)" + required: false + default: "android,iOS" + packages: + description: "Packages (comma-separated, e.g. pillow:11.1.0,pydantic-core:2.33.2)" + required: false + default: "pydantic-core:2.33.2" + build_number: + description: "Build number" + required: false + default: "1" + +env: + PYTHON_VERSION: "3.12.12" + PYTHON_SHORT_VERSION: "3.12" + MOBILE_FORGE_CACHE_DOWNLOADS_OFF: "1" + NDK_VERSION: r27d + +jobs: + setup: + runs-on: ubuntu-latest + outputs: + matrix: ${{ steps.set-matrix.outputs.matrix }} + steps: + - id: set-matrix + shell: bash + run: | + ARCHS="${{ inputs.archs || 'android,iOS' }}" + PACKAGES="${{ inputs.packages || 'pydantic-core:2.33.2' }}" + BUILD_NUMBER="${{ inputs.build_number || '1' }}" + + matrix='{"include":[' + first=true + for arch in $(echo "$ARCHS" | tr ',' ' '); do + for pkg in $(echo "$PACKAGES" | tr ',' ' '); do + pkg_name="${pkg%%:*}" + if [ "$first" = true ]; then first=false; else matrix+=','; fi + if [[ "$arch" == "android" ]]; then + runner="ubuntu-latest" + platform="android" + else + runner="macos-latest" + platform="ios" + fi + matrix+="{\"job_name\":\"${platform}: ${pkg_name}\",\"artifact_name\":\"${platform}-${pkg_name}\",\"runner\":\"$runner\",\"platform\":\"$platform\",\"forge_arch\":\"$arch\",\"forge_packages\":\"$pkg\",\"build_number\":\"$BUILD_NUMBER\"}" + done + done + matrix+=']}' + echo "matrix=$matrix" >> "$GITHUB_OUTPUT" + + build: + needs: setup + name: ${{ matrix.job_name }} + runs-on: ${{ matrix.runner }} + strategy: + fail-fast: false + matrix: ${{ fromJson(needs.setup.outputs.matrix) }} + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: ${{ env.PYTHON_SHORT_VERSION }} + + - name: Build and publish wheels + shell: bash + env: + GEMFURY_TOKEN: ${{ secrets.GEMFURY_TOKEN }} + APPVEYOR_PULL_REQUEST_NUMBER: "" + FORGE_ARCH: ${{ matrix.forge_arch }} + FORGE_PACKAGES: ${{ matrix.forge_packages }} + BUILD_NUMBER: ${{ matrix.build_number }} + PLATFORM: ${{ matrix.platform }} + run: | + set -euxo pipefail + + . .ci/common.sh + export MOBILE_FORGE_ANDROID_SUPPORT_PATH="" + export MOBILE_FORGE_IOS_SUPPORT_PATH="" + + if [[ "$PLATFORM" == "android" ]]; then + sudo apt-get update + sudo apt-get install -y sqlite3 + + python_android_dir="$HOME/projects/python-build/android" + curl -#OL "https://github.com/flet-dev/python-build/releases/download/v${PYTHON_SHORT_VERSION}/python-android-mobile-forge-${PYTHON_SHORT_VERSION}.tar.gz" + mkdir -p "$python_android_dir" + tar -xzf "python-android-mobile-forge-${PYTHON_SHORT_VERSION}.tar.gz" -C "$python_android_dir" + + . .ci/install_ndk.sh + + curl https://sh.rustup.rs -sSf | sh -s -- -y + . "$HOME/.cargo/env" + export PATH="$PATH:$HOME/.cargo/bin" + rustup target add aarch64-linux-android + rustup target add arm-linux-androideabi + rustup target add x86_64-linux-android + rustup target add i686-linux-android + + export MOBILE_FORGE_ANDROID_SUPPORT_PATH="$python_android_dir" + else + python_ios_dir="$HOME/projects/python-build/darwin/Python-Apple-support" + curl -#OL "https://github.com/flet-dev/python-build/releases/download/v${PYTHON_SHORT_VERSION}/python-ios-mobile-forge-${PYTHON_SHORT_VERSION}.tar.gz" + mkdir -p "$python_ios_dir" + tar -xzf "python-ios-mobile-forge-${PYTHON_SHORT_VERSION}.tar.gz" -C "$python_ios_dir" + + curl https://sh.rustup.rs -sSf | sh -s -- -y + . "$HOME/.cargo/env" + export PATH="$PATH:$HOME/.cargo/bin" + rustup target add aarch64-apple-ios + rustup target add aarch64-apple-ios-sim + rustup target add x86_64-apple-ios + + export MOBILE_FORGE_IOS_SUPPORT_PATH="$python_ios_dir" + fi + + source ./setup.sh "$PYTHON_VERSION" + export PATH="$PATH:$HOME/.cargo/bin" + + IFS=' ' read -r -a packages <<< "$FORGE_PACKAGES" + for package in "${packages[@]}"; do + forge "$FORGE_ARCH" "$package:$BUILD_NUMBER" + done + + rm -f dist/bzip2-* dist/xz-* dist/openssl-* dist/libffi-* + + if compgen -G "dist/*.whl" > /dev/null; then + publish_to_pypi dist/*.whl + fi + + - name: Upload logs on success + if: ${{ success() && hashFiles('logs/*.log') != '' }} + uses: actions/upload-artifact@v4 + with: + name: logs-${{ matrix.artifact_name }}-${{ github.run_id }}-${{ github.run_attempt }} + path: logs/*.log + + - name: Upload errors on failure + if: ${{ failure() && hashFiles('errors/*.log') != '' }} + uses: actions/upload-artifact@v4 + with: + name: errors-${{ matrix.artifact_name }}-${{ github.run_id }}-${{ github.run_attempt }} + path: errors/*.log diff --git a/make_dep_wheels.py b/make_dep_wheels.py index 5c685d61..411ae65b 100644 --- a/make_dep_wheels.py +++ b/make_dep_wheels.py @@ -16,16 +16,7 @@ from pathlib import Path -def make_wheel(package, os_name, target): - """Create a target-specific wheel for a given package. - - Requires that PYTHON_APPLE_SUPPORT is set in the environment, and that variable - points to a completed support build. - - :param package: The name of the package to build (e.g., "BZip2") - :param os_name: The OS name to target (e.g., "iOS") - :param target: The target specifier (e.g., "iphoneos.arm64") - """ +def get_versions_path(os_name): support = Path( os.environ[ ( @@ -35,21 +26,65 @@ def make_wheel(package, os_name, target): ) ] ) - - versions_file = ( + return ( support / "support" / ".".join(sys.version.split(".")[:2]) / os_name / "VERSIONS" ) + + +def get_dependencies(os_name): + versions_file = get_versions_path(os_name) + dependencies = [] + with versions_file.open(encoding="utf-8") as f: + for line in f: + match = re.match(r"^([^:]+):\s+(.+)$", line.strip()) + if not match: + continue + key = match[1] + if ( + key.lower() == "python version" + or key.lower() == "build" + or key.lower().startswith("min ") + ): + continue + dependencies.append(key) + return dependencies + + +def get_targets(os_name): + if os_name == "android": + if sys.version_info[:2] >= (3, 13): + return ["arm64-v8a", "x86_64"] + return ["arm64-v8a", "armeabi-v7a", "x86_64", "x86"] + return [ + "iphoneos.arm64", + "iphonesimulator.arm64", + "iphonesimulator.x86_64", + ] + + +def make_wheel(package, os_name, target): + """Create a target-specific wheel for a given package. + + Requires that PYTHON_APPLE_SUPPORT is set in the environment, and that variable + points to a completed support build. + + :param package: The name of the package to build (e.g., "BZip2") + :param os_name: The OS name to target (e.g., "iOS") + :param target: The target specifier (e.g., "iphoneos.arm64") + """ + support = get_versions_path(os_name).parents[3] + versions_file = get_versions_path(os_name) with versions_file.open(encoding="utf-8") as f: versions = f.read() package_version_build = re.search( rf"^{package}: (.*)", versions, re.MULTILINE | re.IGNORECASE )[1] - min_version = re.search(rf"^Min {os_name} version: (.*)", versions, re.MULTILINE)[1] + min_version = re.search(rf"^Min {os_name} version: (.*)", versions, re.MULTILINE | re.IGNORECASE)[1] package_version, package_build = package_version_build.split("-") @@ -136,13 +171,7 @@ def make_wheel(package, os_name, target): if __name__ == "__main__": os_name = sys.argv[1] - for target in { - "android": ["arm64-v8a", "armeabi-v7a", "x86_64", "x86"], - "iOS": [ - "iphoneos.arm64", - "iphonesimulator.arm64", - "iphonesimulator.x86_64", - ], - }[os_name]: - for dep in ["BZip2", "XZ", "libFFI", "OpenSSL"]: + dependencies = get_dependencies(os_name) + for target in get_targets(os_name): + for dep in dependencies: make_wheel(dep, os_name, target) diff --git a/recipes/contourpy/meta.yaml b/recipes/contourpy/meta.yaml index d00f6ec4..b05eb7b8 100644 --- a/recipes/contourpy/meta.yaml +++ b/recipes/contourpy/meta.yaml @@ -6,14 +6,14 @@ requirements: build: - ninja - cmake - - git+https://github.com/flet-dev/meson@ios-dynamiclib + - meson host: - pybind11 # {% if sdk == 'android' %} - - flet-libcpp-shared 27.2.12479018 + - flet-libcpp-shared >=27.2.12479018 # {% endif %} build: backend-args: - -Csetup-args=--cross-file - - -Csetup-args={MESON_CROSS_FILE} \ No newline at end of file + - -Csetup-args={MESON_CROSS_FILE} diff --git a/recipes/flet-libcpp-shared/meta.yaml b/recipes/flet-libcpp-shared/meta.yaml index 12184be3..18055a6c 100644 --- a/recipes/flet-libcpp-shared/meta.yaml +++ b/recipes/flet-libcpp-shared/meta.yaml @@ -1,6 +1,6 @@ package: name: flet-libcpp-shared - version: 27.2.12479018 + version: 27.3.13750724 source: url: https://github.com/flet-dev/awesome-flet/archive/refs/heads/main.zip \ No newline at end of file diff --git a/recipes/flet-libcrc32c/build.sh b/recipes/flet-libcrc32c/build.sh index 2767996e..3a1cbbaf 100755 --- a/recipes/flet-libcrc32c/build.sh +++ b/recipes/flet-libcrc32c/build.sh @@ -12,6 +12,7 @@ if [ $CROSS_VENV_SDK == "android" ]; then -DCRC32C_USE_GLOG=0 \ -DCMAKE_BUILD_TYPE=Release \ -DBUILD_SHARED_LIBS=1 \ + -DCMAKE_SHARED_LINKER_FLAGS="$LDFLAGS" \ -DCMAKE_INSTALL_PREFIX="$PREFIX" else cmake \ diff --git a/recipes/flet-libcurl/build.sh b/recipes/flet-libcurl/build.sh index f0b69969..be944abb 100755 --- a/recipes/flet-libcurl/build.sh +++ b/recipes/flet-libcurl/build.sh @@ -1,7 +1,14 @@ #!/bin/bash set -eu -./configure --host=$HOST_TRIPLET --prefix=$PREFIX --with-openssl=$PLATLIB/opt +OPENSSL_PREFIX="$PLATLIB/opt" +if [ ! -f "$OPENSSL_PREFIX/include/openssl/ssl.h" ] || \ + { [ ! -f "$OPENSSL_PREFIX/lib/libssl.a" ] && [ ! -f "$OPENSSL_PREFIX/lib/libssl.so" ]; } || \ + { [ ! -f "$OPENSSL_PREFIX/lib/libcrypto.a" ] && [ ! -f "$OPENSSL_PREFIX/lib/libcrypto.so" ]; }; then + OPENSSL_PREFIX="$PYTHON_PREFIX" +fi + +./configure --host=$HOST_TRIPLET --prefix=$PREFIX --with-openssl="$OPENSSL_PREFIX" make -j $CPU_COUNT make install @@ -10,4 +17,4 @@ rm -r $PREFIX/lib/{*.la,pkgconfig} if [ $CROSS_VENV_SDK == "android" ]; then rm -r $PREFIX/lib/*.a -fi \ No newline at end of file +fi diff --git a/recipes/flet-libcurl/meta.yaml b/recipes/flet-libcurl/meta.yaml index 39d732b3..9dba6cc6 100644 --- a/recipes/flet-libcurl/meta.yaml +++ b/recipes/flet-libcurl/meta.yaml @@ -12,8 +12,10 @@ build: requirements: host: - - openssl 3.0.15 + # {% if sdk in ['iphoneos', 'iphonesimulator'] %} + - openssl >=3.0.15 + # {% endif %} - flet-libpsl 0.21.5 patches: - - config.patch \ No newline at end of file + - config.patch diff --git a/recipes/flet-libgdal/build.sh b/recipes/flet-libgdal/build.sh index 774bbc93..b815f03d 100755 --- a/recipes/flet-libgdal/build.sh +++ b/recipes/flet-libgdal/build.sh @@ -11,6 +11,7 @@ if [ $CROSS_VENV_SDK == "android" ]; then -DANDROID_ABI=$ANDROID_ABI \ -DCMAKE_TOOLCHAIN_FILE=$NDK_ROOT/build/cmake/android.toolchain.cmake \ -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_SHARED_LINKER_FLAGS="$LDFLAGS" \ -DCMAKE_INSTALL_PREFIX="$PREFIX" \ -DCMAKE_FIND_ROOT_PATH_MODE_INCLUDE=NEVER \ -DCMAKE_FIND_ROOT_PATH_MODE_LIBRARY=NEVER \ diff --git a/recipes/flet-libgeos/build.sh b/recipes/flet-libgeos/build.sh index 0572db12..dfb261c5 100755 --- a/recipes/flet-libgeos/build.sh +++ b/recipes/flet-libgeos/build.sh @@ -8,6 +8,7 @@ if [ $CROSS_VENV_SDK == "android" ]; then -DANDROID_ABI=$ANDROID_ABI \ -DCMAKE_TOOLCHAIN_FILE=$NDK_ROOT/build/cmake/android.toolchain.cmake \ -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_SHARED_LINKER_FLAGS="$LDFLAGS" \ -DCMAKE_INSTALL_PREFIX="$PREFIX" \ -DBUILD_TESTING=0 else diff --git a/recipes/flet-libjpeg/build.sh b/recipes/flet-libjpeg/build.sh index 936a0add..a3cee1e0 100755 --- a/recipes/flet-libjpeg/build.sh +++ b/recipes/flet-libjpeg/build.sh @@ -8,6 +8,7 @@ if [ $CROSS_VENV_SDK == "android" ]; then -DANDROID_PLATFORM=$SDK_VERSION \ -DANDROID_ABI=$ANDROID_ABI \ -DCMAKE_TOOLCHAIN_FILE=$NDK_ROOT/build/cmake/android.toolchain.cmake \ + -DCMAKE_SHARED_LINKER_FLAGS="$LDFLAGS" \ -DCMAKE_INSTALL_PREFIX=$PREFIX . else cmake -G"Unix Makefiles" \ diff --git a/recipes/flet-libproj/build.sh b/recipes/flet-libproj/build.sh index f19a8424..64e77fb8 100755 --- a/recipes/flet-libproj/build.sh +++ b/recipes/flet-libproj/build.sh @@ -8,6 +8,7 @@ if [ $CROSS_VENV_SDK == "android" ]; then -DANDROID_ABI=$ANDROID_ABI \ -DCMAKE_TOOLCHAIN_FILE=$NDK_ROOT/build/cmake/android.toolchain.cmake \ -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_SHARED_LINKER_FLAGS="$LDFLAGS" \ -DCMAKE_INSTALL_PREFIX="$PREFIX" \ -DBUILD_TESTING=0 \ -DTIFF_LIBRARY="$PLATLIB/opt/lib/libtiff.so" \ diff --git a/recipes/flet-libpyjni/build.sh b/recipes/flet-libpyjni/build.sh index fb46ea3c..57d0b107 100755 --- a/recipes/flet-libpyjni/build.sh +++ b/recipes/flet-libpyjni/build.sh @@ -12,6 +12,7 @@ if [ $CROSS_VENV_SDK == "android" ]; then -DCMAKE_TOOLCHAIN_FILE=$NDK_ROOT/build/cmake/android.toolchain.cmake \ -DCMAKE_BUILD_TYPE=Release \ -DBUILD_SHARED_LIBS=1 \ + -DCMAKE_SHARED_LINKER_FLAGS="$LDFLAGS" \ -DCMAKE_INSTALL_PREFIX="$PREFIX" else echo "flet-libpyjni library can be built for Android only." diff --git a/recipes/matplotlib/meta.yaml b/recipes/matplotlib/meta.yaml index 4df9c1cf..f097cec1 100644 --- a/recipes/matplotlib/meta.yaml +++ b/recipes/matplotlib/meta.yaml @@ -5,7 +5,7 @@ package: requirements: build: - ninja - - git+https://github.com/flet-dev/meson@ios-dynamiclib + - meson host: - numpy ^2.0.0 - pybind11 diff --git a/recipes/pandas/meta.yaml b/recipes/pandas/meta.yaml index c106cef5..a5acaf71 100644 --- a/recipes/pandas/meta.yaml +++ b/recipes/pandas/meta.yaml @@ -8,7 +8,7 @@ package: requirements: build: - ninja - - git+https://github.com/flet-dev/meson@ios-dynamiclib + - meson host: - numpy ^2.0.0 # {% if sdk == 'android' %} diff --git a/recipes/pillow/meta.yaml b/recipes/pillow/meta.yaml index 8f7cfb6a..46c9fa48 100644 --- a/recipes/pillow/meta.yaml +++ b/recipes/pillow/meta.yaml @@ -8,7 +8,7 @@ requirements: - flet-libjpeg 3.0.90 - flet-libfreetype 2.13.3 -# {% if version and version >= (11,0,0) %} +# {% if not version or version >= (11,0,0) %} # pillow >= 11.x patches: @@ -28,4 +28,4 @@ build: # libfreetype references both libz and libbz2 # but doesn't link them into the static library LDFLAGS: -lz -lbz2 -# {% endif %} \ No newline at end of file +# {% endif %} diff --git a/setup.sh b/setup.sh index 1ae4317d..6105bc74 100755 --- a/setup.sh +++ b/setup.sh @@ -146,19 +146,21 @@ if [ ! -z "$MOBILE_FORGE_ANDROID_SUPPORT_PATH" ]; then return fi - if [ ! -e $MOBILE_FORGE_ANDROID_SUPPORT_PATH/install/android/armeabi-v7a/python-$PYTHON_VERSION/bin/python$PYTHON_VER ]; then - echo "MOBILE_FORGE_ANDROID_SUPPORT_PATH does not appear to contain a Python $PYTHON_VERSION Android armeabi-v7a device binary." - return - fi - if [ ! -e $MOBILE_FORGE_ANDROID_SUPPORT_PATH/install/android/x86_64/python-$PYTHON_VERSION/bin/python$PYTHON_VER ]; then echo "MOBILE_FORGE_ANDROID_SUPPORT_PATH does not appear to contain a Python $PYTHON_VERSION Android x86_64 device binary." return fi - if [ ! -e $MOBILE_FORGE_ANDROID_SUPPORT_PATH/install/android/x86/python-$PYTHON_VERSION/bin/python$PYTHON_VER ]; then - echo "MOBILE_FORGE_ANDROID_SUPPORT_PATH does not appear to contain a Python $PYTHON_VERSION Android x86 device binary." - return + if [ "$PYTHON_VER" = "3.12" ]; then + if [ ! -e $MOBILE_FORGE_ANDROID_SUPPORT_PATH/install/android/armeabi-v7a/python-$PYTHON_VERSION/bin/python$PYTHON_VER ]; then + echo "MOBILE_FORGE_ANDROID_SUPPORT_PATH does not appear to contain a Python $PYTHON_VERSION Android armeabi-v7a device binary." + return + fi + + if [ ! -e $MOBILE_FORGE_ANDROID_SUPPORT_PATH/install/android/x86/python-$PYTHON_VERSION/bin/python$PYTHON_VER ]; then + echo "MOBILE_FORGE_ANDROID_SUPPORT_PATH does not appear to contain a Python $PYTHON_VERSION Android x86 device binary." + return + fi fi echo "MOBILE_FORGE_ANDROID_SUPPORT_PATH: $MOBILE_FORGE_ANDROID_SUPPORT_PATH" @@ -184,4 +186,4 @@ echo " forge iphoneos:arm64 lru-dict" echo echo "Build all applicable versions of lru-dict for all iOS targets:" echo " forge iOS --all-versions lru-dict" -echo \ No newline at end of file +echo diff --git a/src/forge/build.py b/src/forge/build.py index b356bb66..04b18aeb 100644 --- a/src/forge/build.py +++ b/src/forge/build.py @@ -64,8 +64,10 @@ def install_requirements(self, target): requirements = [] for requirement in self.package.meta["requirements"][target]: try: - package, version = requirement.split() - if version.startswith("^"): + package, version = requirement.split(maxsplit=1) + if version.startswith((">=", "<=", "!=", "==", "~=", ">", "<")): + specifier = f"{package}{version}" + elif version.startswith("^"): specifier = f"{package}>={version[1:]}" elif version.startswith("~"): specifier = f"{package}~={version[1:]}" @@ -102,10 +104,27 @@ def fix_host_tool_shims(self): [ "#!/bin/sh\n", "'''exec' {} \"$0\" \"$@\"\n".format(python_path), - "' '''\n", + "' '''\n\n", ] + lines[1:] ) + elif ( + len(lines) > 2 + and lines[0].strip() == "#!/bin/sh" + and lines[1].startswith("'''exec' ") + and lines[2].startswith("' '''") + and lines[2].strip() != "' '''" + ): + # Repair legacy malformed shim output where the separator line was + # accidentally merged with Python code (e.g. "' '''import sys"). + log(self.log_file, f"Repairing malformed host shim: {shim}") + suffix = lines[2][len("' '''") :] + repaired = [lines[0], lines[1], "' '''\n"] + if suffix: + repaired.append(suffix) + repaired += lines[3:] + with open(shim, "w") as f: + f.writelines(repaired) @abstractmethod def download_source_url(self): ... @@ -246,18 +265,11 @@ def compile_env(self, **kwargs) -> dict[str, str]: ar = sysconfig_data["AR"] cc = sysconfig_data["CC"] cxx = sysconfig_data["CXX"] - strip = ( - str(Path(ar).parent.joinpath("llvm-strip")) - if ar and self.cross_venv.sdk == "android" - else "strip" - ) - ranlib = ( - str(Path(ar).parent.joinpath("llvm-ranlib")) - if ar and self.cross_venv.sdk == "android" - else "ranlib" - ) + strip = "strip" + ranlib = "ranlib" cflags = self.cross_venv.sysconfig_data["CFLAGS"] cppflags = self.cross_venv.sysconfig_data["CPPFLAGS"] + ndk_sysroot = None # Add install root include if (install_root / "include").is_dir(): @@ -278,6 +290,43 @@ def compile_env(self, **kwargs) -> dict[str, str]: cflags += f" -I{self.cross_venv.sdk_root}/usr/include" cppflags += f" -mios-version-min={self.cross_venv.sdk_version}" + else: + # Some Python Android support archives reference an embedded NDK path + # that isn't present in CI. If NDK_HOME is set, re-point missing + # compiler/binutils paths to that installed NDK toolchain. + ndk_home = os.environ.get("NDK_HOME") + if ndk_home: + prebuilt_dirs = list( + (Path(ndk_home) / "toolchains" / "llvm" / "prebuilt").glob("*") + ) + if prebuilt_dirs: + ndk_bin = prebuilt_dirs[0] / "bin" + if not Path(cc).is_file(): + cc = str(ndk_bin / Path(cc).name) + if not Path(cxx).is_file(): + cxx = str(ndk_bin / Path(cxx).name) + if not Path(ar).is_file(): + ar = str(ndk_bin / Path(ar).name) + if not Path(strip).is_file(): + strip = str(ndk_bin / "llvm-strip") + if not Path(ranlib).is_file(): + ranlib = str(ndk_bin / "llvm-ranlib") + + # Derive strip/ranlib from the final AR location when available. + if ar: + ar_parent = Path(ar).parent + derived_strip = ar_parent / "llvm-strip" + derived_ranlib = ar_parent / "llvm-ranlib" + if derived_strip.is_file(): + strip = str(derived_strip) + if derived_ranlib.is_file(): + ranlib = str(derived_ranlib) + ndk_sysroot = Path(cc).parent.parent / "sysroot" + if (ndk_sysroot / "usr" / "include").is_dir(): + cflags += f" -I{ndk_sysroot}/usr/include" + if self.cross_venv.sdk != "android": + strip = "strip" + ranlib = "ranlib" ldflags = self.cross_venv.sysconfig_data["LDFLAGS"] @@ -288,10 +337,33 @@ def compile_env(self, **kwargs) -> dict[str, str]: if (install_root / "lib").is_dir(): ldflags += f" -L{install_root}/lib" + if self.cross_venv.sdk == "android" and ndk_sysroot: + ndk_triplet_lib = ( + ndk_sysroot + / "usr" + / "lib" + / self.cross_venv.platform_triplet + / str(self.cross_venv.sdk_version) + ) + ndk_arch_lib = ( + ndk_sysroot / "usr" / "lib" / self.cross_venv.platform_triplet + ) + if ndk_triplet_lib.is_dir(): + ldflags += f" -L{ndk_triplet_lib}" + elif ndk_arch_lib.is_dir(): + ldflags += f" -L{ndk_arch_lib}" + + # 16 KB page alignment required by Google Play (Android 15+) + ldflags += " -Wl,-z,max-page-size=16384" + # cargo_ldflags = re.sub(r"-march=[\w-]+", "", ldflags) cargo_ldflags = " -L{}/lib".format(self.cross_venv.sysconfig_data["prefix"]) cargo_ldflags += " -C link-arg=-undefined -C link-arg=dynamic_lookup" + if self.cross_venv.sdk == "android": + # 16 KB page alignment required by Google Play (Android 15+) + cargo_ldflags += " -C link-arg=-z -C link-arg=max-page-size=16384" + if self.cross_venv.sdk != "android": # Replace any hard-coded reference to -isysroot with the actual reference ldflags = re.sub( @@ -338,8 +410,14 @@ def compile_env(self, **kwargs) -> dict[str, str]: "PYO3_CROSS_PYTHON_VERSION": self.cross_venv.sysconfig_data[ "py_version_short" ], - "PYO3_CROSS_LIB_DIR": "{}/lib".format( - self.cross_venv.sysconfig_data["prefix"] + # pyo3 expects a directory containing _sysconfigdata__*.py. + # Newer Apple support layouts place this outside prefix/lib. + "PYO3_CROSS_LIB_DIR": str( + ( + self.cross_venv.host_sysconfig.parent + if self.cross_venv.host_sysconfig is not None + else Path(self.cross_venv.sysconfig_data["prefix"]) / "lib" + ) ), } env.update(kwargs) @@ -361,6 +439,9 @@ def compile_env(self, **kwargs) -> dict[str, str]: if self.cross_venv.sdk == "android": cc_parts = cc.split("/") env["NDK_ROOT"] = "/".join(cc_parts[: cc_parts.index("toolchains")]) + env["NDK_SYSROOT"] = str( + ndk_sysroot or (Path(cc).parent.parent / "sysroot") + ) env["ANDROID_ABI"] = self.cross_venv.arch env["HOST_TRIPLET"] = self.cross_venv.platform_triplet @@ -431,9 +512,23 @@ def write_message_file(self, filename: Path, data): with filename.open("w", encoding="utf-8") as f: generator.Generator(f, maxheaderlen=0).flatten(msg) + @property + def wheel_tag(self) -> str: + return f"py3-none-{self.cross_venv.tag}" + def fix_wheel(self, wheel_dir: Path): log(self.log_file, f"[{self.cross_venv}] Fixing wheel contents") + + # Normalize wheel tags to forge platform tags so repacked wheels use + # android_24_arm64_v8a / ios_13_0_arm64_iphoneos style platform tags. + wheel_metadata_path = next(wheel_dir.glob("*.dist-info")) / "WHEEL" + wheel_metadata = self.read_message_file(wheel_metadata_path) + if "Tag" in wheel_metadata: + del wheel_metadata["Tag"] + wheel_metadata["Tag"] = self.wheel_tag + self.write_message_file(wheel_metadata_path, wheel_metadata) + if self.cross_venv.sdk == "android": env = self.compile_env() @@ -525,7 +620,7 @@ def make_wheel(self): "Root-Is-Purelib": "false", "Generator": "mobile-forge", "Build": build_num, - "Tag": f"py3-none-{self.cross_venv.tag}", + "Tag": self.wheel_tag, }, ) self.write_message_file( @@ -544,6 +639,8 @@ def make_wheel(self): # Re-pack the wheel file log(self.log_file, f"\n[{self.cross_venv}] Packing wheel") + dist_dir = Path.cwd() / "dist" + dist_dir.mkdir(parents=True, exist_ok=True) self.cross_venv.run( self.log_file, [ @@ -553,7 +650,7 @@ def make_wheel(self): "pack", str(self.build_path / "wheel"), "--dest-dir", - str(Path.cwd() / "dist"), + str(dist_dir), "--build-number", str(build_num), ], @@ -630,6 +727,11 @@ def log_file_path(self) -> Path: / f"{self.package.name}-{self.package.version}-cp3{sys.version_info.minor}-{self.cross_venv.tag}.log" ) + @property + def wheel_tag(self) -> str: + py_tag = f"cp3{sys.version_info.minor}" + return f"{py_tag}-{py_tag}-{self.cross_venv.tag}" + def download_source_url(self): return get_pypi_source_urls(self.package.name)[self.package.version] @@ -749,7 +851,9 @@ def _build(self): env = self.compile_env() # Set the cross host platform in the environment - env["_PYTHON_HOST_PLATFORM"] = self.cross_venv.platform_identifier + env["_PYTHON_HOST_PLATFORM"] = self.cross_venv._tag_identifier( + self.cross_venv.sdk, self.cross_venv.sdk_version, self.cross_venv.arch + ) meson_cross_file = self._create_meson_cross(env) @@ -821,6 +925,8 @@ def _build(self): # re-pack the wheel to "dist" log(self.log_file, f"\n[{self.cross_venv}] Packing wheel to dist") + dist_dir = Path.cwd() / "dist" + dist_dir.mkdir(parents=True, exist_ok=True) pack_args = [ "build-python", "-m", @@ -828,7 +934,7 @@ def _build(self): "pack", str(tmp_wheel_dir), "--dest-dir", - str(Path.cwd() / "dist"), + str(dist_dir), ] if self.package.meta["build"]["number"]: pack_args.extend( diff --git a/src/forge/cross.py b/src/forge/cross.py index 30d78f48..33a96340 100644 --- a/src/forge/cross.py +++ b/src/forge/cross.py @@ -20,13 +20,14 @@ class CrossVEnv: "watchOS": "4.0", } + ANDROID_HOST_ARCHS = ( + ("arm64-v8a", "x86_64") + if sys.version_info[:2] >= (3, 13) + else ("arm64-v8a", "armeabi-v7a", "x86_64", "x86") + ) + HOST_SDKS = { - "android": [ - ("android", "arm64-v8a"), - ("android", "armeabi-v7a"), - ("android", "x86_64"), - ("android", "x86"), - ], + "android": [("android", arch) for arch in ANDROID_HOST_ARCHS], "iOS": [ ("iphoneos", "arm64"), ("iphonesimulator", "arm64"), @@ -72,6 +73,12 @@ class CrossVEnv: "x86_64": "x86_64-linux-android", "x86": "i686-linux-android", } + ANDROID_PLATFORM_MACHINE = { + "arm64-v8a": "aarch64", + "armeabi-v7a": "arm", + "x86_64": "x86_64", + "x86": "i686", + } def __init__(self, sdk, sdk_version, arch): self.sdk = sdk @@ -83,7 +90,7 @@ def __init__(self, sdk, sdk_version, arch): }[self.sdk] self.platform_identifier = self._platform_identifier(sdk, sdk_version, arch) self.tag = ( - self._platform_identifier(sdk, sdk_version, arch) + self._tag_identifier(sdk, sdk_version, arch) .replace("-", "_") .replace(".", "_") ) @@ -98,6 +105,7 @@ def __init__(self, sdk, sdk_version, arch): self._scheme_paths = None self._install_root = None self._sdk_root = None + self.host_sysconfig = None def __str__(self): return self.venv_name @@ -227,9 +235,12 @@ def sdk_root(self) -> Path: @classmethod def _platform_identifier(self, sdk, version, arch): if sdk == "android": - if version is None: - version = 21 - identifier = f"{sdk}-{version}-{arch}" + if sys.version_info[:2] >= (3, 13): + identifier = f"{sdk}-{self.ANDROID_PLATFORM_MACHINE[arch]}" + else: + if version is None: + version = 21 + identifier = f"{sdk}-{version}-{arch}" elif sdk in {"iphoneos", "iphonesimulator"}: if version is None: version = "13.0" @@ -246,6 +257,14 @@ def _platform_identifier(self, sdk, version, arch): raise ValueError(f"Don't know how to build wheels for {sdk}") return identifier + @classmethod + def _tag_identifier(self, sdk, version, arch): + if sdk == "android": + if version is None: + version = 21 + return f"{sdk}-{version}-{arch}" + return self._platform_identifier(sdk, version, arch) + def create( self, location=None, @@ -297,6 +316,8 @@ def create( ) self.sysconfigdata_name = host_sysconfig.stem + self.host_sysconfig = host_sysconfig + if self.host_os != "iOS" and not host_sysconfig.is_file(): raise RuntimeError(f"Can't find host sysconfig {host_sysconfig}") From cf7a8e9d3a5c99f29d3638108e703f1aba575164 Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Sun, 29 Mar 2026 14:51:59 -0700 Subject: [PATCH 096/142] Add 16KB ELF alignment check for Android .so files in fix_wheel Parses PT_LOAD segments and fails the build if any shared library has alignment below 16384, catching misaligned binaries early. --- src/forge/build.py | 47 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/src/forge/build.py b/src/forge/build.py index 04b18aeb..0991e51e 100644 --- a/src/forge/build.py +++ b/src/forge/build.py @@ -4,6 +4,7 @@ import os import re import shutil +import struct import sys import tarfile import zipfile @@ -516,6 +517,48 @@ def write_message_file(self, filename: Path, data): def wheel_tag(self) -> str: return f"py3-none-{self.cross_venv.tag}" + def _check_elf_alignment(self, so_path: Path): + """Verify that all PT_LOAD segments are 16KB-aligned.""" + MIN_ALIGNMENT = 16384 + with open(so_path, "rb") as f: + magic = f.read(4) + if magic != b"\x7fELF": + return + ei_class = struct.unpack("B", f.read(1))[0] + is_64 = ei_class == 2 + + # Read e_phoff, e_phentsize, e_phnum from ELF header + if is_64: + f.seek(32) + e_phoff = struct.unpack("= {MIN_ALIGNMENT}. " + f"Library is not 16KB page-aligned." + ) + log(self.log_file, f"[{self.cross_venv}] {so_path.name}: 16KB alignment OK") + def fix_wheel(self, wheel_dir: Path): log(self.log_file, f"[{self.cross_venv}] Fixing wheel contents") @@ -539,6 +582,10 @@ def fix_wheel(self, wheel_dir: Path): [env["STRIP"], "--strip-unneeded", str(so)], ) + # Verify 16KB page alignment (required by Google Play) + for so in wheel_dir.glob("**/*.so"): + self._check_elf_alignment(so) + # add missing requirements from "host" if len(self.package.meta["requirements"]["host"]): metadata_path = next(wheel_dir.glob("*.dist-info")) / "METADATA" From c437240040ee246f11d9b081be040917d529f89a Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Sun, 29 Mar 2026 15:13:48 -0700 Subject: [PATCH 097/142] Skip 16KB alignment check for 32-bit ELFs Only 64-bit ABIs (arm64-v8a, x86_64) require 16KB page alignment. --- src/forge/build.py | 29 ++++++++++------------------- 1 file changed, 10 insertions(+), 19 deletions(-) diff --git a/src/forge/build.py b/src/forge/build.py index 0991e51e..657ce80c 100644 --- a/src/forge/build.py +++ b/src/forge/build.py @@ -525,31 +525,22 @@ def _check_elf_alignment(self, so_path: Path): if magic != b"\x7fELF": return ei_class = struct.unpack("B", f.read(1))[0] - is_64 = ei_class == 2 - - # Read e_phoff, e_phentsize, e_phnum from ELF header - if is_64: - f.seek(32) - e_phoff = struct.unpack(" Date: Sun, 29 Mar 2026 15:19:09 -0700 Subject: [PATCH 098/142] Update libxml2 source URL to GNOME HTTPS Replace the libxml2 2.9.8 source URL from http://xmlsoft.org/.../libxml2-2.9.8.tar.gz to the GNOME HTTPS mirror (https://download.gnome.org/sources/libxml2/2.9/libxml2-2.9.8.tar.xz). Keeps the same version and existing mobile.patch; switches to a secure HTTPS host and the .tar.xz archive format. --- recipes/flet-libxml2/meta.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/recipes/flet-libxml2/meta.yaml b/recipes/flet-libxml2/meta.yaml index 6d9f7375..420c4fbf 100755 --- a/recipes/flet-libxml2/meta.yaml +++ b/recipes/flet-libxml2/meta.yaml @@ -3,7 +3,7 @@ package: version: 2.9.8 source: - url: http://xmlsoft.org/download/libxml2-2.9.8.tar.gz + url: https://download.gnome.org/sources/libxml2/2.9/libxml2-2.9.8.tar.xz patches: - mobile.patch \ No newline at end of file From e922af13f22be954e196634d0bad767c60feb854 Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Sun, 29 Mar 2026 15:20:42 -0700 Subject: [PATCH 099/142] Fix flet-libcrc32c builds --- recipes/flet-libcrc32c/build.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/recipes/flet-libcrc32c/build.sh b/recipes/flet-libcrc32c/build.sh index 3a1cbbaf..0fdc5e15 100755 --- a/recipes/flet-libcrc32c/build.sh +++ b/recipes/flet-libcrc32c/build.sh @@ -3,6 +3,7 @@ set -eu if [ $CROSS_VENV_SDK == "android" ]; then cmake \ + -DCMAKE_POLICY_VERSION_MINIMUM=3.5 \ -DCMAKE_SYSTEM_NAME=Android \ -DANDROID_PLATFORM=$SDK_VERSION \ -DANDROID_ABI=$ANDROID_ABI \ @@ -16,6 +17,7 @@ if [ $CROSS_VENV_SDK == "android" ]; then -DCMAKE_INSTALL_PREFIX="$PREFIX" else cmake \ + -DCMAKE_POLICY_VERSION_MINIMUM=3.5 \ -DCMAKE_SYSTEM_NAME=iOS \ -DCMAKE_OSX_SYSROOT=$SDK \ -DCMAKE_OSX_ARCHITECTURES=$HOST_ARCH \ From 49313c6e29387aab270d06cd289f7b8ced2da798 Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Sun, 29 Mar 2026 15:25:23 -0700 Subject: [PATCH 100/142] Use HTTPS GNOME source for libxslt Update the libxslt recipe source URL to the HTTPS GNOME mirror and .tar.xz archive (libxslt-1.1.32). This replaces the previous http://xmlsoft.org tar.gz link with a secure, canonical download location while keeping the package version unchanged. --- recipes/flet-libxslt/meta.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/recipes/flet-libxslt/meta.yaml b/recipes/flet-libxslt/meta.yaml index 1702c79d..fdf5705b 100755 --- a/recipes/flet-libxslt/meta.yaml +++ b/recipes/flet-libxslt/meta.yaml @@ -3,7 +3,7 @@ package: version: 1.1.32 source: - url: http://xmlsoft.org/download/libxslt-1.1.32.tar.gz + url: https://download.gnome.org/sources/libxslt/1.1/libxslt-1.1.32.tar.xz requirements: host: From 946ed8388d71f6916db82cf9a4d97c60d881c3ba Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Sun, 29 Mar 2026 15:26:37 -0700 Subject: [PATCH 101/142] Use manual workflow_dispatch trigger Replace automatic push and pull_request triggers with workflow_dispatch in .github/workflows/build-wheels-with-cibuildwheel.yml so wheels builds are started manually. This avoids running the expensive CI on every push/PR and gives maintainers control over when to run the build. --- .github/workflows/build-wheels-with-cibuildwheel.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/build-wheels-with-cibuildwheel.yml b/.github/workflows/build-wheels-with-cibuildwheel.yml index a284ed67..8b8a5353 100644 --- a/.github/workflows/build-wheels-with-cibuildwheel.yml +++ b/.github/workflows/build-wheels-with-cibuildwheel.yml @@ -1,8 +1,7 @@ name: wheels-android on: - push: - pull_request: + workflow_dispatch: jobs: build_android_wheels: From f1e8d8c7c6f07de46bf8c4458206a96380b8810b Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Sun, 29 Mar 2026 15:40:41 -0700 Subject: [PATCH 102/142] Disable pkg-config in flet-libcurl build Add --without-pkg-config to the configure invocation in recipes/flet-libcurl/build.sh. This prevents pkg-config from being used during configuration so the provided --with-openssl prefix is respected and system pkg-config metadata won't interfere with the build. --- recipes/flet-libcurl/build.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/recipes/flet-libcurl/build.sh b/recipes/flet-libcurl/build.sh index be944abb..08933c01 100755 --- a/recipes/flet-libcurl/build.sh +++ b/recipes/flet-libcurl/build.sh @@ -8,7 +8,7 @@ if [ ! -f "$OPENSSL_PREFIX/include/openssl/ssl.h" ] || \ OPENSSL_PREFIX="$PYTHON_PREFIX" fi -./configure --host=$HOST_TRIPLET --prefix=$PREFIX --with-openssl="$OPENSSL_PREFIX" +./configure --host=$HOST_TRIPLET --prefix=$PREFIX --with-openssl="$OPENSSL_PREFIX" --without-pkg-config make -j $CPU_COUNT make install From d88482c5e007c9ec974ed275a661a0151eab8089 Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Sun, 29 Mar 2026 15:43:52 -0700 Subject: [PATCH 103/142] Remove Mobile Forge CI workflow Delete .github/workflows/mobile-forge.yml which contained the Mobile Forge CI pipeline for building and publishing Android/iOS wheels (matrix jobs for pydantic-core), including Python/rust/NDK setup, forge packaging steps, and artifact uploads for logs/errors. --- .github/workflows/mobile-forge.yml | 122 ----------------------------- 1 file changed, 122 deletions(-) delete mode 100644 .github/workflows/mobile-forge.yml diff --git a/.github/workflows/mobile-forge.yml b/.github/workflows/mobile-forge.yml deleted file mode 100644 index e9f1c7cd..00000000 --- a/.github/workflows/mobile-forge.yml +++ /dev/null @@ -1,122 +0,0 @@ -name: Mobile Forge CI - -on: - push: - pull_request: - workflow_dispatch: - -env: - PYTHON_VERSION: "3.12.12" - PYTHON_SHORT_VERSION: "3.12" - MOBILE_FORGE_CACHE_DOWNLOADS_OFF: "1" - NDK_VERSION: r27c - -jobs: - build: - name: ${{ matrix.job_name }} - runs-on: ${{ matrix.runner }} - strategy: - fail-fast: false - matrix: - include: - - job_name: "Android: pydantic-core 2.33.2" - runner: ubuntu-latest - forge_arch: android - forge_packages: "pydantic-core:2.33.2" - build_number: "1" - platform: android - - job_name: "iOS: pydantic-core 2.33.2" - runner: macos-latest - forge_arch: iOS - forge_packages: "pydantic-core:2.33.2" - build_number: "1" - platform: ios - - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Set up Python - uses: actions/setup-python@v5 - with: - python-version: ${{ env.PYTHON_SHORT_VERSION }} - - - name: Build and publish wheels - shell: bash - env: - GEMFURY_TOKEN: ${{ secrets.GEMFURY_TOKEN }} - APPVEYOR_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number || '' }} - FORGE_ARCH: ${{ matrix.forge_arch }} - FORGE_PACKAGES: ${{ matrix.forge_packages }} - BUILD_NUMBER: ${{ matrix.build_number }} - PLATFORM: ${{ matrix.platform }} - run: | - set -euxo pipefail - - . .ci/common.sh - export MOBILE_FORGE_ANDROID_SUPPORT_PATH="" - export MOBILE_FORGE_IOS_SUPPORT_PATH="" - - if [[ "$PLATFORM" == "android" ]]; then - sudo apt-get update - sudo apt-get install -y sqlite3 - - python_android_dir="$HOME/projects/python-build/android" - curl -#OL "https://github.com/flet-dev/python-build/releases/download/v${PYTHON_SHORT_VERSION}/python-android-mobile-forge-${PYTHON_SHORT_VERSION}.tar.gz" - mkdir -p "$python_android_dir" - tar -xzf "python-android-mobile-forge-${PYTHON_SHORT_VERSION}.tar.gz" -C "$python_android_dir" - - .ci/install_ndk.sh - - curl https://sh.rustup.rs -sSf | sh -s -- -y - . "$HOME/.cargo/env" - export PATH="$PATH:$HOME/.cargo/bin" - rustup target add aarch64-linux-android - rustup target add arm-linux-androideabi - rustup target add x86_64-linux-android - rustup target add i686-linux-android - - export MOBILE_FORGE_ANDROID_SUPPORT_PATH="$python_android_dir" - else - python_ios_dir="$HOME/projects/python-build/darwin/Python-Apple-support" - curl -#OL "https://github.com/flet-dev/python-build/releases/download/v${PYTHON_SHORT_VERSION}/python-ios-mobile-forge-${PYTHON_SHORT_VERSION}.tar.gz" - mkdir -p "$python_ios_dir" - tar -xzf "python-ios-mobile-forge-${PYTHON_SHORT_VERSION}.tar.gz" -C "$python_ios_dir" - - curl https://sh.rustup.rs -sSf | sh -s -- -y - . "$HOME/.cargo/env" - export PATH="$PATH:$HOME/.cargo/bin" - rustup target add aarch64-apple-ios - rustup target add aarch64-apple-ios-sim - rustup target add x86_64-apple-ios - - export MOBILE_FORGE_IOS_SUPPORT_PATH="$python_ios_dir" - fi - - source ./setup.sh "$PYTHON_VERSION" - export PATH="$PATH:$HOME/.cargo/bin" - - IFS=' ' read -r -a packages <<< "$FORGE_PACKAGES" - for package in "${packages[@]}"; do - forge "$FORGE_ARCH" "$package:$BUILD_NUMBER" - done - - rm -f dist/bzip2-* dist/xz-* dist/openssl-* dist/libffi-* - - if compgen -G "dist/*.whl" > /dev/null; then - publish_to_pypi dist/*.whl - fi - - - name: Upload logs on success - if: ${{ success() && hashFiles('logs/*.log') != '' }} - uses: actions/upload-artifact@v4 - with: - name: ${{ matrix.platform }}-logs-${{ github.run_id }}-${{ github.run_attempt }} - path: logs/*.log - - - name: Upload errors on failure - if: ${{ failure() && hashFiles('errors/*.log') != '' }} - uses: actions/upload-artifact@v4 - with: - name: ${{ matrix.platform }}-errors-${{ github.run_id }}-${{ github.run_attempt }} - path: errors/*.log From ae7c6f792c49e2cfde9d3c5ec97ccdd60300dc4e Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Sun, 29 Mar 2026 15:47:14 -0700 Subject: [PATCH 104/142] Disable Python bindings for Android build Add -DBUILD_PYTHON_BINDINGS=OFF to the Android cmake invocation in recipes/flet-libgdal/build.sh so Python bindings are not built when CROSS_VENV_SDK==android. This prevents attempting to compile Python extensions in the Android cross-compile environment. --- recipes/flet-libgdal/build.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/recipes/flet-libgdal/build.sh b/recipes/flet-libgdal/build.sh index b815f03d..b9008c81 100755 --- a/recipes/flet-libgdal/build.sh +++ b/recipes/flet-libgdal/build.sh @@ -27,7 +27,8 @@ if [ $CROSS_VENV_SDK == "android" ]; then -DGDAL_USE_CURL=OFF \ -DGDAL_USE_LIBXML2=OFF \ -DBUILD_APPS=OFF \ - -DBUILD_TESTING=OFF + -DBUILD_TESTING=OFF \ + -DBUILD_PYTHON_BINDINGS=OFF else cmake .. \ -DCMAKE_SYSTEM_NAME=iOS \ From 63e3f5bb84aebd00f41fd857d5a1aa24a9e5b699 Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Sun, 29 Mar 2026 15:49:23 -0700 Subject: [PATCH 105/142] Disable pkg-config via environment variable Set PKG_CONFIG=false before running configure and remove the --without-pkg-config flag. This forces the configure script to act as if pkg-config is unavailable (helpful for cross-compilation or environments without pkg-config) and avoids passing the configure-specific option. Build and install steps remain unchanged. --- recipes/flet-libcurl/build.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/recipes/flet-libcurl/build.sh b/recipes/flet-libcurl/build.sh index 08933c01..36391d8d 100755 --- a/recipes/flet-libcurl/build.sh +++ b/recipes/flet-libcurl/build.sh @@ -8,7 +8,7 @@ if [ ! -f "$OPENSSL_PREFIX/include/openssl/ssl.h" ] || \ OPENSSL_PREFIX="$PYTHON_PREFIX" fi -./configure --host=$HOST_TRIPLET --prefix=$PREFIX --with-openssl="$OPENSSL_PREFIX" --without-pkg-config +PKG_CONFIG=false ./configure --host=$HOST_TRIPLET --prefix=$PREFIX --with-openssl="$OPENSSL_PREFIX" make -j $CPU_COUNT make install From f601dc94599ae6604ba3038621d0072b89df773f Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Sun, 29 Mar 2026 16:10:09 -0700 Subject: [PATCH 106/142] Skip sys.prefix dirs when cross-compiling Update Pillow setup patch to avoid unconditionally adding sys.prefix lib/include directories when cross-compiling. The change wraps the _add_directory calls for sys.prefix in a check against self.disable_platform_guessing so host headers/libs won't be pulled in during cross-compilation. Also includes minor whitespace/formatting cleanup around initialize_options. --- recipes/pillow/patches/setup-11.x.patch | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/recipes/pillow/patches/setup-11.x.patch b/recipes/pillow/patches/setup-11.x.patch index 640dc1b6..8f119ca3 100644 --- a/recipes/pillow/patches/setup-11.x.patch +++ b/recipes/pillow/patches/setup-11.x.patch @@ -4,7 +4,7 @@ index a85731d..fbbb5b6 100644 +++ b/setup.py @@ -355,9 +355,7 @@ class pil_build_ext(build_ext): return True if value in configuration.get(option, []) else None - + def initialize_options(self) -> None: - self.disable_platform_guessing = self.check_configuration( - "platform-guessing", "disable" @@ -13,3 +13,16 @@ index a85731d..fbbb5b6 100644 self.add_imaging_libs = "" build_ext.initialize_options(self) for x in self.feature: +@@ -548,8 +546,10 @@ class pil_build_ext(build_ext): + for d in os.environ[k].split(os.path.pathsep): + _add_directory(library_dirs, d) + +- _add_directory(library_dirs, os.path.join(sys.prefix, "lib")) +- _add_directory(include_dirs, os.path.join(sys.prefix, "include")) ++ # Skip adding sys.prefix paths when cross-compiling to avoid host headers ++ if not self.disable_platform_guessing: ++ _add_directory(library_dirs, os.path.join(sys.prefix, "lib")) ++ _add_directory(include_dirs, os.path.join(sys.prefix, "include")) + + # + # add platform directories From 3feee10438a0b4d3e1325b7a98639f1af1f4b4b4 Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Sun, 29 Mar 2026 16:16:16 -0700 Subject: [PATCH 107/142] Skip sys.prefix paths when cross-compiling Patch setup.py to avoid adding sys.prefix lib/include directories unconditionally. The sys.prefix paths are now only added when platform guessing is enabled (prevents picking up host headers when cross-compiling). Also includes small comment and whitespace cleanups around environment path handling. --- recipes/pillow/patches/setup-11.x.patch | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/recipes/pillow/patches/setup-11.x.patch b/recipes/pillow/patches/setup-11.x.patch index 8f119ca3..d78195bb 100644 --- a/recipes/pillow/patches/setup-11.x.patch +++ b/recipes/pillow/patches/setup-11.x.patch @@ -1,5 +1,4 @@ diff --git a/setup.py b/setup.py -index a85731d..fbbb5b6 100644 --- a/setup.py +++ b/setup.py @@ -355,9 +355,7 @@ class pil_build_ext(build_ext): @@ -13,13 +12,13 @@ index a85731d..fbbb5b6 100644 self.add_imaging_libs = "" build_ext.initialize_options(self) for x in self.feature: -@@ -548,8 +546,10 @@ class pil_build_ext(build_ext): - for d in os.environ[k].split(os.path.pathsep): +@@ -550,8 +548,10 @@ class pil_build_ext(build_ext): + for d in os.environ[k].split(os.path.pathsep): _add_directory(library_dirs, d) - _add_directory(library_dirs, os.path.join(sys.prefix, "lib")) - _add_directory(include_dirs, os.path.join(sys.prefix, "include")) -+ # Skip adding sys.prefix paths when cross-compiling to avoid host headers ++ # Skip sys.prefix paths when cross-compiling to avoid host headers + if not self.disable_platform_guessing: + _add_directory(library_dirs, os.path.join(sys.prefix, "lib")) + _add_directory(include_dirs, os.path.join(sys.prefix, "include")) From 1a9ea903d37cdfcb5d1bd06232dbede004876a9e Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Sun, 29 Mar 2026 16:29:57 -0700 Subject: [PATCH 108/142] Strip host /usr/ include/lib paths from Pillow cross-compilation The build Python's sysconfig leaks /usr/include into compiler dirs via crossenv, causing glibc headers to shadow NDK sysroot headers on Linux CI runners. --- recipes/pillow/patches/setup-11.x.patch | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/recipes/pillow/patches/setup-11.x.patch b/recipes/pillow/patches/setup-11.x.patch index d78195bb..b438622c 100644 --- a/recipes/pillow/patches/setup-11.x.patch +++ b/recipes/pillow/patches/setup-11.x.patch @@ -25,3 +25,16 @@ diff --git a/setup.py b/setup.py # # add platform directories +@@ -684,6 +684,12 @@ class pil_build_ext(build_ext): + self.compiler.include_dirs = include_dirs + self.compiler.include_dirs + + # ++ # When cross-compiling, remove host system include/lib paths that ++ # leak in from the build Python's sysconfig (e.g. /usr/include). ++ if self.disable_platform_guessing: ++ self.compiler.include_dirs = [d for d in self.compiler.include_dirs if not d.startswith("/usr/")] ++ self.compiler.library_dirs = [d for d in self.compiler.library_dirs if not d.startswith("/usr/")] ++ # + # look for available libraries + + feature = self.feature From 83d75c8a6652a8c5f8e3c862b4467311877d30ce Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Sun, 29 Mar 2026 17:25:46 -0700 Subject: [PATCH 109/142] Relax host dependency pins to minimum versions Update recipes/grpcio/meta.yaml to use >= constraints for host dependencies: openssl >=3.0.15 and flet-libcpp-shared >=27.2.12479018. This relaxes exact version pins to allow newer compatible builds while enforcing minimum required versions. --- recipes/grpcio/meta.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/recipes/grpcio/meta.yaml b/recipes/grpcio/meta.yaml index aa6e54d9..018f9fc5 100644 --- a/recipes/grpcio/meta.yaml +++ b/recipes/grpcio/meta.yaml @@ -21,6 +21,6 @@ patches: # {% if sdk == 'android' %} requirements: host: - - openssl 3.0.15 - - flet-libcpp-shared 27.2.12479018 + - openssl >=3.0.15 + - flet-libcpp-shared >=27.2.12479018 # {% endif %} \ No newline at end of file From 6c5b8fb551dbeb7191faaf6e85b63f1a5452e873 Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Sun, 29 Mar 2026 17:27:51 -0700 Subject: [PATCH 110/142] Pin Cython <3.1 in pyjnius build requirements Add a build requirement for Cython <3.1 to the pyjnius recipe to prevent incompatibilities with newer Cython releases during the build. This updates recipes/pyjnius/meta.yaml to include the pinned Cython version while leaving existing host requirements and patches intact. --- recipes/pyjnius/meta.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/recipes/pyjnius/meta.yaml b/recipes/pyjnius/meta.yaml index 26c42351..9c0b6072 100644 --- a/recipes/pyjnius/meta.yaml +++ b/recipes/pyjnius/meta.yaml @@ -6,5 +6,7 @@ patches: - mobile.patch requirements: + build: + - Cython <3.1 host: - flet-libpyjni 1.0.1 \ No newline at end of file From 9c106129a3d3e251e4a9b50b1c67e87bdf952a4f Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Sun, 29 Mar 2026 17:43:24 -0700 Subject: [PATCH 111/142] Move Android NDK env setup before templating When cross-building for Android, set NDK-related environment variables (NDK_ROOT, NDK_SYSROOT, ANDROID_ABI, ANDROID_API_LEVEL, HOST_TRIPLET) before performing env value templating so formatted values can reference them. Removes the duplicated Android env block that previously ran after templating. --- src/forge/build.py | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/forge/build.py b/src/forge/build.py index 657ce80c..dfa62291 100644 --- a/src/forge/build.py +++ b/src/forge/build.py @@ -423,6 +423,16 @@ def compile_env(self, **kwargs) -> dict[str, str]: } env.update(kwargs) + if self.cross_venv.sdk == "android": + cc_parts = cc.split("/") + env["NDK_ROOT"] = "/".join(cc_parts[: cc_parts.index("toolchains")]) + env["NDK_SYSROOT"] = str( + ndk_sysroot or (Path(cc).parent.parent / "sysroot") + ) + env["ANDROID_ABI"] = self.cross_venv.arch + env["ANDROID_API_LEVEL"] = str(self.cross_venv.sdk_version) + env["HOST_TRIPLET"] = self.cross_venv.platform_triplet + script_vars = { **env, **self.cross_venv.scheme_paths, @@ -437,15 +447,6 @@ def compile_env(self, **kwargs) -> dict[str, str]: else: env[key] = str(value).format(**script_vars) - if self.cross_venv.sdk == "android": - cc_parts = cc.split("/") - env["NDK_ROOT"] = "/".join(cc_parts[: cc_parts.index("toolchains")]) - env["NDK_SYSROOT"] = str( - ndk_sysroot or (Path(cc).parent.parent / "sysroot") - ) - env["ANDROID_ABI"] = self.cross_venv.arch - env["HOST_TRIPLET"] = self.cross_venv.platform_triplet - # Add in some user environment keys that are useful for key in [ "TMPDIR", From dadd96248e6f60b90c635a497d3425c5032bbc62 Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Sun, 29 Mar 2026 18:51:56 -0700 Subject: [PATCH 112/142] Fix grpcio OpenSSL include path for Android cross-compilation grpcio hardcodes /usr/include/openssl for system OpenSSL. Add explicit -I and -L flags pointing to the cross-compiled OpenSSL in opt/. Also apply variable substitution to CFLAGS/LDFLAGS in script_env so {platlib} and other template vars are resolved. --- recipes/grpcio/meta.yaml | 4 ++-- src/forge/build.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/recipes/grpcio/meta.yaml b/recipes/grpcio/meta.yaml index 018f9fc5..560282a0 100644 --- a/recipes/grpcio/meta.yaml +++ b/recipes/grpcio/meta.yaml @@ -8,8 +8,8 @@ build: GRPC_PYTHON_BUILD_SYSTEM_OPENSSL: '1' GRPC_PYTHON_BUILD_SYSTEM_ZLIB: '1' PLATFORM: android - CFLAGS: '-U__ANDROID_API__ -D__ANDROID_API__={{ sdk_version }} -Wno-reserved-user-defined-literal' - LDFLAGS: '-llog' + CFLAGS: '-U__ANDROID_API__ -D__ANDROID_API__={{ sdk_version }} -Wno-reserved-user-defined-literal -I{platlib}/opt/include' + LDFLAGS: '-llog -L{platlib}/opt/lib' # {% else %} CXXFLAGS: -std=c++14 -Wno-c++11-narrowing LDFLAGS: '-framework CoreFoundation' diff --git a/src/forge/build.py b/src/forge/build.py index dfa62291..e50849d4 100644 --- a/src/forge/build.py +++ b/src/forge/build.py @@ -443,7 +443,7 @@ def compile_env(self, **kwargs) -> dict[str, str]: # Set up any additional environment variables needed in the script environment. for key, value in self.package.meta["build"]["script_env"].items(): if key in ["LDFLAGS", "CFLAGS", "CPPFLAGS"]: - env[key] += " " + value + env[key] += " " + str(value).format(**script_vars) else: env[key] = str(value).format(**script_vars) From d1d358eeb27504f0cfb1ce4ab0994ac492522425 Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Tue, 31 Mar 2026 12:23:16 -0700 Subject: [PATCH 113/142] Fix grpcio OpenSSL discovery for Android via OPENSSL_ROOT_DIR grpcio hardcodes /usr/include/openssl for system OpenSSL. Patch setup.py to read OPENSSL_ROOT_DIR env var and set it in the recipe to point to the cross-compiled OpenSSL in site-packages/opt. --- recipes/grpcio/meta.yaml | 3 ++- recipes/grpcio/patches/mobile.patch | 30 ++++++++++------------------- 2 files changed, 12 insertions(+), 21 deletions(-) diff --git a/recipes/grpcio/meta.yaml b/recipes/grpcio/meta.yaml index 560282a0..cc1b03f4 100644 --- a/recipes/grpcio/meta.yaml +++ b/recipes/grpcio/meta.yaml @@ -8,7 +8,8 @@ build: GRPC_PYTHON_BUILD_SYSTEM_OPENSSL: '1' GRPC_PYTHON_BUILD_SYSTEM_ZLIB: '1' PLATFORM: android - CFLAGS: '-U__ANDROID_API__ -D__ANDROID_API__={{ sdk_version }} -Wno-reserved-user-defined-literal -I{platlib}/opt/include' + OPENSSL_ROOT_DIR: '{platlib}/opt' + CFLAGS: '-U__ANDROID_API__ -D__ANDROID_API__={{ sdk_version }} -Wno-reserved-user-defined-literal' LDFLAGS: '-llog -L{platlib}/opt/lib' # {% else %} CXXFLAGS: -std=c++14 -Wno-c++11-narrowing diff --git a/recipes/grpcio/patches/mobile.patch b/recipes/grpcio/patches/mobile.patch index 418c12a1..946a1c05 100644 --- a/recipes/grpcio/patches/mobile.patch +++ b/recipes/grpcio/patches/mobile.patch @@ -1,5 +1,4 @@ diff --git a/setup.py b/setup.py -index 48bfefe..ff21bc5 100644 --- a/setup.py +++ b/setup.py @@ -58,12 +58,14 @@ CARES_INCLUDE = ( @@ -18,22 +17,13 @@ index 48bfefe..ff21bc5 100644 if "openbsd" in sys.platform: CARES_INCLUDE += (os.path.join("third_party", "cares", "config_openbsd"),) RE2_INCLUDE = (os.path.join("third_party", "re2"),) -@@ -329,15 +331,16 @@ EXTENSION_INCLUDE_DIRECTORIES = ( - + ADDRESS_SORTING_INCLUDE - + CARES_INCLUDE - + RE2_INCLUDE -- + SSL_INCLUDE - + UPB_INCLUDE - + UPB_GRPC_GENERATED_INCLUDE - + UPBDEFS_GRPC_GENERATED_INCLUDE - + UTF8_RANGE_INCLUDE - + XXHASH_INCLUDE -- + ZLIB_INCLUDE - ) - -+if "android" not in sys.platform: -+ EXTENSION_INCLUDE_DIRECTORIES += SSL_INCLUDE + ZLIB_INCLUDE -+ - EXTENSION_LIBRARIES = () - if "linux" in sys.platform: - EXTENSION_LIBRARIES += ("rt",) +@@ -304,7 +306,9 @@ if BUILD_WITH_SYSTEM_OPENSSL: + ) + CORE_C_FILES = filter(lambda x: "src/boringssl" not in x, CORE_C_FILES) +- SSL_INCLUDE = (os.path.join("/usr", "include", "openssl"),) ++ # Use cross-compiled OpenSSL headers when OPENSSL_ROOT_DIR is set ++ _ssl_prefix = os.environ.get("OPENSSL_ROOT_DIR", "/usr") ++ SSL_INCLUDE = (os.path.join(_ssl_prefix, "include"),) + + if BUILD_WITH_SYSTEM_ZLIB: + CORE_C_FILES = filter(lambda x: "third_party/zlib" not in x, CORE_C_FILES) From 16a5fb25e4f03b9da7eb98b6104fd59ad4dd50a0 Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Tue, 31 Mar 2026 12:57:03 -0700 Subject: [PATCH 114/142] Fix grpcio patch: restore ZLIB_INCLUDE exclusion for Android ZLIB_INCLUDE adds /usr/include which leaks host glibc headers on CI. Keep SSL_INCLUDE (now via OPENSSL_ROOT_DIR) always, skip ZLIB_INCLUDE on Android only. --- recipes/grpcio/patches/mobile.patch | 32 +++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/recipes/grpcio/patches/mobile.patch b/recipes/grpcio/patches/mobile.patch index 946a1c05..89c6c1ac 100644 --- a/recipes/grpcio/patches/mobile.patch +++ b/recipes/grpcio/patches/mobile.patch @@ -1,7 +1,6 @@ -diff --git a/setup.py b/setup.py ---- a/setup.py -+++ b/setup.py -@@ -58,12 +58,14 @@ CARES_INCLUDE = ( +--- a/setup.py 2026-03-31 12:55:12 ++++ b/setup.py 2026-03-31 12:56:03 +@@ -58,12 +58,14 @@ os.path.join("third_party", "cares"), os.path.join("third_party", "cares", "cares"), ) @@ -17,13 +16,34 @@ diff --git a/setup.py b/setup.py if "openbsd" in sys.platform: CARES_INCLUDE += (os.path.join("third_party", "cares", "config_openbsd"),) RE2_INCLUDE = (os.path.join("third_party", "re2"),) -@@ -304,7 +306,9 @@ if BUILD_WITH_SYSTEM_OPENSSL: +@@ -302,7 +304,9 @@ + lambda x: "third_party/boringssl" not in x, CORE_C_FILES ) CORE_C_FILES = filter(lambda x: "src/boringssl" not in x, CORE_C_FILES) - SSL_INCLUDE = (os.path.join("/usr", "include", "openssl"),) + # Use cross-compiled OpenSSL headers when OPENSSL_ROOT_DIR is set + _ssl_prefix = os.environ.get("OPENSSL_ROOT_DIR", "/usr") + SSL_INCLUDE = (os.path.join(_ssl_prefix, "include"),) - + if BUILD_WITH_SYSTEM_ZLIB: CORE_C_FILES = filter(lambda x: "third_party/zlib" not in x, CORE_C_FILES) +@@ -329,14 +333,17 @@ + + ADDRESS_SORTING_INCLUDE + + CARES_INCLUDE + + RE2_INCLUDE +- + SSL_INCLUDE + + UPB_INCLUDE + + UPB_GRPC_GENERATED_INCLUDE + + UPBDEFS_GRPC_GENERATED_INCLUDE + + UTF8_RANGE_INCLUDE + + XXHASH_INCLUDE +- + ZLIB_INCLUDE + ) ++ ++# On Android, SSL_INCLUDE uses OPENSSL_ROOT_DIR; skip ZLIB_INCLUDE to avoid /usr/include ++EXTENSION_INCLUDE_DIRECTORIES += SSL_INCLUDE ++if "android" not in sys.platform: ++ EXTENSION_INCLUDE_DIRECTORIES += ZLIB_INCLUDE + + EXTENSION_LIBRARIES = () + if "linux" in sys.platform: From 42284b1c040eeaf2bbc071f4c7416f1b2c078e5b Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Tue, 31 Mar 2026 13:55:56 -0700 Subject: [PATCH 115/142] Add 16KB page alignment to opencv-python CMake build opencv-python uses scikit-build/CMake which doesn't inherit LDFLAGS. Pass -DCMAKE_SHARED_LINKER_FLAGS with max-page-size=16384 via CMAKE_ARGS. --- recipes/opencv-python/meta.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/recipes/opencv-python/meta.yaml b/recipes/opencv-python/meta.yaml index 639906a2..4aaa6038 100644 --- a/recipes/opencv-python/meta.yaml +++ b/recipes/opencv-python/meta.yaml @@ -27,6 +27,7 @@ build: -DANDROID_NATIVE_API_LEVEL={ANDROID_API_LEVEL} -DANDROID_ALLOW_UNDEFINED_VERSION_SCRIPT_SYMBOLS=1 -DCMAKE_TOOLCHAIN_FILE={NDK_ROOT}/build/cmake/android.toolchain.cmake + -DCMAKE_SHARED_LINKER_FLAGS="-Wl,-z,max-page-size=16384" -DOPENCV_FORCE_PYTHON_LIBS=ON -DPYTHON3_INCLUDE_PATH={prefix}/include/python{py_version_short} -DPYTHON3_LIBRARIES={prefix}/lib/libpython{py_version_short}.so From b54a4ea8fffdf01c512e4413863affa511ebb527 Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Tue, 31 Mar 2026 16:01:12 -0700 Subject: [PATCH 116/142] Add CMAKE_MODULE_LINKER_FLAGS for opencv-python 16KB alignment cv2.abi3.so is a CMake MODULE, not SHARED library, so it needs CMAKE_MODULE_LINKER_FLAGS in addition to CMAKE_SHARED_LINKER_FLAGS. --- recipes/opencv-python/meta.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/recipes/opencv-python/meta.yaml b/recipes/opencv-python/meta.yaml index 4aaa6038..12989d1a 100644 --- a/recipes/opencv-python/meta.yaml +++ b/recipes/opencv-python/meta.yaml @@ -28,6 +28,7 @@ build: -DANDROID_ALLOW_UNDEFINED_VERSION_SCRIPT_SYMBOLS=1 -DCMAKE_TOOLCHAIN_FILE={NDK_ROOT}/build/cmake/android.toolchain.cmake -DCMAKE_SHARED_LINKER_FLAGS="-Wl,-z,max-page-size=16384" + -DCMAKE_MODULE_LINKER_FLAGS="-Wl,-z,max-page-size=16384" -DOPENCV_FORCE_PYTHON_LIBS=ON -DPYTHON3_INCLUDE_PATH={prefix}/include/python{py_version_short} -DPYTHON3_LIBRARIES={prefix}/lib/libpython{py_version_short}.so From 62c8f335d002bfe22929073b415ad315c19e3d81 Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Wed, 1 Apr 2026 07:31:38 -0700 Subject: [PATCH 117/142] Fix host dependency version handling in wheel METADATA Use exact version (==) by default, preserve explicit specifiers like >=, and handle dependencies without versions. Fixes double >= in output. --- src/forge/build.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/forge/build.py b/src/forge/build.py index e50849d4..eb177d74 100644 --- a/src/forge/build.py +++ b/src/forge/build.py @@ -588,8 +588,15 @@ def fix_wheel(self, wheel_dir: Path): self.log_file, f"[{self.cross_venv}] Adding {req} requirement to METADATA", ) - req_name, req_ver = req.split(" ") - metadata["Requires-Dist"] = f"{req_name} (>={req_ver})" + parts = req.split(" ", 1) + req_name = parts[0] + if len(parts) > 1: + req_ver = parts[1] + if req_ver[0].isdigit(): + req_ver = f"=={req_ver}" + metadata["Requires-Dist"] = f"{req_name} ({req_ver})" + else: + metadata["Requires-Dist"] = req_name self.write_message_file(metadata_path, metadata) From cbcb145b1325e5b56b4089e68812398fe661e28d Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Mon, 4 May 2026 17:17:16 -0700 Subject: [PATCH 118/142] Bump libxml2/libxslt/lxml; add recipe-bump skill (#48) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Bump flet-libxml2 to 2.15.3 Drive the source URL and patch selection from a single Jinja version variable so switching back to 2.9.8 still builds. Replace the old mobile.patch (config.sub iOS triplets + libxml2.syms tweaks for the 2.9 layout) with two version-targeted patches: mobile-2.9.x.patch keeps the original content, mobile-2.15.x.patch only teaches the modernized config.sub about *-apple-ios-simulator. build.sh: pass --without-iconv on Android (NDK bionic lacks iconv until API 28; 2.15.x makes it mandatory by default while 2.9.x silently soft-failed). Make the post-install cleanup tolerate the 2.15.x layout where share/ is no longer created and globs may not match (nullglob + rm -rf). * Bump flet-libxslt to 1.1.45; ship static archives in iOS wheels flet-libxslt: drive version, libxml2 host requirement, and patch selection from a single Jinja block (numpy-style). Replace the old mobile.patch (config.sub iOS triplets for the 1.1.32 layout) with two version-targeted patches: mobile-1.1.32.patch keeps the original content, mobile-1.1.45.patch only teaches the modernized config.sub about *-apple-ios-simulator. 1.1.45 pulls in flet-libxml2 2.15.3 to satisfy its >= 2.15.1 requirement. build.sh: only recurse into libxslt/libexslt subdirs. xsltproc links -lxml2 and on iOS the SDK's libxml2.tbd predates 1.1.45's use of xmlCtxtParseDocument / xmlXPathValuePush, so the CLI binary fails to link; the wheel only needs the libraries. Same cleanup robustness fix as libxml2 (nullglob + rm -rf). flet-libxml2 + flet-libxslt build.sh: stop deleting *.a from the wheel's lib/. iOS only builds static libs, so the previous cleanup left lib/ empty and forced downstream packages onto dynamic_lookup or the SDK stub. Android only builds shared libs (no *.a produced), so this is a no-op there. flet-libxml2/meta.yaml: switch to the comment-prefixed Jinja idiom (# {% ... %}) so YAML linters parse it cleanly, matching numpy and flet-libxslt. * Bump lxml to 6.1.0 Drive version, libxml2/libxslt host pinning, and the iOS-only LDFLAGS=-liconv from a single Jinja block. lxml 5.x doesn't compile against libxml2 2.15 (per upstream's CHANGES) so the older lxml version stays paired with libxml2 2.9.8 / libxslt 1.1.32. iOS libxml2.a now references iconv (it's built --with-iconv against the system libiconv), and lxml's libraries() list omits iconv on non-Windows non-static builds. Add -liconv via script_env LDFLAGS on iOS only — Android's libxml2 is built --without-iconv and doesn't need it. The existing mobile.patch (filter MacOSX SDK include path out of xml2-config --cflags) still applies cleanly to 6.1.0. * Add native-recipe-bumps skill Captures the conventions used while bumping flet-libxml2 (2.9.8 → 2.15.3), flet-libxslt (1.1.32 → 1.1.45), and lxml (5.3.0 → 6.1.0): the comment-prefixed Jinja idiom for version-conditional meta.yaml (URL, host pins, patch filename in one block), the build.sh quirks that bit us (bash 3.2 + set -u, nullglob cleanup, keeping *.a in the wheel, SUBDIRS overrides, --without-iconv on Android), the pitfall catalogue (iOS SDK libxml2.tbd, lxml's missing -liconv, config.sub ios-simulator gap, libxml2.syms removed in 2.10), and the forge CLI surface for re-running builds. --- .claude/skills/native-recipe-bumps/SKILL.md | 232 ++++++++++++++++++ recipes/flet-libxml2/build.sh | 14 +- recipes/flet-libxml2/meta.yaml | 13 +- .../flet-libxml2/patches/mobile-2.15.x.patch | 14 ++ .../{mobile.patch => mobile-2.9.x.patch} | 0 recipes/flet-libxslt/build.sh | 13 +- recipes/flet-libxslt/meta.yaml | 17 +- .../{mobile.patch => mobile-1.1.32.patch} | 0 .../flet-libxslt/patches/mobile-1.1.45.patch | 14 ++ recipes/lxml/meta.yaml | 20 +- 10 files changed, 320 insertions(+), 17 deletions(-) create mode 100644 .claude/skills/native-recipe-bumps/SKILL.md create mode 100644 recipes/flet-libxml2/patches/mobile-2.15.x.patch rename recipes/flet-libxml2/patches/{mobile.patch => mobile-2.9.x.patch} (100%) rename recipes/flet-libxslt/patches/{mobile.patch => mobile-1.1.32.patch} (100%) create mode 100644 recipes/flet-libxslt/patches/mobile-1.1.45.patch diff --git a/.claude/skills/native-recipe-bumps/SKILL.md b/.claude/skills/native-recipe-bumps/SKILL.md new file mode 100644 index 00000000..c3776b63 --- /dev/null +++ b/.claude/skills/native-recipe-bumps/SKILL.md @@ -0,0 +1,232 @@ +--- +name: native-recipe-bumps +description: Playbook for bumping native-library recipes in mobile-forge (libxml2, libxslt, openssl-class C deps and their consumers). Covers the Jinja-templated meta.yaml pattern for version-conditional URLs / patches / host pins, the build.sh quirks for cross-compiling autotools projects to iOS and Android (NDK r27d, API 24, Python 3.12), and the recurring pitfalls (iconv on Android, iOS static-only builds, bash 3.2 + set -u, etc). +--- + +# Bumping native-library recipes in mobile-forge + +This skill captures conventions for editing recipes in `recipes//` so that: +- the new version builds on iPhoneOS, iPhoneSimulator, and Android API 24, and +- the recipe stays back-compatible — flipping one Jinja `version` line at the top reverts to the previously-pinned version (URL, patches, host deps follow automatically). + +## File layout per recipe + +``` +recipes// + meta.yaml # rendered through Jinja before YAML parsing + build.sh # optional; for autotools / make-based deps + patches/ + mobile-.patch # one per supported version line + mobile-.patch +``` + +## meta.yaml: the Jinja idiom + +`src/forge/package.py` runs the file through `jinja2.Template(...).render(sdk=..., sdk_version=..., arch=..., version=..., py_version=...)` *before* `yaml.safe_load`. Two patterns matter: + +**1. Comment-prefixed Jinja (`# {% ... %}`)** — the only form that keeps the YAML linter happy. `{% set %}` / `{% if %}` lines that don't produce YAML output should always be `# {% ... %}`. The `#` plus blank rendered output is a no-op for YAML. This is the same idiom `recipes/numpy/meta.yaml` uses. + +**2. Single conditional block sets every dependent variable** — version, host-dep versions, patch filename, anything else that branches by version. Then the body of the file just interpolates `{{ var }}`. Avoid scattering multiple `{% if %}` blocks throughout the file. + +Canonical shape (from `recipes/flet-libxslt/meta.yaml`): + +```yaml +# {% set version = "1.1.45" %} +# {% if version == "1.1.32" %} +# {% set libxml2_version = "2.9.8" %} +# {% set patch = "mobile-1.1.32.patch" %} +# {% else %} +# {% set libxml2_version = "2.15.3" %} +# {% set patch = "mobile-1.1.45.patch" %} +# {% endif %} + +package: + name: flet-libxslt + version: '{{ version }}' + +source: + url: https://download.gnome.org/sources/libxslt/{{ version.rsplit('.', 1)[0] }}/libxslt-{{ version }}.tar.xz + +requirements: + host: + - flet-libxml2 {{ libxml2_version }} + +patches: + - {{ patch }} +``` + +To go back to 1.1.32: change one line at the top — URL, host requirement, and patch all flip in lockstep. + +### URL templating for GNOME tarballs + +`https://download.gnome.org/sources///-.tar.xz` — directory is major.minor, file is full version: + +``` +url: https://download.gnome.org/sources/libxml2/{{ version.rsplit('.', 1)[0] }}/libxml2-{{ version }}.tar.xz +``` + +`version.rsplit('.', 1)[0]` turns `2.15.3` → `2.15`, `2.9.8` → `2.9`. + +### SDK-conditional script_env + +The Jinja `sdk` variable holds `'iphoneos'`, `'iphonesimulator'`, or `'android'`. The framework formats `script_env.LDFLAGS / CFLAGS / CPPFLAGS` by *appending* to the compiler-derived value (other keys are set verbatim). Use this for platform-specific link flags: + +```yaml +build: + script_env: + WITH_XML2_CONFIG: '{platlib}/opt/bin/xml2-config' +# {% if sdk != 'android' %} + LDFLAGS: -liconv +# {% endif %} +``` + +`numpy/meta.yaml` writes `sdk == 'iOS'` — that branch never matches the values that are actually passed (the per-slice SDK names). Don't copy that comparison; use `sdk == 'iphoneos'` / `sdk == 'iphonesimulator'` / `sdk == 'android'`. + +## Patches + +Patches in `meta.yaml`'s `patches:` list are simple filenames in `patches/`. The framework has *no* conditional-patch support — don't extend the schema for it. Put the conditional in Jinja: + +- one patch file per supported version line, named `mobile-.patch` +- `# {% set patch = "mobile-X.Y.x.patch" %}` inside the version block +- `patches: [{{ patch }}]` in the body + +When a patch needs to apply across both old and new versions (e.g. lxml's `setupinfo.py` macOS-SDK filter), keep it as a single `mobile.patch` and don't introduce conditional naming. Verify with `patch --dry-run -p1 --ignore-whitespace < patches/mobile.patch` against both extracted tarballs before committing. + +### Renaming with `git mv` + +When splitting `mobile.patch` into `mobile-X.Y.x.patch` + `mobile-A.B.x.patch`, do `git mv` for the original then add the new file — git detects the rename and history is preserved. + +## build.sh patterns + +### Bash 3.2 + `set -u` compatibility + +macOS still ships bash 3.2. Two gotchas: + +- **No bash arrays for optional flags** — `"${arr[@]}"` on an empty array under `set -u` errors with `unbound variable`. Use a plain string: + ```bash + if [ "$CROSS_VENV_SDK" = "android" ]; then + iconv_arg=--without-iconv + else + iconv_arg=--with-iconv + fi + ./configure ... $iconv_arg + ``` +- **`shopt -s nullglob` for cleanup globs** — without it, `rm -r $PREFIX/lib/*.la` passes literal `*.la` when nothing matches and fails. Combined with `rm -rf` it makes cleanup tolerant of layout changes between versions. + +### Cleanup recipe + +```bash +shopt -s nullglob +rm -rf $PREFIX/share +rm -rf $PREFIX/lib/cmake $PREFIX/lib/pkgconfig $PREFIX/lib/*.la $PREFIX/lib/*.sh +``` + +**Do *not* delete `*.a`.** iOS only builds static archives. Removing them leaves `lib/` empty, and downstream consumers (lxml, libxslt) that want to link statically have nothing to find. Android only produces `*.so` so the `.a` line would be a no-op there anyway. + +### Available env vars in build.sh + +The framework exposes (see `compile()` in `src/forge/build.py`): + +- `HOST_TRIPLET`, `HOST_ARCH`, `BUILD_TRIPLET` +- `SDK`, `SDK_VERSION`, `SDK_ROOT` (empty for Android) +- `CROSS_VENV_SDK` — same as `SDK`, the canonical "is this Android?" check +- `PREFIX` — install root (`/wheel/opt`) +- `PYTHON_PREFIX`, `PLATLIB` +- `CPU_COUNT`, plus `CC` / `CXX` / `AR` / `STRIP` / `RANLIB` / `CFLAGS` / `CPPFLAGS` / `LDFLAGS` + +There is **no** `RECIPE_DIR` env var. Don't try to apply patches from build.sh — let the framework's `patch_source()` do it. + +### Skipping CLI binary subdirs + +When a project's autotools build links a CLI tool against the library and that tool can't be linked on iOS (e.g. xsltproc using libxml2 symbols not in the iOS SDK's `libxml2.tbd`), restrict recursion: + +```bash +make -j $CPU_COUNT V=1 SUBDIRS='lib1 lib2' +make install SUBDIRS='lib1 lib2' +``` + +This is cleaner than fighting the linker — wheels don't ship CLI tools anyway. + +## Cross-compile pitfalls (catalogue) + +- **Android NDK r27d API 24 has no `iconv`** in bionic (added in API 28). For libxml2 ≥ 2.10 configure makes iconv mandatory by default (silent soft-fail in 2.9.x). Pass `--without-iconv` for Android only; iOS has system iconv. +- **iOS builds static-only**, Android builds shared-only with this toolchain. Don't assume both produce both. +- **iOS SDK ships `libxml2.tbd` with an *old* libxml2 API.** When statically linking our newer libxml2 into a CLI binary, the linker pulls the SDK stub for unresolved transitive symbols and fails. For a wheel target this only matters if you build a binary; for shared-object Python extensions, dyld resolves at load time so it's fine. +- **iOS linker doesn't auto-add `-liconv`.** When libxml2 is built with iconv and linked statically into something else, the consumer must add `-liconv` explicitly. lxml's `setupinfo.libraries()` lists `xslt exslt xml2 z m` only, so push `-liconv` via `script_env.LDFLAGS` for non-Android. +- **macOS SDK include leaks into cross-build.** lxml's `xml2-config --cflags` parsing picks up `-I…/MacOSX.sdk/usr/include`. The recipe ships a `mobile.patch` to filter that out — apply or carry forward when bumping lxml. +- **Header reshuffles.** libxml2 < 2.15 installs to `$includedir/libxml2/libxml`; the build.sh `mv $PREFIX/include/libxml2/libxml $PREFIX/include` flatten still applies in 2.15.x — re-check on future bumps. +- **`libxml2.syms` was removed upstream around 2.10.** Old `mobile.patch`es that comment out `docb*` / `xmlDllMain` symbols don't apply to ≥ 2.10 and are unnecessary there (modern config.sub already handles `*-apple-ios`). +- **`config.sub` in modern releases handles `*-apple-ios` natively** but still rejects `*-apple-ios-simulator` (kernel=ios, os=simulator combo not whitelisted). The minimal patch is to add an `ios-simulator*)` case in the `case $basic_os in` block that sets `kernel=` and `os=$basic_os`. + +## Verification before re-running `forge build` + +Cheap checks worth doing in-shell, without spinning up the cross-venv: + +```bash +# Render meta.yaml with both target versions and inspect the parsed result +source venv3.12/bin/activate && python -c " +import jinja2, yaml +with open('recipes//meta.yaml') as f: + tpl = f.read() +for v in ['', '']: + src = tpl.replace('', v, 1) if v != '' else tpl + rendered = jinja2.Template(src).render(sdk='iphoneos', sdk_version='13.0', arch='arm64', version=None, py_version=None) + print(yaml.safe_load(rendered)) +" + +# Confirm patches still apply against fresh tarballs +cd /tmp && tar xf -.tar.xz && cd - +patch --dry-run -p1 --ignore-whitespace < /path/to/recipes//patches/mobile-.patch + +# Quick triplet sanity check on a config.sub patch +./config.sub aarch64-apple-ios-simulator +./config.sub x86_64-apple-ios-simulator +./config.sub aarch64-linux-android +``` + +Render with both `sdk='iphoneos'` and `sdk='android'` whenever the file has SDK conditionals. + +## Build / debug loop + +`forge` takes a *host* (top-level platform name like `iOS`/`android`, or a `platform:arch` / `platform:version:arch` triple) followed by one or more recipe names. There is no `build` subcommand. + +```bash +# Single arch — fastest iteration, good for quick tests +forge iphoneos:arm64 flet-libxslt +forge iphonesimulator:arm64 flet-libxslt +forge iphonesimulator:x86_64 flet-libxslt +forge android:arm64-v8a flet-libxslt +forge android:armeabi-v7a flet-libxslt +forge android:x86_64 flet-libxslt +forge android:x86 flet-libxslt + +# All arches for one platform +forge iOS flet-libxslt +forge android flet-libxslt + +# Override the version without editing meta.yaml (':') +forge android flet-libxslt:1.1.32 +forge iphoneos:arm64 lxml:5.3.0 + +# Override version + build number (':::' or '::') +forge android flet-libxslt:1.1.45::1 + +# Useful flags +forge --clean iphoneos:arm64 flet-libxml2 # wipe build dir first +forge -v iOS lxml # verbose log +forge --all-versions iOS lxml # build every supported version +``` + +Recipes can also be addressed by path (anything containing a slash): `forge iOS ./recipes/lxml`. + +After a failure, the latest log lives at `errors/--.log` (or `errors/--cp312-.log` for Python packages). It includes the full stderr+stdout *plus* the recipe's environment dumped near the bottom — useful for confirming `CROSS_VENV_SDK`, `PREFIX`, etc. were what you expected. + +When a build mostly succeeds and dies in cleanup, look at the last `<<< Return code: N` line and the immediately preceding shell error — most "failed" libxml2/libxslt builds are post-install `rm` errors, not real build failures. + +## Recipes that already follow these conventions + +- `recipes/flet-libxml2/` — Jinja version + iconv conditional in build.sh, two version-suffixed patches. +- `recipes/flet-libxslt/` — single Jinja block sets version + libxml2 dep + patch; SUBDIRS override to skip xsltproc. +- `recipes/lxml/` — version-conditional libxml2/libxslt host pins; SDK-conditional `LDFLAGS=-liconv`; carries `mobile.patch` for the macOS SDK include filter. +- `recipes/flet-libopaque/` — minimal `{% set version %}` + URL template, no version branching needed. +- `recipes/numpy/` — selective patch via Jinja + override-version (`{% if version and version < (2, 0) %}`); shows the override-driven pattern when versions need to be flippable from the CLI rather than the meta.yaml itself. diff --git a/recipes/flet-libxml2/build.sh b/recipes/flet-libxml2/build.sh index fd4f9f82..9d8bc951 100755 --- a/recipes/flet-libxml2/build.sh +++ b/recipes/flet-libxml2/build.sh @@ -1,12 +1,20 @@ #!/bin/bash set -eu -./configure --host=$HOST_TRIPLET --prefix=$PREFIX --without-python +# Android NDK bionic does not expose iconv until API 28; we target 24. +if [ "$CROSS_VENV_SDK" = "android" ]; then + iconv_arg=--without-iconv +else + iconv_arg=--with-iconv +fi + +./configure --host=$HOST_TRIPLET --prefix=$PREFIX --without-python $iconv_arg make -j $CPU_COUNT make install mv $PREFIX/include/libxml2/libxml $PREFIX/include rm -r $PREFIX/include/libxml2 -rm -r $PREFIX/share -rm -r $PREFIX/lib/{cmake,pkgconfig,*.a,*.la,*.sh} \ No newline at end of file +shopt -s nullglob +rm -rf $PREFIX/share +rm -rf $PREFIX/lib/cmake $PREFIX/lib/pkgconfig $PREFIX/lib/*.la $PREFIX/lib/*.sh \ No newline at end of file diff --git a/recipes/flet-libxml2/meta.yaml b/recipes/flet-libxml2/meta.yaml index 420c4fbf..83d36302 100755 --- a/recipes/flet-libxml2/meta.yaml +++ b/recipes/flet-libxml2/meta.yaml @@ -1,9 +1,16 @@ +# {% set version = "2.15.3" %} +# {% if version.startswith('2.9.') %} +# {% set patch = "mobile-2.9.x.patch" %} +# {% else %} +# {% set patch = "mobile-2.15.x.patch" %} +# {% endif %} + package: name: flet-libxml2 - version: 2.9.8 + version: '{{ version }}' source: - url: https://download.gnome.org/sources/libxml2/2.9/libxml2-2.9.8.tar.xz + url: https://download.gnome.org/sources/libxml2/{{ version.rsplit('.', 1)[0] }}/libxml2-{{ version }}.tar.xz patches: - - mobile.patch \ No newline at end of file + - {{ patch }} diff --git a/recipes/flet-libxml2/patches/mobile-2.15.x.patch b/recipes/flet-libxml2/patches/mobile-2.15.x.patch new file mode 100644 index 00000000..1a267163 --- /dev/null +++ b/recipes/flet-libxml2/patches/mobile-2.15.x.patch @@ -0,0 +1,14 @@ +diff --git a/config.sub b/config.sub +--- a/config.sub ++++ b/config.sub +@@ -1323,6 +1323,10 @@ + nto-qnx*) + kernel=nto + os=`echo "$basic_os" | sed -e 's|nto-qnx|qnx|'` ++ ;; ++ ios-simulator*) ++ kernel= ++ os=$basic_os + ;; + *-*) + # shellcheck disable=SC2162 diff --git a/recipes/flet-libxml2/patches/mobile.patch b/recipes/flet-libxml2/patches/mobile-2.9.x.patch similarity index 100% rename from recipes/flet-libxml2/patches/mobile.patch rename to recipes/flet-libxml2/patches/mobile-2.9.x.patch diff --git a/recipes/flet-libxslt/build.sh b/recipes/flet-libxslt/build.sh index 5f8572d8..f865c203 100755 --- a/recipes/flet-libxslt/build.sh +++ b/recipes/flet-libxslt/build.sh @@ -7,8 +7,13 @@ export LIBS="-lxml2" ./configure --host=$HOST_TRIPLET --prefix=$PREFIX --without-crypto --without-python \ --with-libxml-include-prefix=$PLATLIB/opt/include \ --with-libxml-libs-prefix=$PLATLIB/opt/lib -make -j $CPU_COUNT V=1 -make install +# Skip the xsltproc CLI / doc / tests subdirs: xsltproc links against +# libxml2 and on iOS the SDK's bundled libxml2.tbd predates 1.1.45's +# usage of xmlCtxtParseDocument / xmlXPathValuePush, so the binary +# fails to link. The wheel only needs the libraries. +make -j $CPU_COUNT V=1 SUBDIRS='libxslt libexslt' +make install SUBDIRS='libxslt libexslt' -rm -r $PREFIX/share -rm -r $PREFIX/lib/{libxslt-*,pkgconfig,*.a,*.la,*.sh} \ No newline at end of file +shopt -s nullglob +rm -rf $PREFIX/share +rm -rf $PREFIX/lib/libxslt-* $PREFIX/lib/pkgconfig $PREFIX/lib/cmake $PREFIX/lib/*.la $PREFIX/lib/*.sh \ No newline at end of file diff --git a/recipes/flet-libxslt/meta.yaml b/recipes/flet-libxslt/meta.yaml index fdf5705b..02ce4b2b 100755 --- a/recipes/flet-libxslt/meta.yaml +++ b/recipes/flet-libxslt/meta.yaml @@ -1,13 +1,22 @@ +# {% set version = "1.1.45" %} +# {% if version == "1.1.32" %} +# {% set libxml2_version = "2.9.8" %} +# {% set patch = "mobile-1.1.32.patch" %} +# {% else %} +# {% set libxml2_version = "2.15.3" %} +# {% set patch = "mobile-1.1.45.patch" %} +# {% endif %} + package: name: flet-libxslt - version: 1.1.32 + version: '{{ version }}' source: - url: https://download.gnome.org/sources/libxslt/1.1/libxslt-1.1.32.tar.xz + url: https://download.gnome.org/sources/libxslt/{{ version.rsplit('.', 1)[0] }}/libxslt-{{ version }}.tar.xz requirements: host: - - flet-libxml2 2.9.8 + - flet-libxml2 {{ libxml2_version }} patches: - - mobile.patch \ No newline at end of file + - {{ patch }} diff --git a/recipes/flet-libxslt/patches/mobile.patch b/recipes/flet-libxslt/patches/mobile-1.1.32.patch similarity index 100% rename from recipes/flet-libxslt/patches/mobile.patch rename to recipes/flet-libxslt/patches/mobile-1.1.32.patch diff --git a/recipes/flet-libxslt/patches/mobile-1.1.45.patch b/recipes/flet-libxslt/patches/mobile-1.1.45.patch new file mode 100644 index 00000000..1a267163 --- /dev/null +++ b/recipes/flet-libxslt/patches/mobile-1.1.45.patch @@ -0,0 +1,14 @@ +diff --git a/config.sub b/config.sub +--- a/config.sub ++++ b/config.sub +@@ -1323,6 +1323,10 @@ + nto-qnx*) + kernel=nto + os=`echo "$basic_os" | sed -e 's|nto-qnx|qnx|'` ++ ;; ++ ios-simulator*) ++ kernel= ++ os=$basic_os + ;; + *-*) + # shellcheck disable=SC2162 diff --git a/recipes/lxml/meta.yaml b/recipes/lxml/meta.yaml index ef28a048..7a959b51 100644 --- a/recipes/lxml/meta.yaml +++ b/recipes/lxml/meta.yaml @@ -1,16 +1,30 @@ +# {% set version = "6.1.0" %} +# {% if version.startswith('5.') %} +# {% set libxml2_version = "2.9.8" %} +# {% set libxslt_version = "1.1.32" %} +# {% else %} +# {% set libxml2_version = "2.15.3" %} +# {% set libxslt_version = "1.1.45" %} +# {% endif %} + package: name: lxml - version: 5.3.0 + version: '{{ version }}' build: script_env: WITH_XML2_CONFIG: '{platlib}/opt/bin/xml2-config' WITH_XSLT_CONFIG: '{platlib}/opt/bin/xslt-config' +# {% if sdk != 'android' %} + # libxml2 on iOS is built with iconv; lxml's setup.py doesn't add + # -liconv to the link line, so do it here. + LDFLAGS: -liconv +# {% endif %} patches: - mobile.patch requirements: host: - - flet-libxslt 1.1.32 - - flet-libxml2 2.9.8 \ No newline at end of file + - flet-libxslt {{ libxslt_version }} + - flet-libxml2 {{ libxml2_version }} From 826fb19e2a3df567145869fb11b6fb9a8a830f1d Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Mon, 25 May 2026 17:41:18 -0700 Subject: [PATCH 119/142] Coolprop (#49) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Rewrite absolute-path DT_NEEDED entries in built .so files CMake-based recipes link against libpython by absolute path. Combined with libpython lacking a DT_SONAME, that absolute build-host path ends up recorded verbatim in the extension's DT_NEEDED list and won't resolve at load time on the target device. Shift each NEEDED d_val past the last '/' to point at the basename within the same string — no string rewriting required. Handles both ELF32 and ELF64. * Add coolprop recipe for Android and iOS --- recipes/coolprop/meta.yaml | 42 ++++++++ .../patches/mkdir-cython-output.patch | 12 +++ src/forge/build.py | 97 +++++++++++++++++++ 3 files changed, 151 insertions(+) create mode 100644 recipes/coolprop/meta.yaml create mode 100644 recipes/coolprop/patches/mkdir-cython-output.patch diff --git a/recipes/coolprop/meta.yaml b/recipes/coolprop/meta.yaml new file mode 100644 index 00000000..2da66cdc --- /dev/null +++ b/recipes/coolprop/meta.yaml @@ -0,0 +1,42 @@ +package: + name: coolprop + version: 7.2.0 + +requirements: + build: + - cmake +# {% if sdk == 'android' %} + host: + - flet-libcpp-shared >=27.2.12479018 +# {% endif %} + +patches: + - mkdir-cython-output.patch + +# {% if sdk == 'android' %} +build: + script_env: + CMAKE_ARGS: >- + -DCMAKE_TOOLCHAIN_FILE={NDK_ROOT}/build/cmake/android.toolchain.cmake + -DANDROID_ABI={ANDROID_ABI} + -DANDROID_PLATFORM=android-{ANDROID_API_LEVEL} + -DANDROID_STL=c++_shared + -DCMAKE_SHARED_LINKER_FLAGS=-Wl,-z,max-page-size=16384 + -DCMAKE_MODULE_LINKER_FLAGS=-Wl,-z,max-page-size=16384 + -DPython_LIBRARY={prefix}/lib/libpython{py_version_short}.so + -DPython_INCLUDE_DIR={prefix}/include/python{py_version_short} + -DPython3_LIBRARY={prefix}/lib/libpython{py_version_short}.so + -DPython3_INCLUDE_DIR={prefix}/include/python{py_version_short} +# {% else %} +build: + script_env: + CMAKE_ARGS: >- + -DCMAKE_SYSTEM_NAME=iOS + -DCMAKE_OSX_SYSROOT={{ sdk }} + -DCMAKE_OSX_DEPLOYMENT_TARGET={{ sdk_version }} + -DCMAKE_OSX_ARCHITECTURES={{ arch }} + -DPython_LIBRARY={prefix}/lib/libpython{py_version_short}.dylib + -DPython_INCLUDE_DIR={prefix}/include/python{py_version_short} + -DPython3_LIBRARY={prefix}/lib/libpython{py_version_short}.dylib + -DPython3_INCLUDE_DIR={prefix}/include/python{py_version_short} +# {% endif %} diff --git a/recipes/coolprop/patches/mkdir-cython-output.patch b/recipes/coolprop/patches/mkdir-cython-output.patch new file mode 100644 index 00000000..c1968094 --- /dev/null +++ b/recipes/coolprop/patches/mkdir-cython-output.patch @@ -0,0 +1,12 @@ +--- a/wrappers/Python/CMakeLists.txt ++++ b/wrappers/Python/CMakeLists.txt +@@ -137,6 +137,9 @@ set(CYTHON_FLAGS + --directive c_string_encoding=ascii + ) + ++# Cython does not create the output's parent directory; create it ourselves. ++file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/CoolProp") ++ + # Generate CoolProp module + add_custom_command( + OUTPUT CoolProp/CoolProp.cpp diff --git a/src/forge/build.py b/src/forge/build.py index eb177d74..1d12bf73 100644 --- a/src/forge/build.py +++ b/src/forge/build.py @@ -518,6 +518,98 @@ def write_message_file(self, filename: Path, data): def wheel_tag(self) -> str: return f"py3-none-{self.cross_venv.tag}" + def _rewrite_absolute_needed(self, so_path: Path): + # Some libraries (notably libpython built without DT_SONAME) end up + # recorded in DT_NEEDED by their absolute build-host path when linked + # via CMake's absolute-path style. That path won't exist on the + # target device. Shift each DT_NEEDED d_val past the last '/' in the + # existing string — no string rewriting needed because the basename + # already lives at the suffix of the absolute path. + with open(so_path, "r+b") as f: + if f.read(4) != b"\x7fELF": + return + ei_class = struct.unpack("B", f.read(1))[0] + if ei_class == 1: + # ELF32: 4-byte fields, 8-byte dyn entries, 40-byte sections. + shoff_pos, shoff_fmt = 32, " " + f"'{name[slash + 1:].decode(errors='replace')}'", + ) + def _check_elf_alignment(self, so_path: Path): """Verify that all PT_LOAD segments are 16KB-aligned.""" MIN_ALIGNMENT = 16384 @@ -574,6 +666,11 @@ def fix_wheel(self, wheel_dir: Path): [env["STRIP"], "--strip-unneeded", str(so)], ) + # Rewrite any absolute-path DT_NEEDED entries to their basename + # (e.g. libpython linked by absolute path under CMake builds). + for so in wheel_dir.glob("**/*.so"): + self._rewrite_absolute_needed(so) + # Verify 16KB page alignment (required by Google Play) for so in wheel_dir.glob("**/*.so"): self._check_elf_alignment(so) From d8bce1deb99f3aab781fa060824710f600429f98 Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Wed, 27 May 2026 07:42:04 -0700 Subject: [PATCH 120/142] rasterio 1.5.0 (#50) --- recipes/rasterio/meta.yaml | 21 +++++++++++++++++++++ recipes/rasterio/patches/mobile.patch | 17 +++++++++++++++++ 2 files changed, 38 insertions(+) create mode 100644 recipes/rasterio/meta.yaml create mode 100644 recipes/rasterio/patches/mobile.patch diff --git a/recipes/rasterio/meta.yaml b/recipes/rasterio/meta.yaml new file mode 100644 index 00000000..d14f24f2 --- /dev/null +++ b/recipes/rasterio/meta.yaml @@ -0,0 +1,21 @@ +package: + name: rasterio + version: 1.5.0 + +requirements: + host: + - flet-libgdal 3.10.0 + - numpy ^2.0.0 + +build: + script_env: + GDAL_VERSION: 3.10.0 + GDAL_LIB_PATH: '{platlib}/opt/lib' + GDAL_INCLUDE_PATH: '{platlib}/opt/include' + GDAL_LIBS: gdal +# {% if sdk != 'android' %} + LDFLAGS: '-undefined dynamic_lookup' +# {% endif %} + +patches: + - mobile.patch diff --git a/recipes/rasterio/patches/mobile.patch b/recipes/rasterio/patches/mobile.patch new file mode 100644 index 00000000..ddb84079 --- /dev/null +++ b/recipes/rasterio/patches/mobile.patch @@ -0,0 +1,17 @@ +diff --git a/setup.py b/setup.py +--- a/setup.py ++++ b/setup.py +@@ -251,6 +251,13 @@ + e, + ) + ++ if 'GDAL_LIB_PATH' in os.environ: ++ library_dirs.extend(os.environ['GDAL_LIB_PATH'].split(":")) ++ if 'GDAL_INCLUDE_PATH' in os.environ: ++ include_dirs.extend(os.environ['GDAL_INCLUDE_PATH'].split(":")) ++ if 'GDAL_LIBS' in os.environ: ++ libraries.extend(os.environ['GDAL_LIBS'].split(",")) ++ + # Get GDAL API version from environment variable. + if 'GDAL_VERSION' in os.environ: + gdalversion = os.environ['GDAL_VERSION'] From 10b57d7ae70870d334e905b41294149f665145ed Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Wed, 27 May 2026 10:25:26 -0700 Subject: [PATCH 121/142] Add libcpp-shared host dependency for rasterio Include a conditional host requirement in recipes/rasterio/meta.yaml: add flet-libcpp-shared >=27.2.12479018 wrapped in a Jinja if-check (sdk == 'android'). This ensures the shared C++ runtime is only required for Android builds; no other changes were made. --- recipes/rasterio/meta.yaml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/recipes/rasterio/meta.yaml b/recipes/rasterio/meta.yaml index d14f24f2..db38d942 100644 --- a/recipes/rasterio/meta.yaml +++ b/recipes/rasterio/meta.yaml @@ -6,7 +6,10 @@ requirements: host: - flet-libgdal 3.10.0 - numpy ^2.0.0 - +# {% if sdk == 'android' %} + - flet-libcpp-shared >=27.2.12479018 +# {% endif %} + build: script_env: GDAL_VERSION: 3.10.0 From 885598e6e784e46fb10185dc014e3d2c9c44b3bf Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Thu, 28 May 2026 12:02:24 -0700 Subject: [PATCH 122/142] primp 1.3.1 (#51) --- recipes/primp/meta.yaml | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 recipes/primp/meta.yaml diff --git a/recipes/primp/meta.yaml b/recipes/primp/meta.yaml new file mode 100644 index 00000000..344ef6f7 --- /dev/null +++ b/recipes/primp/meta.yaml @@ -0,0 +1,3 @@ +package: + name: primp + version: 1.3.1 \ No newline at end of file From 059226c65b10b203685724cb95f6165205242331 Mon Sep 17 00:00:00 2001 From: TheEthicalBoy <98978078+ndonkoHenri@users.noreply.github.com> Date: Fri, 29 May 2026 21:34:42 +0200 Subject: [PATCH 123/142] ujson 5.12.1 (#52) --- recipes/ujson/meta.yaml | 14 ++++++++++++++ recipes/ujson/test_ujson.py | 23 +++++++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 recipes/ujson/meta.yaml create mode 100644 recipes/ujson/test_ujson.py diff --git a/recipes/ujson/meta.yaml b/recipes/ujson/meta.yaml new file mode 100644 index 00000000..36ae023a --- /dev/null +++ b/recipes/ujson/meta.yaml @@ -0,0 +1,14 @@ +package: + name: ujson + version: 5.12.1 + +# {% if sdk == 'android' %} +# ujson links its bundled double-conversion C++ code against NDK's libc++. +# NDK r27 defaults to libc++_shared, so the .so has a runtime dlopen() on +# libc++_shared.so. flet-libcpp-shared ships that .so to jniLibs// via +# serious_python_android/android/build.gradle's copyOpt_ task. +# iOS uses Apple's system libc++ — no runtime dep needed. +requirements: + host: + - flet-libcpp-shared >=27.2.12479018 +# {% endif %} \ No newline at end of file diff --git a/recipes/ujson/test_ujson.py b/recipes/ujson/test_ujson.py new file mode 100644 index 00000000..93ff57c2 --- /dev/null +++ b/recipes/ujson/test_ujson.py @@ -0,0 +1,23 @@ +def test_basic(): + import ujson + + data = { + "name": "flet", + "version": 1, + "active": True, + "tags": ["mobile", "python"], + "ratio": 3.141592653589793, + "nothing": None, + } + encoded = ujson.dumps(data) + assert isinstance(encoded, str) + + decoded = ujson.loads(encoded) + assert decoded == data + + +def test_double_conversion(): + import ujson + + pi = 3.141592653589793 + assert ujson.loads(ujson.dumps(pi)) == pi From 7dd9bf72c3cc40cf882b865fb7e0bd3a12842aed Mon Sep 17 00:00:00 2001 From: TheEthicalBoy <98978078+ndonkoHenri@users.noreply.github.com> Date: Sat, 30 May 2026 18:48:54 +0200 Subject: [PATCH 124/142] Improve CI workflow (#53) * initial commit * migrate to using uv * add Rust setup and target configuration for mobile builds * enhance CI workflow to detect changed recipes and add publish option * update build-wheels workflow to remove additional support-tree dependency wheels --- .appveyor.yml | 310 ------------------ .ci/common.sh | 10 +- .../build-wheels-with-cibuildwheel.yml | 12 +- .github/workflows/build-wheels.yml | 99 ++++-- setup.sh | 63 +--- 5 files changed, 84 insertions(+), 410 deletions(-) delete mode 100644 .appveyor.yml diff --git a/.appveyor.yml b/.appveyor.yml deleted file mode 100644 index 2a52e7c0..00000000 --- a/.appveyor.yml +++ /dev/null @@ -1,310 +0,0 @@ -image: macos-monterey - -skip_branch_with_pr: true - -environment: - PYTHON_VERSION: 3.12.7 - PYTHON_SHORT_VERSION: 3.12 - GEMFURY_TOKEN: - secure: trYGM65OQ1+HYnOYOe/NOHrofLpP3bz64nHwVWPJhiUIYll3MrrQd7ilFNp+zSkI - MOBILE_FORGE_CACHE_DOWNLOADS_OFF: 1 - - matrix: - - job_name: 'Android: pydantic-core 2.33.2' - job_group: build_android - FORGE_ARCH: android - FORGE_PACKAGES: >- - pydantic-core:2.33.2 - BUILD_NUMBER: 1 - - - job_name: 'iOS: pydantic-core 2.33.2' - job_group: build_ios - FORGE_ARCH: iOS - FORGE_PACKAGES: >- - pydantic-core:2.33.2 - BUILD_NUMBER: 1 - - # ================================================== - - # - job_name: 'Android arm64-v8a: opencv-python' - # job_group: build_android - # FORGE_ARCH: 'android:arm64-v8a' - # FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 - # BUILD_NUMBER: 1 - - # - job_name: 'Android armeabi-v7a: opencv-python' - # job_group: build_android - # FORGE_ARCH: 'android:armeabi-v7a' - # FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 - # BUILD_NUMBER: 1 - - # - job_name: 'Android x86_64: opencv-python' - # job_group: build_android - # FORGE_ARCH: 'android:x86_64' - # FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 - # BUILD_NUMBER: 1 - - # - job_name: 'Android x86: opencv-python' - # job_group: build_android - # FORGE_ARCH: 'android:x86' - # FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 - # BUILD_NUMBER: 1 - - # - job_name: 'iOS iphone arm64: opencv-python' - # job_group: build_ios - # FORGE_ARCH: 'iphoneos:arm64' - # FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 - # BUILD_NUMBER: 1 - - # - job_name: 'iOS simulator arm64: opencv-python' - # job_group: build_ios - # FORGE_ARCH: 'iphonesimulator:arm64' - # FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 - # BUILD_NUMBER: 1 - - # - job_name: 'iOS simulator x86_64: opencv-python' - # job_group: build_ios - # FORGE_ARCH: 'iphonesimulator:x86_64' - # FORGE_PACKAGES: numpy:2.1.1 opencv-python:4.10.0.84 - # BUILD_NUMBER: 1 - - # - job_name: 'Android: pydantic-core, pillow, lru-dict, contourpy, kiwisolver, aiohttp, bitarray, argon2-cffi-binding, bcrypt, cryptography, brotli, websockets' - # job_group: build_android - # FORGE_ARCH: android - # FORGE_PACKAGES: >- - # cffi:1.17.1 - # flet-libcpp-shared:27.2.12479018 - # flet-libjpeg:3.0.90 - # flet-libpng:1.6.43 - # flet-libfreetype:2.13.3 - # pillow:10.4.0 - # lru-dict:1.3.0 - # yarl:1.11.1 - # contourpy:1.3.0 - # kiwisolver:1.4.7 - # aiohttp:3.9.5 - # bitarray:2.9.2 - # argon2-cffi-bindings:21.2.0 - # bcrypt:4.2.0 - # cryptography:43.0.1 - # brotli:1.1.0 - # pydantic-core:2.23.3 - # websockets:13.0.1 - # time-machine:2.16.0 - # markupsafe:2.1.5 - # BUILD_NUMBER: 1 - - # - job_name: 'Android: numpy, matplotlib, pandas, blis' - # job_group: build_android - # FORGE_ARCH: android - # FORGE_PACKAGES: >- - # flet-libcpp-shared:27.2.12479018 - # numpy:1.26.4 - # numpy:2.1.1 - # flet-libjpeg:3.0.90 - # matplotlib:3.9.2 - # pandas:2.2.2 - # blis:1.0.0 - # BUILD_NUMBER: 1 - - # - job_name: 'iOS: pillow, lru-dict, yarl, contourpy, kiwisolver, aiohttp, bitarray, websockets' - # job_group: build_ios - # FORGE_ARCH: iOS - # FORGE_PACKAGES: >- - # flet-libjpeg:3.0.90 - # flet-libpng:1.6.43 - # flet-libfreetype:2.13.3 - # pillow:10.4.0 - # lru-dict:1.3.0 - # yarl:1.11.1 - # contourpy:1.3.0 - # kiwisolver:1.4.7 - # aiohttp:3.9.5 - # bitarray:2.9.2 - # websockets:13.0.1 - # time-machine:2.16.0 - # markupsafe:2.1.5 - # BUILD_NUMBER: 1 - - # - job_name: 'iOS: cffi, argon2-cffi-bindings, bcrypt, cryptography, brotli' - # job_group: build_ios - # FORGE_ARCH: iOS - # FORGE_PACKAGES: >- - # cffi:1.17.1 - # argon2-cffi-bindings:21.2.0 - # bcrypt:4.2.0 - # cryptography:43.0.1 - # brotli:1.1.0 - # BUILD_NUMBER: 1 - - # - job_name: 'iOS: pydantic-core' - # job_group: build_ios - # FORGE_ARCH: iOS - # FORGE_PACKAGES: >- - # pydantic-core:2.23.3 - # BUILD_NUMBER: 1 - - # - job_name: 'iOS: numpy, matplotlib, pandas, blis' - # job_group: build_ios - # FORGE_ARCH: iOS - # FORGE_PACKAGES: >- - # numpy:1.26.4 - # numpy:2.1.1 - # flet-libjpeg:3.0.90 - # matplotlib:3.9.2 - # pandas:2.2.2 - # blis:1.0.0 - # BUILD_NUMBER: 1 - - # - job_name: Re-build Simple index - # job_group: rebuild_index - # job_depends_on: build_android, build_ios - -stack: -- python $PYTHON_SHORT_VERSION - -on_success: -- sh: | - if test -d logs; then - find logs -type f -iname *.log -exec appveyor PushArtifact {} \; - fi - -on_failure: -- sh: | - if test -d errors; then - find errors -type f -iname *.log -exec appveyor PushArtifact {} \; - fi - -for: - # ====================================== - # Build Android packages - # ====================================== - - - matrix: - only: - - job_group: build_android - - environment: - APPVEYOR_BUILD_WORKER_IMAGE: ubuntu-gce-c - NDK_VERSION: r27d - - install: - - sudo apt update - - sudo apt install sqlite3 - - . .ci/common.sh - - # download Python for Android - - python_android_dir=$HOME/projects/python-build/android - - curl -#OL https://github.com/flet-dev/python-build/releases/download/v${PYTHON_SHORT_VERSION}/python-android-mobile-forge-${PYTHON_SHORT_VERSION}.tar.gz - - mkdir -p $python_android_dir - - tar -xzf python-android-mobile-forge-${PYTHON_SHORT_VERSION}.tar.gz -C $python_android_dir - - # install Android NDK - - . .ci/install_ndk.sh - - # install Rust - - curl https://sh.rustup.rs -sSf | sh -s -- -y - - . "$HOME/.cargo/env" - - export PATH="$PATH:$HOME/.cargo/bin" - - rustup target add aarch64-linux-android - - rustup target add arm-linux-androideabi - - rustup target add x86_64-linux-android - - rustup target add i686-linux-android - - # configure forge - - export MOBILE_FORGE_ANDROID_SUPPORT_PATH=$python_android_dir - - source ./setup.sh $PYTHON_VERSION - - build_script: - - sh: | - IFS=' ' read -r -a packages <<< "$FORGE_PACKAGES" - for package in "${packages[@]}"; do - forge $FORGE_ARCH $package:$BUILD_NUMBER || exit 1 - done - - # cleanup - - rm dist/bzip2-* - - rm dist/xz-* - - rm dist/openssl-* - - rm dist/libffi-* - - deploy_script: - # - pip install boto3 - # - python .ci/publish-wheels.py dist - - publish_to_pypi dist/*.whl - - test: off - - # ====================================== - # Build iOS packages - # ====================================== - - - matrix: - only: - - job_group: build_ios - - environment: - APPVEYOR_BUILD_WORKER_IMAGE: macos-sonoma - - install: - - . .ci/common.sh - - # download Python for iOS - - python_ios_dir=$HOME/projects/python-build/darwin/Python-Apple-support - - curl -#OL https://github.com/flet-dev/python-build/releases/download/v${PYTHON_SHORT_VERSION}/python-ios-mobile-forge-${PYTHON_SHORT_VERSION}.tar.gz - - mkdir -p $python_ios_dir - - tar -xzf python-ios-mobile-forge-${PYTHON_SHORT_VERSION}.tar.gz -C $python_ios_dir - - # install Rust - - curl https://sh.rustup.rs -sSf | sh -s -- -y - - . "$HOME/.cargo/env" - - export PATH="$PATH:$HOME/.cargo/bin" - - rustup target add aarch64-apple-ios - - rustup target add aarch64-apple-ios-sim - - rustup target add x86_64-apple-ios - - # configure forge - - export MOBILE_FORGE_IOS_SUPPORT_PATH=$python_ios_dir - - source ./setup.sh $PYTHON_VERSION - - # refresh PATH - - export PATH="$PATH:$HOME/.cargo/bin" - - build_script: - - sh: | - IFS=' ' read -r -a packages <<< "$FORGE_PACKAGES" - for package in "${packages[@]}"; do - forge $FORGE_ARCH $package:$BUILD_NUMBER || exit 1 - done - - # cleanup - - rm dist/bzip2-* - - rm dist/xz-* - - rm dist/libffi-* - - rm dist/openssl-* - - deploy_script: - # - pip install boto3 - # - python .ci/publish-wheels.py dist - - publish_to_pypi dist/*.whl - - test: off - - # ====================================== - # Rebuild Simple index - # ====================================== - - - matrix: - only: - - job_group: rebuild_index - - environment: - APPVEYOR_BUILD_WORKER_IMAGE: ubuntu - - deploy_script: - - python -m ensurepip --upgrade - - pip3 install --upgrade setuptools - - pip3 install boto3 - - python .ci/rebuild-simple-index.py - - test: off diff --git a/.ci/common.sh b/.ci/common.sh index 0e724950..6073bf34 100644 --- a/.ci/common.sh +++ b/.ci/common.sh @@ -1,7 +1,5 @@ function publish_to_pypi() { - if [[ "$APPVEYOR_PULL_REQUEST_NUMBER" == "" ]]; then - for wheel in "$@"; do - curl -F package=@$wheel https://$GEMFURY_TOKEN@push.fury.io/flet/ - done - fi -} \ No newline at end of file + for wheel in "$@"; do + curl -F package=@$wheel https://$GEMFURY_TOKEN@push.fury.io/flet/ + done +} diff --git a/.github/workflows/build-wheels-with-cibuildwheel.yml b/.github/workflows/build-wheels-with-cibuildwheel.yml index 8b8a5353..42129b02 100644 --- a/.github/workflows/build-wheels-with-cibuildwheel.yml +++ b/.github/workflows/build-wheels-with-cibuildwheel.yml @@ -3,6 +3,9 @@ name: wheels-android on: workflow_dispatch: +env: + UV_PYTHON: "3.12" # cibuildwheel runner python; not the target + jobs: build_android_wheels: runs-on: ubuntu-latest @@ -10,10 +13,8 @@ jobs: steps: - uses: actions/checkout@v4 - - name: Set up Python - uses: actions/setup-python@v5 - with: - python-version: "3.12" # cibuildwheel runner python; not the target + - name: Setup uv + uses: astral-sh/setup-uv@v6 - name: Set up JDK uses: actions/setup-java@v4 @@ -34,8 +35,7 @@ jobs: wget https://files.pythonhosted.org/packages/04/24/4b2031d72e840ce4c1ccb255f693b15c334757fc50023e4db9537080b8c4/websockets-16.0.tar.gz tar xf websockets-16.0.tar.gz cd websockets-16.0 - python -m pip install -U pip cibuildwheel - cibuildwheel --output-dir wheelhouse + uvx cibuildwheel --output-dir wheelhouse - uses: actions/upload-artifact@v4 with: diff --git a/.github/workflows/build-wheels.yml b/.github/workflows/build-wheels.yml index ae24a63e..52e3c3a0 100644 --- a/.github/workflows/build-wheels.yml +++ b/.github/workflows/build-wheels.yml @@ -17,10 +17,13 @@ on: description: "Build number" required: false default: "1" + publish: + description: "Publish to PyPI" + type: boolean + default: false env: - PYTHON_VERSION: "3.12.12" - PYTHON_SHORT_VERSION: "3.12" + UV_PYTHON: "3.12.12" MOBILE_FORGE_CACHE_DOWNLOADS_OFF: "1" NDK_VERSION: r27d @@ -30,11 +33,43 @@ jobs: outputs: matrix: ${{ steps.set-matrix.outputs.matrix }} steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Get changed recipes + id: changed-recipes + uses: tj-actions/changed-files@v45 + with: + files: recipes/** + dir_names: true + dir_names_max_depth: 2 + + - id: detect-packages + shell: bash + env: + GITHUB_EVENT_NAME: ${{ github.event_name }} + INPUT_PACKAGES: ${{ inputs.packages }} + CHANGED_DIRS: ${{ steps.changed-recipes.outputs.all_changed_files }} + run: | + SMOKE_TEST="pydantic-core:2.33.2" + if [[ "$GITHUB_EVENT_NAME" == "workflow_dispatch" ]]; then + pkgs="${INPUT_PACKAGES:-$SMOKE_TEST}" + else + pkgs="" + for dir in $CHANGED_DIRS; do + [[ -f "$dir/meta.yaml" ]] || continue # skip deleted recipes + pkgs="${pkgs:+$pkgs,}${dir#recipes/}:" + done + pkgs="${pkgs:-$SMOKE_TEST}" + fi + echo "Detected packages: $pkgs" + echo "packages=$pkgs" >> "$GITHUB_OUTPUT" + - id: set-matrix shell: bash run: | ARCHS="${{ inputs.archs || 'android,iOS' }}" - PACKAGES="${{ inputs.packages || 'pydantic-core:2.33.2' }}" + PACKAGES="${{ steps.detect-packages.outputs.packages }}" BUILD_NUMBER="${{ inputs.build_number || '1' }}" matrix='{"include":[' @@ -46,11 +81,13 @@ jobs: if [[ "$arch" == "android" ]]; then runner="ubuntu-latest" platform="android" + rust_targets="aarch64-linux-android,arm-linux-androideabi,x86_64-linux-android,i686-linux-android" else runner="macos-latest" platform="ios" + rust_targets="aarch64-apple-ios,aarch64-apple-ios-sim,x86_64-apple-ios" fi - matrix+="{\"job_name\":\"${platform}: ${pkg_name}\",\"artifact_name\":\"${platform}-${pkg_name}\",\"runner\":\"$runner\",\"platform\":\"$platform\",\"forge_arch\":\"$arch\",\"forge_packages\":\"$pkg\",\"build_number\":\"$BUILD_NUMBER\"}" + matrix+="{\"job_name\":\"${platform}: ${pkg_name}\",\"artifact_name\":\"${platform}-${pkg_name}\",\"runner\":\"$runner\",\"platform\":\"$platform\",\"forge_arch\":\"$arch\",\"forge_packages\":\"$pkg\",\"build_number\":\"$BUILD_NUMBER\",\"rust_targets\":\"$rust_targets\"}" done done matrix+=']}' @@ -68,16 +105,17 @@ jobs: - name: Checkout uses: actions/checkout@v4 - - name: Set up Python - uses: actions/setup-python@v5 + - name: Setup uv + uses: astral-sh/setup-uv@v6 + + - name: Setup Rust + uses: dtolnay/rust-toolchain@stable with: - python-version: ${{ env.PYTHON_SHORT_VERSION }} + targets: ${{ matrix.rust_targets }} - - name: Build and publish wheels + - name: Build wheels shell: bash env: - GEMFURY_TOKEN: ${{ secrets.GEMFURY_TOKEN }} - APPVEYOR_PULL_REQUEST_NUMBER: "" FORGE_ARCH: ${{ matrix.forge_arch }} FORGE_PACKAGES: ${{ matrix.forge_packages }} BUILD_NUMBER: ${{ matrix.build_number }} @@ -85,6 +123,8 @@ jobs: run: | set -euxo pipefail + PYTHON_SHORT_VERSION="${UV_PYTHON%.*}" + . .ci/common.sh export MOBILE_FORGE_ANDROID_SUPPORT_PATH="" export MOBILE_FORGE_IOS_SUPPORT_PATH="" @@ -97,47 +137,38 @@ jobs: curl -#OL "https://github.com/flet-dev/python-build/releases/download/v${PYTHON_SHORT_VERSION}/python-android-mobile-forge-${PYTHON_SHORT_VERSION}.tar.gz" mkdir -p "$python_android_dir" tar -xzf "python-android-mobile-forge-${PYTHON_SHORT_VERSION}.tar.gz" -C "$python_android_dir" + export MOBILE_FORGE_ANDROID_SUPPORT_PATH="$python_android_dir" . .ci/install_ndk.sh - - curl https://sh.rustup.rs -sSf | sh -s -- -y - . "$HOME/.cargo/env" - export PATH="$PATH:$HOME/.cargo/bin" - rustup target add aarch64-linux-android - rustup target add arm-linux-androideabi - rustup target add x86_64-linux-android - rustup target add i686-linux-android - - export MOBILE_FORGE_ANDROID_SUPPORT_PATH="$python_android_dir" else python_ios_dir="$HOME/projects/python-build/darwin/Python-Apple-support" curl -#OL "https://github.com/flet-dev/python-build/releases/download/v${PYTHON_SHORT_VERSION}/python-ios-mobile-forge-${PYTHON_SHORT_VERSION}.tar.gz" mkdir -p "$python_ios_dir" tar -xzf "python-ios-mobile-forge-${PYTHON_SHORT_VERSION}.tar.gz" -C "$python_ios_dir" - - curl https://sh.rustup.rs -sSf | sh -s -- -y - . "$HOME/.cargo/env" - export PATH="$PATH:$HOME/.cargo/bin" - rustup target add aarch64-apple-ios - rustup target add aarch64-apple-ios-sim - rustup target add x86_64-apple-ios - export MOBILE_FORGE_IOS_SUPPORT_PATH="$python_ios_dir" fi - source ./setup.sh "$PYTHON_VERSION" - export PATH="$PATH:$HOME/.cargo/bin" + source ./setup.sh "$UV_PYTHON" IFS=' ' read -r -a packages <<< "$FORGE_PACKAGES" for package in "${packages[@]}"; do forge "$FORGE_ARCH" "$package:$BUILD_NUMBER" done - rm -f dist/bzip2-* dist/xz-* dist/openssl-* dist/libffi-* + # Drop the support-tree dep wheels produced by make_dep_wheels.py + # iOS deps: bzip2, libffi, mpdecimal, openssl, xz + # Android deps: bzip2, libffi, openssl, sqlite, xz + rm -f dist/bzip2-* dist/libffi-* dist/mpdecimal-* dist/openssl-* dist/sqlite-* dist/xz-* - if compgen -G "dist/*.whl" > /dev/null; then - publish_to_pypi dist/*.whl - fi + - name: Publish wheels + if: ${{ inputs.publish && hashFiles('dist/*.whl') != '' }} + shell: bash + env: + GEMFURY_TOKEN: ${{ secrets.GEMFURY_TOKEN }} + run: | + set -euxo pipefail + . .ci/common.sh + publish_to_pypi dist/*.whl - name: Upload logs on success if: ${{ success() && hashFiles('logs/*.log') != '' }} diff --git a/setup.sh b/setup.sh index 6105bc74..1201bc0b 100755 --- a/setup.sh +++ b/setup.sh @@ -24,11 +24,14 @@ if [ -z "$1" ]; then return fi -PYTHON_VERSION=$1 -read python_version_major python_version_minor < <(echo $PYTHON_VERSION | sed -E 's/^([0-9]+)\.([0-9]+).*/\1 \2/') -PYTHON_VER=$python_version_major.$python_version_minor +if ! command -v uv &> /dev/null; then + echo "Error: uv is not installed. Install it with:" + echo " curl -LsSf https://astral.sh/uv/install.sh | sh" + return +fi -PYTHON_URL_PREFIX=https://github.com/indygreg/python-build-standalone/releases/download/20260203/cpython-$PYTHON_VERSION+20260203 +PYTHON_VERSION=$1 +PYTHON_VER="${PYTHON_VERSION%.*}" echo "Python version: $PYTHON_VERSION" echo "Python short version: $PYTHON_VER" @@ -43,58 +46,10 @@ venv_dir="$(pwd)/venv$PYTHON_VER" if [ ! -d $venv_dir ]; then echo "Creating Python $PYTHON_VER virtual environment for build in $venv_dir..." - if ! [ -d "tools/python" ]; then - if [ $(uname) = "Darwin" ]; then - # macOS - if [ $(uname -m) = "arm64" ]; then - PYTHON_SUFFIX="aarch64-apple-darwin-install_only.tar.gz" - else - PYTHON_SUFFIX="x86_64-apple-darwin-install_only.tar.gz" - fi - else - # Linux - if [ $(uname -m) = "arm64" ]; then - PYTHON_SUFFIX="aarch64-unknown-linux-gnu-install_only.tar.gz" - else - PYTHON_SUFFIX="x86_64_v3-unknown-linux-gnu-install_only.tar.gz" - fi - fi - - if ! [ -f "downloads/python-${PYTHON_VERSION}-${PYTHON_SUFFIX}" ]; then - echo "Downloading Python ${PYTHON_VERSION}" - python_dist_filename="downloads/python-${PYTHON_VERSION}-${PYTHON_SUFFIX}" - mkdir -p downloads - rm -rf $python_dist_filename - curl --location --progress-bar --fail "${PYTHON_URL_PREFIX}-${PYTHON_SUFFIX}" --output $python_dist_filename - if [ $? -ne 0 ]; then - echo "Can't download a Python from ${PYTHON_URL_PREFIX}-${PYTHON_SUFFIX}" - return - fi - fi - - mkdir -p tools - tar -xzf "downloads/python-${PYTHON_VERSION}-${PYTHON_SUFFIX}" -C tools - fi - - # BUILD_PYTHON=$(which python$PYTHON_VER) - # if [ $? -ne 0 ]; then - # echo "Can't find a Python $PYTHON_VER binary on the path." - # return - # fi - - BUILD_PYTHON=tools/python/bin/python - - if ! [ -f $BUILD_PYTHON ]; then - echo "Can't find a Python $BUILD_PYTHON binary on the path." - return - fi - - echo "Using $BUILD_PYTHON as the build python" - $BUILD_PYTHON -m venv $venv_dir + uv venv --seed --python="$PYTHON_VERSION" $venv_dir source $venv_dir/bin/activate - pip install -U pip - pip install -e . wheel + uv pip install -e . echo "Building platform dependency wheels..." if [ ! -z "$MOBILE_FORGE_IOS_SUPPORT_PATH" ]; then From 04a211613b62bedd408bf8b22b101c53491c9039 Mon Sep 17 00:00:00 2001 From: TheEthicalBoy <98978078+ndonkoHenri@users.noreply.github.com> Date: Sat, 30 May 2026 18:54:39 +0200 Subject: [PATCH 125/142] initial commit (#56) --- recipes/orjson/meta.yaml | 7 +++++++ recipes/orjson/test_orjson.py | 26 ++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 recipes/orjson/meta.yaml create mode 100644 recipes/orjson/test_orjson.py diff --git a/recipes/orjson/meta.yaml b/recipes/orjson/meta.yaml new file mode 100644 index 00000000..1f7e86d8 --- /dev/null +++ b/recipes/orjson/meta.yaml @@ -0,0 +1,7 @@ +package: + name: orjson + version: 3.11.9 + +build: + script_env: + _PYTHON_SYSCONFIGDATA_NAME: '{sysconfigdata_name}' diff --git a/recipes/orjson/test_orjson.py b/recipes/orjson/test_orjson.py new file mode 100644 index 00000000..3789c7d3 --- /dev/null +++ b/recipes/orjson/test_orjson.py @@ -0,0 +1,26 @@ +def test_basic(): + """Confirm the wheel loads and round-trips a representative payload.""" + import orjson + + payload = { + "library": "orjson", + "version": orjson.__version__, + "active": True, + "tags": ["mobile", "python", "flet"], + "ratio": 3.141592653589793, + "nothing": None, + } + + encoded = orjson.dumps(payload) + assert isinstance(encoded, bytes) # orjson returns bytes, not str + + decoded = orjson.loads(encoded) + assert decoded == payload + + +def test_numeric_precision(): + """Round-trip a float at the f64 precision boundary.""" + import orjson + + pi = 3.141592653589793 + assert orjson.loads(orjson.dumps(pi)) == pi From 0074a918e97d530147230169263671a4a7ec754b Mon Sep 17 00:00:00 2001 From: TheEthicalBoy <98978078+ndonkoHenri@users.noreply.github.com> Date: Sat, 30 May 2026 21:26:07 +0200 Subject: [PATCH 126/142] recipe: selectolax 0.4.10 (#55) * recipe: selectolax 0.4.10 * Update build-wheels.yml to publish wheels on python3.12 branch push --- .github/workflows/build-wheels.yml | 2 +- recipes/selectolax/meta.yaml | 3 +++ recipes/selectolax/test_selectolax.py | 16 ++++++++++++++++ 3 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 recipes/selectolax/meta.yaml create mode 100644 recipes/selectolax/test_selectolax.py diff --git a/.github/workflows/build-wheels.yml b/.github/workflows/build-wheels.yml index 52e3c3a0..7a9337cf 100644 --- a/.github/workflows/build-wheels.yml +++ b/.github/workflows/build-wheels.yml @@ -161,7 +161,7 @@ jobs: rm -f dist/bzip2-* dist/libffi-* dist/mpdecimal-* dist/openssl-* dist/sqlite-* dist/xz-* - name: Publish wheels - if: ${{ inputs.publish && hashFiles('dist/*.whl') != '' }} + if: ${{ hashFiles('dist/*.whl') != '' && (inputs.publish || (github.event_name == 'push' && github.ref == 'refs/heads/python3.12')) }} shell: bash env: GEMFURY_TOKEN: ${{ secrets.GEMFURY_TOKEN }} diff --git a/recipes/selectolax/meta.yaml b/recipes/selectolax/meta.yaml new file mode 100644 index 00000000..68ceaf1e --- /dev/null +++ b/recipes/selectolax/meta.yaml @@ -0,0 +1,3 @@ +package: + name: selectolax + version: 0.4.10 diff --git a/recipes/selectolax/test_selectolax.py b/recipes/selectolax/test_selectolax.py new file mode 100644 index 00000000..a7e6f17e --- /dev/null +++ b/recipes/selectolax/test_selectolax.py @@ -0,0 +1,16 @@ +def test_modest_parser(): + """Parse HTML + CSS-select with the Modest engine.""" + from selectolax.parser import HTMLParser + + tree = HTMLParser("

hello

world

") + nodes = tree.css("p.x") + assert [n.text() for n in nodes] == ["hello", "world"] + + +def test_lexbor_parser(): + """Parse HTML + CSS-select with the Lexbor engine.""" + from selectolax.lexbor import LexborHTMLParser + + tree = LexborHTMLParser("
  • a
  • b
  • c
") + items = tree.css("li") + assert [n.text() for n in items] == ["a", "b", "c"] From 711ac73c7fae56369cde278ef09aef433e1d33f4 Mon Sep 17 00:00:00 2001 From: TheEthicalBoy <98978078+ndonkoHenri@users.noreply.github.com> Date: Sat, 30 May 2026 21:26:39 +0200 Subject: [PATCH 127/142] recipe: biopython 1.87 (#54) * recipe: biopython 1.87 * Update build-wheels.yml to publish wheels on python3.12 branch push --- recipes/biopython/meta.yaml | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 recipes/biopython/meta.yaml diff --git a/recipes/biopython/meta.yaml b/recipes/biopython/meta.yaml new file mode 100644 index 00000000..fa4d660a --- /dev/null +++ b/recipes/biopython/meta.yaml @@ -0,0 +1,3 @@ +package: + name: biopython + version: "1.87" From 64529e7089b76d608dcea29521d626b5c3077d7a Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Mon, 1 Jun 2026 12:40:57 -0700 Subject: [PATCH 128/142] Preserve upstream wheel Python/ABI tag in fix_wheel (#61) fix_wheel was unconditionally rewriting the WHEEL Tag with `self.wheel_tag` (cp3X-cp3X-), discarding the tag maturin / the upstream backend had emitted. For abi3 crates like cryptography this turned `cp37-abi3-` into `cp312-cp312-` and the produced wheel name followed, which was wrong on three counts: - semantically incorrect: the inner _rust.abi3.so is stable-ABI; - unnecessarily restrictive: pip refuses the wheel on cp313+; - wasteful: forces per-Python-version rebuilds. Now `fix_wheel` keeps the existing pythontag-abitag portion and swaps only the platform component, falling back to self.wheel_tag only when the upstream wheel didn't carry a Tag header. Restores the cp3X-abi3-* wheels we shipped before commit 4cf1c1f. --- src/forge/build.py | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/forge/build.py b/src/forge/build.py index 1d12bf73..ef7da5c5 100644 --- a/src/forge/build.py +++ b/src/forge/build.py @@ -649,11 +649,21 @@ def fix_wheel(self, wheel_dir: Path): # Normalize wheel tags to forge platform tags so repacked wheels use # android_24_arm64_v8a / ios_13_0_arm64_iphoneos style platform tags. + # Preserve the Python/ABI part the upstream build wrote (e.g. maturin + # emits `cp37-abi3-*` for cryptography); only the platform component + # is swapped. Falls back to self.wheel_tag when no Tag was written. wheel_metadata_path = next(wheel_dir.glob("*.dist-info")) / "WHEEL" wheel_metadata = self.read_message_file(wheel_metadata_path) - if "Tag" in wheel_metadata: - del wheel_metadata["Tag"] - wheel_metadata["Tag"] = self.wheel_tag + upstream_tags = wheel_metadata.get_all("Tag", []) + del wheel_metadata["Tag"] + new_tags = [] + for tag in upstream_tags: + py, abi, _platform = tag.rsplit("-", 2) + new_tags.append(f"{py}-{abi}-{self.cross_venv.tag}") + if not new_tags: + new_tags = [self.wheel_tag] + for tag in new_tags: + wheel_metadata["Tag"] = tag self.write_message_file(wheel_metadata_path, wheel_metadata) if self.cross_venv.sdk == "android": From 37108c0a8e22ba93f93bf135bbd92f887fa07c6b Mon Sep 17 00:00:00 2001 From: TheEthicalBoy <98978078+ndonkoHenri@users.noreply.github.com> Date: Mon, 1 Jun 2026 22:33:52 +0200 Subject: [PATCH 129/142] Make `meta.yaml` the source of truth for `build.number` (#59) * Remove build_number input and related references from build-wheels workflow. * set build numbers for all recipes based on their respective PyPi max values --- .github/workflows/build-wheels.yml | 10 ++-------- recipes/aiohttp/meta.yaml | 3 +++ recipes/argon2-cffi-bindings/meta.yaml | 3 +++ recipes/bcrypt/meta.yaml | 1 + recipes/biopython/meta.yaml | 3 +++ recipes/bitarray/meta.yaml | 3 +++ recipes/blis/meta.yaml | 3 +++ recipes/brotli/meta.yaml | 3 +++ recipes/cffi/meta.yaml | 3 +++ recipes/contourpy/meta.yaml | 1 + recipes/coolprop/meta.yaml | 5 ++--- recipes/cryptography/meta.yaml | 1 + recipes/fiona/meta.yaml | 1 + recipes/flet-libcpp-shared/meta.yaml | 3 +++ recipes/flet-libcrc32c/meta.yaml | 2 +- recipes/flet-libcurl/meta.yaml | 2 +- recipes/flet-libfreetype/meta.yaml | 2 +- recipes/flet-libgdal/meta.yaml | 2 +- recipes/flet-libgeos/meta.yaml | 2 +- recipes/flet-libjpeg/meta.yaml | 2 +- recipes/flet-libjq/meta.yaml | 2 +- recipes/flet-libopaque/meta.yaml | 3 +++ recipes/flet-liboprf/meta.yaml | 1 + recipes/flet-libpng/meta.yaml | 2 +- recipes/flet-libproj/meta.yaml | 14 ++++++-------- recipes/flet-libpsl/meta.yaml | 2 +- recipes/flet-libpyjni/meta.yaml | 2 +- recipes/flet-libsodium/meta.yaml | 3 +++ recipes/flet-libtiff/meta.yaml | 2 +- recipes/flet-libxml2/meta.yaml | 3 +++ recipes/flet-libxslt/meta.yaml | 3 +++ recipes/gdal/meta.yaml | 1 + recipes/google-crc32c/meta.yaml | 3 ++- recipes/greenlet/meta.yaml | 3 ++- recipes/grpcio/meta.yaml | 1 + recipes/jiter/meta.yaml | 1 + recipes/jq/meta.yaml | 1 + recipes/kiwisolver/meta.yaml | 3 +++ recipes/lru-dict/meta.yaml | 3 +++ recipes/lxml/meta.yaml | 1 + recipes/markupsafe/meta.yaml | 3 +++ recipes/matplotlib/meta.yaml | 1 + recipes/msgpack/meta.yaml | 3 +++ recipes/msgspec/meta.yaml | 3 +++ recipes/numpy/meta.yaml | 1 + recipes/opaque/meta.yaml | 3 +++ recipes/opencv-python/meta.yaml | 5 ++--- recipes/orjson/meta.yaml | 1 + recipes/pandas/meta.yaml | 1 + recipes/pendulum/meta.yaml | 1 + recipes/pillow/meta.yaml | 3 ++- recipes/primp/meta.yaml | 5 ++++- recipes/protobuf/meta.yaml | 3 +++ recipes/pycryptodome/meta.yaml | 3 +++ recipes/pycryptodomex/meta.yaml | 3 +++ recipes/pydantic-core/meta.yaml | 1 + recipes/pyjnius/meta.yaml | 3 +++ recipes/pymongo/meta.yaml | 5 ++++- recipes/pynacl/meta.yaml | 3 +++ recipes/pyobjus/meta.yaml | 3 +++ recipes/pyogrio/meta.yaml | 1 + recipes/pyproj/meta.yaml | 1 + recipes/pysodium/meta.yaml | 3 +++ recipes/pyyaml/meta.yaml | 3 +++ recipes/rasterio/meta.yaml | 1 + recipes/regex/meta.yaml | 5 ++++- recipes/rpds-py/meta.yaml | 1 + recipes/ruamel.yaml.clib/meta.yaml | 5 ++++- recipes/selectolax/meta.yaml | 3 +++ recipes/shapely/meta.yaml | 3 +++ recipes/sqlalchemy/meta.yaml | 5 ++++- recipes/tiktoken/meta.yaml | 1 + recipes/time-machine/meta.yaml | 5 ++++- recipes/tokenizers/meta.yaml | 1 + recipes/ujson/meta.yaml | 3 +++ recipes/websockets/meta.yaml | 5 ++++- recipes/yarl/meta.yaml | 3 +++ recipes/zope.interface/meta.yaml | 5 ++++- recipes/zstandard/meta.yaml | 5 ++++- 79 files changed, 177 insertions(+), 45 deletions(-) diff --git a/.github/workflows/build-wheels.yml b/.github/workflows/build-wheels.yml index 7a9337cf..14a18070 100644 --- a/.github/workflows/build-wheels.yml +++ b/.github/workflows/build-wheels.yml @@ -13,10 +13,6 @@ on: description: "Packages (comma-separated, e.g. pillow:11.1.0,pydantic-core:2.33.2)" required: false default: "pydantic-core:2.33.2" - build_number: - description: "Build number" - required: false - default: "1" publish: description: "Publish to PyPI" type: boolean @@ -70,7 +66,6 @@ jobs: run: | ARCHS="${{ inputs.archs || 'android,iOS' }}" PACKAGES="${{ steps.detect-packages.outputs.packages }}" - BUILD_NUMBER="${{ inputs.build_number || '1' }}" matrix='{"include":[' first=true @@ -87,7 +82,7 @@ jobs: platform="ios" rust_targets="aarch64-apple-ios,aarch64-apple-ios-sim,x86_64-apple-ios" fi - matrix+="{\"job_name\":\"${platform}: ${pkg_name}\",\"artifact_name\":\"${platform}-${pkg_name}\",\"runner\":\"$runner\",\"platform\":\"$platform\",\"forge_arch\":\"$arch\",\"forge_packages\":\"$pkg\",\"build_number\":\"$BUILD_NUMBER\",\"rust_targets\":\"$rust_targets\"}" + matrix+="{\"job_name\":\"${platform}: ${pkg_name}\",\"artifact_name\":\"${platform}-${pkg_name}\",\"runner\":\"$runner\",\"platform\":\"$platform\",\"forge_arch\":\"$arch\",\"forge_packages\":\"$pkg\",\"rust_targets\":\"$rust_targets\"}" done done matrix+=']}' @@ -118,7 +113,6 @@ jobs: env: FORGE_ARCH: ${{ matrix.forge_arch }} FORGE_PACKAGES: ${{ matrix.forge_packages }} - BUILD_NUMBER: ${{ matrix.build_number }} PLATFORM: ${{ matrix.platform }} run: | set -euxo pipefail @@ -152,7 +146,7 @@ jobs: IFS=' ' read -r -a packages <<< "$FORGE_PACKAGES" for package in "${packages[@]}"; do - forge "$FORGE_ARCH" "$package:$BUILD_NUMBER" + forge "$FORGE_ARCH" "$package" done # Drop the support-tree dep wheels produced by make_dep_wheels.py diff --git a/recipes/aiohttp/meta.yaml b/recipes/aiohttp/meta.yaml index abef3d71..71224793 100644 --- a/recipes/aiohttp/meta.yaml +++ b/recipes/aiohttp/meta.yaml @@ -1,3 +1,6 @@ package: name: aiohttp version: 3.9.5 + +build: + number: 4 diff --git a/recipes/argon2-cffi-bindings/meta.yaml b/recipes/argon2-cffi-bindings/meta.yaml index 236b2240..9620c2a6 100644 --- a/recipes/argon2-cffi-bindings/meta.yaml +++ b/recipes/argon2-cffi-bindings/meta.yaml @@ -1,3 +1,6 @@ package: name: argon2-cffi-bindings version: 21.2.0 + +build: + number: 4 diff --git a/recipes/bcrypt/meta.yaml b/recipes/bcrypt/meta.yaml index f249fd43..82201ecf 100644 --- a/recipes/bcrypt/meta.yaml +++ b/recipes/bcrypt/meta.yaml @@ -3,5 +3,6 @@ package: version: 4.2.0 build: + number: 4 script_env: _PYTHON_SYSCONFIGDATA_NAME: '{sysconfigdata_name}' \ No newline at end of file diff --git a/recipes/biopython/meta.yaml b/recipes/biopython/meta.yaml index fa4d660a..1d64f33d 100644 --- a/recipes/biopython/meta.yaml +++ b/recipes/biopython/meta.yaml @@ -1,3 +1,6 @@ package: name: biopython version: "1.87" + +build: + number: 0 diff --git a/recipes/bitarray/meta.yaml b/recipes/bitarray/meta.yaml index 8f29ceac..fd3f930d 100644 --- a/recipes/bitarray/meta.yaml +++ b/recipes/bitarray/meta.yaml @@ -1,3 +1,6 @@ package: name: bitarray version: 3.6.1 + +build: + number: 4 diff --git a/recipes/blis/meta.yaml b/recipes/blis/meta.yaml index d395e142..effaa8d8 100644 --- a/recipes/blis/meta.yaml +++ b/recipes/blis/meta.yaml @@ -2,6 +2,9 @@ package: name: blis version: 1.0.0 +build: + number: 4 + requirements: host: - numpy ^2.0.0 diff --git a/recipes/brotli/meta.yaml b/recipes/brotli/meta.yaml index ad8c51ad..37863a41 100644 --- a/recipes/brotli/meta.yaml +++ b/recipes/brotli/meta.yaml @@ -1,3 +1,6 @@ package: name: Brotli version: 1.1.0 + +build: + number: 4 diff --git a/recipes/cffi/meta.yaml b/recipes/cffi/meta.yaml index 25b39bbc..506cc3e6 100644 --- a/recipes/cffi/meta.yaml +++ b/recipes/cffi/meta.yaml @@ -2,6 +2,9 @@ package: name: cffi version: 1.17.1 +build: + number: 4 + requirements: host: - libffi diff --git a/recipes/contourpy/meta.yaml b/recipes/contourpy/meta.yaml index b05eb7b8..0f2e97bc 100644 --- a/recipes/contourpy/meta.yaml +++ b/recipes/contourpy/meta.yaml @@ -14,6 +14,7 @@ requirements: # {% endif %} build: + number: 5 backend-args: - -Csetup-args=--cross-file - -Csetup-args={MESON_CROSS_FILE} diff --git a/recipes/coolprop/meta.yaml b/recipes/coolprop/meta.yaml index 2da66cdc..7f9c1918 100644 --- a/recipes/coolprop/meta.yaml +++ b/recipes/coolprop/meta.yaml @@ -13,9 +13,10 @@ requirements: patches: - mkdir-cython-output.patch -# {% if sdk == 'android' %} build: + number: 1 script_env: +# {% if sdk == 'android' %} CMAKE_ARGS: >- -DCMAKE_TOOLCHAIN_FILE={NDK_ROOT}/build/cmake/android.toolchain.cmake -DANDROID_ABI={ANDROID_ABI} @@ -28,8 +29,6 @@ build: -DPython3_LIBRARY={prefix}/lib/libpython{py_version_short}.so -DPython3_INCLUDE_DIR={prefix}/include/python{py_version_short} # {% else %} -build: - script_env: CMAKE_ARGS: >- -DCMAKE_SYSTEM_NAME=iOS -DCMAKE_OSX_SYSROOT={{ sdk }} diff --git a/recipes/cryptography/meta.yaml b/recipes/cryptography/meta.yaml index 1ab42e92..a64edca3 100644 --- a/recipes/cryptography/meta.yaml +++ b/recipes/cryptography/meta.yaml @@ -7,6 +7,7 @@ requirements: - openssl ^3.0.12 build: + number: 4 script_env: OPENSSL_DIR: '{platlib}/opt' _PYTHON_SYSCONFIGDATA_NAME: '{sysconfigdata_name}' \ No newline at end of file diff --git a/recipes/fiona/meta.yaml b/recipes/fiona/meta.yaml index a966ad5e..962160c0 100644 --- a/recipes/fiona/meta.yaml +++ b/recipes/fiona/meta.yaml @@ -7,6 +7,7 @@ requirements: - flet-libgdal 3.10.0 build: + number: 4 script_env: GDAL_VERSION: 3.10.0 GDAL_LIB_PATH: '{platlib}/opt/lib' diff --git a/recipes/flet-libcpp-shared/meta.yaml b/recipes/flet-libcpp-shared/meta.yaml index 18055a6c..96147f47 100644 --- a/recipes/flet-libcpp-shared/meta.yaml +++ b/recipes/flet-libcpp-shared/meta.yaml @@ -2,5 +2,8 @@ package: name: flet-libcpp-shared version: 27.3.13750724 +build: + number: 4 + source: url: https://github.com/flet-dev/awesome-flet/archive/refs/heads/main.zip \ No newline at end of file diff --git a/recipes/flet-libcrc32c/meta.yaml b/recipes/flet-libcrc32c/meta.yaml index 7d9b942e..40114603 100644 --- a/recipes/flet-libcrc32c/meta.yaml +++ b/recipes/flet-libcrc32c/meta.yaml @@ -3,7 +3,7 @@ package: version: 1.1.2 build: - number: 1 + number: 4 source: url: https://github.com/google/crc32c/archive/refs/tags/1.1.2.tar.gz diff --git a/recipes/flet-libcurl/meta.yaml b/recipes/flet-libcurl/meta.yaml index 9dba6cc6..c4e3d547 100644 --- a/recipes/flet-libcurl/meta.yaml +++ b/recipes/flet-libcurl/meta.yaml @@ -8,7 +8,7 @@ source: url: https://curl.se/download/curl-{{ version }}.tar.gz build: - number: 1 + number: 4 requirements: host: diff --git a/recipes/flet-libfreetype/meta.yaml b/recipes/flet-libfreetype/meta.yaml index 139a8bb9..511ec378 100644 --- a/recipes/flet-libfreetype/meta.yaml +++ b/recipes/flet-libfreetype/meta.yaml @@ -3,7 +3,7 @@ package: version: 2.13.3 build: - number: 1 + number: 2 source: url: https://download.savannah.gnu.org/releases/freetype/freetype-2.13.3.tar.gz diff --git a/recipes/flet-libgdal/meta.yaml b/recipes/flet-libgdal/meta.yaml index 17c9e612..dec9cc4c 100644 --- a/recipes/flet-libgdal/meta.yaml +++ b/recipes/flet-libgdal/meta.yaml @@ -8,7 +8,7 @@ source: url: https://github.com/OSGeo/gdal/releases/download/v{{ version }}/gdal-{{ version }}.tar.gz build: - number: 1 + number: 4 requirements: build: diff --git a/recipes/flet-libgeos/meta.yaml b/recipes/flet-libgeos/meta.yaml index 5acb7e7e..5e9f89b7 100644 --- a/recipes/flet-libgeos/meta.yaml +++ b/recipes/flet-libgeos/meta.yaml @@ -3,7 +3,7 @@ package: version: 3.13.0 build: - number: 1 + number: 4 source: url: http://download.osgeo.org/geos/geos-3.13.0.tar.bz2 diff --git a/recipes/flet-libjpeg/meta.yaml b/recipes/flet-libjpeg/meta.yaml index c3ad9580..38a6fbd7 100644 --- a/recipes/flet-libjpeg/meta.yaml +++ b/recipes/flet-libjpeg/meta.yaml @@ -6,7 +6,7 @@ source: url: https://github.com/libjpeg-turbo/libjpeg-turbo/releases/download/3.0.90/libjpeg-turbo-3.0.90.tar.gz build: - number: 1 + number: 4 requirements: build: diff --git a/recipes/flet-libjq/meta.yaml b/recipes/flet-libjq/meta.yaml index 948eee21..400c32b4 100644 --- a/recipes/flet-libjq/meta.yaml +++ b/recipes/flet-libjq/meta.yaml @@ -8,7 +8,7 @@ source: url: https://github.com/jqlang/jq/releases/download/jq-{{ version }}/jq-{{ version }}.tar.gz build: - number: 1 + number: 4 requirements: build: diff --git a/recipes/flet-libopaque/meta.yaml b/recipes/flet-libopaque/meta.yaml index 3fe3c907..b5804dff 100644 --- a/recipes/flet-libopaque/meta.yaml +++ b/recipes/flet-libopaque/meta.yaml @@ -4,6 +4,9 @@ package: name: flet-libopaque version: '{{ version }}' +build: + number: 4 + source: url: https://github.com/stef/libopaque/archive/refs/tags/v{{ version }}.tar.gz diff --git a/recipes/flet-liboprf/meta.yaml b/recipes/flet-liboprf/meta.yaml index b9389643..76c0486d 100644 --- a/recipes/flet-liboprf/meta.yaml +++ b/recipes/flet-liboprf/meta.yaml @@ -12,6 +12,7 @@ requirements: - flet-libsodium 1.0.20 build: + number: 4 script_env: CFLAGS: '-Qunused-arguments -Wno-unreachable-code' diff --git a/recipes/flet-libpng/meta.yaml b/recipes/flet-libpng/meta.yaml index 21eaa2c4..9614942a 100644 --- a/recipes/flet-libpng/meta.yaml +++ b/recipes/flet-libpng/meta.yaml @@ -3,7 +3,7 @@ package: version: 1.6.43 build: - number: 1 + number: 4 source: url: https://github.com/pnggroup/libpng/archive/refs/tags/v1.6.43.tar.gz diff --git a/recipes/flet-libproj/meta.yaml b/recipes/flet-libproj/meta.yaml index 76134754..7b040427 100644 --- a/recipes/flet-libproj/meta.yaml +++ b/recipes/flet-libproj/meta.yaml @@ -8,17 +8,15 @@ source: url: https://download.osgeo.org/proj/proj-{{ version }}.tar.gz build: - number: 1 + number: 4 +# {% if sdk != 'android' %} + script_env: + LDFLAGS: '-undefined dynamic_lookup' +# {% endif %} requirements: build: - cmake host: - flet-libtiff 4.7.0 - - flet-libcurl 8.11.0 - -# {% if sdk != 'android' %} -build: - script_env: - LDFLAGS: '-undefined dynamic_lookup' -# {% endif %} \ No newline at end of file + - flet-libcurl 8.11.0 \ No newline at end of file diff --git a/recipes/flet-libpsl/meta.yaml b/recipes/flet-libpsl/meta.yaml index d8da3832..92047cea 100644 --- a/recipes/flet-libpsl/meta.yaml +++ b/recipes/flet-libpsl/meta.yaml @@ -8,7 +8,7 @@ source: url: https://github.com/rockdaboot/libpsl/releases/download/{{ version }}/libpsl-{{ version }}.tar.gz build: - number: 1 + number: 4 patches: - config.patch \ No newline at end of file diff --git a/recipes/flet-libpyjni/meta.yaml b/recipes/flet-libpyjni/meta.yaml index aaf13d64..52b15198 100644 --- a/recipes/flet-libpyjni/meta.yaml +++ b/recipes/flet-libpyjni/meta.yaml @@ -3,7 +3,7 @@ package: version: 1.0.1 build: - number: 1 + number: 4 source: url: https://github.com/flet-dev/libpyjni/releases/download/v1.0.1/pyjni-1.0.1.tar.gz diff --git a/recipes/flet-libsodium/meta.yaml b/recipes/flet-libsodium/meta.yaml index 0b37a42b..568622d1 100644 --- a/recipes/flet-libsodium/meta.yaml +++ b/recipes/flet-libsodium/meta.yaml @@ -4,5 +4,8 @@ package: name: flet-libsodium version: '{{ version }}' +build: + number: 4 + source: url: https://github.com/jedisct1/libsodium/releases/download/{{ version }}-RELEASE/libsodium-{{ version }}.tar.gz \ No newline at end of file diff --git a/recipes/flet-libtiff/meta.yaml b/recipes/flet-libtiff/meta.yaml index 7380bfb5..ea05b71b 100644 --- a/recipes/flet-libtiff/meta.yaml +++ b/recipes/flet-libtiff/meta.yaml @@ -8,7 +8,7 @@ source: url: https://download.osgeo.org/libtiff/tiff-{{ version }}.tar.gz build: - number: 1 + number: 4 requirements: host: diff --git a/recipes/flet-libxml2/meta.yaml b/recipes/flet-libxml2/meta.yaml index 83d36302..607b99ae 100755 --- a/recipes/flet-libxml2/meta.yaml +++ b/recipes/flet-libxml2/meta.yaml @@ -9,6 +9,9 @@ package: name: flet-libxml2 version: '{{ version }}' +build: + number: 1 + source: url: https://download.gnome.org/sources/libxml2/{{ version.rsplit('.', 1)[0] }}/libxml2-{{ version }}.tar.xz diff --git a/recipes/flet-libxslt/meta.yaml b/recipes/flet-libxslt/meta.yaml index 02ce4b2b..6704b837 100755 --- a/recipes/flet-libxslt/meta.yaml +++ b/recipes/flet-libxslt/meta.yaml @@ -11,6 +11,9 @@ package: name: flet-libxslt version: '{{ version }}' +build: + number: 1 + source: url: https://download.gnome.org/sources/libxslt/{{ version.rsplit('.', 1)[0] }}/libxslt-{{ version }}.tar.xz diff --git a/recipes/gdal/meta.yaml b/recipes/gdal/meta.yaml index 877f2bf8..26c031c6 100644 --- a/recipes/gdal/meta.yaml +++ b/recipes/gdal/meta.yaml @@ -7,6 +7,7 @@ requirements: - flet-libgdal 3.10.0 build: + number: 4 script_env: GDAL_VERSION: 3.10.0 GDAL_PREFIX: '{platlib}/opt' diff --git a/recipes/google-crc32c/meta.yaml b/recipes/google-crc32c/meta.yaml index 83512090..349b81a1 100644 --- a/recipes/google-crc32c/meta.yaml +++ b/recipes/google-crc32c/meta.yaml @@ -6,8 +6,9 @@ requirements: host: - flet-libcrc32c 1.1.2 -# {% if sdk != 'android' %} build: + number: 4 +# {% if sdk != 'android' %} script_env: LDFLAGS: '-lc++' # {% endif %} \ No newline at end of file diff --git a/recipes/greenlet/meta.yaml b/recipes/greenlet/meta.yaml index bdcaa310..90104e66 100644 --- a/recipes/greenlet/meta.yaml +++ b/recipes/greenlet/meta.yaml @@ -2,8 +2,9 @@ package: name: greenlet version: 3.1.1 -# {% if sdk != 'android' %} build: + number: 4 +# {% if sdk != 'android' %} script_env: CXXFLAGS: -std=c++14 # {% endif %} \ No newline at end of file diff --git a/recipes/grpcio/meta.yaml b/recipes/grpcio/meta.yaml index cc1b03f4..1afda7c5 100644 --- a/recipes/grpcio/meta.yaml +++ b/recipes/grpcio/meta.yaml @@ -3,6 +3,7 @@ package: version: 1.67.1 build: + number: 5 script_env: # {% if sdk == 'android' %} GRPC_PYTHON_BUILD_SYSTEM_OPENSSL: '1' diff --git a/recipes/jiter/meta.yaml b/recipes/jiter/meta.yaml index 27a817c9..e88513f4 100644 --- a/recipes/jiter/meta.yaml +++ b/recipes/jiter/meta.yaml @@ -3,5 +3,6 @@ package: version: 0.8.2 build: + number: 4 script_env: _PYTHON_SYSCONFIGDATA_NAME: '{sysconfigdata_name}' \ No newline at end of file diff --git a/recipes/jq/meta.yaml b/recipes/jq/meta.yaml index 5249ea96..7b78f433 100644 --- a/recipes/jq/meta.yaml +++ b/recipes/jq/meta.yaml @@ -7,5 +7,6 @@ requirements: - flet-libjq 1.7.1 build: + number: 4 script_env: JQPY_USE_SYSTEM_LIBS: 1 \ No newline at end of file diff --git a/recipes/kiwisolver/meta.yaml b/recipes/kiwisolver/meta.yaml index 482075ca..811876fe 100644 --- a/recipes/kiwisolver/meta.yaml +++ b/recipes/kiwisolver/meta.yaml @@ -2,6 +2,9 @@ package: name: kiwisolver version: 1.4.7 +build: + number: 4 + # {% if sdk == 'android' %} requirements: host: diff --git a/recipes/lru-dict/meta.yaml b/recipes/lru-dict/meta.yaml index 6b2ba9af..680fcda9 100644 --- a/recipes/lru-dict/meta.yaml +++ b/recipes/lru-dict/meta.yaml @@ -1,3 +1,6 @@ package: name: lru-dict version: 1.3.0 + +build: + number: 4 diff --git a/recipes/lxml/meta.yaml b/recipes/lxml/meta.yaml index 7a959b51..fa41ef2c 100644 --- a/recipes/lxml/meta.yaml +++ b/recipes/lxml/meta.yaml @@ -12,6 +12,7 @@ package: version: '{{ version }}' build: + number: 1 script_env: WITH_XML2_CONFIG: '{platlib}/opt/bin/xml2-config' WITH_XSLT_CONFIG: '{platlib}/opt/bin/xslt-config' diff --git a/recipes/markupsafe/meta.yaml b/recipes/markupsafe/meta.yaml index 8a10f7a1..700d466d 100644 --- a/recipes/markupsafe/meta.yaml +++ b/recipes/markupsafe/meta.yaml @@ -1,3 +1,6 @@ package: name: MarkupSafe version: 2.1.5 + +build: + number: 4 diff --git a/recipes/matplotlib/meta.yaml b/recipes/matplotlib/meta.yaml index f097cec1..5b1cbec2 100644 --- a/recipes/matplotlib/meta.yaml +++ b/recipes/matplotlib/meta.yaml @@ -12,6 +12,7 @@ requirements: - flet-libjpeg 3.0.90 build: + number: 4 # {% if sdk == 'android' and arch in ['armeabi-v7a', 'x86'] %} script_env: CPPFLAGS: -Wno-c++11-narrowing diff --git a/recipes/msgpack/meta.yaml b/recipes/msgpack/meta.yaml index 4e00554c..293c7c43 100644 --- a/recipes/msgpack/meta.yaml +++ b/recipes/msgpack/meta.yaml @@ -1,3 +1,6 @@ package: name: msgpack version: 1.1.0 + +build: + number: 4 diff --git a/recipes/msgspec/meta.yaml b/recipes/msgspec/meta.yaml index 3b52e5b4..b9842c22 100644 --- a/recipes/msgspec/meta.yaml +++ b/recipes/msgspec/meta.yaml @@ -2,6 +2,9 @@ package: name: msgspec version: 0.18.6 +build: + number: 4 + requirements: build: - setuptools ^69.5.1 \ No newline at end of file diff --git a/recipes/numpy/meta.yaml b/recipes/numpy/meta.yaml index 47bbde4f..05b04b08 100644 --- a/recipes/numpy/meta.yaml +++ b/recipes/numpy/meta.yaml @@ -17,6 +17,7 @@ patches: {% endif %} build: + number: 4 script_env: NPY_DISABLE_SVML: 1 diff --git a/recipes/opaque/meta.yaml b/recipes/opaque/meta.yaml index 3e1b6f63..a96fc3f3 100644 --- a/recipes/opaque/meta.yaml +++ b/recipes/opaque/meta.yaml @@ -2,6 +2,9 @@ package: name: opaque version: 0.2.0 +build: + number: 4 + requirements: host: - flet-libopaque 0.99.8 \ No newline at end of file diff --git a/recipes/opencv-python/meta.yaml b/recipes/opencv-python/meta.yaml index 12989d1a..a3830d0c 100644 --- a/recipes/opencv-python/meta.yaml +++ b/recipes/opencv-python/meta.yaml @@ -9,9 +9,10 @@ requirements: patches: - mobile.patch -# {% if sdk == 'android' %} build: + number: 4 script_env: +# {% if sdk == 'android' %} CMAKE_ARGS: >- -DANDROID=ON -DWITH_IPP=OFF @@ -34,8 +35,6 @@ build: -DPYTHON3_LIBRARIES={prefix}/lib/libpython{py_version_short}.so -DPYTHON3_NUMPY_INCLUDE_DIRS={platlib}/numpy/_core/include # {% else %} -build: - script_env: CMAKE_ARGS: >- -DAPPLE_FRAMEWORK=ON -DCMAKE_SYSTEM_NAME=iOS diff --git a/recipes/orjson/meta.yaml b/recipes/orjson/meta.yaml index 1f7e86d8..1a7edd2a 100644 --- a/recipes/orjson/meta.yaml +++ b/recipes/orjson/meta.yaml @@ -3,5 +3,6 @@ package: version: 3.11.9 build: + number: 1 script_env: _PYTHON_SYSCONFIGDATA_NAME: '{sysconfigdata_name}' diff --git a/recipes/pandas/meta.yaml b/recipes/pandas/meta.yaml index a5acaf71..5234d422 100644 --- a/recipes/pandas/meta.yaml +++ b/recipes/pandas/meta.yaml @@ -19,6 +19,7 @@ patches: - mobile.patch build: + number: 4 backend-args: - -Csetup-args=--cross-file - -Csetup-args={MESON_CROSS_FILE} diff --git a/recipes/pendulum/meta.yaml b/recipes/pendulum/meta.yaml index 68c697f1..7aed052d 100644 --- a/recipes/pendulum/meta.yaml +++ b/recipes/pendulum/meta.yaml @@ -3,6 +3,7 @@ package: version: 3.0.0 build: + number: 4 script_env: _PYTHON_SYSCONFIGDATA_NAME: '{sysconfigdata_name}' # {% if sdk == 'iphonesimulator' %} diff --git a/recipes/pillow/meta.yaml b/recipes/pillow/meta.yaml index 46c9fa48..b8df623e 100644 --- a/recipes/pillow/meta.yaml +++ b/recipes/pillow/meta.yaml @@ -22,8 +22,9 @@ patches: # {% endif %} -# {% if sdk != 'android' %} build: + number: 4 +# {% if sdk != 'android' %} script_env: # libfreetype references both libz and libbz2 # but doesn't link them into the static library diff --git a/recipes/primp/meta.yaml b/recipes/primp/meta.yaml index 344ef6f7..8c2275a0 100644 --- a/recipes/primp/meta.yaml +++ b/recipes/primp/meta.yaml @@ -1,3 +1,6 @@ package: name: primp - version: 1.3.1 \ No newline at end of file + version: 1.3.1 + +build: + number: 1 diff --git a/recipes/protobuf/meta.yaml b/recipes/protobuf/meta.yaml index 1846a408..38777832 100644 --- a/recipes/protobuf/meta.yaml +++ b/recipes/protobuf/meta.yaml @@ -1,3 +1,6 @@ package: name: protobuf version: 5.28.3 + +build: + number: 4 diff --git a/recipes/pycryptodome/meta.yaml b/recipes/pycryptodome/meta.yaml index bf322325..b57c3896 100644 --- a/recipes/pycryptodome/meta.yaml +++ b/recipes/pycryptodome/meta.yaml @@ -2,5 +2,8 @@ package: name: pycryptodome version: 3.21.0 +build: + number: 4 + patches: - mobile.patch \ No newline at end of file diff --git a/recipes/pycryptodomex/meta.yaml b/recipes/pycryptodomex/meta.yaml index f8c10a89..2f81852d 100644 --- a/recipes/pycryptodomex/meta.yaml +++ b/recipes/pycryptodomex/meta.yaml @@ -2,5 +2,8 @@ package: name: pycryptodomex version: 3.21.0 +build: + number: 4 + patches: - mobile.patch \ No newline at end of file diff --git a/recipes/pydantic-core/meta.yaml b/recipes/pydantic-core/meta.yaml index 009c58da..cb3ef624 100644 --- a/recipes/pydantic-core/meta.yaml +++ b/recipes/pydantic-core/meta.yaml @@ -3,5 +3,6 @@ package: version: 2.33.2 build: + number: 4 script_env: _PYTHON_SYSCONFIGDATA_NAME: '{sysconfigdata_name}' \ No newline at end of file diff --git a/recipes/pyjnius/meta.yaml b/recipes/pyjnius/meta.yaml index 9c0b6072..2c33aa00 100644 --- a/recipes/pyjnius/meta.yaml +++ b/recipes/pyjnius/meta.yaml @@ -2,6 +2,9 @@ package: name: pyjnius version: 1.6.1 +build: + number: 4 + patches: - mobile.patch diff --git a/recipes/pymongo/meta.yaml b/recipes/pymongo/meta.yaml index 53d1369c..79a9cbb7 100644 --- a/recipes/pymongo/meta.yaml +++ b/recipes/pymongo/meta.yaml @@ -1,3 +1,6 @@ package: name: pymongo - version: 4.10.1 \ No newline at end of file + version: 4.10.1 + +build: + number: 4 diff --git a/recipes/pynacl/meta.yaml b/recipes/pynacl/meta.yaml index b2df7a2f..46fd8671 100644 --- a/recipes/pynacl/meta.yaml +++ b/recipes/pynacl/meta.yaml @@ -2,6 +2,9 @@ package: name: PyNaCl version: 1.5.0 +build: + number: 4 + requirements: host: - flet-libsodium 1.0.20 diff --git a/recipes/pyobjus/meta.yaml b/recipes/pyobjus/meta.yaml index 7ac0dc55..15d6fd1a 100644 --- a/recipes/pyobjus/meta.yaml +++ b/recipes/pyobjus/meta.yaml @@ -2,6 +2,9 @@ package: name: pyobjus version: 1.2.3 +build: + number: 1 + patches: - mobile.patch diff --git a/recipes/pyogrio/meta.yaml b/recipes/pyogrio/meta.yaml index 104bb531..fa6c36fe 100644 --- a/recipes/pyogrio/meta.yaml +++ b/recipes/pyogrio/meta.yaml @@ -7,6 +7,7 @@ requirements: - flet-libgdal 3.10.0 build: + number: 4 script_env: GDAL_VERSION: 3.10.0 GDAL_LIBRARY_PATH: '{platlib}/opt/lib' diff --git a/recipes/pyproj/meta.yaml b/recipes/pyproj/meta.yaml index 50408874..0d26cf64 100644 --- a/recipes/pyproj/meta.yaml +++ b/recipes/pyproj/meta.yaml @@ -3,6 +3,7 @@ package: version: 3.7.0 build: + number: 4 script_env: PROJ_VERSION: 9.5.0 PROJ_DIR: '{platlib}/opt' diff --git a/recipes/pysodium/meta.yaml b/recipes/pysodium/meta.yaml index 823a2cab..2bc8811e 100644 --- a/recipes/pysodium/meta.yaml +++ b/recipes/pysodium/meta.yaml @@ -2,6 +2,9 @@ package: name: pysodium version: 0.7.18 +build: + number: 4 + requirements: host: - flet-libsodium 1.0.20 \ No newline at end of file diff --git a/recipes/pyyaml/meta.yaml b/recipes/pyyaml/meta.yaml index 5ada0c05..96829e21 100644 --- a/recipes/pyyaml/meta.yaml +++ b/recipes/pyyaml/meta.yaml @@ -1,3 +1,6 @@ package: name: PyYAML version: 6.0.2 + +build: + number: 4 diff --git a/recipes/rasterio/meta.yaml b/recipes/rasterio/meta.yaml index db38d942..4ced6b06 100644 --- a/recipes/rasterio/meta.yaml +++ b/recipes/rasterio/meta.yaml @@ -11,6 +11,7 @@ requirements: # {% endif %} build: + number: 2 script_env: GDAL_VERSION: 3.10.0 GDAL_LIB_PATH: '{platlib}/opt/lib' diff --git a/recipes/regex/meta.yaml b/recipes/regex/meta.yaml index 60ef895d..3d6ac1b0 100644 --- a/recipes/regex/meta.yaml +++ b/recipes/regex/meta.yaml @@ -1,3 +1,6 @@ package: name: regex - version: 2024.11.6 \ No newline at end of file + version: 2024.11.6 + +build: + number: 4 diff --git a/recipes/rpds-py/meta.yaml b/recipes/rpds-py/meta.yaml index 907a6484..12297f6b 100644 --- a/recipes/rpds-py/meta.yaml +++ b/recipes/rpds-py/meta.yaml @@ -3,5 +3,6 @@ package: version: 0.23.1 build: + number: 4 script_env: _PYTHON_SYSCONFIGDATA_NAME: '{sysconfigdata_name}' \ No newline at end of file diff --git a/recipes/ruamel.yaml.clib/meta.yaml b/recipes/ruamel.yaml.clib/meta.yaml index 2caa1ed0..0a2e8158 100644 --- a/recipes/ruamel.yaml.clib/meta.yaml +++ b/recipes/ruamel.yaml.clib/meta.yaml @@ -1,3 +1,6 @@ package: name: ruamel.yaml.clib - version: 0.2.12 \ No newline at end of file + version: 0.2.12 + +build: + number: 1 diff --git a/recipes/selectolax/meta.yaml b/recipes/selectolax/meta.yaml index 68ceaf1e..7d482f29 100644 --- a/recipes/selectolax/meta.yaml +++ b/recipes/selectolax/meta.yaml @@ -1,3 +1,6 @@ package: name: selectolax version: 0.4.10 + +build: + number: 0 diff --git a/recipes/shapely/meta.yaml b/recipes/shapely/meta.yaml index 22d9884d..b50c9594 100644 --- a/recipes/shapely/meta.yaml +++ b/recipes/shapely/meta.yaml @@ -2,6 +2,9 @@ package: name: shapely version: 2.0.6 +build: + number: 4 + requirements: host: - flet-libgeos 3.13.0 diff --git a/recipes/sqlalchemy/meta.yaml b/recipes/sqlalchemy/meta.yaml index 3b52fe59..6fe0f3e2 100644 --- a/recipes/sqlalchemy/meta.yaml +++ b/recipes/sqlalchemy/meta.yaml @@ -1,3 +1,6 @@ package: name: sqlalchemy - version: 2.0.36 \ No newline at end of file + version: 2.0.36 + +build: + number: 4 diff --git a/recipes/tiktoken/meta.yaml b/recipes/tiktoken/meta.yaml index 88290fa3..3300bb0f 100644 --- a/recipes/tiktoken/meta.yaml +++ b/recipes/tiktoken/meta.yaml @@ -3,5 +3,6 @@ package: version: 0.9.0 build: + number: 4 script_env: _PYTHON_SYSCONFIGDATA_NAME: '{sysconfigdata_name}' \ No newline at end of file diff --git a/recipes/time-machine/meta.yaml b/recipes/time-machine/meta.yaml index 8f8c5a59..caec2e55 100644 --- a/recipes/time-machine/meta.yaml +++ b/recipes/time-machine/meta.yaml @@ -1,3 +1,6 @@ package: name: time-machine - version: 2.16.0 \ No newline at end of file + version: 2.16.0 + +build: + number: 4 diff --git a/recipes/tokenizers/meta.yaml b/recipes/tokenizers/meta.yaml index 85322cf1..2562faab 100644 --- a/recipes/tokenizers/meta.yaml +++ b/recipes/tokenizers/meta.yaml @@ -3,5 +3,6 @@ package: version: 0.21.0 build: + number: 4 script_env: _PYTHON_SYSCONFIGDATA_NAME: '{sysconfigdata_name}' \ No newline at end of file diff --git a/recipes/ujson/meta.yaml b/recipes/ujson/meta.yaml index 36ae023a..96af0659 100644 --- a/recipes/ujson/meta.yaml +++ b/recipes/ujson/meta.yaml @@ -2,6 +2,9 @@ package: name: ujson version: 5.12.1 +build: + number: 1 + # {% if sdk == 'android' %} # ujson links its bundled double-conversion C++ code against NDK's libc++. # NDK r27 defaults to libc++_shared, so the .so has a runtime dlopen() on diff --git a/recipes/websockets/meta.yaml b/recipes/websockets/meta.yaml index a4f7c61f..fdc85c2a 100644 --- a/recipes/websockets/meta.yaml +++ b/recipes/websockets/meta.yaml @@ -1,3 +1,6 @@ package: name: websockets - version: 13.0.1 \ No newline at end of file + version: 13.0.1 + +build: + number: 4 diff --git a/recipes/yarl/meta.yaml b/recipes/yarl/meta.yaml index b87129db..f4f15591 100644 --- a/recipes/yarl/meta.yaml +++ b/recipes/yarl/meta.yaml @@ -2,6 +2,9 @@ package: name: yarl version: 1.11.1 +build: + number: 4 + requirements: build: - cython \ No newline at end of file diff --git a/recipes/zope.interface/meta.yaml b/recipes/zope.interface/meta.yaml index 60fc6735..5bb53148 100644 --- a/recipes/zope.interface/meta.yaml +++ b/recipes/zope.interface/meta.yaml @@ -1,3 +1,6 @@ package: name: zope.interface - version: '7.2' \ No newline at end of file + version: '7.2' + +build: + number: 4 diff --git a/recipes/zstandard/meta.yaml b/recipes/zstandard/meta.yaml index ac640897..d194e1f4 100644 --- a/recipes/zstandard/meta.yaml +++ b/recipes/zstandard/meta.yaml @@ -1,3 +1,6 @@ package: name: zstandard - version: 0.23.0 \ No newline at end of file + version: 0.23.0 + +build: + number: 4 From 13f4958a6596848ae5d82676d95fcfc7d7b95796 Mon Sep 17 00:00:00 2001 From: TheEthicalBoy <98978078+ndonkoHenri@users.noreply.github.com> Date: Mon, 1 Jun 2026 22:38:10 +0200 Subject: [PATCH 130/142] fix(numpy): add Android `flet-libcpp-shared` host dep (#58) * numpy: declare flet-libcpp-shared host dep on Android * bump numpy meta.yaml build number --- recipes/numpy/meta.yaml | 8 ++++++-- recipes/numpy/test_numpy.py | 23 +++++++++++++++++++++++ 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/recipes/numpy/meta.yaml b/recipes/numpy/meta.yaml index 05b04b08..ff8aa45c 100644 --- a/recipes/numpy/meta.yaml +++ b/recipes/numpy/meta.yaml @@ -8,6 +8,10 @@ package: requirements: build: - ninja +{% if sdk == 'android' %} + host: + - flet-libcpp-shared >=27.2.12479018 +{% endif %} patches: {% if version and version < (2, 0) %} @@ -17,7 +21,7 @@ patches: {% endif %} build: - number: 4 + number: 5 script_env: NPY_DISABLE_SVML: 1 @@ -33,4 +37,4 @@ build: longdouble_format: IEEE_QUAD_LE # {% else %} longdouble_format: IEEE_DOUBLE_LE -# {% endif %} \ No newline at end of file +# {% endif %} diff --git a/recipes/numpy/test_numpy.py b/recipes/numpy/test_numpy.py index ee7122bf..51a7d333 100644 --- a/recipes/numpy/test_numpy.py +++ b/recipes/numpy/test_numpy.py @@ -20,3 +20,26 @@ def test_performance(): duration = time() - start_time print(f"{duration:.3f}") assert duration < 0.7 + + +def test_fft(): + """Forces _pocketfft_umath.so to load — the canary for the libc++_shared + Android dep.""" + import numpy as np + + # 8-point FFT of a pure cosine at frequency k=2. The real-input FFT of + # cos(2π · k · n / N) has two equal-magnitude peaks at bins k and N-k. + x = np.cos(2 * np.pi * 2 * np.arange(8) / 8) + spectrum = np.fft.fft(x) + magnitudes = np.abs(spectrum) + + # Peaks at bins 2 and 6 with magnitude N/2 = 4 for unit-amplitude cosine. + assert magnitudes[2] > 3.9, f"bin 2 magnitude = {magnitudes[2]}" + assert magnitudes[6] > 3.9, f"bin 6 magnitude = {magnitudes[6]}" + # All other bins should be ~0 (within fp noise). + other = max(float(magnitudes[i]) for i in (0, 1, 3, 4, 5, 7)) + assert other < 1e-6, f"unexpected non-zero bin: {other}" + + # Round-trip: inverse FFT recovers the original signal. + recovered = np.fft.ifft(spectrum).real + assert np.allclose(recovered, x) From 2f6ce8f44c1bef218e9e8df514c7c35163b1658b Mon Sep 17 00:00:00 2001 From: TheEthicalBoy <98978078+ndonkoHenri@users.noreply.github.com> Date: Mon, 1 Jun 2026 22:40:59 +0200 Subject: [PATCH 131/142] fix(`pyyaml`): bundle the `_yaml` C accelerator via new `flet-libyaml` recipe (#62) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * pyyaml: bundle the _yaml C accelerator via new flet-libyaml recipe The pyyaml wheels currently published on pypi.flet.dev ship pure- Python only — every Android build of PyYAML 6.0.2 to date is missing the `_yaml` Cython accelerator, and iOS has never shipped a pyyaml wheel at all (`https://pypi.flet.dev/pyyaml/` lists four Android wheels and zero iOS wheels). PyYAML's setup.py wraps the C-extension build in `except DistutilsPlatformError: log.warn ("skipping build_ext")`, so without libyaml's headers + .so on the build root the wheel still builds, it just silently omits the .so. The pure-Python loader works for basic `yaml.safe_load`, so the gap is invisible until code reaches for `yaml.CSafeDumper` / `yaml.CSafeLoader` (absent from the namespace because cyaml.py only exposes them when `_yaml` imports), or until someone notices 500-doc round-trips take ~10× longer than they should. Three changes here: 1. `recipes/flet-libyaml/` — new recipe for libyaml 0.2.5 (https://github.com/yaml/libyaml). Builds the shared library on Android and both shared + the .a archive on iOS, mirroring how `flet-libsodium` is consumed by PyNaCl: Android pyyaml dynamically links libyaml.so, iOS pyyaml links it statically into `_yaml.cpython-*.so`. `libyaml_la_LDFLAGS` is rewritten to add `-avoid-version` (so the install name stays `libyaml.so` / `libyaml.dylib` instead of `libyaml-0.so`) and `-pthread` (filler that keeps libtool's bare `-F` on iOS from eating the next token, mirroring the libsodium fix). 2. `recipes/pyyaml/meta.yaml` — declare `flet-libyaml 0.2.5` as a host dep. Comment explains the silent skip behaviour so a future reader doesn't undo it without realising what they're removing. 3. `recipes/pyyaml/test_pyyaml.py` — three pytest functions that any pyyaml-using Flet app actually depends on: - `test_basic`: yaml.safe_dump → safe_load roundtrip. Passes even on a pure-Python wheel; proves the wheel ships. - `test_c_extension`: import _yaml + assert hasattr(_yaml, "CParser"). This is the canary — fires when the .so was never bundled (the current published wheel) or when libyaml fails to load at runtime on-device. - `test_csafedumper_binding`: `from yaml import CSafeDumper, CSafeLoader`. Functionally subsumed by test_c_extension but kept because it's the import shape real apps break on, and a clean ImportError here points a debugger at the _yaml/libyaml chain instead of an obscure attribute-missing surprise downstream. Note on the publish-first dance ------------------------------- This PR introduces a brand-new flet-libyaml package that pyyaml host-deps. CI's matrix is flat (no inter-job artifact sharing), so on the first run after merge the `pyyaml` job will fail to resolve `flet-libyaml==0.2.5` from pypi.flet.dev — it doesn't exist there yet, and the `flet-libyaml` job builds it in a different runner. The unblock: dispatch the workflow manually with `packages=flet-libyaml:1` + `publish=true` to push libyaml's wheels to pypi.flet.dev via Gemfury, then re-run the pyyaml job (or wait for the next push). Once libyaml is on pypi.flet.dev, pyyaml resolves cleanly and produces a wheel that actually includes `_yaml.cpython-*.so` on both Android and iOS. * pyyaml: bump build.number from 4 to 5 The previously-published pyyaml-6.0.2-4-*.whl set on pypi.flet.dev (Android: arm64-v8a, armeabi-v7a, x86, x86_64; iOS: none) was built before `flet-libyaml` existed, so PyYAML's setup.py silently skipped `_yaml` and shipped pure-Python only. Build 5 — produced from the same source tarball but with libyaml on the build root courtesy of the preceding commit — ships `_yaml.cpython-*.so` for the first time and supersedes the -4- wheels via PEP 427 build-tag tie-break. iOS gets a pyyaml wheel for the first time at the same build tag. --- recipes/flet-libyaml/build.sh | 62 ++++++++++++++++++++++++++++++++++ recipes/flet-libyaml/meta.yaml | 9 +++++ recipes/pyyaml/meta.yaml | 9 ++++- recipes/pyyaml/test_pyyaml.py | 42 +++++++++++++++++++++++ 4 files changed, 121 insertions(+), 1 deletion(-) create mode 100755 recipes/flet-libyaml/build.sh create mode 100644 recipes/flet-libyaml/meta.yaml create mode 100644 recipes/pyyaml/test_pyyaml.py diff --git a/recipes/flet-libyaml/build.sh b/recipes/flet-libyaml/build.sh new file mode 100755 index 00000000..1e25e5f9 --- /dev/null +++ b/recipes/flet-libyaml/build.sh @@ -0,0 +1,62 @@ +#!/bin/bash +set -eu + +if [ $CROSS_VENV_SDK != "android" ]; then + case $HOST_TRIPLET in + arm64-apple-ios) + HOST_TRIPLET=arm-apple-darwin23 + ;; + arm64-apple-ios-simulator) + HOST_TRIPLET=aarch64-apple-darwin23 + ;; + x86_64-apple-ios-simulator) + HOST_TRIPLET=x86_64-apple-darwin23 + ;; + *) + echo "Unknown host triplet: '$HOST_TRIPLET'" + exit 1 + ;; + esac +fi + +# On Android we want libyaml as a shared library — pyyaml's `_yaml.so` links +# against it dynamically and forge ships `libyaml.so` in `opt/lib/`. +# On iOS we additionally need the static archive (`libyaml.a`) so pyyaml's +# `-lyaml` resolves at link time. iOS pyyaml statically links libyaml into +# `_yaml.cpython-*.so`, mirroring how PyNaCl statically links libsodium via +# the `libsodium.a` that flet-libsodium ships in `opt/lib/`. +if [ $CROSS_VENV_SDK == "android" ]; then + ./configure --host=$HOST_TRIPLET --prefix=$PREFIX --disable-static +else + ./configure --host=$HOST_TRIPLET --prefix=$PREFIX +fi + +# Rewrite libyaml_la_LDFLAGS to drop libtool's library-versioning flags and to +# work around forge's `-F ""` quoting on iOS: +# +# - Default flags are `-no-undefined -release $(YAML_LT_RELEASE) -version-info $(YAML_LT_CURRENT):$(YAML_LT_REVISION):$(YAML_LT_AGE)`. +# `-release` + `-version-info` make libtool produce a versioned dylib +# (`libyaml-0.2.dylib` / `libyaml-0.so`). On Android that forced PyYAML's +# `-lyaml` to need a separate `libyaml.so → libyaml-0.so` shim; on iOS the +# versioned install_name path doesn't exist yet at link time and clang dies. +# `-avoid-version` makes libtool skip versioning entirely → plain +# `libyaml.so` / `libyaml.dylib` with matching soname/install_name. +# - `-pthread` is benign filler. forge injects `-F ""` +# into LDFLAGS for iOS, but libtool re-emits it as bare `-F ` (empty +# arg) — clang then consumes the NEXT token as the framework path. With +# no filler, that next token is `-install_name` and the install_name flag +# silently disappears, dropping clang into "treat /path/libyaml.dylib as a +# source file" mode → "no such file or directory". libsodium happens to +# have `-pthread` in this slot from its own LDFLAGS, which is why +# libsodium builds cleanly; we add it here for the same reason. +sed -i.bak 's/^\(libyaml_la_LDFLAGS *=\).*$/\1 -no-undefined -avoid-version -pthread/' src/Makefile +rm src/Makefile.bak + +make -j $CPU_COUNT +make install + +rm -r $PREFIX/lib/{*.la,pkgconfig} + +if [ $CROSS_VENV_SDK != "android" ]; then + mv $PREFIX/lib/libyaml.dylib $PREFIX/../libyaml.so +fi diff --git a/recipes/flet-libyaml/meta.yaml b/recipes/flet-libyaml/meta.yaml new file mode 100644 index 00000000..80a5da46 --- /dev/null +++ b/recipes/flet-libyaml/meta.yaml @@ -0,0 +1,9 @@ +package: + name: flet-libyaml + version: 0.2.5 + +build: + number: 1 + +source: + url: https://github.com/yaml/libyaml/releases/download/0.2.5/yaml-0.2.5.tar.gz diff --git a/recipes/pyyaml/meta.yaml b/recipes/pyyaml/meta.yaml index 96829e21..c3be4692 100644 --- a/recipes/pyyaml/meta.yaml +++ b/recipes/pyyaml/meta.yaml @@ -3,4 +3,11 @@ package: version: 6.0.2 build: - number: 4 + number: 5 + +requirements: + host: + # Without libyaml's headers + shared library on the build root, PyYAML's + # setup.py silently skips the `_yaml` C extension (`DistutilsPlatformError` + # → `log.warn("skipping build_ext")`) and ships a pure-Python wheel. + - flet-libyaml 0.2.5 diff --git a/recipes/pyyaml/test_pyyaml.py b/recipes/pyyaml/test_pyyaml.py new file mode 100644 index 00000000..62b451ad --- /dev/null +++ b/recipes/pyyaml/test_pyyaml.py @@ -0,0 +1,42 @@ +def test_basic(): + """Round-trip a small document through PyYAML's C-loader and C-dumper.""" + import yaml + + doc = { + "name": "mobile-forge", + "components": ["recipes", "tests", "ci"], + "android": {"api": 24, "abi": ["arm64-v8a", "x86_64"]}, + "iOS": {"min": "13.0"}, + } + text = yaml.safe_dump(doc, sort_keys=True) + assert yaml.safe_load(text) == doc + + +def test_c_extension(): + """The C accelerator (_yaml) is what this recipe primarily exists for. + + PyYAML exposes `CSafeDumper`/`CSafeLoader` only when the `_yaml` C + extension successfully imports — otherwise they're simply absent + from the `yaml` package namespace (no exception, no None — just + missing names). Probe by importing `_yaml` and checking it carries + the Cython-emitted `CParser` class. That assertion fires both when + the .so was never shipped AND when libyaml fails to load at import + time on the device.""" + import _yaml + + assert hasattr(_yaml, "CParser"), ( + "PyYAML's _yaml C extension loaded but is missing CParser — " + "libyaml probably failed to load at import time" + ) + + +def test_csafedumper_binding(): + """The user-facing surface: `from yaml import CSafeDumper, CSafeLoader`. + + Functionally subsumed by test_c_extension (cyaml.py exposes these + classes iff `_yaml.CParser` exists), but kept as a separate test + because (a) this is the import shape real apps break on and (b) a + clean ImportError here points a future debugger straight at the + `_yaml`/libyaml chain instead of an obscure attribute-missing + surprise downstream.""" + from yaml import CSafeDumper, CSafeLoader # noqa: F401 From 1d84f993b59ce170d5fdf0e8244bf675bae2bec9 Mon Sep 17 00:00:00 2001 From: TheEthicalBoy <98978078+ndonkoHenri@users.noreply.github.com> Date: Mon, 1 Jun 2026 22:41:43 +0200 Subject: [PATCH 132/142] recipe: pyxirr 0.10.8 (#57) * recipe: pyxirr 0.10.8 * remove mobile patch * Add build number to pyxirr meta.yaml --- recipes/pyxirr/meta.yaml | 6 +++--- recipes/pyxirr/patches/mobile.patch | 10 ---------- recipes/pyxirr/test_pyxirr.py | 22 ++++++++++++++++++++++ 3 files changed, 25 insertions(+), 13 deletions(-) delete mode 100644 recipes/pyxirr/patches/mobile.patch create mode 100644 recipes/pyxirr/test_pyxirr.py diff --git a/recipes/pyxirr/meta.yaml b/recipes/pyxirr/meta.yaml index aed575fc..f76acfb1 100644 --- a/recipes/pyxirr/meta.yaml +++ b/recipes/pyxirr/meta.yaml @@ -1,6 +1,6 @@ package: name: pyxirr - version: 0.10.6 + version: 0.10.8 -patches: - - mobile.patch \ No newline at end of file +build: + number: 1 diff --git a/recipes/pyxirr/patches/mobile.patch b/recipes/pyxirr/patches/mobile.patch deleted file mode 100644 index ff5bf54f..00000000 --- a/recipes/pyxirr/patches/mobile.patch +++ /dev/null @@ -1,10 +0,0 @@ -diff --git a/pyproject.toml b/pyproject.toml -index be1a7b7..7bda5b8 100644 ---- a/pyproject.toml -+++ b/pyproject.toml -@@ -1,4 +1,5 @@ - [project] -+version = "0.10.6" - name = "pyxirr" - description-content-type = "text/markdown; charset=UTF-8; variant=GFM" - requires-python = ">=3.7,<3.14" diff --git a/recipes/pyxirr/test_pyxirr.py b/recipes/pyxirr/test_pyxirr.py new file mode 100644 index 00000000..4a5aede7 --- /dev/null +++ b/recipes/pyxirr/test_pyxirr.py @@ -0,0 +1,22 @@ +def test_basic(): + """Proves the wheel loads and the Rust solver works: irr() finds the rate + where npv() == 0, so we check both the known value and the npv round-trip.""" + import pyxirr + + amounts = [-100, 39, 59, 55, 20] + r = pyxirr.irr(amounts) + assert abs(r - 0.2809484211599611) < 1e-6 + assert abs(pyxirr.npv(r, amounts)) < 1e-6 + + +def test_xirr(): + """XIRR is the function pyxirr is named after. Exercises date parsing and + the day-count engine (defaults to ACT_365F) on top of the solver.""" + import pyxirr + from datetime import date + + dates = [date(2020, 1, 1), date(2021, 1, 1), date(2022, 1, 1)] + amounts = [-1000, 750, 500] + rate = pyxirr.xirr(dates, amounts) + assert abs(rate - 0.17500926461545202) < 1e-4 + assert abs(pyxirr.xnpv(rate, dates, amounts)) < 1e-4 From 4f2ad23de301030677139317bc445638be8c3b0f Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Tue, 2 Jun 2026 17:06:54 -0700 Subject: [PATCH 133/142] Resolve per-version support paths in setup.sh `source ./setup.sh 3.13.13` now picks up MOBILE_FORGE_IOS_SUPPORT_PATH_3_13 and MOBILE_FORGE_ANDROID_SUPPORT_PATH_3_13 if they're set, so a single .envrc can declare paths for 3.12 / 3.13 / 3.14 side-by-side instead of having to re-export per version. The unversioned MOBILE_FORGE_*_SUPPORT_PATH vars are still honored as a fallback. --- setup.sh | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/setup.sh b/setup.sh index 035a64f0..d7963119 100755 --- a/setup.sh +++ b/setup.sh @@ -37,8 +37,24 @@ python_version_minor="${PYTHON_VER#*.}" echo "Python version: $PYTHON_VERSION" echo "Python short version: $PYTHON_VER" +# Per-version support-path overrides: MOBILE_FORGE_{IOS,ANDROID}_SUPPORT_PATH__ +# (e.g. MOBILE_FORGE_IOS_SUPPORT_PATH_3_13). When set, they take precedence over +# the unversioned variable for this session, so .envrc can declare paths for +# 3.12 / 3.13 / 3.14 side-by-side and `source ./setup.sh ` picks the right one. +versioned_suffix="${PYTHON_VER//./_}" +ios_versioned_var="MOBILE_FORGE_IOS_SUPPORT_PATH_${versioned_suffix}" +android_versioned_var="MOBILE_FORGE_ANDROID_SUPPORT_PATH_${versioned_suffix}" +if [ -n "${!ios_versioned_var}" ]; then + export MOBILE_FORGE_IOS_SUPPORT_PATH="${!ios_versioned_var}" +fi +if [ -n "${!android_versioned_var}" ]; then + export MOBILE_FORGE_ANDROID_SUPPORT_PATH="${!android_versioned_var}" +fi + if [[ -z "$MOBILE_FORGE_IOS_SUPPORT_PATH" && -z "$MOBILE_FORGE_ANDROID_SUPPORT_PATH" ]]; then echo "Neither MOBILE_FORGE_IOS_SUPPORT_PATH nor MOBILE_FORGE_ANDROID_SUPPORT_PATH are defined." + echo "Set MOBILE_FORGE_{IOS,ANDROID}_SUPPORT_PATH or per-version overrides" + echo "MOBILE_FORGE_{IOS,ANDROID}_SUPPORT_PATH_${versioned_suffix}." return fi From 01642f6cdbefc043c96a9a45b235de80bce31415 Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Wed, 3 Jun 2026 12:02:02 -0700 Subject: [PATCH 134/142] setup.sh: portable indirect variable expansion for zsh + bash The per-version support-path resolver was using bash's `${!varname}` indirect expansion. zsh doesn't support that form (it uses `${(P)var}`), so sourcing .envrc from a zsh shell - the default on recent macOS - aborted with `./setup.sh:47: bad substitution` before any venv could be created. Replace with `eval "varname=\${$indirect:-}"`, which is portable across both shells. Functionally identical to the prior bash-only path: empty or unset overrides leave the unversioned MOBILE_FORGE_*_SUPPORT_PATH fallback untouched. --- setup.sh | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/setup.sh b/setup.sh index d7963119..4da2c8ba 100755 --- a/setup.sh +++ b/setup.sh @@ -44,11 +44,15 @@ echo "Python short version: $PYTHON_VER" versioned_suffix="${PYTHON_VER//./_}" ios_versioned_var="MOBILE_FORGE_IOS_SUPPORT_PATH_${versioned_suffix}" android_versioned_var="MOBILE_FORGE_ANDROID_SUPPORT_PATH_${versioned_suffix}" -if [ -n "${!ios_versioned_var}" ]; then - export MOBILE_FORGE_IOS_SUPPORT_PATH="${!ios_versioned_var}" +# Indirect variable expansion: bash uses ${!var}, zsh uses ${(P)var}. +# `eval` is the portable form that works in both. +eval "ios_versioned_val=\${$ios_versioned_var:-}" +eval "android_versioned_val=\${$android_versioned_var:-}" +if [ -n "$ios_versioned_val" ]; then + export MOBILE_FORGE_IOS_SUPPORT_PATH="$ios_versioned_val" fi -if [ -n "${!android_versioned_var}" ]; then - export MOBILE_FORGE_ANDROID_SUPPORT_PATH="${!android_versioned_var}" +if [ -n "$android_versioned_val" ]; then + export MOBILE_FORGE_ANDROID_SUPPORT_PATH="$android_versioned_val" fi if [[ -z "$MOBILE_FORGE_IOS_SUPPORT_PATH" && -z "$MOBILE_FORGE_ANDROID_SUPPORT_PATH" ]]; then From b64468498ed9a6adb99a62a5e233c46a83d6ba99 Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Wed, 3 Jun 2026 12:02:13 -0700 Subject: [PATCH 135/142] Pin crossenv to the open Python 3.14 fix branch Python 3.14 made several changes that the upstream-pinned `@flet` branch can't handle yet: - `sysconfig._init_config_vars` became lazy, so crossenv's PathFinder patch recursed into half-initialised sysconfig and crashed with `AttributeError: 'installed_base'`. - The patched-modules sweep iterated `sys.modules.items()` directly, and the lazy sysconfig init grew it mid-iteration on 3.14, raising `RuntimeError: dictionary changed size during iteration`. - `ctypes/__init__.py` started doing `PyDLL(_sysconfig.get_config_var("LDLIBRARY"))` at module load, and the crossenv-patched value (the host's `libpython3.X.so`) doesn't exist on the build platform's dlopen path. All three are addressed in the open PR (flet-dev/crossenv#1). Pin the branch directly so a fresh `pip install -e .` in a 3.13/3.14 venv gets the fix without waiting for the PR to land on `@flet`. Flip back to `@flet` once the PR is merged. --- pyproject.toml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 6dd11818..85379660 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -29,7 +29,9 @@ classifiers = [ dependencies = [ # Currently using a fork of crossenv to get iOS fixes. # Replace when/if these are merged and released. - "crossenv @ git+https://github.com/flet-dev/crossenv@flet", + # Pinning the open fix branch (PR flet-dev/crossenv#1) so Python 3.14 + # cross-envs bootstrap cleanly. Flip back to @flet once the PR is merged. + "crossenv @ git+https://github.com/flet-dev/crossenv@fix/python-3.14-sysconfig-lazy-init", #"crossenv @ git+https://github.com/freakboy3742/crossenv@f0f07129eb06ea16d180650a26a02df2b948b888", #"crossenv @ git+https://github.com/benfogle/crossenv", "httpx == 0.27.0", From 33fecdaae454d4575ac973161551a558d0249879 Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Wed, 3 Jun 2026 12:02:29 -0700 Subject: [PATCH 136/142] Python 3.14 cross-build support: PYO3 LIBDIR + recipe bumps Three changes that together unblock building Rust-bound extension wheels for Android on Python 3.14. src/forge/build.py: add the host LIBDIR to the cargo link-search path. PYO3_CROSS_LIB_DIR is required to point at the host stdlib directory so that maturin's auto-detector finds `_sysconfigdata__*.py` (and, on 3.14+, build-details.json) - but that directory does not contain the actual `libpython*.so` files. The linker then receives `-lpython3` / `-lpython3.X` and fails to resolve them. Pull LIBDIR out of the host sysconfig and add it as an extra `-L` so the canonical libpython location is on the search path while PYO3_CROSS_LIB_DIR keeps doing its sysconfig-discovery job. recipes/cryptography/meta.yaml: select 48.0.0 on Python 3.14, keep 43.0.1 on <=3.13. cryptography 43.0.1 pins pyo3 0.22.2, which hard-stops at Python 3.13 (`error: the configured Python interpreter version (3.14) is newer than PyO3's maximum supported version (3.13)`). 48.0.0 moves the workspace to pyo3 0.28, which knows 3.14 natively and is classified as 3.14-supported on PyPI. Selecting per-version via Jinja so 3.12/3.13 consumers keep the previously-validated 43.0.1 build. recipes/pydantic-core/meta.yaml: bump 2.33.2 -> 2.47.0. Same root cause - 2.33.2 bundles a pre-3.14 pyo3 and aborts the Rust build with the same "newer than PyO3's maximum supported version" check; 2.47.0 bumps the embedded pyo3 to a version that knows 3.14. --- recipes/cryptography/meta.yaml | 6 ++++++ recipes/pydantic-core/meta.yaml | 2 +- src/forge/build.py | 9 +++++++++ 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/recipes/cryptography/meta.yaml b/recipes/cryptography/meta.yaml index a64edca3..95639320 100644 --- a/recipes/cryptography/meta.yaml +++ b/recipes/cryptography/meta.yaml @@ -1,6 +1,12 @@ package: name: cryptography +# cryptography 43.0.1 pins pyo3 0.22.2 which hard-stops at Python 3.13. +# 48.0.0 moves to pyo3 0.28 (knows 3.14) and classifies 3.14 as supported. +# {% if py_version.minor >= 14 %} + version: 48.0.0 +# {% else %} version: 43.0.1 +# {% endif %} requirements: host: diff --git a/recipes/pydantic-core/meta.yaml b/recipes/pydantic-core/meta.yaml index cb3ef624..46ea247d 100644 --- a/recipes/pydantic-core/meta.yaml +++ b/recipes/pydantic-core/meta.yaml @@ -1,6 +1,6 @@ package: name: pydantic-core - version: 2.33.2 + version: 2.47.0 build: number: 4 diff --git a/src/forge/build.py b/src/forge/build.py index ef7da5c5..76c69170 100644 --- a/src/forge/build.py +++ b/src/forge/build.py @@ -359,6 +359,15 @@ def compile_env(self, **kwargs) -> dict[str, str]: # cargo_ldflags = re.sub(r"-march=[\w-]+", "", ldflags) cargo_ldflags = " -L{}/lib".format(self.cross_venv.sysconfig_data["prefix"]) + # On Android, pyo3-ffi (and similar) link `-lpython3` / `-lpython3.`. + # PYO3_CROSS_LIB_DIR points at the host stdlib directory (so maturin can + # find _sysconfigdata__*.py and build-details.json there), but the + # actual `libpython*.so` files live in the host install's `lib/` + # directory (LIBDIR). Add LIBDIR as an extra library search path so the + # linker can resolve those `-lpython*` references. + host_libdir = self.cross_venv.sysconfig_data.get("LIBDIR") + if host_libdir: + cargo_ldflags += f" -L{host_libdir}" cargo_ldflags += " -C link-arg=-undefined -C link-arg=dynamic_lookup" if self.cross_venv.sdk == "android": From 483cb69eb386601e1a6ca541db6f5caff678d114 Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Wed, 3 Jun 2026 12:12:29 -0700 Subject: [PATCH 137/142] Update crossenv dependency to use the main branch for Python 3.14 compatibility --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 85379660..872a4c3a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -31,7 +31,7 @@ dependencies = [ # Replace when/if these are merged and released. # Pinning the open fix branch (PR flet-dev/crossenv#1) so Python 3.14 # cross-envs bootstrap cleanly. Flip back to @flet once the PR is merged. - "crossenv @ git+https://github.com/flet-dev/crossenv@fix/python-3.14-sysconfig-lazy-init", + "crossenv @ git+https://github.com/flet-dev/crossenv@flet", #"crossenv @ git+https://github.com/freakboy3742/crossenv@f0f07129eb06ea16d180650a26a02df2b948b888", #"crossenv @ git+https://github.com/benfogle/crossenv", "httpx == 0.27.0", From 21d0ccf61720e7bec5ff28f6e1cd7a62e87c9362 Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Wed, 3 Jun 2026 12:50:44 -0700 Subject: [PATCH 138/142] Remove cibuildwheel build workflow from CI configuration --- .../build-wheels-with-cibuildwheel.yml | 43 ------------------- 1 file changed, 43 deletions(-) delete mode 100644 .github/workflows/build-wheels-with-cibuildwheel.yml diff --git a/.github/workflows/build-wheels-with-cibuildwheel.yml b/.github/workflows/build-wheels-with-cibuildwheel.yml deleted file mode 100644 index 42129b02..00000000 --- a/.github/workflows/build-wheels-with-cibuildwheel.yml +++ /dev/null @@ -1,43 +0,0 @@ -name: wheels-android - -on: - workflow_dispatch: - -env: - UV_PYTHON: "3.12" # cibuildwheel runner python; not the target - -jobs: - build_android_wheels: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - - - name: Setup uv - uses: astral-sh/setup-uv@v6 - - - name: Set up JDK - uses: actions/setup-java@v4 - with: - distribution: temurin - java-version: "17" - - - name: Set up Android SDK - uses: android-actions/setup-android@v3 - - - name: Build Android wheels - env: - CIBW_PLATFORM: android - CIBW_BUILD: "cp313-android_*" - CIBW_ARCHS_ANDROID: "arm64_v8a x86_64" - ANDROID_API_LEVEL: "24" - run: | - wget https://files.pythonhosted.org/packages/04/24/4b2031d72e840ce4c1ccb255f693b15c334757fc50023e4db9537080b8c4/websockets-16.0.tar.gz - tar xf websockets-16.0.tar.gz - cd websockets-16.0 - uvx cibuildwheel --output-dir wheelhouse - - - uses: actions/upload-artifact@v4 - with: - name: wheels-android - path: websockets-16.0/wheelhouse/*.whl \ No newline at end of file From 8e34ffc63e7c3767b85663c99b5e181e6200d826 Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Wed, 3 Jun 2026 14:46:10 -0700 Subject: [PATCH 139/142] Auto-download Python support packages in setup.sh setup.sh now fetches the mobile-forge support packages from the flet-dev/python-build releases when MOBILE_FORGE_*_SUPPORT_PATH is not already set, caching tarballs under downloads/. Platform selection defaults by OS (macOS: iOS+Android, Linux: Android) and accepts an optional argument. CI is simplified to delegate the download to setup.sh. --- .github/workflows/build-wheels.yml | 20 ++----- README.rst | 83 +++++++++++++----------------- setup.sh | 82 +++++++++++++++++++++++++++++ 3 files changed, 122 insertions(+), 63 deletions(-) diff --git a/.github/workflows/build-wheels.yml b/.github/workflows/build-wheels.yml index 4887cae4..e248e9c2 100644 --- a/.github/workflows/build-wheels.yml +++ b/.github/workflows/build-wheels.yml @@ -117,32 +117,18 @@ jobs: run: | set -euxo pipefail - PYTHON_SHORT_VERSION="${UV_PYTHON%.*}" - . .ci/common.sh - export MOBILE_FORGE_ANDROID_SUPPORT_PATH="" - export MOBILE_FORGE_IOS_SUPPORT_PATH="" if [[ "$PLATFORM" == "android" ]]; then sudo apt-get update sudo apt-get install -y sqlite3 - python_android_dir="$HOME/projects/python-build/android" - curl -#OL "https://github.com/flet-dev/python-build/releases/download/v${PYTHON_SHORT_VERSION}/python-android-mobile-forge-${PYTHON_SHORT_VERSION}.tar.gz" - mkdir -p "$python_android_dir" - tar -xzf "python-android-mobile-forge-${PYTHON_SHORT_VERSION}.tar.gz" -C "$python_android_dir" - export MOBILE_FORGE_ANDROID_SUPPORT_PATH="$python_android_dir" - . .ci/install_ndk.sh - else - python_ios_dir="$HOME/projects/python-build/darwin/Python-Apple-support" - curl -#OL "https://github.com/flet-dev/python-build/releases/download/v${PYTHON_SHORT_VERSION}/python-ios-mobile-forge-${PYTHON_SHORT_VERSION}.tar.gz" - mkdir -p "$python_ios_dir" - tar -xzf "python-ios-mobile-forge-${PYTHON_SHORT_VERSION}.tar.gz" -C "$python_ios_dir" - export MOBILE_FORGE_IOS_SUPPORT_PATH="$python_ios_dir" fi - source ./setup.sh "$UV_PYTHON" + # setup.sh downloads the matching mobile-forge support package for the + # requested platform and sets MOBILE_FORGE_*_SUPPORT_PATH. + source ./setup.sh "$UV_PYTHON" "$PLATFORM" IFS=' ' read -r -a packages <<< "$FORGE_PACKAGES" for package in "${packages[@]}"; do diff --git a/README.rst b/README.rst index 42a400ac..d8b09e05 100644 --- a/README.rst +++ b/README.rst @@ -9,69 +9,60 @@ definitely encouraged. Usage ----- -Before using Mobile Forge, you'll need to compile Python for your build platform (e.g., -your laptop), and for host platform (e.g., for iOS). It may be helpful to use a project -like `Python-Apple-support `__ to -manage this compilation process. +Mobile Forge builds wheels against pre-compiled Python "support" packages for the host +platforms (iOS and Android). You no longer need to compile or download those packages +yourself — ``setup.sh`` fetches them for you. -Using Python-Apple-support -~~~~~~~~~~~~~~~~~~~~~~~~~~ +Getting started +~~~~~~~~~~~~~~~ -If you *do* use Python-Apple-support, this repo contains an activation script that will -configure your environment so it's ready to use. +1. Install `uv `__ (used to create the build virtual + environment):: -1. Set an environment variable declaring the location of your Python-Apple-support - checkout:: + $ curl -LsSf https://astral.sh/uv/install.sh | sh - $ export PYTHON_APPLE_SUPPORT=/path/to/Python-Apple-support - -2. Clone this repository, and run the activate script for the Python version you want to +2. Clone this repository and source the setup script for the Python version you want to use:: - $ git clone https://github.com/beeware/mobile-forge.git + $ git clone https://github.com/flet-dev/mobile-forge.git $ cd mobile-forge - $ source ./setup-iOS.sh 3.11 - -This will create a Python virtual environment, install mobile forge, and provide -some hints at forge commands you can run. - -If a virtual environment already exists, it will be activated, and the same hints -displayed. - -The hard way -~~~~~~~~~~~~ - -If you're *not* using Python-Apple-support, the setup process requires more manual steps:: + $ source ./setup.sh 3.13 -1. Create and activate a virtual environment using the Python build platform, using the - build platform Python compiled in step 1. + On first run this downloads the matching mobile-forge support package(s) into + ``downloads/`` (gitignored), creates a Python virtual environment, installs mobile + forge, builds the platform dependency wheels, and prints some hints at ``forge`` + commands you can run. Subsequent runs reuse the cached download and the existing + virtual environment. -2. Clone this repository, and install it into your freshly created virtual environment:: + By default, on macOS both iOS and Android packages are downloaded; on Linux only + Android. To restrict this, pass the platform(s) as a second argument:: - (venv3.11) $ git clone https://github.com/beeware/mobile-forge.git - (venv3.11) $ cd mobile-forge - (venv3.11) $ pip install -e . + $ source ./setup.sh 3.13 iOS + $ source ./setup.sh 3.13 android + $ source ./setup.sh 3.13 iOS,android -3. Ensure your ``PATH`` contains any tools that were necessary to compile the host CPython, - and does *not* contain any macOS development libraries. Mobile-forge will clean the ``PATH`` - to remove known problematic paths (e.g., paths added by Homebrew, rbenv, npm, etc). +Bring your own support package +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -4. Set environment variables that define the location of the Python executable for each - of the **host** platforms you intend to target. For iOS, this means defining - 3 environment variables:: +If you maintain your own support packages (for example, a local +`Python-Apple-support `__ build), set +``MOBILE_FORGE_IOS_SUPPORT_PATH`` and/or ``MOBILE_FORGE_ANDROID_SUPPORT_PATH`` to the +extracted trees before sourcing ``setup.sh``. When set, these paths are authoritative — +``setup.sh`` validates them and skips the automatic download. Per-version overrides +(``MOBILE_FORGE_IOS_SUPPORT_PATH_3_13`` etc.) are also honored, so several Python +versions can be configured side-by-side. - (venv3.11) $ export MOBILE_FORGE_IPHONEOS_ARM64=... - (venv3.11) $ export MOBILE_FORGE_IPHONESIMULATOR_ARM64=... - (venv3.11) $ export MOBILE_FORGE_IPHONESIMULATOR_X86_64=... +Building a package +~~~~~~~~~~~~~~~~~ -5. Build a package. The ``packages`` folder contains recipes for packages. ``lru-dict`` - is a good first package to try:: +The ``recipes`` folder contains recipes for packages. ``lru-dict`` is a good first +package to try:: - (venv3.11) $ forge iOS lru-dict + $ forge iOS lru-dict - Or, to build a wheel for a single architecture:: +Or, to build a wheel for a single architecture:: - (venv3.11) $ forge iphonesimulator:12.0:arm64 lru-dict + $ forge iphonesimulator:arm64 lru-dict Once this command completes, there should be a wheel for each platform in the ``dist`` folder. A log for each successful build will be in the ``logs`` folder; a log for each diff --git a/setup.sh b/setup.sh index 4da2c8ba..31d61a50 100755 --- a/setup.sh +++ b/setup.sh @@ -37,6 +37,56 @@ python_version_minor="${PYTHON_VER#*.}" echo "Python version: $PYTHON_VERSION" echo "Python short version: $PYTHON_VER" +# Download (and cache) a mobile-forge Python support package from the +# flet-dev/python-build releases, extracting it into $2. The tarball is cached +# under downloads/ (gitignored) and reused on subsequent runs. +download_support() { + local plat="$1" dest="$2" + local tarball="python-${plat}-mobile-forge-${PYTHON_VER}.tar.gz" + local url="https://github.com/flet-dev/python-build/releases/download/v${PYTHON_VER}/${tarball}" + + if [ -d "$dest/support" ]; then + return 0 + fi + + mkdir -p downloads + if [ ! -f "downloads/${tarball}" ]; then + echo "Downloading ${tarball}..." + if ! curl -fL -o "downloads/${tarball}" "$url"; then + echo "Failed to download ${url}" + rm -f "downloads/${tarball}" + return 1 + fi + fi + + echo "Extracting ${tarball} into ${dest}..." + mkdir -p "$dest" + tar -xzf "downloads/${tarball}" -C "$dest" +} + +# Echo the directory that actually contains the support/ tree: $1 itself, or a +# single wrapper subdirectory if the tarball ships one. +resolve_support_root() { + local d="$1" + if [ -d "$d/support" ]; then + echo "$d" + return + fi + local sub + for sub in "$d"/*/; do + if [ -d "${sub}support" ]; then + echo "${sub%/}" + return + fi + done + echo "$d" +} + +# Default-initialize so the script is safe under `set -u` even when the caller +# (e.g. CI) hasn't exported these. Real values are filled in below. +export MOBILE_FORGE_IOS_SUPPORT_PATH="${MOBILE_FORGE_IOS_SUPPORT_PATH:-}" +export MOBILE_FORGE_ANDROID_SUPPORT_PATH="${MOBILE_FORGE_ANDROID_SUPPORT_PATH:-}" + # Per-version support-path overrides: MOBILE_FORGE_{IOS,ANDROID}_SUPPORT_PATH__ # (e.g. MOBILE_FORGE_IOS_SUPPORT_PATH_3_13). When set, they take precedence over # the unversioned variable for this session, so .envrc can declare paths for @@ -55,6 +105,35 @@ if [ -n "$android_versioned_val" ]; then export MOBILE_FORGE_ANDROID_SUPPORT_PATH="$android_versioned_val" fi +# Platforms with an explicit (possibly versioned) path are user-managed and +# authoritative — validate them as-is, never auto-download. +explicit="" +[ -n "$MOBILE_FORGE_IOS_SUPPORT_PATH" ] && explicit="$explicit iOS" +[ -n "$MOBILE_FORGE_ANDROID_SUPPORT_PATH" ] && explicit="$explicit android" + +if [ -z "$explicit" ]; then + # Auto-download selection: 2nd arg, then $MOBILE_FORGE_PLATFORMS, then OS default. + platforms="${2:-${MOBILE_FORGE_PLATFORMS:-}}" + if [ -z "$platforms" ]; then + [ "$(uname)" = "Darwin" ] && platforms="iOS android" || platforms="android" + fi + for p in $(echo "$platforms" | tr ',' ' '); do + case "$(echo "$p" | tr '[:upper:]' '[:lower:]')" in + ios) + dest="$(pwd)/downloads/support/python-ios-mobile-forge-${PYTHON_VER}" + download_support ios "$dest" || return + export MOBILE_FORGE_IOS_SUPPORT_PATH="$(resolve_support_root "$dest")" + ;; + android) + dest="$(pwd)/downloads/support/python-android-mobile-forge-${PYTHON_VER}" + download_support android "$dest" || return + export MOBILE_FORGE_ANDROID_SUPPORT_PATH="$(resolve_support_root "$dest")" + ;; + *) echo "Unknown platform: $p (expected iOS or android)" ;; + esac + done +fi + if [[ -z "$MOBILE_FORGE_IOS_SUPPORT_PATH" && -z "$MOBILE_FORGE_ANDROID_SUPPORT_PATH" ]]; then echo "Neither MOBILE_FORGE_IOS_SUPPORT_PATH nor MOBILE_FORGE_ANDROID_SUPPORT_PATH are defined." echo "Set MOBILE_FORGE_{IOS,ANDROID}_SUPPORT_PATH or per-version overrides" @@ -163,3 +242,6 @@ echo echo "Build all applicable versions of lru-dict for all iOS targets:" echo " forge iOS --all-versions lru-dict" echo + +# The script is sourced; don't leave helper functions in the user's shell. +unset -f download_support resolve_support_root From c98d9ec19b13ae20f3bcb835f6a9b47190420682 Mon Sep 17 00:00:00 2001 From: ndonkoHenri Date: Thu, 4 Jun 2026 02:15:30 +0200 Subject: [PATCH 140/142] Map iOS to darwin artifact name in download_support python-build's CI uploads iOS and macOS tarballs under a single "python-darwin-" artifact. The bundled tarball filename (python-ios-mobile-forge-.tar.gz) is unchanged, just the wrapping artifact name. Without this, PYTHON_BUILD_RUN_ID overrides fail on iOS with "Failed to download artifact python-ios-3.12" while android works. --- setup.sh | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/setup.sh b/setup.sh index 7b1106a7..9a9201e2 100755 --- a/setup.sh +++ b/setup.sh @@ -58,14 +58,20 @@ download_support() { mkdir -p downloads if [ ! -f "downloads/${tarball}" ]; then if [ -n "${PYTHON_BUILD_RUN_ID:-}" ]; then - echo "Fetching ${tarball} from python-build run ${PYTHON_BUILD_RUN_ID}..." + # python-build's CI uploads iOS tarballs under the "darwin" artifact + # (it bundles iOS + macOS together). The android lane has a 1:1 artifact name. + local artifact_plat="$plat" + [ "$plat" = "ios" ] && artifact_plat="darwin" + local artifact_name="python-${artifact_plat}-${PYTHON_VER}" + + echo "Fetching ${tarball} from python-build run ${PYTHON_BUILD_RUN_ID} (artifact: ${artifact_name})..." local stage stage="$(mktemp -d)" if ! gh run download "$PYTHON_BUILD_RUN_ID" \ --repo flet-dev/python-build \ - --name "python-${plat}-${PYTHON_VER}" \ + --name "$artifact_name" \ --dir "$stage"; then - echo "Failed to download artifact python-${plat}-${PYTHON_VER} from run ${PYTHON_BUILD_RUN_ID}" + echo "Failed to download artifact ${artifact_name} from run ${PYTHON_BUILD_RUN_ID}" rm -rf "$stage" return 1 fi From c8926d2959a4542e9b8e403ebb2c515e83447bfc Mon Sep 17 00:00:00 2001 From: ndonkoHenri Date: Thu, 4 Jun 2026 02:30:45 +0200 Subject: [PATCH 141/142] Bump all recipe build numbers to 10 for python-build vNext MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The new flet-dev/python-build release (3.12.13 / 3.13.13 / 3.14.5) changes the cross-compile sysroot — even unchanged recipes produce slightly different wheels (libpython, sysconfigdata). Bump to a uniform floor of 10 (current max was 6) so pip resolves to the new generation across the board. --- .ci/read_meta.py | 2 +- recipes/aiohttp/meta.yaml | 2 +- recipes/argon2-cffi-bindings/meta.yaml | 2 +- recipes/bcrypt/meta.yaml | 2 +- recipes/biopython/meta.yaml | 2 +- recipes/bitarray/meta.yaml | 2 +- recipes/blis/meta.yaml | 2 +- recipes/brotli/meta.yaml | 2 +- recipes/cffi/meta.yaml | 2 +- recipes/contourpy/meta.yaml | 2 +- recipes/coolprop/meta.yaml | 2 +- recipes/cryptography/meta.yaml | 2 +- recipes/fiona/meta.yaml | 2 +- recipes/flet-libcpp-shared/meta.yaml | 2 +- recipes/flet-libcrc32c/meta.yaml | 2 +- recipes/flet-libcurl/meta.yaml | 2 +- recipes/flet-libfreetype/meta.yaml | 2 +- recipes/flet-libgdal/meta.yaml | 2 +- recipes/flet-libgeos/meta.yaml | 2 +- recipes/flet-libjpeg/meta.yaml | 2 +- recipes/flet-libjq/meta.yaml | 2 +- recipes/flet-libopaque/meta.yaml | 2 +- recipes/flet-liboprf/meta.yaml | 2 +- recipes/flet-libpng/meta.yaml | 2 +- recipes/flet-libproj/meta.yaml | 2 +- recipes/flet-libpsl/meta.yaml | 2 +- recipes/flet-libpyjni/meta.yaml | 2 +- recipes/flet-libsodium/meta.yaml | 2 +- recipes/flet-libtiff/meta.yaml | 2 +- recipes/flet-libxml2/meta.yaml | 2 +- recipes/flet-libxslt/meta.yaml | 2 +- recipes/flet-libyaml/meta.yaml | 2 +- recipes/gdal/meta.yaml | 2 +- recipes/google-crc32c/meta.yaml | 2 +- recipes/greenlet/meta.yaml | 2 +- recipes/grpcio/meta.yaml | 2 +- recipes/jiter/meta.yaml | 2 +- recipes/jq/meta.yaml | 2 +- recipes/kiwisolver/meta.yaml | 2 +- recipes/lru-dict/meta.yaml | 2 +- recipes/lxml/meta.yaml | 2 +- recipes/markupsafe/meta.yaml | 2 +- recipes/matplotlib/meta.yaml | 2 +- recipes/msgpack/meta.yaml | 2 +- recipes/msgspec/meta.yaml | 2 +- recipes/numpy/meta.yaml | 2 +- recipes/opaque/meta.yaml | 2 +- recipes/opencv-python/meta.yaml | 2 +- recipes/orjson/meta.yaml | 2 +- recipes/pandas/meta.yaml | 2 +- recipes/pendulum/meta.yaml | 2 +- recipes/pillow/meta.yaml | 2 +- recipes/primp/meta.yaml | 2 +- recipes/protobuf/meta.yaml | 2 +- recipes/pycryptodome/meta.yaml | 2 +- recipes/pycryptodomex/meta.yaml | 2 +- recipes/pydantic-core/meta.yaml | 2 +- recipes/pyjnius/meta.yaml | 2 +- recipes/pymongo/meta.yaml | 2 +- recipes/pynacl/meta.yaml | 2 +- recipes/pyobjus/meta.yaml | 2 +- recipes/pyogrio/meta.yaml | 2 +- recipes/pyproj/meta.yaml | 2 +- recipes/pysodium/meta.yaml | 2 +- recipes/pyxirr/meta.yaml | 2 +- recipes/pyyaml/meta.yaml | 2 +- recipes/rasterio/meta.yaml | 2 +- recipes/regex/meta.yaml | 2 +- recipes/rpds-py/meta.yaml | 2 +- recipes/ruamel.yaml.clib/meta.yaml | 2 +- recipes/selectolax/meta.yaml | 2 +- recipes/shapely/meta.yaml | 2 +- recipes/sqlalchemy/meta.yaml | 2 +- recipes/tiktoken/meta.yaml | 2 +- recipes/time-machine/meta.yaml | 2 +- recipes/tokenizers/meta.yaml | 2 +- recipes/ujson/meta.yaml | 2 +- recipes/websockets/meta.yaml | 2 +- recipes/yarl/meta.yaml | 2 +- recipes/zope.interface/meta.yaml | 2 +- recipes/zstandard/meta.yaml | 2 +- 81 files changed, 81 insertions(+), 81 deletions(-) diff --git a/.ci/read_meta.py b/.ci/read_meta.py index 452458fe..03834253 100644 --- a/.ci/read_meta.py +++ b/.ci/read_meta.py @@ -51,7 +51,7 @@ def main(path: str) -> int: sdk_version=24, arch="arm64-v8a", version=None, - py_version=(3, 12, 12), + py_version=sys.version_info, ) meta = yaml.safe_load(rendered) or {} pkg = meta.get("package") or {} diff --git a/recipes/aiohttp/meta.yaml b/recipes/aiohttp/meta.yaml index 71224793..2167604a 100644 --- a/recipes/aiohttp/meta.yaml +++ b/recipes/aiohttp/meta.yaml @@ -3,4 +3,4 @@ package: version: 3.9.5 build: - number: 4 + number: 10 diff --git a/recipes/argon2-cffi-bindings/meta.yaml b/recipes/argon2-cffi-bindings/meta.yaml index 9620c2a6..926adcce 100644 --- a/recipes/argon2-cffi-bindings/meta.yaml +++ b/recipes/argon2-cffi-bindings/meta.yaml @@ -3,4 +3,4 @@ package: version: 21.2.0 build: - number: 4 + number: 10 diff --git a/recipes/bcrypt/meta.yaml b/recipes/bcrypt/meta.yaml index 82201ecf..f5fc5792 100644 --- a/recipes/bcrypt/meta.yaml +++ b/recipes/bcrypt/meta.yaml @@ -3,6 +3,6 @@ package: version: 4.2.0 build: - number: 4 + number: 10 script_env: _PYTHON_SYSCONFIGDATA_NAME: '{sysconfigdata_name}' \ No newline at end of file diff --git a/recipes/biopython/meta.yaml b/recipes/biopython/meta.yaml index 1d64f33d..f5c94ce5 100644 --- a/recipes/biopython/meta.yaml +++ b/recipes/biopython/meta.yaml @@ -3,4 +3,4 @@ package: version: "1.87" build: - number: 0 + number: 10 diff --git a/recipes/bitarray/meta.yaml b/recipes/bitarray/meta.yaml index fd3f930d..70981fd9 100644 --- a/recipes/bitarray/meta.yaml +++ b/recipes/bitarray/meta.yaml @@ -3,4 +3,4 @@ package: version: 3.6.1 build: - number: 4 + number: 10 diff --git a/recipes/blis/meta.yaml b/recipes/blis/meta.yaml index effaa8d8..33474910 100644 --- a/recipes/blis/meta.yaml +++ b/recipes/blis/meta.yaml @@ -3,7 +3,7 @@ package: version: 1.0.0 build: - number: 4 + number: 10 requirements: host: diff --git a/recipes/brotli/meta.yaml b/recipes/brotli/meta.yaml index 37863a41..04ed998f 100644 --- a/recipes/brotli/meta.yaml +++ b/recipes/brotli/meta.yaml @@ -3,4 +3,4 @@ package: version: 1.1.0 build: - number: 4 + number: 10 diff --git a/recipes/cffi/meta.yaml b/recipes/cffi/meta.yaml index 506cc3e6..981f5e49 100644 --- a/recipes/cffi/meta.yaml +++ b/recipes/cffi/meta.yaml @@ -3,7 +3,7 @@ package: version: 1.17.1 build: - number: 4 + number: 10 requirements: host: diff --git a/recipes/contourpy/meta.yaml b/recipes/contourpy/meta.yaml index 0f2e97bc..01aedb20 100644 --- a/recipes/contourpy/meta.yaml +++ b/recipes/contourpy/meta.yaml @@ -14,7 +14,7 @@ requirements: # {% endif %} build: - number: 5 + number: 10 backend-args: - -Csetup-args=--cross-file - -Csetup-args={MESON_CROSS_FILE} diff --git a/recipes/coolprop/meta.yaml b/recipes/coolprop/meta.yaml index 7f9c1918..42187ef0 100644 --- a/recipes/coolprop/meta.yaml +++ b/recipes/coolprop/meta.yaml @@ -14,7 +14,7 @@ patches: - mkdir-cython-output.patch build: - number: 1 + number: 10 script_env: # {% if sdk == 'android' %} CMAKE_ARGS: >- diff --git a/recipes/cryptography/meta.yaml b/recipes/cryptography/meta.yaml index 95639320..7b7aaf0f 100644 --- a/recipes/cryptography/meta.yaml +++ b/recipes/cryptography/meta.yaml @@ -13,7 +13,7 @@ requirements: - openssl ^3.0.12 build: - number: 4 + number: 10 script_env: OPENSSL_DIR: '{platlib}/opt' _PYTHON_SYSCONFIGDATA_NAME: '{sysconfigdata_name}' \ No newline at end of file diff --git a/recipes/fiona/meta.yaml b/recipes/fiona/meta.yaml index 603d9e44..0e8f9c4b 100644 --- a/recipes/fiona/meta.yaml +++ b/recipes/fiona/meta.yaml @@ -12,7 +12,7 @@ requirements: # {% endif %} build: - number: 5 + number: 10 script_env: GDAL_VERSION: 3.10.0 GDAL_LIB_PATH: '{platlib}/opt/lib' diff --git a/recipes/flet-libcpp-shared/meta.yaml b/recipes/flet-libcpp-shared/meta.yaml index f1dfb896..a85e418f 100644 --- a/recipes/flet-libcpp-shared/meta.yaml +++ b/recipes/flet-libcpp-shared/meta.yaml @@ -7,7 +7,7 @@ package: platforms: [android] build: - number: 4 + number: 10 source: url: https://github.com/flet-dev/awesome-flet/archive/refs/heads/main.zip \ No newline at end of file diff --git a/recipes/flet-libcrc32c/meta.yaml b/recipes/flet-libcrc32c/meta.yaml index 40114603..906b892b 100644 --- a/recipes/flet-libcrc32c/meta.yaml +++ b/recipes/flet-libcrc32c/meta.yaml @@ -3,7 +3,7 @@ package: version: 1.1.2 build: - number: 4 + number: 10 source: url: https://github.com/google/crc32c/archive/refs/tags/1.1.2.tar.gz diff --git a/recipes/flet-libcurl/meta.yaml b/recipes/flet-libcurl/meta.yaml index c4e3d547..2a331953 100644 --- a/recipes/flet-libcurl/meta.yaml +++ b/recipes/flet-libcurl/meta.yaml @@ -8,7 +8,7 @@ source: url: https://curl.se/download/curl-{{ version }}.tar.gz build: - number: 4 + number: 10 requirements: host: diff --git a/recipes/flet-libfreetype/meta.yaml b/recipes/flet-libfreetype/meta.yaml index 511ec378..6c25ec8a 100644 --- a/recipes/flet-libfreetype/meta.yaml +++ b/recipes/flet-libfreetype/meta.yaml @@ -3,7 +3,7 @@ package: version: 2.13.3 build: - number: 2 + number: 10 source: url: https://download.savannah.gnu.org/releases/freetype/freetype-2.13.3.tar.gz diff --git a/recipes/flet-libgdal/meta.yaml b/recipes/flet-libgdal/meta.yaml index dec9cc4c..ba29642c 100644 --- a/recipes/flet-libgdal/meta.yaml +++ b/recipes/flet-libgdal/meta.yaml @@ -8,7 +8,7 @@ source: url: https://github.com/OSGeo/gdal/releases/download/v{{ version }}/gdal-{{ version }}.tar.gz build: - number: 4 + number: 10 requirements: build: diff --git a/recipes/flet-libgeos/meta.yaml b/recipes/flet-libgeos/meta.yaml index 5e9f89b7..08e5c6e6 100644 --- a/recipes/flet-libgeos/meta.yaml +++ b/recipes/flet-libgeos/meta.yaml @@ -3,7 +3,7 @@ package: version: 3.13.0 build: - number: 4 + number: 10 source: url: http://download.osgeo.org/geos/geos-3.13.0.tar.bz2 diff --git a/recipes/flet-libjpeg/meta.yaml b/recipes/flet-libjpeg/meta.yaml index 38a6fbd7..3f36b603 100644 --- a/recipes/flet-libjpeg/meta.yaml +++ b/recipes/flet-libjpeg/meta.yaml @@ -6,7 +6,7 @@ source: url: https://github.com/libjpeg-turbo/libjpeg-turbo/releases/download/3.0.90/libjpeg-turbo-3.0.90.tar.gz build: - number: 4 + number: 10 requirements: build: diff --git a/recipes/flet-libjq/meta.yaml b/recipes/flet-libjq/meta.yaml index 400c32b4..e3d26a36 100644 --- a/recipes/flet-libjq/meta.yaml +++ b/recipes/flet-libjq/meta.yaml @@ -8,7 +8,7 @@ source: url: https://github.com/jqlang/jq/releases/download/jq-{{ version }}/jq-{{ version }}.tar.gz build: - number: 4 + number: 10 requirements: build: diff --git a/recipes/flet-libopaque/meta.yaml b/recipes/flet-libopaque/meta.yaml index b5804dff..63009c71 100644 --- a/recipes/flet-libopaque/meta.yaml +++ b/recipes/flet-libopaque/meta.yaml @@ -5,7 +5,7 @@ package: version: '{{ version }}' build: - number: 4 + number: 10 source: url: https://github.com/stef/libopaque/archive/refs/tags/v{{ version }}.tar.gz diff --git a/recipes/flet-liboprf/meta.yaml b/recipes/flet-liboprf/meta.yaml index 76c0486d..54c9034c 100644 --- a/recipes/flet-liboprf/meta.yaml +++ b/recipes/flet-liboprf/meta.yaml @@ -12,7 +12,7 @@ requirements: - flet-libsodium 1.0.20 build: - number: 4 + number: 10 script_env: CFLAGS: '-Qunused-arguments -Wno-unreachable-code' diff --git a/recipes/flet-libpng/meta.yaml b/recipes/flet-libpng/meta.yaml index 9614942a..43f54bfe 100644 --- a/recipes/flet-libpng/meta.yaml +++ b/recipes/flet-libpng/meta.yaml @@ -3,7 +3,7 @@ package: version: 1.6.43 build: - number: 4 + number: 10 source: url: https://github.com/pnggroup/libpng/archive/refs/tags/v1.6.43.tar.gz diff --git a/recipes/flet-libproj/meta.yaml b/recipes/flet-libproj/meta.yaml index 7b040427..c3a0936b 100644 --- a/recipes/flet-libproj/meta.yaml +++ b/recipes/flet-libproj/meta.yaml @@ -8,7 +8,7 @@ source: url: https://download.osgeo.org/proj/proj-{{ version }}.tar.gz build: - number: 4 + number: 10 # {% if sdk != 'android' %} script_env: LDFLAGS: '-undefined dynamic_lookup' diff --git a/recipes/flet-libpsl/meta.yaml b/recipes/flet-libpsl/meta.yaml index 92047cea..37c2f732 100644 --- a/recipes/flet-libpsl/meta.yaml +++ b/recipes/flet-libpsl/meta.yaml @@ -8,7 +8,7 @@ source: url: https://github.com/rockdaboot/libpsl/releases/download/{{ version }}/libpsl-{{ version }}.tar.gz build: - number: 4 + number: 10 patches: - config.patch \ No newline at end of file diff --git a/recipes/flet-libpyjni/meta.yaml b/recipes/flet-libpyjni/meta.yaml index c6813628..354e8333 100644 --- a/recipes/flet-libpyjni/meta.yaml +++ b/recipes/flet-libpyjni/meta.yaml @@ -6,7 +6,7 @@ package: platforms: [android] build: - number: 4 + number: 10 source: url: https://github.com/flet-dev/libpyjni/releases/download/v1.0.1/pyjni-1.0.1.tar.gz diff --git a/recipes/flet-libsodium/meta.yaml b/recipes/flet-libsodium/meta.yaml index 568622d1..b59b9f45 100644 --- a/recipes/flet-libsodium/meta.yaml +++ b/recipes/flet-libsodium/meta.yaml @@ -5,7 +5,7 @@ package: version: '{{ version }}' build: - number: 4 + number: 10 source: url: https://github.com/jedisct1/libsodium/releases/download/{{ version }}-RELEASE/libsodium-{{ version }}.tar.gz \ No newline at end of file diff --git a/recipes/flet-libtiff/meta.yaml b/recipes/flet-libtiff/meta.yaml index ea05b71b..510b1175 100644 --- a/recipes/flet-libtiff/meta.yaml +++ b/recipes/flet-libtiff/meta.yaml @@ -8,7 +8,7 @@ source: url: https://download.osgeo.org/libtiff/tiff-{{ version }}.tar.gz build: - number: 4 + number: 10 requirements: host: diff --git a/recipes/flet-libxml2/meta.yaml b/recipes/flet-libxml2/meta.yaml index 607b99ae..782425f2 100755 --- a/recipes/flet-libxml2/meta.yaml +++ b/recipes/flet-libxml2/meta.yaml @@ -10,7 +10,7 @@ package: version: '{{ version }}' build: - number: 1 + number: 10 source: url: https://download.gnome.org/sources/libxml2/{{ version.rsplit('.', 1)[0] }}/libxml2-{{ version }}.tar.xz diff --git a/recipes/flet-libxslt/meta.yaml b/recipes/flet-libxslt/meta.yaml index 6704b837..eb1a9bad 100755 --- a/recipes/flet-libxslt/meta.yaml +++ b/recipes/flet-libxslt/meta.yaml @@ -12,7 +12,7 @@ package: version: '{{ version }}' build: - number: 1 + number: 10 source: url: https://download.gnome.org/sources/libxslt/{{ version.rsplit('.', 1)[0] }}/libxslt-{{ version }}.tar.xz diff --git a/recipes/flet-libyaml/meta.yaml b/recipes/flet-libyaml/meta.yaml index 80a5da46..8f7d8911 100644 --- a/recipes/flet-libyaml/meta.yaml +++ b/recipes/flet-libyaml/meta.yaml @@ -3,7 +3,7 @@ package: version: 0.2.5 build: - number: 1 + number: 10 source: url: https://github.com/yaml/libyaml/releases/download/0.2.5/yaml-0.2.5.tar.gz diff --git a/recipes/gdal/meta.yaml b/recipes/gdal/meta.yaml index 7849683b..57a5e03c 100644 --- a/recipes/gdal/meta.yaml +++ b/recipes/gdal/meta.yaml @@ -16,7 +16,7 @@ requirements: # {% endif %} build: - number: 5 + number: 10 script_env: GDAL_VERSION: 3.10.0 GDAL_PREFIX: '{platlib}/opt' diff --git a/recipes/google-crc32c/meta.yaml b/recipes/google-crc32c/meta.yaml index 349b81a1..9ae9814c 100644 --- a/recipes/google-crc32c/meta.yaml +++ b/recipes/google-crc32c/meta.yaml @@ -7,7 +7,7 @@ requirements: - flet-libcrc32c 1.1.2 build: - number: 4 + number: 10 # {% if sdk != 'android' %} script_env: LDFLAGS: '-lc++' diff --git a/recipes/greenlet/meta.yaml b/recipes/greenlet/meta.yaml index 33f5d863..ff40fc22 100644 --- a/recipes/greenlet/meta.yaml +++ b/recipes/greenlet/meta.yaml @@ -10,7 +10,7 @@ requirements: # {% endif %} build: - number: 5 + number: 10 # {% if sdk != 'android' %} script_env: CXXFLAGS: -std=c++14 diff --git a/recipes/grpcio/meta.yaml b/recipes/grpcio/meta.yaml index 1ce96d93..916410e8 100644 --- a/recipes/grpcio/meta.yaml +++ b/recipes/grpcio/meta.yaml @@ -3,7 +3,7 @@ package: version: 1.67.1 build: - number: 6 + number: 10 script_env: # {% if sdk == 'android' %} GRPC_PYTHON_BUILD_SYSTEM_OPENSSL: '1' diff --git a/recipes/jiter/meta.yaml b/recipes/jiter/meta.yaml index e88513f4..70d0640e 100644 --- a/recipes/jiter/meta.yaml +++ b/recipes/jiter/meta.yaml @@ -3,6 +3,6 @@ package: version: 0.8.2 build: - number: 4 + number: 10 script_env: _PYTHON_SYSCONFIGDATA_NAME: '{sysconfigdata_name}' \ No newline at end of file diff --git a/recipes/jq/meta.yaml b/recipes/jq/meta.yaml index 7b78f433..13b0fcf4 100644 --- a/recipes/jq/meta.yaml +++ b/recipes/jq/meta.yaml @@ -7,6 +7,6 @@ requirements: - flet-libjq 1.7.1 build: - number: 4 + number: 10 script_env: JQPY_USE_SYSTEM_LIBS: 1 \ No newline at end of file diff --git a/recipes/kiwisolver/meta.yaml b/recipes/kiwisolver/meta.yaml index 811876fe..3be1f0e8 100644 --- a/recipes/kiwisolver/meta.yaml +++ b/recipes/kiwisolver/meta.yaml @@ -3,7 +3,7 @@ package: version: 1.4.7 build: - number: 4 + number: 10 # {% if sdk == 'android' %} requirements: diff --git a/recipes/lru-dict/meta.yaml b/recipes/lru-dict/meta.yaml index 680fcda9..5e5e250b 100644 --- a/recipes/lru-dict/meta.yaml +++ b/recipes/lru-dict/meta.yaml @@ -3,4 +3,4 @@ package: version: 1.3.0 build: - number: 4 + number: 10 diff --git a/recipes/lxml/meta.yaml b/recipes/lxml/meta.yaml index fa41ef2c..b6e3a141 100644 --- a/recipes/lxml/meta.yaml +++ b/recipes/lxml/meta.yaml @@ -12,7 +12,7 @@ package: version: '{{ version }}' build: - number: 1 + number: 10 script_env: WITH_XML2_CONFIG: '{platlib}/opt/bin/xml2-config' WITH_XSLT_CONFIG: '{platlib}/opt/bin/xslt-config' diff --git a/recipes/markupsafe/meta.yaml b/recipes/markupsafe/meta.yaml index 700d466d..d30edb96 100644 --- a/recipes/markupsafe/meta.yaml +++ b/recipes/markupsafe/meta.yaml @@ -3,4 +3,4 @@ package: version: 2.1.5 build: - number: 4 + number: 10 diff --git a/recipes/matplotlib/meta.yaml b/recipes/matplotlib/meta.yaml index 0be8d42c..7e8247c3 100644 --- a/recipes/matplotlib/meta.yaml +++ b/recipes/matplotlib/meta.yaml @@ -15,7 +15,7 @@ requirements: # {% endif %} build: - number: 5 + number: 10 # {% if sdk == 'android' and arch in ['armeabi-v7a', 'x86'] %} script_env: CPPFLAGS: -Wno-c++11-narrowing diff --git a/recipes/msgpack/meta.yaml b/recipes/msgpack/meta.yaml index 293c7c43..cc816be0 100644 --- a/recipes/msgpack/meta.yaml +++ b/recipes/msgpack/meta.yaml @@ -3,4 +3,4 @@ package: version: 1.1.0 build: - number: 4 + number: 10 diff --git a/recipes/msgspec/meta.yaml b/recipes/msgspec/meta.yaml index b9842c22..e9abe94b 100644 --- a/recipes/msgspec/meta.yaml +++ b/recipes/msgspec/meta.yaml @@ -3,7 +3,7 @@ package: version: 0.18.6 build: - number: 4 + number: 10 requirements: build: diff --git a/recipes/numpy/meta.yaml b/recipes/numpy/meta.yaml index ff8aa45c..0766afea 100644 --- a/recipes/numpy/meta.yaml +++ b/recipes/numpy/meta.yaml @@ -21,7 +21,7 @@ patches: {% endif %} build: - number: 5 + number: 10 script_env: NPY_DISABLE_SVML: 1 diff --git a/recipes/opaque/meta.yaml b/recipes/opaque/meta.yaml index 56295e54..e4645d24 100644 --- a/recipes/opaque/meta.yaml +++ b/recipes/opaque/meta.yaml @@ -3,7 +3,7 @@ package: version: 0.2.0 build: - number: 5 + number: 10 requirements: host: diff --git a/recipes/opencv-python/meta.yaml b/recipes/opencv-python/meta.yaml index a3830d0c..a64d1880 100644 --- a/recipes/opencv-python/meta.yaml +++ b/recipes/opencv-python/meta.yaml @@ -10,7 +10,7 @@ patches: - mobile.patch build: - number: 4 + number: 10 script_env: # {% if sdk == 'android' %} CMAKE_ARGS: >- diff --git a/recipes/orjson/meta.yaml b/recipes/orjson/meta.yaml index 1a7edd2a..18fc8f44 100644 --- a/recipes/orjson/meta.yaml +++ b/recipes/orjson/meta.yaml @@ -3,6 +3,6 @@ package: version: 3.11.9 build: - number: 1 + number: 10 script_env: _PYTHON_SYSCONFIGDATA_NAME: '{sysconfigdata_name}' diff --git a/recipes/pandas/meta.yaml b/recipes/pandas/meta.yaml index 45da06e7..e71a0618 100644 --- a/recipes/pandas/meta.yaml +++ b/recipes/pandas/meta.yaml @@ -19,7 +19,7 @@ patches: - mobile.patch build: - number: 5 + number: 10 backend-args: - -Csetup-args=--cross-file - -Csetup-args={MESON_CROSS_FILE} diff --git a/recipes/pendulum/meta.yaml b/recipes/pendulum/meta.yaml index 7aed052d..b0ca84c3 100644 --- a/recipes/pendulum/meta.yaml +++ b/recipes/pendulum/meta.yaml @@ -3,7 +3,7 @@ package: version: 3.0.0 build: - number: 4 + number: 10 script_env: _PYTHON_SYSCONFIGDATA_NAME: '{sysconfigdata_name}' # {% if sdk == 'iphonesimulator' %} diff --git a/recipes/pillow/meta.yaml b/recipes/pillow/meta.yaml index ace75766..231c0ff0 100644 --- a/recipes/pillow/meta.yaml +++ b/recipes/pillow/meta.yaml @@ -23,7 +23,7 @@ patches: # {% endif %} build: - number: 5 + number: 10 script_env: # {% if sdk == 'android' %} # pillow's setup.py manually probes `self.compiler.{include,library}_dirs` diff --git a/recipes/primp/meta.yaml b/recipes/primp/meta.yaml index 8c2275a0..9ac5a9d3 100644 --- a/recipes/primp/meta.yaml +++ b/recipes/primp/meta.yaml @@ -3,4 +3,4 @@ package: version: 1.3.1 build: - number: 1 + number: 10 diff --git a/recipes/protobuf/meta.yaml b/recipes/protobuf/meta.yaml index 38777832..b7c3cb59 100644 --- a/recipes/protobuf/meta.yaml +++ b/recipes/protobuf/meta.yaml @@ -3,4 +3,4 @@ package: version: 5.28.3 build: - number: 4 + number: 10 diff --git a/recipes/pycryptodome/meta.yaml b/recipes/pycryptodome/meta.yaml index 88d1fdb6..987bb298 100644 --- a/recipes/pycryptodome/meta.yaml +++ b/recipes/pycryptodome/meta.yaml @@ -3,7 +3,7 @@ package: version: 3.21.0 build: - number: 5 + number: 10 # pycryptodome's internal Crypto/Util/_raw_api.py tries a cffi-based # fast path first, and only falls back to ctypes.pythonapi.PyObject_GetBuffer diff --git a/recipes/pycryptodomex/meta.yaml b/recipes/pycryptodomex/meta.yaml index 70da98cb..60ba14f5 100644 --- a/recipes/pycryptodomex/meta.yaml +++ b/recipes/pycryptodomex/meta.yaml @@ -3,7 +3,7 @@ package: version: 3.21.0 build: - number: 5 + number: 10 # Same fix rationale as recipes/pycryptodome/meta.yaml — pycryptodomex is # the sister package (same code under `Cryptodome.*` namespace). Without diff --git a/recipes/pydantic-core/meta.yaml b/recipes/pydantic-core/meta.yaml index 46ea247d..55eea88e 100644 --- a/recipes/pydantic-core/meta.yaml +++ b/recipes/pydantic-core/meta.yaml @@ -3,6 +3,6 @@ package: version: 2.47.0 build: - number: 4 + number: 10 script_env: _PYTHON_SYSCONFIGDATA_NAME: '{sysconfigdata_name}' \ No newline at end of file diff --git a/recipes/pyjnius/meta.yaml b/recipes/pyjnius/meta.yaml index 263974de..98adc31e 100644 --- a/recipes/pyjnius/meta.yaml +++ b/recipes/pyjnius/meta.yaml @@ -4,7 +4,7 @@ package: platforms: [android] build: - number: 4 + number: 10 patches: - mobile.patch diff --git a/recipes/pymongo/meta.yaml b/recipes/pymongo/meta.yaml index 79a9cbb7..478305d0 100644 --- a/recipes/pymongo/meta.yaml +++ b/recipes/pymongo/meta.yaml @@ -3,4 +3,4 @@ package: version: 4.10.1 build: - number: 4 + number: 10 diff --git a/recipes/pynacl/meta.yaml b/recipes/pynacl/meta.yaml index 46fd8671..bbec2254 100644 --- a/recipes/pynacl/meta.yaml +++ b/recipes/pynacl/meta.yaml @@ -3,7 +3,7 @@ package: version: 1.5.0 build: - number: 4 + number: 10 requirements: host: diff --git a/recipes/pyobjus/meta.yaml b/recipes/pyobjus/meta.yaml index 96d4507c..5d1ad234 100644 --- a/recipes/pyobjus/meta.yaml +++ b/recipes/pyobjus/meta.yaml @@ -4,7 +4,7 @@ package: platforms: [ios] build: - number: 2 + number: 10 patches: - mobile.patch diff --git a/recipes/pyogrio/meta.yaml b/recipes/pyogrio/meta.yaml index 80ba2bda..c0ea41a3 100644 --- a/recipes/pyogrio/meta.yaml +++ b/recipes/pyogrio/meta.yaml @@ -12,7 +12,7 @@ requirements: # {% endif %} build: - number: 5 + number: 10 script_env: GDAL_VERSION: 3.10.0 GDAL_LIBRARY_PATH: '{platlib}/opt/lib' diff --git a/recipes/pyproj/meta.yaml b/recipes/pyproj/meta.yaml index 1b8b4bdd..2513822f 100644 --- a/recipes/pyproj/meta.yaml +++ b/recipes/pyproj/meta.yaml @@ -3,7 +3,7 @@ package: version: 3.7.0 build: - number: 5 + number: 10 script_env: PROJ_VERSION: 9.5.0 PROJ_DIR: '{platlib}/opt' diff --git a/recipes/pysodium/meta.yaml b/recipes/pysodium/meta.yaml index 2bc8811e..531482f8 100644 --- a/recipes/pysodium/meta.yaml +++ b/recipes/pysodium/meta.yaml @@ -3,7 +3,7 @@ package: version: 0.7.18 build: - number: 4 + number: 10 requirements: host: diff --git a/recipes/pyxirr/meta.yaml b/recipes/pyxirr/meta.yaml index f76acfb1..f38fea16 100644 --- a/recipes/pyxirr/meta.yaml +++ b/recipes/pyxirr/meta.yaml @@ -3,4 +3,4 @@ package: version: 0.10.8 build: - number: 1 + number: 10 diff --git a/recipes/pyyaml/meta.yaml b/recipes/pyyaml/meta.yaml index c3be4692..fd0b36b9 100644 --- a/recipes/pyyaml/meta.yaml +++ b/recipes/pyyaml/meta.yaml @@ -3,7 +3,7 @@ package: version: 6.0.2 build: - number: 5 + number: 10 requirements: host: diff --git a/recipes/rasterio/meta.yaml b/recipes/rasterio/meta.yaml index 31927e67..3e2b82b3 100644 --- a/recipes/rasterio/meta.yaml +++ b/recipes/rasterio/meta.yaml @@ -17,7 +17,7 @@ requirements: # {% endif %} build: - number: 3 + number: 10 script_env: GDAL_VERSION: 3.10.0 GDAL_LIB_PATH: '{platlib}/opt/lib' diff --git a/recipes/regex/meta.yaml b/recipes/regex/meta.yaml index 3d6ac1b0..0ff8c759 100644 --- a/recipes/regex/meta.yaml +++ b/recipes/regex/meta.yaml @@ -3,4 +3,4 @@ package: version: 2024.11.6 build: - number: 4 + number: 10 diff --git a/recipes/rpds-py/meta.yaml b/recipes/rpds-py/meta.yaml index 12297f6b..110231ed 100644 --- a/recipes/rpds-py/meta.yaml +++ b/recipes/rpds-py/meta.yaml @@ -3,6 +3,6 @@ package: version: 0.23.1 build: - number: 4 + number: 10 script_env: _PYTHON_SYSCONFIGDATA_NAME: '{sysconfigdata_name}' \ No newline at end of file diff --git a/recipes/ruamel.yaml.clib/meta.yaml b/recipes/ruamel.yaml.clib/meta.yaml index 0a2e8158..86314a71 100644 --- a/recipes/ruamel.yaml.clib/meta.yaml +++ b/recipes/ruamel.yaml.clib/meta.yaml @@ -3,4 +3,4 @@ package: version: 0.2.12 build: - number: 1 + number: 10 diff --git a/recipes/selectolax/meta.yaml b/recipes/selectolax/meta.yaml index 7d482f29..67b1d0b0 100644 --- a/recipes/selectolax/meta.yaml +++ b/recipes/selectolax/meta.yaml @@ -3,4 +3,4 @@ package: version: 0.4.10 build: - number: 0 + number: 10 diff --git a/recipes/shapely/meta.yaml b/recipes/shapely/meta.yaml index b50c9594..2ea41ad8 100644 --- a/recipes/shapely/meta.yaml +++ b/recipes/shapely/meta.yaml @@ -3,7 +3,7 @@ package: version: 2.0.6 build: - number: 4 + number: 10 requirements: host: diff --git a/recipes/sqlalchemy/meta.yaml b/recipes/sqlalchemy/meta.yaml index 6fe0f3e2..d1cef09f 100644 --- a/recipes/sqlalchemy/meta.yaml +++ b/recipes/sqlalchemy/meta.yaml @@ -3,4 +3,4 @@ package: version: 2.0.36 build: - number: 4 + number: 10 diff --git a/recipes/tiktoken/meta.yaml b/recipes/tiktoken/meta.yaml index 3300bb0f..0b8f2b5d 100644 --- a/recipes/tiktoken/meta.yaml +++ b/recipes/tiktoken/meta.yaml @@ -3,6 +3,6 @@ package: version: 0.9.0 build: - number: 4 + number: 10 script_env: _PYTHON_SYSCONFIGDATA_NAME: '{sysconfigdata_name}' \ No newline at end of file diff --git a/recipes/time-machine/meta.yaml b/recipes/time-machine/meta.yaml index caec2e55..b2acd8d0 100644 --- a/recipes/time-machine/meta.yaml +++ b/recipes/time-machine/meta.yaml @@ -3,4 +3,4 @@ package: version: 2.16.0 build: - number: 4 + number: 10 diff --git a/recipes/tokenizers/meta.yaml b/recipes/tokenizers/meta.yaml index 15a7f9c6..74050fba 100644 --- a/recipes/tokenizers/meta.yaml +++ b/recipes/tokenizers/meta.yaml @@ -13,6 +13,6 @@ requirements: # {% endif %} build: - number: 5 + number: 10 script_env: _PYTHON_SYSCONFIGDATA_NAME: '{sysconfigdata_name}' \ No newline at end of file diff --git a/recipes/ujson/meta.yaml b/recipes/ujson/meta.yaml index 96af0659..cfbb1113 100644 --- a/recipes/ujson/meta.yaml +++ b/recipes/ujson/meta.yaml @@ -3,7 +3,7 @@ package: version: 5.12.1 build: - number: 1 + number: 10 # {% if sdk == 'android' %} # ujson links its bundled double-conversion C++ code against NDK's libc++. diff --git a/recipes/websockets/meta.yaml b/recipes/websockets/meta.yaml index fdc85c2a..95c87d1b 100644 --- a/recipes/websockets/meta.yaml +++ b/recipes/websockets/meta.yaml @@ -3,4 +3,4 @@ package: version: 13.0.1 build: - number: 4 + number: 10 diff --git a/recipes/yarl/meta.yaml b/recipes/yarl/meta.yaml index f4f15591..13a53eaf 100644 --- a/recipes/yarl/meta.yaml +++ b/recipes/yarl/meta.yaml @@ -3,7 +3,7 @@ package: version: 1.11.1 build: - number: 4 + number: 10 requirements: build: diff --git a/recipes/zope.interface/meta.yaml b/recipes/zope.interface/meta.yaml index 5bb53148..f8fabad5 100644 --- a/recipes/zope.interface/meta.yaml +++ b/recipes/zope.interface/meta.yaml @@ -3,4 +3,4 @@ package: version: '7.2' build: - number: 4 + number: 10 diff --git a/recipes/zstandard/meta.yaml b/recipes/zstandard/meta.yaml index d194e1f4..917c4711 100644 --- a/recipes/zstandard/meta.yaml +++ b/recipes/zstandard/meta.yaml @@ -3,4 +3,4 @@ package: version: 0.23.0 build: - number: 4 + number: 10 From 10258dadaf7ec0e9a5385ed8727a6f31fdc89e1c Mon Sep 17 00:00:00 2001 From: ndonkoHenri Date: Thu, 4 Jun 2026 02:50:25 +0200 Subject: [PATCH 142/142] Add concurrency group to build-wheels workflow Dedupes the push + pull_request pair that fires when a branch with an open PR gets a new commit, and cancels in-flight runs when a newer event for the same branch arrives. --- .github/workflows/build-wheels.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/build-wheels.yml b/.github/workflows/build-wheels.yml index c4d01bb6..9f086be1 100644 --- a/.github/workflows/build-wheels.yml +++ b/.github/workflows/build-wheels.yml @@ -20,6 +20,11 @@ on: required: false default: "" +# Cancel in-flight runs when a newer event arrives for the same logical branch. +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.ref_name }} + cancel-in-progress: true + env: UV_PYTHON: "3.12.13" MOBILE_FORGE_CACHE_DOWNLOADS_OFF: "1"