Cocoapods: Can't use subspec in child target whose parent target uses parent spec

Created on 3 Nov 2017  ·  43Comments  ·  Source: CocoaPods/CocoaPods

Report

What did you do?

I have a pod containing a rather complex graph of classes modeling my domain entities (let's call it Commons). In order to make testing easier for clients of the pod, having to create those object graphs, I have a subspec including builders that provide object graphs populated with initial values (Commons/Test).

In my client project I have a parent target which declares a dependency on the root spec, and a child test target declaring a dependency to the Test subspec. Something like this:

abstract_target 'project-parent' do
  platform :ios, '8.2'

  # Common dependencies
  pod 'Commons'

  target 'projectA' do
    # Dependencies for project A
  end

  target 'projectB' do
    # Dependencies for project B

    target 'project-tests' do
      inherit! :search_paths

      #Test dependencies
      pod 'Commons/Test'
    end
  end
end

What did you expect to happen?

I expected the project to correctly build and run unit tests.

What happened instead?

The project seems to build correctly, but when I try to run the unit tests inside Xcode I get the following error:

2017-11-03 13:21:13.828800+0100 ios-sim[55586:6417762] Failed to load test bundle from file:///.../Library/Developer/Xcode/DerivedData/ios-ckatbnjhinhmdfgunhgkvfmrzrmn/Build/Products/DebugSpartan-iphonesimulator/ios-sim.app/PlugIns/unit-tests.xctest/: Error Domain=NSCocoaErrorDomain Code=3588 "dlopen(/.../Library/Developer/Xcode/DerivedData/ios-ckatbnjhinhmdfgunhgkvfmrzrmn/Build/Products/DebugSpartan-iphonesimulator/ios-sim.app/PlugIns/unit-tests.xctest/unit-tests, 265): Symbol not found: __T013wuaki_commons18StableReachabilityCAA010ObservableD0AAWP
  Referenced from: /.../Library/Developer/Xcode/DerivedData/ios-ckatbnjhinhmdfgunhgkvfmrzrmn/Build/Products/DebugSpartan-iphonesimulator/ios-sim.app/PlugIns/unit-tests.xctest/unit-tests
  Expected in: /.../Library/Developer/CoreSimulator/Devices/06A4745D-D20B-44F4-B2AA-BE87034E6672/data/Containers/Bundle/Application/428C0AEB-4FBD-404F-A126-FEFCA78341CB/ios-sim.app/Frameworks/wuaki_commons.framework/wuaki_commons
 in /.../Library/Developer/Xcode/DerivedData/ios-ckatbnjhinhmdfgunhgkvfmrzrmn/Build/Products/DebugSpartan-iphonesimulator/ios-sim.app/PlugIns/unit-tests.xctest/unit-tests" UserInfo={NSLocalizedFailureReason=No se ha podido cargar el paquete., NSLocalizedRecoverySuggestion=Vuelve a instalar el paquete., NSFilePath=/.../Library/Developer/Xcode/DerivedData/ios-ckatbnjhinhmdfgunhgkvfmrzrmn/Build/Products/DebugSpartan-iphonesimulator/ios-sim.app/PlugIns/unit-tests.xctest/unit-tests, NSDebugDescription=dlopen(/.../Library/Developer/Xcode/DerivedData/ios-ckatbnjhinhmdfgunhgkvfmrzrmn/Build/Products/DebugSpartan-iphonesimulator/ios-sim.app/PlugIns/unit-tests.xctest/unit-tests, 265): Symbol not found: __T013wuaki_commons18StableReachabilityCAA010ObservableD0AAWP
  Referenced from: /.../Library/Developer/Xcode/DerivedData/ios-ckatbnjhinhmdfgunhgkvfmrzrmn/Build/Products/DebugSpartan-iphonesimulator/ios-sim.app/PlugIns/unit-tests.xctest/unit-tests
  Expected in: /.../Library/Developer/CoreSimulator/Devices/06A4745D-D20B-44F4-B2AA-BE87034E6672/data/Containers/Bundle/Application/428C0AEB-4FBD-404F-A126-FEFCA78341CB/ios-sim.app/Frameworks/wuaki_commons.framework/wuaki_commons
 in /.../Library/Developer/Xcode/DerivedData/ios-ckatbnjhinhmdfgunhgkvfmrzrmn/Build/Products/DebugSpartan-iphonesimulator/ios-sim.app/PlugIns/unit-tests.xctest/unit-tests, NSBundlePath=/.../Library/Developer/Xcode/DerivedData/ios-ckatbnjhinhmdfgunhgkvfmrzrmn/Build/Products/DebugSpartan-iphonesimulator/ios-sim.app/PlugIns/unit-tests.xctest, NSLocalizedDescription=No se ha podido cargar el paquete “unit-tests”.}

