Static libraries and frameworks are only linked to the user target by classic CocoaPods. That approach will not work if we are building frameworks and have a vendored static library as a transitive dependency, because the linker expects all symbols to be resolved in this case.
Using -undefined dynamic_lookup
or linking to both the dynamic framework and the user target could be solutions to pursue for the future, but as a first step, we should reject these cases.
To reject vendored_libraries
we can simply use the file extension, for vendored_frameworks
we have to check if the included binary is statically or dynamically linked.
Even if we find a workaround for the linking without duplicating symbols, mixing frameworks and static libaries won't work for another reason: we don't build clang modules for static libraries, which causes compiler errors, if the framework's public headers import public headers of the static library with a non-module-import.
I guess, that happens because public headers are imported by the umbrella header and will have implicit clang module exports. That also includes transitive imported headers. If the imported header is not within the same target, it can't probably be exported as nested module, if it isn't already part of a clang module itself.
So I'm trying to work around a few complications. My app is Objective-C. My framework is written in Swift, and depends on Swift frameworks, Objective-C frameworks, and static libraries distributed as CocoaPods/frameworks.
So I've got the static library as a transitive dependency issue as the main bad guy.
I've also got the no-dynamic-frameworks on iOS 7 issue, less so of an issue, but would be amazing to tackle.
@fluidsonic seems to have some serious wisdom on this topic.. as apparently Our app uses use_frameworks! (aka dynamic frameworks) for development & testing and use_frameworks!(false) (aka static libraries) when submitting to the App Store (due to lack of iOS 7 support).
We've split our app into a lot of parts/modules (using separate Pods for each) which are linked together by CocoaPods. These modules in turn use several static library Pods as transitive dependencies and they work for us even when all Pods are built as dynamic frameworks.
Sounds like magic to me. Eager to hear more/see some snippets/podfiles/spec if possible!
Regarding your second issue: Getting dynamic frameworks work on iOS 7 is only possible for Development & Ad Hoc builds. It's the App Store which will reject such apps when submitting. We solved that by having separate targets for dev/testing & App Store: Testing
uses dynamic frameworks while App Store
imports the framework's Swift files directly. So far this works fine as long as there are no file name collisions.
The workarounds necessary for making this work depend on the static Pod you're trying to use.
Let's use Crashlytics
as an example.
I'll assume you use the latest non-beta CocoaPods version.
We have a dynamic framework Pod in our app called CrashlyticsService
which basically just abstracts away our Crashlytics code. It's also written in Swift.
The Podspec is similar to this:
Pod::Spec.new do |s|
s.name = 'CrashlyticsService'
s.platform = :ios, '7.0'
s.source_files = '**/*.swift'
s.dependency 'Crashlytics'
s.pod_target_xcconfig = {
'FRAMEWORK_SEARCH_PATHS' => '$(inherited) $(PODS_ROOT)/Crashlytics',
'OTHER_LDFLAGS' => '$(inherited) -undefined dynamic_lookup'
}
end
Because Crashlytics's Pod is not a valid framework (it includes headers of the unrelated Fabric framework - I reported that bug to them but they didn't fix it yet) I slightly modified the Pod's header files & use this modified version instead in our app's Podfile
:
# tell CocoaPods what version of Crashlytics you want
pod 'Crashlytics', :git => 'https://github.com/fluidsonic/Crashlytics.git', :tag => 'v3.1.0'
# tell CocoaPods to use your dynamic framework (you most likely already have something like this)
pod 'CrashlyticsService', :path => 'Modules/Services/Crashlytics'
In order to prevent CocoaPods from complaining about the use of static transitive dependencies you use this simple hack in your Podfile
:
pre_install do |installer|
# workaround for https://github.com/CocoaPods/CocoaPods/issues/3289
def installer.verify_no_static_framework_transitive_dependencies; end
end
If you already have another pre_install
hook must add the code to the existing one instead.
Other static Pods are added in a similar way although some will need more or other workarounds.
If you have any problems when integrating the example or other static Pods then just post the errors here.
So, this is pretty great. I got my transitive static dependency (Firebase, in this case) working.
A couple questions on that front, given that I'm using a custom podspec for Firebase..
1) Is it possible to define pre_install hooks in podspecs?
2) Could the s.pod_target_xcconfig
be put in the Firebase podspec instead of the consuming framework podspec?
So, my afternoon is already 100 times better. I'm still very interested about the iOS 7/Swift situation though. Besides how you actually pulled off automating the pulling of the frameworks Swift files in, I'm most interested in what happens then to namespaces? If the Swift files are just being pulled in manually instead of as a framework, don't they then lose their module/namespace? If so, I think Swift frameworks like Alamofire, ReactiveCocoa, etc. would just crumble to pieces... types would be redefined, access control means nothing, etc.
Great that the workarounds work for you too!
Regarding your questions:
pre_install
hook in .podspec
s. If you want to distribute a public framework which depends on these workarounds you'll have to mention them in the set-up instructions for developers using your framework..podspec
. You could try using user_target_xcconfig
instead of pod_target_xcconfig
but I don't think that this will work. Like for the other question you'll have to mention the workaround in the set-up instructions.The situation here is indeed really bad but I don't think there's much room for improvement.
App Store
target. We update the references manually from time to time whenever we need to make a new App Store archive. Usually this takes us 1-2 hours every few weeks which is okay.What is a problem though are the import
statements which must not be used when everything is thrown in the same namespace - i.e. in App Store builds. We solved that by using conditional compilation (for which you have to touch the code):
import UIKit
#if !FALLBACK
import Module1
import Module2
#endif
Then you just need to add the -DFALLBACK
flag to the App Store
target and all imports are gone.
We're really looking forward for dropping iOS 7 support asap...
Okay, I think that's what I expected. Thanks for confirming!
Thanks again!
@fluidsonic One last question: trying to push my podspec to a private spec repo, and its failing with the transitive static dependency error. How can I circumvent that (given that the pre_install hook hack is Podfile only)?
Okay, we're done with iOS 7 support in our app and will drop it now!
use_frameworks!
for one target and use_frameworks!(false)
for other targets. CocoaPods now always uses frameworks which will break for use_frameworks!(false)
builds because the frameworks are built but never copied nor does the App Store support the frameworks on iOS 7.We might get around the problem by using deduplicate_targets: false
mentioned in the release notes but for some stupid reason this must be set by each developer on their own machine instead of just in the Podfile. We're not investing any more time in making our app iOS 7 compatible.
Anyway that deduplication bug is not related to this GitHub issue and such a discussion should take place in the related issue. I primarily post it here as an important follow-up for @mhuusko5.
@fluidsonic having issues with the..
s.pod_target_xcconfig = {
'FRAMEWORK_SEARCH_PATHS' => '$(inherited) $(PODS_ROOT)/Crashlytics',
'OTHER_LDFLAGS' => '$(inherited) -undefined dynamic_lookup'
}
.. method, where my project builds fine for simulator/device, but get a symbol not found (from the static library) error at runtime when targeting device.
Ever run into this?
It appears that the framework is in fact being loaded, and classes of that framework are accessible. The only things inaccessible/causing the crash are "FOUNDATION_EXPORT"s.
Anyone have any idea why CP would successfully link a static library, but not some of its exported string variables?
What exactly is not found? What does the log say?
It was some random NSString consts. Ended up fixing this yesterday, and while I'm at it, completely avoiding the need for..
s.pod_target_xcconfig = {
'FRAMEWORK_SEARCH_PATHS' => '$(inherited) $(PODS_ROOT)/FRAM_NAME',
'OTHER_LDFLAGS' => '$(inherited) -undefined dynamic_lookup'
}
.. and..
pre_install do |installer|
# workaround for https://github.com/CocoaPods/CocoaPods/issues/3289
def installer.verify_no_static_framework_transitive_dependencies; end
end
.. by creating a pod for the framework as follows...
Pod::Spec.new do |s|
s.name = 'Spotify-iOS-SDK'
s.module_name = 'Spotify'
s.summary = 'The new Spotify iOS SDK.'
s.version = '0.10.3'
s.license = { :type => 'proprietary', :text => 'https://developer.spotify.com/developer-terms-of-use/' }
s.author = { 'Spotify' => 'https://developer.spotify.com/' }
s.homepage = 'https://developer.spotify.com/technologies/spotify-ios-sdk/'
s.platform = :ios
s.ios.deployment_target = '7.0'
s.requires_arc = true
s.framework = 'Foundation', 'AVFoundation'
s.source = { :http => 'https://github.com/spotify/ios-sdk/archive/beta-10.zip' }
# The goods
s.pod_target_xcconfig = {
'OTHER_LDFLAGS' => '$(inherited) -ObjC'
}
s.preserve_paths = 'ios-sdk-beta-10/Spotify.framework/Spotify'
s.prepare_command = 'touch Empty.m && cp ios-sdk-beta-10/Spotify.framework/Spotify libSpotify.a && cp ios-sdk-beta-10/Spotify.framework/Headers/* .'
s.source_files = 'Empty.m', '*.h'
s.public_header_files = '*.h'
s.vendored_libraries = 'libSpotify.a'
end
Another working example of this method (the one I yanked it from), is Firebase as of a couple days ago: https://github.com/CocoaPods/Specs/blob/master/Specs/Firebase/2.4.1/Firebase.podspec.json
Anyway, so it behaves perfectly with use_frameworks! or not, as a direct or transitive dependency, with Swift or Obj-C. Very nice and tidy.
Will report back if I end up having any issues. Have done sim/device builds, haven't tried a TestFlight build or App Store submit, but I'm not expecting issues. In the case of Firebase, their static lib is even bitcode enabled, and it behaves appropriately bitcode wise when used as a direct or transitive dependency.
0.39.0.rc.1
seems to break everything again. Getting a bunch of undefined symbol errors from transitive library pods, when compiling.
Has the way static libraries are treated changed?
@mhuusko5 please open a new issue with the information requested in the contributing guidelines
@mhuusko5 Same here. Tried your solution, all good for simulator builds, but getting errors like this when building for device:
Undefined symbols for architecture arm64:
"__mh_execute_header", referenced from:
-[DeviceInfo executableUUID] in libSplunkMint.a(DeviceInfo.o)
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
I'm trying to include dynamic framework into the project, which uses SplunkMint
static framework/library as a transient dependency.
Have you opened a new issue to track this one?
I'm using 1.0.0.beta5
at the moment.
@mhuusko5 @fluidsonic have you find a definitive way of including a dependency on a podfile to a pod that has a dependency with static framework?
@matynz I don't think there is a definitive solution for this issue.
It always depends on the Pods you're trying to use and how you want to use them.
Google & Firebase Pods for example are total pain to use with dynamic frameworks. And the workarounds only work if you use each static framework/library in only a single Pod and not from multiple Pods.
Our app has two static dependencies left: AppsFlyerFramework
and GoogleAnalytics
. They're both linked to and used inside a sub-Pod of our app instead of from the app target directly. That way we can abstract our tracking logic through our sub-Pod(s).
We used to have a lot more static frameworks but less and less were necessary over time.
All the hacks & workarounds we did in order to use them along our dynamic frameworks are doing fine in production for more than a year now.
We'll continue to use them until we no longer need any static frameworks. We don't accept that static dependencies prevent us from using dynamic frameworks which would in turn prevent us from building a well-structured modularized app (and Swift still requires dynamic frameworks).
We're currently using these workarounds:
Podfile: Disable CocoaPod's check for transitive static dependencies.
pre_install do |installer|
# workaround for https://github.com/CocoaPods/CocoaPods/issues/3289
def installer.verify_no_static_framework_transitive_dependencies; end
end
Podfile: Make sure the static frameworks are not linked to the app itself by editing the generated xcconfig
files. We link the static frameworks directly to the Pod which needs them. Note that while the Pod is called AppsFlyerFramework
the actual framework is named AppsFlyer
.
post_install do |installer|
project = installer.pods_project
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 "AppsFlyer" /, '')
configFile = configFile.gsub(/-framework "GoogleAnalytics" /, '')
File.open(configFilePath, 'w') { |file| file << configFile }
end
end
end
We've also made our own .podspec
for the GoogleAnalytics
Pod which turns the static library into a static framework since Swift can only work with frameworks/modules:
GoogleAnalytics.podspec:
{
"name": "GoogleAnalytics",
"version": "3.14.0",
"summary": "Google Analytics - measure your app performance",
"description": "Google Analytics lets you track application events you care about and gain insights from discovery and installation to conversion and engagement",
"homepage": "https://www.google.com/analytics",
"license": {
"type": "Copyright",
"text": "Copyright 2015 Google Inc."
},
"authors": "Google, Inc.",
"platforms": {
"ios": "5.0"
},
"vendored_frameworks": [
"GoogleAnalytics.framework"
],
"frameworks": [
"CoreData",
"SystemConfiguration"
],
"libraries": [
"sqlite3",
"z"
],
"source": {
"http": "https://www.gstatic.com/cpdc/69fd9fe84a8fea60-GoogleAnalytics-3.14.0.tar.gz"
},
"prepare_command": "mkdir -p GoogleAnalytics.framework/Modules && mv Headers/Public GoogleAnalytics.framework/Headers && mv Libraries/libGoogleAnalytics.a GoogleAnalytics.framework/GoogleAnalytics && echo 'framework module GoogleAnalytics {\n umbrella header \"GoogleAnalytics.h\"\n\n export *\n module * { export * }\n}' > GoogleAnalytics.framework/Modules/module.modulemap && echo '#import \"GAI.h\"\n#import \"GAIDictionaryBuilder.h\"\n#import \"GAIEcommerceFields.h\"\n#import \"GAIEcommerceProduct.h\"\n#import \"GAIEcommerceProductAction.h\"\n#import \"GAIEcommercePromotion.h\"\n#import \"GAIFields.h\"\n#import \"GAILogger.h\"\n#import \"GAITrackedViewController.h\"\n#import \"GAITracker.h\"' > GoogleAnalytics.framework/Headers/GoogleAnalytics.h && rm -rf Headers Libraries"
}
Last but not least we had to update the .podspec
s of our sub-Pods which need these libraries. This one for example needs the AppsFlyerFramework
pod:
Pod::Spec.new do |s|
# omitted some properties not relevant for the workaround
s.frameworks = 'AppsFlyer' # make sure the framework is linked to this Pod directly
# note that you must also link all transitive dependencies of the static framework too, should it need some (e.g. SystemConfiguration framework, sqlite3, zlib)
s.dependency 'AppsFlyerFramework' # obviously
# add the static framework to the framework search path so that you can actually use it
s.pod_target_xcconfig = {
'FRAMEWORK_SEARCH_PATHS' => '$(PODS_ROOT)/AppsFlyerFramework'
}
end
Again, the solution depends a lot on the static Pods you want to use and on the Pods using them.
HTH
Any update to this?
I was curious about why can't just embed the static lib in the lower most framework depend on it.
If only one framework direct depend on the lib, this solution works well.
If two or more framework depend on it, then can extract a intermediate framework direct depend on the lib.
Can anyone detailed point out shortcomings of this solution?This will break the Module Header
?
Or dynamic generate a intermediate framework from the static lib, then referenced by other lib or framework.
I have a A.framework which i am using in my swift app Test.
A.framework has a podspec which has s.dependency = 'Crashlytics' which is a static framework.
Now when i do pod install on swift app Test, in Test's podfile i have to write below since i am using static framework:
pre_install do |installer|
# workaround for https://github.com/CocoaPods/CocoaPods/issues/3289
def installer.verify_no_static_framework_transitive_dependencies; end
end
Now when i compile Test, it give me 'Crashlytics, file not found error'. If i manually go to Test->Pods->A->Link binary with library->browse and add crashlytics.framework, error goes away.
How can i add a run script which will automate this manual step for me.
Thanks.
@jamehta to achieve that we add the relevant info to our framework's .podspec
.
Note that you must also include all frameworks and libraries used by Crashlytics
since CocoaPods will not add these to the Pod too,
s.frameworks = 'Crashlytics', 'Security', 'SystemConfiguration' # plus other frameworks you use
s.libraries = 'c++', 'z'
s.pod_target_xcconfig = {
'FRAMEWORK_SEARCH_PATHS' => '$(inherited) $(PODS_ROOT)/Crashlytics/iOS'
}
In addition we have to prevent CocoaPods from linking the static framework to the main binary or otherwise Crashlytics would be linked twice, which can result in weird problems.
in Podfile
:
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 "Crashlytics" /, '')
File.open(configFilePath, 'w') { |file| file << configFile }
end
end
end
@fluidsonic i already tried this. s.frameworks adds Crashlytics to link binary build phase but it has some weird path for Crashlytics.framework which is Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS10.3.sdk/System/Library/Frameworks/Crashlytics.framework. When i re-add manually by clicking + sign in link binary build phase of Testapp->Pods->A->Build Phase->Link binary with library and selecting Crashlytics.framework from Test app->Pods->Crashlytics->iOS->Crashlytics.framework, it works fine but automatically it does not. also i have to use below:
'FRAMEWORK_SEARCH_PATHS' => '$(inherited) $(PODS_CONFIGURATION_BUILD_DIR)/Crashlytics'
if i use '$(inherited) $(PODS_ROOT)/Crashlytics', after pod install when i go and check TestApp->Pods->A->Build Settings->Framework search path, it overrides all the other entries of my dependencies mentioned in A's podspec and just have two entries 1) inherited 2) PODS_ROOT/Crashlytics.
also found that s.frameworks is for system frameworks and crashlytics is not system framework. not sure if it is the right thing to use. may b that is the reason it is not adding right .framework ?
I also tried s.vendored_frameworks = 'Crashlytics.framework', 'Fabric.framework', 'Applause.framework' but no luck.
@jamehta I've added the missing $(inherited)
to my comment.
The path you mentioned is not the one used by CocoaPods. It's likely the one where the Crashlytics Mac App installed the Crashlytics framework. Don't use that path!
Also do not add any framework manually to your own Pod. Let CocoaPods do all the work.
s.frameworks
works for any framework - not just system frameworks, as long as the framework can be found using FRAMEWORK_SEARCH_PATHS
.
When you applied all changes I've posted above, what error do you get and what is the content of the directory <your project>/Pods/Crashlytics
?
error i get is when i use above code:
also i dont see "Crashlytics" under
As you see in screenshot above path that it takes is weird. that is the reason build fails with crashlytics not found since right framework file is not added.
lol, stupid Crashlytics Pod! Why can't they just release it Open Source…
The path is wrong. It should read like that in the podspec:
s.pod_target_xcconfig = {
'FRAMEWORK_SEARCH_PATHS' => '$(inherited) $(PODS_ROOT)/Crashlytics/iOS'
}
(updated by complete comment above)
'FRAMEWORK_SEARCH_PATHS' => '$(inherited) $(PODS_ROOT)/Crashlytics/iOS'
OR
'FRAMEWORK_SEARCH_PATHS' => '$(inherited) $(PODS_ROOT)/iOS/Crashlytics'
Tried both without luck.
i still feel problem is with the path of crashlytics that is added in link binary phase. it has weird path
as seen below: from where is it taking this path and why it is taking wrong path ?
so i still see the same erorr.
My test project I've just created works fine with my latest change.
Is there a Crashlytics framework at that weird location?
Still the same error?
What code is causing the error?
Can you post your Podfile and podspec please?
I am using cocoapods-1.2.1
This is my podfile:
source 'https://github.com/CocoaPods/Specs'
platform :ios, 8.0
project 'App'
use_frameworks!
inhibit_all_warnings!
target 'App' do
pod 'Activity', '0.0.6'
end
target 'AppTests' do
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
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
config.build_settings['ENABLE_BITCODE'] = 'NO'
config.build_settings['EXPANDED_CODE_SIGN_IDENTITY'] = ""
config.build_settings['CODE_SIGNING_REQUIRED'] = "NO"
config.build_settings['CODE_SIGNING_ALLOWED'] = "NO"
config.build_settings['CLANG_ENABLE_OBJC_WEAK'] ||= 'YES'
config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '8.0'
end
end
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 "Crashlytics" /, '')
File.open(configFilePath, 'w') { |file| file << configFile }
end
end
end
Below is my podspec:
Pod::Spec.new do |s|
s.name = "Activity"
s.version = "0.0.6"
s.summary = "Activity"
s.homepage = "https://github.com/jamehta/Activity"
s.author = "PayPal"
s.platform = :ios, "7.0"
s.source = { :git => "https://github.com/jamehta/Activity.git", :tag => "0.0.2" }
s.dependency 'ActivitySdk', '0.0.4'
s.source_files = 'Activity/**/*.swift', 'Activity/Activity.h'
s.frameworks = 'Crashlytics', 'Security', 'SystemConfiguration'
s.libraries = 'c++', 'z'
s.pod_target_xcconfig = {
'FRAMEWORK_SEARCH_PATHS' => '$(inherited) $(PODS_ROOT)/Crashlytics/iOS'
}
end
Your podspec lacks an s.dependency
for Crashlytics ;)
Add it!
@fluidsonic thanks for helping out !! may b i lost it in back and forth changes to attempt the solve.
@fluidsonic You mind helping me diagnose a similar problem? I am using a pod called AnalyticsKit
which allows for reporting analytics to multiple providers with little effort and most of the providers have their own static framework like Crashlytics/Intercom for example. AnalyticsKit
is made up of various subspecs for each provider along with Core
I am trying to add a few subspecs to my app and I had everything building at one point but then was getting runtime errors when Crashlytics was trying to be initialized in the appDidLaunch
. Here is the AnalyticsKit CocoaPod
(My own fork) where you can look at the podspec and this is what I have in my Podfile
for my app that also depends on Crashlytics:
target 'AppTarget' do
platform :ios, '9.0'
pod 'Crashlytics'
pod 'Intercom'
end
pre_install do |installer|
def installer.verify_no_static_framework_transitive_dependencies; end
end
post_install do |installer|
project = installer.pods_project
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 "Crashlytics" /, '')
configFile = configFile.gsub(/-framework "Intercom" /, '')
File.open(configFilePath, 'w') { |file| file << configFile }
end
end
end
I currently am getting errors such as this now in my app target:
@kdawgwilk : [EDIT] In case it helps the Linker Errors are due to the absence of _Fabric_ framework in the base podspec... .
Most helpful comment
iOS 7 & Dynamic Frameworks
Regarding your second issue: Getting dynamic frameworks work on iOS 7 is only possible for Development & Ad Hoc builds. It's the App Store which will reject such apps when submitting. We solved that by having separate targets for dev/testing & App Store:
Testing
uses dynamic frameworks whileApp Store
imports the framework's Swift files directly. So far this works fine as long as there are no file name collisions.Static Transitive Dependencies
The workarounds necessary for making this work depend on the static Pod you're trying to use.
Let's use
Crashlytics
as an example.I'll assume you use the latest non-beta CocoaPods version.
We have a dynamic framework Pod in our app called
CrashlyticsService
which basically just abstracts away our Crashlytics code. It's also written in Swift.The Podspec is similar to this:
Because Crashlytics's Pod is not a valid framework (it includes headers of the unrelated Fabric framework - I reported that bug to them but they didn't fix it yet) I slightly modified the Pod's header files & use this modified version instead in our app's
Podfile
:In order to prevent CocoaPods from complaining about the use of static transitive dependencies you use this simple hack in your
Podfile
:If you already have another
pre_install
hook must add the code to the existing one instead.Other static Pods are added in a similar way although some will need more or other workarounds.
If you have any problems when integrating the example or other static Pods then just post the errors here.