Skip to content

Commit 18f55ce

Browse files
committed
Add support for handling XCPrivacy manifests.
1 parent 35c7e52 commit 18f55ce

File tree

5 files changed

+77
-1
lines changed

5 files changed

+77
-1
lines changed

Apple/__main__.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -577,6 +577,7 @@ def create_xcframework(platform: str) -> str:
577577

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

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

651+
# Apple identifies certain libraries as "security risks"; OpenSSL is
652+
# one of those libraries. Since we have statically linked OpenSSL into
653+
# dynamic libraries that will be converted into frameworks when an
654+
# application is built, we are also responsible for providing
655+
# .xcprivacy files for those frameworks.
656+
print(f" - {multiarch} xcprivacy files")
657+
for module, privacy in [
658+
("_hashlib", "OpenSSL"),
659+
("_ssl", "OpenSSL"),
660+
]:
661+
shutil.copy(
662+
PYTHON_DIR
663+
/ f"Apple/{platform}/Resources/{privacy}.xcprivacy",
664+
slice_path
665+
/ f"lib-{arch}/python{version_tag}/lib-dynload/{module}.xcprivacy",
666+
)
667+
650668
print(" - build tools")
651669
shutil.copytree(
652670
PYTHON_DIR / "Apple/testbed/Python.xcframework/build",
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3+
<plist version="1.0">
4+
<dict>
5+
<key>NSPrivacyAccessedAPITypes</key>
6+
<array>
7+
<dict>
8+
<key>NSPrivacyAccessedAPIType</key>
9+
<string>NSPrivacyAccessedAPICategoryFileTimestamp</string>
10+
<key>NSPrivacyAccessedAPITypeReasons</key>
11+
<array>
12+
<string>C617.1</string>
13+
</array>
14+
</dict>
15+
</array>
16+
<key>NSPrivacyCollectedDataTypes</key>
17+
<array/>
18+
<key>NSPrivacyTrackingDomains</key>
19+
<array/>
20+
<key>NSPrivacyTracking</key>
21+
<false/>
22+
</dict>
23+
</plist>

Apple/testbed/Python.xcframework/build/utils.sh

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@ install_dylib () {
6767

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

100+
# If the framework provides an xcprivacy file, install it.
101+
if [ -e "$MODULE_PATH/$MODULE_NAME.xcprivacy" ]; then
102+
echo "Installing XCPrivacy file for $FRAMEWORK_FOLDER/$FULL_MODULE_NAME"
103+
XCPRIVACY_FILE="$CODESIGNING_FOLDER_PATH/$FRAMEWORK_FOLDER/PrivacyInfo.xcprivacy"
104+
if [ -e "$XCPRIVACY_FILE" ]; then
105+
rm -rf "$XCPRIVACY_FILE"
106+
fi
107+
mv "$MODULE_PATH/$MODULE_NAME.xcprivacy" "$XCPRIVACY_FILE"
108+
fi
109+
97110
echo "Signing framework as $EXPANDED_CODE_SIGN_IDENTITY_NAME ($EXPANDED_CODE_SIGN_IDENTITY)..."
98111
/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"
99112
}

Doc/using/ios.rst

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,12 @@ App Store Compliance
328328
The only mechanism for distributing apps to third-party iOS devices is to
329329
submit the app to the iOS App Store; apps submitted for distribution must pass
330330
Apple's app review process. This process includes a set of automated validation
331-
rules that inspect the submitted application bundle for problematic code.
331+
rules that inspect the submitted application bundle for problematic code. There
332+
are some steps that must be taken to ensure that your app will be able to pass
333+
these validation steps.
334+
335+
Incompatible code in the standard library
336+
-----------------------------------------
332337

333338
The Python standard library contains some code that is known to violate these
334339
automated rules. While these violations appear to be false positives, Apple's
@@ -339,3 +344,18 @@ The Python source tree contains
339344
:source:`a patch file <Mac/Resources/app-store-compliance.patch>` that will remove
340345
all code that is known to cause issues with the App Store review process. This
341346
patch is applied automatically when building for iOS.
347+
348+
Privacy manifests
349+
-----------------
350+
351+
In April 2025, Apple introduced a requirement for `certain third-party
352+
libraries to provide a Privacy Manifest
353+
<https://developer.apple.com/support/third-party-SDK-requirements>`__.
354+
As a result, if you have a binary module that uses one of the affected
355+
libraries, you must provide an ``.xcprivacy`` file for that library.
356+
OpenSSL is one library affected by this requirement, but there are others.
357+
358+
If you produce a binary module named ``mymodule.so``, and use you the Xcode
359+
build script described in step 7 above, you can place a ``mymodule.xcprivacy``
360+
file next to ``mymodule.so``, and the privacy manifest will be installed into
361+
the required location when the binary module is converted into a framework.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
XCframeworks now include privacy manifests to satisfy Apple App Store
2+
submission requirements.

0 commit comments

Comments
 (0)