As you can see the operation seems to fail while linking due to a missing symbol (a Swift class defined in Commons/Test, but not in Commons). So I guess that due to the conflicting dependencies the system is always building the parent spec (Commons) but not the child subspec(Commons/Test).

Is this expected? Am I doing anything wrong? The only workaround I've found is to declare the parent target to depend on the child subspec, but that would include classes in the final product that are only intended for testing purposes.

CocoaPods Environment

Stack

   CocoaPods : 1.3.1
        Ruby : ruby 2.4.2p198 (2017-09-14 revision 59899) [x86_64-darwin16]
    RubyGems : 2.6.13
        Host : Mac OS X 10.12.6 (16G29)
       Xcode : 9.0.1 (9A1004)
         Git : git version 2.13.5 (Apple Git-94)
Ruby lib dir : /Users/jose.gonzalez/.rbenv/versions/2.4.2/lib
Repositories : marketing-suite - https://github.com/Marketing-Suite/podSpec.git @ 2d77bd9975a85b82e177cebdbce835faa54e674a
               master - https://github.com/CocoaPods/Specs.git @ 8d8f95bedb522a3d3f0987f9bb6fd48d65c8e528
               rakuten-it-scm-eco-core-ios-specs - https://gitpub.rakuten-it.com/scm/eco/core-ios-specs.git @ 8500fcc9546e11d5980ab3c22cf4b702cda40f67
               wuakitv - [email protected]:wuakitv/ios-specs.git @ 5136038257a346a45ce76e2ea105dab18be1eb8d
               wuakitv-1 - https://github.com/wuakitv/ios-specs.git @ 5136038257a346a45ce76e2ea105dab18be1eb8d

Installation Source

Executable Path: /Users/jose.gonzalez/Documents/projects/rakuten/ios/ios-v3/vendor/bundle/ruby/2.4.0/bin/pod

Plugins

cocoapods-deintegrate : 1.0.1
cocoapods-plugins     : 1.0.0
cocoapods-search      : 1.0.0
cocoapods-stats       : 1.0.0
cocoapods-trunk       : 1.3.0
cocoapods-try         : 1.1.0
slather               : 2.4.3

Podfile

install! 'cocoapods', :deterministic_uuids => false
use_frameworks!
inhibit_all_warnings!

platform :ios, '8.2'

source "https://github.com/CocoaPods/Specs.git"
source "https://gitpub.rakuten-it.com/scm/eco/core-ios-specs.git"
source "https://github.com/wuakitv/ios-specs.git"
source "https://github.com/Marketing-Suite/podSpec.git"

