Creación de marcos de trabajo iOS / OSX: ¿es necesario codificarlos antes de distribuirlos a otros desarrolladores?


90

Estoy aprendiendo a crear frameworks iOS y OSX. Tomemos iOS, por ejemplo, los siguientes pasos me funcionan hasta ahora:

  1. xcodebuild framework usando -sdk iphonesimulator y Build action
  2. xcodebuild framework usando -sdk iphoneos y Build action
  3. Utilice la herramienta lipo para crear binario universal de modo que lipo -infoproduzca lo esperado:

Las arquitecturas en el archivo fat: Foo.framework / Foo son: i386 x86_64 armv7 arm64

Las preguntas son:

  1. Leí que mi marco puede ser re-firmado por el desarrollador que lo está usando: "Code Sign on Copy" pero no entiendo cuáles son las condiciones previas para ello, es decir, ¿debo agregar el paso de codeign para codificar ese binario universal con mi identidad de firma antes distribuyéndolo a otros desarrolladores?

  2. si la anterior es positiva, ¿debo usar mi identidad de "Distribución de iPhone: ..." o "Desarrollador de iPhone: ..." es suficiente (para que mi marco, que es parte de algún proyecto de iOS, pase todo tipo de validaciones, especialmente la de App Store ) ?.

El trasfondo de mi respuesta es el "Error de CodeSign: se requiere la firma de código para el tipo de producto 'Marco' en el SDK 'iOS 8.3'" que he visto en varios marcos de terceros y Carthage # 235 o "el objeto de código no está firmado en absoluto "(un ejemplo: problema que informé en Realm # 1998 .

Así que quiero estar seguro de que los usuarios de mis frameworks no encontrarán ningún problema de codificación cuando los utilicen.

PD: Esta pregunta se vuelve aún más interesante cuando no se aplica a un solo desarrollador, sino a una organización que es un proveedor de frameworks.


Este comentario sugiere usar 'CODE_SIGN_IDENTITY = iPhone Developer' pero no está claro por qué se usa 'Desarrollador' en lugar de 'Distribución de iPhone'.
Stanislav Pankevich

Tema relacionado: Exportar aplicación con marco integrado pero sin una respuesta definitiva.
Stanislav Pankevich

También engañé esta pregunta en los foros de desarrolladores de Apple: forums.developer.apple.com/thread/6400 .
Stanislav Pankevich

tengo una pregunta cuando distribuye su marco, distribuye una compilación de depuración o una compilación de lanzamiento? y si lo distribuye en la versión de lanzamiento, ¿cómo se hace?
niczm25

@ niczm25, esta es una forma de cómo lo hago: stanislaw.github.io/2015/11/23/… .
Stanislav Pankevich

Respuestas:


137

Abrí la recompensa: "Buscando una respuesta basada en fuentes creíbles y / o oficiales". pero no lo he recibido desde entonces.

Si bien la respuesta proporcionada por @jackslash es correcta, solo cuenta una parte de la historia, por lo que quiero escribir la mía propia de una manera que me gustaría haberla visto en el momento en que estaba haciendo esta pregunta.

La realidad de esta respuesta es: julio de 2015. Lo más probable es que las cosas cambien.

En primer lugar, afirmemos que las acciones necesarias para la correcta firma del código del marco deben dividirse en pasos que el desarrollador del marco debe tomar y los pasos que debe tomar el consumidor del marco.

TLDR;

Para el marco OSX: el desarrollador es libre de distribuir el marco OSX sin codificarlo, ya que el consumidor lo volverá a codificar de todos modos.

Para el marco de iOS: el desarrollador es libre de distribuir el marco de iOS sin codificarlo, ya que el consumidor lo volverá a codificar de todos modos, pero Xcode obliga al desarrollador a codificar su marco cuando lo construyen para un dispositivo iOS.

Debido al radar: "Los marcos de iOS que contienen segmentos del simulador no se pueden enviar a la App Store" El consumidor del marco de iOS se ve obligado a ejecutar un script especial como "copy_frameworks" o "strip_frameworks", que utiliza lipo -removepara quitar segmentos del simulador del marco de iOS y volver a -codesigns despojó el marco porque en este punto su identidad de firma de código, sea lo que sea (o no), se elimina como efecto secundario de la lipo -removemanipulación.

Sigue una respuesta más larga.


Esta respuesta no es "extraída de fuentes confiables y / o oficiales", sino que se basa en una serie de observaciones empíricas.

Observación empírica # 1: al consumidor no le importa porque rediseñarán el marco que reciben del desarrollador

