Карта частного модуля для фреймворка

Я использую этот ответ, чтобы создать карту модуля для создания модуля для CommonCrypto, чтобы я мог использовать его в фреймворке.

Однако это означает, что любые проекты, в которых я использую этот фреймворк, имеют доступ к CommonCrypto с import CommonCrypto — и, что еще хуже, объявление CommonCrypto в другом фреймворке и импорт его в проект приводит к ошибкам Redefinition of module 'CommonCrypto'.

т.е. следующая установка:

MainProject
    |--> import FrameworkA - module map for CommonCrypto
    |--> import FrameworkB - module map for CommonCrypto

Есть ли способ создать карту модуля, но сделать ее частной для той платформы, в которой она создана/используется? (Подобно атрибуту доступа internal в Swift для Framework). В документах llvm Clang показан файл private attribute, но я не могу понять, куда поместить это в мою карту модуля, и, возможно, это даже не для этой цели! Также есть атрибут export, но опять же я не совсем уверен, как использовать это...!

Это моя карта модуля, которую я использую для CommonCrypto — $(SDKROOT) заменяется на этапе сборки в правильное место (для iphoneos или iphonesimulator SDK):

module CommonCrypto [system] [extern_c] {
    umbrella header "$(SDKROOT)/usr/include/CommonCrypto/CommonCrypto.h"
    export *
}

Это прекрасно работает (за исключением того, что вы не можете «перейти к определению», но я не возражаю против этого) для использования в FrameworkA / FrameworkB.


person Rich    schedule 14.12.2015    source источник
comment
Привет, есть новости по этому поводу? У меня такая же точная настройка для libz :(   -  person tmpz    schedule 02.02.2016
comment
Рич, не могли бы вы предоставить скрипт этапа сборки, который заменяет $(SKROOT)? Спасибо!   -  person appleitung    schedule 15.02.2016
comment
@appleitung: Скрипт находится здесь: gist.github.com/rhodgkins/5eecee8bcbdb6021fc798247132e9fa7, а затем настройте его следующим образом: postimg.org/image/fj7j9nsqp в проекте. Не забудьте также добавить каталог $(PROJECT_DIR)/$(TARGET_NAME)/ExternalFrameworks/ в параметр сборки *Framework Search Paths. Затем все карты модулей должны находиться в папке входного каталога, причем имя папки, содержащей карту модулей, является именем.   -  person Rich    schedule 12.04.2016


Ответы (1)


Отказ от ответственности: я не пробовал это для CommonCrypto, но это работает для моего случая с libz

Возможным решением этой проблемы является создание module.private.modulemap, как описано в Clang. документация

Так, например, в FrameworkA вы можете написать файл module.modulemap для FrameworkA следующим образом:

module FrameworkACommon {
}

Затем вы должны создать файл module.private.modulemap вот так

explicit  FrameworkACommon.Crypto [system] [extern_c] {
   header "/Applications/Xcode6-Beta5.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator8.0.sdk/usr/include/CommonCrypto/CommonCrypto.h"
    link "CommonCrypto"
    export *
}

Затем повторите для FrameworkB.

Теперь CommonCrypto является частным модулем как в FrameworkA, так и в FrameworkB, и имена не будут конфликтовать.

person tmpz    schedule 03.02.2016
comment
Ницца! Спасибо, что поделились - буду пробовать! - person Rich; 03.02.2016
comment
@tmpz Я получаю много «использования необъявленного типа ...». Вы сталкивались с этим? - person nsinvocation; 10.02.2016
comment
Вы, вероятно, получаете необъявленный тип, потому что ваш модуль не экспортирует заголовки. export * экспортирует заголовки в FrameworkACommon, а чтобы импортировать их, вам нужно написать FrameworkACommon.Crypto, но на этом все остановится. Экспортированные заголовки не будут видны после FrameworkACommon, теперь они являются внутренними. - person tmpz; 10.02.2016
comment
Есть ли способ заставить такие вещи работать с помощью CocoaPods? Я пробовал несколько вещей с модулями, но я просто не могу заставить его работать - person cjwirth; 22.02.2016
comment
@cjwirth Вы можете указать карту модуля для спецификации CocoaPod. - person Rich; 27.09.2016
comment
Это опечатка: в FrameworkA вы можете написать файл module.modulemap для CommonCrypto вот так. Означает ли это, что в FrameworkA вы можете написать файл module.modulemap для FrameworkA вот так? - person hnh; 13.10.2016
comment
@hnh Это опечатка. Исправлена. - person tmpz; 14.10.2016
comment
Пытаясь заставить это работать с Xcode 8 :-) Карты модулей, которые вы предоставляете, вы не просто добавляете их в путь импорта Swift, вы также устанавливаете их как файл карты модуля и файл карты частного модуля в цели, правильно ? Кроме того, ваш говорит, что модуль FrameworkACommon {}, учитывая настройку вопроса, является ли это еще одной опечаткой и должен быть модулем FrameworkA и явным модулем FrameworkA.CommonCrypto? - person hnh; 14.10.2016
comment
Не могли бы вы проверить это: stackoverflow.com/q/56769304/1364053 - person nr5; 26.06.2019
comment
Этот ответ больше не работает, так как в Clang изменился способ работы карт приватных модулей. Корневой модуль карты частных модулей теперь должен называться Foo_Private. См. stackoverflow.com/a/65236670/1005419 полный способ, который работает в декабре 2020 года. - person Thomas McGuire; 10.12.2020