Swift субмодули в Cocoapods

Я пытаюсь настроить следующее расположение частных Cocoapods:

PodA зависит от PodB который зависит от CommonCrypto,

CommonCrypto это dylib который поставляется с iOS, но не имеет Swift Модуль заголовка. В PodB Я создал кастом module.modulemap со следующим содержанием:

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

PodB проходит тест на ворс (pod spec lint PodB.podspec) после добавления следующих строк:

# 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' }

В PodAЯ зависим от PodB с s.dependency = 'PodB', При распушении PodA с pod spec lint --sources=myrepo PodA.podspec Я получаю сообщение об ошибке при компиляции Swift файл с import PodB:

missing required module 'CommonCrypto'

Как я могу исправить это? Для меня не имеет значения, если CommonCrypto является частным или публичным PodB,

Я пытался добавить export * в module.modulemap но это не имело значения.

4 ответа

Решение

Я решил эту проблему с (немного) некрасивым обходным путем; Я экспортировал путь включения в родительский проект.

Поскольку включаемые пути являются многозначными, то есть список, в отличие от одного параметра, Cocoapods может объединить любой родительский проект (PodA) устанавливается с любым подпроектом (PodB) требует.

Я пробовал это решение раньше, но оно не удалось, так как я использовал HEADER_SEARCH_PATHS вместо SWIFT_INCLUDE_PATHS, Соответствующий бит фиксированного подспека выглядит так:

# 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 это то, что позволяет PodB ввести настройки сборки в PodA, Как правило, это не очень хорошая идея, и ее можно использовать, чтобы испортить все, поэтому я бы приветствовал лучшее решение, но в конкретном случае указания родительских модулей на модуль я думаю, что это приемлемо.

Тем не менее, я думаю, что это решение потерпит неудачу, если PodA зависел от обоих PodB а также PodC где оба B а также C требуется CommonCrypto...

До сих пор мне повезло, просто скопировав все необходимые заголовки CommonCrypto в один соединительный заголовок и включив его в модуль. CommonCrypto изменяется очень редко, и вполне вероятно, что это будет модульный заголовок до того, как с ним произойдут какие-либо важные изменения. Смотрите RNCryptor.h для примера файла заголовка. Обратите внимание, что все #ifdef включаются условные выражения и каждый заголовок целиком (не только то, что требуется для этого проекта). Это должно защитить от нескольких пакетов, импортирующих один и тот же файл (если заголовок не изменяется).

Результирующий podspec просто включает в себя .h как источник:

s.source_files = 'RNCryptor.swift', 'RNCryptor.h'

Вы добавили фреймворк в файл спецификации podB?

s.frameworks = 'CommonCrypto'

Использование $(PODS_TARGET_SRCROOT) вместо $(PODS_ROOT)/podname/ сработало для меня

s.source_files = 'Classes/**/*.swift', 'modules/**/*.map'
s.preserve_paths = 'modules/**/*.map'

s.pod_target_xcconfig = {
   'SWIFT_INCLUDE_PATHS[sdk=iphoneos*]'         => '$(PODS_TARGET_SRCROOT)/modules/iphoneos/CommonCrypto',
   'SWIFT_INCLUDE_PATHS[sdk=iphonesimulator*]'  => '$(PODS_TARGET_SRCROOT)/modules/iphonesimulator/CommonCrypto',
}

Файлы module.map: modules/iphoneos/CommonCrypto/module.map:

module CommonCrypto [system] {
    header "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/usr/include/CommonCrypto/CommonCrypto.h"
    export *
}

Модули /iphonesimulator/CommonCrypto/module.map:

module CommonCrypto [system] {
    header "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/usr/include/CommonCrypto/CommonCrypto.h"
    export *
}
Другие вопросы по тегам