Search code examples
cocoapodsswift2commoncryptopodspec

Swift sub-modules in Cocoapods


I'm trying to set up the following arrangement of private Cocoapods:

PodA depends on PodB which depends on CommonCrypto.

CommonCrypto is a dylib that ships with iOS but doesn't have a Swift header module. Within PodB I've created a custom module.modulemap with the following contents:

module CommonCrypto [system] {
    header "/usr/include/CommonCrypto/CommonCrypto.h"
}

PodB passes the lint test (pod spec lint PodB.podspec) after adding the following lines:

# Ensure module isn't deleted by CocoaPods
s.preserve_paths = 'path_to/PodB/CommonCrypto'
s.pod_target_xcconfig = { 'HEADER_SEARCH_PATHS' => '$(PODS_ROOT)/path_to/CommonCrypto' }

Within PodA, I depend on PodB with s.dependency = 'PodB'. When linting PodA with pod spec lint --sources=myrepo PodA.podspec I get an error compiling any Swift file with import PodB:

missing required module 'CommonCrypto'

How can I go about fixing this? It doesn't matter to me if CommonCrypto is private or public to PodB.

I tried adding export * to module.modulemap but that made no difference.


Solution

  • I solved this issue with a (slightly) ugly workaround; I exported the include path to the parent project.

    Since include paths are multi-valued, a list as opposed to a single setting, Cocoapods can merge whatever the parent project (PodA) sets with whatever the subproject (PodB) requires.

    I had tried this solution before but it failed since I was using HEADER_SEARCH_PATHS instead of SWIFT_INCLUDE_PATHS. The relevant bit of the fixed podspec looks like this:

    # Ensure module isn't deleted by CocoaPods
    s.preserve_paths = 'path_to/PodB/CommonCrypto'
    s.pod_target_xcconfig = { 'SWIFT_INCLUDE_PATHS' => '$(PODS_ROOT)/path_to/CommonCrypto' }
    s.user_target_xcconfig = { 'SWIFT_INCLUDE_PATHS' => '$(PODS_ROOT)/path_to/CommonCrypto' }
    

    user_target_xcconfig is what allows PodB to inject build settings into PodA. This is generally not a great idea and could be used to screw up all kinds of things, so I'd welcome a better solution, but in the particular case of pointing parent pods to a module I think it is acceptable.

    That said I think this solution would fail if PodA depended on both PodB and PodC where both B and C required CommonCrypto...