Which extra settings in Xcode are applied when Archiving? - ios

I have an iOS project. In response to Build (with a release configuration selected in the scheme) the dsym for it weighs in at 6.5MB. However, when I Archive (with the same configuration selected in the scheme) it weighs in at only 2.9MB.
This is not an academic problem. The missing data includes all the symbols for my static libraries, which is making my crash logs a lot less useful.
Which settings could account for a difference between a Build and Archive with the same configuration selected?
This is with Xcode 5.0, though I think I've been having this problem for a while.

I believe a few things it does are:
Remove all debugging symbols from the app to the .dsym file
Compresses various articles from ascii to binary (such as strings
files)
Some of the differences may be from the following build flags:
DEPLOYMENT_POSTPROCESSING=YES
STRIP_INSTALLED_PRODUCT=YES
SEPARATE_STRIP=YES
COPY_PHASE_STRIP=YES

Related

How to reduce the size of my custom iOS framework?

I'd created a custom framework in iOS, with swift4 in Xcode 9.2. The framework contains 9 .swift files, when I tried to archive and create a .framework file, the resultant shows a size of 5MB. However, the 9swift files totally shows a file size of just 72KB. The archived, .framework file is too big in size(5 MB) which my client doesn't agree with.
I'd tried to remove the unwanted code but still the size remains the same, they want me to make it like that of Android framework, which is just 34KB of size. This is the first time I'm creating a framework and I'm out of solutions, can someone help me to reduce the size of the framework without reducing the files?
There are two things I've tried and it has worked for me. Maybe it can also be useful for you.
The linker exports all the symbols by default. You can limit that through some techniques discussed in this article about Symbol Visibility. Also, there is a nice feature in the linker that allows you specify with symbols must be exported or not exported. Exporting only the interface symbols might help you reduce size and your client not waste memory.
So, in practice:
Considering that my framework archive is MyFramework.framework.
I've listed all symbols of MyFramework.framework/MyFramework by running $ nm -g MyFramework.framework/MyFramework and selected the symbols that my binary needed to export (symbols my client would need to access).
All selected symbols were saved in a text file. So assuming that among all the symbols listed, you'll need to save to the text file only the ones you need (your client needs).
Open MyFramework project and set Build Settings -> Exported Symbols File to point to the text file you just created.
With the binary in hands, you can strip some symbols using strip -N MyFramework.framework/MyFramework.
In my case I could achieve something good but I think it might change from project to project. Also, I was dealing with Objective-C. I made a sample Swift project with the results achieved. You can check it out at https://github.com/gbazilio/ios-framework-size.
Hope it helps for you as it did for me.

IPA File Structure - SupportSwift & Symbols

When unzipping the ".ipa" file, the output is: Payload directory that contains the application. However, sometimes the output is: Payload, SwiftSupport and Symbols directories.
What are the conditions to generate both SwiftSupport and Symbols directories?
Also, I noticed that SwiftSupport contains .dylib files, which -I assume- they are already exist in the application (right click -> show package contents -> frameworks), so:
The application should work fine even if they are not exist, what are the purpose of generating them?
I couldn't find any useful reference to describe what I'm looking for.
After playing with archiver I found answers for all your questions.
What are the conditions to generate both SwiftSupport and Symbols directories?
SwiftSupport folder is managed by option ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES from target's Build Settings
Symbols directory is managed by checkbox on export dialog:
Since Xcode 7 there is also support for exportOptionsPlist with symbol export option for command line build, more details here
Second part is more interesting:
The application should work fine even if they are not exist, what are the purpose of generating them?
Answer to this question I found in ... apple's documentation:
Always embed the Swift standard libraries in the target's products, even if the target does not contain any Swift code. For example, this should be enabled if the target is embedding other products which contain Swift, or if it is a test target which does not contain Swift but which is testing a product which does. This setting only applies to wrapped products, not to standalone binary products.
So application's .ipa can contains this folder with libraries even without using of swift directly
As sage444's answer give your some explanation to your answer. There are few points that I have observed.
Symbols: You need this folder to symbolicate your crash logs.
SwiftSupport: Although you have two copies of dylib one in Payload and other in framework. But when you upload it to iTunesConnect then the size of your downloadable app is less than the size of your ipa file. The iTunesConnect manages your duplicate items (dylibs).
For more info you can check this answer

How to build a Framework fat binary (all archs) that still compatible with archive and upload to AppStore?

