Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
20 changes: 19 additions & 1 deletion Apple/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ def unpack_deps(
for name_ver in [
"BZip2-1.0.8-2",
"libFFI-3.4.7-2",
"OpenSSL-3.0.16-2",
"OpenSSL-3.0.17-1",
"XZ-5.6.4-2",
"mpdecimal-4.0.0-2",
"zstd-1.5.7-1",
Expand Down Expand Up @@ -577,6 +577,7 @@ def create_xcframework(platform: str) -> str:

# Extract the package version from the merged framework
version = package_version(package_path / "Python.xcframework")
version_tag = ".".join(version.split(".")[:2])

# On non-macOS platforms, each framework in XCframework only contains the
# headers, libPython, plus an Info.plist. Other resources like the standard
Expand Down Expand Up @@ -647,6 +648,23 @@ def create_xcframework(platform: str) -> str:
slice_framework / f"Headers/pyconfig-{arch}.h",
)

# Apple identifies certain libraries as "security risks"; if you
# statically link those libraries into a Framework, you become
# responsible for providing a privacy manifest for that framework.
xcprivacy_file = {
"OpenSSL": subdir(host_triple) / "prefix/share/OpenSSL.xcprivacy"
}
print(f" - {multiarch} xcprivacy files")
for module, lib in [
("_hashlib", "OpenSSL"),
("_ssl", "OpenSSL"),
]:
shutil.copy(
xcprivacy_file[lib],
slice_path
/ f"lib-{arch}/python{version_tag}/lib-dynload/{module}.xcprivacy",
)

print(" - build tools")
shutil.copytree(
PYTHON_DIR / "Apple/testbed/Python.xcframework/build",
Expand Down
13 changes: 13 additions & 0 deletions Apple/testbed/Python.xcframework/build/utils.sh
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@ install_dylib () {

# The name of the extension file
EXT=$(basename "$FULL_EXT")
# The name and location of the module
MODULE_PATH=$(dirname "$FULL_EXT")
MODULE_NAME=$(echo $EXT | cut -d "." -f 1)
# The location of the extension file, relative to the bundle
RELATIVE_EXT=${FULL_EXT#$CODESIGNING_FOLDER_PATH/}
# The path to the extension file, relative to the install base
Expand Down Expand Up @@ -94,6 +97,16 @@ install_dylib () {
# Create a back reference to the .so file location in the framework
echo "${RELATIVE_EXT%.so}.fwork" > "$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER/$FULL_MODULE_NAME.origin"

# If the framework provides an xcprivacy file, install it.
if [ -e "$MODULE_PATH/$MODULE_NAME.xcprivacy" ]; then
echo "Installing XCPrivacy file for $FRAMEWORK_FOLDER/$FULL_MODULE_NAME"
XCPRIVACY_FILE="$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER/PrivacyInfo.xcprivacy"
if [ -e "$XCPRIVACY_FILE" ]; then
rm -rf "$XCPRIVACY_FILE"
fi
mv "$MODULE_PATH/$MODULE_NAME.xcprivacy" "$XCPRIVACY_FILE"
fi

echo "Signing framework as $EXPANDED_CODE_SIGN_IDENTITY_NAME ($EXPANDED_CODE_SIGN_IDENTITY)..."
/usr/bin/codesign --force --sign "$EXPANDED_CODE_SIGN_IDENTITY" ${OTHER_CODE_SIGN_FLAGS:-} -o runtime --timestamp=none --preserve-metadata=identifier,entitlements,flags --generate-entitlement-der "$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER"
}
Expand Down
22 changes: 21 additions & 1 deletion Doc/using/ios.rst
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,12 @@ App Store Compliance
The only mechanism for distributing apps to third-party iOS devices is to
submit the app to the iOS App Store; apps submitted for distribution must pass
Apple's app review process. This process includes a set of automated validation
rules that inspect the submitted application bundle for problematic code.
rules that inspect the submitted application bundle for problematic code. There
are some steps that must be taken to ensure that your app will be able to pass
these validation steps.

Incompatible code in the standard library
-----------------------------------------

The Python standard library contains some code that is known to violate these
automated rules. While these violations appear to be false positives, Apple's
Expand All @@ -339,3 +344,18 @@ The Python source tree contains
:source:`a patch file <Mac/Resources/app-store-compliance.patch>` that will remove
all code that is known to cause issues with the App Store review process. This
patch is applied automatically when building for iOS.

Privacy manifests
-----------------

In April 2025, Apple introduced a requirement for `certain third-party
libraries to provide a Privacy Manifest
<https://developer.apple.com/support/third-party-SDK-requirements>`__.
As a result, if you have a binary module that uses one of the affected
libraries, you must provide an ``.xcprivacy`` file for that library.
OpenSSL is one library affected by this requirement, but there are others.

If you produce a binary module named ``mymodule.so``, and use you the Xcode
build script described in step 7 above, you can place a ``mymodule.xcprivacy``
file next to ``mymodule.so``, and the privacy manifest will be installed into
the required location when the binary module is converted into a framework.
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
XCframeworks now include privacy manifests to satisfy Apple App Store
submission requirements.
Loading