Создание фреймворков iOS / OSX: нужно ли их кодировать перед распространением среди других разработчиков?

91

Я учусь создавать фреймворки для iOS и OSX. Возьмем, к примеру, iOS, у меня пока работают следующие шаги:

  1. xcodebuild framework с использованием -sdk iphonesimulator и действия сборки
  2. каркас xcodebuild с использованием -sdk iphoneos и действия сборки
  3. Используйте инструмент липо, чтобы создать универсальный двоичный файл, чтобы lipo -infoполучить ожидаемые результаты:

Архитектуры в толстом файле: Foo.framework / Foo: i386 x86_64 armv7 arm64

Вопросы следующие:

  1. Я читал, что моя структура может быть повторно подписана разработчиком, который ее использует: «Подпись кода при копировании», но я не понимаю, каковы предварительные условия для этого, т.е. должен ли я добавить шаг кодовой подписи для кодовой подписи этого универсального двоичного файла с моей подписью перед распространять среди других разработчиков?

  2. если предыдущий результат положительный - должен ли я использовать свой идентификатор «iPhone Distribution: ...» или «iPhone Developer: ...» достаточно (чтобы моя структура, являющаяся частью какого-либо проекта iOS, прошла все виды проверок, особенно проверку App Store ) ?.

Фоном для моего ответа является «Ошибка CodeSign: для типа продукта« Framework »в SDK« iOS 8.3 »требуется подпись кода», которую я видел на ряде сторонних платформ, а также в Carthage # 235 или «объект кода не подписан. вообще "(один пример: проблема, о которой я сообщил в Realm # 1998 .

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

PS Этот вопрос становится еще более интересным, если применить его не к одному разработчику, а к организации, которая является поставщиком фреймворка.

Станислав Панкевич
источник
В этом комментарии предлагается использовать «CODE_SIGN_IDENTITY = iPhone Developer», но неясно, почему «Разработчик» используется вместо «iPhone Distribution».
Станислав Панкевич
Связанная тема: Экспорт приложения со встроенной структурой, но без однозначного ответа.
Станислав Панкевич
Я также задул этот вопрос на форумах разработчиков Apple: forum.developer.apple.com/thread/6400 .
Станислав Панкевич
у меня есть вопрос, когда вы распространяете свой фреймворк, распространяете отладочную сборку или выпускаете сборку? а если распространять в релизной сборке, как это сделать?
niczm25
@ niczm25, это один из способов, как я это делаю: stanislaw.github.io/2015/11/23/… .
Станислав Панкевич

Ответы:

138

Я открыл награду: «Ищу ответ из надежных и / или официальных источников». но с тех пор не получал.

Хотя ответ, предоставленный @jackslash, правильный, он рассказывает только часть истории, поэтому я хочу написать свой собственный так, как я хотел бы видеть его в тот момент, когда я задавал этот вопрос.

Актуальность этого ответа: июль 2015 года. Скорее всего, что-то изменится.

Прежде всего, давайте заявим, что действия, необходимые для правильного подписания кода фреймворка, должны быть разделены на шаги, которые должен предпринять Разработчик фреймворка, и шаги, которые должен предпринять Потребитель фреймворка.

TL; DR;

Для фреймворка OSX: разработчик может распространять фреймворк OSX без его кодовой подписи, поскольку Потребитель все равно перекодирует его.

Для платформы iOS: разработчик может распространять платформу iOS без ее кодовой подписи, поскольку Потребитель все равно перекодирует ее, но Xcode заставляет разработчика кодировать свою структуру при сборке для устройства iOS.

Из-за радара: «Платформы iOS, содержащие фрагменты симулятора, не могут быть отправлены в App Store». Потребитель инфраструктуры iOS вынужден запускать специальный скрипт, такой как «copy_frameworks» или «strip_frameworks», который используется lipo -removeдля удаления фрагментов симулятора из инфраструктуры iOS и повторного -codesigns раздели фреймворк, потому что на этом этапе его идентификация кодового обозначения, чем бы она ни была (или не была), удаляется как побочный эффект lipo -removeманипуляции.

Далее следует более длинный ответ.


Этот ответ не является «заимствованием из заслуживающих доверия и / или официальных источников», а скорее основан на ряде эмпирических наблюдений.

Эмпирическое наблюдение №1: Потребителя это не волнует, потому что он будет перекодировать структуру, полученную от разработчика.

