diff --git a/.ci/common.sh b/.ci/common.sh index 5a60983..6073bf3 100644 --- a/.ci/common.sh +++ b/.ci/common.sh @@ -3,38 +3,3 @@ function publish_to_pypi() { curl -F package=@$wheel https://$GEMFURY_TOKEN@push.fury.io/flet/ done } - -# Resolve which python-build tarball source to use. -# When PYTHON_BUILD_RUN_ID is set (workflow_dispatch input), fetch the -# named tarball from that python-build Actions run's artifacts; otherwise -# download from the canonical v release URL. -# -# Args: -# $1 artifact_platform — "android" | "darwin" (matches the python-build artifact name) -# $2 tarball — e.g. python-android-mobile-forge-3.12.tar.gz -# $3 extract_dir — local dir to extract the tarball into -# -# Caller env: -# PYTHON_SHORT_VERSION — e.g. 3.12 (required) -# PYTHON_BUILD_RUN_ID — empty for release URL; non-empty for `gh run download` -# GH_TOKEN — needed only when PYTHON_BUILD_RUN_ID is set -# RUNNER_TEMP — GitHub Actions runner temp dir (only used in override path) -function fetch_python_build_tarball() { - local artifact_platform="$1" - local tarball="$2" - local extract_dir="$3" - if [[ -n "${PYTHON_BUILD_RUN_ID:-}" ]]; then - echo "Fetching $tarball from python-build run $PYTHON_BUILD_RUN_ID" - local stage="$RUNNER_TEMP/python-build-artifact" - rm -rf "$stage" - mkdir -p "$stage" - gh run download "$PYTHON_BUILD_RUN_ID" \ - --repo flet-dev/python-build \ - --name "python-${artifact_platform}-${PYTHON_SHORT_VERSION}" \ - --dir "$stage" - tar -xzf "$stage/$tarball" -C "$extract_dir" - else - curl -#OL "https://github.com/flet-dev/python-build/releases/download/v${PYTHON_SHORT_VERSION}/$tarball" - tar -xzf "$tarball" -C "$extract_dir" - fi -} diff --git a/.ci/read_meta.py b/.ci/read_meta.py index 452458f..0383425 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/.github/workflows/build-wheels-with-cibuildwheel.yml b/.github/workflows/build-wheels-with-cibuildwheel.yml deleted file mode 100644 index 2fcd5d1..0000000 --- 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@v5 - - - name: Setup uv - uses: astral-sh/setup-uv@v7 - - - name: Set up JDK - uses: actions/setup-java@v5 - with: - distribution: temurin - java-version: "17" - - - name: Set up Android SDK - uses: android-actions/setup-android@v4 - - - 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@v6 - 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 a93d666..9f086be 100644 --- a/.github/workflows/build-wheels.yml +++ b/.github/workflows/build-wheels.yml @@ -20,8 +20,13 @@ 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.12" + UV_PYTHON: "3.12.13" MOBILE_FORGE_CACHE_DOWNLOADS_OFF: "1" FORGE_NDK_VERSION: r27d # used by forge for wheel cross-compile. FLUTTER_NDK_VERSION: "28.2.13676358" # used by flutter for apk build. @@ -179,32 +184,19 @@ 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" - mkdir -p "$python_android_dir" - fetch_python_build_tarball "android" \ - "python-android-mobile-forge-${PYTHON_SHORT_VERSION}.tar.gz" \ - "$python_android_dir" - export MOBILE_FORGE_ANDROID_SUPPORT_PATH="$python_android_dir" - else - python_ios_dir="$HOME/projects/python-build/darwin/Python-Apple-support" - mkdir -p "$python_ios_dir" - fetch_python_build_tarball "darwin" \ - "python-ios-mobile-forge-${PYTHON_SHORT_VERSION}.tar.gz" \ - "$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. When the + # PYTHON_BUILD_RUN_ID env (from inputs above) is set, setup.sh + # fetches from that python-build Actions run's artifacts instead of + # the canonical v release. + 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 42a400a..d8b09e0 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/recipes/aiohttp/meta.yaml b/recipes/aiohttp/meta.yaml index 7122479..2167604 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 9620c2a..926adcc 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 82201ec..f5fc579 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 1d64f33..f5c94ce 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 fd3f930..70981fd 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 effaa8d..3347491 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 37863a4..04ed998 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 506cc3e..981f5e4 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 0f2e97b..01aedb2 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 7f9c191..42187ef 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 a64edca..7b7aaf0 100644 --- a/recipes/cryptography/meta.yaml +++ b/recipes/cryptography/meta.yaml @@ -1,13 +1,19 @@ 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: - 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 603d9e4..0e8f9c4 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 f1dfb89..a85e418 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 4011460..906b892 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 c4e3d54..2a33195 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 511ec37..6c25ec8 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 dec9cc4..ba29642 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 5e9f89b..08e5c6e 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 38a6fbd..3f36b60 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 400c32b..e3d26a3 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 b5804df..63009c7 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 76c0486..54c9034 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 9614942..43f54bf 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 7b04042..c3a0936 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 92047ce..37c2f73 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 c681362..354e833 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 568622d..b59b9f4 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 ea05b71..510b117 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 607b99a..782425f 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 6704b83..eb1a9ba 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 80a5da4..8f7d891 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 7849683..57a5e03 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 349b81a..9ae9814 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 33f5d86..ff40fc2 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 1ce96d9..916410e 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 e88513f..70d0640 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 7b78f43..13b0fcf 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 811876f..3be1f0e 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 680fcda..5e5e250 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 fa41ef2..b6e3a14 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 700d466..d30edb9 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 0be8d42..7e8247c 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 293c7c4..cc816be 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 b9842c2..e9abe94 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 ff8aa45..0766afe 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 56295e5..e4645d2 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 a3830d0..a64d188 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 1a7edd2..18fc8f4 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 45da06e..e71a061 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 7aed052..b0ca84c 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 ace7576..231c0ff 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 8c2275a..9ac5a9d 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 3877783..b7c3cb5 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 88d1fdb..987bb29 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 70da98c..60ba14f 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 cb3ef62..55eea88 100644 --- a/recipes/pydantic-core/meta.yaml +++ b/recipes/pydantic-core/meta.yaml @@ -1,8 +1,8 @@ package: name: pydantic-core - version: 2.33.2 + 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 263974d..98adc31 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 79a9cbb..478305d 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 46fd867..bbec225 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 96d4507..5d1ad23 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 80ba2bd..c0ea41a 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 1b8b4bd..2513822 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 2bc8811..531482f 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 f76acfb..f38fea1 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 c3be469..fd0b36b 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 31927e6..3e2b82b 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 3d6ac1b..0ff8c75 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 12297f6..110231e 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 0a2e815..86314a7 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 7d482f2..67b1d0b 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 b50c959..2ea41ad 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 6fe0f3e..d1cef09 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 3300bb0..0b8f2b5 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 caec2e5..b2acd8d 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 15a7f9c..74050fb 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 96af065..cfbb111 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 fdc85c2..95c87d1 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 f4f1559..13a53ea 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 5bb5314..f8fabad 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 d194e1f..917c471 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 diff --git a/setup.sh b/setup.sh index 1201bc0..9a9201e 100755 --- a/setup.sh +++ b/setup.sh @@ -32,12 +32,141 @@ fi PYTHON_VERSION=$1 PYTHON_VER="${PYTHON_VERSION%.*}" +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, extracting it +# into $2. Source is either the canonical v release on +# flet-dev/python-build, or a specific Actions run's artifacts when +# $PYTHON_BUILD_RUN_ID is set (used in CI to validate unreleased +# python-build branches against the recipe matrix). Tarballs are cached +# under downloads/ (gitignored) and reused on subsequent runs. +# +# Reads from caller env: +# PYTHON_BUILD_RUN_ID — empty for release URL; non-empty for `gh run download` +# (requires `gh` installed and a GITHUB_TOKEN / login) +download_support() { + local plat="$1" dest="$2" + local tarball="python-${plat}-mobile-forge-${PYTHON_VER}.tar.gz" + + if [ -d "$dest/support" ]; then + return 0 + fi + + mkdir -p downloads + if [ ! -f "downloads/${tarball}" ]; then + if [ -n "${PYTHON_BUILD_RUN_ID:-}" ]; then + # 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 "$artifact_name" \ + --dir "$stage"; then + echo "Failed to download artifact ${artifact_name} from run ${PYTHON_BUILD_RUN_ID}" + rm -rf "$stage" + return 1 + fi + mv "$stage/${tarball}" "downloads/${tarball}" + rm -rf "$stage" + else + local url="https://github.com/flet-dev/python-build/releases/download/v${PYTHON_VER}/${tarball}" + echo "Downloading ${tarball}..." + if ! curl -fL -o "downloads/${tarball}" "$url"; then + echo "Failed to download ${url}" + rm -f "downloads/${tarball}" + return 1 + fi + 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 +# 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}" +# 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_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" + echo "MOBILE_FORGE_{IOS,ANDROID}_SUPPORT_PATH_${versioned_suffix}." return fi @@ -106,7 +235,7 @@ if [ ! -z "$MOBILE_FORGE_ANDROID_SUPPORT_PATH" ]; then return fi - if [ "$PYTHON_VER" = "3.12" ]; then + if [ "$python_version_minor" -lt 13 ]; 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 @@ -142,3 +271,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 diff --git a/src/forge/build.py b/src/forge/build.py index 1d12bf7..71ff020 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":