diff --git a/darwin/package-macos-for-dart.sh b/darwin/package-macos-for-dart.sh index cc608ff..502a956 100755 --- a/darwin/package-macos-for-dart.sh +++ b/darwin/package-macos-for-dart.sh @@ -34,12 +34,34 @@ mkdir -p $stdlib_dir # copy Python.xcframework rsync -av --exclude-from=$script_dir/python-darwin-framework.exclude $python_apple_support_root/support/$python_version_short/macOS/Python.xcframework $frameworks_dir -cp -r $script_dir/Modules $frameworks_dir/Python.xcframework/macos-arm64_x86_64/Python.framework -mkdir -p $frameworks_dir/Python.xcframework/macos-arm64_x86_64/Python.framework/Headers -cp -r $python_apple_support_root/support/$python_version_short/macOS/Python.xcframework/macos-arm64_x86_64/Python.framework/Versions/$python_version_short/include/python$python_version_short/* $frameworks_dir/Python.xcframework/macos-arm64_x86_64/Python.framework/Headers +# Overlay the module map and public headers. +# +# macOS frameworks are VERSIONED bundles: everything at the framework root must be +# a symlink into Versions/Current, and only `Versions` itself is a real directory. +# These used to be written as real directories at the root, which codesign rejects +# outright once the framework is signed in its own right: +# +# Python.framework: unsealed contents present in the root directory of an +# embedded framework +# +# That went unnoticed while only the outer xcframework was signed. Write them into +# Versions/Current and symlink from the root, which is both what codesign requires +# and what CPython's own macOS framework does for Headers and Resources. +macos_fw=$frameworks_dir/Python.xcframework/macos-arm64_x86_64/Python.framework +[ -d "$macos_fw/Versions/Current" ] || { + echo "expected a versioned macOS framework at $macos_fw"; exit 1; } + +cp -r $script_dir/Modules "$macos_fw/Versions/Current/" +mkdir -p "$macos_fw/Versions/Current/Headers" +cp -r $python_apple_support_root/support/$python_version_short/macOS/Python.xcframework/macos-arm64_x86_64/Python.framework/Versions/$python_version_short/include/python$python_version_short/* "$macos_fw/Versions/Current/Headers" # The built-in modulemap (if the source framework shipped one) is replaced by the # overlaid darwin/Modules/module.modulemap above; -f tolerates builds without one. -rm -f $frameworks_dir/Python.xcframework/macos-arm64_x86_64/Python.framework/Headers/module.modulemap +rm -f "$macos_fw/Versions/Current/Headers/module.modulemap" + +for _d in Headers Modules; do + rm -rf "$macos_fw/$_d" + ln -sfn "Versions/Current/$_d" "$macos_fw/$_d" +done # Last mutation of the bundle: stable, provider-owned identifier for the Python # runtime, replacing CPython's shared `org.python.python`. The macOS framework is diff --git a/darwin/xcframework_signing.sh b/darwin/xcframework_signing.sh index 414f2e4..eda83bf 100644 --- a/darwin/xcframework_signing.sh +++ b/darwin/xcframework_signing.sh @@ -285,7 +285,12 @@ xcf_verify_one() { local fw count=0 while IFS= read -r fw; do [ -n "$fw" ] || continue - if [ ! -d "$fw/_CodeSignature" ] && [ ! -d "$fw/Versions/A/_CodeSignature" ]; then + # `codesign -dv` rather than probing for a _CodeSignature directory: a + # versioned bundle keeps it at Versions//_CodeSignature, and the + # version directory is not always "A" (CPython's macOS framework uses the + # Python version, e.g. Versions/3.14). codesign exits non-zero with + # "code object is not signed at all", which is the question being asked. + if ! codesign -dv "$fw" >/dev/null 2>&1; then xcf_err "$fw: inner framework is unsigned" return 1 fi