59

Problem:

While submitting the app to the App Store the following error is reported:

Unsupported Architecture. Your executable contains unsupported architecture '[x86_64, i386]

Questions:

  1. How can the above error be resolved ?

  2. How can I check the architectures used by the archive or IPA ?

  3. How can I ensure that the Release archive doesn't include x86_64 and i386 (simulator architectures).

    • Is it only possible through script or is there is a setting in Build Settings or else where ?
user1046037
  • 16,755
  • 12
  • 92
  • 138
  • 2
    go to build settings-> search for "architecture", you can check the "architectures" tab there, commonly by default it must be armv7,arm64 architecture, please check which one is shown to you – Mehul Thakkar Mar 07 '17 at 06:50
  • 2
    Also, sometimes the above error is shown because of improper build, please clean, then build and then archieve and upload(dont forget to clean and then build). Lets try again.. possibly you will get success in that way – Mehul Thakkar Mar 07 '17 at 06:51
  • I suppose the problem is that some of the frameworks used were built included the x86_64 and i386 architectures. So would have to remove it manually. – user1046037 Mar 07 '17 at 07:09
  • https://stackoverflow.com/a/51324598/6898523 – MAhipal Singh Jul 13 '18 at 12:08

5 Answers5

137

Apple has started complaining if app contains simulator architectures during distribution.

How can the above error be resolved ?

Solution :

Add below code in run script of Project target, this remove the simulator architecture (x86_64 and i386) from your app on building process:

Shell :

/bin/sh

Code :

APP_PATH="${TARGET_BUILD_DIR}/${WRAPPER_NAME}"

# This script loops through the frameworks embedded in the application and
# removes unused architectures.
find "$APP_PATH" -name '*.framework' -type d | while read -r FRAMEWORK
do
FRAMEWORK_EXECUTABLE_NAME=$(defaults read "$FRAMEWORK/Info.plist" CFBundleExecutable)
FRAMEWORK_EXECUTABLE_PATH="$FRAMEWORK/$FRAMEWORK_EXECUTABLE_NAME"
echo "Executable is $FRAMEWORK_EXECUTABLE_PATH"

EXTRACTED_ARCHS=()

for ARCH in $ARCHS
do
echo "Extracting $ARCH from $FRAMEWORK_EXECUTABLE_NAME"
lipo -extract "$ARCH" "$FRAMEWORK_EXECUTABLE_PATH" -o "$FRAMEWORK_EXECUTABLE_PATH-$ARCH"
EXTRACTED_ARCHS+=("$FRAMEWORK_EXECUTABLE_PATH-$ARCH")
done

echo "Merging extracted architectures: ${ARCHS}"
lipo -o "$FRAMEWORK_EXECUTABLE_PATH-merged" -create "${EXTRACTED_ARCHS[@]}"
rm "${EXTRACTED_ARCHS[@]}"

echo "Replacing original executable with thinned version"
rm "$FRAMEWORK_EXECUTABLE_PATH"
mv "$FRAMEWORK_EXECUTABLE_PATH-merged" "$FRAMEWORK_EXECUTABLE_PATH"

done

Solution :

There one more solution, if you wish to do it only once. But be careful though as after doing following steps, you will not be able to run app on simulator. Do it just before deploying the app on Testflight/App-store.

Go inside the your ProjectFramework.framework folder of your project from terminal. Run following commands:

lipo -remove i386 ProjectFramework_SDK -o ProjectFramework_SDK 
lipo -remove x86_64 ProjectFramework_SDK -o ProjectFramework_SDK

Check the architectures from framework?

$ lipo -info PathToProject/ProjectName.framework/ProjectName

Output will be : → Architectures in the fat file: ProjectName are: i386 x86_64 armv7 arm64

Ref. doc: http://ikennd.ac/blog/2015/02/stripping-unwanted-architectures-from-dynamic-libraries-in-xcode/

nikdange_me
  • 2,949
  • 2
  • 16
  • 24
  • 2
    Thanks, noticed the same solution in http://stackoverflow.com/questions/30547283/submit-to-app-store-issues – user1046037 Mar 07 '17 at 07:07
  • 1
    Yeah, sure you can answer it completely. If the code was referenced from a different place it would be nice to provide link to the reference, so that they get credited. – user1046037 Mar 07 '17 at 07:11
  • How can I find the architectures from the IPA not from the framework ? Also if the code was referenced from some other place / stackoverflow answer, please provide original link instead of the code – user1046037 Mar 07 '17 at 08:03
  • I referred from the blog site which I have mentioned, and part of another solution was implemented by me so that's it. – nikdange_me Mar 07 '17 at 08:07
  • Hi, @user1046037 I tried to architecture info from IPA file, I didn't find any way to get it. But you can find its info from .xcarchive file. – nikdange_me Mar 07 '17 at 09:31
  • @nikdange_me, Should i change the Script's "APP_PATH"? APP_PATH="${TARGET_BUILD_DIR}/${WRAPPER_NAME}" can anyone write an example please? what are the steps? should i run it from the "Terminal?" – Ofir Malachi Jun 06 '17 at 14:47
  • @OfirMalachi you don't have to change the script! Sorry for late reply! :| – nikdange_me Jun 08 '17 at 09:22
  • @nikdange_me after implementing this solution and archiving and uploading to app store successfully how can I run it back in the simulator ? I only applied the script to specific frameworks so the script has a slight modification. I receive linker errors on the frameworks the script modifies – Vince Jun 15 '17 at 00:54
  • @Vince out of above two solutions which solution you have tried? – nikdange_me Jun 15 '17 at 01:17
  • @nikdange_me - sorry, I used the first one (the build script) – Vince Jun 15 '17 at 03:27
  • Nothing to be sorry about, bro! :) @Vince try removing script and run. We will need this script while distribution, as it remove simulator architecture from app. – nikdange_me Jun 15 '17 at 04:12
  • 7
    It's very important that the run script must be placed after the step to embed frameworks – garanda Dec 04 '17 at 12:29
  • Btw, remove can be done in one line like this: `lipo -remove i386 -remove x86_64 -remove armv7 FrameworkName -o FrameworkName` – RAM237 Sep 14 '20 at 09:16
  • **Warning**: The script fails silently if the target frameworks are not fat binaries and produces a broken .ipa file that can't be installed on the devices. This is likely to happen when you use XCFrameworks. – kean Nov 02 '21 at 16:57
