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 *
}