Where to put a Swift framework for execution?

I've built a simple command-line application in Swift. In the interests of code re-use the application uses a Swift framework that I also wrote and everything builds fine. When I go to run it from Terminal I'll get an error saying that it can't find the framework that the application depends on. It will give me the same error even if I copy the framework in to the same directory as the executable itself. Where does the framework need to be copied to so that it will be found when running the executable?

There’s really two questions here:

  • Where is your tool currently expecting the framework to be?

  • Where should the framework be?

With regards the first point, it’s hard to say given the info you’ve posted but it’s easy for you to work this for yourself: just run

otool -L
over the tool. For example, the following command shows which frameworks the
scutil
tool depends on and where those frameworks are expected to be:
$ otool -L /usr/sbin/scutil
/usr/sbin/scutil:
    /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (compatibility version 150.0.0, current version 1153.18.0)
    /System/Library/Frameworks/SystemConfiguration.framework/Versions/A/SystemConfiguration (compatibility version 1.0.0, current version 699.30.1)
    /usr/lib/libedit.3.dylib (compatibility version 2.0.0, current version 3.0.0)
    /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1213.0.0)

With regards your second question, if you want the framework to be available to all apps on the system you should put it in

/Library/Frameworks
. As this is a single flat ‘namespace’ you should give the framework an appropriately unique name.

Oh, I should stress that this answer assumes you’re building a command line tool (which can’t embed a framework) or you’re building a framework that you actually want to share between apps. If you’re building a standalone app you should embed the framework within the app.

Share and Enjoy

Quinn "The Eskimo!"
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

I guess I was unaware of how to tell my command-line application where to find the framework that it depends on. I assume this is a project setting somewhere?


I don't need to copy this to the system-wide framework location. I was hoping just to copy it to where the executable resides because this is just a toy project more for a learning exercise than anything else.

This is the error I get when trying to run the command-line tool when I have the framework in the same directory as the exectable:


dyld: Library not loaded: @rpath/Currency.framework/Versions/A/Currency
  Referenced from: /Users/jon/Library/Developer/Xcode/DerivedData/Craps_Simulator-gzxxzsbodmdtcigfpglcpkdebcxa/Build/Products/Debug/./Craps Simulator
  Reason: image not found
Trace/BPT trap: 5


I saw in the project settings in XCode there is something called "Runpath Search Paths" and one of them had @executable_path/../Frameworks so I created a Frameworks direcrtory one level up from the executable and copied the framework in there but it also wasn't found.

You need to read the dyld man page, which explains how these relative references work.

When you create a framework (from the Cocoa Framework template) it assumes that the framework will be embedded within your application, so it sets the Runpath Search Paths (

LD_RUNPATH_SEARCH_PATHS
) build setting to include directories that the framework would appear in a typical app. If you’re not using the framework embedded within your app, things get more complex.

Do you plan to use the framework just in your tool? Or in other situations do you plan to use the framework embedded within an app?

Share and Enjoy

Quinn "The Eskimo!"
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Pretty sure you can't build standalone Swift-based frameworks, only embedded (not necessarily impossible, mind, but unsupported for anyone not already called Apple). See:


http://stackoverflow.com/a/24072626/2298645


That discusses Xcode 6/Swift 1.x, but I've been trying to build a standalone framework using Xcode 7/Swift 2 and get exactly the same results. It's a right PITA for third-party framework devs wanting to build out the larger ecosystem, but there's a lot of things about Xcode7 and Swift2 that aren't properly baked yet so not entirely surprising. (Apple's platform is all about the "apps" now, so as long as embedded frameworks are working, standalone build support probably isn't a high priority.) For now, I think you just have to grit your teeth and add a build phase shell script to your commandline project to copy your latest "framework" files over to it whenever it builds (ugh).

@hhas01 You mentioned a build phase shell script that copies your frameworks to the build directory. Does it means that it is possible to use frameworks on swift command line applications? I tried that and failed, would you be kind to explain how you did it?