Распространения двоичных фреймворков известных проектов с открытым исходным кодом на Github не имеют кодовой подписи . Команда codesign -d -vvvvдает: «объект кода вообще не подписан» во всех бинарных фреймворках iOS и OSX, которые я использовал. Некоторые примеры: ReactiveCocoa и Mantle , Realm , PromiseKit .

Из этого наблюдения ясно, что авторы этих фреймворков предполагают, что их код будет подписан Потребителем от их имени, то есть Потребитель должен использовать либо флаг «Подпись кода при копировании» на этапе сборки «Встраивать фреймворки», предоставляемый Xcode, либо использовать некоторую пользовательскую оболочку скрипт, который делает то же самое вручную: кодирует фреймворк от имени Потребителя.

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

Эмпирическое наблюдение №2, которое применимо только к iOS и полностью заботит разработчиков.

В то время как Потребитель не заботится ли структура получать их от застройщика codesigned или нет, разработчик все еще нуждается в CodeSign своих рамок IOS , как часть процесса сборки , когда они строят его для IOS устройств , поскольку в противном случае Xcode не строит: CodeSign error: code signing is required for product type 'Framework' in SDK 'iOS 8.1'. Процитирую Джастина Спара-Саммерса :

Фреймворки OS X не нуждаются в кодовой подписи при сборке ... К сожалению, Xcode требует, чтобы фреймворки iOS имели кодовую подпись во время сборки.

Это довольно хорошо отвечает на мой вопрос №2: идентичности «iPhone Developer» достаточно, чтобы уговорить Xcode создать платформу iOS для устройства. Этот комментарий к Карфагену № 339 говорит о том же.

Эмпирическое наблюдение no 3: липо-инструмент

Специфическое поведение льего инструмента: при нанесении на рамочную двоичный, она всегда рекурсивно удаляет любой CodeSign тождества из него : lipo -create/-remove codesigned framework ... -> not codesigned framework.

Это может быть ответом на то, почему все примеры в наблюдении №1 вообще не имеют кодовой подписи: их кодовая идентичность сдувается после нанесения липосакции, но поскольку, согласно наблюдению №1, потребителя все равно, все в порядке.

Это наблюдение особенно актуально для следующего наблюдения №4 об AppStore.

Эмпирическое наблюдение №4: фреймворки iOS, содержащие фрагменты симулятора, нельзя отправить в App Store

Это широко обсуждается в: Realm # 1163 и Carthage # 188, и радар открыт: rdar: // 19209161 .

Это полностью забота Потребителя: для универсальной платформы iOS, которую Потребитель включает в свое приложение, при создании приложения они должны запускать специальный скрипт (настраиваемая фаза запуска сценария), который удаляет фрагмент симулятора из двоичного файла этой платформы, чтобы приложение могло пройти проверку AppStore.

Хороший пример бинарных фреймворков, который я нашел в Realm: strip-frameworks.sh .

Он используется lipoдля удаления всех срезов архитектур, отличных от других, ${VALID_ARCHS}а затем перекодирует их с идентичностью Потребителя - здесь вступает в силу наблюдение №3: структура должна быть перекодирована из-за манипуляций с липо.

В Carthage есть скрипт CopyFrameworks.swift, который делает то же самое для всех фреймворков, включенных Потребителем: он удаляет фрагменты симулятора и перекодирует фреймворк от имени Потребителя.

Также есть хорошая статья: Удаление нежелательных архитектур из динамических библиотек в Xcode .


Теперь краткий обзор шагов, необходимых для создания как iOS, так и OSX с точки зрения разработчика и потребителя. Сначала более простой:

OSX

Разработчик:

  1. Строит платформу OSX
  2. Дает это потребителю

От разработчика не требуется никаких действий по кодированию.

Потребитель:

  1. Получает платформу OSX от разработчика
  2. Копирует фреймворк в каталог Frameworks / и автоматически кодирует его от их имени, от имени Потребителя, как часть процесса «Кодовая подпись при копировании».

iOS

Разработчик:

  1. Создает платформу iOS для устройства. Кодирование требуется Xcode, идентификатора «iPhone Developer» достаточно.
  2. Создает платформу iOS для симулятора.
  3. Использует липо, которое производит универсальный фреймворк iOS из предыдущих двух. На этом этапе кодовое обозначение 1 шага потеряно: двоичный файл универсальной платформы «вообще не подписан», но это нормально, поскольку «Потребителю все равно».
  4. Дает это потребителю

