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 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.