Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
2b58a4f
ci: add multi-Python matrix dimension (3.12 / 3.13 / 3.14)
ndonkoHenri Jun 8, 2026
feb8ce8
improve
ndonkoHenri Jun 8, 2026
e881d55
setup.sh + forge: relocate pkg-config .pc files so meson can find Pyt…
ndonkoHenri Jun 8, 2026
789be22
forge: declare pkg-config in meson cross-file [binaries]
ndonkoHenri Jun 8, 2026
a147a5d
setup.sh: also substitute $(BLDLIBRARY) in python-X.Y.pc
ndonkoHenri Jun 8, 2026
bb6c7a2
forge: include host python pkgconfig dir in PKG_CONFIG_PATH
ndonkoHenri Jun 9, 2026
838c244
ci: split per-python matrix into orchestrator + reusable child workflow
ndonkoHenri Jun 9, 2026
1598586
ci(orchestrator): pass GEMFURY_TOKEN explicitly instead of inherit
ndonkoHenri Jun 9, 2026
60a0f7b
ci(child): job_name -> "recipe ver (platform) #build"
ndonkoHenri Jun 9, 2026
00b7239
Revert "Preserve upstream wheel Python/ABI tag in fix_wheel (#61)"
ndonkoHenri Jun 9, 2026
35f89e0
flet-libcurl: probe sibling openssl-* dir for 3.14+ Android layout
ndonkoHenri Jun 9, 2026
99d5416
forge: expose HOST_PYTHON_HOME + use it in flet-libcurl openssl probe
ndonkoHenri Jun 9, 2026
56cc5d4
flet-libgdal + flet-libproj: probe sibling sqlite-* dir for 3.14+ And…
ndonkoHenri Jun 9, 2026
3624033
forge: expose HOST_PYTHON_HOME on every recipe's compile_env
ndonkoHenri Jun 9, 2026
5ef9820
coolprop: anchor Python_LIBRARY / Python_INCLUDE_DIR on HOST_PYTHON_H…
ndonkoHenri Jun 9, 2026
899565c
ci(child): install pkg-config on iOS lane (macos-26) too
ndonkoHenri Jun 9, 2026
76a47e0
forge: add /opt/homebrew/bin (and /usr/local/bin) to PATH on iOS host
ndonkoHenri Jun 9, 2026
5d145e6
forge: scan site-packages/*/share/pkgconfig for PKG_CONFIG_PATH
ndonkoHenri Jun 9, 2026
f4b12b4
ci(child): attempt mobile tests on cp3.13/cp3.14 with continue-on-error
ndonkoHenri Jun 9, 2026
e4e3899
forge: add -framework Python to iOS LDFLAGS
ndonkoHenri Jun 10, 2026
0c664e7
forge + flet-libfreetype: stop pkg-config from leaking macOS Homebrew…
ndonkoHenri Jun 10, 2026
fb92e92
coolprop: mirror HOST_PYTHON_HOME switch to iOS branch
ndonkoHenri Jun 10, 2026
e7de8da
forge: move iOS -framework Python from LDFLAGS into meson cross-file …
ndonkoHenri Jun 10, 2026
4e7bd94
ci(child): only `brew install pkg-config` when missing on iOS lane
ndonkoHenri Jun 10, 2026
2ec4f8e
ci(child): drop `brew install pkg-config` on iOS lane
ndonkoHenri Jun 10, 2026
46a4d36
ci(workflow): streamline comments and improve job_name formatting in …
ndonkoHenri Jun 10, 2026
dabd3f4
ci(child): drop stale abi3 branch from dist-test wheel renamer
ndonkoHenri Jun 10, 2026
2e82dff
ci(workflow): add mobile_test_pythons input to allow selective mobile…
ndonkoHenri Jun 10, 2026
7cd97f0
ci(workflow): update build-wheels-version inputs and caching behavior
ndonkoHenri Jun 10, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
411 changes: 411 additions & 0 deletions .github/workflows/build-wheels-version.yml

Large diffs are not rendered by default.

431 changes: 96 additions & 335 deletions .github/workflows/build-wheels.yml

Large diffs are not rendered by default.

16 changes: 8 additions & 8 deletions recipes/coolprop/meta.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,18 @@ build:
-DANDROID_STL=c++_shared
-DCMAKE_SHARED_LINKER_FLAGS=-Wl,-z,max-page-size=16384
-DCMAKE_MODULE_LINKER_FLAGS=-Wl,-z,max-page-size=16384
-DPython_LIBRARY={prefix}/lib/libpython{py_version_short}.so
-DPython_INCLUDE_DIR={prefix}/include/python{py_version_short}
-DPython3_LIBRARY={prefix}/lib/libpython{py_version_short}.so
-DPython3_INCLUDE_DIR={prefix}/include/python{py_version_short}
-DPython_LIBRARY={HOST_PYTHON_HOME}/lib/libpython{py_version_short}.so
-DPython_INCLUDE_DIR={HOST_PYTHON_HOME}/include/python{py_version_short}
-DPython3_LIBRARY={HOST_PYTHON_HOME}/lib/libpython{py_version_short}.so
-DPython3_INCLUDE_DIR={HOST_PYTHON_HOME}/include/python{py_version_short}
# {% else %}
CMAKE_ARGS: >-
-DCMAKE_SYSTEM_NAME=iOS
-DCMAKE_OSX_SYSROOT={{ sdk }}
-DCMAKE_OSX_DEPLOYMENT_TARGET={{ sdk_version }}
-DCMAKE_OSX_ARCHITECTURES={{ arch }}
-DPython_LIBRARY={prefix}/lib/libpython{py_version_short}.dylib
-DPython_INCLUDE_DIR={prefix}/include/python{py_version_short}
-DPython3_LIBRARY={prefix}/lib/libpython{py_version_short}.dylib
-DPython3_INCLUDE_DIR={prefix}/include/python{py_version_short}
-DPython_LIBRARY={HOST_PYTHON_HOME}/lib/libpython{py_version_short}.dylib
-DPython_INCLUDE_DIR={HOST_PYTHON_HOME}/include/python{py_version_short}
-DPython3_LIBRARY={HOST_PYTHON_HOME}/lib/libpython{py_version_short}.dylib
-DPython3_INCLUDE_DIR={HOST_PYTHON_HOME}/include/python{py_version_short}
# {% endif %}
23 changes: 23 additions & 0 deletions recipes/flet-libcurl/build.sh
Original file line number Diff line number Diff line change
@@ -1,13 +1,36 @@
#!/bin/bash
set -eu

# OpenSSL discovery, for 3 known layouts across python-build versions:
# 1. host-dep extraction (iOS): the openssl wheel is declared in
# `requirements.host`, pip extracts it into $PLATLIB/opt — so headers
# land at $PLATLIB/opt/include/openssl/ssl.h and libs at
# $PLATLIB/opt/lib/libssl.{a,so}.
OPENSSL_PREFIX="$PLATLIB/opt"

# 2. python-build 3.12/3.13 (Android): openssl is bundled directly
# into the python install dir, so $PYTHON_PREFIX itself acts as the
# prefix and headers live at $PYTHON_PREFIX/include/openssl/ssl.h.
if [ ! -f "$OPENSSL_PREFIX/include/openssl/ssl.h" ] || \
{ [ ! -f "$OPENSSL_PREFIX/lib/libssl.a" ] && [ ! -f "$OPENSSL_PREFIX/lib/libssl.so" ]; } || \
{ [ ! -f "$OPENSSL_PREFIX/lib/libcrypto.a" ] && [ ! -f "$OPENSSL_PREFIX/lib/libcrypto.so" ]; }; then
OPENSSL_PREFIX="$PYTHON_PREFIX"
fi

# 3. python-build 3.14+ (Android): openssl lives as a *sibling* of the
# python install dir (e.g. .../install/android/<abi>/openssl-3.0.20-1).
# Glob siblings of $HOST_PYTHON_HOME (the support-tree python install
# dir, distinct from $PYTHON_PREFIX which on 3.14 relocates into the
# cross-venv), and take the first match.
if [ ! -f "$OPENSSL_PREFIX/include/openssl/ssl.h" ]; then
for candidate in "$HOST_PYTHON_HOME"/../openssl-*; do
if [ -f "$candidate/include/openssl/ssl.h" ]; then
OPENSSL_PREFIX="$candidate"
break
fi
done
fi

PKG_CONFIG=false ./configure --host=$HOST_TRIPLET --prefix=$PREFIX --with-openssl="$OPENSSL_PREFIX"
make -j $CPU_COUNT
make install
Expand Down
2 changes: 1 addition & 1 deletion recipes/flet-libfreetype/meta.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ build:
number: 10

source:
url: https://download.savannah.gnu.org/releases/freetype/freetype-2.13.3.tar.gz
url: https://downloads.sourceforge.net/project/freetype/freetype2/2.13.3/freetype-2.13.3.tar.gz

patches:
- config.patch
Expand Down
20 changes: 18 additions & 2 deletions recipes/flet-libgdal/build.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,22 @@
#!/bin/bash
set -eu

# SQLite3 discovery for Android:
# - 3.12/3.13: sqlite3.h is bundled inside the python install dir,
# so $HOST_PYTHON_HOME/include/sqlite3.h works.
# - 3.14+: sqlite3.h lives in a sibling dir alongside the python
# install (.../install/android/<abi>/sqlite-X.Y.Z/include/).
# The .so library itself stays inside $HOST_PYTHON_HOME/lib/ on both.
SQLITE3_INC="$HOST_PYTHON_HOME/include"
if [ ! -f "$SQLITE3_INC/sqlite3.h" ]; then
for candidate in "$HOST_PYTHON_HOME"/../sqlite-*; do
if [ -f "$candidate/include/sqlite3.h" ]; then
SQLITE3_INC="$candidate/include"
break
fi
done
fi

mkdir build
cd build

Expand All @@ -18,8 +34,8 @@ if [ $CROSS_VENV_SDK == "android" ]; then
-DCMAKE_FIND_USE_CMAKE_SYSTEM_PATH=NO \
-DPROJ_LIBRARY=$PLATLIB/opt/lib/libproj.so \
-DPROJ_INCLUDE_DIR=$PLATLIB/opt/include \
-DSQLite3_LIBRARY=$PYTHON_PREFIX/lib/libsqlite3_python.so \
-DSQLite3_INCLUDE_DIR=$PYTHON_PREFIX/include \
-DSQLite3_LIBRARY=$HOST_PYTHON_HOME/lib/libsqlite3_python.so \
-DSQLite3_INCLUDE_DIR=$SQLITE3_INC \
-DGDAL_BUILD_OPTIONAL_DRIVERS=OFF \
-DOGR_BUILD_OPTIONAL_DRIVERS=OFF \
-DGDAL_USE_EXPAT=OFF \
Expand Down
20 changes: 18 additions & 2 deletions recipes/flet-libproj/build.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,22 @@
#!/bin/bash
set -eu

# SQLite3 discovery for Android:
# - 3.12/3.13: sqlite3.h is bundled inside the python install dir,
# so $HOST_PYTHON_HOME/include/sqlite3.h works.
# - 3.14+: sqlite3.h lives in a sibling dir alongside the python
# install (.../install/android/<abi>/sqlite-X.Y.Z/include/).
# The .so library itself stays inside $HOST_PYTHON_HOME/lib/ on both.
SQLITE3_INC="$HOST_PYTHON_HOME/include"
if [ ! -f "$SQLITE3_INC/sqlite3.h" ]; then
for candidate in "$HOST_PYTHON_HOME"/../sqlite-*; do
if [ -f "$candidate/include/sqlite3.h" ]; then
SQLITE3_INC="$candidate/include"
break
fi
done
fi

if [ $CROSS_VENV_SDK == "android" ]; then
cmake \
-DCMAKE_SYSTEM_NAME=Android \
Expand All @@ -15,8 +31,8 @@ if [ $CROSS_VENV_SDK == "android" ]; then
-DTIFF_INCLUDE_DIR="$PLATLIB/opt/include" \
-DCURL_LIBRARY="$PLATLIB/opt/lib/libcurl.so" \
-DCURL_INCLUDE_DIR="$PLATLIB/opt/include" \
-DSQLite3_LIBRARY=$PYTHON_PREFIX/lib/libsqlite3_python.so \
-DSQLite3_INCLUDE_DIR=$PYTHON_PREFIX/include
-DSQLite3_LIBRARY=$HOST_PYTHON_HOME/lib/libsqlite3_python.so \
-DSQLite3_INCLUDE_DIR=$SQLITE3_INC
else
cmake \
-DCMAKE_SYSTEM_NAME=iOS \
Expand Down
48 changes: 47 additions & 1 deletion setup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,52 @@ download_support() {
echo "Extracting ${tarball} into ${dest}..."
mkdir -p "$dest"
tar -xzf "downloads/${tarball}" -C "$dest"

# Rewrite the `prefix=` line in every shipped `lib/pkgconfig/*.pc` to pkg-config's relocatable
# form `prefix=${pcfiledir}/../..` so consumer pkg-config invocations resolve include/lib paths to the actual
# on-disk install root, NOT the build-time `/usr/local` autoconf default that CPython bakes in. Without
# this, meson's `py.dependency()` gets `-I/usr/local/include/python3.X` (a path that does not exist on
# the CI runner) and reports the Python dep as "not found" — surfaced by numpy 2.4.6 on Python 3.14 Android.
relocate_pkgconfig_prefix "$dest"
}

# Walk every `.pc` file under <dest>/.../lib/pkgconfig/ and rewrite the (literal absolute-path) `prefix=`
# line to pkg-config's standard relocatable `prefix=${pcfiledir}/../..`. Idempotent — if the line is
# already in the relocatable form, the sed substitution silently leaves the file alone. Safe to call
# across versions/platforms; the find prunes to pkgconfig dirs explicitly.
relocate_pkgconfig_prefix() {
local dest="$1"
# Find every lib/pkgconfig dir under the extracted tree. CPython ships .pc files under
# <install>/<abi>/python-<ver>/lib/pkgconfig on Android and under <Python.xcframework>/<slice>/lib/pkgconfig on iOS.
find "$dest" -type d -name pkgconfig 2>/dev/null | while read -r pcdir; do
# `prefix=${pcfiledir}/../..` -- pkg-config/pkgconf substitutes ${pcfiledir} with the .pc
# file's actual directory at lookup time. <dir>/../.. on a .pc at <install>/lib/pkgconfig/*.pc
# resolves to <install> -- the consumer's real install prefix.
#
# Also substitute `$(BLDLIBRARY)` in the Libs: line. CPython's autoconf-built python-X.Y.pc
# ships `Libs: -L${libdir} $(BLDLIBRARY)` -- the `$(BLDLIBRARY)` is supposed to expand to `-lpython3.X`
# at install time but never does, and pkg-config passes the literal through to the linker which then
# fails with `clang++: error: no such file or directory: '$(BLDLIBRARY)'`. Only the python-X.Y.pc files
# are affected; python-X.Y-embed.pc already has `-lpythonX.Y` written directly. We fix both
# idempotently by rewriting `$(BLDLIBRARY)` -> `-lpython${ver}` where ver is derived from the .pc filename.
for pc in "$pcdir"/*.pc; do
[ -f "$pc" ] || continue
# macOS sed doesn't have -i without an extension arg; use a portable in-place edit via a temp file.
local tmp
tmp="$(mktemp)"
sed -E 's|^prefix=.*|prefix=${pcfiledir}/../..|' "$pc" > "$tmp" && mv "$tmp" "$pc"

# If this is a python-X.Y.pc (not the -embed variant or some other recipe-shipped .pc), substitute
# $(BLDLIBRARY) with the matching -lpythonX.Y.
local base
base="$(basename "$pc")"
if [[ "$base" =~ ^python-([0-9]+\.[0-9]+)\.pc$ ]]; then
local ver="${BASH_REMATCH[1]}"
tmp="$(mktemp)"
sed -E 's|\$\(BLDLIBRARY\)|-lpython'"$ver"'|g' "$pc" > "$tmp" && mv "$tmp" "$pc"
fi
done
done
}

# Echo the directory that actually contains the support/ tree: $1 itself, or a
Expand Down Expand Up @@ -273,4 +319,4 @@ 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
unset -f download_support resolve_support_root relocate_pkgconfig_prefix
113 changes: 95 additions & 18 deletions src/forge/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -234,8 +234,12 @@ def prepare(self, clean=True):
)
shutil.rmtree(self.build_path)

# Re-download sources if caching is disabled or no cached tarball exists.
# By default, the cached tarball is reused across arch builds to avoid downloading
# the same source multiple times. Disable caching when testing source-tarball patches,
# since each arch reuses and re-unpacks the same cached archive.
if (
os.getenv(f"MOBILE_FORGE_CACHE_DOWNLOADS_OFF")
os.getenv("MOBILE_FORGE_CACHE_DOWNLOADS_OFF")
or not self.source_archive_path.is_file()
):
log(self.log_file, f"\n[{self.cross_venv}] Download package sources")
Expand Down Expand Up @@ -384,7 +388,13 @@ def compile_env(self, **kwargs) -> dict[str, str]:
if (self.cross_venv.sdk_root / "usr" / "lib").is_dir():
ldflags += f" -L{self.cross_venv.sdk_root}/usr/lib"

# Add the framework path
# Add the framework search path. We do *not* append `-framework Python`
# here -- doing so breaks autoconf-based builds like flet-libfreetype, whose
# `./configure` probes the C compiler by linking a trivial hello.c against $LDFLAGS;
# `-framework Python` makes that probe fail with `configure: error: C compiler cannot create executables`.
# Cargo/setuptools/meson recipes each get the framework link via their own channel (cargo_ldflags
# below, the cross sysconfig'\''s LDSHARED for setuptools, and the meson cross-file'\''s
# c_link_args / cpp_link_args augmented in _create_meson_cross for meson).
ldflags += f' -F "{self.cross_venv.host_python_home}"'
cargo_ldflags += f" -C link-arg=-F{self.cross_venv.host_python_home} -C link-arg=-framework -C link-arg=Python"

Expand All @@ -400,6 +410,42 @@ def compile_env(self, **kwargs) -> dict[str, str]:
else self.cross_venv.platform_triplet
)

# Point pkg-config at the pkgconfig dirs that matter for the target build:
# 1. host_python_home/lib/pkgconfig — where python-X.Y.pc lives.
# Required for meson's `py.dependency()` to resolve the
# Python C dep via the relocated `.pc` files.
# 2. install_root/lib/pkgconfig — where flet-lib* extract their
# own `.pc` files when installed as host wheels.
# 3. <cross-venv>/{build,cross}/lib/pythonX.Y/site-packages/*/share/pkgconfig
# — pure-Python wheels (pybind11, …) ship their .pc files bundled
# inside site-packages rather than the usual lib/pkgconfig dir, so
# `dependency('pybind11')` via meson's pkg-config method only resolves
# once the .pc dir under the installed wheel is added explicitly.
# All three sets of `.pc` files use `prefix=${pcfiledir}/../..` so
# pkg-config emits paths relative to the on-disk .pc location.
pkg_config_paths = []
python_pc_dir = self.cross_venv.host_python_home / "lib" / "pkgconfig"
if python_pc_dir.is_dir():
pkg_config_paths.append(str(python_pc_dir))
pc_dir = install_root / "lib" / "pkgconfig"
if pc_dir.is_dir():
pkg_config_paths.append(str(pc_dir))
if self.cross_venv.venv_path.is_dir():
py_short = f"python3.{sys.version_info.minor}"
for env_root in ("build", "cross"):
site_dir = (
self.cross_venv.venv_path
/ env_root
/ "lib"
/ py_short
/ "site-packages"
)
if site_dir.is_dir():
for share_pkgconfig in site_dir.glob("*/share/pkgconfig"):
if share_pkgconfig.is_dir():
pkg_config_paths.append(str(share_pkgconfig))
pkg_config_path = ":".join(pkg_config_paths)

