When linking the JavaScriptCore framework with an iOS 7 deployment target the app links to Frameworks/JavaScriptCore.framework
:
otool -L -arch armv7 MyApp
MyApp:
/System/Library/Frameworks/JavaScriptCore.framework/JavaScriptCore (compatibility version 1.0.0, current version 537.51.2)
/System/Library/Frameworks/UIKit.framework/UIKit (compatibility version 1.0.0, current version 2935.137.0)
...
When linking the JavaScriptCore framework with an iOS 6 deployment target the app links to PrivateFrameworks/JavaScriptCore.framework
:
otool -L -arch armv7 MyApp
MyApp:
/System/Library/PrivateFrameworks/JavaScriptCore.framework/JavaScriptCore (compatibility version 1.0.0, current version 537.51.2)
/System/Library/Frameworks/UIKit.framework/UIKit (compatibility version 1.0.0, current version 2935.137.0)
...
This is because the JavaScriptCore framework has special symbols that instruct the linker to change its dylib install path depending on the deployment target version:
nm JavaScriptCore.framework/JavaScriptCore | grep '\$ld\$'
00000000003959a0 S $ld$install_name$os4.3$/System/Library/PrivateFrameworks/JavaScriptCore.framework/JavaScriptCore
00000000003959a1 S $ld$install_name$os5.0$/System/Library/PrivateFrameworks/JavaScriptCore.framework/JavaScriptCore
00000000003959a2 S $ld$install_name$os5.1$/System/Library/PrivateFrameworks/JavaScriptCore.framework/JavaScriptCore
00000000003959a3 S $ld$install_name$os6.0$/System/Library/PrivateFrameworks/JavaScriptCore.framework/JavaScriptCore
00000000003959a4 S $ld$install_name$os6.1$/System/Library/PrivateFrameworks/JavaScriptCore.framework/JavaScriptCore
The JavaScriptCore framework is available in the PrivateFrameworks
directory in iOS 4.3 to 6.1 so the app finds it there at startup. On iOS 7, PrivateFrameworks/JavaScriptCore.framework
is a symbolic link to Frameworks/JavaScriptCore.framework
so that the app can run on both iOS 6 and 7.
Although not documented anywhere, this was clearly a deliberate move from Apple to add backward compatibility to the JavaScriptCore framework. But unfortunately, the App Store validation team did not get the memo from the JavaScriptCore team and apps linking the JavaScriptCore framework and targeting iOS below 7 will be rejected because they are using a framework in the PrivateFrameworks
directory. Please duplicate rdar://problem/17076670 if you want Apple to solve this issue.
In the meantime, you can workaround the rejection by removing the JavaScriptCore framework from your project and using the following Other Linker Flags instead (adapt for each undefined symbol error you get)
-Wl,-U,_JSGlobalContextCreate
-Wl,-U,_JSGlobalContextRelease
This tells the linker to resolve the symbols dynamically. Since the JavaScriptCore framework is always indirectly loaded through UIKit → WebKit → JavaScriptCore, the symbols will resolve just fine at runtime and your app should not be rejected since it doesn’t explicitly link the JavaScriptCore framework anymore.