iOS - Building a static framework with other framework dependencies - ios

I am building an iOS static framework (MyFramework.framework) using the method described here.
However, methods in MyFramework.framework are also dependent on the OpenCV framework for iOS (opencv2.framework). Now I understand that I cannot build/link the OpenCV symbols into MyFramework.framework directly, and that the parent project that includes MyFramework.framework will also have to include the opencv2.framework.
My question is this: when building/developing the MyFramework.framework project, how can I reference the opencv2.framework headers? Do I have to copy the headers to the MyFramework.framework project even if I don't directly have opencv2.framework in there? Or is there another way to reference them?

Drag the OpenCV2.framework to the Frameworks group in Xcode. In the Build Phases, remove the framework from the Link Binary With Libraries build phase. Now you can reference the OpenCV2 headers without linking it directly to your framework.

Related

XCode Framework doesnt contain dylib symbols

I'm trying to integrate 2 dynamic libraries (written in C) together with its API header (one header) into a xcode framework, let's call it nanogen_c, so that I can call its functions inside a swift application.
For this I'm creating a framework in xcode, build it, and then I would expect the framework to contain the symbols of the dynamic libraries, so that ultimately I can create a xcframework containing both the arm64 and x86_64 frameworks, and when including it in a project it would be able to link.
But when checking the symbols of the framework, it's (almost) empty:
% nm -gU nanogen_c
0000000000007ff8 S _nanogen_cVersionNumber
0000000000007fc8 S _nanogen_cVersionString
And so when creating an xcframework out of these, I get linking issues because the function symbols are not found in the framework.
I'm pretty sure I'm missing some step in building the framework, but I can't figure out what...
The steps I do to make the framework (here for the arm64 architecture):
Create new Xcode project > Framework called nanogen_c
Drag libraries and headers into the project
At pop-up : Check ‘Copy items if needed’
In project settings > Build Settings
Set ‘Enable Bitcode’ to No
Set ‘Build Libraries for Distribution’ to Yes
Set ‘Skip Install’ to No
In project settings > General > Frameworks and Libraries
Change ‘Embed’ options for both dylibs to ‘Embed & Sign’
In project settings > Build Phases > Headers
Move the API header to public
In nanogen_c.h framework header, append this line at the end:
#import "nanogen_c/<name_of_api_header>.h"
Set build target to ‘Any IOS Device (arm64)’
Press ‘cmd + B’ to build
Framework is built into /Users//Library/Developer/Xcode/DerivedData/nanogen_c-/Build/Products/Debug-iphoneos/nanogen_c.framework
Check contents of nanogen_c.framework, it contains the dylibs and header, but nanogen_c file doesnt contain the symbols from the dynamic libraries.
I know that the dynamic library itself contains all the necessary symbols, because when manually adding linker flags to the xcode project it succesfully links/builds, however this is no permanent solution because afterwards when trying to install the application to the iphone, the dynamic libraries are not installed with it.
Does anyone know what I'm missing?

Convert a static library target into a framework target in an Xcode project

I have a an Xcode project which produces a static library. My team plans all new development in Swift. It is not possible to add Swift files to the static library project. We are dropping support for iOS 7, so it is now possible to include frameworks in our iOS app. Therefore, I intend to convert my static library project to a framework project.
I have looked but I cannot find any tools or advice for how to perform this conversion. The static library is large (more than 100 .m files).
I'm hoping for a better answer than create a new parallel framework target. I've attempted this twice. The first time as a swift target, but I wasn't able to easily import all the Objective C files. Next, as an Objective C target, but there is no .pch anymore.
To convert the static/dynamic linked framework from static linked library,
Add a new cocoa touch framework as a TARGET in your existing static linked library project.
In the Build Phases, adding all the .m, .mm, .c, .cpp, .metal, etc. into "\Build Phases\Compile Sources" phase of your static linked framework target.
Put the headers that you want to exposed in to "\Build Phases\Headers".
For dynamic linked framework, remember to check the Mach-O Type setting in your Build Settings. If you are going to use swift, you need to make sure the Mach-O type is set as dynamic library so that it will become a dynamic linked framework. For static linked framework, you'll need to set the Mach-O type as static library, but you cannot use swift in the converted static linked framework (only objective-c, objective-c++, C++, C, etc. are allowed).
Then for the app that wants to use this framework just need to include the headers as #import and add the framework into "Build Phases\Link Binary With Libraries" of your App Target. If the converted framework is dynamic linked framework, you will need to put it into "Embedded Binaries".
I saw that someone created the framework manually, creating a module.framework file and copying all the header files in a module.framework/Headers folder. This solution seems to work, the project can import correctly the files and see them as a framework correctly.
I'm not sure this is the best way to do it tough, I'm trying it on a big project that ATM is importing the static library through cocoapods, but it seems like I have some problem with the visibility of some of the classes using the framework.