Las distribuciones de marcos binarios de proyectos de código abierto conocidos en Github no están codificadas . El comando codesign -d -vvvvda: "el objeto de código no está firmado en absoluto" en todos los marcos binarios de iOS y OSX que solía explorar. Algunos ejemplos: ReactiveCocoa y Mantle , Realm , PromiseKit .

A partir de esta observación, queda claro que los autores de estos marcos pretenden que sean codificados por el Consumidor, en su nombre, es decir, un Consumidor debe usar la bandera "Firmar código en la copia" en la fase de compilación de "Marcos integrados" proporcionada por Xcode o usar algún shell personalizado script que hace lo mismo manualmente: framework codesigns en nombre del consumidor.

No encontré ningún ejemplo de lo contrario: marco de código abierto que se distribuiría con identidad de firma de código en él, por lo que en el resto de la respuesta estoy asumiendo que este enfoque ampliamente adoptado es correcto: no hay necesidad de que el desarrollador del marco distribuir su marco a otros desarrolladores con identidad de codificación en él porque el consumidor de todos modos lo volverá a codificar .

Observación empírica n. ° 2 que se aplica solo a iOS y que es una preocupación exclusiva del desarrollador

Mientras Consumidor no le importa si marco que reciben de desarrollador se codesigned o no, desarrollador todavía tiene que Codesign su marco iOS como parte de su proceso de construcción cuando construyen para dispositivo iOS porque de lo contrario no se acumula Xcode: CodeSign error: code signing is required for product type 'Framework' in SDK 'iOS 8.1'. Para citar a Justin Spahr-Summers :

Los marcos de OS X no necesitan estar codificados en la compilación ... Desafortunadamente, Xcode requiere que los marcos de iOS estén codificados en el momento de la compilación.

Esto responde bastante bien a mi pregunta # 2: la identidad de "desarrollador de iPhone" es suficiente para engatusar a Xcode para que construya un marco iOS para el dispositivo. Este comentario sobre Cartago # 339 dice lo mismo.

Observación empírica n. ° 3: herramienta lipo

Comportamiento específico de la herramienta lipo: cuando se aplica a binario marco, siempre elimina recursivamente cualquier identidad codiseño de ella : lipo -create/-remove codesigned framework ... -> not codesigned framework.

Esta podría ser una respuesta a por qué todos los ejemplos de la observación n. ° 1 no están codificados en absoluto: su identidad de firma de códigos desaparece después de que se aplica la lipo, pero dado que, según la observación n. ° 1, al consumidor no le importa que esté bien.

Esta observación es especialmente relevante para la siguiente observación # 4 sobre AppStore.

Observación empírica n. ° 4: los marcos de iOS que contienen segmentos de simulador no se pueden enviar a la App Store

Esto se discute ampliamente en: Realm # 1163 y Carthage # 188 y el radar está abierto: rdar: // 19209161 .

Esto es una preocupación total del consumidor: para el marco universal de iOS que el consumidor incluye en su aplicación, cuando la aplicación se está construyendo, debe ejecutar un script especial (Fase de ejecución de script personalizada) que elimina el segmento del simulador del binario de ese marco para que la aplicación pueda pasar la validación de AppStore.

El buen ejemplo de marcos binarios que encontré en Realm: strip-frameworks.sh .

Se utiliza lipopara eliminar todos los segmentos de arquitecturas que no sean ${VALID_ARCHS}y luego lo vuelve a codificar con la identidad del consumidor ; aquí es donde entra en juego la observación n. ° 3: el marco debe ser rediseñado debido a las manipulaciones de lipo en él.

Carthage tiene el script CopyFrameworks.swift que hace lo mismo con todos los frameworks incluidos por Consumer: elimina las porciones del simulador y vuelve a codificar el framework en nombre de Consumer.

También hay un buen artículo: Eliminación de arquitecturas no deseadas de bibliotecas dinámicas en Xcode .


Ahora, la descripción general de los pasos necesarios para producir iOS y OSX desde la perspectiva del desarrollador y del consumidor. Primero el más fácil:

OSX

Desarrollador:

  1. Construye el marco OSX
  2. Se lo da al consumidor

No se requieren actividades de codificación por parte del desarrollador.

Consumidor:

  1. Recibe el marco OSX del desarrollador
  2. Copia el marco en el directorio Frameworks / y lo codifica automáticamente en su nombre, el del consumidor, como parte del proceso de "Firma de código en copia".

iOS

Desarrollador:

  1. Construye el marco de iOS para el dispositivo. Xcode requiere la codificación, la identidad de "desarrollador de iPhone" es suficiente.
  2. Construye el marco de iOS para el simulador.
  3. Utiliza lipo que produce un marco iOS universal de los dos anteriores. En este punto, la identidad de codificación de 1 paso se pierde: el marco binario universal "no está firmado en absoluto", pero eso está bien ya que "al consumidor no le importa".
  4. Se lo da al consumidor

