Building an iOS Universal Static Library or XCFramework
The Chilkat iOS download includes a separate static library for each supported architecture slice. This page shows how to combine those slices correctly — either into universal static libraries or into a modern XCFramework.
Jump to: Library layout Recommended outputs Device lib Simulator lib XCFramework Full script Don't mix slices Inspect a slice
- Combine device slices with other device slices.
- Combine simulator slices with other simulator slices.
- Never combine device and simulator slices into one traditional
.afile.
Chilkat iOS library layout
The download contains static libraries organized by architecture slice:
lib/ ├─ arm64/ libchilkatIos.a device ├─ arm64e/ libchilkatIos.a device, A12 and later ├─ armv7/ libchilkatIos.a older 32-bit device ├─ armv7s/ libchilkatIos.a older 32-bit device ├─ arm64-sim/ libchilkatIos.a simulator on Apple Silicon └─ x86_64/ libchilkatIos.a simulator on Intel
The important distinction is not only the CPU architecture, but also the
Apple platform the slice was built for. For example, arm64 and
arm64-sim are both ARM64, yet they are not interchangeable —
one targets physical iOS devices and the other targets the iOS Simulator.
| Slice | Platform |
|---|---|
arm64 | iOS device |
arm64-sim | iOS Simulator on Apple Silicon |
x86_64 | iOS Simulator on Intel |
Recommended outputs
There are two good ways to package the Chilkat iOS static libraries.
Option 1 — Two universal static libraries
Build one library for device and one for the simulator, and link whichever matches your current build target.
| Library | Used for |
|---|---|
libchilkatIos.a | Physical iPhone / iPad |
libchilkatSimIos.a | iOS Simulator |
Option 2 — XCFramework
Package both libraries into Chilkat.xcframework. Xcode
automatically selects the right binary for each build, so this is usually the
best format for modern projects.
Build the iOS device universal library
Combine only the device slices:
cd lib /usr/bin/libtool -static \ arm64/libchilkatIos.a \ arm64e/libchilkatIos.a \ armv7/libchilkatIos.a \ armv7s/libchilkatIos.a \ -o libchilkatIos.a cd ..
This creates lib/libchilkatIos.a, for use when building for a physical
iOS device.
Build the iOS Simulator universal library
Combine only the simulator slices:
cd lib /usr/bin/libtool -static \ arm64-sim/libchilkatIos.a \ x86_64/libchilkatIos.a \ -o libchilkatSimIos.a cd ..
This creates lib/libchilkatSimIos.a, for use when building for the
iOS Simulator.
Build an XCFramework
After creating the separate device and simulator static libraries, package them
into an XCFramework. You also supply the Chilkat public header directory —
replace include below with the actual path to the Chilkat headers.
xcodebuild -create-xcframework \ -library lib/libchilkatIos.a -headers include \ -library lib/libchilkatSimIos.a -headers include \ -output Chilkat.xcframework
The resulting Chilkat.xcframework can be added to an Xcode project as
a binary dependency.
-headers option must point to the directory containing the
Chilkat .h files (for example include or
/path/to/chilkat/include) — not at a single header file.
Complete example script
This script builds the device library, builds the simulator library, and packages both into an XCFramework.
#!/bin/bash set -e # Run from the directory that contains lib/ and include/, # where lib/ holds the Chilkat architecture slices and # include/ holds the Chilkat header files. rm -f lib/libchilkatIos.a rm -f lib/libchilkatSimIos.a rm -rf Chilkat.xcframework echo "Building iOS device universal static library..." /usr/bin/libtool -static \ lib/arm64/libchilkatIos.a \ lib/arm64e/libchilkatIos.a \ lib/armv7/libchilkatIos.a \ lib/armv7s/libchilkatIos.a \ -o lib/libchilkatIos.a echo "Building iOS Simulator universal static library..." /usr/bin/libtool -static \ lib/arm64-sim/libchilkatIos.a \ lib/x86_64/libchilkatIos.a \ -o lib/libchilkatSimIos.a echo "Building XCFramework..." xcodebuild -create-xcframework \ -library lib/libchilkatIos.a -headers include \ -library lib/libchilkatSimIos.a -headers include \ -output Chilkat.xcframework echo "Done."
/usr/bin/libtool explicitly on purpose. A different
libtool (from Homebrew, MacPorts, etc.) may take precedence on your
PATH and will not produce a valid static library. Verify with
which libtool.
What happens if device and simulator slices are mixed
.a mixes
different Apple platforms into a single library:
# WRONG — mixes device (arm64/armv7) with simulator (arm64-sim/x86_64) /usr/bin/libtool -static \ arm64/libchilkatIos.a \ arm64-sim/libchilkatIos.a \ x86_64/libchilkatIos.a \ armv7/libchilkatIos.a \ armv7s/libchilkatIos.a \ -o libchilkatIos.a
The linker may then fail with an error similar to:
ld: building for iOS Simulator, but linking in object file built for iOS
or:
ld: building for iOS Simulator, but linking in object file built for macOS, for architecture x86_64
The exact wording varies, but the cause is the same: the app is built for one platform while the linker found an object file built for another.
Why architecture alone is not enough
A slice is identified by its CPU architecture and its target platform. The same architecture name can refer to more than one platform:
| Architecture | Possible platforms |
|---|---|
arm64 | iOS device, iOS Simulator, macOS |
x86_64 | iOS Simulator, macOS |
These are different build targets and cannot be freely mixed simply because the architecture name matches.
Inspecting a static library slice
To confirm what platform a slice was built for, inspect its load commands:
otool -lv libchilkatIos.a
Look for platform-related load commands such as:
LC_BUILD_VERSION LC_VERSION_MIN_IPHONEOS LC_VERSION_MIN_MACOSX
A device library should identify as an iOS device build, and a simulator library
should identify as an iOS Simulator build — a simulator slice should not appear
as a macOS slice merely because it uses x86_64 or arm64.
Summary
- Build two separate universal static libraries:
libchilkatIos.a(device) andlibchilkatSimIos.a(simulator). - Combine device slices with device slices, and simulator slices with simulator slices — keep the two binaries separate.
- For modern Xcode projects, package both into
Chilkat.xcframeworkso Xcode picks the correct binary automatically.