The heartbreak of the Xcode “Undefined symbols for architecture xxx” linker message

As an iOS developer — or any type of software developer — you’re eventually going to run into linker errors. Sometimes they’re easy to fix (i.e., you’re missing an #include for a header file). Sometimes they’re crazy complex, subtle, and very difficult to solve. Today we’ll talk about some tools (file, otool) and techniques (setting library target hardware architectures) you can use for solving difficult Xcode linker errors.


When writing robust iOS applications, you may want to, or be required to, link third-party libraries into your Xcode projects. You may be writing your own libraries. Why reinvent the wheel if someone else has written some solid code with an elegant and well-documented API? When carefully crafted, libraries written in say C++ or Java can be platform-independent — capable of being compiled to target different hardware architectures like Intel or ARM.

Let’s suppose you’re working on an iOS app for the iPhone/iPad. For the app to run on an iDevice, your app project’s Targets -> targetName -> Build Settings -> Architectures -> Valid Architectures need to be set to:

(Note that nowadays, “armv7s” is generally optional.) Say you have a static library (“archive”) like library.a. We could discuss dynamically linked libraries, but let’s keep it simple. You’ll add the library to your Xcode app project in Project -> Target -> Build Phases -> Link Binary With Libraries. You compile/link your project in the simulator or on an actual device by pressing the ⌘-C keys or by clicking Product -> Build and… say what!?!? You see the dreaded stop-sign-with-exclamation-point error icon () in the Toolbar. You look at Xcode’s Issue Navigator (compiler/linker warnings and errors) and find that you’ve got linker (ld) errors like:

  • “ld: warning: ignoring file /path/to/library/library.a, missing required architecture i386 in file /path/to/library/library.a (2 slices)”
  • “Undefined symbols for architecture i386: “_OBJC_CLASS_$_MethodName”, referenced from: objc-class-ref in libraryObjectCodeFile1.o”

The symbols — like class and method names — are “undefined” because i386 is speaking Intel-ese and arm64/armv7 is speaking ARM-ese. The binary file formats for the libraries are different. One is unintelligible to the other.

How do we solve this problem? Try to think this through before reading further… Hint: you need to build an app binary, the file which contains the machine code for an iDevice to execute. That binary file must be compatible with the iDevice. I’ll go make a cup of coffee with my new Keurig while you ponder this conundrum.


You set Valid Architectures to arm64 armv7 armv7s in your app project, but the linker errors are telling you that you’re “missing required architecture i386” and you have “Undefined symbols for architecture i386”. Sounds like you’re trying to link an app binary you meant for iPhone/iPad with an ARM processor with a library binary meant for a device with an Intel processor (or vice versa, it depends on the situation). Think of this metaphor: You’re trying to put a BMW transmission into a Toyota. It can’t be done.

If you have the source code for library.a, you can easily fix the problem. Remove the current reference to library.a in your app project in Project -> Target -> Build Phases -> Link Binary With Libraries. Open the library’s project in Xcode and change the Valid Architectures to arm64 armv7 armv7s. Do a Product -> Clean (keyboard shortcut ⌘-⇧-K), build, and drag and drop the newly-built library/archive into your app project. Clean your app project, rebuild, and your app will run on the iDevice!

Suppose you don’t have the source code for library.a. You’ll need to get a version of the library that was built for arm64 armv7 armv7s. Contact the vendor/creator of the library. What about looking at this problem more deeply, considering the fact that sometimes compilers and linkers don’t always give you wholly accurate information, i.e., yeah, there’s an error, but the message they’re spewing only points to the actual solution. Consider the fact that you may be dealing with a bunch of different libraries. What to do?

There are a couple of tools, “file” and “otool”, built into MacOS (Unix), that come in handy for determining the target hardware architecture of a library. Open up a Terminal window and change directory to the location where the library/archive lives. Run the “file” command and inspect its output:

The “file” tool is generally less verbose, but does have a lot of options you can try. If you want really verbose details, check out “otool:”

Suppose you were able to get a copy of library.a for the arm64 armv7 armv7s architectures. Let’s run the “file” command on the archive:

There you go! Put the compatible version of the library into your app’s Xcode project, clean, build, and you’ll be able to run the app on an iDevice!

As always, post a comment if you have questions or feedback.

Author: Andrew Jaffee

Avid and well-published author, software engineer, designer, and developer, now specializing in iOS mobile app development in Objective-C and Swift, but with a strong background in C#, C++, .NET, JavaScript, HTML, CSS, jQuery, SQL Server, MySQL, Oracle, Agile, Test Driven Development, Git, Continuous Integration, Responsive Web Design, blah, blah, blah ... Did I miss any fad-based catch phrases? My brain avatar was kindly provided by http://icons8.com under a Creative Commons Attribution-NoDerivs 3.0 Unported license.

Leave a Reply

Your email address will not be published. Required fields are marked *