Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can't add dynamic frameworks to Command Line Tool

Goals

I added Command Line Tool target to an iOS app and linked with swift frameworks. (tested with Realm and SwiftyJSON)

Expected Results

Build Command Line tool with those libraries.

Actual Results

Xcode output: dyld: Library not loaded: @rpath/libswiftCore.dylib Referenced from: .../Xcode/DerivedData/.../Build/Products/Debug/RealmSwift.framework/Versions/A/RealmSwift Reason: Incompatible library version: RealmSwift requires version 1.0.0 or later, but libswiftCore.dylib provides version 0.0.0

Steps to Reproduce

Create empty Swift Command Line Tool and link Realm frameworks

Code Sample

CommandLineTest.zip

Version of Frameworks and Tooling

Realm version: github "realm/realm-cocoa" "master" SwiftyJSON version: github "acegreen/SwiftyJSON" "swift3"

Xcode version: 8 GM (which is on the App Store)

Dependency manager + version: Carthage 0.18

like image 949
Jauzee Avatar asked Jan 06 '23 09:01

Jauzee


1 Answers

Command-line tools are best with static archives because everything is distributed as a single binary. Looking at Realm, I don't see that there is a static archive option. They do have an iOS static framework that I got compiling for macOS but that's not quite what you want. You might want to try playing with Realm's source a bit more to see if you can get it to produce a static archive.

In the mean time, as a workaround, you'll need to tell Xcode where to find the dylibs at runtime and also to install them somewhere.

  1. In your Build Settings, go down to "Runpath Search Paths" and add "@rpath".
  2. In Build Phases, under Copy Files, click the + button and add both Realm.framework and RealmSwift.framework from your project.
  3. Because Realm is compiled with an older version of Swift, you also need to specify "Use Legacy Swift Language Version" in Build Settings.

That will get your project building and finding the Realm libraries but now it will fail to find libswiftCore.dylib. That's because normally command-line tools are statically linked with the Swift library but as soon as you add a framework/dylib, the linker no longer includes the static version.

  1. Go back to Build Phases, Copy Files, and add the following:
libswiftObjectiveC.dylib
libswiftIOKit.dylib
libswiftFoundation.dylib
libswiftDispatch.dylib
libswiftDarwin.dylib
libswiftCoreGraphics.dylib
libswiftCore.dylib

You can find them inside your Xcode installation and then ./Contents/Developer/Toolchains/Swift_2.3.xctoolchain/usr/lib/swift/macosx/

WARNING: Keep in mind that you will need to distribute the frameworks and the dylibs with your command-line tool and they will need to be in the same directory as the tool. You can put them somewhere else on the system by specifying a different runpath but you'll still need them distributed with your tool.

The nice thing about a .app bundle is that it gives you a place to put this stuff and users can just drag-and-drop it to install it. If you could get a static archive version of Realm, you could distribute everything in one binary.

like image 138
Myke Olson Avatar answered Jan 28 '23 05:01

Myke Olson