Transformation for Silicon:

Overcoming technical challenges with the new Apple Silicon M1 chips

Transformation for silicon

Overcoming technical challenges with the new Apple Silicon M1 chips

In 2020 MONDIRAAN DC got accepted to the Apple Universal App Quick Start Program and received a new Apple Silicon Mac Mini device with the new ARM-based M1 processor for testing purposes. Thanks to this we were able to quickly solve an unexpected technical problem that was arising when the M1 chip-based Apple computers went live.

MONDRIAAN is developing a large-scale push notification service for a leading Scandinavian media group, Sanoma in Finland (check out our case studies with them in details here). One of the iOS developers working on the group’s iOS media apps run into some obstacles running this media app on the simulator while having the push notification library in it.

As it turned out our Client’s developer has just received a new Apple computer also equipped with the ARM-based M1 chip.

Our iOS platform lead recounts the story of how this technical challenge was overcome:

We have an iOS library, which is used for push notification handling. One of our client reached out to us with an error: when he tried to compile his app (containing our library) on the new Apple Silicon M1 computer, he got an error like this one:

building for iOS Simulator, but linking in object file built for iOS, file ‘/Users/dev2/Documents/SPNS/SPNSSDKTest/Pods/SPNS/SPNS/libSPNSCommon.a’ for architecture arm64
building for iOS Simulator, but linking in object file built for iOS, file ‘/Users/dev2/Documents/SPNS/SPNSSDKTest/Pods/SPNS/SPNS/libSPNSCommon.a’ for architecture arm64

Not so promising.

Our SDK is a fat static lib. This means: a single binary contains all necessary architectures for the iOS device and for the simulator:
For devices: armv7 and arm64
For simulator: i386 ans x86_64
We can build only for one target: either for device or for simulator. So we have to build a lib for device and a lib for simulator separately. After building, we create a single library with the lipo command. This will contain all architectures we need and this is the fat library.

