18

I've created iOS Framework project using this method: https://github.com/jverkoey/iOS-Framework

Works pretty neat but I'm a little confused on how to include libraries/frameworks that are needed by my framework to work and, in particular, how to do it so that in case 3rd party client app that uses my framework can include these libs as well without conflicts.

Let's say my framework code needs these two things:

  • FacebookSDK.framework
  • libFlurry.a

The first one is an iOS Framework. When I add it to "Link Binary With Libraries" phase in my Framework and try compile the client project that uses my framework the linker complains about missing symbols - I need to add FacebookSDK to the client project which is great: there is no possibility of conflicts if client apps wants to use Facebook.

However when I do the same with Flurry static library I get duplicate symbols error when compiling client project. Which confuses me a bit, because isn't FacebookSDK.framework just a packaged static library?

ukaszs-iMac:FacebookSDK.framework lukasz$ file Versions/A/FacebookSDK 
Versions/A/FacebookSDK: Mach-O universal binary with 3 architectures
Versions/A/FacebookSDK (for architecture i386): current ar archive random library
Versions/A/FacebookSDK (for architecture armv7):    current ar archive random library
Versions/A/FacebookSDK (for architecture cputype (12) cpusubtype (11)): current ar archive random library

So my questions are:

  1. why a library embedded in framework (like Facebook) is not linked to my Framework project product, whereas library included as .a file is?
  2. how to include .a file in my framework so that it does not produce duplicate symbols error when client app using my framework also needs this particular static library?
Łukasz Sromek
  • 3,637
  • 3
  • 30
  • 43

7 Answers7

17

For the use case you are describing, you should be linking to these external libraries from your application, NOT your own framework. It can be one or the other, but it can't be both.

If you decide that these dependancies belong as the responsibility of the application, you would remove them from "Link Binary With Libraries" and any other explicit linking configuration, and just project your framework project with the path to these frameworks and libraries so it can find the symbols (but not link against them) at compile time (i.e. the path to the libraries should be included LIBRARY_SEARCH_PATHS).

quellish
  • 21,123
  • 4
  • 76
  • 83
  • I want to create a framework which has Google Maps sdk dependency. Could you please let me know the steps how to do that. – Invincible Apr 23 '17 at 05:20
  • 11
    @quellish If the framework uses #import "FacebookSDK.h" you the dependencies are linked from the application. how would you create a binary of the framework itself since it will fail because undefined symbols of FacebookSDK. Can you please explain this? – hariszaman Jul 04 '17 at 12:33
4
  1. Use cocoapods , it's easy (http://cocoapods.org/)

  2. Your application developers will have to include the podfile and download the dependencies.

  3. While developing your SDK use a reference application/demo app on top of the SDK to simulate this.

rustylepord
  • 5,681
  • 6
  • 36
  • 49
  • Quick question, trying to figure out the scenario when an application uses 2 frameworks and both frameworks use a shared library, is this an issue for the linker when building the app? – Bob Jan 31 '15 at 00:15
  • No I don't think so , since you have only one pod file exposed. – rustylepord Feb 02 '15 at 09:34
  • 2
    Do not know how practical this is as an answer. sure it takes away the pain from framework developer. you can't force users of your framework to use cocoapods, especially if their apps are using other dependancy management systems or their apps have been out there for a while & they just want to include your framework for a new addition... – nsuinteger Nov 11 '15 at 09:52
  • @rustylepord do you have some tutorial on this? I want to develop a framework which uses FB SDK, I want to give my framework to my vendors and once they install my framework using cocoapods it should install FB also as it is a dependency. – anoop4real Jul 19 '17 at 05:39
2

You shouldn't link anything when building your framework but just create a *.a binary with your framework's objects.

Also you should not include code from other libraries in your framework as client applications may be adding the same libraries directly or requiring different versions of them, thus creating conflicts.

Off course you can reference *.h header files from other libraries in your framework in order to compile your objects.

As a result the installation steps for your framework should detail other required frameworks/libraries needed, their supported versions, how to add resource files (if any), etc. Just some of the many reasons why you may want to consider Creating a CocoaPods' podspec instead.

Rivera
  • 10,792
  • 3
  • 58
  • 102
1

You should use CocoaPods. Your dependency on Facebook can be done by linking against the CocoaPod.

If you want to include that particular version of Facebook in your pod, you can put it in your repo and use the vendored_frameworks property to refer to it.

Similarly if you wanted to vendor libFlurry.a, you could do so using s.vendored_libraries.

For system libraries, you don't need to vendor them, e.g. libZ.a.

I strongly recommend creating your CocoaPod using pod lib create YourPodName. They've recently changed the mechanism for how this works and it's really nice.

You can create an Example project that shows how to use your code in context of an app.

Then one of the other neat things I just learned about, someone can do pod try YourPodName and it will automatically download, integrate and run the Xcode project.

CocoaPods is worth the trouble.

funroll
  • 35,925
  • 7
  • 54
  • 59
  • For large frameworks (e.g. Parse and Facebook) and when working with multiple custom development pods, I found that CocoaPods slows down your development because it requires recompilation of all the sources of the SDK as well as your code. – fatuhoku Nov 25 '15 at 10:01
  • @fatuhoku I've actually been trying to solve this problem recently for some in-house developed pods. There should be a way to leverage the pod specs but not need to recompile everything all the time. Haven't figured it out yet. – funroll Nov 25 '15 at 16:52
  • @funroll Is there a code I need to include in my podfile so I can link against a pod? – Fernando Reynoso Oct 28 '19 at 22:58
1

I am building my framework project using CocoaPods. The framework uses some 3rd libs from CocoaPods. Podfile specifies to install dependency on target of the framework. When I build the framework, it includes all libs in the binary.

If I add use_frameworks! in Podfile, when the framework is built, it will not include 3rd party libs.

Evan
  • 1,152
  • 1
  • 11
  • 18
  • Hi Evan, I have the same requirement and was using the same steps you said above for Dynamic Framework and it compiles and links as expected. Now I need to generate a Static Framework with 3rd party libs included in the binary. How do I do that? To build a Static framework I just updated Mach-O type to Static Library and was able to generate Static Framework except that the binary doesn't have 3rd party libs. – Shiva Reddy Sep 26 '20 at 05:02
0

Use CocoaPods dependancy manager. Here's a good guide,

7 miniute video tutorial

Rukshan
  • 7,902
  • 6
  • 43
  • 61
-3

Mostly if you install third party frameworks you can install with cocoapods (which is really nice, I would definitely do that) or they offer you to download the framework and include it in your Project. If you decide to download the library and include it there is normally a list of frameworks you need in the "Getting started" guide.

Means: Offer them to install using cocoapods and to download your library but do not include anything else, give them a list what they need.

iCaramba
  • 2,589
  • 16
  • 31