How to use private cocoapods dependencies in public pods
10 Jan 2023How to use private cocoapods dependencies in public pods
This article is the result of some findings I have come across or learned while freelancing at Tiendeo. It's a bit of an edge case, and I hope It can be useful to you
As an iOS developer, you will encounter Cocoapods very often. Most likely, you will be using It to import your dependencies into your app or target.
However, when exporting your frameworks for others to use, you might run into some edge cases. One such case will happen if you ever want to publish a framework that includes a private framework. This could be common if your company offers an SDK, while using some internal components. The resulting dependency diagram could be the following:
The problem
When attempting to publish My Public Pod
, by using pod trunk push
you will encounter the following error:
- ERROR | iOS unknown: Encountered an unknown error (Unable to find a specification for `[Private Framework] (= x.y.z)` depended upon by `[My Public Framework]`
[!] The spec did not pass validation, due to 1 error
The solution (?)
The issue lies on the private framework not being found in the public cocoapods repo, so the standard mechanism for declaring dependencies in cocoapods is not the way to go. Instead, we'll have to use the vendored_frameworks
declaration in our Podspec, and upload the private dependency as one of our own. At this point, your podspec will most likely look like this:
Pod::Spec.new do |spec|
spec.name = 'MyPublicFramework'
spec.version = '1.0'
spec.license = 'MIT'
spec.summary = 'A description of my pod'
spec.homepage = 'https://darioroa.com'
spec.author = 'Dario Roa'
spec.source = { :git => 'git://github.com/darioroa/MyPublicFramework.git', :tag => 'v1.0' }
# Vendored Frameworks
s.vendored_frameworks = 'MyPublicFramework.framework'
# Dependency declaration
spec.dependency 'MyPrivateFramework'
end
Our goal is to include the private framework alongside our public one, by declaring It as a vendored framework:
Pod::Spec.new do |spec|
spec.name = 'MyPublicFramework'
spec.version = '1.0'
spec.license = 'MIT'
spec.summary = 'A description of my pod'
spec.homepage = 'https://darioroa.com'
spec.author = 'Dario Roa'
spec.source = { :git => 'git://github.com/darioroa/MyPublicFramework.git', :tag => 'v1.0' }
# Vendored Frameworks
s.vendored_frameworks = 'MyPublicFramework.framework', 'Frameworks/MyPrivateFramework.framework'
# Private framework not listed as a dependency anymore
end
Note that this is more of a workaround, and will also require including any dependencies of our private dependency in this format. For instance, if MyPrivateFramework
depends on SuperSecretFramework
:
# Vendored Frameworks
s.vendored_frameworks = 'MyPublicFramework.framework', 'Frameworks/MyPrivateFramework.framework', 'Frameworks/SuperSecretFramework.framework'
You may also notice we have declared these frameworks inside a Frameworks
folder. This is the way we will include them into our upload.
When calling pod trunk push
, you will need to also include this Frameworks
folder containing the private framework and all of its dependencies.
With this setup, you will hopefully be able to publish your framework in the public Cocoapods repo, but including non-public components.
Constraints
This guide is more of a workaround, and as such will likely not always work. If it does, you should also keep in mind its restrictions:
- The private framework and its dependencies must be compiled to a
.framework
file. So you have to also manage those dependencies manually and make sure you're including the right version for each upload. - You need to include all dependencies of the private framework. This could result in this method not being viable anymore, depending on your setup and needs.
I hope you found this useful. Have fun with Cocoapods 😉