env = {
"AR": ar,
"CC": cc,
Expand All @@ -409,6 +455,18 @@ def compile_env(self, **kwargs) -> dict[str, str]:
"CFLAGS": cflags,
"CPPFLAGS": cppflags,
"LDFLAGS": ldflags,
"PKG_CONFIG_PATH": pkg_config_path,
# PKG_CONFIG_LIBDIR overrides pkg-config's *default* search list
# (typically /opt/homebrew/lib/pkgconfig + /usr/lib/pkgconfig on
# macOS, /usr/lib/pkgconfig on Linux). Without it, recipes like
# Pillow that scan via pkg-config will happily resolve libtiff /
# liblcms2 / libpng to the build host's macOS dylibs and try to
# link them into iOS .so files -- the linker then aborts with
# "ld: building for 'iOS', but linking in dylib (...) built for
# 'macOS'". Point LIBDIR at the same support-tree-only paths
# PKG_CONFIG_PATH already enumerates so pkg-config can't even
# see Homebrew's pkgconfig dir.
"PKG_CONFIG_LIBDIR": pkg_config_path,
"CROSS_VENV_SDK": self.cross_venv.sdk,
"CARGO_BUILD_TARGET": cargo_build_target,
"CARGO_TARGET_{}_LINKER".format(
Expand All @@ -429,6 +487,16 @@ def compile_env(self, **kwargs) -> dict[str, str]:
else Path(self.cross_venv.sysconfig_data["prefix"]) / "lib"
)
),
# The on-disk python install directory for the target SDK /
# arch inside the mobile-forge support tree
# (`MOBILE_FORGE_<SDK>_SUPPORT_PATH/install/<sdk>/<arch>/python-<X.Y.Z>`
# on Android, the matching Python.xcframework slice on
# iOS). Always a real directory on disk -- useful when a
# recipe needs to locate sibling artifacts shipped alongside
# Python in the support tree, or to pin Python_LIBRARY /
# Python_INCLUDE_DIR against a path that doesn't move with
# crossenv relocation across python-build versions.
"HOST_PYTHON_HOME": str(self.cross_venv.host_python_home),
}
env.update(kwargs)

