Thanks for adding support for static frameworks in v1.5.0! 🌈
I'd like to switch several of my dependencies to be statically linked, but I'm not sure if it safe for the library authors to make this change for everyone.
Here is a discussion where Keychain-Swift is weighing the pros/cons: https://github.com/evgenyneu/keychain-swift/issues/74
Rather than having the library writer force static or dynamic, can we have the user of the pod choose?
This issue is a precursor to a larger refactor we would like to do in potentially a CocoaPods 2.0 version in which we allow app developers to choose how to pack and link a given pod (of course with some limitations and input from the pod author).
I can keep this issue open since we do not have any other issue that closely asks for this, however, I do not anticipate any immediate work on this.
An ugly solution is to publish a separate podspec that uses the static framework flag. It's the best I can give you for now.
Just for reference, this library can be used in the meantime: https://github.com/keith/swift-staticlibs
An easy but non-standard solution to choosing between static or dynamic linking is adding the following to the Podfile (I've tried and used it with CP 1.4):
use_frameworks!
...
dynamic_frameworks = ['PromiseKit']
# make all the other frameworks into static frameworks by overriding the static_framework? function to return true
pre_install do |installer|
installer.pod_targets.each do |pod|
if !dynamic_frameworks.include?(pod.name)
puts "Overriding the static_framework? method for #{pod.name}"
def pod.static_framework?;
true
end
end
end
end
We enable the use of frameworks and then make us of the static_framework?
ruby function to force all the modules (except a list we define) to be compiled as static frameworks.
Curious to see what the CocoaPods team think about this. It's probably not their first recommendation, but I'm putting it out here just for the discussion.
It's a nice hack IMO ;)
There hasn't been any activity on this issue recently. Due to the high number of incoming GitHub notifications, we have to clean some of the old issues, as many of them have already been resolved with the latest updates.
Thanks for posting @bpoplauschi! I've spent hours trying to figure this out and your solution worked for me.
This is what worked best for my project for others still looking at this-
use_frameworks!
$static_framework = ['Flipper']
pre_install do |installer|
installer.pod_targets.each do |pod|
if $static_framework.include?(pod.name)
pod.host_requires_frameworks = false
end
end
end
Update for CP 1.7+ - I tried @dmac81's solution, but it didn't work (all frameworks were still built as dynamic). What worked for me was
pre_install do |installer|
installer.pod_targets.each do |pod|
if $static_framework.include?(pod.name)
def pod.build_as_static_framework?;
true
end
end
end
end
This is the same principle as above, just taking into account the deprecation of static_framework
in favour of build_as_static_framework
from CP 1.7 - https://www.rubydoc.info/gems/cocoapods/Pod/Target:static_framework%3F
@bpoplauschi's updated solution still didn't work for me (Xcode 11 beta 4 + CP 1.7.5) :(
We have just upgraded from 1.6.x to 1.7.3 and using the new build_as_static_framework
seems to work partially where the static_framework
was working fine. With 1.7.3, the framework's code does seem to be getting linked statically into the main binary, but the framework's resources are not being copied over to the main directory and are therefore not found at runtime in the main bundle.
We are actually seeing the framework getting embedded in the app's Frameworks
directory (which is odd, since it's not a dynamic framework - running file
on the binary reveals that it is an ar archive
) while the Copy Pods Resources
phase is missing all of the framework's resources.
This is all using Xcode 10.2.1.
Is this expected behavior? It feels like if the framework's code is getting linked into the main binary, the resources should follow suit? As it is right now, it feels like the framework is part dynamically linked, part statically.
@FarAndHeight @hujunfeng you are probably right. After all, we are hacking around the built in CP features, so it's expected that as some point, things will go south.
Maybe someone from the @orta or someone else from the CP team can comment on why this behaviour has changed and how / if we can update the hack.
(in my case, I am using Rome which means CP is used to build the binaries and we link them manually, that is why this issue hasn't been a problem to me).
I noticed that there are some duplicated file linker errors that show up when overriding build_as_static_framework?
. This is due to some configuration that occurs based on the actual underlying build_type
.
Here is what fixed this for me. Riffing off of @bpoplauschi
pre_install do |installer|
installer.pod_targets.each do |pod|
if $static_framework.include?(pod.name)
def pod.build_type;
Pod::Target::BuildType.static_framework
end
end
end
end
@bpoplauschi @dmac81 : I am using Cocoapods 1.8.4 and neither of these solutions work. Do you have any pointers?
@dnkoutso
An ugly solution is to publish a separate podspec that uses the static framework flag. It's the best I can give you for now.
What do you mean by "publish a separate podspec". Can you please elaborate?
Part of this will be available in 1.9 but not on a per-pod basis and rather on on a global basis through use_frameworks!(:linkage => :static)
An easy but non-standard solution to choosing between static or dynamic linking is adding the following to the Podfile (I've tried and used it with CP 1.4):
use_frameworks! ... dynamic_frameworks = ['PromiseKit'] # make all the other frameworks into static frameworks by overriding the static_framework? function to return true pre_install do |installer| installer.pod_targets.each do |pod| if !dynamic_frameworks.include?(pod.name) puts "Overriding the static_framework? method for #{pod.name}" def pod.static_framework?; true end end end end
We enable the use of frameworks and then make us of the
static_framework?
ruby function to force all the modules (except a list we define) to be compiled as static frameworks.Curious to see what the CocoaPods team think about this. It's probably not their first recommendation, but I'm putting it out here just for the discussion.
I managed to change a good percentage of my frameworks from dynamic to static. However, when trying to send the binary do AppStore the following error is displayed:
"”Invalid Bundle Structure — The binary file ‘[NAME_OF_STATIC_FRAMEWORK]’ is not permitted. Your app can’t contain standalone executables or libraries, other than a valid CFBundleExecutable of supported bundles. Refer to the Bundle Programming Guide at https://developer.apple.com/go/?id=bundle-structure for information on the iOS app bundle structure.”"
Did this happen to anybody?
Most helpful comment
An easy but non-standard solution to choosing between static or dynamic linking is adding the following to the Podfile (I've tried and used it with CP 1.4):
We enable the use of frameworks and then make us of the
static_framework?
ruby function to force all the modules (except a list we define) to be compiled as static frameworks.Curious to see what the CocoaPods team think about this. It's probably not their first recommendation, but I'm putting it out here just for the discussion.