Thanks to Apple Universal App Quick Start Program (https://developer.apple.com/programs/universal/), we were able to reproduce the error on Apple Silicon (with arm64 chipset). Here is the error message again:

building for iOS Simulator, but linking in object file built for iOS, file ‘/Users/dev2/Documents/SPNS/SPNSSDKTest/Pods/SPNS/SPNS/libSPNSCommon.a’ for architecture arm64
This means we will need the arm64 architecture compiled for simulator as well (because the Apple Silicon has arm64 chipset, not x86_64). So we need the following architectures:
For devices: armv7 and arm64
For simulator: i386 ans x86_64 arm64

Here is our build script:

xcodebuild -configuration “iphoneos” -target “${LIB_NAME}” -sdk iphoneos
xcodebuild -configuration “iphonesimulator” -target “${LIB_NAME}” -sdk iphonesimulator
All we needed is to add arm64 to VALID_ARCHITECTURES, so we’ll have the arm64 architecture for simulator sdk as well:
We could think we solved the problem but when creating the fat library with script:
lipo -create “${DEVICE_DIR}/lib${LIB_NAME}.a” “${SIMULATOR_DIR}/lib${LIB_NAME}.a” -output “${INSTALL_DIR}/include/${LIB_NAME}/lib${LIB_NAME}.a”
The following error occurred:
fatal error: lipo: build/iphoneos-iphoneos/libSPNS.a and build/iphonesimulator-iphonesimulator/libSPNS.a have the same architectures (arm64) and can’t be in the same fat output file
This was pretty annoying as we need the compiled arm64 architecture both for device and for simulator. To overcome this issue, there were couple of possibilities:
– build separate libs with different names
– force our users to use Rosetta on Apple Silicon
– repackage our libs in an XCFamework. The recently introduced XCFamework can contain the same architecture more than once. This is a great advantage compared to the fat lib which can contain one architecture only once. And as we need our lib compiled to arm64 architecture both for device and simulator, XCFramework can suit our needs.

We chose the XCFramework as this is the cleanest solution.

So instead of creating a fat library, we created an XCFramework package:

xcodebuild -create-xcframework \
-library “${DEVICE_DIR}/lib${LIB_NAME}.a” \
-headers “${DEVICE_DIR}/include/${LIB_NAME}” \
-library “${SIMULATOR_DIR}/lib${LIB_NAME}.a” \
-headers “${SIMULATOR_DIR}/include/${LIB_NAME}” \
-output “${INSTALL_DIR}/include/${LIB_NAME}/lib${LIB_NAME}.xcframework”
Here is the outcome:
So whe have the arm64 architecture for simulator and for device targets.
As we distribute our SDK via cocoapods, we had to modify our podspec file.
We had:
s.subspec ‘Core’ do |core|
core.source_files = ‘SPNS/*.{h}’
core.vendored_libraries = ‘SPNS/libSPNS.a’
end
And now we have:
s.subspec ‘Core’ do |core|
core.source_files = ‘SPNS/libSPNS.xcframework/ios-arm64_armv7/Headers/*.{h}’
core.vendored_frameworks = ‘SPNS/libSPNS.xcframework’
end
That’s it.
It was a huge help to be able to investigate and try the outcome on an actual Apple Silicon device.
On client side, all the developers have to do is increment the version number in the podfile and run pod install.

In 2020 MONDIRAAN DC got accepted to the Apple Universal App Quick Start Program and received a new Apple Silicon Mac Mini device with the new ARM-based M1 processor for testing purposes. Thanks to this we were able to quickly solve an unexpected technical problem that was arising when the M1 chip-based Apple computers went live.

MONDRIAAN is developing a large-scale push notification service for a leading Scandinavian media group, Sanoma in Finland (check out our case studies with them in details here). One of the iOS developers working on the group’s iOS media apps run into some obstacles running this media app on the simulator while having the push notification library in it.

As it turned out our Client’s developer has just received a new Apple computer also equipped with the ARM-based M1 chip.

Our iOS platform lead recounts the story of how this technical challenge was overcome:We have an iOS library, which is used for push notification handling. One of our client reached out to us with an error: when he tried to compile his app (containing our library) on the new Apple Silicon M1 computer, he got an error like this one:

building for iOS Simulator, but linking in object file built for iOS, file ‘/Users/dev2/Documents/SPNS/SPNSSDKTest/Pods/SPNS/SPNS/libSPNSCommon.a’ for architecture arm64
building for iOS Simulator, but linking in object file built for iOS, file ‘/Users/dev2/Documents/SPNS/SPNSSDKTest/Pods/SPNS/SPNS/libSPNSCommon.a’ for architecture arm64

Not so promising.

Our SDK is a fat static lib. This means: a single binary contains all necessary architectures for the iOS device and for the simulator:
For devices: armv7 and arm64
For simulator: i386 ans x86_64
We can build only for one target: either for device or for simulator. So we have to build a lib for device and a lib for simulator separately. After building, we create a single library with the lipo command. This will contain all architectures we need and this is the fat library.

Thanks to Apple Universal App Quick Start Program (https://developer.apple.com/programs/universal/), we were able to reproduce the error on Apple Silicon (with arm64 chipset). Here is the error message again:

building for iOS Simulator, but linking in object file built for iOS, file ‘/Users/dev2/Documents/SPNS/SPNSSDKTest/Pods/SPNS/SPNS/libSPNSCommon.a’ for architecture arm64
This means we will need the arm64 architecture compiled for simulator as well (because the Apple Silicon has arm64 chipset, not x86_64). So we need the following architectures:
For devices: armv7 and arm64
For simulator: i386 ans x86_64 arm64

Here is our build script:

xcodebuild -configuration “iphoneos” -target “${LIB_NAME}” -sdk iphoneos
xcodebuild -configuration “iphonesimulator” -target “${LIB_NAME}” -sdk iphonesimulator
All we needed is to add arm64 to VALID_ARCHITECTURES, so we’ll have the arm64 architecture for simulator sdk as well:
We could think we solved the problem but when creating the fat library with script:
lipo -create “${DEVICE_DIR}/lib${LIB_NAME}.a” “${SIMULATOR_DIR}/lib${LIB_NAME}.a” -output “${INSTALL_DIR}/include/${LIB_NAME}/lib${LIB_NAME}.a”
The following error occurred:
fatal error: lipo: build/iphoneos-iphoneos/libSPNS.a and build/iphonesimulator-iphonesimulator/libSPNS.a have the same architectures (arm64) and can’t be in the same fat output file
This was pretty annoying as we need the compiled arm64 architecture both for device and for simulator. To overcome this issue, there were couple of possibilities:
– build separate libs with different names
– force our users to use Rosetta on Apple Silicon
– repackage our libs in an XCFamework. The recently introduced XCFamework can contain the same architecture more than once. This is a great advantage compared to the fat lib which can contain one architecture only once. And as we need our lib compiled to arm64 architecture both for device and simulator, XCFramework can suit our needs.

We chose the XCFramework as this is the cleanest solution.

So instead of creating a fat library, we created an XCFramework package:

xcodebuild -create-xcframework \
-library “${DEVICE_DIR}/lib${LIB_NAME}.a” \
-headers “${DEVICE_DIR}/include/${LIB_NAME}” \
-library “${SIMULATOR_DIR}/lib${LIB_NAME}.a” \
-headers “${SIMULATOR_DIR}/include/${LIB_NAME}” \
-output “${INSTALL_DIR}/include/${LIB_NAME}/lib${LIB_NAME}.xcframework”
Here is the outcome:
So whe have the arm64 architecture for simulator and for device targets.
As we distribute our SDK via cocoapods, we had to modify our podspec file.
We had:
s.subspec ‘Core’ do |core|
core.source_files = ‘SPNS/*.{h}’
core.vendored_libraries = ‘SPNS/libSPNS.a’
end
And now we have:
s.subspec ‘Core’ do |core|
core.source_files = ‘SPNS/libSPNS.xcframework/ios-arm64_armv7/Headers/*.{h}’
core.vendored_frameworks = ‘SPNS/libSPNS.xcframework’
end
That’s it.
It was a huge help to be able to investigate and try the outcome on an actual Apple Silicon device.
On client side, all the developers have to do is increment the version number in the podfile and run pod install.

If you have faced similar challenges with your mobile development projects we would love to hear your story and assist in solving it with our development team.

If you have faced similar challenges with your mobile development projects we would love to hear your story and assist in solving it with our development team.