Was wondering whether you had consciously decided to use dynamic frameworks over static libraries or if adding static libraries to Carthage would be something worth contributing.
We've had Alamofire and EmitterKit built statically (to support iOS 7) in production for a few months now. You get namespacing and Xcode knows about the headers (yay autocomplete)
Would love to use carthage for dependency management and would be happy to contribute, wanted to see if adding support for static linking is a dead end w.r.t. Carthage before submitting a PR
The choice to use dynamic framework, and not static libraries or static frameworks, was an intentional one. There's no real advantage to a static library or framework apart from iOS 7 support. Since we'd prefer to be forward looking, iOS 7 becomes less important every day, and support for them in Carthage would add complexity to the project, we've chosen not to support them. Sorry!
Thanks @mdiep! That does make sense
Well if I have a framework project which internally requires other projects (which I'd like to manage with Carthage) I'd need to use static library targets for those dependent projects. (Or I have to tell the framework consumer to link and embed every last one of those)
Or am I missing something?
The idea is that the framework consumer would link and embed the dependencies, which could also be dependencies of other projects.
Yeah I know, but in many cases this is not very practical (imagine having a few dependencies that most likely the framework consumer doesn't even have access to e.g. your own private frameworks)
Or for example if you are building a framework that provides data from the Internet. It makes sense to have Alamofire remain an external dependency for the consumer (they should embed and link to it as it is a very common library with many applications) but it doesn't make much sense to have the JSON decoding library also linked. It should better be compiled in directly.
It would be nice if Carthage would allow for this.
it doesn't make much sense to have the JSON decoding library also linked. It should better be compiled in directly.
Sure it does. You could easily have a framework for another service that also wants to use JSON decoding.
Sorry, but I am not sure what to say.
It _could_ make sense, I agree, but if my framework provides for example stock market data, I cannot possibly understand how you can believe that it is meaningful that a stock presenting app, which, mind you, consumes my imaginary framework, must link to some JSON parsing library, as the framework would expressly exist to hide that complexity.
Let's say you make an app for stock market analysis. It interacts with 3 services to show information about stocks:
You want to provide one app that combines data from all 3.
You find 3 .frameworks:
StockMarket.frameworkStockStories.frameworkStockToots.frameworkEach of those frameworks needs to decode JSON and decides to use a JSONDecoderRing library. If any of those frameworks embeds JSONDecoderRing directly, then the app may not work鈥攊t's tied to that version of JSONDecoderRing.
This is particularly a problem if there are multiple versioning requirements. If StockMarket.framework embeds version 1.2 of JSONDecoderRing, but StockToots.framework requires version 1.3, then the app may not work. IIRC, even if you embed version 1.3 in the app or in StockToots.framework, it's undefined which version the app will use at runtime. Maybe it will work half the time. Maybe it will work on your machine, but not your users' machines. You don't know.
That's the problem Carthage is really meant to solve. You specify that you need certain versions of StockMarket.framework, StockStories.framework, and StockToots.framework. Carthage picks a version of JSONDecoderRing.framework that works with all 3 and makes it so you can embed that framework exactly once.
You, as the maker of StockMarket.framework, can't know whether a framework consumer will want to use another framework that uses one of StockMarket.framework's dependencies. It's a minor inconvenience that consumers need to embed JSONDecoderRing.framework, but it's a _minor_ inconvenience and it works.
I completely follow your reasoning and agree with your points, but quite often I don't want to use a framework at all for those reasons but rather a static library that is 'hidden' in my framework and doesn't interact at all with foreign code. Is that unreasonable?
But why do you care so much if the library dependency is "hidden"? Outside of the very minor one-time cost for embedding in top level projects you're introducing many other potential problems.
Also, true static libraries in the sense that you seem to be looking for can't even be built from Swift source.
Mhmm thinking about it, I guess you are right.
I guess I need to evolve ;)
Sorry for dragging out this issue for so long.
In other words, unless there is zero possibility of no other code ever wanting to use that dependency you can't hide it. This is a core principle of Carthage. It's designed to resolve those standalone framework dependencies that themselves may have transitive dependencies.
I completely agree with not hiding internal dependencies. However, OS X command-line tools cannot use dynamic frameworks. Is there a preferred way of using Carthage to build command-line tools?
(Currently, I'm letting Carthage check out the code, and then I just include the source directly into my project. This works, but defeats module ACLs. I recognize this may all be Swift and Framework limitations. Just trying to develop a best practice around this w/ Carthage.)
I wish there was a good answer for frameworks for command line apps. The only workable solution I'm aware of is what carthage does -- package the exe and frameworks in an app bundle and extract them.
In my case, I can't have a dynamic library because I'm writing a library to use on Xamarin.iOS. The binding only works for static libraries.
What about the significant cost of having dynamic frameworks on app launch time? Some apps can't even load and are killed because dyld takes too long to resolve all the symbols.
Those people are statically linking Swift libraries with success.
See:
https://github.com/artsy/eigen/issues/586
https://github.com/johnno1962/Accelerator
https://github.com/stepanhruda/dyld-image-loading-performance
@steeve this last issue has gone away in 9.35 and up, I think. Personally I'm finding the conversion of static libraries to dynamic daunting (for switching from Cocoapods to Carthage)...
Most helpful comment
What about the significant cost of having dynamic frameworks on app launch time? Some apps can't even load and are killed because
dyldtakes too long to resolve all the symbols.Those people are statically linking Swift libraries with success.
See:
https://github.com/artsy/eigen/issues/586
https://github.com/johnno1962/Accelerator
https://github.com/stepanhruda/dyld-image-loading-performance