XCFramework — бинарный формат Apple, объединяющий библиотеки для iOS, macOS, tvOS и watchOS в одном пакете. Разработан для замены .framework и устранения проблем fat binaries при сборке под разные архитектуры симулятора и устройства. По данным Apple WWDC 2019, XCFramework стал обязательным форматом для поставки SDK, поддерживающих несколько платформ, и полностью заменил устаревший подход с универсальными бинарниками.
Главное
XCFramework — формат упаковки бинарных библиотек и фреймворков, представленный Apple на WWDC 2019. Основная цель — создание одного bundle, который содержит скомпилированные версии библиотеки для всех целевых платформ и архитектур.
До появления XCFramework разработчики использовали .framework с fat binary, объединяющим несколько архитектур через утилиту lipo. Этот подход создавал проблемы: при сборке проекта для симулятора fat binary содержал и архитектуру симулятора, и устройства, что приводило к ошибкам при отправке сборки в App Store. Разработчикам приходилось писать Run Script фазы для удаления ненужных архитектур.
По данным Apple Developer Documentation (2024), XCFramework поддерживает все платформы экосистемы Apple: iOS, iPadOS, macOS, tvOS, watchOS, visionOS и катализаторные приложения. Каждая платформа получает отдельный срез внутри пакета, что исключает конфликты архитектур и упрощает распространение SDK.
XCFramework применяется в трёх основных сценариях: поставка закрытых SDK сторонним разработчикам, распространение нативных модулей для Flutter и React Native, и публикация библиотек, требующих предварительной компиляции. Формат обязателен для всех новых SDK, публикуемых в экосистеме Apple.
Разработчики выбирают XCFramework когда исходный код нельзя раскрывать, когда библиотека использует проприетарные алгоритмы или когда требуется лицензионная защита. В отличие от Swift Package Manager, который работает с исходным кодом, XCFramework поставляет уже скомпилированные бинарные файлы.
Проблема fat binary заключалась в том, что универсальный бинарник содержал несколько архитектур в одном Mach-O файле. При сборке приложения для симулятора Xcode включал в бинарник архитектуру arm64 устройства и x86_64 симулятора — App Store принимал только архитектуру устройства.
Традиционное решение включало добавление Run Script фазы с вызовом lipo для удаления симуляторных архитектур из итоговой сборки. Этот подход был хрупким и ломался при обновлениях Xcode или при добавлении новых архитектур (например, arm64 для симулятора на Apple Silicon).
По данным Swift.org (2023), команда Swift Package Manager изначально столкнулась с этой проблемой при попытке поддерживать бинарные зависимости. XCFramework решил её на уровне формата: каждый срез — отдельная папка с Info.plist, описывающим целевую платформу и архитектуру. Xcode автоматически выбирает нужный срез при сборке, не требуя пост-обработки.
Каждый срез в XCFramework содержит только одну комбинацию платформы и архитектуры. Например, ios-arm64 содержит бинарник только для устройств iOS, а ios-x86_64-simulator — только для симулятора Intel Mac. Xcode автоматически выбирает правильный срез, исключая необходимость в скриптах удаления архитектур и снижая риск ошибок сборки.
Срез ios-arm64-x86_64-simulator появился для поддержки Apple Silicon Mac. Ранее для симулятора требовался отдельный бинарник под arm64 (Apple Silicon) и x86_64 (Intel). XCFramework допускает fat binary внутри одного среза для симулятора — это единственное исключение, когда fat binary оправдан.
Пакет XCFramework представляет собой директорию с расширением .xcframework, содержащую Info.plist на верхнем уровне и папки с бинарными срезами. Каждый срез включает .framework или .a библиотеку для конкретной платформы.
MyLibrary.xcframework/
Info.plist
ios-arm64/
MyLibrary.framework/
Info.plist
MyLibrary
ios-x86_64-simulator/
MyLibrary.framework/
Info.plist
MyLibrary
macos-arm64-x86_64/
MyLibrary.framework/
Info.plist
MyLibrary
Info.plist пакета содержит ключ AvailableLibraries, перечисляющий идентификаторы LibraryIdentifier, LibraryPath и SupportedPlatform для каждого среза. Xcode читает этот файл при добавлении XCFramework в проект и автоматически конфигурирует пути поиска и фазу Embed Frameworks.
Каждый срез представляет собой полноценный .framework или статическую библиотеку с собственным Info.plist. Это позволяет XCFramework поддерживать смешанные типы: статические библиотеки для одних платформ и динамические фреймворки для других, хотя на практике чаще используется один тип для всех срезов.
Создание XCFramework выполняется через xcodebuild -create-xcframework. Команда принимает на вход уже собранные .framework или .a библиотеки для каждой платформы и объединяет их в единый пакет.
Процесс состоит из двух шагов: сначала собираются бинарники под каждую целевую платформу, затем они упаковываются в XCFramework. Для сборки используются стандартные destination флаги Xcode.
# Step 1: build frameworks for each platform
xcodebuild archive -scheme MyLibrary -destination "generic/platform=iOS Simulator"
xcodebuild archive -scheme MyLibrary -destination "generic/platform=iOS"
xcodebuild archive -scheme MyLibrary -destination "generic/platform=macOS"
# Step 2: create XCFramework
xcodebuild -create-xcframework -framework ./iOS/MyLibrary.framework -framework ./iOSSim/MyLibrary.framework -framework ./macOS/MyLibrary.framework -output ./MyLibrary.xcframework
Флаг -create-xcframework появился в Xcode 11. Команда автоматически создаёт правильную структуру директорий и генерирует Info.plist с описанием всех платформ. Если один из .framework повреждён или собран с неправильной архитектурой, xcodebuild выдаёт ошибку на этапе валидации.
Для CI/CD используется shell-скрипт, автоматизирующий сборку под все платформы и создание XCFramework. Популярный подход — обёртка в виде Makefile или Fastlane лейна с параметризацией scheme и output path.
# build_xcframework.sh - automation script
set -e
SCHEME="MyLibrary"
OUTPUT="./build"
xcodebuild archive -scheme "$SCHEME" -sdk iphonesimulator -archivePath "$OUTPUT/sim.xcarchive"
xcodebuild archive -scheme "$SCHEME" -sdk iphoneos -archivePath "$OUTPUT/dev.xcarchive"
xcodebuild -create-xcframework -framework "$OUTPUT/dev.xcarchive/Products/Library/Frameworks/MyLibrary.framework" -framework "$OUTPUT/sim.xcarchive/Products/Library/Frameworks/MyLibrary.framework" -output "$OUTPUT/MyLibrary.xcframework"
Такой скрипт выполняется в CI-пайплайне (GitHub Actions, Bitrise, Jenkins) после прогона тестов. Результирующий XCFramework архивируется и загружается как артефакт релиза или публикуется через менеджер зависимостей вроде CocoaPods с помощью pod spec.
Подключение XCFramework в Xcode-проект не требует ручного конфигурирования путей поиска. Достаточно перетащить .xcframework в секцию Frameworks, Libraries, and Embedded Content в General настройках target.
В отличие от .framework, XCFramework не требует добавления Run Script фазы для удаления симуляторных архитектур. Xcode автоматически определяет доступные срезы и включает только нужные для текущей схемы сборки. Для физического устройства используется срез ios-arm64, для симулятора — ios-arm64-x86_64-simulator или ios-x86_64-simulator.
import MyLibrary
func processData() {
// XCFramework resolves the correct slice at build time
let processor = DataProcessor()
let result = processor.analyze(input: "sample")
print(result)
}
Для CocoaPods интеграция происходит через podspec с указанием vendored_frameworks и списком поддерживаемых платформ. Менеджер зависимостей автоматически определяет, какие срезы нужны для проекта. Многие коммерческие SDK — Firebase, Adjust, AppsFlyer — перешли на XCFramework для упрощения установки.
Swift Package Manager и XCFramework не конкурируют, а дополняют друг друга. SPM работает с исходным кодом и собирает зависимости при каждой сборке проекта. XCFramework предоставляет готовые бинарники, не требуя компиляции на стороне потребителя.
С выходом Swift Package Manager 5.3 Apple добавила поддержку бинарных зависимостей — теперь SPM может загружать XCFramework как удалённую зависимость. Package.swift указывает URL на бинарный артефакт и его контрольную сумму для верификации.
По данным Swift Package Manager documentation (2024), бинарные зависимости рекомендуется использовать для SDK, которые не раскрывают исходный код, или для библиотек, чья сборка занимает непропорционально много времени. Для open-source проектов предпочтительна поставка исходным кодом через SPM.
| Критерий | XCFramework | Swift Package Manager |
|---|---|---|
| Формат | Бинарный (.xcframework) | Исходный код |
| Защита кода | Полная | Нет |
| Время сборки | Минимальное (копирование) | Зависит от объёма кода |
| Гибкость платформ | Все Apple платформы | Зависит от Package.swift |
| Интеграция | Drag-and-drop или SPM | Package.swift |
Часто задаваемые вопросы
.framework — устаревший формат, содержащий fat binary с архитектурами устройства и симулятора. XCFramework хранит каждый срез отдельно, исключая конфликты архитектур при сборке. Apple рекомендует XCFramework для всех новых проектов и миграции существующих.
CocoaPods поддерживает XCFramework начиная с версии 1.9. В podspec достаточно указать spec.vendored_frameworks и spec.static_framework. Менеджер автоматически разрешает зависимости, учитывая доступные срезы для платформы проекта.
Apple не удаляет поддержку .framework, но для новых SDK рекомендует исключительно XCFramework. При отправке приложения в App Store с fat binary в старом формате возможны ошибки Invalid Bundle из-за симуляторных архитектур, что делает XCFramework практической необходимостью.
Начиная с Swift 5.3, бинарные зависимости в SPM используют XCFramework. Package.swift указывает url и checksum бинарного пакета. SPM загружает, проверяет целостность и подключает XCFramework как системную зависимость без компиляции исходного кода.
visionOS поддерживается в XCFramework начиная с Xcode 15. На WWDC 2023 Apple подтвердила, что формат расширен для Apple Vision Pro. Срез для visionOS имеет SupportedPlatform = xros и включает архитектуру arm64.
Итоги
Мы разработаем мобильное приложение под ключ
IT Sectr создаёт приложения для iOS и Android для стартапов и бизнеса с 2017 года. Мы проконсультируем вас и предложим наилучшее решение.