Expand Down Expand Up @@ -616,7 +684,7 @@ def _rewrite_absolute_needed(self, so_path: Path):
self.log_file,
f"[{self.cross_venv}] {so_path.name}: NEEDED "
f"'{name.decode(errors='replace')}' -> "
f"'{name[slash + 1:].decode(errors='replace')}'",
f"'{name[slash + 1 :].decode(errors='replace')}'",
)

def _check_elf_alignment(self, so_path: Path):
Expand Down Expand Up @@ -658,21 +726,11 @@ 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)
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
if "Tag" in wheel_metadata:
del wheel_metadata["Tag"]
wheel_metadata["Tag"] = self.wheel_tag
self.write_message_file(wheel_metadata_path, wheel_metadata)

if self.cross_venv.sdk == "android":
Expand Down Expand Up @@ -973,12 +1031,31 @@ def _create_meson_cross(self, env: dict[str, str]):
/ "bin"
/ f"python3.{sys.version_info.minor}"
),
# Declare pkg-config explicitly. Meson cross-compile mode otherwise treats
# pkg-config as a build-machine-only tool and refuses to use it for target dep
# resolution -- even when it's installed and on PATH. Without this declaration
# meson reports "Found pkg-config: NO" regardless, defeats `py.dependency()` via
# pkg-config, and falls through to the sysconfig path that 3.14 doesn't tolerate the
# autoconf-baked `/usr/local` paths in. With it declared, meson invokes
# pkg-config + honors PKG_CONFIG_PATH (set in compile_env() above), reads the
# relocated `.pc` file, and emits the consumer-correct -I/-L flags.
"pkg-config": "pkg-config",
},
"built-in options": {
"c_args": env["CFLAGS"],
"cpp_args": env["CPPFLAGS"],
"c_links_args": env["LDFLAGS"],
"cpp_links_args": env["LDFLAGS"],
# iOS: append `-framework Python` to the meson c/cpp link args (not LDFLAGS env) so
# meson recipes (numpy, contourpy with pybind11, …) resolve the Python C API at link time
# without breaking autoconf-based builds whose hello.c probe also reads $LDFLAGS.
# See compile_env() in this file for the matching half of this split.
"c_links_args": (
env["LDFLAGS"]
+ (" -framework Python" if self.cross_venv.host_os == "iOS" else "")
),
"cpp_links_args": (
env["LDFLAGS"]
+ (" -framework Python" if self.cross_venv.host_os == "iOS" else "")
),
},
"properties": {"needs_exe_wrapper": False},
"host_machine": {
Expand Down
3 changes: 3 additions & 0 deletions src/forge/cross.py
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,9 @@ def cross_kwargs(self, kwargs):
str(self.venv_path / "bin"),
str(self.venv_path / self.venv_path.name / "bin"),
str(Path.home() / ".cargo/bin"),
"/opt/homebrew/bin",
# For Intel-mac or older CI runner images that put Homebrew under /usr/local.
"/usr/local/bin",
"/usr/bin",
"/bin",
"/usr/sbin",
Expand Down
Loading