Cocoapods: Framework Search Path is missing dependent targets when using `use_framework!` and subspecs

Created on 6 May 2016  路  19Comments  路  Source: CocoaPods/CocoaPods

馃寛

Report

I did a sample code matching my real world problem when I tried to migrate to use_frameworks!, no idea why but the problem is that the Framework Search Path for some pods don't include all the dependencies, specifically the ones that come from another pod.

I think this is related to https://github.com/CocoaPods/CocoaPods/issues/5241. I didn't add the sample code there because I wasn't sure.

What did you do?

  1. Download the sample project
  2. Run pod install in the app directory
  3. Open the workspace
  4. Try to build the App target (or each pod target directly if you want to double check something)

    What did you expected to happen?

The build to work.

What happened instead?

Build fails to build the asserts pod:

search-path-fail/logger/Classes/Logger.h:1:9: 'CocoaLumberjack/CocoaLumberjack.h' file not found
search-path-fail/asserts/Classes/Asserts.m:1:9: Could not build module 'logger'

This happens because CocoaLumberjack (which is needed to build logger that asserts depend on) is not added to asserts' Framework Search Path.

Adding the missing dependency to Framework Search Path to both asserts and sharedlib-Core makes the build successful.

Podfile

source 'https://github.com/CocoaPods/Specs.git'

platform :ios, '8.0'
use_frameworks!

target 'App' do

  pod 'logger', path: '../logger'
  pod 'sharedlib/Core', path: '../sharedlib'
  pod 'asserts', path: '../asserts'

  target 'Test' do
    inherit! :search_paths

    pod 'testkit', path: '../testkit'
    pod 'sharedlib/Testing', path: '../sharedlib'
  end
end

Podspecs

Unnecessary metadata ommited.

logger

Pod::Spec.new do |s|
  s.name         = "logger"
  s.default_subspecs = 'Core'

  s.subspec 'Core' do |c|
    c.source_files  = "Classes/**/*.{h,m}"

    c.dependency "CocoaLumberjack"
  end

  s.subspec 'Crashlytics' do |cr|
    cr.dependency 'CrashlyticsRecorder'
  end
end

asserts

Pod::Spec.new do |s|
  s.name         = "asserts"
  s.source_files  = "Classes", "Classes/**/*.{h,m}"
  s.exclude_files = "Classes/Exclude"

  s.dependency "logger"
end

sharedlib

Pod::Spec.new do |s|
  s.name         = "sharedlib"
  s.subspec 'Core' do |core|
    core.source_files  = "Classes/Core/*.{h,m}"
    core.dependency "asserts"
    core.dependency "logger"
  end

  s.subspec 'Testing' do |t|
    t.source_files  = "Classes/Testing/*.{h,m}"
    t.dependency 'testkit'
  end
end

testkit

Pod::Spec.new do |s|
  s.name         = "testkit"
  s.source_files  = "Classes/**/*.{h,m}"

  s.framework = 'XCTest'

  s.dependency 'asserts'
end
moderate detailed defect

Most helpful comment

Yes, you can set the podspec's module_name. (This is happening since clang module names have to be valid c99ext identifiers)

All 19 comments

So I don't think inheriting across different subspecs of the same pod actually can work, so if that's the issue here I think the answer probably just a better error up front -- not sure though

Let me know if I can help more, I haven't completely understand the problem yet.

FWIW the project builds if you remove use_frameworks!.

Based on your first hunch, I tested removing sharedLib/Testing from the Test target and the same problem still happens.

@fcy this is actually such a great bug report, would you mind me using it as an integration spec in CocoaPods?

@segiddins Not at all 馃槅

@segiddins thanks for fixing it so quickly!

If I may add a question related to converting projects to use_framework!. I depend on Amplitude-iOS pod, before to import I'd just #import <Amplitude-iOS/Amplitude.h> but after switching to frameworks I have to change the dash to an underscore: #import <Amplitude_iOS/Amplitude.h>. Is that expected? If I were the pod creator could I fix it somehow so the import name matches the pod name?

Yes, you can set the podspec's module_name. (This is happening since clang module names have to be valid c99ext identifiers)

if I set the module_name to an invalid c99ext would it work? 馃槙

no, it _must_ be a valid c99ext identifier

Last thing, more for completeness than a question. Given a pod named Foo+Bar in order to have a import that works for both frameworks and static libraries the module_name would have to be its c99ext version: Foo_Bar.

correct! (I'd honestly just recommend pod names having valid c99ext identifier names for new pods, it avoids a lot of confusion)

I think I've found a variation of this problem. Instead of missing a framework search path entry for another pod it is missing the "$(PLATFORM_DIR)/Developer/Library/Frameworks" for when the dependency is to a framework instead of a pod. Will try to make a sample project but wanted to post here just to make sure this at least makes sense.

That path should only be needed to import XCTest iirc

XCTest is exactly the framework that is missing.

Ah! Is it declared as a dependency in the podspec?

Yep

That's a bug! A new issue with an example pod that triggers this would be greatly appreciated. Thanks!

馃憤 I'm working on it.

Was this page helpful?
0 / 5 - 0 ratings