I managed to copy the framework to the executable directory. The executable finds the framework but it complains about the framework referencing the libswiftCore.dylib and not finding it.


dyld: Library not loaded: @rpath/libswiftCore.dylib
  Referenced from: /Users/paulofaria/Development/HTTP Server/Build/Products/Debug/Frameworks/Anthology.framework/Versions/A/Anthology
  Reason: image not found


If I go to the framework build settings and change Embedded Content Contains Swift Code to Yes when I run the command line application it them finds the libswiftCore.dylib but it warns that libswiftCore.dylib is duplicated.


objc[27495]: Class _TtCSs18_EmptyArrayStorage is implemented in both /Users/paulofaria/Development/HTTP Server/Build/Products/Debug/Frameworks/Anthology.framework/Versions/A/Frameworks/libswiftCore.dylib and /Users/paulofaria/Development/HTTP Server/Build/Products/Debug/server. One of the two will be used. Which one is undefined.
objc[27495]: Class _TtCSs24_ContiguousArrayStorage1 is implemented in both /Users/paulofaria/Development/HTTP Server/Build/Products/Debug/Frameworks/Anthology.framework/Versions/A/Frameworks/libswiftCore.dylib and /Users/paulofaria/Development/HTTP Server/Build/Products/Debug/server. One of the two will be used. Which one is undefined.
objc[27495]: Class _TtCSs18_CocoaSetGenerator is implemented in both /Users/paulofaria/Development/HTTP Server/Build/Products/Debug/Frameworks/Anthology.framework/Versions/A/Frameworks/libswiftCore.dylib and /Users/paulofaria/Development/HTTP Server/Build/Products/Debug/server. One of the two will be used. Which one is undefined.
objc[27495]: Class _TtCSs25_CocoaDictionaryGenerator is implemented in both /Users/paulofaria/Development/HTTP Server/Build/Products/Debug/Frameworks/Anthology.framework/Versions/A/Frameworks/libswiftCore.dylib and /Users/paulofaria/Development/HTTP Server/Build/Products/Debug/server. One of the two will be used. Which one is undefined.


.....

If I run otool in the framework, even though I changed Embedded Content Contains Swift Code to No (In the framework), it returns a @rpath/libswiftCore.dylib dependency.


otool -L Frameworks/Anthology.framework/Anthology           
Frameworks/Anthology.framework/Anthology:
  @rpath/Anthology.framework/Versions/A/Anthology (compatibility version 1.0.0, current version 1.0.0)
  /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1225.0.0)
  /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (compatibility version 150.0.0, current version 1229.11.0)
  /usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 228.0.0)
  @rpath/libswiftCore.dylib (compatibility version 0.0.0, current version 0.0.0)


And if I run otool on the application it doesn't return a @rpath/libswiftCore.dylib dependency even though I changed Embedded Content Contains Swift Code to Yes (In the application)


otool -L server                                                     
server:
  /usr/local/lib/libfcgi.0.dylib (compatibility version 1.0.0, current version 1.0.0)
  /usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 120.1.0)
  /System/Library/Frameworks/Foundation.framework/Versions/C/Foundation (compatibility version 300.0.0, current version 1229.0.0)
  @rpath/Anthology.framework/Versions/A/Anthology (compatibility version 1.0.0, current version 1.0.0)
  /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1225.0.0)
  /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (compatibility version 150.0.0, current version 1229.11.0)
  /usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 228.0.0)


It makes no sense


And I just realized that I have this warning:


Check dependencies
Not running swift-stdlib-tool: EMBEDDED_CONTENT_CONTAINS_SWIFT is enabled, but the product type 'Command-line Tool' is not a wrapper type.

Hey eskimo! Could you please take a look at the issue I posted below?

Has there been any progress on this issue?


I am trying to build a library with Swift code, and then a Command Line tool that links against that library.


So far, no joy.


(it works with a Cocoa App, just not Command Line tool)

Where to put a Swift framework for execution?
 
 
Q