Consider this directory tree from a vendor:
OwningTheLibs/
OwningTheLibs.a
include/
OwningTheLibs/
OwningTheLibs.h
module.modulemap
The vendor will probably say "this supports iOS and iOS simulator". (As of 2019/2020 this is no longer true, but we don't need to get in to that right now.)
Run the lipo tool on the .a to get a check for its contents:
~ lipo -info OwningTheLibs/libOwningTheLibs.a
Architectures in the fat file: OwningTheLibs/libOwningTheLibs.a are: x86_64 arm64If you get Non-fat file, stop.
You cannot proceed.
Thin the binary using lipo:
~ mkdir -p device
~ mkdir -p simulator
~ lipo -thin x86_64 libOwningTheLibs.a -output simulator/libOwningTheLibs.a
~ lipo -thin arm64 libOwningTheLibs.a -output device/libOwningTheLibs.aCreate the xcframework:
xcodebuild -create-xcframework -library simulator/libOwningTheLibs.a -headers include -library device/libOwningTheLibs.a -headers include -output OwningTheLibs.xcframeworkNote: If the vendor gave you debug symbols or Bitcode maps — which is unlikely, let's be honest - add
-debug-symbolsafter any-headers. It will need to be repeated multiple times.
The resulting xcframework will look like this:
OwningTheLibs.xcframework/
ios-x86_64-simulator/
Headers/
OwningTheLibs/
OwningTheLibs.h
module.modulemap
libOwningTheLibs.a
ios-arm64/
Headers/
OwningTheLibs/
OwningTheLibs.h
module.modulemap
libOwningTheLibs.a
The resulting xcframework can be dragged into Xcode into the "Frameworks, Libraries, and Embedded Content" of a target, or embedded into a Swift package:
// swift-tools-version:5.5
// The swift-tools-version declares the minimum version of Swift required to build this package.
import PackageDescription
let package = Package(
name: "OwningThePackages",
platforms: [ .iOS(.v14) ],
products: [
.library(
name: "OwningThePackages",
targets: ["OwningThePackages"]),
],
targets: [
.target(
name: "OwningThePackages",
dependencies: ["OwningTheLibs"]),
.binaryTarget(
name: "OwningTheLibs",
path: "OwningTheLibs.xcframework")
]
)