I've built a Framework for distribution (not open source),everything is working despite Xcode not having a nice support for developing Frameworks.
The problem is that when archiving for AppStore you get the error:
The executable <EXECUTABLE_NAME_AND_PATH>.framework contains unsupported architectures[x86_64,i386]
The solution to the error above is to strip out the architectures mentioned, as already discussed in this question and in other sources as well.
The problem is that to use the binary on Xcode it is necessary to have all architectures, but to archive I cannot have all of them. How to build the framework in a way that it contains all the architectures (or in a way that simulators accept it) and still be able to archive and upload to AppStore without using the custom scripts to strip the exceeding architectures?
It looks like you need to build two fat libraries, one for development and another one for deployment.
This way you can create two targets into your project (you can duplicate the existing target). One target will be used for development and be linked with the full framework. The other target will be used for archiving and will be linked to the reduced framework.
Hoping this helps...

Xcode unable to find strip-frameworks.sh directory

I recently update Xcode to Version 7.1, which included Swift 2.1. I installed Swift 2.1 with no troubles. After attempting to run my project, I realized that I needed to grab the latest version of Realm, since the previous version did not support Swift 2.1. I deleted the old frameworks and imported Realm 0.96.2. Whenever I run, I now get this error:
bash: /Users/userName/Library/Developer/Xcode/DerivedData/appName-ghiroqitgsbvfhdqxsscyokyoouz/Build/Products/Debug-iphoneos/appName.app/Frameworks/Realm.framework/strip-frameworks.sh: No such file or directory
I suspected the problem was with the script that is required if you wish to submit your app the the App Store, so I removed the Run Script Phase, added a new one, and copied the script from the Realm documentation site:
bash "${BUILT_PRODUCTS_DIR}/${FRAMEWORKS_FOLDER_PATH}/Realm.framework/strip-frameworks.sh"
I thought that that would fix it, but it did not. I then thought that the problem may be in the Realm.framework or RealmSwift.framework files, so I removed them and re-imported them (Just in case I messed something up). Nothing changed. Does anyone know if there is a fix to this error?
Thanks!
-CodeIt
From the error message, it seems like, you didn't added Realm.framework and RealmSwift.framework to the Embedded Binaries pane, which you find in the General tab of your project, as shown below:
For further validation, you can check the tab Build Phases. It should look like below:
Note: Make sure that the run script phase comes after the Embed Frameworks phase.
Why is this script needed?
The vendored frameworks are not just single executables, but actually FAT binaries which are archives of linked executables on different architectures. This includes architecture slices for arm64 and armv7, which are necessary for deployment on the phone as well as i386 and x86_64 which are necessary for running the app in the simulator.
The strip-frameworks.sh script main responsibility is to take care of removing unnecessary slices. This reduces the final package size and is necessary for AppStore deployment because iTunes Connect rejects apps with simulator architectures.
More Details
The script works on base of the build setting VALID_ARCHS. Because that is changing the signed executable of the framework, it also needs to take care of code signing. Since introduction of bitcode, it also got further post processing as responsibility. It extracts the included *.bcsymbolmap files from the framework bundle and places them into correct path in the *.xcarchive.
The FAQ topic on Bitcode of PSPDFKit has a good explanation on what BCSymbolMaps are:
A BCSymbolMap is a lot like a dSYM for bitcode. Xcode builds it as part of creating the app binary, and also for every dynamic framework. It's required for re-symbolicating function/method names to understand crashers.
In my case, change the process order in Build Phases to solve
not OK
OK

How is a .dSYM file created?

I'm working on an app with another developer and they just submitted a release to the app store that was built on their computer. In order to make a build on my machine (that belongs to the same git commit), I have to alter the path to one of the libraries we use in my XCode project. Will any changes I make to the XCode project file change the dSYM? If I was able to make a build without modifying the XCode project file, would the dSYM file be the same?
A dSYM file is a "debug symbols file". It is generated when the "Strip Debug Symbols" setting is enabled in the build settings of your project.
When this setting is enabled, symbol names of your objects are removed from the resulting compiled binary (one of the many countermeasures to try and prevent would be hackers/crackers from reverse engineering your code, amongst other optimisations for binary size, etc.).
dSYM files will likely change each time your app is compiled (probably every single time due to date stamping), and have nothing to do with the project settings.
They are useful for re-symbolicating your crash reports. With a stripped binary, you won't be able to read any crash reports without first re-symbolicating them. Without the dSYM the crash report will just show memory addresses of objects and methods. Xcode uses the dSYM to put the symbols back into the crash report and allow you to read it properly.
Ideally, your dSYM file shouldn't be tracked in your git repo. Like other binaries that change on building, it's not useful to keep them in source control. However, having that said, it is important that you keep the dSYM files for each distributed build (betas, press releases, app store distributions, etc.) somewhere safe so that you are able to symbolicate any crash reports you might get. Xcode does this automatically for you when you use the Archive option. The created archive contains your app and its dSYM and is stored within Xcode's derived data directory.

Resources