What is the usage of OTHER_LDFLAGS in podspec? - ios

My project has various plugins, and every plugin associate with one podspec file. e.g. I have coreSDK plugin in which we have core functionality for project. In coreSDK podspec we added few dependencies for google, Facebook and twitter.
Currently Im working social integration for all three framework but I observed these three frameworks are not showing added to coreSDK target because of that I am not getting social framework access. One of my friend suggested me to add those frameworks in OTHER_LDFLAGS so that they will get added to coreSDK target.
I will do this but before that I want to know what is the purpose of OTHER_LDFLAGS in podspec. How it works?

OTHER_LDFLAGS is nothing but Other Linker Flags. It causes the actual pods to be linked into your application.

This flag is used by xcodebuild which uses it when calling ld linker to link an app target with a frameworks and indicate in which languages they were written.

Related

use_framework! in Podfile caused 'React/RCTBridgeDelegate.h' not found

I'm currently integrating a private library from vendor which they mentioned it's required to have use_framework! added in Podfile. Apparently I found out from them, the framework is written in Objective-C, if so.. why is use_framework! needed? I thought this is the reason why we use use_framework!
use_frameworks tells CocoaPods that you want to use Frameworks instead of Static Libraries. Since Swift does not support Static Libraries you have to use frameworks.
Currently I'm facing this build time issue 'React/RCTBridgeDelegate.h' not found in AppDelegate.h
Side info,
My project is running on React Native Firebase v6, hence I have added # $RNFirebaseAsStaticFramework = true to handle the use_framework! case. Read more about this here.
I'll get the following error if I don't append use_framework!
Framework not found helloFramework
Here's the Xcode error . . . .
I confirmed my project's scheme has the React Bulleyes icon from podfile and I'm building on this scheme
My questions, why do I get this issue when I use use_frameworks! ? What's is the correct way to handle this issue?
Update:
Created issue at React Native Github
TLDR
Append $(inherited) at Framework Search Paths .
Explanation
Apparently, when we apply use_frameworks! at Podfile. Our Xcode project will replace libPods-{projectName}.a with Pods_{projectName}.framework.
Since our project is relying on Frameworks to build, we have to append $(inherited) to Framework Search Paths at Target > Build Settings > Search Paths > Framework Search Paths. This will inherit the build settings from project level to target level. Read more here.

Embedding XCFramework in application with project framework dependencies

I have an Xcode workspace which features a project with an iOS Application target, and another project with a Framework target. The framework target is dependent on another framework, which is integrated in the form of an xcframework:
MyApp
MyFramework
OtherFramework
Using regular OtherFramework.framework would require it to be linked to MyFramework and then embedded in MyApp even though MyApp doesn't require the framework itself. However when integrating with xcframework, this project then fails to build with a No such module 'OtherFramework' error.
Project settings:
MyFramework Project
MyApp Project
Removing OtherFramework.xcframework from the MyApp target fixes the build issue, but then causes library not loaded errors as the framework is not present in the application.
Demo project here: https://github.com/msaps/XCFramework-Link-Issue
How are you meant to link an xcframework in an application and link in a dependent framework?
Why?
pyckamil just posted this article which explains the issue in detail: Everything wrong with XCFrameworks.
It turns out Xcode has an optimisation for the ProcessXCFrameworkLibrary step which extracts the correct .framework from an .xcframework for the active build architecture. This is only run once which causes issues for additional targets that try to link the same framework.
Update
This issue is resolved in Xcode 12.0
UPDATED - Resolved in Xcode 12.0
shinsuk came up with a reliable workaround that works by adding architecture-explicit framework search paths to ensure the correct .framework within an XCFramework is found.
Details can be found in the README.
Check build settings and defining the Framework Search Paths to a folder which contains the frameworks in question. If the frameworks are placed in your project directory, simply set the framework search path to $(SRCROOT) and set it to recursive.
check the response Getting error "No such module" using Xcode, but the framework is there
IMO, It seems not xcframework issue.
Check out this answer: https://stackoverflow.com/a/59435627/2661407
Umbrella frameworks are not supported on iOS, watchOS, or tvOS.
OtherFramework.xcframework should be signed and embedded in your host app.
and add "#executable_path/Frameworks" setting into your MyFramework.framework > Build settings > Runpath Search Paths.
I had this issue as well after using xcframework instead of framework. So I changed my project structure:
The MyFramework Peoject embed OtherFramework.xcframework,Then make it exported using #_exported import OtherFramework in MyFramework Project. And the MyApp just link MyFramework but can both import/use MyFramework and OtherFramework.
BTW, It seems to custom the #rpath and manual codesign the OtherFramework.
I had an issue like that as well.
First, make sure if you have MyFramework.framework file within the same directory as MyApp.
Second, when building MyFramework.framework, make sure that OtherFramework.xcframework is as well in MyFramework's project directory.
And one more thing, check target SDK versions. They should be somewhere on the same level.
I had the same issue as you, and after seeing your pbxproj I think it can be solved the same way.
Change your framework search path to recursive (either through UI or manually editing the pbxproj "$(SRCROOT)/../Frameworks" => "$(SRCROOT)/../Frameworks/**"), like so: https://github.com/msaps/XCFramework-Link-Issue/pull/1/files

