Apple does not provide an easy way to generate universal frameworks using Xcode alone. Because of this, developers generally write a shell script to build the frameworks for simulators and devices. We then use the “lipo” command to combine the different architectures into one universal framework. Prior to app submission to the App and Play stores, developers execute a script to remove the unnecessary architectures. While this approach works well it raises the following important questions:
What will happen if Apple removes this command utility?
Without using the “lipo” command, Xcode allows developers to link separate frameworks for simulators and devices in the following way using xcconfigs:
OTHER_LDFLAGS[sdk=iphoneos*] = -framework Test.framework OTHER_LDFLAGS[sdk=iphonesimulator*] = -framework Test.framework
The advantage to this method is if Apple ever removes the “lipo” command from MAC OS X, developers won’t need to change anything. Plus developers won’t be required to use a tool or utility which isn’t explicitly documented and supported by Apple.
However, if we have three variants, we will need to distribute six different frameworks which increases the effort required to maintain the distributions. Moreover, this approach does not work with the cocoapods because there is no easy way to specify which pod should be installed for which simulator or device.
Does Apple itself use the lipo command?
To answer this question, I conducted two experiments with a sample project built against a Release configuration and a Generic iOS Device.
Dynamic framework using Objective-C language
Dynamic framework using swift language
By looking at these screenshots, we can clearly say Apple uses the lipo command. We can then say with fairly high confidence that it isn’t likely this command utility will be removed in the near future.
What is the impact on performance of the build process?
To verify the performance of using the lipo command, I performed the following experiments. (To capture the script run time, I used the “time” command built into OS X.)
Calculate the time to combine the architectures
I created a script that executes the “lipo” command only to combine architectures.
#!/bin/bash #Script to combine architectures. time lipo -create -output \ "universal/Test.framework/Test" \ "iphoneos/Test.framework/Test"\ "iphonesimulator/Test.framework/Test"
real 0m 0.021s user 0m 0.003s sys 0m 0.008s
Calculate the time to remove simulator architectures
I created a script that executes the “lipo” command only to remove architectures.
#!/bin/bash #Remove i386 architecture lipo -remove i386 \ "universal/Test.framework/Test" \ -output "universal/Test.framework/Test" #Remove x86_64 architecture lipo -remove x86_64 \ "universal/Test.framework/Test" \ -output "universal/Test.framework/Test"
real 0m 0.036s user 0m 0.004s sys 0m 0.012s
According to these results, the average time to combine and remove architectures is 21ms and 36ms, respectively.
Since, Apple uses it in Xcode already, developers can also use the “lipo” command to combine or remove architectures. As a bonus, it has an unnoticeable impact on the performance of the app build process.