JavaScriptCore framework availability on iOS
Asked Answered
P

1

7

I am using the JavaScriptCore framework that was introduced in iOS 7. My app has an iOS 6.0 deployment target. I am linking the app with JavaScriptCore.framework (which is by default in required mode). The new JavaScript Objective-C classes (JSContext, JSValue etc.) are obviously not available when running on iOS 6 but I can still use the plain C API, i.e. JSGlobalContextCreate(), JSObjectCallAsFunction() etc.

If I link the MultipeerConnectivity framework which was also introduced in iOS 7 and I run my app on iOS 6, I get an expected crash at startup:

dyld: Library not loaded: /System/Library/Frameworks/MultipeerConnectivity.framework/MultipeerConnectivity
  Referenced from: /var/mobile/Applications/5AB83411-CEFC-437D-88F8-6B80C36CCE9F/MyApp.app/MyApp
  Reason: image not found

Why is my app not crashing with the same dyld error when I link the JavaScriptCore framework?

Pendant answered 7/5, 2014 at 9:58 Comment(0)
P
22

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.

Pendant answered 7/5, 2014 at 9:58 Comment(2)
I bet there's also something to do with LGPL compliance in there as well.Mehala
I'm pretty confident that it has nothing to do with LGPL compliance, just a matter of SDK incompatibility.Pendant

© 2022 - 2024 — McMap. All rights reserved.