Adding frameworks to Xcode project

I have added a framework to xcode project. Under Build phases->Link Binary With Libraries.
The framework consists of a library file (.a file) and a folder "Headers" which includes all the necessary header files for that framework.
Now I am trying to import a header file in the framework to one of my classes.
#import <MySDK/MyHeaderFile.h>
But an error occurs "Symbol not found" while building.
My understanding was that, if we are using framework instead of library file there is no need to add the header files path in "Header Search Path".
But still, I have specified the path to my framework in header search path.
Also I have specified the framework path in Framework search and Library Search path options.
This is first time I am working with frameworks. For libraries I just added the .a files and specified full path to header files in header search path.
What configuration am I missing for adding frameworks?
If it's a static library file and a bunch of headers, it's not a framework. A framework is a specific method of packaging files. On MacOS X static and dynamic frameworks have one structure, while static frameworks on iOS have a different structure.
For a static framework using Xcode 5, your file structure would look like this:
MySDK.framework/
en.lproj/
Headers/
MyHeaderFile.h
Info.plist
MySDK
Where MySDK is the binary archive file (it should not be MySDK.a). If you have a file ending in .a , you have a static library rather than a framework. Building a static framework using Xcode 5 isn't easy but it is also not impossible. Building a static library is much, much easier and trouble free however. It sounds like you already have a static library, so you just have to tell Xcode where to find the library archive and header files using the appropriate search path settings for your project or target.
If/when you DO have a framework, adding it to "Link libraries and frameworks" OR setting "Other linker flags" to "-framework path/to/MySDK.framework" will work fine.
Newer versions of Xcode may support different functionality for building or using frameworks, however linking against them should be largely the same.
MySDK/MyHeaderFile.h : This explains that your library is inside MySDK folder. Check if it exists in same path. Otherwise you'll get "Symbol Not Found" error.

handling dependencies for iOS Framework project

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:
why a library embedded in framework (like Facebook) is not linked to my Framework project product, whereas library included as .a file is?
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?
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).
Use cocoapods , it's easy (http://cocoapods.org/)
Your application developers will have to include the podfile and download the dependencies.
While developing your SDK use a reference application/demo app on top of the SDK to simulate this.
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.
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.
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.
Use CocoaPods dependancy manager. Here's a good guide,
7 miniute video tutorial
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.

Embed OpenCV framework inside another xCode project without linking

I have developed an xCode static library for an iPhone App using OpenCV.
Now I want to give my static library to them but I don't want them to go through the hassle of making OpenCV work in their project by changing build settings and all that, that's what I already had to do myself in the static library.
I usually use the 'Projectception' method by dragging my static-library-project into my main xCode project. However when I use this method I usually need to add all the frameworks I use in the static library project again in my main project in the 'Link Binary with Libraries' build phase.
So my question is: is there a way that the OpenCV is only in my static library project and that a new project that imports this static library does not have to do anything extra for OpenCV to work?
Yes. Clone(copy) opencv inside your project (headers and implementation)*, desclare the copied files inside your project and don't use any c/c++ include folder and any library linkage.
*implementations are in modules/.../src/

Resources