Interdependent frameworks Xcode

I'm working on a set of (internal use only) frameworks that encapsulate various elements of my development process. Some of these frameworks are dependent on one another, but I'd like to keep them separate so as to be more manageable. I'm running into various compiler errors now which I think have to do with the dependencies overlapping.
At the moment all of these frameworks and an app share the same workspace as different projects. How can I configure my app and frameworks to compile in this situation?
Here's the boiled down idea:
App dependencies: A.framework B.framework C.framework D.framework
A.framework dependencies none
B.framework dependencies A.framework
C.framework dependencies A.framework B.framework
D.framework dependencies none
More info:
Currently, in C.framework, I have dragged A and B.frameworks into the "Frameworks" folder. I read elsewhere to do that an to not Link Binary With Libraries. Either way, I get a compiler error for some functions that are in the headers of both A and B.framework:
ld: symbol(s) not found for architecture armv7
The build settings for A & B have "Build Active Architectures Only" set to NO and valid architectures set to include "armv7".
B.framework, however has no issue building.
Update :
I'm now able to get the App to build, by Linking Binaries in each of the targets... however it immediately crashed with this error :
dyld: Library not loaded: #rpath/A.framework/A
Referenced from: /var/containers/Bundle/Application/94488FD7-B731-4E6B-86E6-3D2F09BB4E04/App.app/App
Reason: image not found
The problem most likely causing this error message is related to the libraries not building in the correct order.
One possible solution to the order the libraries get built lies in adding all dependent libraries as sub-projects to the main project. This is appropriate when all projects are owned and maintained by the same entity, as the OP mentioned.
Add each project to the main one by going to "Build Phases -> Link Binary With Libraries.", then add each framework project file using the "+" button. Then go to each sub-project, and add it's dependencies.
For B.framework project, go to "Link Binary With Libraries.", and add A.framework as a dependency.
Similarly, for C.framework, add A.framework and B.framework, as dependencies.
As a suggestion, also add all frameworks to "Link Binary With Libraries.", under the main project, all of them get used.
One thing to keep an eye out in such situation, is to make sure there are no circular dependencies, and dependencies don't get added multiple times in different projects.
The image below shows an example of a similar setup to the one in the OP. There is a FrameworkTest project. All 4 frameworks are added as "Link Binary With Libraries." under it. For FrameworkB, FrameworkA is added under "Link Binary With Libraries.". Similarly workflow for FrameworkC. Xcode seemed to figure out the dependencies without the need for "Target Dependancies" settings. This project builds and runs. Haven't gotten as far as calling items from each framework.
Another solution to this, using a workspace would be to have one top level project, and move each framework as a sub-project. Then add each framework to the top-level project's "Embedded Frameworks" section.
Use the "Link Binary With Libraries." section of each framework sub-project, to define its dependencies.
Ok, so I seem to have gotten past this in the following way.
Instead of having my workspace have each framework as a separate "top-level" project, I moved the framework projects into sub projects of the App project.
Then, I added each framework to the App's "Embed Frameworks" section (and was able to remove it from "Link Binary.." and "Target Dependencies" sections.
Within each framework, I used the "Link Binary..." section to include the dependent frameworks.
I'm not sure that I understand all the pieces to why this works, but at least I can move on!
Thanks #vel-genov for your help!
Make sure these settings are correct:
FRAMEWORK_SEARCH_PATHS (in Build Settings)
Link Binary With Libraries (in Build Phases)
INSTALL_PATH (change to #rpath for all frameworks) (in Build Phases)
#rpath (Runpath Search Paths) (add #executable_path/../Frameworks for your app and all frameworks that need embedded another framework) (in Build Settings)

CocoaPods and Target Dependencies

I recently inherited an old iOS 5 multi-project that have a xcworkspace that have the following projects:
Communications project: contains some reusable code and frameworks, defines a target as static library.
Client project: iOS client project that has nested a symbolic link to the 1. project and includes a Target Dependency to it.
Manager project: same structure as described for 2..
Note: to clarify the meaning of static library and nested projects, please have a look to http://www.raywenderlich.com/41377/creating-a-static-library-in-ios-tutorial (Method 2: Subprojects).
I am trying to add CocoaPods for the 3rd project, but I can't modify the HEADER_SEARCH_PATHS and OTHER_LDFLAGS values because they are use to link the static library.
Is there any workaround for this?
I found the answer, it is as simple as add manually the $(inherited) option to HEADER_SEARCH_PATHS without deleting the existing static library headers dir.

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.

Resources