Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for source static library framework CocoaPods #6651

Closed
1 task done
paulb777 opened this issue Apr 13, 2017 · 15 comments
Closed
1 task done

Add support for source static library framework CocoaPods #6651

paulb777 opened this issue Apr 13, 2017 · 15 comments
Labels
s1:awaiting input Waiting for input from the original author

Comments

@paulb777
Copy link
Member

🌈

Report

What did you do?

Currently CocoaPods requires static library frameworks with module maps to be binary (via vendored_frameworks). This is an impediment to providing source CocoaPods, since dynamic frameworks are not always viable:

  • If a pod has dependencies that are static library frameworks, the pod itself must be static.
  • The slower cold start time to main of dynamic libraries is not acceptable for some apps. We've measured around a 600 millisecond impact of each dynamic library.

Relatedly, the !use_frameworks option is confusing and has inconsistent behavior. For source pods, it causes the pod to be built into a dynamic library framework AND to use a module map. For source, there is no way to get a module map. Yet, if the pod is binary, !use_frameworks allows a static framework and a module map.

What did you expect to happen?

Instead, it would be nice to have separate options to indicate using module maps and to indicate whether the framework should be static or dynamic.

CocoaPods should be able to analyze the dependency tree to determine if a source framework must be dynamic, static or either. For example, If a pod is the dependent of a dynamic library, it must be dynamic. If a pod has a static library dependency, it must be static.

@benasher44
Copy link
Member

Hi there! Thanks for the suggestion! Currently, people specify whether or not they want to integrate source pods statically or dynamically vis the use_frameworks! dsl. Given that the start times are an issue of the application integrating the libraries and can choose to integrate the pods either statically or as dynamic frameworks, I'm not sure it makes sense to push this responsibility to the pod specs/authors. Does that make sense, or is there something I'm missing here? I'm not sure we explicitly disallow module maps for source pods that are integrated statically. That might be a bug.

@benasher44 benasher44 added the s1:awaiting input Waiting for input from the original author label Apr 26, 2017
@paulb777
Copy link
Member Author

Hi Ben, thanks for the response.

Either I'm misunderstanding or you're not understanding the issue I'm seeing. If all pods are source and Objective C, I agree that everything is controllable.

There are two other use cases that cause the problem:

  1. If my app is Swift, the only way to get a static library pod is to make it binary. If it's source, it will be built into a dynamic library framework because of the Swift requirement to specify use_frameworks!

  2. I would like to open source a pod that depends on a closed source static library pod. This is not possible because of the error : ": Encountered an unknown error (The 'Pods-App' target has transitive dependencies that include static binaries: ". The only workaround is to keep my pod closed source as well.

@samdmarshall
Copy link
Contributor

@paulb777 to clarify something here, you say you are seeing roughly 600ms additional startup time for each additional dynamic library that you to the app. Please be aware that this same start-up time issue will exist regardless of using static or dynamic libraries, since using static libraries makes you deal with the cost up-front when loading the executable binary vs additional supplimentary binaries after the primary has been loaded by the dynamic linker.

This leaves you with a few options:

  1. convert the closed source static library into a dynamic library (instructions for doing so can be found here)
  2. use only dynamic libraries or only static libraries
  3. manually perform integration of the library (without using cocoapods)

These are the only approaches that can be taken in this scenario as integrating both static and dynamic libraries in combination does not play well with the linker unless manually configured.

@paulb777
Copy link
Member Author

paulb777 commented May 17, 2017

@samdmarshall Thanks for the reply.

The cost of dynamic library loading is substantially higher than loading a static library that is already built into the app, since a dynamic library needs to do all of its relocations at runtime instead of build time like a static library.

There are more details in this 2016 WWDC session where Apple recommends including no more than six dynamic frameworks in an app.

I would like to go with your option 2 and only use static libraries. However, CocoaPods does not support this unless the libraries are binaries included in vendored_frameworks. There is no way, at least that I've found, to have a source CocoaPod depend on another CocoaPod that includes a static library framework.

@samdmarshall
Copy link
Contributor

@paulb777 i'm aware, those costs are negligible in comparison to the larger picture of the process of dyld load and exec. and to be quite frank the truth of the matter is that apple is extremely out of touch with the realities of building large apps for their platform (because they don't), and limiting to 6 frameworks (even not including swift's runtime libraries) is not a feasible solution for many people.

To address your predicament: I am not sure why you cannot have an open sourced library that is distributed via dependency management as a static library. What you propose was investigated at one point but was not deemed viable due to incompatibilities with how some static libraries are produced (specifically the Google Analytics library) and not being able to get a reliable outcome that approach was dropped to avoid needing to require manual integration steps on a very commonly used library.

@paulb777
Copy link
Member Author

paulb777 commented Jun 1, 2017

Replaced by #6772

@paulb777 paulb777 closed this as completed Jun 1, 2017
@jlaws
Copy link

jlaws commented Jul 1, 2017

@samdmarshall the costs are not negligible, I have seen the same issues as Paul. Carthage already added support for this. Here is a great analysis:

https://blog.automatic.com/how-we-cut-our-ios-apps-launch-time-in-half-with-this-one-cool-trick-7aca2011e2ea

@samdmarshall
Copy link
Contributor

@jlaws i still stand by my original statment; as that blog post doesn't take into account WHY there is such an increased time. the underlying reason is not because of static versus dynamic; it is because of the additional requirements that iOS's security model places on loading dynamic libraries.

@paulb777
Copy link
Member Author

paulb777 commented Jul 3, 2017

@samdmarshall Why does it matter what the reason is for the increased time? Wouldn't it be a good thing for CocoaPods to provide better support for static libraries?

I provided more context for the need in #6772 and a non-intrusive PR at #6811

@evgenyneu
Copy link

evgenyneu commented Feb 11, 2018

I'm maintaining a library written in Swift. A user of this library has asked to add static_framework=true to the podspec file. I'm worried that it may create problems for other existing users, or users may want to continue using dynamic library. Is there a way for a user to choose if they want a dynamic or static library in the Podfile instead of me imposing this for everyone in the podspec?

@segiddins
Copy link
Member

Is there a way for a user to choose if they want a dynamic or static library in the Podfile instead of me imposing this for everyone in the podspec?

Not yet

@orta
Copy link
Member

orta commented Feb 12, 2018

This discussion is ongoing in #7428

@reitzig
Copy link

reitzig commented Feb 22, 2018

I want to write a CLI application based on framework dependencies and it turns out to be so much hassle. Apparently, no use case but "build an app for the app store" is really relevant to Apple, or much of the Swiftyverse. :/

@sisoje

This comment has been minimized.

@segiddins
Copy link
Member

@sisoje that comment is completely uncalled for

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
s1:awaiting input Waiting for input from the original author
Projects
None yet
Development

No branches or pull requests

9 participants