From 1369509f0e3c0fccb4af667eade45ab24290d8ec Mon Sep 17 00:00:00 2001 From: Abdo Date: Thu, 1 Oct 2026 23:03:51 +0300 Subject: [PATCH 1/5] Preserve Python executables --- Makefile | 11 ++++++++--- patch/Python/release.macOS.exclude | 2 -- patch/make-relocatable.sh | 11 +++++++++++ 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index aff9ff6e..fad50ba0 100644 --- a/Makefile +++ b/Makefile @@ -497,9 +497,10 @@ $$(PYTHON_INCLUDE-$(sdk))/pyconfig.h: $$(PYTHON_LIB-$(sdk)) # Copy binary helpers from the first target in the $(sdk) SDK cp -r $$(PYTHON_BIN-$$(firstword $$(SDK_TARGETS-$(sdk)))) $$(PYTHON_BIN-$(sdk)) - # Create a non-executable stub binary python3 - echo "#!/bin/bash\necho Can\\'t run $(sdk) binary\nexit 1" > $$(PYTHON_BIN-$(sdk))/python$(PYTHON_VER) - chmod 755 $$(PYTHON_BIN-$(sdk))/python$(PYTHON_VER) + # Merge the python3 binary from each target in the $(sdk) SDK into a fat binary + lipo -create -output $$(PYTHON_BIN-$(sdk))/python$(PYTHON_VER) \ + $$(foreach target,$$(SDK_TARGETS-$(sdk)),$$(PYTHON_BIN-$$(target))/python$(PYTHON_VER)) \ + 2>&1 | tee -a install/$(os)/$(sdk)/python-$(PYTHON_VERSION).lipo.log # Copy headers as-is from the first target in the $(sdk) SDK cp -r $$(PYTHON_INCLUDE-$$(firstword $$(SDK_TARGETS-$(sdk)))) $$(PYTHON_INCLUDE-$(sdk)) @@ -641,6 +642,10 @@ $$(PYTHON_XCFRAMEWORK-$(os))/Info.plist: \ 2>&1 | tee -a $$(PYTHON_INSTALL-macosx)/python-$(os).codesign.log find $$(PYTHON_FRAMEWORK-macosx) -name "*.so" -type f -exec codesign -s - --preserve-metadata=identifier,entitlements,flags,runtime -f {} \; \ 2>&1 | tee -a $$(PYTHON_INSTALL-macosx)/python-$(os).codesign.log + find $$(PYTHON_INSTALL_VERSION-macosx)/bin -type f -perm +111 -exec sh -c 'file "$$$$1" | grep -q Mach-O' _ {} \; -exec codesign -s - --preserve-metadata=identifier,entitlements,flags,runtime -f {} \; \ + 2>&1 | tee -a $$(PYTHON_INSTALL-macosx)/python-$(os).codesign.log + codesign -s - --preserve-metadata=identifier,entitlements,flags,runtime -f $$(PYTHON_INSTALL_VERSION-macosx)/Resources/Python.app \ + 2>&1 | tee -a $$(PYTHON_INSTALL-macosx)/python-$(os).codesign.log codesign -s - --preserve-metadata=identifier,entitlements,flags,runtime -f $$(PYTHON_FRAMEWORK-macosx) \ 2>&1 | tee -a $$(PYTHON_INSTALL-macosx)/python-$(os).codesign.log diff --git a/patch/Python/release.macOS.exclude b/patch/Python/release.macOS.exclude index 3bc247c1..368130b6 100644 --- a/patch/Python/release.macOS.exclude +++ b/patch/Python/release.macOS.exclude @@ -6,7 +6,6 @@ ._Python ._Resources Resources/._Python.app -Resources/Python.app Versions/._Current Versions/*/.__CodeSignature Versions/*/._bin @@ -17,7 +16,6 @@ Versions/*/._include Versions/*/._lib Versions/*/._Resources Versions/*/._share -Versions/*/bin Versions/*/etc Versions/*/Frameworks Versions/*/lib/python*/idlelib diff --git a/patch/make-relocatable.sh b/patch/make-relocatable.sh index f268cd70..536b792c 100755 --- a/patch/make-relocatable.sh +++ b/patch/make-relocatable.sh @@ -24,4 +24,15 @@ for module in `find . -name "*.dylib" -type f -o -name "*.so" -type f`; do done fi done +for exe in `find bin Resources/Python.app/Contents/MacOS -type f -perm +111`; do + if [ "$(otool -L ${exe} 2>/dev/null | grep -c /Library/Frameworks/Python.framework)" != "0" ]; then + echo Rewrite references to Python library in ${exe} + install_name_tool -change /Library/Frameworks/Python.framework/Versions/${PYTHON_VER}/Python @rpath/Python.framework/Versions/${PYTHON_VER}/Python ${exe} + # Add an rpath pointing at the directory that contains Python.framework + # (one level up per path component, plus 3 for Python.framework/Versions/X.Y) + depth=$(( $(echo ${exe} | tr -cd '/' | wc -c) + 3 )) + rpath=@executable_path$(printf '/..%.0s' $(seq ${depth})) + install_name_tool -add_rpath ${rpath} ${exe} + fi +done popd From d76836cd41aaaad49b86dc9c97ea7e388b4a2599 Mon Sep 17 00:00:00 2001 From: Abdo Date: Thu, 1 Oct 2026 23:04:08 +0300 Subject: [PATCH 2/5] Update docs --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 63b3ef6f..eb4c4818 100644 --- a/README.md +++ b/README.md @@ -71,7 +71,7 @@ Each support package contains: On iOS/tvOS/watchOS/visionOS, the `Python.xcframework` contains a slice for each supported ABI (device and simulator). The folder containing the slice can also be used as a `PYTHONHOME`, as it contains a `bin`, `include` and `lib` directory. -The `bin` folder does not contain Python executables (as they can't be invoked). However, it *does* contain shell aliases for the compilers that are needed to build packages. This is required because Xcode uses the `xcrun` alias to dynamically generate the name of binaries, but a lot of C tooling expects that `CC` will not contain spaces. +The `bin` folder contains shell aliases for the compilers that are needed to build packages (in addition to Python executables). This is required because Xcode uses the `xcrun` alias to dynamically generate the name of binaries, but a lot of C tooling expects that `CC` will not contain spaces. Each slice of an iOS/tvOS/watchOS/visionOS XCframework also contains a `platform-config` folder with a subfolder for each supported architecture in that slice. These subfolders can be used to make a macOS Python environment behave as if it were on an iOS/tvOS/watchOS/visionOS device. This works in one of two ways: From a296d572f1a6cdd53538b88e86eb948ee524549c Mon Sep 17 00:00:00 2001 From: Abdo Date: Fri, 2 Oct 2026 01:12:13 +0300 Subject: [PATCH 3/5] Restore non-executable stub for non-macOS platforms --- Makefile | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index fad50ba0..15015a7b 100644 --- a/Makefile +++ b/Makefile @@ -497,10 +497,9 @@ $$(PYTHON_INCLUDE-$(sdk))/pyconfig.h: $$(PYTHON_LIB-$(sdk)) # Copy binary helpers from the first target in the $(sdk) SDK cp -r $$(PYTHON_BIN-$$(firstword $$(SDK_TARGETS-$(sdk)))) $$(PYTHON_BIN-$(sdk)) - # Merge the python3 binary from each target in the $(sdk) SDK into a fat binary - lipo -create -output $$(PYTHON_BIN-$(sdk))/python$(PYTHON_VER) \ - $$(foreach target,$$(SDK_TARGETS-$(sdk)),$$(PYTHON_BIN-$$(target))/python$(PYTHON_VER)) \ - 2>&1 | tee -a install/$(os)/$(sdk)/python-$(PYTHON_VERSION).lipo.log + # Create a non-executable stub binary python3 + echo "#!/bin/bash\necho Can\\'t run $(sdk) binary\nexit 1" > $$(PYTHON_BIN-$(sdk))/python$(PYTHON_VER) + chmod 755 $$(PYTHON_BIN-$(sdk))/python$(PYTHON_VER) # Copy headers as-is from the first target in the $(sdk) SDK cp -r $$(PYTHON_INCLUDE-$$(firstword $$(SDK_TARGETS-$(sdk)))) $$(PYTHON_INCLUDE-$(sdk)) From d999ecfd96b52f305e7e93afa0df6fda074ef9fc Mon Sep 17 00:00:00 2001 From: Abdo Date: Fri, 2 Oct 2026 01:12:41 +0300 Subject: [PATCH 4/5] Revert "Update docs" This reverts commit d76836cd41aaaad49b86dc9c97ea7e388b4a2599. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index eb4c4818..63b3ef6f 100644 --- a/README.md +++ b/README.md @@ -71,7 +71,7 @@ Each support package contains: On iOS/tvOS/watchOS/visionOS, the `Python.xcframework` contains a slice for each supported ABI (device and simulator). The folder containing the slice can also be used as a `PYTHONHOME`, as it contains a `bin`, `include` and `lib` directory. -The `bin` folder contains shell aliases for the compilers that are needed to build packages (in addition to Python executables). This is required because Xcode uses the `xcrun` alias to dynamically generate the name of binaries, but a lot of C tooling expects that `CC` will not contain spaces. +The `bin` folder does not contain Python executables (as they can't be invoked). However, it *does* contain shell aliases for the compilers that are needed to build packages. This is required because Xcode uses the `xcrun` alias to dynamically generate the name of binaries, but a lot of C tooling expects that `CC` will not contain spaces. Each slice of an iOS/tvOS/watchOS/visionOS XCframework also contains a `platform-config` folder with a subfolder for each supported architecture in that slice. These subfolders can be used to make a macOS Python environment behave as if it were on an iOS/tvOS/watchOS/visionOS device. This works in one of two ways: From 50a9e6085b231d9a840fe266123a8fbcf96d0288 Mon Sep 17 00:00:00 2001 From: Abdo Date: Fri, 2 Oct 2026 01:16:44 +0300 Subject: [PATCH 5/5] Exclude broken scripts --- patch/Python/release.macOS.exclude | 3 +++ 1 file changed, 3 insertions(+) diff --git a/patch/Python/release.macOS.exclude b/patch/Python/release.macOS.exclude index 368130b6..2acaa6c2 100644 --- a/patch/Python/release.macOS.exclude +++ b/patch/Python/release.macOS.exclude @@ -16,6 +16,9 @@ Versions/*/._include Versions/*/._lib Versions/*/._Resources Versions/*/._share +Versions/*/bin/idle* +Versions/*/bin/pydoc* +Versions/*/bin/python*-config Versions/*/etc Versions/*/Frameworks Versions/*/lib/python*/idlelib