abstract_target 'wuaki-ios-parent' do
  platform :ios, '8.2'
  project 'wuaki-ios/wuaki-ios', 'DebugSpartan' => :debug, 'ReleaseSpartan' => :release

  # Infrastructure (DI, logging, deep linking...)
  pod 'XCGLogger', '~> 5.0.1'
  pod 'RxSwift', '~> 4.0'
  pod 'RxCocoa', '~> 4.0'
  pod 'Then', '~> 2.0'
  pod 'Result', '~> 3.0'

  # Metrics & monitoring
  pod 'Google/Analytics', '~> 3.0.3'
  pod 'Crashlytics', '~> 3.8.3'
  pod 'Appsee', '~> 2.3.2'
  pod 'FBSDKCoreKit', '~> 4.26'

  # Feedback
  pod 'iRate', '~> 1.11.6'
  pod 'RakutenMobileSDK/feedback', '~> 2.11.1'
  pod 'HCSStarRatingView', '~> 1.4.5'

  # Push notifications
  pod 'EMSMobileSDK', '~> 1.2.0'

  # Interface
  pod 'Cartography', '~> 1.1'
  pod 'Masonry', '~> 1.0.2'
  pod 'XLForm', '~> 3.2.0'
  pod 'TTTAttributedLabel', '~> 1.13.4'
  pod 'JVFloatLabeledTextField', '~> 1.1.1'
  pod 'STPopupPreview', '~> 1.0.1'
  pod 'wuaki-ios-ui', '~> 0.4.1'
  pod 'wuaki-commons', :path => '../ios-commons'

  target 'wuaki-ios' do
    pod 'wuaki-ios-playback', '~> 0.4.1'
  end

  target 'wuaki-ios-sim' do
    pod 'wuaki-ios-playback/Simulator', '~> 0.4.1'

    target 'unit-tests' do
      inherit! :search_paths

      pod 'Quick', '~> 1.2.0'
      pod 'Nimble', '~> 7.0.0'
      pod 'RxBlocking', '~> 4.0'
      pod 'Nimble-Snapshots', '~> 5.0.0'
      # TODO: Remove this when https://github.com/facebook/ios-snapshot-test-case/issues/227 gets fixed
      pod 'FBSnapshotTestCase', :git => 'https://github.com/jgongo/ios-snapshot-test-case.git'
      pod 'wuaki-commons/Test', :path => '../ios-commons'
    end
  end
end

post_install do |installer|
  installer.pods_project.targets.each do |target|
    target.build_configurations.each do |config|
      # Disable bitcode until the Widevine SDK supports it
      config.build_settings['ENABLE_BITCODE'] = 'NO'
    end
  end
end
defect

Most helpful comment

I have the use case that I'd like to link the full library to the main application, but extensions do not need the full library. Extensions handle single or a few use cases and a full library could be a lot of overhead.

All 43 comments

Is pod 'Commons/Test' a test_spec? If so can you try 1.4.0.beta.2 since a lot of bugs around test specs have been fixed in 1.4.x.

Also a sample app demonstrating the issue is the best way for us to debug and diagnose.

May also be related to #6967 that was fixed in 1.4.0, so please try the beta

@dnkoutso I didn't know about test_spec. As far as I understand from this blog entry, a test_spec specifies the sources for the unit tests of your spec, so you can include them alongside the sources of your pod.

If I have understood it correctly, this is not the case for my subspec. My subspec contains testing helper classes for clients of the pod.

Let me elaborate on my case: my pod contains quite a few classes modelling the domain entities of my application. An object graph for some of the entities may have more than 5 levels of nested objects. I have another project that depends on this pod, and creates ViewModels. In order to test those ViewModels I need to create complex object graphs. The subspec contains builder classes that provide already built graph objects with example values. So the subspec is intended to be used in testing targets, but it doesn't contain unit tests for the root spec. Does this make sense?

@paulb777 Thanks Paul, gonna give it a try!

@paulb777 I have just tried with 1.4.0.beta.2, same result 😢

An important point (which I don't know if it's stated clearly enough): the project builds correctly. I get the error when running the unit tests, so it seems a dynamic linking problem.

@jgongo Sorry to hear that it's still not fixed in 1.4.x. As @dnkoutso said, we'll likely need a reproducible sample app to debug and diagnose.

Here you have it:
subspec-bug.zip

If you execute the tests inside the application project they will fail. If you edit subspec-bug/application/Podfile and change line 11 to contain the following, and run pod install:

  pod 'domain/Test', :path => '../domain'

the tests will run properly.