Consumidor:

  1. Recibe el marco de iOS del desarrollador
  2. Copia el marco en el directorio Frameworks / (este paso puede ser redundante según el script del paso 3).
  3. Utiliza una secuencia de comandos especial como parte del proceso de compilación: esta secuencia de comandos elimina el simulador del marco de iOS y luego lo vuelve a codificar en su nombre, el del consumidor.

9
Este es un artículo valioso. Nice one
jackslash

@Stanislaw agradece la información y los datos valiosos. Mientras estoy escribiendo un marco que yo mismo diseñé para los desarrolladores, quiero que puedan tomar el marco tal como está y usarlo sin necesidad de hacer un script especial para cargarlo en la tienda de aplicaciones. Creo que GoogleMobileAd funciona de esa manera. pero dices que deben ejecutar cierto script? ¿Tiene idea de cómo GoogleMobileAds no requiere eso? gracias
Michael A

@MichaelA, de hecho eso es interesante. Veré.
Stanislav Pankevich

¿Podría darme un enlace a GoogleMobileAds que está usando?
Stanislav Pankevich

1
Gracias por ahorrarme tiempo, eso funcionó para mí. Xcode 7.3, Mac OS X 10.11.4.
eugen

21

Al leer el hilo vinculado en el repositorio de Carthage, parece relativamente simple. Si está distribuyendo el marco binario, debe codificar y firmarlo y si está distribuyendo la fuente a través de carthage o mazorcas de cacao, no lo hace, ya que esas herramientas se encargan de esto a través de diferentes métodos.

La razón por la que necesita firmarlo con código cuando distribuye el marco binario es que Xcode no producirá un marco binario sin que el código lo firme. Si intenta no firmar el código del marco binario, obtendrá este error:

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

No importa con qué identidad se codifique para firmar el marco (desarrollador de iPhone o distribución de iPhone) porque, como señala, el marco se volverá a codificar con la configuración de "firma de código en copia". Esto significa que su marco será rediseñado por el certificado apropiado del perfil de desarrollador del consumidor del marco cuando su marco se copie en su aplicación. Esto significa que no habrá problemas con la App Store, ya que solo verá la firma del código final del consumidor del marco.

Al final del día, también puede firmar el código de su binario .framework, ya que no quiere tener que mantener un proceso de compilación exótico, y como Xcode solo generará marcos firmados, no debe alejarse demasiado del valores predeterminados. Realmente no importa de todos modos porque el consumidor final lo volverá a firmar.


en su respuesta, en el segundo párrafo, está diciendo que no hay necesidad de codificar el marco porque será rediseñado por el consumidor y ahora también estoy 95% seguro de que es cierto, pero no entiendo por qué, al mismo tiempo, en el primer párrafo dice: "Si distribuye el marco binario, debe codificar y firmarlo". ¿Cuál es la diferencia? Si distribuyo el marco binario (es decir, no su fuente a través de carthage o cocoapods) por qué ¿Necesitaría firmarlo con código?
Stanislav Pankevich

Creo que no debería codificar mi marco independientemente del tipo de distribución que utilice (archivo .framework comprimido o carthage o cocoapods). Ejemplos: todas las siguientes distribuciones de marcos binarios no están codificadas: Realm , ReactiveCocoa , OCMockito .
Stanislav Pankevich

Así que estoy un poco confundido con su "Si está distribuyendo el marco binario, debe codificar y firmarlo", que (en mi humilde opinión) contradice el resto de su respuesta. Por favor aclare. También tenga en cuenta que abrí esta recompensa como "Buscando una respuesta basada en fuentes creíbles y / u oficiales".
Stanislav Pankevich

1
Sí, también he mirado a Realm y OCMockito. Realm tiene identidades de "desarrollador de iPhone" y sí, OCMockito es una biblioteca estática. Creo que entiendo el problema: es la lipo lo que elimina la firma en código de los iphoneos cuando combina iphoneos firmados con código y simulador de iphones sin firma.
Stanislav Pankevich

1
tengo una pregunta cuando distribuye su marco, distribuye una compilación de depuración o una compilación de lanzamiento? y si lo distribuye en la versión de lanzamiento, ¿cómo se hace?
niczm25

1

La respuesta de Stanislav Pankevich anterior es muy válida y correcta. Pero tenga en cuenta que a partir de Xcode 9.4, el IDE le pedirá que desactive la firma de código para iOS Cocoa Touch Frameworks. Apple aquí ahora dice que no se recomienda que firme el código de su .framework.

Espero que esto ayude.


1
¿Tiene una fuente para que Apple recomiende no firmar marcos?
Rick
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.