The 'Pods' Target Has Transitive Dependencies That Include Static Binaries' When Installing Gcm

The 'Pods' target has transitive dependencies that include static binaries' when installing 'Google-Maps-iOS-Utils'

I had figured out this after much struggle. On request google guys have put a tutorial on their git repository.
Here is the link

The 'Pods' target has transitive dependencies that include static binaries' when installing GCM

Update

With Cocoapods V 0.38.2 it is now possible to use GMC, or any other Objective-C frameworks with Swift frameworks like Alamofire

Make sure that you use use_frameworks! in the podfile

# Uncomment this line to define a global platform for your project
# platform :ios, '8.2'
use_frameworks!

target 'Project' do
pod 'Google'
pod 'Google/CloudMessaging'
pod 'Alamofire'
end

target 'ProjectTests' do

end

Old Answer

I'm using a Swift project too and i'm only using Objective-C frameworks, because Swift & Objective-C frameworks didn't work for me yet.

Try install GCM only without use_frameworks! and without the Alamofire framework (written in Swift)

# Uncomment this line to define a global platform for your project
# platform :ios, '8.2'

target 'Project' do
pod 'Google'
pod 'Google/CloudMessaging'
end

target 'ProjectTests' do

end

I ran into some problems when I'm importing GCM in the bridging header file. I'm curious if you encounter the same problems.

Solution for Google Cloud Messaging when the BridingHeader or GGLInstanceIDDelegate is not working, is to install 'Google' pod 'Google'

Cocoapods : target has transitive dependencies that include static binaries when installing 'VialerSIPLib'

if any one is Still wondring ,it can't be Done

Using dynamic vendored frameworks shouldn't be a problem even if the
developer isn't using CocoaPods with use_frameworks!, unless they for
some reason need a static lib, such as if building a command line
tool, where static linking is preferable.

So .You Could add the static library manually and link it in you project or wait for the vendor to Change the library into a dynamic Framework

More info here

For me this is how i solved it :-

1- Downloaded the static library using Cocoapods without use_frameworks!

2- used Carthage for Adding other libraries

3- and if a library Doesn't have a Carthage support i would do it manually (Not advised since alot of Duplicate dependencies may Appear)

The 'Pods-App' target has transitive dependencies that include static binaries when using GTM in a swift framework

Well, after months I had to come back to this project. Since the GTM pod hasn't change and still has static libraries as dependencies, it is still impossible to create a framework that has the GTM pod as dependency and to distribute it through Cocoapods.

I eventually decided to ignore Cocoapods and to manually add the third party frameworks to mine. So this answer won't match perfectly my question but it is the only way I found to ditribute my framework.

So, the first step is to create a new project. Select Cocoa Touch Framework :

Select Cocoa Touch Framework

Give it a name, mine will be myFramework. Once your workplace is ready, add a new target to it :

how to add a new target

Click on the cross platform tab and select the Aggregate template. I'll name mine Aggregate (so much originality). But we won't care too much about it for now.

Aggregate target

Once you have done that, your workplace is set for you to create your amazing framework ! Let's dive a bit further !

You're gonna now create or copy your source files. If you copy them, don't forget to check the box Copy items if needed and be sure that they are added to the framework target :

verify the options when copying your files

Until now, no big surprise I guess.

Since my question was about GTM, that's the framework we're gonna add as a dependency for our framework. I couldn't find the source elsewhere that on Cocoapods, so I created a new project (I used the application template and named it PodApp), then I added Cocoapods to it. Open your terminal and navigate into the PodApp project folder :

  1. pod init
  2. vi Podfile
  3. Under #Pods for PodApp, add pod 'GoogleTagManager', '~> 6.0.0'
  4. Save and close the Podfile, and run pod install
  5. Once the dependency is downloaded and installed, close the PodApp project window and run open PodApp.xcworkspace

In your Framework project, add a new new Group you'll name Frameworks (right click in the Xcode Navigator -> new Group). You're gonna copy all the dependencies Cocoapods downloaded in the PodApp project under the Frameworks group of myFramework. Once again, dont forget to add it to myFramework target and to copy items if needed as seen above.

Drag and drop frameworks in your project

On the below image, click on 1, 2, 3, if everything went well, you should see the frameworks/libs you just added on 4.

xcode project

For Firebase to work well, you'll also have to link with AdSupport.framework. Simply click on the + (5), search for it, and add it.

I had some troubles with GoogleToolBoxForMac too, what I had to do was to build the PodApp project, and to copy the GoogleToolBoxForMac.framework under PodApp/Pods/Products/ in the group myFramework/Frameworks/. Remember to add it to the correct target and to copy the item.

Another tricky detail related to GTM : you have to add some resources to your framework. Follow the step on the next image :

Sample Image