I have been having the same issue if the child target has a more restrictive subspec than the parent(i.e. doesn't include all files from the default subspec), in runtime I get a symbol not found on one of the "extra" classes of the full spec.

I first noticed this behaviour with a custom private pod, but was also able to reproduce it with Bolts in this Podfile:

platform :ios, '9.0'
use_frameworks!

target 'App' do
  pod 'Bolts'
end

target 'Today' do
  pod 'Bolts/Tasks'
end

If then in the code I do the following:

import Bolts
let task = BFTaskCompletionSource<NSString>() //included from Bolts/Taks -> fine
let nav = BFAppLinkNavigation() //included from Bolts -> will get dyld:Symbol not found in runtime

It compiles fine but when it runs I get dyld: Symbol not found: _OBJC_CLASS_$_BFAppLinkNavigation

I can see the that the Pods-PodTest generated framework has included two copies of Bolts: Bolts and Bolts-Tasks.

I tested with version 1.4.0.beta.2 and still had the same issue

Here is a full reproducible sample app:
PodTest.zip

@jgongo (and @felix-dumit) Thanks for the test cases. I'm able to reproduce, but so far, not able to find a path to a fix. This issue will likely go onto the 1.5 todo list.

There hasn't been any activity on this issue recently. Due to the high number of incoming GitHub notifications, we have to clean some of the old issues, as many of them have already been resolved with the latest updates.

Issue is still present in version 1.4.0

@felix-dumit nobody claimed that the issue was fixed in 1.4.0, it is still open and there are no PRs to fix the issue and it has a milestone of 1.5.0.

@dnkoutso I know, I was just commenting for stable bot so it wouldn't close this

@felix-dumit 👍 my bad

I have the same issue on a private pod. Any plans on fixing this? Would be awesome to be able to only include whats needed in other targets.

@paulb777 as we wrap up 1.5.0.beta.1 do we still want to tackle this?

also this does not appear to be a static frameworks issue correct?

It would be awesome to tackle it, but I don't have to time to work on it. I can only be the lazy complainer 😢

@dnkoutso Nothing to do with static frameworks. I did do a few other things in 1.4.0 ;-)

I'm unlikely to have time for 1.5.0.beta.1, but can try to take another stab in the next few weeks.

Let's aim for 1.5.0.beta.2

I made progress on isolating this today. The wrong domain.framework is getting linked into the app, even though both are built. I'll try to continue within the next week.

In the subspec-bug example from @jgongo, the app and the test targets have two different domain.frameworks. The test version doesn't get found because the app one is found first.

~/Library/Developer/CoreSimulator/Devices  $ find . | grep /Frameworks/domain.framework/domain
./8D10C86A-FEB3-49BF-89CE-B6DD72164243/data/Containers/Bundle/Application/9E658993-9978-4A36-989F-84CC30A34303/application.app/PlugIns/applicationTests.xctest/Frameworks/domain.framework/domain
./8D10C86A-FEB3-49BF-89CE-B6DD72164243/data/Containers/Bundle/Application/9E658993-9978-4A36-989F-84CC30A34303/application.app/Frameworks/domain.framework/domain
~/Library/Developer/CoreSimulator/Devices  $ ls -l ./8D10C86A-FEB3-49BF-89CE-B6DD72164243/data/Containers/Bundle/Application/9E658993-9978-4A36-989F-84CC30A34303/application.app/PlugIns/applicationTests.xctest/Frameworks/domain.framework/domain ./8D10C86A-FEB3-49BF-89CE-B6DD72164243/data/Containers/Bundle/Application/9E658993-9978-4A36-989F-84CC30A34303/application.app/Frameworks/domain.framework/domain
-rw-r--r--  1 paulbeusterien  eng  52288 Mar 22 16:53 ./8D10C86A-FEB3-49BF-89CE-B6DD72164243/data/Containers/Bundle/Application/9E658993-9978-4A36-989F-84CC30A34303/application.app/Frameworks/domain.framework/domain
-rw-r--r--  1 paulbeusterien  eng  62896 Mar 22 16:53 ./8D10C86A-FEB3-49BF-89CE-B6DD72164243/data/Containers/Bundle/Application/9E658993-9978-4A36-989F-84CC30A34303/application.app/PlugIns/applicationTests.xctest/Frameworks/domain.framework/domain
~/Library/Developer/CoreSimulator/Devices  $ nm ./8D10C86A-FEB3-49BF-89CE-B6DD72164243/data/Containers/Bundle/Application/9E658993-9978-4A36-989F-84CC30A34303/application.app/Frameworks/domain.framework/domain | grep EnttityBu
~/Library/Developer/CoreSimulator/Devices  $ nm ./8D10C86A-FEB3-49BF-89CE-B6DD72164243/data/Containers/Bundle/Application/9E658993-9978-4A36-989F-84CC30A34303/application.app/PlugIns/applicationTests.xctest/Frameworks/domain.framework/domain | grep EntityB | head -3
0000000000002850 T __T06domain13EntityBuilderC4withACXDSS9property1_tF
0000000000002950 T __T06domain13EntityBuilderC4withACXDSS9property2_tF
0000000000002a40 T __T06domain13EntityBuilderC5buildAA0B0VyF

