Hello here is our Podspec which has a default_subspec
and an optional subspec (which won't be taken since the default is already set). That subspec has more features, but takes an additional 8MB of size...
`s.default_subspec = 'mainSDK'
s.subspec 'mainSDK' do |mainSDK|
mainSDK.vendored_frameworks = 'mainSDK.framework'
mainSDK.source_files = "mainSDK.framework/Headers/*.h"
end
s.subspec 'additionalSDK' do |additionalSDK|
additionalSDK.source_files = "additionalSDK.framework/Headers/*.h"
additionalSDK.vendored_frameworks =['additionalSDK.framework', 'mainSDK.framework']
end
Now, in our mainSDK we include additionalSDK with #if canImport(additionalSDK) We then provide code related to additionalSDK in between those compiler flags, like this:
#if canImport(additionalSDK)
//adding optional delegate
class ViewController: UIViewController, OptionalDelagate
#else
//no need for delagete
class ViewController: UIViewController
#endif
However, after client integrates our mainSDK he sees that this framework is missing module: additionalSDK.framework
How is this possible? We have marked additionalSDK as optional in our workspace. We have tried to set additionalSDK as a -weak_framework in other linker flags(Build settings) , but this did not helped.
If client integrates additionalSDK everything works well, because all frameworks are linked..
Optional dependencies, without CocoaPods work well, it is just problem of CocoaPods or I don't know how to configure it
s.platform = :ios
s.ios.deployment_target = '9.0'
s.name = "mainSDK"
s.summary = "mainSDK IOS SDK"
s.requires_arc = true
# 2
s.version = "1.0.8.6.5"
s.source = { :http => "https://s3-eu-west-1.amazonaws.com/zipOfSDK.zip"}
s.framework = "UIKit"
s.source_files = "mainSDK.framework/Headers/*.h"
s.default_subspec = 'mainSDK'
s.subspec 'mainSDK' do |mainSDK|
mainSDK.vendored_frameworks = 'mainSDK.framework'
mainSDK.source_files = "mainSDK.framework/Headers/*.h"
end
s.subspec 'additionalSDK' do |additionalSDK|
additionalSDK.source_files = "additionalSDK.framework/Headers/*.h"
additionalSDK.vendored_frameworks =['additionalSDK.framework', 'mainSDK.framework']
end
s.swift_version = "4.2"
end
Short answer: Using #if canImport(Module)
would not allow you to achieve what you described in a closed source setup. I see some misunderstanding of how this conditional compilation works.
What I mean is that you've already built a framework. Seems that #if canImport
is resolved at a compile time, so it is not dynamic.
When you use already prebuilt mainSDK.framework
, the part #if canImport(additionalSDK)
was already evaluated. And the result depends on the availability of 'additionalSDK' in the build chain, when it was built (so on your machine when you prepare it for shipping to clients), not when it is linked.
I found someone struggling with a similar issue here: https://flint.tools/blog/finding-a-weak-linking-solution.html
The good news is, that what you want to achieve is possible using weak linking and objective-C interoperability.
I'm working on a short article about the topic, in the meantime, here is an example repository with a working setup, similar to what you described as requirements:
https://github.com/amichnia/Swift-framework-with-optional-frameworks
It supports:
Update:
I finished an article, which should describe the solution in more details. It is available at https://medium.com/@amichnia_31596/create-a-mostly-swift-framework-with-optional-features-7e8a9ac960f9
Can't achieve that by saying that mainSDK is MainTarget and additionalSDK is your AdditionalTarget? What I see is that whatever version
you want differently it will be just another target
. You can right-click on the original target, select duplicate from the current target and after it you can make the changes you wish to linking frameworks within the Build Phases section.
#check1:
check you have use_frameworks!
uncommented like this:
# Uncomment this line if you're using Swift
use_frameworks!
#check2:
try to delete the ModuleCache
if you really think the Framework
is there and in the right path. To delete ModuleCache just delete ~/Library/Developer/Xcode/DerivedData/ModuleCache
directory, clean the project and delete project-specific derived data just to be sure.
When you do the normal cleanup, the ModuleCache directory usually doesn't get rebuilt.
#check3:
inspect your framework to see if it contains a Modules
folder with a module.modulemap
file inside it (right click on your framework > Show In Finder > make sure your modulemap is there)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With