Ever since Apple introduced iOS SDK 8.0, apps referencing CoreVideo or OpenGLES may encounter the following linker error:
framework not found Metal for architecture armv7
This happens only when:
1. The build target is a real device and not the Simulator.
2. The linker flags include the “-ObjC” flag (this one is set by default in CocoaPods).
3. The code was compiled with SDK 8.0, and used by an app compiled for an earlier SDK (using XCode < 6.0).
The reason behind this, is actually a bug / bad design by Apple, which failed to preserve backward compatibility for non-Metal devices (namely: armv7 & armv7s).
Taking a look at CoreVideo.h reveals this:
However, COREVIDEO_SUPPORTS_METAL is defined only as #if TARGET_OS_IPHONE
(which is not enough, since armv7/s devices do not support Metal).
The new “Link Frameworks Automatically” flag
In XCode 5, Apple introduced a new linker flag, named “Link Frameworks Automatically”, which defaults to “YES”. The purpose of this flag is to reduce the effort required by developers when adding a framework. Before the introduction of this flag, developers had to link their projects with system frameworks prior to using them. This flag allows them to simply use the frameworks.
After a thorough investigation, we found out that this works by the addition of a special load command in the output binary, called “LC_LINKER_OPTION”, which contains the framework that the binary links to. For example, when running:
otool -arch armv7 –l Appsee.framework/Appsee
We found out the following sections:
Load command 14
string #1 -framework
string #2 OpenGLES
Load command 15
string #1 -framework
string #2 Metal
Load command 16
As you can see, this will cause the linker to implicitly search for “Metal” when used.
Until/if Apple addresses this issue, our solution was to disable the “Link Frameworks Automatically” flag when building the framework. This way, the load commands will not be included in the binary and it may be used for non-metal architectures. Nothing else should be affected, since this flag does not seem to work for frameworks referenced by our framework (i.e.: when an app links with Appsee, it would still need to reference the different frameworks which Appsee uses, whether the flag was on or off).
The following posts helped us (thanks!) –