firebase / quickstart-ios

Firebase Quickstart Samples for iOS
https://firebase.google.com
Apache License 2.0
2.79k stars 1.47k forks source link

Update Podspec so Firebase can be a transitive dependency #245

Closed ninjudd closed 7 years ago

ninjudd commented 7 years ago

As explained here:

https://github.com/CocoaPods/CocoaPods/issues/6138

Firebase cannot be added as a dependency of another Cocoapod because the Firebase podspec modulemap is not correct. I don't fully understand what needs to be done to fix this, but perhaps @benasher44 can add more details.

See: https://github.com/CocoaPods/CocoaPods/issues/6138#issuecomment-258960994

ninjudd commented 7 years ago

Any update on this? 😬

morganchen12 commented 7 years ago

There are other limitations here; Firebase can't (shouldn't) be used as a dependency of a dylib since it's distributed as a static library. We are talking about changing this, but as the saying goes, I can't give you a timeline or anything concrete.

If you have a burning need to ship a library depending on Firebase, let me know and I'll give you more details.

MyroMac commented 7 years ago

Hey @morganchen12 , I'm shipping an CocoaPod that is an iOS SDK that depends on Firebase. It seems to be working but I was wondering if you have any resources/docs that I can read over to make sure that I didn't miss anything. Thanks!

morganchen12 commented 7 years ago

It is something that's worth writing a doc on given the amount of feedback we've had on it. I'll try to write something up after Google I/O happens.

zpap commented 7 years ago

Hey @morganchen12 I'll need some details on how to ship a library depending on Firebase. Thank you.

morganchen12 commented 7 years ago

You'll need to build the whole thing as a static framework (complete with architecture slices for device and simulator) and then distribute it as a vendored_binary through CocoaPods. This way all of your dependencies are properly resolved at link time.

If you're not using your library in Swift and thus don't need to ship a framework module, you can just distribute it as a static library.

Xcode doesn't provide a way to build a static framework, only a dynamic one. So you'll have to do some legwork outside of Xcode.

x-cray commented 7 years ago

@morganchen12 And in my case I really need to use it in Swift target. Is there any info on that?

morganchen12 commented 7 years ago

@x-cray if you're using Firebase in a Swift application target, you should be fine with the current installation instructions. If you're using it in an embedded framework target in the same Xcode project as your app target, you can integrate without duplicate class definition issues by using CocoaPods' inherit! :search_paths and making your app a subtarget of your embedded framework.

Do neither of these work for you?

x-cray commented 7 years ago

@morganchen12 Sorry for not providing the complete use case. So, I need to created a pod which depends on Firebase. The pod is basically a wrapper for Firebase messaging which I want to reuse in different Apps. The scenario is like here https://github.com/CocoaPods/CocoaPods/issues/6138. I'm aware of the fact that Firebase is static framework and I'm trying the workaround from https://github.com/CocoaPods/CocoaPods/issues/2926#issuecomment-300332642. So far I've successfully done that for TwitterKit and Crashlytics but their podspecs are much simpler comparing to Firebase.

x-cray commented 7 years ago

Tried to switch to FirebaseCommunity. Works so far. Thanks.

x-cray commented 7 years ago

@morganchen12 Ok, it still doesn't fix my issue since I need to use FirebaseDynamicLinks in my pod. So you're saying that the only way is to have both my wrapping framework and app target in the same Xcode project?

morganchen12 commented 7 years ago

Yes.

morganchen12 commented 7 years ago

Update on this: We're working with CocoaPods to add support for static dependency trees, meaning you'll be able to build on top of Firebase so long as the dependency subtree including Firebase is entirely static libraries (mostly). This is slated to be released in CocoaPods 1.4.x. This still does have limitations, but not nearly as many as there used to be. In the future we may release Firebase as a dynamic set of frameworks, but no immediate plans exist for this yet.

morganchen12 commented 7 years ago

This is now released in CocoaPods 1.4.0, and Firebase will not be available as a set of dylibs in the near future.

neerajgoyal12 commented 7 years ago

Using cocoapod version

1.4.0.beta.2

created the pod spec using cocoapod version

1.3.x

and still facing the same issue ?

I am also trying to add Firebase/Core as dependency and importing it in one of the classes

import Firebase

gets

no such module Firebase

Example Project Here

https://github.com/neerajgoyal12/NCore/tree/recommendedProjectSettings

morganchen12 commented 7 years ago

This isn't something that happens automatically in 1.4.x, as it comes with its own set of caveats. Take a look at https://github.com/CocoaPods/CocoaPods/pull/6811.

If you haven't already, I highly encourage you read up on static and dynamic linking and the differences between the two in order to achieve an understanding of what it means for modern dependency managers. Here is a good place to start.

neerajgoyal12 commented 6 years ago

@morganchen12 Thanks a lot for pointing me in the correct direction.

Posting this for someone still struggling with this issue

also special thanks to CocoaPods/CocoaPods#2926 (comment) [https://github.com/CocoaPods/CocoaPods/issues/2926#issuecomment-300332642]

Below is my pod environment

Executable Path: /Users/systology/.rbenv/versions/2.2.3/bin/pod

Plugins

cocoapods-deintegrate : 1.0.1
cocoapods-plugins     : 1.0.0
cocoapods-search      : 1.0.0
cocoapods-stats       : 1.0.0
cocoapods-trunk       : 1.3.0
cocoapods-try         : 1.1.0

