diff --git a/.github/workflows/build-wheels.yml b/.github/workflows/build-wheels.yml index 9f086be1..7865d8b4 100644 --- a/.github/workflows/build-wheels.yml +++ b/.github/workflows/build-wheels.yml @@ -13,6 +13,13 @@ on: description: "Packages (comma-separated, e.g. pillow:11.1.0,pydantic-core:2.33.2) — or 'ALL' to build/test every recipe" required: false default: "pydantic-core:2.33.2" + prebuild_recipes: + description: | + Comma-separated list of recipes (typically flet-lib*) to + build FIRST and seed into the matrix's dist/ for host-dep pip resolution + (e.g. flet-libgdal -> gdal). + required: false + default: "" python_build_run_id: description: | flet-dev/python-build Actions run-id whose artifacts to use as the @@ -178,9 +185,11 @@ jobs: env: FORGE_ARCH: ${{ matrix.forge_arch }} FORGE_PACKAGES: ${{ matrix.forge_packages }} + PREBUILD_RECIPES: ${{ inputs.prebuild_recipes }} PLATFORM: ${{ matrix.platform }} PYTHON_BUILD_RUN_ID: ${{ inputs.python_build_run_id }} - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} # used by `gh run download` + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + PIP_FIND_LINKS: ${{ github.workspace }}/dist run: | set -euxo pipefail @@ -198,6 +207,16 @@ jobs: # the canonical v release. source ./setup.sh "$UV_PYTHON" "$PLATFORM" + # When prebuild_recipes is set, this step builds those recipes FIRST. Their wheels + # land in dist/ alongside the consumer wheels. PIP_FIND_LINKS points forge's + # host-dep pip resolution at dist/, so the consumer build below picks up the + # freshly-built libs over whatever pypi.flet.dev has published. + if [[ -n "${PREBUILD_RECIPES:-}" ]]; then + for lib in $(echo "$PREBUILD_RECIPES" | tr ',' ' '); do + forge "$FORGE_ARCH" "$lib" + done + fi + IFS=' ' read -r -a packages <<< "$FORGE_PACKAGES" for package in "${packages[@]}"; do forge "$FORGE_ARCH" "$package" diff --git a/recipes/aiohttp/meta.yaml b/recipes/aiohttp/meta.yaml index 2167604a..7fe95737 100644 --- a/recipes/aiohttp/meta.yaml +++ b/recipes/aiohttp/meta.yaml @@ -1,6 +1,6 @@ package: name: aiohttp - version: 3.9.5 + version: 3.14.0 build: - number: 10 + number: 1 diff --git a/recipes/argon2-cffi-bindings/meta.yaml b/recipes/argon2-cffi-bindings/meta.yaml index 926adcce..f81e0bb2 100644 --- a/recipes/argon2-cffi-bindings/meta.yaml +++ b/recipes/argon2-cffi-bindings/meta.yaml @@ -1,6 +1,6 @@ package: name: argon2-cffi-bindings - version: 21.2.0 + version: 25.1.0 build: - number: 10 + number: 1 diff --git a/recipes/bcrypt/meta.yaml b/recipes/bcrypt/meta.yaml index f5fc5792..6237ae32 100644 --- a/recipes/bcrypt/meta.yaml +++ b/recipes/bcrypt/meta.yaml @@ -1,8 +1,8 @@ package: name: bcrypt - version: 4.2.0 + version: 5.0.0 build: - number: 10 + number: 1 script_env: _PYTHON_SYSCONFIGDATA_NAME: '{sysconfigdata_name}' \ No newline at end of file diff --git a/recipes/bitarray/meta.yaml b/recipes/bitarray/meta.yaml index 70981fd9..3b788b59 100644 --- a/recipes/bitarray/meta.yaml +++ b/recipes/bitarray/meta.yaml @@ -1,6 +1,6 @@ package: name: bitarray - version: 3.6.1 + version: 3.8.1 build: - number: 10 + number: 1 diff --git a/recipes/blis/meta.yaml b/recipes/blis/meta.yaml index 33474910..7df0db4b 100644 --- a/recipes/blis/meta.yaml +++ b/recipes/blis/meta.yaml @@ -1,9 +1,9 @@ package: name: blis - version: 1.0.0 + version: 1.3.3 build: - number: 10 + number: 1 requirements: host: diff --git a/recipes/blis/patches/mobile.patch b/recipes/blis/patches/mobile.patch index 479017ad..ddd34412 100644 --- a/recipes/blis/patches/mobile.patch +++ b/recipes/blis/patches/mobile.patch @@ -1,53 +1,45 @@ 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; - } - --#elif defined(__APPLE__) || defined(_MSC_VER) // !defined(BLIS_DISABLE_SYSTEM) -+#elif defined(__APPLE__) || defined(_MSC_VER) || defined(__ANDROID__) // !defined(BLIS_DISABLE_SYSTEM) - - #include - +@@ -319,7 +319,7 @@ + + // -- pthread_barrier_*() -- + +-#if defined(__APPLE__) || defined(_MSC_VER) ++#if defined(__APPLE__) || defined(_MSC_VER) || defined(__ANDROID__) + + // For OS X and Windows, we define barriers ourselves in terms of the rest + // of the API, though for slightly different reasons: For Windows, we must diff --git a/blis/_src/include/linux-generic/blis.h b/blis/_src/include/linux-generic/blis.h -index d5158ff..bf3fbe5 100644 --- a/blis/_src/include/linux-generic/blis.h +++ b/blis/_src/include/linux-generic/blis.h -@@ -1581,7 +1581,7 @@ typedef pthread_cond_t bli_pthread_cond_t; - typedef pthread_condattr_t bli_pthread_condattr_t; - typedef pthread_once_t bli_pthread_once_t; - +@@ -1537,7 +1537,7 @@ typedef pthread_cond_t bli_pthread_cond_t; + typedef pthread_condattr_t bli_pthread_condattr_t; + typedef pthread_once_t bli_pthread_once_t; + -#if defined(__APPLE__) +#if defined(__APPLE__) || defined(__ANDROID__) - + // 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 d0944c9..6b3c19e 100644 --- a/setup.py +++ b/setup.py -@@ -21,6 +21,7 @@ import subprocess +@@ -21,8 +21,13 @@ import sys import platform import numpy +import sysconfig - - - PLATFORM_TO_ARCH = { -@@ -36,6 +37,10 @@ PLATFORM_TO_ARCH = { - + MOD_NAMES = ["blis.cy", "blis.py"] - ++ +# Redirect the compiler to CC +os.environ["BLIS_ARCH"] = "generic" +os.environ["BLIS_COMPILER"] = os.environ["CC"] -+ + print("BLIS_COMPILER?", os.environ.get("BLIS_COMPILER", "None")) - - -@@ -220,6 +225,9 @@ class ExtensionBuilder(build_ext, build_ext_options): + +@@ -199,6 +204,9 @@ objects = [] platform_arch = platform + "-" + py_arch compiler = self.get_compiler_name() @@ -57,12 +49,12 @@ index d0944c9..6b3c19e 100644 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): +@@ -228,6 +236,8 @@ 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 - + # spec["flags"].append( + # "-D__cpuid=__cpuid_function" + # ) diff --git a/recipes/brotli/meta.yaml b/recipes/brotli/meta.yaml index 04ed998f..743f1462 100644 --- a/recipes/brotli/meta.yaml +++ b/recipes/brotli/meta.yaml @@ -1,6 +1,6 @@ package: name: Brotli - version: 1.1.0 + version: 1.2.0 build: - number: 10 + number: 1 diff --git a/recipes/cffi/meta.yaml b/recipes/cffi/meta.yaml index 981f5e49..b5665bbb 100644 --- a/recipes/cffi/meta.yaml +++ b/recipes/cffi/meta.yaml @@ -1,9 +1,9 @@ package: name: cffi - version: 1.17.1 + version: 2.0.0 build: - number: 10 + number: 1 requirements: host: diff --git a/recipes/contourpy/meta.yaml b/recipes/contourpy/meta.yaml index 01aedb20..89ff05b9 100644 --- a/recipes/contourpy/meta.yaml +++ b/recipes/contourpy/meta.yaml @@ -1,6 +1,6 @@ package: name: contourpy - version: 1.3.1 + version: 1.3.3 requirements: build: @@ -14,7 +14,7 @@ requirements: # {% endif %} build: - number: 10 + number: 1 backend-args: - -Csetup-args=--cross-file - -Csetup-args={MESON_CROSS_FILE} diff --git a/recipes/fiona/meta.yaml b/recipes/fiona/meta.yaml index 0e8f9c4b..474fa1d3 100644 --- a/recipes/fiona/meta.yaml +++ b/recipes/fiona/meta.yaml @@ -4,7 +4,7 @@ package: requirements: host: - - flet-libgdal 3.10.0 + - flet-libgdal 3.13.1 # {% if sdk != 'android' %} # iOS-only — see GDAL_LIBS comment below for the rationale. - openssl >=3.0.15 @@ -12,9 +12,15 @@ requirements: # {% endif %} build: - number: 10 + # Same source version as pypi.flet.dev's fiona-1.10.1-10 wheel, but + # this rebuild links against flet-libgdal 3.13.1 (vs. the published + # wheel's 3.10.0). pip's wheel selection picks the higher build_tag + # per PEP 427 when name+version collide; the new wheel must outrank + # build 10 or downstream installs would silently keep the old + # libgdal-3.10-linked fiona and the gdal chain bump would be invisible. + number: 11 script_env: - GDAL_VERSION: 3.10.0 + GDAL_VERSION: 3.13.1 GDAL_LIB_PATH: '{platlib}/opt/lib' GDAL_INCLUDE_PATH: '{platlib}/opt/include' # {% if sdk == 'android' %} diff --git a/recipes/flet-libgdal/build.sh b/recipes/flet-libgdal/build.sh index b9008c81..ccf87b29 100755 --- a/recipes/flet-libgdal/build.sh +++ b/recipes/flet-libgdal/build.sh @@ -26,6 +26,7 @@ if [ $CROSS_VENV_SDK == "android" ]; then -DGDAL_USE_OPENSSL=OFF \ -DGDAL_USE_CURL=OFF \ -DGDAL_USE_LIBXML2=OFF \ + -DGDAL_USE_OPENMP=OFF \ -DBUILD_APPS=OFF \ -DBUILD_TESTING=OFF \ -DBUILD_PYTHON_BINDINGS=OFF @@ -48,8 +49,10 @@ else -DSQLite3_INCLUDE_DIR=$SDK_ROOT/usr/include \ -DGDAL_BUILD_OPTIONAL_DRIVERS=OFF \ -DOGR_BUILD_OPTIONAL_DRIVERS=OFF \ + -DGDAL_USE_OPENMP=OFF \ -DBUILD_APPS=OFF \ - -DBUILD_TESTING=OFF + -DBUILD_TESTING=OFF \ + -DBUILD_PYTHON_BINDINGS=OFF fi cmake --build . -j $CPU_COUNT diff --git a/recipes/flet-libgdal/meta.yaml b/recipes/flet-libgdal/meta.yaml index ba29642c..cabe470e 100644 --- a/recipes/flet-libgdal/meta.yaml +++ b/recipes/flet-libgdal/meta.yaml @@ -1,4 +1,4 @@ -{% set version = "3.10.0" %} +{% set version = "3.13.1" %} package: name: flet-libgdal @@ -8,10 +8,13 @@ source: url: https://github.com/OSGeo/gdal/releases/download/v{{ version }}/gdal-{{ version }}.tar.gz build: - number: 10 + number: 1 requirements: build: - cmake host: - - flet-libproj 9.5.0 \ No newline at end of file + - flet-libproj 9.5.0 + +patches: + - mobile.patch diff --git a/recipes/flet-libgdal/patches/mobile.patch b/recipes/flet-libgdal/patches/mobile.patch new file mode 100644 index 00000000..8460b7be --- /dev/null +++ b/recipes/flet-libgdal/patches/mobile.patch @@ -0,0 +1,24 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -221,6 +221,12 @@ endif() + endif() + set(ENV{MKL_ENABLE_INSTRUCTIONS} "SSE4_2") + ++# Mobile cross-compile guard: GDAL 3.13 unconditionally probes for the ++# target Python interpreter even when -DBUILD_PYTHON_BINDINGS=OFF. Under ++# CMake 4.x that trips policy CMP0190 ("Interpreter and/or Compiler ++# components cannot be searched when CMAKE_CROSSCOMPILING_EMULATOR ++# variable is not specified"). Skip the block when bindings are off. ++if (BUILD_PYTHON_BINDINGS OR NOT DEFINED BUILD_PYTHON_BINDINGS) + if (Python_LOOKUP_VERSION) + set(Python_FIND_STRATEGY VERSION) + find_package(Python ${Python_LOOKUP_VERSION} EXACT COMPONENTS Interpreter Development NumPy) +@@ -248,6 +254,7 @@ if (Python_Interpreter_FOUND) + endif () + endif() + endif() ++endif() + + # Restore previous value of MKL_ENABLE_INSTRUCTIONS + if(DEFINED BACKUP_ENV_VAR_MKL_ENABLE_INSTRUCTIONS) diff --git a/recipes/flet-libgeos/meta.yaml b/recipes/flet-libgeos/meta.yaml index 08e5c6e6..df3f1247 100644 --- a/recipes/flet-libgeos/meta.yaml +++ b/recipes/flet-libgeos/meta.yaml @@ -1,13 +1,13 @@ package: name: flet-libgeos - version: 3.13.0 + version: 3.13.1 build: - number: 10 + number: 1 source: - url: http://download.osgeo.org/geos/geos-3.13.0.tar.bz2 + url: http://download.osgeo.org/geos/geos-3.13.1.tar.bz2 requirements: build: - - cmake \ No newline at end of file + - cmake diff --git a/recipes/flet-libopaque/meta.yaml b/recipes/flet-libopaque/meta.yaml index 63009c71..19c1492b 100644 --- a/recipes/flet-libopaque/meta.yaml +++ b/recipes/flet-libopaque/meta.yaml @@ -1,11 +1,11 @@ -{% set version = "0.99.8" %} +{% set version = "1.0.1" %} package: name: flet-libopaque version: '{{ version }}' build: - number: 10 + number: 1 source: url: https://github.com/stef/libopaque/archive/refs/tags/v{{ version }}.tar.gz diff --git a/recipes/gdal/meta.yaml b/recipes/gdal/meta.yaml index 57a5e03c..ec7a997e 100644 --- a/recipes/gdal/meta.yaml +++ b/recipes/gdal/meta.yaml @@ -1,10 +1,14 @@ package: name: gdal - version: 3.10.0 + # Pinned to match `flet-libgdal` (the host C library). GDAL's Python + # bindings hard-require an exact major.minor match with libgdal — + # any bump here must come with flet-libgdal bumped to the same + # version, plus fiona / rasterio / pyogrio re-pinned in lockstep. + version: 3.13.1 requirements: host: - - flet-libgdal 3.10.0 + - flet-libgdal 3.13.1 # {% if sdk == 'android' %} # libgdal links C++; the SWIG-generated _gdal.so loads via dlopen which # needs libc++_shared.so on Android. @@ -16,9 +20,9 @@ requirements: # {% endif %} build: - number: 10 + number: 1 script_env: - GDAL_VERSION: 3.10.0 + GDAL_VERSION: 3.13.1 GDAL_PREFIX: '{platlib}/opt' GDAL_CFLAGS: '' # {% if sdk != 'android' %} diff --git a/recipes/gdal/patches/config.patch b/recipes/gdal/patches/config.patch index 59b046e5..bfc91805 100644 --- a/recipes/gdal/patches/config.patch +++ b/recipes/gdal/patches/config.patch @@ -1,16 +1,16 @@ diff --git a/setup.py b/setup.py --- a/setup.py +++ b/setup.py -@@ -54,6 +54,8 @@ - include_dirs = ['/home/even/gdal/3.10/build/port', '/home/even/gdal/3.10/port', '/home/even/gdal/3.10/build/gcore', '/home/even/gdal/3.10/gcore', '/home/even/gdal/3.10/alg', '/home/even/gdal/3.10/ogr/', '/home/even/gdal/3.10/ogr/ogrsf_frmts', '/home/even/gdal/3.10/gnm', '/home/even/gdal/3.10/apps'] - library_dirs = ['/home/even/gdal/3.10/build'] +@@ -55,6 +55,8 @@ + include_dirs = ['/home/runner/work/gdal/gdal/python_pkgs/port', '/home/runner/work/gdal/gdal/port', '/home/runner/work/gdal/gdal/python_pkgs/gcore', '/home/runner/work/gdal/gdal/gcore', '/home/runner/work/gdal/gdal/gcore/multidim', '/home/runner/work/gdal/gdal/alg', '/home/runner/work/gdal/gdal/ogr/', '/home/runner/work/gdal/gdal/ogr/ogrsf_frmts', '/home/runner/work/gdal/gdal/gnm', '/home/runner/work/gdal/gdal/apps'] + library_dirs = ['/home/runner/work/gdal/gdal/python_pkgs'] libraries = ['gdal'] +if 'GDAL_LIBS' in os.environ: + libraries = os.environ['GDAL_LIBS'].split(',') # --------------------------------------------------------------------------- -@@ -228,6 +230,9 @@ +@@ -240,6 +242,9 @@ def get_gdal_config(self, option): try: diff --git a/recipes/google-crc32c/meta.yaml b/recipes/google-crc32c/meta.yaml index 9ae9814c..15b6cd0b 100644 --- a/recipes/google-crc32c/meta.yaml +++ b/recipes/google-crc32c/meta.yaml @@ -1,13 +1,13 @@ package: name: google-crc32c - version: 1.6.0 + version: 1.8.0 requirements: host: - flet-libcrc32c 1.1.2 build: - number: 10 + number: 1 # {% if sdk != 'android' %} script_env: LDFLAGS: '-lc++' diff --git a/recipes/greenlet/meta.yaml b/recipes/greenlet/meta.yaml index ff40fc22..bd3cc63e 100644 --- a/recipes/greenlet/meta.yaml +++ b/recipes/greenlet/meta.yaml @@ -1,6 +1,6 @@ package: name: greenlet - version: 3.1.1 + version: 3.5.1 # {% if sdk == 'android' %} requirements: @@ -10,7 +10,7 @@ requirements: # {% endif %} build: - number: 10 + number: 1 # {% if sdk != 'android' %} script_env: CXXFLAGS: -std=c++14 diff --git a/recipes/grpcio/meta.yaml b/recipes/grpcio/meta.yaml index 916410e8..347307e9 100644 --- a/recipes/grpcio/meta.yaml +++ b/recipes/grpcio/meta.yaml @@ -1,9 +1,9 @@ package: name: grpcio - version: 1.67.1 + version: 1.81.0 build: - number: 10 + number: 1 script_env: # {% if sdk == 'android' %} GRPC_PYTHON_BUILD_SYSTEM_OPENSSL: '1' @@ -13,7 +13,10 @@ build: 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 + # grpcio 1.81's vendored abseil-cpp requires C++17 (policy_checks.h rejects anything < C++17). + # The narrowing warning suppression is carried forward from the prior C++14 setting + # because some legacy grpc files still trip on init-list narrowing. + CXXFLAGS: -std=c++17 -Wno-c++11-narrowing LDFLAGS: '-framework CoreFoundation' # {% endif %} diff --git a/recipes/grpcio/patches/mobile.patch b/recipes/grpcio/patches/mobile.patch index 6a9f5a33..89c6c1ac 100644 --- a/recipes/grpcio/patches/mobile.patch +++ b/recipes/grpcio/patches/mobile.patch @@ -47,18 +47,3 @@ EXTENSION_LIBRARIES = () if "linux" in sys.platform: ---- a/third_party/zlib/zutil.h 2026-05-31 19:02:14 -+++ b/third_party/zlib/zutil.h 2026-05-31 19:02:15 -@@ -143,8 +143,10 @@ - # if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os - # include /* for fdopen */ - # else --# ifndef fdopen --# define fdopen(fd,mode) NULL /* No fdopen() */ -+# if !defined(__APPLE__) -+# ifndef fdopen -+# define fdopen(fd,mode) NULL /* No fdopen() */ -+# endif - # endif - # endif - # endif diff --git a/recipes/jiter/meta.yaml b/recipes/jiter/meta.yaml index 70d0640e..f6eaacd5 100644 --- a/recipes/jiter/meta.yaml +++ b/recipes/jiter/meta.yaml @@ -1,8 +1,8 @@ package: name: jiter - version: 0.8.2 + version: 0.15.0 build: - number: 10 + number: 1 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 13b0fcf4..0e166f8a 100644 --- a/recipes/jq/meta.yaml +++ b/recipes/jq/meta.yaml @@ -1,12 +1,12 @@ package: name: jq - version: 1.8.0 + version: 1.11.0 requirements: host: - flet-libjq 1.7.1 build: - number: 10 + number: 1 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 3be1f0e8..90cc402e 100644 --- a/recipes/kiwisolver/meta.yaml +++ b/recipes/kiwisolver/meta.yaml @@ -1,9 +1,9 @@ package: name: kiwisolver - version: 1.4.7 + version: 1.5.0 build: - number: 10 + number: 1 # {% if sdk == 'android' %} requirements: diff --git a/recipes/lru-dict/meta.yaml b/recipes/lru-dict/meta.yaml index 5e5e250b..d526cd44 100644 --- a/recipes/lru-dict/meta.yaml +++ b/recipes/lru-dict/meta.yaml @@ -1,6 +1,6 @@ package: name: lru-dict - version: 1.3.0 + version: 1.4.1 build: - number: 10 + number: 1 diff --git a/recipes/lxml/meta.yaml b/recipes/lxml/meta.yaml index b6e3a141..fd40fde1 100644 --- a/recipes/lxml/meta.yaml +++ b/recipes/lxml/meta.yaml @@ -1,4 +1,4 @@ -# {% set version = "6.1.0" %} +# {% set version = "6.1.1" %} # {% if version.startswith('5.') %} # {% set libxml2_version = "2.9.8" %} # {% set libxslt_version = "1.1.32" %} @@ -12,7 +12,7 @@ package: version: '{{ version }}' build: - number: 10 + 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 d30edb96..1a53d314 100644 --- a/recipes/markupsafe/meta.yaml +++ b/recipes/markupsafe/meta.yaml @@ -1,6 +1,6 @@ package: name: MarkupSafe - version: 2.1.5 + version: 3.0.3 build: - number: 10 + number: 1 diff --git a/recipes/markupsafe/test_markupsafe.py b/recipes/markupsafe/test_markupsafe.py index ca43e106..2c59aa55 100644 --- a/recipes/markupsafe/test_markupsafe.py +++ b/recipes/markupsafe/test_markupsafe.py @@ -14,8 +14,17 @@ def test_escape(): def test_speedups_loaded(): """Confirms the C extension `markupsafe._speedups` actually loaded; the - pure-Python fallback wouldn't expose `escape` from this module.""" + pure-Python fallback wouldn't expose the C accelerator at all. + + Markupsafe 3.0 renamed the C entry point: `escape` (2.x) became + `_escape_inner` (3.x). The public `markupsafe.escape` dispatches to + it. We probe whichever name the installed version exposes so the + test stays useful across version bumps.""" from markupsafe import _speedups - assert callable(_speedups.escape) - assert str(_speedups.escape("<&>")) == "<&>" + fn = getattr(_speedups, "_escape_inner", None) or getattr(_speedups, "escape", None) + assert callable(fn), ( + f"neither _escape_inner nor escape on markupsafe._speedups; " + f"have: {[n for n in dir(_speedups) if not n.startswith('__')]}" + ) + assert str(fn("<&>")) == "<&>" diff --git a/recipes/matplotlib/meta.yaml b/recipes/matplotlib/meta.yaml index 7e8247c3..a76c2d79 100644 --- a/recipes/matplotlib/meta.yaml +++ b/recipes/matplotlib/meta.yaml @@ -1,6 +1,6 @@ package: name: matplotlib - version: 3.10.0 + version: 3.10.9 requirements: build: @@ -15,7 +15,7 @@ requirements: # {% endif %} build: - number: 10 + number: 1 # {% 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 cc816be0..a2d6a2bb 100644 --- a/recipes/msgpack/meta.yaml +++ b/recipes/msgpack/meta.yaml @@ -1,6 +1,6 @@ package: name: msgpack - version: 1.1.0 + version: 1.1.2 build: - number: 10 + number: 1 diff --git a/recipes/msgspec/meta.yaml b/recipes/msgspec/meta.yaml index e9abe94b..210703de 100644 --- a/recipes/msgspec/meta.yaml +++ b/recipes/msgspec/meta.yaml @@ -1,9 +1,9 @@ package: name: msgspec - version: 0.18.6 + version: 0.21.1 build: - number: 10 + number: 1 requirements: build: diff --git a/recipes/numpy/meta.yaml b/recipes/numpy/meta.yaml index 0766afea..3f91824e 100644 --- a/recipes/numpy/meta.yaml +++ b/recipes/numpy/meta.yaml @@ -3,7 +3,7 @@ package: name: numpy - version: 2.2.2 + version: 2.4.6 requirements: build: @@ -13,15 +13,13 @@ requirements: - flet-libcpp-shared >=27.2.12479018 {% endif %} -patches: {% if version and version < (2, 0) %} +patches: - mobile-1.26.4.patch -{% else %} - - mobile-2.2.2.patch {% endif %} build: - number: 10 + number: 1 script_env: NPY_DISABLE_SVML: 1 @@ -33,7 +31,7 @@ build: meson: properties: -# {% if sdk == 'iOS' or (sdk == 'android' and arch in ['arm64-v8a', 'x86_64']) %} +# {% if sdk == 'android' and arch in ['arm64-v8a', 'x86_64'] %} longdouble_format: IEEE_QUAD_LE # {% else %} longdouble_format: IEEE_DOUBLE_LE diff --git a/recipes/numpy/patches/mobile-2.2.2.patch b/recipes/numpy/patches/mobile-2.2.2.patch deleted file mode 100644 index 77e972a1..00000000 --- a/recipes/numpy/patches/mobile-2.2.2.patch +++ /dev/null @@ -1,13 +0,0 @@ -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/opaque/meta.yaml b/recipes/opaque/meta.yaml index e4645d24..3422b080 100644 --- a/recipes/opaque/meta.yaml +++ b/recipes/opaque/meta.yaml @@ -1,21 +1,19 @@ package: name: opaque - version: 0.2.0 + version: 1.0.0 build: - number: 10 + number: 1 requirements: host: - - flet-libopaque 0.99.8 + - flet-libopaque 1.0.1 -# Patch upstream setup.py to declare `pysodium` as install_requires. -# Upstream's 0.2.0 setup.py only sets `requires=["libsodium"]` (metadata- -# only, NOT a real pip dependency), so when the recipe-tester installs -# `opaque` pip doesn't pull pysodium, and `import opaque` then fails at -# runtime with `ModuleNotFoundError: No module named 'pysodium'`. The -# 1.0.0 upstream tried to fix this but shipped `install_requires = -# ("pysodium")` — string-without-trailing-comma is just a string, not a -# tuple, and setuptools silently drops it. +# opaque 1.0.0 upstream tried to fix the install_requires problem the +# 0.2.0 recipe had to work around, but shipped `install_requires = +# ("pysodium")` — string-without-trailing-comma is just a string, not +# a tuple, which setuptools treats inconsistently. mobile.patch rewrites +# it to a proper list `install_requires=["pysodium"]` so pip pulls +# pysodium reliably. patches: - mobile.patch diff --git a/recipes/opaque/patches/mobile.patch b/recipes/opaque/patches/mobile.patch index 4e9cf75a..d3402ac5 100644 --- a/recipes/opaque/patches/mobile.patch +++ b/recipes/opaque/patches/mobile.patch @@ -1,11 +1,12 @@ diff --git a/setup.py b/setup.py --- a/setup.py +++ b/setup.py -@@ -19,6 +19,7 @@ +@@ -21,7 +21,7 @@ long_description=read('README.md'), long_description_content_type="text/markdown", requires=["libsodium"], +- install_requires = ("pysodium"), + install_requires=["pysodium"], classifiers=["Development Status :: 4 - Beta", - "License :: OSI Approved :: BSD License", + "License :: OSI Approved :: GNU Lesser General Public License v3 or later (LGPLv3+)", "Topic :: Security :: Cryptography", diff --git a/recipes/opencv-python/meta.yaml b/recipes/opencv-python/meta.yaml index a64d1880..8ac09601 100644 --- a/recipes/opencv-python/meta.yaml +++ b/recipes/opencv-python/meta.yaml @@ -1,8 +1,14 @@ package: name: opencv-python - version: 4.10.0.84 + version: 4.12.0.88 requirements: + build: + # opencv-python's setup.py invokes its own dependency check (via scikit-build) which + # hard-requires cmake>=3.5 on PATH. macOS runners pre-install cmake but iOS lane's + # cross-venv strips it from the shimmed PATH, so add the pip-installable shim that + # ships a cmake binary into the build venv. + - cmake host: - numpy ^2.0.0 @@ -10,7 +16,7 @@ patches: - mobile.patch build: - number: 10 + number: 1 script_env: # {% if sdk == 'android' %} CMAKE_ARGS: >- diff --git a/recipes/opencv-python/patches/mobile.patch b/recipes/opencv-python/patches/mobile.patch index c0c389aa..c54ecc3f 100644 --- a/recipes/opencv-python/patches/mobile.patch +++ b/recipes/opencv-python/patches/mobile.patch @@ -1,6 +1,3 @@ -diff --git a/a.diff b/a.diff -new file mode 100644 -index 0000000..e69de29 diff --git a/opencv/CMakeLists.txt b/opencv/CMakeLists.txt index f5e39b4..1bd8629 100644 --- a/opencv/CMakeLists.txt @@ -342,25 +339,23 @@ index e729c86..c5779d3 100644 --- a/opencv/modules/videoio/misc/python/pyopencv_videoio.hpp +++ b/opencv/modules/videoio/misc/python/pyopencv_videoio.hpp @@ -23,7 +23,7 @@ bool pyopencv_to(PyObject *o, std::vector& apis, const Arg - + template<> bool pyopencv_to(PyObject* obj, cv::VideoCapture& stream, const ArgInfo& info) { - Ptr * obj_getp = nullptr; + cv::Ptr * obj_getp = nullptr; if (!pyopencv_VideoCapture_getp(obj, obj_getp)) return (failmsgp("Incorrect type of self (must be 'VideoCapture' or its derivative)") != nullptr); - -diff --git a/pyproject.toml b/pyproject.toml -index 71de7f9..740eabe 100644 ---- a/pyproject.toml -+++ b/pyproject.toml -@@ -9,5 +9,5 @@ requires = [ - "numpy>=2.0.0; python_version>='3.9'", - "pip", - "scikit-build>=0.14.0", -- "setuptools==59.2.0", -+ "setuptools", - ] + +@@ -117,7 +117,7 @@ private: + }; + + template<> +-bool pyopencv_to(PyObject* obj, Ptr& p, const ArgInfo&) ++bool pyopencv_to(PyObject* obj, cv::Ptr& p, const ArgInfo&) + { + if (!obj) + return false; diff --git a/setup.py b/setup.py index 48d5a65..125b9b4 100644 --- a/setup.py diff --git a/recipes/pandas/meta.yaml b/recipes/pandas/meta.yaml index e71a0618..3d8fdeed 100644 --- a/recipes/pandas/meta.yaml +++ b/recipes/pandas/meta.yaml @@ -1,6 +1,6 @@ package: name: pandas - version: 2.2.3 + version: 3.0.3 # {% if not version or version >= (2,1) %} # pandas >= 2.1.0 @@ -19,7 +19,7 @@ patches: - mobile.patch build: - number: 10 + number: 1 backend-args: - -Csetup-args=--cross-file - -Csetup-args={MESON_CROSS_FILE} diff --git a/recipes/pandas/patches/mobile.patch b/recipes/pandas/patches/mobile.patch index 4df6c777..4c772afc 100644 --- a/recipes/pandas/patches/mobile.patch +++ b/recipes/pandas/patches/mobile.patch @@ -1,21 +1,8 @@ ---- a/pyproject.toml 2026-05-31 23:37:15 -+++ b/pyproject.toml 2026-05-31 23:37:15 -@@ -2,8 +2,10 @@ - # 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", -+ # Upstream pinned 0.13.1 + 1.2.1 — bump to a recent meson-python so the -+ # mobile-forge meson-wrapper.py below works (older mesonpy ignored the -+ # tool.meson-python.meson setting). -+ "meson-python>=0.16.0", - "wheel", - "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 -@@ -809,3 +811,15 @@ +--- a/pyproject.toml ++++ b/pyproject.toml +@@ -833,3 +833,15 @@ [tool.codespell] - ignore-words-list = "blocs, coo, hist, nd, sav, ser, recuse, nin, timere, expec, expecs" + ignore-words-list = "blocs, coo, hist, nd, sav, ser, recuse, nin, timere, expec, expecs, indext, SME, NotIn, tructures, tru, indx, abd, ABD" ignore-regex = 'https://([\w/\.])+' + +# Added by mobile-forge mobile.patch — see meson-wrapper.py. diff --git a/recipes/pendulum/meta.yaml b/recipes/pendulum/meta.yaml index b0ca84c3..7002a94c 100644 --- a/recipes/pendulum/meta.yaml +++ b/recipes/pendulum/meta.yaml @@ -1,14 +1,11 @@ package: name: pendulum - version: 3.0.0 + version: 3.2.0 build: - number: 10 + number: 1 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 +# {% endif %} \ No newline at end of file diff --git a/recipes/pendulum/patches/mobile.patch b/recipes/pendulum/patches/mobile.patch deleted file mode 100644 index 8d410b4c..00000000 --- a/recipes/pendulum/patches/mobile.patch +++ /dev/null @@ -1,12 +0,0 @@ -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 - } diff --git a/recipes/pillow/meta.yaml b/recipes/pillow/meta.yaml index 231c0ff0..ba25fa36 100644 --- a/recipes/pillow/meta.yaml +++ b/recipes/pillow/meta.yaml @@ -1,6 +1,6 @@ package: name: Pillow - version: 11.1.0 + version: 12.2.0 requirements: host: @@ -8,11 +8,13 @@ requirements: - flet-libjpeg 3.0.90 - flet-libfreetype 2.13.3 -# {% if not version or version >= (11,0,0) %} -# pillow >= 11.x +# {% if not version or version >= (12,0,0) %} +# pillow >= 12.x (12.x drops `self.add_imaging_libs = ""` from +# initialize_options, so the 11.x patch's hunk-1 context no longer +# matches; the 12.x patch is otherwise identical to the 11.x one.) patches: - - setup-11.x.patch + - setup-12.x.patch # {% else %} # pillow <= 10.x @@ -23,7 +25,7 @@ patches: # {% endif %} build: - number: 10 + number: 1 script_env: # {% if sdk == 'android' %} # pillow's setup.py manually probes `self.compiler.{include,library}_dirs` diff --git a/recipes/pillow/patches/setup-11.x.patch b/recipes/pillow/patches/setup-12.x.patch similarity index 71% rename from recipes/pillow/patches/setup-11.x.patch rename to recipes/pillow/patches/setup-12.x.patch index 318082d6..62279a35 100644 --- a/recipes/pillow/patches/setup-11.x.patch +++ b/recipes/pillow/patches/setup-12.x.patch @@ -1,17 +1,27 @@ diff --git a/setup.py b/setup.py --- a/setup.py +++ b/setup.py -@@ -355,9 +355,7 @@ +@@ -372,11 +372,17 @@ 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: + setattr(self, f"disable_{x}", self.check_configuration(x, "disable")) + setattr(self, f"enable_{x}", self.check_configuration(x, "enable")) ++ # Mobile-forge: force-disable optional features whose libraries ++ # mobile-forge does NOT supply via host deps. Pillow 12 added ++ # brotli to the link line whenever the headers can be reached; ++ # on iOS the cross site-packages happens to expose them, so the ++ # build pulls in `-lbrotlicommon -lbrotlidec` but no matching ++ # static archive exists in the link search path, breaking the ++ # _imaging.so link with `ld: library 'brotlicommon' not found`. ++ self.disable_brotli = True + for x in ("raqm", "fribidi"): @@ -547,8 +545,10 @@ for d in os.environ[k].split(os.path.pathsep): _add_directory(library_dirs, d) @@ -55,5 +65,13 @@ diff --git a/setup.py b/setup.py + self.compiler.library_dirs = [d for d in self.compiler.library_dirs if d not in _host_leaks] + # # look for available libraries - + feature = self.feature +@@ -998,7 +1023,7 @@ + + if sys.platform == "ios": + # Ensure transitive dependencies are linked. +- libs.extend(["z", "bz2", "brotlicommon", "brotlidec", "png"]) ++ libs.extend(["z", "bz2"]) + + self._update_extension("PIL._imagingft", libs, defs, srcs) diff --git a/recipes/protobuf/meta.yaml b/recipes/protobuf/meta.yaml index b7c3cb59..04bcff13 100644 --- a/recipes/protobuf/meta.yaml +++ b/recipes/protobuf/meta.yaml @@ -1,6 +1,6 @@ package: name: protobuf - version: 5.28.3 + version: 7.35.0 build: - number: 10 + number: 1 diff --git a/recipes/pycryptodome/meta.yaml b/recipes/pycryptodome/meta.yaml index 987bb298..e92c0bc5 100644 --- a/recipes/pycryptodome/meta.yaml +++ b/recipes/pycryptodome/meta.yaml @@ -1,9 +1,9 @@ package: name: pycryptodome - version: 3.21.0 + version: 3.23.0 build: - number: 10 + number: 1 # 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/pycryptodome/patches/mobile.patch b/recipes/pycryptodome/patches/mobile.patch index c3b69392..acd0f670 100644 --- a/recipes/pycryptodome/patches/mobile.patch +++ b/recipes/pycryptodome/patches/mobile.patch @@ -32,10 +32,10 @@ index e0065c3..3b14e00 100644 diff --git a/setup.py b/setup.py --- a/setup.py +++ b/setup.py -@@ -521,6 +521,9 @@ +@@ -523,6 +523,9 @@ platforms='Posix; MacOS X; Windows', zip_safe=False, - python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*', + python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, !=3.6.*', + # Mobile: cffi is needed at runtime to avoid the broken + # ctypes.pythonapi.PyObject_GetBuffer path. See recipes/pycryptodome/meta.yaml. + install_requires=['cffi'], diff --git a/recipes/pycryptodomex/meta.yaml b/recipes/pycryptodomex/meta.yaml index 60ba14f5..3beb6887 100644 --- a/recipes/pycryptodomex/meta.yaml +++ b/recipes/pycryptodomex/meta.yaml @@ -1,9 +1,9 @@ package: name: pycryptodomex - version: 3.21.0 + version: 3.23.0 build: - number: 10 + number: 1 # Same fix rationale as recipes/pycryptodome/meta.yaml — pycryptodomex is # the sister package (same code under `Cryptodome.*` namespace). Without diff --git a/recipes/pycryptodomex/patches/mobile.patch b/recipes/pycryptodomex/patches/mobile.patch index 84edf413..0cf315c4 100644 --- a/recipes/pycryptodomex/patches/mobile.patch +++ b/recipes/pycryptodomex/patches/mobile.patch @@ -32,10 +32,10 @@ index e0065c3..3b14e00 100644 diff --git a/setup.py b/setup.py --- a/setup.py +++ b/setup.py -@@ -521,6 +521,9 @@ +@@ -523,6 +523,9 @@ platforms='Posix; MacOS X; Windows', zip_safe=False, - python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*', + python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, !=3.6.*', + # Mobile: cffi is needed at runtime to avoid the broken + # ctypes.pythonapi.PyObject_GetBuffer path. See recipes/pycryptodomex/meta.yaml. + install_requires=['cffi'], diff --git a/recipes/pyjnius/meta.yaml b/recipes/pyjnius/meta.yaml index 98adc31e..298932d6 100644 --- a/recipes/pyjnius/meta.yaml +++ b/recipes/pyjnius/meta.yaml @@ -1,10 +1,10 @@ package: name: pyjnius - version: 1.6.1 + version: 1.7.0 platforms: [android] build: - number: 10 + number: 1 patches: - mobile.patch diff --git a/recipes/pyjnius/patches/mobile.patch b/recipes/pyjnius/patches/mobile.patch index 2c3e83cd..0f601f6a 100644 --- a/recipes/pyjnius/patches/mobile.patch +++ b/recipes/pyjnius/patches/mobile.patch @@ -37,18 +37,20 @@ index a688e2b..7018adf 100644 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() - +@@ -191,13 +191,13 @@ class MetaJavaClass(MetaJavaBase): + if __javainterfaces__ and __javabaseclass__: + - baseclass = j_env[0].FindClass(j_env, __javabaseclass__) + baseclass = PyJni_FindClass(__javabaseclass__) - interfaces = malloc(sizeof(jclass) * len(__javainterfaces__)) - + interfaces = j_env[0].NewObjectArray(j_env, len(__javainterfaces__), classClass, NULL) + # 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) - + # interfaces[n] = j_env[0].FindClass(j_env, i) +- j_env[0].SetObjectArrayElement(j_env, interfaces, n, j_env[0].FindClass(j_env, i)) ++ j_env[0].SetObjectArrayElement(j_env, interfaces, n, PyJni_FindClass(i)) + getProxyClass = j_env[0].GetStaticMethodID( j_env, baseclass, "getProxyClass", @@ -206,8 +206,7 @@ class MetaJavaClass(MetaJavaBase): diff --git a/recipes/pymongo/meta.yaml b/recipes/pymongo/meta.yaml index 478305d0..979cc541 100644 --- a/recipes/pymongo/meta.yaml +++ b/recipes/pymongo/meta.yaml @@ -1,6 +1,6 @@ package: name: pymongo - version: 4.10.1 + version: 4.17.0 build: - number: 10 + number: 1 diff --git a/recipes/pynacl/meta.yaml b/recipes/pynacl/meta.yaml index bbec2254..85c45245 100644 --- a/recipes/pynacl/meta.yaml +++ b/recipes/pynacl/meta.yaml @@ -1,9 +1,9 @@ package: name: PyNaCl - version: 1.5.0 + version: 1.6.2 build: - number: 10 + number: 1 requirements: host: diff --git a/recipes/pynacl/patches/mobile.patch b/recipes/pynacl/patches/mobile.patch index 24d54087..e522a731 100644 --- a/recipes/pynacl/patches/mobile.patch +++ b/recipes/pynacl/patches/mobile.patch @@ -1,16 +1,7 @@ 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( +@@ -197,7 +197,7 @@ setup( package_data={"nacl": ["py.typed"]}, ext_package="nacl", cffi_modules=["src/bindings/build.py:ffi"], @@ -19,5 +10,4 @@ index 96d4b32..045314f 100644 + # cmdclass={"build_ext": build_ext}, + # distclass=Distribution, zip_safe=False, - classifiers=[ - "Programming Language :: Python :: Implementation :: CPython", + ) diff --git a/recipes/pyobjus/meta.yaml b/recipes/pyobjus/meta.yaml index 5d1ad234..d9e79ebb 100644 --- a/recipes/pyobjus/meta.yaml +++ b/recipes/pyobjus/meta.yaml @@ -1,10 +1,10 @@ package: name: pyobjus - version: 1.2.3 + version: 1.2.4 platforms: [ios] build: - number: 10 + number: 1 patches: - mobile.patch diff --git a/recipes/pyobjus/patches/mobile.patch b/recipes/pyobjus/patches/mobile.patch index 3dcbee99..9eaa7a61 100644 --- a/recipes/pyobjus/patches/mobile.patch +++ b/recipes/pyobjus/patches/mobile.patch @@ -1,5 +1,4 @@ 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 @@ @@ -11,10 +10,9 @@ index c31b7ba..6d0cf85 100644 #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": +@@ -110,7 +110,7 @@ objc_method_description* protocol_copyMethodDescriptionList(Protocol *p, BOOL isRequiredMethod, BOOL isInstanceMethod, unsigned int *outCount) @@ -23,101 +21,46 @@ index 3a17bbb..4f43c6a 100644 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 = [] diff --git a/pyobjus/pyobjus_conversions.pxi b/pyobjus/pyobjus_conversions.pxi --- a/pyobjus/pyobjus_conversions.pxi +++ b/pyobjus/pyobjus_conversions.pxi -@@ -428,10 +428,8 @@ +@@ -428,7 +428,7 @@ return arg elif arg in (True, False): return autoclass('NSNumber').alloc().initWithBool_(int(arg)) - elif isinstance(arg, (str, unicode)): + elif isinstance(arg, str): return autoclass('NSString').alloc().initWithUTF8String_(arg) -- elif isinstance(arg, long): -- return autoclass('NSNumber').alloc().initWithInt_(arg) elif isinstance(arg, int): return autoclass('NSNumber').alloc().initWithLong_(arg) - elif isinstance(arg, float): -@@ -525,10 +523,10 @@ - # method is accepting long - elif sig == b'l': - if by_value: -- (val_ptr)[0] = long(arg) -+ (val_ptr)[0] = int(arg) - else: - if not objc_ref: -- (arg_val_ptr)[0] = long(arg) -+ (arg_val_ptr)[0] = int(arg) - (val_ptr)[0] = arg_val_ptr - # method is accepting long long - elif sig == b'q': -@@ -692,7 +690,7 @@ - # ARRAY, ETC. - else: - # TODO: Add better conversion between primitive types! -- if type(arg) is long: -+ if type(arg) is int: - (val_ptr)[0] = arg - elif type(arg) is str: - # passing bytes as void* is the same as for char* +diff --git a/setup.py b/setup.py +--- a/setup.py ++++ b/setup.py +@@ -43,23 +43,10 @@ + include_dirs = [] + + if sys.platform == "ios": +- ios_ver = platform.ios_ver() +- ios_deps_path = join(dirname(__file__), "ios-deps-install") +- +- # Check if the ios-deps-install directory exists +- if not exists(ios_deps_path): +- raise RuntimeError( +- "iOS dependencies not found. Please run the .ci/build_ios_dependencies.sh script to build them." +- ) +- +- ffi_lib_path = join( +- ios_deps_path, +- "iphonesimulator" if ios_ver.is_simulator else "iphoneos", +- arch, +- ) +- library_dirs.append(join(ffi_lib_path, "lib")) +- include_dirs.append(join(ffi_lib_path, "include")) +- include_dirs.append(join(ffi_lib_path, "include", "ffi")) ++ # Mobile-forge supplies libffi via the recipe's libffi host dep ++ # (CFLAGS/CPPFLAGS/LDFLAGS already point at {platlib}/opt). Bypass ++ # the build-time ios-deps-install/ check pyobjus 1.2.4 added; let ++ # forge's env do the libffi wiring. + libraries.append('objc') + + depends = [join('pyobjus', x) for x in ( diff --git a/recipes/pyogrio/meta.yaml b/recipes/pyogrio/meta.yaml index c0ea41a3..016a6d35 100644 --- a/recipes/pyogrio/meta.yaml +++ b/recipes/pyogrio/meta.yaml @@ -1,10 +1,10 @@ package: name: pyogrio - version: 0.10.0 + version: 0.12.1 requirements: host: - - flet-libgdal 3.10.0 + - flet-libgdal 3.13.1 # {% if sdk != 'android' %} # iOS-only — see GDAL_LIBS comment below for the rationale. - openssl >=3.0.15 @@ -12,9 +12,9 @@ requirements: # {% endif %} build: - number: 10 + number: 1 script_env: - GDAL_VERSION: 3.10.0 + GDAL_VERSION: 3.13.1 GDAL_LIBRARY_PATH: '{platlib}/opt/lib' GDAL_INCLUDE_PATH: '{platlib}/opt/include' # {% if sdk != 'android' %} diff --git a/recipes/pyproj/meta.yaml b/recipes/pyproj/meta.yaml index 2513822f..d8692002 100644 --- a/recipes/pyproj/meta.yaml +++ b/recipes/pyproj/meta.yaml @@ -1,9 +1,9 @@ package: name: pyproj - version: 3.7.0 + version: 3.7.2 build: - number: 10 + number: 1 script_env: PROJ_VERSION: 9.5.0 PROJ_DIR: '{platlib}/opt' diff --git a/recipes/pyyaml/meta.yaml b/recipes/pyyaml/meta.yaml index fd0b36b9..39ecc026 100644 --- a/recipes/pyyaml/meta.yaml +++ b/recipes/pyyaml/meta.yaml @@ -1,9 +1,9 @@ package: name: PyYAML - version: 6.0.2 + version: 6.0.3 build: - number: 10 + number: 1 requirements: host: diff --git a/recipes/rasterio/meta.yaml b/recipes/rasterio/meta.yaml index 3e2b82b3..0dd84102 100644 --- a/recipes/rasterio/meta.yaml +++ b/recipes/rasterio/meta.yaml @@ -4,7 +4,7 @@ package: requirements: host: - - flet-libgdal 3.10.0 + - flet-libgdal 3.13.1 - numpy ^2.0.0 # {% if sdk == 'android' %} # rasterio's `_warp.so` / `_filepath.so` / `_fill.so` carry @@ -17,9 +17,15 @@ requirements: # {% endif %} build: - number: 10 + # Same source version as pypi.flet.dev's rasterio-1.5.0-10 wheel, but + # this rebuild links against flet-libgdal 3.13.1 (vs. the published + # wheel's 3.10.0). pip's wheel selection picks the higher build_tag + # per PEP 427 when name+version collide; the new wheel must outrank + # build 10 or downstream installs would silently keep the old + # libgdal-3.10-linked rasterio and the gdal chain bump would be invisible. + number: 11 script_env: - GDAL_VERSION: 3.10.0 + GDAL_VERSION: 3.13.1 GDAL_LIB_PATH: '{platlib}/opt/lib' GDAL_INCLUDE_PATH: '{platlib}/opt/include' # {% if sdk == 'android' %} diff --git a/recipes/regex/meta.yaml b/recipes/regex/meta.yaml index 0ff8c759..d937f513 100644 --- a/recipes/regex/meta.yaml +++ b/recipes/regex/meta.yaml @@ -1,6 +1,6 @@ package: name: regex - version: 2024.11.6 + version: 2026.5.9 build: - number: 10 + number: 1 diff --git a/recipes/rpds-py/meta.yaml b/recipes/rpds-py/meta.yaml index 110231ed..ae050831 100644 --- a/recipes/rpds-py/meta.yaml +++ b/recipes/rpds-py/meta.yaml @@ -1,8 +1,8 @@ package: name: rpds-py - version: 0.23.1 + version: 2026.5.1 build: - number: 10 + number: 1 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 86314a71..6c419310 100644 --- a/recipes/ruamel.yaml.clib/meta.yaml +++ b/recipes/ruamel.yaml.clib/meta.yaml @@ -1,6 +1,6 @@ package: name: ruamel.yaml.clib - version: 0.2.12 + version: 0.2.15 build: - number: 10 + number: 1 diff --git a/recipes/shapely/meta.yaml b/recipes/shapely/meta.yaml index 2ea41ad8..96a4f5be 100644 --- a/recipes/shapely/meta.yaml +++ b/recipes/shapely/meta.yaml @@ -1,14 +1,43 @@ package: name: shapely - version: 2.0.6 + version: 2.1.2 build: - number: 10 + number: 1 + script_env: + # shapely 2.1+ supports an official cross-compile path: when both + # GEOS_INCLUDE_PATH and GEOS_LIBRARY_PATH are set, setup.py skips the + # geos-config probe and the version compatibility check, and links + # against `geos_c` directly. Replaces the 2.0.x-era mobile.patch + # that commented out the geos-config block by hand. + GEOS_INCLUDE_PATH: '{platlib}/opt/include' + GEOS_LIBRARY_PATH: '{platlib}/opt/lib' +# {% if sdk != 'android' %} + # iOS-only — flet-libgeos is built static (`-DBUILD_SHARED_LIBS=OFF`), + # which presents two problems for shapely's C++ extension: + # + # 1. shapely's C extension subclasses `geos::geom::GeometryComponentFilter` + # and overrides the virtual `filter_ro(const Geometry*)`. The vtable + # for the base class lives in libgeos.a's object file, but the linker + # only pulls object files that satisfy *direct* symbol references — + # not vtables expected by C++ dispatch. At dlopen, dyld fails on + # `__ZN4geos4geom23GeometryComponentFilter9filter_roEPKNS0_8GeometryE`. + # Fix: `-Wl,-force_load,` brings every object out of + # the archive so the vtable is present in shapely.so. + # + # 2. libgeos_c.a still references geos_c-only externals (and shapely's + # .so references libgeos_c internals); `-undefined dynamic_lookup` + # keeps the link from failing on those, deferring resolution to + # dlopen — at which point force_load has provided what's needed. + # + # Same static-cascade pattern shipped in recipes/pyogrio and + # recipes/fiona, but those only needed the dynamic_lookup half because + # their missing symbols were from *external* deps of libgdal — not + # C++ vtables internal to libgdal itself. + LDFLAGS: '-undefined dynamic_lookup -Wl,-force_load,{platlib}/opt/lib/libgeos.a' +# {% endif %} requirements: host: - - flet-libgeos 3.13.0 + - flet-libgeos 3.13.1 - 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 deleted file mode 100644 index 43aa6df8..00000000 --- a/recipes/shapely/patches/mobile.patch +++ /dev/null @@ -1,75 +0,0 @@ -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", "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/recipes/sqlalchemy/meta.yaml b/recipes/sqlalchemy/meta.yaml index d1cef09f..e31ac41f 100644 --- a/recipes/sqlalchemy/meta.yaml +++ b/recipes/sqlalchemy/meta.yaml @@ -1,6 +1,6 @@ package: name: sqlalchemy - version: 2.0.36 + version: 2.0.50 build: - number: 10 + number: 1 diff --git a/recipes/tiktoken/meta.yaml b/recipes/tiktoken/meta.yaml index 0b8f2b5d..d944529e 100644 --- a/recipes/tiktoken/meta.yaml +++ b/recipes/tiktoken/meta.yaml @@ -1,8 +1,8 @@ package: name: tiktoken - version: 0.9.0 + version: 0.13.0 build: - number: 10 + number: 1 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 b2acd8d0..5d8a446a 100644 --- a/recipes/time-machine/meta.yaml +++ b/recipes/time-machine/meta.yaml @@ -1,6 +1,6 @@ package: name: time-machine - version: 2.16.0 + version: 3.2.0 build: - number: 10 + number: 1 diff --git a/recipes/tokenizers/meta.yaml b/recipes/tokenizers/meta.yaml index 74050fba..456a2274 100644 --- a/recipes/tokenizers/meta.yaml +++ b/recipes/tokenizers/meta.yaml @@ -1,6 +1,15 @@ package: name: tokenizers - version: 0.21.0 + # Capped at 0.22.2 (last stable release without 32-bit-incompatible + # atomics). tokenizers 0.23.1 introduced `static NEXT_CACHE_ID: + # AtomicU64` in src/models/bpe/model.rs which fails to compile on + # `arm-linux-androideabi` (armeabi-v7a) with `error[E0432]: + # unresolved import std::sync::atomic::AtomicU64` — the ARMv7-A + # core has no native 64-bit atomic ops. Re-attempt 0.23+ once we + # carry a recipe-side patch swapping the AtomicU64 for a portable- + # atomic crate, or after upstream gates the cache id on a + # `cfg(target_has_atomic = "64")` build. + version: 0.22.2 # {% if sdk == 'android' %} requirements: @@ -13,6 +22,6 @@ requirements: # {% endif %} build: - number: 10 + number: 1 script_env: _PYTHON_SYSCONFIGDATA_NAME: '{sysconfigdata_name}' \ No newline at end of file diff --git a/recipes/websockets/meta.yaml b/recipes/websockets/meta.yaml index 95c87d1b..4bc04b06 100644 --- a/recipes/websockets/meta.yaml +++ b/recipes/websockets/meta.yaml @@ -1,6 +1,6 @@ package: name: websockets - version: 13.0.1 + version: "16.0" build: - number: 10 + number: 1 diff --git a/recipes/yarl/meta.yaml b/recipes/yarl/meta.yaml index 13a53eaf..bed69dc1 100644 --- a/recipes/yarl/meta.yaml +++ b/recipes/yarl/meta.yaml @@ -1,9 +1,9 @@ package: name: yarl - version: 1.11.1 + version: 1.24.2 build: - number: 10 + number: 1 requirements: build: diff --git a/recipes/zope.interface/meta.yaml b/recipes/zope.interface/meta.yaml index f8fabad5..500cf614 100644 --- a/recipes/zope.interface/meta.yaml +++ b/recipes/zope.interface/meta.yaml @@ -1,6 +1,6 @@ package: name: zope.interface - version: '7.2' + version: '8.5' build: - number: 10 + number: 1 diff --git a/recipes/zstandard/meta.yaml b/recipes/zstandard/meta.yaml index 917c4711..dcea87f9 100644 --- a/recipes/zstandard/meta.yaml +++ b/recipes/zstandard/meta.yaml @@ -1,6 +1,6 @@ package: name: zstandard - version: 0.23.0 + version: 0.25.0 build: - number: 10 + number: 1 diff --git a/src/forge/build.py b/src/forge/build.py index 71ff020f..76c69170 100644 --- a/src/forge/build.py +++ b/src/forge/build.py @@ -658,11 +658,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":