On the popup that opens, click on Add Other and find where you saved the GTM.framework, expand it and add the TagManagerResources.bundle (don't forget to copy the item !).

TagManagerResources.bundle

Since the other resources may give you warnings (in this specific example), you can delete them with the -.

If you want the final user of your framework to be able to use the frameworks that yours embeds, right above the "Copy Bundle Resources", open the "Headers" panel, drag and drop all the project headers to public.

All these frameworks can now be accessed by your own framework, but to make them available, you have to import their headers in your myFramework.h :

#import <myFramework/AnObjectiveCClass.h>

#import <GoogleTagManager/GoogleTagManager.h>
#import <GoogleTagManager/TAGCustomFunction.h>

#import <myFramework/GTMDefines.h>
#import <myFramework/GTMNSData+zlib.h>

#import <FirebaseCore/FirebaseCore.h>
#import <FirebaseAnalytics/FirebaseAnalytics.h>
#import <FirebaseInstanceID/FirebaseInstanceID.h>

#import <myFramework/GAI.h>
#import <myFramework/GAIDictionaryBuilder.h>
#import <myFramework/GAIEcommerceFields.h>
#import <myFramework/GAIEcommerceProduct.h>
#import <myFramework/GAIEcommerceProductAction.h>
#import <myFramework/GAIEcommercePromotion.h>
#import <myFramework/GAIFields.h>
#import <myFramework/GAILogger.h>
#import <myFramework/GAITrackedViewController.h>
#import <myFramework/GAITracker.h>

#import <myFramework/pb_encode.h>
#import <myFramework/pb.h>
#import <myFramework/pb_decode.h>
#import <myFramework/pb_common.h>

Alright, we're almost done !

Project Info / Build Settings

Now, select the Info section of your project (1 in the image above), check the version you're building for (mine is 8.0 for backward compatibility with most devices). Under the Configurations panel, remove the Debug by selecting it, and pressing the -.
Now select Build Settings (2 on the image), we're gonna make some changes in here.

  • Build Active Architecture Only : No
  • Allow Non-modular Includes In Framework Modules : No
  • Valid Architectures : arm64 armv7 i386 x86_64 (since armv7s doesn't build for some frameworks in this example)
  • Preprocessor Macros : PB_NO_PACKED_STRUCTS=1 PB_FIELD_32BIT=1
  • Enable Modules (C and Objective-C) : Yes

In your two targets, for the mentioned Build Settings, set them to $(inherited), it means that they will inherit from the parameters you just set on the Project Build Settings.

In the framework target, I also set the Other Linker Flags as what was set in the PodApp project, but I'm not 100% sure it is necessary.

(FYI, here they are : $(inherited) -ObjC -l"GoogleAnalytics" -l"c++" -l"sqlite3" -l"z" -framework "AdSupport" -framework "CoreTelephony" -framework "FirebaseAnalytics" -framework "FirebaseCore" -framework "FirebaseInstanceID" -framework "GoogleSymbolUtilities" -framework "GoogleTagManager" -framework "GoogleToolboxForMac" -framework "GoogleUtilities" -framework "JavaScriptCore" -framework "SystemConfiguration" -framework "StoreKit" -framework "AddressBook" -framework "CoreData")

Set Define Modules to yes.

Now select the Aggregate target, which will create a fat framework, a file containing several versions of our framework, one for each architecture we specified a few steps ago (arm64 armv7 i386 x86_64). We will have to tell Xcode what we want it to build. Follow the steps of the below image (1) :

image description

In the Build Phases, you want your Aggregate target to build the myFramework.framework before being built itself.

Once the myFramework.framework is added, press the + annotated as 2 in the picture, and select New Run Script Phase.
Paste the following script in it :

# Merge Script

# 1
# Set bash script to exit immediately if any commands fail.
set -e

# 2
# Setup some constants for use later on.
FRAMEWORK_NAME="myFramework"

# 3
# If remnants from a previous build exist, delete them.
if [ -d "${SRCROOT}/build" ]; then
rm -rf "${SRCROOT}/build"
fi

# 4
# Build the framework for device and for simulator (using
# all needed architectures).
xcodebuild -target "${FRAMEWORK_NAME}" -configuration Release -arch arm64 -arch armv7 -arch armv7s only_active_arch=no defines_module=yes -sdk "iphoneos"
xcodebuild -target "${FRAMEWORK_NAME}" -configuration Release -arch x86_64 -arch i386 only_active_arch=no defines_module=yes -sdk "iphonesimulator"

# 5
# Remove .framework file if exists from previous run.
if [ -d "${PROJECT_DIR}/${FRAMEWORK_NAME}.framework" ]; then
rm -rf "${PROJECT_DIR}/${FRAMEWORK_NAME}.framework"
fi

# 6
# Copy the device version of framework to Framework directory.
cp -r "${SRCROOT}/build/Release-iphoneos/${FRAMEWORK_NAME}.framework" "${PROJECT_DIR}/${FRAMEWORK_NAME}.framework"

# 7
# Replace the framework executable within the framework with
# a new version created by merging the device and simulator
# frameworks' executables with lipo.
lipo -create -output "${PROJECT_DIR}/${FRAMEWORK_NAME}.framework/${FRAMEWORK_NAME}" "${SRCROOT}/build/Release-iphoneos/${FRAMEWORK_NAME}.framework/${FRAMEWORK_NAME}" "${SRCROOT}/build/Release-iphonesimulator/${FRAMEWORK_NAME}.framework/${FRAMEWORK_NAME}"

# 8
# Copy the Swift module mappings for the simulator into the
# framework. The device mappings already exist from step 6.
cp -r "${SRCROOT}/build/Release-iphonesimulator/${FRAMEWORK_NAME}.framework/Modules/${FRAMEWORK_NAME}.swiftmodule/" "${PROJECT_DIR}/${FRAMEWORK_NAME}.framework/Modules/${FRAMEWORK_NAME}.swiftmodule"

# 9
# Delete the most recent build.
if [ -d "${SRCROOT}/build" ]; then
rm -rf "${SRCROOT}/build"
fi

# 10
# Remove .zip file if exists from previous run.
if [ -d "${PROJECT_DIR}/${FRAMEWORK_NAME}.zip" ]; then
rm -rf "${PROJECT_DIR}/${FRAMEWORK_NAME}.zip"
fi

# 11
# Zip the Framework and License all together.
zip -r "${PROJECT_DIR}/${FRAMEWORK_NAME}.zip" "${PROJECT_DIR}/LICENSE" "${PROJECT_DIR}/${FRAMEWORK_NAME}.framework"

On the script's step 2, change the name with your framework's name. Take time to understand what it does, and change its behavior if it doesn't meet your requirements. What it does in the end is that it creates a framework and an zip archive in your project's folder. I did that to link it with each of the Github release.

Everything should work fine now. Select Aggregate as the active Scheme, and run it.

Run Aggregate Scheme

If you want to add your framework in a test application, create a new Application project, simply drag and drop your myFramework.framework (from your myFramework folder for example) to your Application project. Once again, don't forget to add it to the correct target, and to copy the items. In your Application target, under the General tab, add your framework in the Embedded Binaries panel, but delete it once from the Linked Frameworks and Libraries panel since it should be there twice (check it out before doing it). Import your framework

import myFramework

and start using what you built !

NB : if you're trying with GTM, do not forget to add the stuff related to a GTM integration (your container and the GoogleInfo plist):

GTM related stuff

I really hope this will help you ! Do not hesitate to comment if anything isn't clear or if you meet a problem, I'll do my best to help you.

Please find my sources below :

  • Steps to Create Swift Framework + Cocoapods
  • cf answer of mattwritescode on 10/31/2017
  • cf answer of stewartmiles on Aug 17, 2017
  • Deep dive into Swift frameworks
  • iOS universal frameworks
  • Universal Framework in Swift

The 'Pods-Runner' target has transitive dependencies that include statically linked binaries

You might want to update CocoaPods, what version are you currently using

https://github.com/CocoaPods/CocoaPods/issues/7234#issuecomment-346119807

follow the instructions that are given in terminal output:

sudo gem install cocoapods

ios pod install gcm

Remove the use_frameworks! from your Podfile and import any Swift libraries manually.

Source (my question): 'The 'Pods' target has transitive dependencies that include static binaries' when installing GCM

iOS pod install gcm and pnchartswift

Unfortunately it is not possible to mix static and dynamic libraries, it's all-or-nothing.

Instead I will suggest you to make use of of the original Obj-C version PNChart, which would solve your issue using GCM.

That means your podfile would look similar to the following:

pod "PNChart"
pod "Google/CloudMessaging"

The only thing you have to do differently when importing the PNChart is to add a briding header importing these libraries. This will make them available anywhere in the code. It would look something like the following:

#import <PNChart.h>
#import <Google/CloudMessaging.h>

UPDATE 1:

Answered OP's question about how to identify static/dynamic.


As a rule of thumb:

  • All dependencies written in Swift are dynamic frameworks.
  • All dependencies written in Obj-C are static libraries.

Apple doesn't let you build static libraries that contain Swift, so the first statement will always be true. The second statement is a bit more complicated, since Apple has previously built a lot of dynamic internal frameworks in Obj-C. This possibility has not been available to third-party developers until iOS 8 (same time as Swift was released), so don't expect any new frameworks written in Obj-C to be dynamic since they might as well be written in Swift.

Right now we are simply in a stage of "limbo" when switching between the two languages. In 1-2 years then hopefully the majority of all third-party dependencies will be written in Swift and we don't have to worry about things like static/dyanmic.

If you are interested, then you can read more about it on the official CocoaPods blog post for release 0.36.



Related Topics



Leave a reply



Submit