Podfile

platform :ios, '8.0'
inhibit_all_warnings!

use_frameworks!

target 'NCore_Example' do
  pod 'NCore', :path => '../'
  pod 'Firebase'
  pod 'Firebase/RemoteConfig'

  target 'NCore_Tests' do
    inherit! :search_paths
    pod 'Quick', '~> 1.2.0'
    pod 'Nimble', '~> 7.0.2'
    pod 'FBSnapshotTestCase' , '~> 2.1.4'
    pod 'Nimble-Snapshots' , '~> 6.3.0'
  end
end

pre_install do |installer|
    # workaround for https://github.com/CocoaPods/CocoaPods/issues/3289
    def installer.verify_no_static_framework_transitive_dependencies; end
end

post_install do |installer|
    project = installer.pods_project

    # prevent frameworks which they are already linked with a module from being linked with the main target again
    installer.aggregate_targets.each do |target|
        project.build_configurations.each do |build_configuration|
            configFilePath = target.xcconfig_path(build_configuration.name)
            configFile = File.read(configFilePath)
            configFile = configFile.gsub(/-framework "Firebase" /, '')
            configFile = configFile.gsub(/-framework "FirebaseCore" /, '')
            configFile = configFile.gsub(/-framework "FirebaseCoreDiagnostics" /, '')
            configFile = configFile.gsub(/-framework "FirebaseNanoPB" /, '')
            configFile = configFile.gsub(/-framework "FirebaseRemoteConfig" /, '')
            configFile = configFile.gsub(/-framework "FirebaseInstanceID" /, '')
            configFile = configFile.gsub(/-framework "FirebaseAnalytics" /, '')
            configFile = configFile.gsub(/-framework "FirebaseABTesting" /, '')
            File.open(configFilePath, 'w') { |file| file << configFile }
        end
    end
end

Below is my podspec

#
# Be sure to run `pod lib lint NCore.podspec' to ensure this is a
# valid spec before submitting.
#
# Any lines starting with a # are optional, but their use is encouraged
# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html
#

Pod::Spec.new do |s|
  s.name             = 'NCore'
  s.version          = '0.1.0'
  s.summary          = 'A short description of NCore.'

# This description is used to generate tags and improve search results.
#   * Think: What does it do? Why did you write it? What is the focus?
#   * Try to keep it short, snappy and to the point.
#   * Write the description between the DESC delimiters below.
#   * Finally, don't worry about the indent, CocoaPods strips it!

  s.description      = <<-DESC
TODO: Add long description of the pod here.
                       DESC

  s.homepage         = 'https://github.com/neerajgoyal12/NCore'
  # s.screenshots     = 'www.example.com/screenshots_1', 'www.example.com/screenshots_2'
  s.license          = { :type => 'MIT', :file => 'LICENSE' }
  s.author           = { 'neerajgoyal12' => 'neerajgoyal12@gmail.com' }
  s.source           = { :git => 'https://github.com/neerajgoyal12/NCore.git', :tag => s.version.to_s }
  # s.social_media_url = 'https://twitter.com/<TWITTER_USERNAME>'

  s.ios.deployment_target = '8.0'

  s.source_files = 'NCore/Classes/**/*'

  # s.resource_bundles = {
  #   'NCore' => ['NCore/Assets/*.png']
  # }

  # s.public_header_files = 'Pod/Classes/**/*.h'
  s.frameworks = 'MapKit', 'Foundation', 'SystemConfiguration', 'CoreText', 'QuartzCore', 'Security', 'UIKit', 'Foundation', 'CoreGraphics','CoreTelephony', 'FirebaseCore', 'FirebaseRemoteConfig', 'FirebaseInstanceID', 'FirebaseAnalytics', 'FirebaseABTesting', 'FirebaseCoreDiagnostics', 'FirebaseNanoPB'
  s.libraries = 'c++', 'sqlite3', 'z'
  # s.vendored_framework = 'Firebase'
  s.dependency 'Firebase'
  s.dependency 'Firebase/Core'
  s.dependency 'Firebase/RemoteConfig'
#  s.dependency 'GoogleToolboxForMac'
#  s.dependency 'nanopb'
#  s.dependency 'Protobuf'
#  s.dependency 'FirebaseInstanceID'
#  s.dependency 'FirebaseAnalytics'
#  s.dependency 'FirebaseABTesting'

  s.pod_target_xcconfig = {
    'FRAMEWORK_SEARCH_PATHS' => '$(inherited) $(PODS_ROOT)/Firebase $(PODS_ROOT)/FirebaseCore/Frameworks $(PODS_ROOT)/FirebaseRemoteConfig/Frameworks $(PODS_ROOT)/FirebaseInstanceID/Frameworks $(PODS_ROOT)/FirebaseAnalytics/Frameworks $(PODS_ROOT)/FirebaseABTesting/Frameworks'
  }

  s.pod_target_xcconfig = {
    'OTHER_LDFLAGS' => '$(inherited) -ObjC'
  }
end

In the end my github project link at the commit where this solution is working both for Development Pod and its tests

Project Link

davidperrenoud commented 5 years ago

In my case, I solved this problem by adding in my .podspec:

s.static_framework = true