Потребитель:

  1. Получает платформу iOS от разработчика
  2. Копирует framework в каталог Frameworks / (этот шаг может быть избыточным в зависимости от того, какой сценарий на шаге 3).
  3. Использует специальный скрипт как часть процесса сборки: этот скрипт отделяет симулятор от фреймворка iOS и затем перекодирует его от их имени, от имени Потребителя.
Станислав Панкевич
источник
10
Это ценная статья. Хороший
jackslash
@Stanislaw благодарит за понимание и ценные данные. Поскольку я пишу фреймворк, созданный мной для разработчиков, я хочу, чтобы они могли взять фреймворк как есть и использовать его без необходимости создавать специальный скрипт для загрузки в магазин приложений. Я думаю, что GoogleMobileAd работает именно так. но вы говорите, что они должны запускать определенный сценарий? Вы знаете, как GoogleMobileAds этого не требует? спасибо
Michael A
@MichaelA, это действительно интересно. Я посмотрю.
Станислав Панкевич
Не могли бы вы дать мне ссылку на GoogleMobileAds, которые вы используете?
Станислав Панкевич
1
Спасибо, что сэкономили мое время, это сработало для меня. Xcode 7.3, Mac OS X 10.11.4.
eugen 07
21

Из прочтения связанной ветки репозитория Carthage это кажется относительно простым. Если вы распространяете двоичный фреймворк, вам необходимо его подписать в коде, а если вы распространяете исходный код через carthage или какао-контейнеры, вы этого не делаете, поскольку эти инструменты позаботятся об этом с помощью различных методов.

Причина, по которой вам нужно подписывать код при распространении двоичной структуры, заключается в том, что Xcode не будет создавать двоичный файл платформы без ее подписи кода. Если вы попытаетесь не подписывать код для двоичной структуры, вы получите эту ошибку:

CodeSign error: code signing is required for product type 'Framework' in SDK 'iOS 8.1'

Неважно, какой идентификатор вы используете для подписи фреймворка (iPhone Developer или iPhone Distribution), потому что, как вы указываете, фреймворк будет перекодирован с настройкой «подписывать код при копировании». Это означает, что ваш фреймворк будет перекодирован соответствующим сертификатом из профиля разработчика потребителя фреймворка, когда ваш фреймворк будет скопирован в их приложение. Это означает, что с App Store не будет проблем, поскольку он увидит только окончательную подпись кода от потребителя фреймворка.

В конце концов, вы можете с таким же успехом подписать свой двоичный файл .framework, поскольку не хотите поддерживать экзотический процесс сборки, а поскольку Xcode будет выводить только подписанные фреймворки, вам не следует отходить слишком далеко от по умолчанию. В любом случае это не имеет значения, потому что конечный потребитель будет повторно подписывать его.

косая черта
источник
в своем ответе во втором абзаце вы говорите, что нет необходимости кодировать структуру, потому что она будет перекодирована потребителем, и я также теперь на 95% уверен, что это правда, но я не понимаю почему в то же время в первом абзаце вы говорите: «Если вы распространяете двоичный фреймворк, вам нужно его подписать в коде» - в чем разница - если я распространяю бинарный фреймворк (т.е. не его источник через carthage или cocoapods), почему Мне нужно будет его кодировать?
Станислав Панкевич
Я думаю, мне не следует кодировать свою структуру, какой бы дистрибутив я ни использовал (заархивированный файл .framework, carthage или cocoapods). Примеры: все следующие дистрибутивы двоичной платформы не имеют кодовой подписи : Realm , ReactiveCocoa , OCMockito .
Станислав Панкевич
Так что я немного смущен вашим "Если вы распространяете двоичную структуру, вам нужно кодировать ее подпись", что (imho) противоречит остальной части вашего ответа. Просьба уточнить. Также обратите внимание, что я открыл эту награду как «Ищу рисунок для ответа из достоверных и / или официальных источников».
Станислав Панкевич
1
Да, я также смотрел Realm и OCMockito. В Realm есть идентификационные данные «iPhone Developer» и да, OCMockito - статическая библиотека. Я думаю, что понимаю проблему - именно липо удаляет кодовую подпись с iphoneos, когда она объединяет iphoneos с кодовой подписью и симулятор iphonesimulator без кодовой подписи.
Станислав Панкевич
1
у меня есть вопрос, когда вы распространяете свой фреймворк, распространяете отладочную сборку или выпускаете сборку? а если распространять в релизной сборке, как это сделать?
niczm25