I'm trying to update pods so that they work for developers who are using use_frameworks! Our pods depend on pods with static vendored_libraries, so use_frameworks! doesn't work for our pods.
In my research, I stumbled upon the Parse pod (https://github.com/CocoaPods/Specs/blob/master/Specs/Parse/1.7.4/Parse.podspec.json) and noticed that it also has a static vendored_library, but that it still works with use_frameworks!. I was able to duplicate this with a locally-modified version of our Podspecs -- it looks like the key tweaks were to have a directory called
If this is a valid use, could CocoaPods support it as a first-class approach? It seems reasonable – every static library is turned into an equivalent dynamic library that can be properly linked against any other dependents. So, if a pod has vendored_libraries, compile them into a dynamic library and use that as the dependency?
Unfortunately, the approach Parse is taking doesn't necessarily work for all static archives. We currently don't have a robust detection on when it does or doesn't work, that's why the workaround is required.
This is still a valid issue, though, eventually there should be an ootb solution.
I see. Though, is an OOTB solution reasonable, even if it doesn't work for all pods? Right now, no pods with static vendored_libraries work without this workaround; with the solution, more pods would work and no pods would stop working that aren't already not working when use_frameworks! is enabled. It won't fix everything but it won't break anything more either. (Though, admittedly, the error messages will probably be harder to figure out.)
I can do the workaround for our pods, but I don't want to build a workaround if it isn't in line with CocoaPods development plans. I'd love to use dynamic library pods, but unfortunately iOS 7 is still too new for us to block our pod users from supporting it.
The issue is if we wrap all static libs into frameworks, certain Pods will be completely unusable and there would be no possible workarounds. Therefore the current solution is preferable.
Makes sense.
One more thought: could we implement this functionality and add a flag to the podspec format that allows developers to enable it? Like (pardon the excessively long name):
"compile_vendored_libraries_into_dynamic_framework": true
As long as that pod is compatible, then everything else should work correctly, right?
We're still investigating a proper solution, that hopefully doesn't involve extending the DSL.
Great! Is there another issue that's tracking this that I can subscribe to (and dupe this one against)?
Thanks for your help!
I'm not sure, I think this might be the best issue on this so far - thanks for your good questions :)
It looks like this is kind of working in CocoaPods 0.38. I can run pod install on a Podfile that definitely has static transitive dependencies, and it almost works. There are issues with header search paths, but it compiles and links properly. When I downgrade to 0.37, the same Podfile fails with the "transitive static libraries" error. Is this behavior intentional? If it is, it'll save me a lot of pain trying to make dynamic pods work with the Parse.podspec-style hacks. I tried with Pods that were being depended on by both the app target and another Pod, and that worked; I tried using some Swift pods, and they worked too.
The header issues seem like an easier fix. I think they are due to a mismatch in how CocoaPods handles header search paths and static libraries now: the code that handles header search paths assumes that every pod is either dynamic or static, while now it appears that some pods can be dynamic and some statically linked into the final binary.
Looks like this commit fixed our issue, since none of our pods are dynamic: https://github.com/CocoaPods/CocoaPods/commit/df34f79ffc2e0a0ddb5a851cebfd89407ec434b5
@perotinus that makes sense, it was the intention to narrow the impact of the transitive dependency rejection to only those cases were it actually applies, a static binary that is linked against the user target, but also used as a dependency by one of the pod targets. Great that this solved your issue :)
Given the increasing support for dynamic vendored libraries, the advent of bitcode and Apple's push away from static libraries, I'm closing this. The use case of trees of all static pods currently works, which fixes a decent amount of the issues.
I have the same Issue with one of my pods. I have a dependency to OpenSSL that is a static library and I need to distribute my pod as a Swift framework. Can you walk me through the process you initially described? Thanks.
Apologies, I've been traveling for a few weeks.
The basic approach to the workaround was to have a source file in source_files that had no content along with a static library as a vendored_library (or perhaps a static fake framework as a vendored_framework). The older Parse podspec that I linked above did this by touching a file in the prepare_command, and copying the binary from the framework to libParse.a, which was referenced in vendored_libraries. This configuration caused older versions of CocoaPods to create a dynamic framework that linked in the referenced static library. It wasn't a supported workaround, it only works for static libraries that have been compiled with the right visibilities of their symbols, and I'm not even sure that the approach will work with newer versions of CocoaPods.
For future reference:
1) You can package the static lib in a framework using http://arsenkin.com/ios-universal-framework.html
2) Then distribute it as a pod doing something like: http://stackoverflow.com/a/33357803/308315
Optional:
3) Create a private pod repo for distributing any private pods: https://guides.cocoapods.org/making/private-cocoapods.html
Most helpful comment
I have the same Issue with one of my pods. I have a dependency to OpenSSL that is a static library and I need to distribute my pod as a Swift framework. Can you walk me through the process you initially described? Thanks.