12

For custom created Dynamic Framework

  1. Open Terminal

  2. Open your project drag path of respective framework to Terminal

    For example, cd /Users/mahipal/Desktop/masterTest/Alamofire.framework

  3. Set your Framework name in below command and run

    lipo -remove i386 Alamofire -o Alamofire && lipo -remove x86_64 Alamofire -o Alamofire

user9912639
  • 153
  • 6
MAhipal Singh
  • 4,745
  • 1
  • 42
  • 57
  • hi, i removed x86_64: " lipo -remove x86_64 WebRTC -o WebRTC" ---> but now my . project got 21 error :(, dont know why, can you help, im using simulator – famfamfam Nov 14 '19 at 08:54
  • example: " Showing All Messages Ignoring file /Users/thehe/Documents/Work/XXX/WebRTC.framework/WebRTC, missing required architecture x86_64 in file /Users/thehe/Documents/Work/XXXX/WebRTC.framework/WebRTC (2 slices) " -----" Showing All Messages Undefined symbol: _RTCInitializeSSL " – famfamfam Nov 14 '19 at 08:56
  • 1
    @famfamfam , actually simulator support only x86_64 architecture framework. so you need to compile& generate framework for simulator also support but when you try to upload binary on store then remove that x86_64 framework – MAhipal Singh Nov 14 '19 at 10:44
  • 1
    tks you, so now i have 2 framework : 1 for simulator, 1 for submit :D – famfamfam Nov 15 '19 at 05:30
6

When using the script of nikdange_me I got:

error: exportArchive: ipatool failed with an exception: #<CmdSpec::NonZeroExcitException: ... >
error: Framework not found in dylib search path

So I altered it and used lipo -remove instead of lipo -extract and lipo -create which solved my problem:

# This script loops through the frameworks embedded in the application 
# and removes unused architectures.

find "${TARGET_BUILD_DIR}/${WRAPPER_NAME}" -name '*.framework' -type d | while read -r FRAMEWORK; do
    FRAMEWORK_EXECUTABLE_NAME=$(defaults read "$FRAMEWORK/Info.plist" CFBundleExecutable)
    FRAMEWORK_EXECUTABLE_PATH="$FRAMEWORK/$FRAMEWORK_EXECUTABLE_NAME"
    for arch in $(lipo -archs $FRAMEWORK_EXECUTABLE_PATH); do
        if ! printf '%s\n' ${ARCHS[@]} | egrep -q "^$arch$"; then
            lipo -remove $arch "$FRAMEWORK_EXECUTABLE_PATH" -o "$FRAMEWORK_EXECUTABLE_PATH" 
        fi
    done
done
Henrik Lineholm
  • 356
  • 1
  • 6
  • 9
6

For Run Script under Build phases, add following steps to the Run Script to remove x86_64 and/or i386:

cd "${ARTIFACTS_FOLDER}"/FrameworkName.framework

lipo -remove x86_64 FrameworkName -o FrameworkName
lipo -remove i386 FrameworkName -o FrameworkName

Can be combined for removing multiple architectures as:

lipo -remove x86_64 FrameworkName -o FrameworkName && lipo -remove i386 FrameworkName -o FrameworkName
Alpana
  • 913
  • 1
  • 13
  • 22
2

For an iOS project, you have the following architectures: arm64 armv7 armv7s i386 x86_64

x86_64, i386 are used for the simulator.

What could be your problem is the framework you are using was build for iOS and not a simulator.

To fix this issue you can bypass the build framework and use lipo command lines.

First: lipo -info [The library.framework location]

Example Usage : lipo -info /Users/.../library.framework/LibrarySDK

Example output :

Architectures in the fat file: /Users/.../library.framework/LibrarySDK are: i386 x86_64 armv7 arm64 

You will get the list of architecture used for that framework.

Second: we need to strip the framework from the simulator architecture and make 2 versions of that framework (1 is used for iOS Device and 1 for the simulator)

using: lipo -remove [architecture] [location] -o [output_location]

Example: lipo -remove i386 /Users/.../SDK -o /Users/.../SDK_Output_Directory

Go to your chosen output directory to get the new generated SDK without the removed architecture to verify you can use the lipo -info command same as above

You can use the same lipo remove command on the newly created SDK but with another architecture lipo -remove x86_64 ... and you will get an SDK only for iOS devices

Third: Take that final SDK and rename it "SDK_Name_IOS" and use it.

Happy coding!!

JhonnyTawk
  • 834
  • 11
  • 23