I'm not sure the necessary build system contortions to solve this would be a better approach than the workaround of using a separate pod for the Test dependency.

My understanding of the subspec semantics is that subspecs are a way of selecting what gets built into a particular library. It could be argued that it is incorrect usage to expect two different configurations of the same library to be built into the same package.

I have the use case that I'd like to link the full library to the main application, but extensions do not need the full library. Extensions handle single or a few use cases and a full library could be a lot of overhead.

@paulb777 are you OK with moving this to 1.6.0? Is there anything further actionable here?

@dnkoutso I'm blocked. From my understanding, the requested use case is outside the scope of subspec capabilities. I'd like someone to confirm that - and then perhaps the docs should be made clearer.

@paulb777 sounds good, moving to 1.6.0 for now.

@paulb777 is this related to https://github.com/CocoaPods/CocoaPods/issues/8033? maybe the same?

@dnkoutso I think you mean #7850.

They're definitely related, but not necessarily the same. In this case, the Podfile is asking for a different subspec configuration for the test versus the host app.

8041 (the fix for #7850) does not help this issue.

I'm not convinced that the desired behavior of a test target wanting to use a subset of a larger framework that's already in the host app is valid in iOS.

I guess I have a very similar issue.
I'm just adding an App Extension to my App and I extracted some common components into a Common Framework that is part of the project I'm working on. The Common Framework is not under cocoapods but even if it would be under Cocoapods the issue would not change.

CommonFramework -> It use Siesta (Core) by Cocoapods
App -> It needs to use Siesta/UI Subspec by Cocoapods, and link manually to CommonFramework
Extension -> It use CommonFramework linked manually + Cocoapods

The result I see is that after pod install Pod project contains two different libraries:

  • Siesta (Core Source Files) (Siesta as Module Name)
  • Siesta.default.UI (Core Source Files + UI Source Files) (Siesta as Module Name)

Both the libraries contains the Core code that will result in a code duplication in two distinct libraries that has the same name (Module Name Collision).

When I run the App Extension everything works as expected while when I run the App it crashes because the Siesta library without UI is chosen from the package.

Why the subspec libraries are not build as separate library with different Module Name and just linked with the dependent libraries?

To have the same Module Name we result in having a code duplication in two separate libraries.
If I'm not wrong Carthage does not use this approach, not having this subspec concept at all and this will result in having two distinct modules. (Core and UI in the Siesta example)

Would it be a better approach to have separate libraries for subspecs? Probably this is not a simple source code change/update

@falcon283 Does #8041 fix your issue? This issue may be specific to test targets. Your issue might be similar to #7850 that was fixed.

Mmm looks promising. I will give it a try ASAP.

It seems to build but then it still crash.

Here my Podfile

target 'CommonFramework' do

    # Pods for CommonFramework
    pod 'Siesta/Core', '~> 1.4.0'

end

target 'Application' do     #<- This target uses CommonFramework linked manually
    inherit! :search_paths
    # Pods for Application
    pod 'Siesta/Core', '~> 1.4.0'
    pod 'Siesta/UI', '~> 1.4.0'

    target 'ApplicationTests' do
        inherit! :search_paths
        # Pods for ApplicationTests
    end

    target 'ApplicationUITests' do
        inherit! :search_paths
        # Pods for ApplicationUITests
    end

end

target 'Extension' do       #<- This target uses CommonFramework linked manually
    inherit! :search_paths
    # Pods for Extension
    pod 'Siesta/Core', '~> 1.4.0'
end

The libraries appear to be better organized with no duplicates but still there is something that prevent the app and the extension to work properly.

Anyway the two libraries Siesta-Core and Siesta-UI still duplicates code inside their packages.


I was finally able to make it works today using Carthage. I removed Siesta from the Podfile, keeping the rest as it is, and I built the two Siesta Frameworks, the UI links the Core, and linked as usual when using Carthage.

I think that having this same handling: Spec + SubSpec that links the Spec should be the nice to have and this should solve any issue of this kind. I don't know how much difficult would be to have it in Cocoapods.
Probably I should create a PR for Siesta to split app the Spec and Subspec in order to have the same behaviour Carthage has by default.

Is it a viable solution for you?

Its a good change to split subspecs maybe into their own target but it is a huge change. We should definitely consider this for a 1.8.0 or 2.0.0 instead.

I see. I will ask and try splitting the subspecs of siesta in the while. The only other alternative would be use the mix of Carthage and Pod

Here to add another use case where I'm facing a similar if not the same issue. I am providing test helpers for ReSwiftThunk as a subspec. Integrating with CocoaPods 1.6.1 and the following in this demo project ExpectThunkDemo works:

platform :ios, '12.1'

target 'ExpectThunkDemo' do
  use_frameworks!
  pod 'ReSwiftThunk', :git => '[email protected]:jjgp/ReSwift-Thunk.git', :branch => 'expect-thunk-proposal'
end

target 'ExpectThunkDemoTests' do
  pod 'ReSwiftThunk/ExpectThunk', :git => '[email protected]:jjgp/ReSwift-Thunk.git', :branch => 'expect-thunk-proposal'
end

When I attempt to add it as a child target with the following I receive a SIGABRT dyld: lazy symbol binding failed: Symbol not found: _$S12ReSwiftThunk06ExpectC0CMa when running the unit tests:

target 'ExpectThunkDemo' do
  use_frameworks!
  pod 'ReSwiftThunk', :git => '[email protected]:jjgp/ReSwift-Thunk.git', :branch => 'expect-thunk-proposal'
  target 'ExpectThunkDemoTests' do
    inherit! :search_paths
    pod 'ReSwiftThunk/ExpectThunk', :git => '[email protected]:jjgp/ReSwift-Thunk.git', :branch => 'expect-thunk-proposal'
  end
end

Here's the abbreviated podspec as found in the PR 19:

Pod::Spec.new do |spec|
  ...
  spec.subspec "Core" do |sp|
    sp.source_files = "ReSwift-Thunk"
  end

  spec.subspec "ExpectThunk" do |sp|
    sp.dependency "ReSwiftThunk/Core"
    sp.pod_target_xcconfig = { "ENABLE_BITCODE" => "NO" }
    sp.framework    = "XCTest"
    sp.source_files = "ReSwift-ThunkTests/ExpectThunk.swift"
  end

  spec.default_subspec = "Core"

  spec.dependency "ReSwift", "~> 4.0"
end

I'll peruse the other linked issues in case I missed something. Thanks!

This got kinda long, so TLDR: I support the following:

Its a good change to split subspecs maybe into their own target but it is a _huge_ change. We should definitely consider this for a 1.8.0 or 2.0.0 instead.

Running into a very similar issue where I somewhat complicated setup involving multiple private pods. I'll try to simplify it with an example:

At the lowest level I have something like a Models pods. Models also utilizes codegen which is run in a script phase.

Pod::Spec.new do |s|
  s.name = 'Models'
  s.static_framework = true

  s.default_subspecs = 'Core', 'Extensions'

  s.subspec 'Core' do |ss|
    ss.source_files = 'Sources/Core/**/*.swift'
    # ss.script_phase
  end

  s.subspec 'Extensions' do |ss|
    ss.source_files = 'Sources/Extensions/**/*.swift'
    ss.dependency 'SomeLargerDependencyYouMightNotAlwaysWant'
  end

  s.subspec 'Mocks' do |ss|
    ss.source_files = 'Sources/Mocks/**/*.swift'
    ss.dependency 'Models/Core'
  end
end

And in some Feature pod

Pod::Spec.new do |s|
  s.name = 'Feature'
  s.static_framework = true

  s.dependency 'Models'
end

Then in an App Podfile

target 'Example' do
    pod 'Models', :path => 'libs/Models/'
    pod 'Feature', :path => 'libs/Feature/'

    target 'Example_Tests' do
        pod 'Models/Mocks', :path => 'libs/Models/'
    end
end

So Example has a dependency on Models, but Example_Tests has a dependency on Models.default-Mocks.

When building only Example, there are no problems because only Models is built.
When building Example_Tests, both Models and Models.default-Mocks are built since Feature has the dependency on Models. Due to the fact that they are both trying to build the same files (and codegen can change them) at the same time (because Models.default-Mocks doesn't depend on Models), I often end up with a failed build due to something like error: input file 'Generated.swift' was modified during the build.

Now there are several workarounds for this, the most obvious being to not run codegen as a script phase and instead put that on the developer as a manual step any time an input file is changed, but ideally I wouldn't have to do that.

None of this would be a problem if subspecs had their own targets.

Its a good change to split subspecs maybe into their own target but it is a _huge_ change. We should definitely consider this for a 1.8.0 or 2.0.0 instead.

In my opinion having each subspec be built as it's own target could be a large improvement to the experience of working with subspecs. This should resolve one of the most common problems I have with subspecs. There is no compiler guarantee that a restrictive subspec will actually compile until you create a project that only pulls in the smaller subspec.
Example:

Pod::Spec.new do |s|
  s.name = 'Commons'

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

  s.subspec 'Extensions' do |ss|
    ss.source_files = 'Sources/Extensions/**/*.swift'
    ss.dependency 'Commons/Core'
  end
end

Someone makes a change in Commons/Core that uses something from Commons/Extensions.

In:

target 'Commons_Example' do
    pod 'Commons', :path => './'
end

That compiles are runs just fine, but in:

target 'Feature_Example' do
    pod 'Commons/Core', :path => './'
end

The compiler will complain about unknown symbols.

I believe this would be a fundamental change to how subspecs work, but could be a huge improvement for people making heavy use of subspecs.

Aside from actually implementing the change in cocoapods, I think the biggest roadblock to a change like this will be the number of currently functional podspecs that won't work correctly because inter-subspec dependencies aren't listed correctly. If you look in my original Models example I made this mistake, it's highly likely that Models/Extensions should have a dependency on Models/Core.

Hello,
I have right now exactly the same issue than @jgongo ,
I have a library than contains a specific subspec useful just for testing porpuses.

The podfile is something as:

target 'FTMTableSectionModules_Example' do
  pod 'FTMTableSectionModules', :path => '../'

  target 'FTMTableSectionModules_Tests' do
    inherit! :search_paths
    pod 'FTMTableSectionModules/TestHelpers', :path => '../'
  end
end

The result is exactly the same. Main app works without problem, however running unit testing always fails in runtime

If I'm right we still don't have a solution for this right?

Thanks

@fjtrujy I finally ended up splitting the test support classes into their own pod. HTH!

I was thinking to do exactly the same things, most probably I would do exactly the same.
Anyway, let's see if guys from @CocoaPodsBot come with a solution.
Thanks

Hi there,
this problem still appears on 1.9.3/1.10.0 beta, is it going to be changed or this is intended behaviour ?

The issue is still open and without any PRs attached to it. Not sure if this is going to be changed or not. Any help would be appreciated here.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

iosdev-republicofapps picture iosdev-republicofapps  ·  3Comments

intelliot picture intelliot  ·  3Comments

steffendsommer picture steffendsommer  ·  3Comments

sonu5 picture sonu5  ·  3Comments

spencerkohan picture spencerkohan  ·  3Comments