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

Allow podfile to specify if dependency should be statically linked #7428

Open
1 task done
bridger opened this issue Feb 12, 2018 · 18 comments
Open
1 task done

Allow podfile to specify if dependency should be statically linked #7428

bridger opened this issue Feb 12, 2018 · 18 comments
Labels
d3:hard An issue that is difficult to solve and may require significant changes t1:enhancement Enhancements that have not been picked up yet. Please comment if you plan to work on it t3:discussion These are issues that can be non-issues, and encompass best practices, or plans for the future.
Milestone

Comments

@bridger
Copy link

bridger commented Feb 12, 2018

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: evgenyneu/keychain-swift#74

Rather than having the library writer force static or dynamic, can we have the user of the pod choose?

@dnkoutso
Copy link
Contributor

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.

@dnkoutso dnkoutso added t3:discussion These are issues that can be non-issues, and encompass best practices, or plans for the future. d3:hard An issue that is difficult to solve and may require significant changes labels Feb 12, 2018
@Digipom
Copy link

Digipom commented Feb 12, 2018

Just for reference, this library can be used in the meantime: https://github.com/keith/swift-staticlibs

@bpoplauschi
Copy link

bpoplauschi commented Apr 2, 2018

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.

@orta
Copy link
Member

orta commented Apr 2, 2018

It's a nice hack IMO ;)

@stale
Copy link

stale bot commented Jul 1, 2018

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.

@stale stale bot added the s1:awaiting input Waiting for input from the original author label Jul 1, 2018
@dnkoutso dnkoutso added t1:enhancement Enhancements that have not been picked up yet. Please comment if you plan to work on it and removed s1:awaiting input Waiting for input from the original author labels Jul 1, 2018
@dnkoutso dnkoutso added this to the 2.0.0 milestone Jul 1, 2018
@nnascim
Copy link

nnascim commented Sep 5, 2018

Thanks for posting @bpoplauschi! I've spent hours trying to figure this out and your solution worked for me.

@davidmcraejr
Copy link

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

@bpoplauschi
Copy link

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

@hujunfeng
Copy link

@bpoplauschi's updated solution still didn't work for me (Xcode 11 beta 4 + CP 1.7.5) :(

@FarAndHeight
Copy link

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.

@bpoplauschi
Copy link

@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).

@AnthonyMillerSF
Copy link

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

@anshulpara
Copy link

@bpoplauschi @dmac81 : I am using Cocoapods 1.8.4 and neither of these solutions work. Do you have any pointers?

@anshulpara
Copy link

@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?

@dnkoutso
Copy link
Contributor

dnkoutso commented Dec 5, 2019

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)

@kvdesa
Copy link

kvdesa commented Mar 5, 2020

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?

@xilin
Copy link

xilin commented Oct 26, 2021

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

I have to change to Pod::BuildType in version 1.10.1

pre_install do |installer|
  installer.pod_targets.each do |pod|
    if $static_framework.include?(pod.name)
      def pod.build_type;
        Pod::BuildType.static_framework
      end
    end
  end
end

@pballada
Copy link

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
d3:hard An issue that is difficult to solve and may require significant changes t1:enhancement Enhancements that have not been picked up yet. Please comment if you plan to work on it t3:discussion These are issues that can be non-issues, and encompass best practices, or plans for the future.
Projects
None yet
Development

No branches or pull requests