Vasily
Vasily

Reputation: 3790

How to make framework in CocoaPods that has multiple targets?

I write a framework and I like to divide framework to small separate submodules (targets). Apple provides a cool description for thing I want to achieve with CocoaPods:

Targets are the basic building blocks of a package. A target can define a module or a test suite. Targets can depend on other targets in this package, and on products in packages which this package depends on.

I could easily do it with Swift Package Manager:

    targets: [
        .target(name: "Network"),
        .target(name: "Service", dependencies: ["Network"])
    ],

I could use import Network in a Service target and it's cool because they are separate modules, logic is clear.

How to achieve it in CocoaPods and Carthage (I write a framework, not the final application)?

What I've tried:

Subspec

I tried to use subspecs:

  s.subspec 'Service' do |ss|
    ss.dependency 'MyFramework/Network'
    ss.source_files = 'Sources/Service/**/*.swift'
  end

  s.subspec 'Network' do |ss|
    ss.source_files = 'Sources/Network/**/*.swift'
  end

It doesn't work as I want because CocoaPods just merges all files into one framework (just divides it to separate folders), so:

  1. I receive namespace collisions.
  2. Fatal error when I try to import Network inside Service because there is no Network target after pod install. So I can't use one that framework with Swift Package Manager. CocoaPods just merges everything to one target MyFramework as I mentioned before.

Separate repos/pods

It's the solution but it's very hard to maintain multiple separate git repositories and make separate commit and pushes. I want to keep everything in a one repo.

Upvotes: 18

Views: 2131

Answers (2)

JhonnyTawk
JhonnyTawk

Reputation: 863

Use the below approach in the pod file, to specify different pods for each target. You can also create multiple def and add different pods in each one in which can be used separately.

In the provided example I have 2 shared pods and 2 targets

  • target1_name is the of one target

  • target2_name is the name of another target

  • shared_pods list of pods

  • shared_pods_2 list of another pods

    use_frameworks!    
    
    def shared_pods
     # Comment the next line if you're not using Swift and don't want to use dynamic frameworks
    
     pod 'RealmSwift'
     pod 'Alamofire'
     pod 'ReachabilitySwift'
     pod 'SDWebImage'       
    end
    
    def shared_pods_2
     pod 'Fabric'
     pod 'Crashlytics'
     pod 'CryptoSwift'
    end
    
    target 'target1_name' do
     shared_pods
    end
    
    target 'target2_name' do
     shared_pods_2
    end
    

Upvotes: 0

SwiftyFinch
SwiftyFinch

Reputation: 475

I'm pretty sure that CocoaPods doesn't have the ability to create separate targets for one podspec.

As you mention above you can create separate podspecs, but in one repository like RxSwift. Then while you are developing you can use some Example project which includes all your podspecs. You don't need to manage different repositories.

Also, you can try to create a module map with different modules, e.g.:

framework module Something {
    framework module Core { ... }
    framework module Toolbox { ... }
    ...
}

And then assign it in podspec, e.g.:

Pod::Spec.new do |s|
  s.module_map = "#{s.name}/#{s.name}.modulemap"
...

But I'm not sure about that. I've tried only the first way as in RxSwift repository.

Upvotes: 2

Related Questions